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

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (118) hide show
  1. package/dist/compass-widget.d.ts +2 -0
  2. package/dist/compass-widget.d.ts.map +1 -1
  3. package/dist/compass-widget.js +8 -5
  4. package/dist/compass-widget.js.map +1 -1
  5. package/dist/context-menu-widget.d.ts.map +1 -1
  6. package/dist/dist.dev.js +3319 -3264
  7. package/dist/fullscreen-widget.d.ts +4 -0
  8. package/dist/fullscreen-widget.d.ts.map +1 -1
  9. package/dist/fullscreen-widget.js +3 -1
  10. package/dist/fullscreen-widget.js.map +1 -1
  11. package/dist/geocoder-widget.d.ts.map +1 -1
  12. package/dist/gimbal-widget.d.ts +2 -0
  13. package/dist/gimbal-widget.d.ts.map +1 -1
  14. package/dist/gimbal-widget.js +18 -15
  15. package/dist/gimbal-widget.js.map +1 -1
  16. package/dist/icon-widget.d.ts +2 -0
  17. package/dist/icon-widget.d.ts.map +1 -1
  18. package/dist/icon-widget.js +3 -2
  19. package/dist/icon-widget.js.map +1 -1
  20. package/dist/index.cjs +3330 -218
  21. package/dist/index.cjs.map +3 -4
  22. package/dist/index.d.ts +1 -0
  23. package/dist/index.d.ts.map +1 -1
  24. package/dist/index.js +1 -0
  25. package/dist/index.js.map +1 -1
  26. package/dist/info-widget.d.ts.map +1 -1
  27. package/dist/lib/components/button-group.d.ts.map +1 -1
  28. package/dist/lib/components/dropdown-menu.d.ts.map +1 -1
  29. package/dist/lib/components/icon-button.d.ts +2 -0
  30. package/dist/lib/components/icon-button.d.ts.map +1 -1
  31. package/dist/lib/components/icon-button.js +5 -2
  32. package/dist/lib/components/icon-button.js.map +1 -1
  33. package/dist/lib/components/popover.d.ts.map +1 -1
  34. package/dist/lib/components/tooltip.d.ts +14 -0
  35. package/dist/lib/components/tooltip.d.ts.map +1 -0
  36. package/dist/lib/components/tooltip.js +64 -0
  37. package/dist/lib/components/tooltip.js.map +1 -0
  38. package/dist/lib/components/user-content.d.ts.map +1 -1
  39. package/dist/loading-widget.d.ts +2 -0
  40. package/dist/loading-widget.d.ts.map +1 -1
  41. package/dist/loading-widget.js +2 -1
  42. package/dist/loading-widget.js.map +1 -1
  43. package/dist/popup-widget.d.ts.map +1 -1
  44. package/dist/reset-view-widget.d.ts +2 -0
  45. package/dist/reset-view-widget.d.ts.map +1 -1
  46. package/dist/reset-view-widget.js +2 -1
  47. package/dist/reset-view-widget.js.map +1 -1
  48. package/dist/screenshot-widget.d.ts +2 -0
  49. package/dist/screenshot-widget.d.ts.map +1 -1
  50. package/dist/screenshot-widget.js +2 -1
  51. package/dist/screenshot-widget.js.map +1 -1
  52. package/dist/scrollbar-widget.d.ts +6 -1
  53. package/dist/scrollbar-widget.d.ts.map +1 -1
  54. package/dist/scrollbar-widget.js +12 -3
  55. package/dist/scrollbar-widget.js.map +1 -1
  56. package/dist/selector-widget.d.ts +2 -0
  57. package/dist/selector-widget.d.ts.map +1 -1
  58. package/dist/selector-widget.js +2 -1
  59. package/dist/selector-widget.js.map +1 -1
  60. package/dist/splitter-widget.d.ts.map +1 -1
  61. package/dist/stylesheet.css +102 -116
  62. package/dist/theme-widget.d.ts +4 -0
  63. package/dist/theme-widget.d.ts.map +1 -1
  64. package/dist/theme-widget.js +4 -2
  65. package/dist/theme-widget.js.map +1 -1
  66. package/dist/themes.d.ts +5 -0
  67. package/dist/themes.d.ts.map +1 -1
  68. package/dist/themes.js +4 -0
  69. package/dist/themes.js.map +1 -1
  70. package/dist/timeline-widget.d.ts +4 -0
  71. package/dist/timeline-widget.d.ts.map +1 -1
  72. package/dist/timeline-widget.js +5 -3
  73. package/dist/timeline-widget.js.map +1 -1
  74. package/dist/toggle-widget.d.ts +4 -0
  75. package/dist/toggle-widget.d.ts.map +1 -1
  76. package/dist/toggle-widget.js +4 -2
  77. package/dist/toggle-widget.js.map +1 -1
  78. package/dist/zoom-widget.d.ts +4 -0
  79. package/dist/zoom-widget.d.ts.map +1 -1
  80. package/dist/zoom-widget.js +3 -1
  81. package/dist/zoom-widget.js.map +1 -1
  82. package/dist.min.js +2 -2
  83. package/package.json +8 -4
  84. package/src/compass-widget.tsx +31 -23
  85. package/src/fullscreen-widget.tsx +7 -0
  86. package/src/gimbal-widget.tsx +62 -54
  87. package/src/icon-widget.tsx +5 -1
  88. package/src/icons/add.svg +1 -0
  89. package/src/icons/chevron-down.svg +1 -0
  90. package/src/icons/chevron-left.svg +1 -0
  91. package/src/icons/chevron-right.svg +1 -0
  92. package/src/icons/chevron-up.svg +1 -0
  93. package/src/icons/close.svg +1 -0
  94. package/src/icons/dark-mode.svg +1 -0
  95. package/src/icons/dropdown.svg +1 -0
  96. package/src/icons/fullscreen-exit.svg +1 -0
  97. package/src/icons/fullscreen.svg +1 -0
  98. package/src/icons/light-mode.svg +1 -0
  99. package/src/icons/loading.svg +1 -0
  100. package/src/icons/pause.svg +1 -0
  101. package/src/icons/photo-camera.svg +1 -0
  102. package/src/icons/play-arrow.svg +1 -0
  103. package/src/icons/remove.svg +1 -0
  104. package/src/icons/reset-focus.svg +1 -0
  105. package/src/index.ts +1 -0
  106. package/src/lib/components/icon-button.tsx +17 -9
  107. package/src/lib/components/tooltip.tsx +116 -0
  108. package/src/loading-widget.tsx +4 -0
  109. package/src/reset-view-widget.tsx +4 -0
  110. package/src/screenshot-widget.tsx +4 -0
  111. package/src/scrollbar-widget.tsx +30 -4
  112. package/src/selector-widget.tsx +4 -0
  113. package/src/stylesheet.css +67 -114
  114. package/src/theme-widget.tsx +8 -1
  115. package/src/themes.ts +5 -0
  116. package/src/timeline-widget.tsx +10 -2
  117. package/src/toggle-widget.tsx +9 -0
  118. package/src/zoom-widget.tsx +8 -0
package/dist/index.cjs CHANGED
@@ -18,8 +18,8 @@ var __copyProps = (to, from, except, desc) => {
18
18
  var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
19
 
20
20
  // dist/index.js
21
- var dist_exports = {};
22
- __export(dist_exports, {
21
+ var index_exports = {};
22
+ __export(index_exports, {
23
23
  CompassWidget: () => CompassWidget,
24
24
  ContextMenuWidget: () => ContextMenuWidget,
25
25
  DarkGlassTheme: () => DarkGlassTheme,
@@ -54,13 +54,3049 @@ __export(dist_exports, {
54
54
  _SplitterWidget: () => SplitterWidget,
55
55
  _StatsWidget: () => StatsWidget,
56
56
  _TimelineWidget: () => TimelineWidget,
57
+ _Tooltip: () => Tooltip,
57
58
  buildViewsFromViewLayout: () => buildViewsFromViewLayout
58
59
  });
59
- module.exports = __toCommonJS(dist_exports);
60
+ module.exports = __toCommonJS(index_exports);
61
+
62
+ // dist/zoom-widget.js
63
+ 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
+ };
60
3098
 
61
3099
  // dist/zoom-widget.js
62
- var import_jsx_runtime3 = require("preact/jsx-runtime");
63
- var import_core = require("@deck.gl/core");
64
3100
  var import_preact = require("preact");
65
3101
 
66
3102
  // dist/lib/components/button-group.js
@@ -71,8 +3107,8 @@ var ButtonGroup = (props) => {
71
3107
  };
72
3108
 
73
3109
  // dist/lib/components/icon-button.js
74
- var import_jsx_runtime2 = require("preact/jsx-runtime");
75
- var import_hooks = require("preact/hooks");
3110
+ var import_jsx_runtime3 = require("preact/jsx-runtime");
3111
+ var import_hooks2 = require("preact/hooks");
76
3112
 
77
3113
  // dist/lib/data-url.js
78
3114
  function getCSSMask(imageUrl) {
@@ -82,20 +3118,87 @@ function getCSSMask(imageUrl) {
82
3118
  return { maskImage: cssUrl, WebkitMaskImage: cssUrl };
83
3119
  }
84
3120
 
3121
+ // dist/lib/components/tooltip.js
3122
+ var import_jsx_runtime2 = require("preact/jsx-runtime");
3123
+ var import_hooks = require("preact/hooks");
3124
+ var import_dom = require("@floating-ui/dom");
3125
+ var Tooltip = ({ content, placement = "right", children }) => {
3126
+ const wrapperRef = (0, import_hooks.useRef)(null);
3127
+ const tooltipRef = (0, import_hooks.useRef)(null);
3128
+ const [visible, setVisible] = (0, import_hooks.useState)(false);
3129
+ const delayRef = (0, import_hooks.useRef)();
3130
+ const show = (0, import_hooks.useCallback)(() => {
3131
+ clearTimeout(delayRef.current);
3132
+ setVisible(true);
3133
+ }, []);
3134
+ const hide = (0, import_hooks.useCallback)(() => {
3135
+ clearTimeout(delayRef.current);
3136
+ setVisible(false);
3137
+ }, []);
3138
+ const onKeyDown = (0, import_hooks.useCallback)((e) => {
3139
+ if (e.key === "Escape")
3140
+ hide();
3141
+ }, [hide]);
3142
+ (0, import_hooks.useEffect)(() => {
3143
+ var _a;
3144
+ const tooltip = tooltipRef.current;
3145
+ const trigger = (_a = wrapperRef.current) == null ? void 0 : _a.firstElementChild;
3146
+ if (!visible || !tooltip || !trigger)
3147
+ return void 0;
3148
+ const updatePosition = () => {
3149
+ (0, import_dom.computePosition)(trigger, tooltip, {
3150
+ placement,
3151
+ strategy: "fixed",
3152
+ middleware: [(0, import_dom.offset)(8), (0, import_dom.flip)(), (0, import_dom.shift)({ padding: 4 })]
3153
+ }).then(({ x, y }) => {
3154
+ if (tooltipRef.current === tooltip) {
3155
+ Object.assign(tooltip.style, { left: `${x}px`, top: `${y}px`, opacity: "1" });
3156
+ }
3157
+ });
3158
+ };
3159
+ return (0, import_dom.autoUpdate)(trigger, tooltip, updatePosition);
3160
+ }, [visible, placement]);
3161
+ (0, import_hooks.useEffect)(() => {
3162
+ return () => clearTimeout(delayRef.current);
3163
+ }, []);
3164
+ const htmlRef = (0, import_hooks.useCallback)((el) => {
3165
+ if (el && content instanceof HTMLElement) {
3166
+ el.replaceChildren(content.cloneNode(true));
3167
+ }
3168
+ }, [content]);
3169
+ const renderContent = () => {
3170
+ if (content instanceof HTMLElement) {
3171
+ return (0, import_jsx_runtime2.jsx)("div", { ref: htmlRef });
3172
+ }
3173
+ return content;
3174
+ };
3175
+ if (content === null || content === void 0 || content === false || content === "") {
3176
+ return (0, import_jsx_runtime2.jsx)(import_jsx_runtime2.Fragment, { children });
3177
+ }
3178
+ return (0, import_jsx_runtime2.jsxs)("div", { ref: wrapperRef, className: "deck-widget-tooltip-trigger", onPointerEnter: show, onPointerLeave: hide, onFocusCapture: show, onBlurCapture: hide, onKeyDown, children: [children, visible && (0, import_jsx_runtime2.jsx)("div", { ref: tooltipRef, className: "deck-widget-tooltip", role: "tooltip", style: {
3179
+ position: "fixed",
3180
+ opacity: 0,
3181
+ fontSize: "12px",
3182
+ padding: "4px 8px"
3183
+ }, children: renderContent() })] });
3184
+ };
3185
+
85
3186
  // dist/lib/components/icon-button.js
86
3187
  var IconButton = (props) => {
87
- const { className = "", style, color, icon, label, onClick, children } = props;
88
- const iconStyle = (0, import_hooks.useMemo)(() => {
3188
+ const { className = "", style, color, icon, label, tooltip, onClick, children } = props;
3189
+ const tooltipContent = tooltip === false ? void 0 : tooltip ?? label;
3190
+ const iconStyle = (0, import_hooks2.useMemo)(() => {
89
3191
  const css = getCSSMask(icon);
90
3192
  if (!color)
91
3193
  return css;
92
3194
  return { ...css, backgroundColor: color };
93
3195
  }, [color, icon]);
94
- return (0, import_jsx_runtime2.jsx)("div", { className: "deck-widget-button", style, children: (0, import_jsx_runtime2.jsx)("button", { className: `deck-widget-icon-button ${className}`, type: "button", onClick, title: label, children: children ? children : (0, import_jsx_runtime2.jsx)("div", { className: "deck-widget-icon", style: iconStyle }) }) });
3196
+ const button = (0, import_jsx_runtime3.jsx)("button", { className: `deck-widget-icon-button ${className}`, type: "button", onClick, "aria-label": label, children: children ? children : (0, import_jsx_runtime3.jsx)("div", { className: "deck-widget-icon", style: iconStyle }) });
3197
+ return (0, import_jsx_runtime3.jsx)("div", { className: "deck-widget-button", style, children: tooltipContent ? (0, import_jsx_runtime3.jsx)(Tooltip, { content: tooltipContent, children: button }) : button });
95
3198
  };
96
3199
 
97
3200
  // dist/zoom-widget.js
98
- var ZoomWidget = class extends import_core.Widget {
3201
+ var ZoomWidget = class extends Widget {
99
3202
  constructor(props = {}) {
100
3203
  super(props);
101
3204
  this.className = "deck-widget-zoom";
@@ -108,13 +3211,13 @@ var ZoomWidget = class extends import_core.Widget {
108
3211
  super.setProps(props);
109
3212
  }
110
3213
  onRenderHTML(rootElement) {
111
- const ui = (0, import_jsx_runtime3.jsxs)(ButtonGroup, { orientation: this.props.orientation, children: [(0, import_jsx_runtime3.jsx)(IconButton, { onClick: () => this.handleZoomIn(), label: this.props.zoomInLabel, className: "deck-widget-zoom-in" }), (0, import_jsx_runtime3.jsx)(IconButton, { onClick: () => this.handleZoomOut(), label: this.props.zoomOutLabel, className: "deck-widget-zoom-out" })] });
3214
+ const ui = (0, import_jsx_runtime4.jsxs)(ButtonGroup, { orientation: this.props.orientation, children: [(0, import_jsx_runtime4.jsx)(IconButton, { onClick: () => this.handleZoomIn(), label: this.props.zoomInLabel, tooltip: this.props.zoomInTooltip, className: "deck-widget-zoom-in" }), (0, import_jsx_runtime4.jsx)(IconButton, { onClick: () => this.handleZoomOut(), label: this.props.zoomOutLabel, tooltip: this.props.zoomOutTooltip, className: "deck-widget-zoom-out" })] });
112
3215
  (0, import_preact.render)(ui, rootElement);
113
3216
  }
114
3217
  isOrthographicView(viewId) {
115
3218
  const deck = this.deck;
116
3219
  const view = (deck == null ? void 0 : deck.isInitialized) && deck.getView(viewId);
117
- return view instanceof import_core.OrthographicView;
3220
+ return view instanceof OrthographicView;
118
3221
  }
119
3222
  handleZoom(viewId, delta) {
120
3223
  var _a, _b, _c, _d;
@@ -126,13 +3229,13 @@ var ZoomWidget = class extends import_core.Widget {
126
3229
  let nextZoom;
127
3230
  let nextZoomY;
128
3231
  if (zoomAxis === "X") {
129
- nextZoom = clamp(zoomX + delta, minZoomX, maxZoomX);
3232
+ nextZoom = clamp5(zoomX + delta, minZoomX, maxZoomX);
130
3233
  nextZoomY = zoomY;
131
3234
  } else if (zoomAxis === "Y") {
132
3235
  nextZoom = zoomX;
133
- nextZoomY = clamp(zoomY + delta, minZoomY, maxZoomY);
3236
+ nextZoomY = clamp5(zoomY + delta, minZoomY, maxZoomY);
134
3237
  } else {
135
- const clampedDelta = clamp(delta, Math.max(minZoomX - zoomX, minZoomY - zoomY), Math.min(maxZoomX - zoomX, maxZoomY - zoomY));
3238
+ const clampedDelta = clamp5(delta, Math.max(minZoomX - zoomX, minZoomY - zoomY), Math.min(maxZoomX - zoomX, maxZoomY - zoomY));
136
3239
  nextZoom = zoomX + clampedDelta;
137
3240
  nextZoomY = zoomY + clampedDelta;
138
3241
  }
@@ -149,7 +3252,7 @@ var ZoomWidget = class extends import_core.Widget {
149
3252
  });
150
3253
  } else {
151
3254
  const { zoom = 0, minZoom, maxZoom } = viewState;
152
- const nextZoom = clamp(zoom + delta, minZoom, maxZoom);
3255
+ const nextZoom = clamp5(zoom + delta, minZoom, maxZoom);
153
3256
  newViewState.zoom = nextZoom;
154
3257
  (_d = (_c = this.props).onZoom) == null ? void 0 : _d.call(_c, {
155
3258
  viewId,
@@ -163,7 +3266,7 @@ var ZoomWidget = class extends import_core.Widget {
163
3266
  };
164
3267
  if (this.props.transitionDuration > 0) {
165
3268
  nextViewState.transitionDuration = this.props.transitionDuration;
166
- nextViewState.transitionInterpolator = "latitude" in nextViewState ? new import_core.FlyToInterpolator() : new import_core.LinearInterpolator({
3269
+ nextViewState.transitionInterpolator = "latitude" in nextViewState ? new FlyToInterpolator() : new LinearInterpolator({
167
3270
  transitionProps: "zoomX" in newViewState ? ["zoomX", "zoomY"] : ["zoom"]
168
3271
  });
169
3272
  }
@@ -181,7 +3284,7 @@ var ZoomWidget = class extends import_core.Widget {
181
3284
  }
182
3285
  };
183
3286
  ZoomWidget.defaultProps = {
184
- ...import_core.Widget.defaultProps,
3287
+ ...Widget.defaultProps,
185
3288
  id: "zoom",
186
3289
  placement: "top-left",
187
3290
  orientation: "vertical",
@@ -189,12 +3292,14 @@ ZoomWidget.defaultProps = {
189
3292
  zoomStep: 1,
190
3293
  zoomInLabel: "Zoom In",
191
3294
  zoomOutLabel: "Zoom Out",
3295
+ zoomInTooltip: void 0,
3296
+ zoomOutTooltip: void 0,
192
3297
  zoomAxis: "all",
193
3298
  viewId: null,
194
3299
  onZoom: () => {
195
3300
  }
196
3301
  };
197
- function clamp(zoom, minZoom, maxZoom) {
3302
+ function clamp5(zoom, minZoom, maxZoom) {
198
3303
  return zoom < minZoom ? minZoom : zoom > maxZoom ? maxZoom : zoom;
199
3304
  }
200
3305
  function normalizeOrthographicViewState({ zoom = 0, zoomX, zoomY, minZoom = -Infinity, maxZoom = Infinity, minZoomX = minZoom, maxZoomX = maxZoom, minZoomY = minZoom, maxZoomY = maxZoom }) {
@@ -204,10 +3309,9 @@ function normalizeOrthographicViewState({ zoom = 0, zoomX, zoomY, minZoom = -Inf
204
3309
  }
205
3310
 
206
3311
  // dist/reset-view-widget.js
207
- var import_jsx_runtime4 = require("preact/jsx-runtime");
3312
+ var import_jsx_runtime5 = require("preact/jsx-runtime");
208
3313
  var import_preact2 = require("preact");
209
- var import_core2 = require("@deck.gl/core");
210
- var ResetViewWidget = class extends import_core2.Widget {
3314
+ var ResetViewWidget = class extends Widget {
211
3315
  constructor(props = {}) {
212
3316
  super(props);
213
3317
  this.className = "deck-widget-reset-view";
@@ -220,7 +3324,7 @@ var ResetViewWidget = class extends import_core2.Widget {
220
3324
  super.setProps(props);
221
3325
  }
222
3326
  onRenderHTML(rootElement) {
223
- (0, import_preact2.render)((0, import_jsx_runtime4.jsx)(IconButton, { className: "deck-widget-reset-focus", label: this.props.label, onClick: this.handleClick.bind(this) }), rootElement);
3327
+ (0, import_preact2.render)((0, import_jsx_runtime5.jsx)(IconButton, { className: "deck-widget-reset-focus", label: this.props.label, tooltip: this.props.tooltip, onClick: this.handleClick.bind(this) }), rootElement);
224
3328
  }
225
3329
  handleClick() {
226
3330
  var _a;
@@ -242,10 +3346,11 @@ var ResetViewWidget = class extends import_core2.Widget {
242
3346
  }
243
3347
  };
244
3348
  ResetViewWidget.defaultProps = {
245
- ...import_core2.Widget.defaultProps,
3349
+ ...Widget.defaultProps,
246
3350
  id: "reset-view",
247
3351
  placement: "top-left",
248
3352
  label: "Reset View",
3353
+ tooltip: void 0,
249
3354
  initialViewState: void 0,
250
3355
  viewId: null,
251
3356
  onReset: () => {
@@ -253,10 +3358,9 @@ ResetViewWidget.defaultProps = {
253
3358
  };
254
3359
 
255
3360
  // dist/gimbal-widget.js
256
- var import_jsx_runtime5 = require("preact/jsx-runtime");
257
- var import_core3 = require("@deck.gl/core");
3361
+ var import_jsx_runtime6 = require("preact/jsx-runtime");
258
3362
  var import_preact3 = require("preact");
259
- var GimbalWidget = class extends import_core3.Widget {
3363
+ var GimbalWidget = class extends Widget {
260
3364
  constructor(props = {}) {
261
3365
  super(props);
262
3366
  this.className = "deck-widget-gimbal";
@@ -274,21 +3378,22 @@ var GimbalWidget = class extends import_core3.Widget {
274
3378
  const viewId = this.viewId || ((_a = Object.values(this.viewports)[0]) == null ? void 0 : _a.id) || "default-view";
275
3379
  const widgetViewport = this.viewports[viewId];
276
3380
  const { rotationOrbit, rotationX } = this.getNormalizedRotation(widgetViewport);
277
- const ui = (0, import_jsx_runtime5.jsx)("div", { className: "deck-widget-button", style: { perspective: 100, pointerEvents: "auto" }, children: (0, import_jsx_runtime5.jsxs)("button", { type: "button", onClick: () => {
3381
+ const tooltipContent = this.props.tooltip === false ? void 0 : this.props.tooltip ?? this.props.label;
3382
+ const ui = (0, import_jsx_runtime6.jsx)("div", { className: "deck-widget-button", style: { perspective: 100, pointerEvents: "auto" }, children: (0, import_jsx_runtime6.jsx)(Tooltip, { content: tooltipContent, children: (0, import_jsx_runtime6.jsxs)("button", { type: "button", onClick: () => {
278
3383
  for (const viewport of Object.values(this.viewports)) {
279
3384
  this.resetOrbitView(viewport);
280
3385
  }
281
- }, title: this.props.label, style: { position: "relative", width: 26, height: 26 }, children: [(0, import_jsx_runtime5.jsx)("svg", { className: "gimbal-outer-ring", width: "100%", height: "100%", viewBox: "0 0 26 26", style: {
3386
+ }, "aria-label": this.props.label, style: { position: "relative", width: 26, height: 26 }, children: [(0, import_jsx_runtime6.jsx)("svg", { className: "gimbal-outer-ring", width: "100%", height: "100%", viewBox: "0 0 26 26", style: {
282
3387
  position: "absolute",
283
3388
  top: 0,
284
3389
  left: 0,
285
3390
  transform: `rotateY(${rotationOrbit}deg)`
286
- }, children: (0, import_jsx_runtime5.jsx)("circle", { cx: "13", cy: "13", r: "10", stroke: "var(--icon-gimbal-outer-color, rgb(68, 92, 204))", strokeWidth: this.props.strokeWidth, fill: "none" }) }), (0, import_jsx_runtime5.jsx)("svg", { className: "gimbal-inner-ring", width: "100%", height: "100%", viewBox: "0 0 26 26", style: {
3391
+ }, children: (0, import_jsx_runtime6.jsx)("circle", { cx: "13", cy: "13", r: "10", stroke: "var(--icon-gimbal-outer-color, rgb(68, 92, 204))", strokeWidth: this.props.strokeWidth, fill: "none" }) }), (0, import_jsx_runtime6.jsx)("svg", { className: "gimbal-inner-ring", width: "100%", height: "100%", viewBox: "0 0 26 26", style: {
287
3392
  position: "absolute",
288
3393
  top: 0,
289
3394
  left: 0,
290
3395
  transform: `rotateX(${rotationX}deg)`
291
- }, children: (0, import_jsx_runtime5.jsx)("circle", { cx: "13", cy: "13", r: "7", stroke: "var(--icon-gimbal-inner-color, rgb(240, 92, 68))", strokeWidth: this.props.strokeWidth, fill: "none" }) })] }) });
3396
+ }, children: (0, import_jsx_runtime6.jsx)("circle", { cx: "13", cy: "13", r: "7", stroke: "var(--icon-gimbal-inner-color, rgb(240, 92, 68))", strokeWidth: this.props.strokeWidth, fill: "none" }) })] }) }) });
292
3397
  (0, import_preact3.render)(ui, rootElement);
293
3398
  }
294
3399
  onViewportChange(viewport) {
@@ -306,7 +3411,7 @@ var GimbalWidget = class extends import_core3.Widget {
306
3411
  rotationOrbit: 0,
307
3412
  rotationX: 0,
308
3413
  transitionDuration: this.props.transitionDuration,
309
- transitionInterpolator: new import_core3.LinearInterpolator({
3414
+ transitionInterpolator: new LinearInterpolator({
310
3415
  transitionProps: ["rotationOrbit", "rotationX"]
311
3416
  })
312
3417
  };
@@ -329,11 +3434,12 @@ var GimbalWidget = class extends import_core3.Widget {
329
3434
  }
330
3435
  };
331
3436
  GimbalWidget.defaultProps = {
332
- ...import_core3.Widget.defaultProps,
3437
+ ...Widget.defaultProps,
333
3438
  id: "gimbal",
334
3439
  placement: "top-left",
335
3440
  viewId: null,
336
3441
  label: "Gimbal",
3442
+ tooltip: void 0,
337
3443
  strokeWidth: 1.5,
338
3444
  transitionDuration: 200,
339
3445
  onReset: () => {
@@ -354,10 +3460,9 @@ function normalizeAndClampAngle(angle) {
354
3460
  }
355
3461
 
356
3462
  // dist/compass-widget.js
357
- var import_jsx_runtime6 = require("preact/jsx-runtime");
358
- var import_core4 = require("@deck.gl/core");
3463
+ var import_jsx_runtime7 = require("preact/jsx-runtime");
359
3464
  var import_preact4 = require("preact");
360
- var CompassWidget = class extends import_core4.Widget {
3465
+ var CompassWidget = class extends Widget {
361
3466
  constructor(props = {}) {
362
3467
  super(props);
363
3468
  this.className = "deck-widget-compass";
@@ -375,11 +3480,12 @@ var CompassWidget = class extends import_core4.Widget {
375
3480
  const viewId = this.viewId || ((_a = Object.values(this.viewports)[0]) == null ? void 0 : _a.id);
376
3481
  const widgetViewport = this.viewports[viewId];
377
3482
  const [rz, rx] = this.getRotation(widgetViewport);
378
- const ui = (0, import_jsx_runtime6.jsx)("div", { className: "deck-widget-button", style: { perspective: 100 }, children: (0, import_jsx_runtime6.jsx)("button", { type: "button", onClick: () => {
3483
+ const tooltipContent = this.props.tooltip === false ? void 0 : this.props.tooltip ?? this.props.label;
3484
+ const ui = (0, import_jsx_runtime7.jsx)("div", { className: "deck-widget-button", style: { perspective: 100 }, children: (0, import_jsx_runtime7.jsx)(Tooltip, { content: tooltipContent, children: (0, import_jsx_runtime7.jsx)("button", { type: "button", onClick: () => {
379
3485
  for (const viewport of Object.values(this.viewports)) {
380
3486
  this.handleCompassReset(viewport);
381
3487
  }
382
- }, title: this.props.label, style: { transform: `rotateX(${rx}deg)` }, children: (0, import_jsx_runtime6.jsx)("svg", { fill: "none", width: "100%", height: "100%", viewBox: "0 0 26 26", children: (0, import_jsx_runtime6.jsxs)("g", { transform: `rotate(${rz},13,13)`, children: [(0, import_jsx_runtime6.jsx)("path", { d: "M10 13.0001L12.9999 5L15.9997 13.0001H10Z", fill: "var(--icon-compass-north-color, rgb(240, 92, 68))" }), (0, import_jsx_runtime6.jsx)("path", { d: "M16.0002 12.9999L13.0004 21L10.0005 12.9999H16.0002Z", fill: "var(--icon-compass-south-color, rgb(204, 204, 204))" })] }) }) }) });
3488
+ }, "aria-label": this.props.label, style: { transform: `rotateX(${rx}deg)` }, children: (0, import_jsx_runtime7.jsx)("svg", { fill: "none", width: "100%", height: "100%", viewBox: "0 0 26 26", children: (0, import_jsx_runtime7.jsxs)("g", { transform: `rotate(${rz},13,13)`, children: [(0, import_jsx_runtime7.jsx)("path", { d: "M10 13.0001L12.9999 5L15.9997 13.0001H10Z", fill: "var(--icon-compass-north-color, rgb(240, 92, 68))" }), (0, import_jsx_runtime7.jsx)("path", { d: "M16.0002 12.9999L13.0004 21L10.0005 12.9999H16.0002Z", fill: "var(--icon-compass-south-color, rgb(204, 204, 204))" })] }) }) }) }) });
383
3489
  (0, import_preact4.render)(ui, rootElement);
384
3490
  }
385
3491
  onViewportChange(viewport) {
@@ -389,9 +3495,9 @@ var CompassWidget = class extends import_core4.Widget {
389
3495
  }
390
3496
  }
391
3497
  getRotation(viewport) {
392
- if (viewport instanceof import_core4.WebMercatorViewport) {
3498
+ if (viewport instanceof WebMercatorViewport) {
393
3499
  return [-viewport.bearing, viewport.pitch];
394
- } else if (viewport instanceof import_core4._GlobeViewport) {
3500
+ } else if (viewport instanceof GlobeViewport) {
395
3501
  return [0, Math.max(-80, Math.min(80, viewport.latitude))];
396
3502
  }
397
3503
  return [0, 0];
@@ -399,7 +3505,7 @@ var CompassWidget = class extends import_core4.Widget {
399
3505
  handleCompassReset(viewport) {
400
3506
  var _a, _b;
401
3507
  const viewId = this.viewId || viewport.id;
402
- if (viewport instanceof import_core4.WebMercatorViewport) {
3508
+ if (viewport instanceof WebMercatorViewport) {
403
3509
  const viewState = this.getViewState(viewId);
404
3510
  const resetPitch = this.getRotation(viewport)[0] === 0;
405
3511
  const nextBearing = 0;
@@ -410,28 +3516,28 @@ var CompassWidget = class extends import_core4.Widget {
410
3516
  bearing: nextBearing,
411
3517
  ...resetPitch ? { pitch: nextPitch } : {},
412
3518
  transitionDuration: this.props.transitionDuration,
413
- transitionInterpolator: new import_core4.FlyToInterpolator()
3519
+ transitionInterpolator: new FlyToInterpolator()
414
3520
  };
415
3521
  this.setViewState(viewId, nextViewState);
416
3522
  }
417
3523
  }
418
3524
  };
419
3525
  CompassWidget.defaultProps = {
420
- ...import_core4.Widget.defaultProps,
3526
+ ...Widget.defaultProps,
421
3527
  id: "compass",
422
3528
  placement: "top-left",
423
3529
  viewId: null,
424
3530
  label: "Reset Compass",
3531
+ tooltip: void 0,
425
3532
  transitionDuration: 200,
426
3533
  onReset: () => {
427
3534
  }
428
3535
  };
429
3536
 
430
3537
  // dist/scale-widget.js
431
- var import_jsx_runtime7 = require("preact/jsx-runtime");
3538
+ var import_jsx_runtime8 = require("preact/jsx-runtime");
432
3539
  var import_preact5 = require("preact");
433
- var import_core5 = require("@deck.gl/core");
434
- var ScaleWidget = class extends import_core5.Widget {
3540
+ var ScaleWidget = class extends Widget {
435
3541
  constructor(props = {}) {
436
3542
  super(props);
437
3543
  this.className = "deck-widget-scale";
@@ -450,7 +3556,7 @@ var ScaleWidget = class extends import_core5.Widget {
450
3556
  const lineOffsetX = 50;
451
3557
  const svgWidth = lineOffsetX + this.scaleWidth;
452
3558
  const tickHeight = 10;
453
- (0, import_preact5.render)((0, import_jsx_runtime7.jsxs)("svg", { className: "deck-widget-scale", width: svgWidth, height: 30, style: { overflow: "visible", background: "transparent" }, onClick: this.handleClick.bind(this), children: [(0, import_jsx_runtime7.jsx)("text", { x: lineOffsetX + 5, y: "10", textAnchor: "end", alignmentBaseline: "middle", style: { fontSize: "16px", fill: "black", fontWeight: "bold", fontFamily: "sans-serif" }, children: this.scaleText }), (0, import_jsx_runtime7.jsx)("line", { x1: lineOffsetX, y1: "15", x2: lineOffsetX + this.scaleWidth, y2: "15", stroke: "black", strokeWidth: "6" }), (0, import_jsx_runtime7.jsx)("line", { x1: lineOffsetX, y1: "15", x2: lineOffsetX, y2: 15 - tickHeight, stroke: "black", strokeWidth: "6" }), (0, import_jsx_runtime7.jsx)("line", { x1: lineOffsetX + this.scaleWidth, y1: "15", x2: lineOffsetX + this.scaleWidth, y2: 15 - tickHeight, stroke: "black", strokeWidth: "6" })] }), rootElement);
3559
+ (0, import_preact5.render)((0, import_jsx_runtime8.jsxs)("svg", { className: "deck-widget-scale", width: svgWidth, height: 30, style: { overflow: "visible", background: "transparent" }, onClick: this.handleClick.bind(this), children: [(0, import_jsx_runtime8.jsx)("text", { x: lineOffsetX + 5, y: "10", textAnchor: "end", alignmentBaseline: "middle", style: { fontSize: "16px", fill: "black", fontWeight: "bold", fontFamily: "sans-serif" }, children: this.scaleText }), (0, import_jsx_runtime8.jsx)("line", { x1: lineOffsetX, y1: "15", x2: lineOffsetX + this.scaleWidth, y2: "15", stroke: "black", strokeWidth: "6" }), (0, import_jsx_runtime8.jsx)("line", { x1: lineOffsetX, y1: "15", x2: lineOffsetX, y2: 15 - tickHeight, stroke: "black", strokeWidth: "6" }), (0, import_jsx_runtime8.jsx)("line", { x1: lineOffsetX + this.scaleWidth, y1: "15", x2: lineOffsetX + this.scaleWidth, y2: 15 - tickHeight, stroke: "black", strokeWidth: "6" })] }), rootElement);
454
3560
  }
455
3561
  onViewportChange(viewport) {
456
3562
  if (!("latitude" in viewport))
@@ -471,7 +3577,7 @@ var ScaleWidget = class extends import_core5.Widget {
471
3577
  }
472
3578
  };
473
3579
  ScaleWidget.defaultProps = {
474
- ...import_core5.Widget.defaultProps,
3580
+ ...Widget.defaultProps,
475
3581
  id: "scale",
476
3582
  placement: "bottom-left",
477
3583
  label: "Scale",
@@ -513,14 +3619,12 @@ function computeScaleCandidate(metersPerPixel) {
513
3619
  }
514
3620
 
515
3621
  // dist/geocoder-widget.js
516
- var import_jsx_runtime9 = require("preact/jsx-runtime");
517
- var import_core6 = require("@deck.gl/core");
518
- var import_core7 = require("@deck.gl/core");
3622
+ var import_jsx_runtime10 = require("preact/jsx-runtime");
519
3623
  var import_preact6 = require("preact");
520
3624
 
521
3625
  // dist/lib/components/dropdown-menu.js
522
- var import_jsx_runtime8 = require("preact/jsx-runtime");
523
- var import_hooks2 = require("preact/hooks");
3626
+ var import_jsx_runtime9 = require("preact/jsx-runtime");
3627
+ var import_hooks3 = require("preact/hooks");
524
3628
  function getMenuItemValue(item) {
525
3629
  return typeof item === "string" ? item : item.value;
526
3630
  }
@@ -531,12 +3635,12 @@ function getMenuItemIcon(item) {
531
3635
  return typeof item === "string" ? void 0 : item.icon;
532
3636
  }
533
3637
  var DropdownMenu = (props) => {
534
- const [isOpen, setIsOpen] = (0, import_hooks2.useState)(false);
535
- return (0, import_jsx_runtime8.jsx)(SimpleMenu, { ...props, style: { ...props.style, position: "absolute" }, isOpen, onClose: () => setIsOpen(false), trigger: (0, import_jsx_runtime8.jsx)("button", { className: "deck-widget-dropdown-button", onClick: () => setIsOpen(!isOpen), children: (0, import_jsx_runtime8.jsx)("span", { className: `deck-widget-dropdown-icon ${isOpen ? "open" : ""}` }) }) });
3638
+ const [isOpen, setIsOpen] = (0, import_hooks3.useState)(false);
3639
+ return (0, import_jsx_runtime9.jsx)(SimpleMenu, { ...props, style: { ...props.style, position: "absolute" }, isOpen, onClose: () => setIsOpen(false), trigger: (0, import_jsx_runtime9.jsx)("button", { className: "deck-widget-dropdown-button", onClick: () => setIsOpen(!isOpen), children: (0, import_jsx_runtime9.jsx)("span", { className: `deck-widget-dropdown-icon ${isOpen ? "open" : ""}` }) }) });
536
3640
  };
537
3641
  var SimpleMenu = (props) => {
538
- const dropdownRef = (0, import_hooks2.useRef)(null);
539
- (0, import_hooks2.useEffect)(() => {
3642
+ const dropdownRef = (0, import_hooks3.useRef)(null);
3643
+ (0, import_hooks3.useEffect)(() => {
540
3644
  const handleClickOutside = (event) => {
541
3645
  if (dropdownRef.current && !dropdownRef.current.contains(event.target)) {
542
3646
  props.onClose();
@@ -560,10 +3664,10 @@ var SimpleMenu = (props) => {
560
3664
  if (props.menuItems.length === 0) {
561
3665
  return null;
562
3666
  }
563
- return (0, import_jsx_runtime8.jsxs)("div", { className: "deck-widget-dropdown-container", ref: dropdownRef, children: [props.trigger, props.isOpen && (0, import_jsx_runtime8.jsx)("ul", { className: "deck-widget-dropdown-menu", style: props.style, children: props.menuItems.map((item, i) => {
3667
+ return (0, import_jsx_runtime9.jsxs)("div", { className: "deck-widget-dropdown-container", ref: dropdownRef, children: [props.trigger, props.isOpen && (0, import_jsx_runtime9.jsx)("ul", { className: "deck-widget-dropdown-menu", style: props.style, children: props.menuItems.map((item, i) => {
564
3668
  const value = getMenuItemValue(item);
565
3669
  const icon = getMenuItemIcon(item);
566
- return (0, import_jsx_runtime8.jsxs)("li", { className: `deck-widget-dropdown-item ${value ? "" : "disabled"}`, onClick: () => handleSelect(value, item), children: [icon && (0, import_jsx_runtime8.jsx)("span", { className: "deck-widget-dropdown-item-icon", style: getCSSMask(icon) }), getMenuItemLabel(item)] }, i);
3670
+ return (0, import_jsx_runtime9.jsxs)("li", { className: `deck-widget-dropdown-item ${value ? "" : "disabled"}`, onClick: () => handleSelect(value, item), children: [icon && (0, import_jsx_runtime9.jsx)("span", { className: "deck-widget-dropdown-item-icon", style: getCSSMask(icon) }), getMenuItemLabel(item)] }, i);
567
3671
  }) })] });
568
3672
  };
569
3673
 
@@ -770,7 +3874,7 @@ var CURRENT_LOCATION_ITEM = {
770
3874
  value: CURRENT_LOCATION2,
771
3875
  icon: LOCATION_ICON
772
3876
  };
773
- var GeocoderWidget = class extends import_core6.Widget {
3877
+ var GeocoderWidget = class extends Widget {
774
3878
  constructor(props = {}) {
775
3879
  super(props);
776
3880
  this.className = "deck-widget-geocoder";
@@ -839,7 +3943,7 @@ var GeocoderWidget = class extends import_core6.Widget {
839
3943
  }
840
3944
  onRenderHTML(rootElement) {
841
3945
  const menuItems = this.props._geolocation ? [CURRENT_LOCATION_ITEM, ...this.geocodeHistory.addressHistory] : [...this.geocodeHistory.addressHistory];
842
- (0, import_preact6.render)((0, import_jsx_runtime9.jsxs)("div", { className: "deck-widget-geocoder", children: [(0, import_jsx_runtime9.jsx)("input", {
3946
+ (0, import_preact6.render)((0, import_jsx_runtime10.jsxs)("div", { className: "deck-widget-geocoder", children: [(0, import_jsx_runtime10.jsx)("input", {
843
3947
  className: "deck-widget-geocoder-input",
844
3948
  type: "text",
845
3949
  placeholder: this.isGettingLocation ? "Finding your location..." : this.geocoder.placeholderLocation ?? "Enter address or location",
@@ -850,7 +3954,7 @@ var GeocoderWidget = class extends import_core6.Widget {
850
3954
  return this.setInput(((_a = e.target) == null ? void 0 : _a.value) || "");
851
3955
  },
852
3956
  onKeyPress: this.handleKeyPress
853
- }), (0, import_jsx_runtime9.jsx)(DropdownMenu, { menuItems, onSelect: this.handleSelect }), this.geocodeHistory.errorText && (0, import_jsx_runtime9.jsx)("div", { className: "deck-widget-geocoder-error", children: this.geocodeHistory.errorText })] }), rootElement);
3957
+ }), (0, import_jsx_runtime10.jsx)(DropdownMenu, { menuItems, onSelect: this.handleSelect }), this.geocodeHistory.errorText && (0, import_jsx_runtime10.jsx)("div", { className: "deck-widget-geocoder-error", children: this.geocodeHistory.errorText })] }), rootElement);
854
3958
  }
855
3959
  flyTo(viewState) {
856
3960
  var _a, _b;
@@ -872,14 +3976,14 @@ var GeocoderWidget = class extends import_core6.Widget {
872
3976
  };
873
3977
  if (this.props.transitionDuration > 0) {
874
3978
  nextViewState.transitionDuration = this.props.transitionDuration;
875
- nextViewState.transitionInterpolator = "latitude" in nextViewState ? new import_core7.FlyToInterpolator() : new import_core7.LinearInterpolator();
3979
+ nextViewState.transitionInterpolator = "latitude" in nextViewState ? new FlyToInterpolator() : new LinearInterpolator();
876
3980
  }
877
3981
  this.setViewState(viewId, nextViewState);
878
3982
  }
879
3983
  }
880
3984
  };
881
3985
  GeocoderWidget.defaultProps = {
882
- ...import_core6.Widget.defaultProps,
3986
+ ...Widget.defaultProps,
883
3987
  id: "geocoder",
884
3988
  viewId: null,
885
3989
  placement: "top-left",
@@ -913,10 +4017,9 @@ function getGeocoder(props) {
913
4017
  }
914
4018
 
915
4019
  // dist/fullscreen-widget.js
916
- var import_jsx_runtime10 = require("preact/jsx-runtime");
917
- var import_core8 = require("@deck.gl/core");
4020
+ var import_jsx_runtime11 = require("preact/jsx-runtime");
918
4021
  var import_preact7 = require("preact");
919
- var FullscreenWidget = class extends import_core8.Widget {
4022
+ var FullscreenWidget = class extends Widget {
920
4023
  constructor(props = {}) {
921
4024
  super(props);
922
4025
  this.className = "deck-widget-fullscreen";
@@ -932,9 +4035,9 @@ var FullscreenWidget = class extends import_core8.Widget {
932
4035
  }
933
4036
  onRenderHTML(rootElement) {
934
4037
  const isFullscreen = this.getFullscreen();
935
- (0, import_preact7.render)((0, import_jsx_runtime10.jsx)(IconButton, { onClick: () => {
936
- this.handleClick().catch((err) => import_core8.log.error(err)());
937
- }, label: isFullscreen ? this.props.exitLabel : this.props.enterLabel, className: isFullscreen ? "deck-widget-fullscreen-exit" : "deck-widget-fullscreen-enter" }), rootElement);
4038
+ (0, import_preact7.render)((0, import_jsx_runtime11.jsx)(IconButton, { onClick: () => {
4039
+ this.handleClick().catch((err) => log_default.error(err)());
4040
+ }, 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);
938
4041
  }
939
4042
  setProps(props) {
940
4043
  this.placement = props.placement ?? this.placement;
@@ -989,29 +4092,29 @@ var FullscreenWidget = class extends import_core8.Widget {
989
4092
  }
990
4093
  };
991
4094
  FullscreenWidget.defaultProps = {
992
- ...import_core8.Widget.defaultProps,
4095
+ ...Widget.defaultProps,
993
4096
  id: "fullscreen",
994
4097
  placement: "top-left",
995
4098
  viewId: null,
996
4099
  enterLabel: "Enter Fullscreen",
997
4100
  exitLabel: "Exit Fullscreen",
4101
+ enterTooltip: void 0,
4102
+ exitTooltip: void 0,
998
4103
  container: void 0,
999
4104
  onFullscreenChange: () => {
1000
4105
  }
1001
4106
  };
1002
4107
 
1003
4108
  // dist/splitter-widget.js
1004
- var import_jsx_runtime11 = require("preact/jsx-runtime");
4109
+ var import_jsx_runtime12 = require("preact/jsx-runtime");
1005
4110
  var import_preact8 = require("preact");
1006
- var import_hooks3 = require("preact/hooks");
1007
- var import_core10 = require("@deck.gl/core");
4111
+ var import_hooks4 = require("preact/hooks");
1008
4112
 
1009
4113
  // dist/view-layout/view-layout.js
1010
- var import_core9 = require("@deck.gl/core");
1011
4114
  var VIEW_LAYOUT_TYPES = /* @__PURE__ */ new Set(["row", "column", "overlay", "spacer"]);
1012
4115
  var VIEW_LAYOUT_ORIENTATIONS = /* @__PURE__ */ new Set(["horizontal", "vertical"]);
1013
4116
  function isViewLayout(child) {
1014
- 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))));
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))));
1015
4118
  }
1016
4119
  function getViewLayoutType(item) {
1017
4120
  if ("orientation" in item) {
@@ -1061,7 +4164,7 @@ function assertViewLayoutChild(child) {
1061
4164
  assertViewLayout(child);
1062
4165
  return;
1063
4166
  }
1064
- if (child instanceof import_core9.View) {
4167
+ if (child instanceof View) {
1065
4168
  return;
1066
4169
  }
1067
4170
  throw new Error("ViewLayout children must be deck.gl View instances or layout objects.");
@@ -1563,7 +4666,7 @@ function evaluateViews(layout, viewLayouts, splitValues) {
1563
4666
  height: `${view.props.height}%`
1564
4667
  }));
1565
4668
  }
1566
- var SplitterWidget = class extends import_core10.Widget {
4669
+ var SplitterWidget = class extends Widget {
1567
4670
  constructor(props) {
1568
4671
  super(props);
1569
4672
  this.className = "deck-widget-splitter";
@@ -1573,7 +4676,7 @@ var SplitterWidget = class extends import_core10.Widget {
1573
4676
  this.updateViewLayout(this.props.viewLayout);
1574
4677
  }
1575
4678
  setProps(props) {
1576
- if (props.viewLayout && !(0, import_core10._deepEqual)(props.viewLayout, this.props.viewLayout, -1)) {
4679
+ if (props.viewLayout && !deepEqual(props.viewLayout, this.props.viewLayout, -1)) {
1577
4680
  this.updateViewLayout(props.viewLayout);
1578
4681
  this.views = void 0;
1579
4682
  }
@@ -1621,11 +4724,11 @@ var SplitterWidget = class extends import_core10.Widget {
1621
4724
  this.doUpdate();
1622
4725
  }
1623
4726
  onRenderHTML(rootElement) {
1624
- (0, import_preact8.render)((0, import_jsx_runtime11.jsx)(import_jsx_runtime11.Fragment, { children: this.viewLayouts.map((layout) => layout.editable && (0, import_jsx_runtime11.jsx)(Splitter, { ...layout, onChange: (newSplit) => this.onChange(newSplit, layout), onDragStart: () => this.props.onDragStart(), onDragEnd: () => this.props.onDragStart() })) }), rootElement);
4727
+ (0, import_preact8.render)((0, import_jsx_runtime12.jsx)(import_jsx_runtime12.Fragment, { children: this.viewLayouts.map((layout) => layout.editable && (0, import_jsx_runtime12.jsx)(Splitter, { ...layout, onChange: (newSplit) => this.onChange(newSplit, layout), onDragStart: () => this.props.onDragStart(), onDragEnd: () => this.props.onDragStart() })) }), rootElement);
1625
4728
  }
1626
4729
  };
1627
4730
  SplitterWidget.defaultProps = {
1628
- ...import_core10.Widget.defaultProps,
4731
+ ...Widget.defaultProps,
1629
4732
  id: "splitter-widget",
1630
4733
  viewLayout: void 0,
1631
4734
  onChange: () => {
@@ -1636,9 +4739,9 @@ SplitterWidget.defaultProps = {
1636
4739
  }
1637
4740
  };
1638
4741
  function Splitter({ orientation, x, y, width, height, split, minSplit, maxSplit, onChange, onDragStart, onDragEnd }) {
1639
- const [dragging, setDragging] = (0, import_hooks3.useState)(false);
1640
- const containerRef = (0, import_hooks3.useRef)(null);
1641
- (0, import_hooks3.useEffect)(() => {
4742
+ const [dragging, setDragging] = (0, import_hooks4.useState)(false);
4743
+ const containerRef = (0, import_hooks4.useRef)(null);
4744
+ (0, import_hooks4.useEffect)(() => {
1642
4745
  if (!dragging) {
1643
4746
  return void 0;
1644
4747
  }
@@ -1681,33 +4784,32 @@ function Splitter({ orientation, x, y, width, height, split, minSplit, maxSplit,
1681
4784
  width: `${width}%`,
1682
4785
  height: `${height}%`
1683
4786
  };
1684
- return (0, import_jsx_runtime11.jsx)("div", { ref: containerRef, style: containerStyle, children: (0, import_jsx_runtime11.jsx)("div", { className: `deck-widget-splitter-handle deck-widget-splitter-handle--${orientation} ${dragging ? "active" : ""}`, style: splitterStyle, onPointerDown: handleDragStart }) });
4787
+ return (0, import_jsx_runtime12.jsx)("div", { ref: containerRef, style: containerStyle, children: (0, import_jsx_runtime12.jsx)("div", { className: `deck-widget-splitter-handle deck-widget-splitter-handle--${orientation} ${dragging ? "active" : ""}`, style: splitterStyle, onPointerDown: handleDragStart }) });
1685
4788
  }
1686
4789
 
1687
4790
  // dist/info-widget.js
1688
- var import_jsx_runtime14 = require("preact/jsx-runtime");
1689
- var import_core11 = require("@deck.gl/core");
4791
+ var import_jsx_runtime15 = require("preact/jsx-runtime");
1690
4792
  var import_preact9 = require("preact");
1691
4793
 
1692
4794
  // dist/lib/components/popover.js
1693
- var import_jsx_runtime12 = require("preact/jsx-runtime");
1694
- var import_hooks4 = require("preact/hooks");
1695
- var import_dom = require("@floating-ui/dom");
4795
+ var import_jsx_runtime13 = require("preact/jsx-runtime");
4796
+ var import_hooks5 = require("preact/hooks");
4797
+ var import_dom2 = require("@floating-ui/dom");
1696
4798
  var Popover = ({ x, y, placement = "right", offset: pixelOffset = 0, arrow: arrowSize = false, arrowColor = "white", children }) => {
1697
- const anchorRef = (0, import_hooks4.useRef)(null);
1698
- const contentRef = (0, import_hooks4.useRef)(null);
1699
- const arrowRef = (0, import_hooks4.useRef)(null);
1700
- const updaterRef = (0, import_hooks4.useRef)();
4799
+ const anchorRef = (0, import_hooks5.useRef)(null);
4800
+ const contentRef = (0, import_hooks5.useRef)(null);
4801
+ const arrowRef = (0, import_hooks5.useRef)(null);
4802
+ const updaterRef = (0, import_hooks5.useRef)();
1701
4803
  updaterRef.current = () => {
1702
4804
  if (!anchorRef.current || !contentRef.current)
1703
4805
  return;
1704
4806
  const arrowWidth = Array.isArray(arrowSize) ? arrowSize[0] : arrowSize || 0;
1705
4807
  const arrowHeight = Array.isArray(arrowSize) ? arrowSize[1] : arrowSize || 0;
1706
4808
  const padding = pixelOffset + Math.max(arrowHeight, arrowWidth);
1707
- const middleware = placement.includes("-") ? [(0, import_dom.offset)(padding), (0, import_dom.flip)(), (0, import_dom.shift)()] : [(0, import_dom.offset)(padding), (0, import_dom.shift)(), (0, import_dom.flip)()];
4809
+ const middleware = placement.includes("-") ? [(0, import_dom2.offset)(padding), (0, import_dom2.flip)(), (0, import_dom2.shift)()] : [(0, import_dom2.offset)(padding), (0, import_dom2.shift)(), (0, import_dom2.flip)()];
1708
4810
  if (arrowRef.current)
1709
- middleware.push((0, import_dom.arrow)({ element: arrowRef.current }));
1710
- (0, import_dom.computePosition)(anchorRef.current, contentRef.current, {
4811
+ middleware.push((0, import_dom2.arrow)({ element: arrowRef.current }));
4812
+ (0, import_dom2.computePosition)(anchorRef.current, contentRef.current, {
1711
4813
  placement,
1712
4814
  strategy: "fixed",
1713
4815
  middleware
@@ -1726,18 +4828,18 @@ var Popover = ({ x, y, placement = "right", offset: pixelOffset = 0, arrow: arro
1726
4828
  }
1727
4829
  });
1728
4830
  };
1729
- (0, import_hooks4.useMemo)(() => {
4831
+ (0, import_hooks5.useMemo)(() => {
1730
4832
  var _a;
1731
4833
  (_a = updaterRef.current) == null ? void 0 : _a.call(updaterRef);
1732
4834
  }, [x, y, placement, arrowSize, pixelOffset]);
1733
- (0, import_hooks4.useEffect)(() => {
4835
+ (0, import_hooks5.useEffect)(() => {
1734
4836
  const anchor = anchorRef.current;
1735
4837
  const content = contentRef.current;
1736
4838
  if (!anchor || !content) {
1737
4839
  return void 0;
1738
4840
  }
1739
4841
  content.style.visibility = "visible";
1740
- const cleanup = (0, import_dom.autoUpdate)(anchor, content, () => {
4842
+ const cleanup = (0, import_dom2.autoUpdate)(anchor, content, () => {
1741
4843
  var _a;
1742
4844
  return (_a = updaterRef.current) == null ? void 0 : _a.call(updaterRef);
1743
4845
  });
@@ -1745,7 +4847,7 @@ var Popover = ({ x, y, placement = "right", offset: pixelOffset = 0, arrow: arro
1745
4847
  cleanup();
1746
4848
  };
1747
4849
  }, []);
1748
- return (0, import_jsx_runtime12.jsx)("div", { style: { position: "absolute", left: x, top: y }, ref: anchorRef, children: (0, import_jsx_runtime12.jsxs)("div", { className: "deck-widget deck-widget-popover", style: { position: "fixed", visibility: "hidden", pointerEvents: "none" }, ref: contentRef, children: [Boolean(arrowSize) && (0, import_jsx_runtime12.jsx)("div", { className: "deck-widget-popover-arrow", style: { position: "absolute" }, ref: arrowRef }), children] }) });
4850
+ return (0, import_jsx_runtime13.jsx)("div", { style: { position: "absolute", left: x, top: y }, ref: anchorRef, children: (0, import_jsx_runtime13.jsxs)("div", { className: "deck-widget deck-widget-popover", style: { position: "fixed", visibility: "hidden", pointerEvents: "none" }, ref: contentRef, children: [Boolean(arrowSize) && (0, import_jsx_runtime13.jsx)("div", { className: "deck-widget-popover-arrow", style: { position: "absolute" }, ref: arrowRef }), children] }) });
1749
4851
  };
1750
4852
  function createArrow(width, height, color, placement) {
1751
4853
  const result = {
@@ -1785,11 +4887,11 @@ function createArrow(width, height, color, placement) {
1785
4887
  }
1786
4888
 
1787
4889
  // dist/lib/components/user-content.js
1788
- var import_jsx_runtime13 = require("preact/jsx-runtime");
1789
- var import_hooks5 = require("preact/hooks");
4890
+ var import_jsx_runtime14 = require("preact/jsx-runtime");
4891
+ var import_hooks6 = require("preact/hooks");
1790
4892
  var UserContent = ({ text, html, element, ...props }) => {
1791
- const containerRef = (0, import_hooks5.useRef)(null);
1792
- (0, import_hooks5.useEffect)(() => {
4893
+ const containerRef = (0, import_hooks6.useRef)(null);
4894
+ (0, import_hooks6.useEffect)(() => {
1793
4895
  if (containerRef.current && element) {
1794
4896
  containerRef.current.append(element);
1795
4897
  }
@@ -1797,11 +4899,11 @@ var UserContent = ({ text, html, element, ...props }) => {
1797
4899
  element == null ? void 0 : element.remove();
1798
4900
  };
1799
4901
  }, [element]);
1800
- return (0, import_jsx_runtime13.jsx)("div", { ref: containerRef, ...props, dangerouslySetInnerHTML: html ? { __html: html } : void 0, children: text });
4902
+ return (0, import_jsx_runtime14.jsx)("div", { ref: containerRef, ...props, dangerouslySetInnerHTML: html ? { __html: html } : void 0, children: text });
1801
4903
  };
1802
4904
 
1803
4905
  // dist/info-widget.js
1804
- var InfoWidget = class extends import_core11.Widget {
4906
+ var InfoWidget = class extends Widget {
1805
4907
  constructor(props) {
1806
4908
  super(props);
1807
4909
  this.className = "deck-widget-info";
@@ -1867,12 +4969,12 @@ var InfoWidget = class extends import_core11.Widget {
1867
4969
  ...this.tooltip.style
1868
4970
  };
1869
4971
  const [x, y] = this.viewport.project(this.tooltip.position);
1870
- const ui = (0, import_jsx_runtime14.jsx)(Popover, { x, y, placement: this.props.placement, arrow: this.props.arrow, arrowColor: "var(--menu-background, #fff)", offset: this.props.offset, children: (0, import_jsx_runtime14.jsx)(UserContent, { className: `deck-widget-popup-content ${this.tooltip.className} ${this.props.className}`, style, html: this.tooltip.html, text: this.tooltip.text, element: this.tooltip.element }) });
4972
+ const ui = (0, import_jsx_runtime15.jsx)(Popover, { x, y, placement: this.props.placement, arrow: this.props.arrow, arrowColor: "var(--menu-background, #fff)", offset: this.props.offset, children: (0, import_jsx_runtime15.jsx)(UserContent, { className: `deck-widget-popup-content ${this.tooltip.className} ${this.props.className}`, style, html: this.tooltip.html, text: this.tooltip.text, element: this.tooltip.element }) });
1871
4973
  (0, import_preact9.render)(ui, rootElement);
1872
4974
  }
1873
4975
  };
1874
4976
  InfoWidget.defaultProps = {
1875
- ...import_core11.Widget.defaultProps,
4977
+ ...Widget.defaultProps,
1876
4978
  id: "info",
1877
4979
  viewId: null,
1878
4980
  mode: "hover",
@@ -1883,10 +4985,9 @@ InfoWidget.defaultProps = {
1883
4985
  };
1884
4986
 
1885
4987
  // dist/popup-widget.js
1886
- var import_jsx_runtime15 = require("preact/jsx-runtime");
1887
- var import_core12 = require("@deck.gl/core");
4988
+ var import_jsx_runtime16 = require("preact/jsx-runtime");
1888
4989
  var import_preact10 = require("preact");
1889
- var PopupWidget = class extends import_core12.Widget {
4990
+ var PopupWidget = class extends Widget {
1890
4991
  constructor(props) {
1891
4992
  super(props);
1892
4993
  this.className = "deck-widget-popup";
@@ -1930,12 +5031,12 @@ var PopupWidget = class extends import_core12.Widget {
1930
5031
  }
1931
5032
  const { marker, content, style } = this.props;
1932
5033
  const [x, y] = this.viewport.project(this.props.position);
1933
- const ui = (0, import_jsx_runtime15.jsxs)("div", { children: [marker && (0, import_jsx_runtime15.jsx)("div", { className: "deck-widget-popup-marker", style: { left: x, top: y }, children: (0, import_jsx_runtime15.jsx)(UserContent, { ...marker, onClick: () => this._setIsOpen(true) }) }), this.isOpen && (0, import_jsx_runtime15.jsx)(Popover, { x, y, placement: this.props.placement, arrow: this.props.arrow, arrowColor: "var(--menu-background, #fff)", offset: this.props.offset, children: (0, import_jsx_runtime15.jsxs)("div", { className: `deck-widget-popup-content ${this.props.className}`, style, children: [this.props.closeButton && (0, import_jsx_runtime15.jsx)("div", { className: "deck-widget-popup-controls", style: { width: "100%", display: "flex", justifyContent: "end" }, children: (0, import_jsx_runtime15.jsx)(IconButton, { className: "deck-widget-popup-close-button", onClick: () => this._setIsOpen(false) }) }), (0, import_jsx_runtime15.jsx)(UserContent, { ...typeof content === "string" ? { text: content } : content })] }) })] });
5034
+ const ui = (0, import_jsx_runtime16.jsxs)("div", { children: [marker && (0, import_jsx_runtime16.jsx)("div", { className: "deck-widget-popup-marker", style: { left: x, top: y }, children: (0, import_jsx_runtime16.jsx)(UserContent, { ...marker, onClick: () => this._setIsOpen(true) }) }), this.isOpen && (0, import_jsx_runtime16.jsx)(Popover, { x, y, placement: this.props.placement, arrow: this.props.arrow, arrowColor: "var(--menu-background, #fff)", offset: this.props.offset, children: (0, import_jsx_runtime16.jsxs)("div", { className: `deck-widget-popup-content ${this.props.className}`, style, children: [this.props.closeButton && (0, import_jsx_runtime16.jsx)("div", { className: "deck-widget-popup-controls", style: { width: "100%", display: "flex", justifyContent: "end" }, children: (0, import_jsx_runtime16.jsx)(IconButton, { className: "deck-widget-popup-close-button", onClick: () => this._setIsOpen(false) }) }), (0, import_jsx_runtime16.jsx)(UserContent, { ...typeof content === "string" ? { text: content } : content })] }) })] });
1934
5035
  (0, import_preact10.render)(ui, rootElement);
1935
5036
  }
1936
5037
  };
1937
5038
  PopupWidget.defaultProps = {
1938
- ...import_core12.Widget.defaultProps,
5039
+ ...Widget.defaultProps,
1939
5040
  id: "info",
1940
5041
  viewId: null,
1941
5042
  position: [0, 0],
@@ -1952,10 +5053,9 @@ PopupWidget.defaultProps = {
1952
5053
  };
1953
5054
 
1954
5055
  // dist/context-menu-widget.js
1955
- var import_jsx_runtime16 = require("preact/jsx-runtime");
1956
- var import_core13 = require("@deck.gl/core");
5056
+ var import_jsx_runtime17 = require("preact/jsx-runtime");
1957
5057
  var import_preact11 = require("preact");
1958
- var ContextMenuWidget = class extends import_core13.Widget {
5058
+ var ContextMenuWidget = class extends Widget {
1959
5059
  constructor(props) {
1960
5060
  super(props);
1961
5061
  this.className = "deck-widget-context-menu";
@@ -2000,7 +5100,7 @@ var ContextMenuWidget = class extends import_core13.Widget {
2000
5100
  position: "static",
2001
5101
  ...this.props.style
2002
5102
  };
2003
- const ui = (0, import_jsx_runtime16.jsx)(Popover, { x: pickInfo.x, y: pickInfo.y, placement: this.props.placement, arrow: this.props.arrow, arrowColor: "var(--menu-background, #fff)", offset: this.props.offset, children: (0, import_jsx_runtime16.jsx)(SimpleMenu, { menuItems: items, onSelect: (value) => this.props.onMenuItemSelected(value, pickInfo), style, isOpen: true, onClose: () => this.hide() }) });
5103
+ const ui = (0, import_jsx_runtime17.jsx)(Popover, { x: pickInfo.x, y: pickInfo.y, placement: this.props.placement, arrow: this.props.arrow, arrowColor: "var(--menu-background, #fff)", offset: this.props.offset, children: (0, import_jsx_runtime17.jsx)(SimpleMenu, { menuItems: items, onSelect: (value) => this.props.onMenuItemSelected(value, pickInfo), style, isOpen: true, onClose: () => this.hide() }) });
2004
5104
  (0, import_preact11.render)(ui, rootElement);
2005
5105
  }
2006
5106
  hide() {
@@ -2009,7 +5109,7 @@ var ContextMenuWidget = class extends import_core13.Widget {
2009
5109
  }
2010
5110
  };
2011
5111
  ContextMenuWidget.defaultProps = {
2012
- ...import_core13.Widget.defaultProps,
5112
+ ...Widget.defaultProps,
2013
5113
  id: "context",
2014
5114
  viewId: null,
2015
5115
  menuItems: [],
@@ -2022,15 +5122,14 @@ ContextMenuWidget.defaultProps = {
2022
5122
  };
2023
5123
 
2024
5124
  // dist/scrollbar-widget.js
2025
- var import_jsx_runtime18 = require("preact/jsx-runtime");
2026
- var import_core14 = require("@deck.gl/core");
5125
+ var import_jsx_runtime19 = require("preact/jsx-runtime");
2027
5126
  var import_preact12 = require("preact");
2028
5127
 
2029
5128
  // dist/lib/components/range-input.js
2030
- var import_jsx_runtime17 = require("preact/jsx-runtime");
2031
- var import_hooks6 = require("preact/hooks");
5129
+ var import_jsx_runtime18 = require("preact/jsx-runtime");
5130
+ var import_hooks7 = require("preact/hooks");
2032
5131
  var wheelListenerOptions = { passive: false };
2033
- var clamp2 = (value, min, max) => {
5132
+ var clamp6 = (value, min, max) => {
2034
5133
  if (value < min) {
2035
5134
  return min;
2036
5135
  }
@@ -2064,16 +5163,16 @@ var getEffectivePage = (pageSize, rangeSize) => {
2064
5163
  function RangeInput(props) {
2065
5164
  const { className = "", min, max, step, value, orientation, pageSize, stepButtons = false, startButtonAriaLabel, endButtonAriaLabel, eventTarget, decorations = [], onChange } = props;
2066
5165
  const vertical = orientation !== "horizontal";
2067
- const rootRef = (0, import_hooks6.useRef)(null);
2068
- const trackRef = (0, import_hooks6.useRef)(null);
2069
- const thumbRef = (0, import_hooks6.useRef)(null);
2070
- const dragStateRef = (0, import_hooks6.useRef)(null);
2071
- const [trackLength, setTrackLength] = (0, import_hooks6.useState)(0);
5166
+ const rootRef = (0, import_hooks7.useRef)(null);
5167
+ const trackRef = (0, import_hooks7.useRef)(null);
5168
+ const thumbRef = (0, import_hooks7.useRef)(null);
5169
+ const dragStateRef = (0, import_hooks7.useRef)(null);
5170
+ const [trackLength, setTrackLength] = (0, import_hooks7.useState)(0);
2072
5171
  const range = max - min;
2073
5172
  const rangeSize = Math.max(0, value[1] - value[0]);
2074
5173
  const maxStart = Math.max(0, range - rangeSize);
2075
- const clampedStart = clamp2(value[0], min, min + maxStart);
2076
- const { thumbLength, thumbOffset } = (0, import_hooks6.useMemo)(() => {
5174
+ const clampedStart = clamp6(value[0], min, min + maxStart);
5175
+ const { thumbLength, thumbOffset } = (0, import_hooks7.useMemo)(() => {
2077
5176
  if (trackLength <= 0 || range <= 0) {
2078
5177
  return { thumbLength: 0, thumbOffset: 0 };
2079
5178
  }
@@ -2082,28 +5181,28 @@ function RangeInput(props) {
2082
5181
  }
2083
5182
  const nextThumbLength = rangeSize / range;
2084
5183
  const travel = Math.max(0, 1 - nextThumbLength);
2085
- const ratio = maxStart <= 0 ? 0 : clamp2((clampedStart - min) / maxStart, 0, 1);
5184
+ const ratio = maxStart <= 0 ? 0 : clamp6((clampedStart - min) / maxStart, 0, 1);
2086
5185
  return {
2087
5186
  thumbLength: Math.max(0, Math.min(nextThumbLength, 1)),
2088
5187
  thumbOffset: travel * ratio
2089
5188
  };
2090
5189
  }, [trackLength, range, rangeSize, maxStart, clampedStart, min]);
2091
- const emitRange = (0, import_hooks6.useCallback)((nextStart) => {
5190
+ const emitRange = (0, import_hooks7.useCallback)((nextStart) => {
2092
5191
  if (!onChange) {
2093
5192
  return;
2094
5193
  }
2095
- const clamped = clamp2(nextStart, min, min + maxStart);
5194
+ const clamped = clamp6(nextStart, min, min + maxStart);
2096
5195
  onChange([clamped, clamped + rangeSize]);
2097
5196
  }, [onChange, min, maxStart, rangeSize]);
2098
- const handleStepNegative = (0, import_hooks6.useCallback)((event) => {
5197
+ const handleStepNegative = (0, import_hooks7.useCallback)((event) => {
2099
5198
  event.stopPropagation();
2100
5199
  emitRange(clampedStart - getEffectiveStep(step, range));
2101
5200
  }, [emitRange, clampedStart, step, range]);
2102
- const handleStepPositive = (0, import_hooks6.useCallback)((event) => {
5201
+ const handleStepPositive = (0, import_hooks7.useCallback)((event) => {
2103
5202
  event.stopPropagation();
2104
5203
  emitRange(clampedStart + getEffectiveStep(step, range));
2105
5204
  }, [emitRange, clampedStart, step, range]);
2106
- const handleTrackClick = (0, import_hooks6.useCallback)((event) => {
5205
+ const handleTrackClick = (0, import_hooks7.useCallback)((event) => {
2107
5206
  if (event.button !== 0) {
2108
5207
  return;
2109
5208
  }
@@ -2121,7 +5220,7 @@ function RangeInput(props) {
2121
5220
  const coordinate = vertical ? event.clientY - trackStart : event.clientX - trackStart;
2122
5221
  const span = Math.max(1, 1 - thumbLength) * trackLength;
2123
5222
  const thumbCenter = thumbLength / 2 * trackLength;
2124
- const ratio = span <= 0 ? 0 : clamp2((coordinate - thumbCenter) / span, 0, 1);
5223
+ const ratio = span <= 0 ? 0 : clamp6((coordinate - thumbCenter) / span, 0, 1);
2125
5224
  emitRange(min + ratio * maxStart);
2126
5225
  }, [vertical, trackLength, thumbLength, emitRange, min, maxStart]);
2127
5226
  const handleThumbPointerDown = (event) => {
@@ -2144,7 +5243,7 @@ function RangeInput(props) {
2144
5243
  event.preventDefault();
2145
5244
  event.stopPropagation();
2146
5245
  };
2147
- const handleThumbPointerMove = (0, import_hooks6.useCallback)((event) => {
5246
+ const handleThumbPointerMove = (0, import_hooks7.useCallback)((event) => {
2148
5247
  const state = dragStateRef.current;
2149
5248
  if (!state || state.pointerId !== event.pointerId) {
2150
5249
  return;
@@ -2153,11 +5252,11 @@ function RangeInput(props) {
2153
5252
  const coordinate = vertical ? event.clientY : event.clientX;
2154
5253
  const delta = coordinate - state.startCoord;
2155
5254
  const ratio = state.startRatio + delta / trackLength2;
2156
- const nextStart = clamp2(ratio * (state.max - state.min), 0, state.maxStart) + state.min;
5255
+ const nextStart = clamp6(ratio * (state.max - state.min), 0, state.maxStart) + state.min;
2157
5256
  emitRange(nextStart);
2158
5257
  event.preventDefault();
2159
5258
  }, [emitRange, vertical]);
2160
- const handleThumbPointerUp = (0, import_hooks6.useCallback)((event) => {
5259
+ const handleThumbPointerUp = (0, import_hooks7.useCallback)((event) => {
2161
5260
  var _a;
2162
5261
  const state = dragStateRef.current;
2163
5262
  if (state && state.pointerId === event.pointerId) {
@@ -2166,7 +5265,7 @@ function RangeInput(props) {
2166
5265
  event.preventDefault();
2167
5266
  }
2168
5267
  }, []);
2169
- const handleKeyDown = (0, import_hooks6.useCallback)((event) => {
5268
+ const handleKeyDown = (0, import_hooks7.useCallback)((event) => {
2170
5269
  switch (event.key) {
2171
5270
  case "ArrowUp":
2172
5271
  case "ArrowLeft":
@@ -2202,7 +5301,7 @@ function RangeInput(props) {
2202
5301
  break;
2203
5302
  }
2204
5303
  }, [vertical, emitRange, clampedStart, step, range, pageSize, rangeSize, min, maxStart]);
2205
- const handleWheel = (0, import_hooks6.useCallback)((event) => {
5304
+ const handleWheel = (0, import_hooks7.useCallback)((event) => {
2206
5305
  event.preventDefault();
2207
5306
  event.stopPropagation();
2208
5307
  if (maxStart === 0) {
@@ -2222,10 +5321,10 @@ function RangeInput(props) {
2222
5321
  }
2223
5322
  emitRange(clampedStart + delta);
2224
5323
  }, [emitRange, clampedStart, maxStart, vertical, step, range, pageSize, rangeSize]);
2225
- (0, import_hooks6.useLayoutEffect)(() => {
5324
+ (0, import_hooks7.useLayoutEffect)(() => {
2226
5325
  setTrackLength(getTrackDimension(trackRef.current, vertical)[1]);
2227
5326
  }, [vertical]);
2228
- (0, import_hooks6.useLayoutEffect)(() => {
5327
+ (0, import_hooks7.useLayoutEffect)(() => {
2229
5328
  const track = trackRef.current;
2230
5329
  if (!track) {
2231
5330
  return void 0;
@@ -2245,7 +5344,7 @@ function RangeInput(props) {
2245
5344
  }
2246
5345
  return void 0;
2247
5346
  }, [vertical]);
2248
- (0, import_hooks6.useEffect)(() => {
5347
+ (0, import_hooks7.useEffect)(() => {
2249
5348
  const eventRoot = eventTarget ?? rootRef.current;
2250
5349
  if (!eventRoot)
2251
5350
  return void 0;
@@ -2256,7 +5355,7 @@ function RangeInput(props) {
2256
5355
  eventRoot.removeEventListener("wheel", handleWheel, wheelListenerOptions);
2257
5356
  };
2258
5357
  }, [eventTarget, handleKeyDown, handleWheel]);
2259
- const decorationElements = (0, import_hooks6.useMemo)(() => {
5358
+ const decorationElements = (0, import_hooks7.useMemo)(() => {
2260
5359
  if (!decorations.length || range <= 0) {
2261
5360
  return [];
2262
5361
  }
@@ -2277,14 +5376,14 @@ function RangeInput(props) {
2277
5376
  left: `${offsetPct}%`,
2278
5377
  width: `${sizePct}%`
2279
5378
  };
2280
- return (0, import_jsx_runtime17.jsx)("div", { className: "deck-widget-range__decoration", style, children: decoration.element }, `decoration-${index}`);
5379
+ return (0, import_jsx_runtime18.jsx)("div", { className: "deck-widget-range__decoration", style, children: decoration.element }, `decoration-${index}`);
2281
5380
  });
2282
5381
  }, [decorations, range, min, vertical]);
2283
- return (0, import_jsx_runtime17.jsxs)("div", { ref: rootRef, tabIndex: 0, role: "scrollbar", "aria-valuemin": min, "aria-valuemax": min + maxStart, "aria-valuenow": clampedStart, "aria-orientation": orientation, className: `${className} deck-widget-range deck-widget-range--${orientation} ${maxStart === 0 ? "deck-widget-range--disabled" : ""}`, children: [stepButtons && (0, import_jsx_runtime17.jsx)("button", { type: "button", className: "deck-widget-range__button deck-widget-range__button--start", "aria-label": startButtonAriaLabel, disabled: clampedStart <= min, onClick: handleStepNegative, children: (0, import_jsx_runtime17.jsx)("span", { className: "deck-widget-icon" }) }), (0, import_jsx_runtime17.jsxs)("div", { className: "deck-widget-range__track", ref: trackRef, onClick: handleTrackClick, children: [(0, import_jsx_runtime17.jsx)("div", { className: "deck-widget-range__decorations", children: decorationElements }), (0, import_jsx_runtime17.jsx)("div", { className: "deck-widget-range__thumb", "data-scrollbar-thumb": "true", ref: thumbRef, style: vertical ? { height: `${thumbLength * 100}%`, top: `${thumbOffset * 100}%` } : { width: `${thumbLength * 100}%`, left: `${thumbOffset * 100}%` }, onPointerDown: handleThumbPointerDown, onPointerMove: handleThumbPointerMove, onPointerUp: handleThumbPointerUp, onPointerCancel: handleThumbPointerUp })] }), stepButtons && (0, import_jsx_runtime17.jsx)("button", { type: "button", className: "deck-widget-range__button deck-widget-range__button--end", "aria-label": endButtonAriaLabel, disabled: clampedStart >= min + maxStart, onClick: handleStepPositive, children: (0, import_jsx_runtime17.jsx)("span", { className: "deck-widget-icon" }) })] });
5382
+ return (0, import_jsx_runtime18.jsxs)("div", { ref: rootRef, tabIndex: 0, role: "scrollbar", "aria-valuemin": min, "aria-valuemax": min + maxStart, "aria-valuenow": clampedStart, "aria-orientation": orientation, className: `${className} deck-widget-range deck-widget-range--${orientation} ${maxStart === 0 ? "deck-widget-range--disabled" : ""}`, children: [stepButtons && (0, import_jsx_runtime18.jsx)("button", { type: "button", className: "deck-widget-range__button deck-widget-range__button--start", "aria-label": startButtonAriaLabel, disabled: clampedStart <= min, onClick: handleStepNegative, children: (0, import_jsx_runtime18.jsx)("span", { className: "deck-widget-icon" }) }), (0, import_jsx_runtime18.jsxs)("div", { className: "deck-widget-range__track", ref: trackRef, onClick: handleTrackClick, children: [(0, import_jsx_runtime18.jsx)("div", { className: "deck-widget-range__decorations", children: decorationElements }), (0, import_jsx_runtime18.jsx)("div", { className: "deck-widget-range__thumb", "data-scrollbar-thumb": "true", ref: thumbRef, style: vertical ? { height: `${thumbLength * 100}%`, top: `${thumbOffset * 100}%` } : { width: `${thumbLength * 100}%`, left: `${thumbOffset * 100}%` }, onPointerDown: handleThumbPointerDown, onPointerMove: handleThumbPointerMove, onPointerUp: handleThumbPointerUp, onPointerCancel: handleThumbPointerUp })] }), stepButtons && (0, import_jsx_runtime18.jsx)("button", { type: "button", className: "deck-widget-range__button deck-widget-range__button--end", "aria-label": endButtonAriaLabel, disabled: clampedStart >= min + maxStart, onClick: handleStepPositive, children: (0, import_jsx_runtime18.jsx)("span", { className: "deck-widget-icon" }) })] });
2284
5383
  }
2285
5384
 
2286
5385
  // dist/scrollbar-widget.js
2287
- var clamp3 = (value, min, max) => {
5386
+ var clamp7 = (value, min, max) => {
2288
5387
  if (value < min) {
2289
5388
  return min;
2290
5389
  }
@@ -2293,10 +5392,10 @@ var clamp3 = (value, min, max) => {
2293
5392
  }
2294
5393
  return value;
2295
5394
  };
2296
- var ScrollbarWidget = class extends import_core14.Widget {
5395
+ var ScrollbarWidget = class _ScrollbarWidget extends Widget {
2297
5396
  constructor(props) {
2298
5397
  const resolved = {
2299
- ...ScrollbarWidget.defaultProps,
5398
+ ..._ScrollbarWidget.defaultProps,
2300
5399
  ...props
2301
5400
  };
2302
5401
  super(resolved);
@@ -2328,7 +5427,7 @@ var ScrollbarWidget = class extends import_core14.Widget {
2328
5427
  const isVertical = this.isVertical();
2329
5428
  const startLabel = this.props.startButtonAriaLabel ?? (isVertical ? "Scroll up" : "Scroll left");
2330
5429
  const endLabel = this.props.endButtonAriaLabel ?? (isVertical ? "Scroll down" : "Scroll right");
2331
- const ui = (0, import_jsx_runtime18.jsx)(RangeInput, { min: 0, max: Math.max(0, this.contentSize), step: this.getEffectiveStep(), pageSize: this.getEffectivePage(), value: [clampedOffset, clampedOffset + this.viewportSize], orientation: this.props.orientation, stepButtons: true, startButtonAriaLabel: startLabel, endButtonAriaLabel: endLabel, eventTarget: wheelTarget, decorations, onChange: this.handleRangeChange });
5430
+ const ui = (0, import_jsx_runtime19.jsx)(RangeInput, { min: 0, max: Math.max(0, this.contentSize), step: this.getEffectiveStep(), pageSize: this.getEffectivePage(), value: [clampedOffset, clampedOffset + this.viewportSize], orientation: this.props.orientation, stepButtons: true, startButtonAriaLabel: startLabel, endButtonAriaLabel: endLabel, eventTarget: wheelTarget, decorations, onChange: this.handleRangeChange });
2332
5431
  (0, import_preact12.render)(ui, element);
2333
5432
  }
2334
5433
  onRemove() {
@@ -2341,6 +5440,10 @@ var ScrollbarWidget = class extends import_core14.Widget {
2341
5440
  var _a, _b, _c;
2342
5441
  return this.props.contentBounds ?? ((_c = (_b = (_a = this.deck) == null ? void 0 : _a.getView(viewId)) == null ? void 0 : _b.controller) == null ? void 0 : _c.maxBounds) ?? null;
2343
5442
  }
5443
+ getContentBoundsPadding(viewId) {
5444
+ var _a, _b, _c;
5445
+ return this.props.contentBoundsPadding ?? ((_c = (_b = (_a = this.deck) == null ? void 0 : _a.getView(viewId)) == null ? void 0 : _b.controller) == null ? void 0 : _c.maxBoundsPadding) ?? null;
5446
+ }
2344
5447
  updateViewport(viewport) {
2345
5448
  if (!viewport) {
2346
5449
  this.contentSize = 0;
@@ -2351,9 +5454,12 @@ var ScrollbarWidget = class extends import_core14.Widget {
2351
5454
  const contentBounds = this.getContentBounds(viewport.id);
2352
5455
  const isVertical = this.isVertical();
2353
5456
  const projectedBounds = contentBounds ? projectBounds(contentBounds, viewport, isVertical) : [0, 0];
5457
+ const contentRect = getMaxBoundsRect(viewport.width, viewport.height, this.getContentBoundsPadding(viewport.id));
5458
+ const contentStart = isVertical ? contentRect.y : contentRect.x;
5459
+ const viewportSize = isVertical ? contentRect.height : contentRect.width;
2354
5460
  this.contentSize = projectedBounds[1] - projectedBounds[0];
2355
- this.scrollOffset = -projectedBounds[0];
2356
- this.viewportSize = isVertical ? viewport.height : viewport.width;
5461
+ this.scrollOffset = contentStart - projectedBounds[0];
5462
+ this.viewportSize = Math.max(0, viewportSize);
2357
5463
  }
2358
5464
  getDecorations(viewport) {
2359
5465
  const { decorations = [] } = this.props;
@@ -2378,7 +5484,7 @@ var ScrollbarWidget = class extends import_core14.Widget {
2378
5484
  } : void 0;
2379
5485
  return {
2380
5486
  position: [start - contentStart, end - contentStart],
2381
- element: (0, import_jsx_runtime18.jsx)("div", { style: {
5487
+ element: (0, import_jsx_runtime19.jsx)("div", { style: {
2382
5488
  pointerEvents: onClick ? "all" : "none",
2383
5489
  width: "100%",
2384
5490
  height: "100%",
@@ -2400,7 +5506,7 @@ var ScrollbarWidget = class extends import_core14.Widget {
2400
5506
  }
2401
5507
  getClampedOffset() {
2402
5508
  const maxScroll = this.getMaxScroll();
2403
- return clamp3(this.scrollOffset, 0, maxScroll);
5509
+ return clamp7(this.scrollOffset, 0, maxScroll);
2404
5510
  }
2405
5511
  isVertical() {
2406
5512
  return this.props.orientation !== "horizontal";
@@ -2419,7 +5525,7 @@ var ScrollbarWidget = class extends import_core14.Widget {
2419
5525
  }
2420
5526
  emitScroll(next) {
2421
5527
  const maxScroll = this.getMaxScroll();
2422
- const target = clamp3(Math.round(next), 0, maxScroll);
5528
+ const target = clamp7(Math.round(next), 0, maxScroll);
2423
5529
  const viewport = this.viewport;
2424
5530
  if (viewport && target !== this.getClampedOffset()) {
2425
5531
  const pixel = viewport.project(viewport.position);
@@ -2441,8 +5547,9 @@ var ScrollbarWidget = class extends import_core14.Widget {
2441
5547
  }
2442
5548
  };
2443
5549
  ScrollbarWidget.defaultProps = {
2444
- ...import_core14.Widget.defaultProps,
5550
+ ...Widget.defaultProps,
2445
5551
  contentBounds: null,
5552
+ contentBoundsPadding: null,
2446
5553
  placement: "top-right",
2447
5554
  viewId: null,
2448
5555
  orientation: "vertical",
@@ -2463,10 +5570,9 @@ function projectBounds(bounds, viewport, isVertical) {
2463
5570
  }
2464
5571
 
2465
5572
  // dist/icon-widget.js
2466
- var import_jsx_runtime19 = require("preact/jsx-runtime");
5573
+ var import_jsx_runtime20 = require("preact/jsx-runtime");
2467
5574
  var import_preact13 = require("preact");
2468
- var import_core15 = require("@deck.gl/core");
2469
- var IconWidget = class extends import_core15.Widget {
5575
+ var IconWidget = class extends Widget {
2470
5576
  constructor(props) {
2471
5577
  super(props);
2472
5578
  this.className = "";
@@ -2479,26 +5585,26 @@ var IconWidget = class extends import_core15.Widget {
2479
5585
  super.setProps(props);
2480
5586
  }
2481
5587
  onRenderHTML(rootElement) {
2482
- const { className, style, icon, color, label, onClick } = this.props;
2483
- (0, import_preact13.render)((0, import_jsx_runtime19.jsx)(IconButton, { className, style, color, icon, label, onClick }), rootElement);
5588
+ const { className, style, icon, color, label, tooltip, onClick } = this.props;
5589
+ (0, import_preact13.render)((0, import_jsx_runtime20.jsx)(IconButton, { className, style, color, icon, label, tooltip, onClick }), rootElement);
2484
5590
  }
2485
5591
  };
2486
5592
  IconWidget.defaultProps = {
2487
- ...import_core15.Widget.defaultProps,
5593
+ ...Widget.defaultProps,
2488
5594
  id: "icon",
2489
5595
  placement: "top-left",
2490
5596
  viewId: null,
2491
5597
  icon: "",
2492
5598
  label: "",
5599
+ tooltip: void 0,
2493
5600
  color: "",
2494
5601
  onClick: void 0
2495
5602
  };
2496
5603
 
2497
5604
  // dist/toggle-widget.js
2498
- var import_jsx_runtime20 = require("preact/jsx-runtime");
5605
+ var import_jsx_runtime21 = require("preact/jsx-runtime");
2499
5606
  var import_preact14 = require("preact");
2500
- var import_core16 = require("@deck.gl/core");
2501
- var ToggleWidget = class extends import_core16.Widget {
5607
+ var ToggleWidget = class extends Widget {
2502
5608
  constructor(props) {
2503
5609
  super(props);
2504
5610
  this.className = "deck-widget-toggle";
@@ -2518,14 +5624,14 @@ var ToggleWidget = class extends import_core16.Widget {
2518
5624
  super.setProps(props);
2519
5625
  }
2520
5626
  onRenderHTML(rootElement) {
2521
- const { className, style, icon, label, color, onIcon = icon, onLabel = label, onColor = color } = this.props;
5627
+ const { className, style, icon, label, tooltip, color, onIcon = icon, onLabel = label, onTooltip, onColor = color } = this.props;
2522
5628
  const on = this.checked;
2523
5629
  rootElement.dataset.checked = String(on);
2524
- (0, import_preact14.render)((0, import_jsx_runtime20.jsx)(IconButton, { className, style, icon: on ? onIcon : icon, label: on ? onLabel : label, color: on ? onColor : color, onClick: this._toggle }), rootElement);
5630
+ (0, import_preact14.render)((0, import_jsx_runtime21.jsx)(IconButton, { className, style, icon: on ? onIcon : icon, label: on ? onLabel : label, tooltip: on ? onTooltip : tooltip, color: on ? onColor : color, onClick: this._toggle }), rootElement);
2525
5631
  }
2526
5632
  };
2527
5633
  ToggleWidget.defaultProps = {
2528
- ...import_core16.Widget.defaultProps,
5634
+ ...Widget.defaultProps,
2529
5635
  id: "icon",
2530
5636
  placement: "top-left",
2531
5637
  viewId: null,
@@ -2533,17 +5639,18 @@ ToggleWidget.defaultProps = {
2533
5639
  icon: "",
2534
5640
  onIcon: void 0,
2535
5641
  label: "",
5642
+ tooltip: void 0,
2536
5643
  onLabel: void 0,
5644
+ onTooltip: void 0,
2537
5645
  color: "",
2538
5646
  onColor: void 0,
2539
5647
  onChange: void 0
2540
5648
  };
2541
5649
 
2542
5650
  // dist/selector-widget.js
2543
- var import_jsx_runtime21 = require("preact/jsx-runtime");
5651
+ var import_jsx_runtime22 = require("preact/jsx-runtime");
2544
5652
  var import_preact15 = require("preact");
2545
- var import_core17 = require("@deck.gl/core");
2546
- var SelectorWidget = class extends import_core17.Widget {
5653
+ var SelectorWidget = class extends Widget {
2547
5654
  constructor(props) {
2548
5655
  super(props);
2549
5656
  this.className = "deck-widget-selector";
@@ -2576,25 +5683,25 @@ var SelectorWidget = class extends import_core17.Widget {
2576
5683
  }
2577
5684
  onRenderHTML(rootElement) {
2578
5685
  const selectedOption = this.props.options.find((opt) => opt.value === this.value) ?? this.props.options[0];
2579
- (0, import_preact15.render)((0, import_jsx_runtime21.jsxs)("div", { children: [(0, import_jsx_runtime21.jsx)(IconButton, { icon: selectedOption.icon, label: selectedOption.label, onClick: this._toggleMenu }), this.isOpen && (0, import_jsx_runtime21.jsx)(Popover, { ...this.isOpen, children: (0, import_jsx_runtime21.jsx)(SimpleMenu, { isOpen: true, style: { pointerEvents: "auto", position: "static" }, menuItems: this.props.options, onSelect: this._handleSelectMode, onClose: this._toggleMenu }) })] }), rootElement);
5686
+ (0, import_preact15.render)((0, import_jsx_runtime22.jsxs)("div", { children: [(0, import_jsx_runtime22.jsx)(IconButton, { icon: selectedOption.icon, label: selectedOption.label, tooltip: this.props.tooltip, onClick: this._toggleMenu }), this.isOpen && (0, import_jsx_runtime22.jsx)(Popover, { ...this.isOpen, children: (0, import_jsx_runtime22.jsx)(SimpleMenu, { isOpen: true, style: { pointerEvents: "auto", position: "static" }, menuItems: this.props.options, onSelect: this._handleSelectMode, onClose: this._toggleMenu }) })] }), rootElement);
2580
5687
  }
2581
5688
  };
2582
5689
  SelectorWidget.defaultProps = {
2583
- ...import_core17.Widget.defaultProps,
5690
+ ...Widget.defaultProps,
2584
5691
  id: "view-selector",
2585
5692
  placement: "top-left",
2586
5693
  viewId: null,
2587
5694
  initialValue: "",
2588
5695
  options: [],
5696
+ tooltip: void 0,
2589
5697
  onChange: () => {
2590
5698
  }
2591
5699
  };
2592
5700
 
2593
5701
  // dist/timeline-widget.js
2594
- var import_jsx_runtime22 = require("preact/jsx-runtime");
2595
- var import_core18 = require("@deck.gl/core");
5702
+ var import_jsx_runtime23 = require("preact/jsx-runtime");
2596
5703
  var import_preact16 = require("preact");
2597
- var TimelineWidget = class extends import_core18.Widget {
5704
+ var TimelineWidget = class extends Widget {
2598
5705
  /**
2599
5706
  * Returns the current time value.
2600
5707
  * In controlled mode, returns the time prop.
@@ -2708,14 +5815,14 @@ var TimelineWidget = class extends import_core18.Widget {
2708
5815
  this.stop();
2709
5816
  }
2710
5817
  onRenderHTML(rootElement) {
2711
- const { timeRange, step, formatLabel } = this.props;
5818
+ const { timeRange, step, formatLabel, playTooltip, pauseTooltip } = this.props;
2712
5819
  const isPlaying = this.getPlaying();
2713
5820
  const currentTime = this.getTime();
2714
5821
  rootElement.dataset.placement = this.props.placement;
2715
- (0, import_preact16.render)((0, import_jsx_runtime22.jsxs)("div", { className: "deck-widget-button-group", children: [isPlaying ? (0, import_jsx_runtime22.jsx)(IconButton, { label: "Pause", className: "deck-widget-timeline-pause", onClick: this.handlePlayPause }) : (0, import_jsx_runtime22.jsx)(IconButton, { label: "Play", className: "deck-widget-timeline-play", onClick: this.handlePlayPause }), (0, import_jsx_runtime22.jsx)(RangeInput, { min: timeRange[0], max: timeRange[1], orientation: "horizontal", step, value: [currentTime, currentTime], onChange: this.handleTimeChange, decorations: [
5822
+ (0, import_preact16.render)((0, import_jsx_runtime23.jsxs)("div", { className: "deck-widget-button-group", children: [isPlaying ? (0, import_jsx_runtime23.jsx)(IconButton, { label: "Pause", tooltip: pauseTooltip, className: "deck-widget-timeline-pause", onClick: this.handlePlayPause }) : (0, import_jsx_runtime23.jsx)(IconButton, { label: "Play", tooltip: playTooltip, className: "deck-widget-timeline-play", onClick: this.handlePlayPause }), (0, import_jsx_runtime23.jsx)(RangeInput, { min: timeRange[0], max: timeRange[1], orientation: "horizontal", step, value: [currentTime, currentTime], onChange: this.handleTimeChange, decorations: [
2716
5823
  {
2717
5824
  position: [currentTime, currentTime + step],
2718
- element: (0, import_jsx_runtime22.jsx)("div", { className: "deck-widget-timeline-label deck-widget-timeline-label--current", children: formatLabel(currentTime) })
5825
+ element: (0, import_jsx_runtime23.jsx)("div", { className: "deck-widget-timeline-label deck-widget-timeline-label--current", children: formatLabel(currentTime) })
2719
5826
  }
2720
5827
  ] })] }), rootElement);
2721
5828
  }
@@ -2750,7 +5857,7 @@ var TimelineWidget = class extends import_core18.Widget {
2750
5857
  }
2751
5858
  };
2752
5859
  TimelineWidget.defaultProps = {
2753
- ...import_core18.Widget.defaultProps,
5860
+ ...Widget.defaultProps,
2754
5861
  id: "timeline",
2755
5862
  placement: "bottom-left",
2756
5863
  viewId: null,
@@ -2767,14 +5874,15 @@ TimelineWidget.defaultProps = {
2767
5874
  playing: void 0,
2768
5875
  onPlayingChange: () => {
2769
5876
  },
2770
- formatLabel: String
5877
+ formatLabel: String,
5878
+ playTooltip: void 0,
5879
+ pauseTooltip: void 0
2771
5880
  };
2772
5881
 
2773
5882
  // dist/screenshot-widget.js
2774
- var import_jsx_runtime23 = require("preact/jsx-runtime");
5883
+ var import_jsx_runtime24 = require("preact/jsx-runtime");
2775
5884
  var import_preact17 = require("preact");
2776
- var import_core19 = require("@deck.gl/core");
2777
- var ScreenshotWidget = class extends import_core19.Widget {
5885
+ var ScreenshotWidget = class extends Widget {
2778
5886
  constructor(props = {}) {
2779
5887
  super(props);
2780
5888
  this.className = "deck-widget-screenshot";
@@ -2787,7 +5895,7 @@ var ScreenshotWidget = class extends import_core19.Widget {
2787
5895
  super.setProps(props);
2788
5896
  }
2789
5897
  onRenderHTML(rootElement) {
2790
- (0, import_preact17.render)((0, import_jsx_runtime23.jsx)(IconButton, { className: "deck-widget-camera", label: this.props.label, onClick: this.handleClick.bind(this) }), rootElement);
5898
+ (0, import_preact17.render)((0, import_jsx_runtime24.jsx)(IconButton, { className: "deck-widget-camera", label: this.props.label, tooltip: this.props.tooltip, onClick: this.handleClick.bind(this) }), rootElement);
2791
5899
  }
2792
5900
  handleClick() {
2793
5901
  if (this.props.onCapture) {
@@ -2814,26 +5922,26 @@ var ScreenshotWidget = class extends import_core19.Widget {
2814
5922
  }
2815
5923
  };
2816
5924
  ScreenshotWidget.defaultProps = {
2817
- ...import_core19.Widget.defaultProps,
5925
+ ...Widget.defaultProps,
2818
5926
  id: "screenshot",
2819
5927
  placement: "top-left",
2820
5928
  viewId: null,
2821
5929
  label: "Screenshot",
5930
+ tooltip: void 0,
2822
5931
  filename: "screenshot.png",
2823
5932
  imageFormat: "image/png",
2824
5933
  onCapture: void 0
2825
5934
  };
2826
5935
 
2827
5936
  // dist/theme-widget.js
2828
- var import_jsx_runtime24 = require("preact/jsx-runtime");
2829
- var import_core20 = require("@deck.gl/core");
2830
- var import_core21 = require("@deck.gl/core");
5937
+ var import_jsx_runtime25 = require("preact/jsx-runtime");
2831
5938
  var import_preact18 = require("preact");
2832
5939
 
2833
5940
  // dist/themes.js
2834
5941
  var LightTheme = {
2835
5942
  "--widget-margin": "12px",
2836
5943
  "--button-size": "28px",
5944
+ "--icon-size": "75%",
2837
5945
  "--button-corner-radius": "8px",
2838
5946
  "--button-background": "#fff",
2839
5947
  "--button-stroke": "rgba(255, 255, 255, 0.3)",
@@ -2862,6 +5970,7 @@ var LightTheme = {
2862
5970
  var DarkTheme = {
2863
5971
  "--widget-margin": "12px",
2864
5972
  "--button-size": "28px",
5973
+ "--icon-size": "75%",
2865
5974
  "--button-corner-radius": "8px",
2866
5975
  "--button-background": "rgba(18, 18, 20, 1)",
2867
5976
  "--button-stroke": "rgba(18, 18, 20, 0.30)",
@@ -2890,6 +5999,7 @@ var DarkTheme = {
2890
5999
  var LightGlassTheme = {
2891
6000
  "--widget-margin": "12px",
2892
6001
  "--button-size": "28px",
6002
+ "--icon-size": "75%",
2893
6003
  "--button-corner-radius": "8px",
2894
6004
  "--button-background": "rgba(255, 255, 255, 0.6)",
2895
6005
  "--button-stroke": "rgba(255, 255, 255, 0.3)",
@@ -2918,6 +6028,7 @@ var LightGlassTheme = {
2918
6028
  var DarkGlassTheme = {
2919
6029
  "--widget-margin": "12px",
2920
6030
  "--button-size": "28px",
6031
+ "--icon-size": "75%",
2921
6032
  "--button-corner-radius": "8px",
2922
6033
  "--button-background": "rgba(18, 18, 20, 0.75)",
2923
6034
  "--button-stroke": "rgba(18, 18, 20, 0.30)",
@@ -2945,7 +6056,7 @@ var DarkGlassTheme = {
2945
6056
  };
2946
6057
 
2947
6058
  // dist/theme-widget.js
2948
- var ThemeWidget = class extends import_core21.Widget {
6059
+ var ThemeWidget = class extends Widget {
2949
6060
  constructor(props = {}) {
2950
6061
  super(props);
2951
6062
  this.className = "deck-widget-theme";
@@ -2962,10 +6073,10 @@ var ThemeWidget = class extends import_core21.Widget {
2962
6073
  super.setProps(props);
2963
6074
  }
2964
6075
  onRenderHTML(rootElement) {
2965
- const { lightModeLabel, darkModeLabel } = this.props;
6076
+ const { lightModeLabel, darkModeLabel, lightModeTooltip, darkModeTooltip } = this.props;
2966
6077
  const currentMode = this.getThemeMode();
2967
6078
  this._applyTheme(currentMode, rootElement);
2968
- (0, import_preact18.render)((0, import_jsx_runtime24.jsx)(IconButton, { onClick: this._handleClick.bind(this), label: currentMode === "dark" ? darkModeLabel : lightModeLabel, className: currentMode === "dark" ? "deck-widget-moon" : "deck-widget-sun" }), rootElement);
6079
+ (0, import_preact18.render)((0, import_jsx_runtime25.jsx)(IconButton, { onClick: this._handleClick.bind(this), label: currentMode === "dark" ? darkModeLabel : lightModeLabel, tooltip: currentMode === "dark" ? darkModeTooltip : lightModeTooltip, className: currentMode === "dark" ? "deck-widget-moon" : "deck-widget-sun" }), rootElement);
2969
6080
  }
2970
6081
  /**
2971
6082
  * Returns the current theme mode.
@@ -2988,16 +6099,16 @@ var ThemeWidget = class extends import_core21.Widget {
2988
6099
  /** Apply theme styling without changing internal state */
2989
6100
  _applyTheme(themeMode, rootElement) {
2990
6101
  const themeStyle = themeMode === "dark" ? this.props.darkModeTheme : this.props.lightModeTheme;
2991
- if ((0, import_core20._deepEqual)(themeStyle, this.appliedTheme, 1)) {
6102
+ if (deepEqual(themeStyle, this.appliedTheme, 1)) {
2992
6103
  return;
2993
6104
  }
2994
6105
  const container = rootElement.closest(".deck-widget-container");
2995
6106
  if (!container)
2996
6107
  return;
2997
- (0, import_core20._applyStyles)(container, themeStyle);
6108
+ applyStyles(container, themeStyle);
2998
6109
  this.appliedTheme = themeStyle;
2999
6110
  const label = themeMode === "dark" ? this.props.darkModeLabel : this.props.lightModeLabel;
3000
- import_core20.log.log(1, `Switched theme to ${label}`, themeStyle)();
6111
+ log_default.log(1, `Switched theme to ${label}`, themeStyle)();
3001
6112
  }
3002
6113
  /** Read browser preference */
3003
6114
  _getInitialThemeMode() {
@@ -3012,13 +6123,15 @@ var ThemeWidget = class extends import_core21.Widget {
3012
6123
  }
3013
6124
  };
3014
6125
  ThemeWidget.defaultProps = {
3015
- ...import_core21.Widget.defaultProps,
6126
+ ...Widget.defaultProps,
3016
6127
  id: "theme",
3017
6128
  placement: "top-left",
3018
6129
  viewId: null,
3019
6130
  lightModeLabel: "Light Mode",
6131
+ lightModeTooltip: void 0,
3020
6132
  lightModeTheme: LightGlassTheme,
3021
6133
  darkModeLabel: "Dark Mode",
6134
+ darkModeTooltip: void 0,
3022
6135
  darkModeTheme: DarkGlassTheme,
3023
6136
  initialThemeMode: "auto",
3024
6137
  themeMode: void 0,
@@ -3027,10 +6140,9 @@ ThemeWidget.defaultProps = {
3027
6140
  };
3028
6141
 
3029
6142
  // dist/loading-widget.js
3030
- var import_jsx_runtime25 = require("preact/jsx-runtime");
6143
+ var import_jsx_runtime26 = require("preact/jsx-runtime");
3031
6144
  var import_preact19 = require("preact");
3032
- var import_core22 = require("@deck.gl/core");
3033
- var LoadingWidget = class extends import_core22.Widget {
6145
+ var LoadingWidget = class extends Widget {
3034
6146
  constructor(props = {}) {
3035
6147
  super(props);
3036
6148
  this.className = "deck-widget-loading";
@@ -3046,7 +6158,7 @@ var LoadingWidget = class extends import_core22.Widget {
3046
6158
  onRenderHTML(rootElement) {
3047
6159
  (0, import_preact19.render)(
3048
6160
  // TODO(ibgreen) - this should not be a button, but styling is so nested that it is easier to reuse this component.
3049
- this.loading && (0, import_jsx_runtime25.jsx)(IconButton, { className: "deck-widget-spinner", label: this.props.label, onClick: this.handleClick.bind(this) }),
6161
+ this.loading && (0, import_jsx_runtime26.jsx)(IconButton, { className: "deck-widget-spinner", label: this.props.label, tooltip: this.props.tooltip, onClick: this.handleClick.bind(this) }),
3050
6162
  rootElement
3051
6163
  );
3052
6164
  }
@@ -3064,21 +6176,21 @@ var LoadingWidget = class extends import_core22.Widget {
3064
6176
  }
3065
6177
  };
3066
6178
  LoadingWidget.defaultProps = {
3067
- ...import_core22.Widget.defaultProps,
6179
+ ...Widget.defaultProps,
3068
6180
  id: "loading",
3069
6181
  placement: "top-left",
3070
6182
  viewId: null,
3071
6183
  label: "Loading layer data",
6184
+ tooltip: void 0,
3072
6185
  onLoadingChange: () => {
3073
6186
  }
3074
6187
  };
3075
6188
 
3076
6189
  // dist/stats-widget.js
3077
- var import_jsx_runtime26 = require("preact/jsx-runtime");
3078
- var import_core23 = require("@deck.gl/core");
3079
- var import_core24 = require("@luma.gl/core");
6190
+ var import_jsx_runtime27 = require("preact/jsx-runtime");
6191
+ var import_core34 = require("@luma.gl/core");
3080
6192
  var import_preact20 = require("preact");
3081
- var import_hooks7 = require("preact/hooks");
6193
+ var import_hooks8 = require("preact/hooks");
3082
6194
  var DEFAULT_COUNT_FORMATTER = (stat) => `${stat.name}: ${stat.count}`;
3083
6195
  function formatTime(time) {
3084
6196
  return time < 1e3 ? `${time.toFixed(2)}ms` : `${(time / 1e3).toFixed(2)}s`;
@@ -3094,7 +6206,7 @@ var DEFAULT_FORMATTERS = {
3094
6206
  fps: (stat) => `${stat.name}: ${Math.round(stat.getHz())}fps`,
3095
6207
  memory: (stat) => `${stat.name}: ${formatMemory(stat.count)}`
3096
6208
  };
3097
- var StatsWidget = class extends import_core23.Widget {
6209
+ var StatsWidget = class extends Widget {
3098
6210
  /**
3099
6211
  * Returns the current expanded state.
3100
6212
  * In controlled mode, returns the expanded prop.
@@ -3149,7 +6261,7 @@ var StatsWidget = class extends import_core23.Widget {
3149
6261
  onRenderHTML(rootElement) {
3150
6262
  const isExpanded = this.getExpanded();
3151
6263
  if (!isExpanded) {
3152
- (0, import_preact20.render)((0, import_jsx_runtime26.jsx)(FpsIcon, { getFps: this._getFps, onClick: this._toggleExpanded }), rootElement);
6264
+ (0, import_preact20.render)((0, import_jsx_runtime27.jsx)(FpsIcon, { getFps: this._getFps, onClick: this._toggleExpanded }), rootElement);
3153
6265
  return;
3154
6266
  }
3155
6267
  const stats = this._getStats();
@@ -3163,11 +6275,11 @@ var StatsWidget = class extends import_core23.Widget {
3163
6275
  stat.reset();
3164
6276
  }
3165
6277
  lines.forEach((line, i) => {
3166
- items.push((0, import_jsx_runtime26.jsx)("div", { style: { whiteSpace: "pre" }, children: line }, `${stat.name}-${i}`));
6278
+ items.push((0, import_jsx_runtime27.jsx)("div", { style: { whiteSpace: "pre" }, children: line }, `${stat.name}-${i}`));
3167
6279
  });
3168
6280
  });
3169
6281
  }
3170
- (0, import_preact20.render)((0, import_jsx_runtime26.jsxs)("div", { className: "deck-widget-stats-container", style: { cursor: "default" }, children: [(0, import_jsx_runtime26.jsxs)("div", { className: "deck-widget-stats-header", style: { cursor: "pointer", pointerEvents: "auto" }, onClick: this._toggleExpanded, children: [(0, import_jsx_runtime26.jsx)("b", { children: title }), deviceLabel && (0, import_jsx_runtime26.jsx)("span", { className: "deck-widget-stats-device", children: deviceLabel }), (0, import_jsx_runtime26.jsx)("button", { className: "deck-widget-dropdown-button", children: (0, import_jsx_runtime26.jsx)("span", { className: "deck-widget-dropdown-icon open" }) })] }), (0, import_jsx_runtime26.jsx)("div", { className: "deck-widget-stats-content", children: items })] }), rootElement);
6282
+ (0, import_preact20.render)((0, import_jsx_runtime27.jsxs)("div", { className: "deck-widget-stats-container", style: { cursor: "default" }, children: [(0, import_jsx_runtime27.jsxs)("div", { className: "deck-widget-stats-header", style: { cursor: "pointer", pointerEvents: "auto" }, onClick: this._toggleExpanded, children: [(0, import_jsx_runtime27.jsx)("b", { children: title }), deviceLabel && (0, import_jsx_runtime27.jsx)("span", { className: "deck-widget-stats-device", children: deviceLabel }), (0, import_jsx_runtime27.jsx)("button", { className: "deck-widget-dropdown-button", children: (0, import_jsx_runtime27.jsx)("span", { className: "deck-widget-dropdown-icon open" }) })] }), (0, import_jsx_runtime27.jsx)("div", { className: "deck-widget-stats-content", children: items })] }), rootElement);
3171
6283
  }
3172
6284
  onRedraw() {
3173
6285
  if (this.getExpanded()) {
@@ -3184,7 +6296,7 @@ var StatsWidget = class extends import_core23.Widget {
3184
6296
  const metrics = ((_a = this.deck) == null ? void 0 : _a.metrics) ?? {};
3185
6297
  return Object.entries(metrics);
3186
6298
  case "luma":
3187
- return Array.from(import_core24.luma.stats.stats.values())[0];
6299
+ return Array.from(import_core34.luma.stats.stats.values())[0];
3188
6300
  case "device":
3189
6301
  const device = (_b = this.deck) == null ? void 0 : _b.device;
3190
6302
  const stats = device == null ? void 0 : device.statsManager.stats.values();
@@ -3221,7 +6333,7 @@ var StatsWidget = class extends import_core23.Widget {
3221
6333
  }
3222
6334
  };
3223
6335
  StatsWidget.defaultProps = {
3224
- ...import_core23.Widget.defaultProps,
6336
+ ...Widget.defaultProps,
3225
6337
  type: "deck",
3226
6338
  placement: "top-left",
3227
6339
  viewId: null,
@@ -3237,8 +6349,8 @@ StatsWidget.defaultProps = {
3237
6349
  }
3238
6350
  };
3239
6351
  function FpsIcon({ getFps, onClick }) {
3240
- const [fps, setFps] = (0, import_hooks7.useState)(getFps());
3241
- (0, import_hooks7.useEffect)(() => {
6352
+ const [fps, setFps] = (0, import_hooks8.useState)(getFps());
6353
+ (0, import_hooks8.useEffect)(() => {
3242
6354
  const onUpdate = () => {
3243
6355
  setFps(getFps());
3244
6356
  timer = requestAnimationFrame(onUpdate);
@@ -3248,6 +6360,6 @@ function FpsIcon({ getFps, onClick }) {
3248
6360
  cancelAnimationFrame(timer);
3249
6361
  };
3250
6362
  }, [getFps]);
3251
- return (0, import_jsx_runtime26.jsx)(IconButton, { onClick, children: (0, import_jsx_runtime26.jsxs)("div", { className: "text", children: ["FPS", (0, import_jsx_runtime26.jsx)("br", {}), fps] }) });
6363
+ return (0, import_jsx_runtime27.jsx)(IconButton, { onClick, children: (0, import_jsx_runtime27.jsxs)("div", { className: "text", children: ["FPS", (0, import_jsx_runtime27.jsx)("br", {}), fps] }) });
3252
6364
  }
3253
6365
  //# sourceMappingURL=index.cjs.map