@deck.gl/widgets 9.4.0-alpha.2 → 9.4.0-beta.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/compass-widget.d.ts +2 -0
- package/dist/compass-widget.d.ts.map +1 -1
- package/dist/compass-widget.js +8 -5
- package/dist/compass-widget.js.map +1 -1
- package/dist/context-menu-widget.d.ts.map +1 -1
- package/dist/dist.dev.js +3319 -3264
- package/dist/fullscreen-widget.d.ts +4 -0
- package/dist/fullscreen-widget.d.ts.map +1 -1
- package/dist/fullscreen-widget.js +3 -1
- package/dist/fullscreen-widget.js.map +1 -1
- package/dist/geocoder-widget.d.ts.map +1 -1
- package/dist/gimbal-widget.d.ts +2 -0
- package/dist/gimbal-widget.d.ts.map +1 -1
- package/dist/gimbal-widget.js +18 -15
- package/dist/gimbal-widget.js.map +1 -1
- package/dist/icon-widget.d.ts +2 -0
- package/dist/icon-widget.d.ts.map +1 -1
- package/dist/icon-widget.js +3 -2
- package/dist/icon-widget.js.map +1 -1
- package/dist/index.cjs +3444 -219
- package/dist/index.cjs.map +3 -4
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/dist/info-widget.d.ts.map +1 -1
- package/dist/lib/components/button-group.d.ts.map +1 -1
- package/dist/lib/components/dropdown-menu.d.ts.map +1 -1
- package/dist/lib/components/icon-button.d.ts +2 -0
- package/dist/lib/components/icon-button.d.ts.map +1 -1
- package/dist/lib/components/icon-button.js +5 -2
- package/dist/lib/components/icon-button.js.map +1 -1
- package/dist/lib/components/popover.d.ts.map +1 -1
- package/dist/lib/components/tooltip.d.ts +14 -0
- package/dist/lib/components/tooltip.d.ts.map +1 -0
- package/dist/lib/components/tooltip.js +64 -0
- package/dist/lib/components/tooltip.js.map +1 -0
- package/dist/lib/components/user-content.d.ts.map +1 -1
- package/dist/loading-widget.d.ts +2 -0
- package/dist/loading-widget.d.ts.map +1 -1
- package/dist/loading-widget.js +2 -1
- package/dist/loading-widget.js.map +1 -1
- package/dist/popup-widget.d.ts.map +1 -1
- package/dist/reset-view-widget.d.ts +2 -0
- package/dist/reset-view-widget.d.ts.map +1 -1
- package/dist/reset-view-widget.js +2 -1
- package/dist/reset-view-widget.js.map +1 -1
- package/dist/screenshot-widget.d.ts +2 -0
- package/dist/screenshot-widget.d.ts.map +1 -1
- package/dist/screenshot-widget.js +2 -1
- package/dist/screenshot-widget.js.map +1 -1
- package/dist/scrollbar-widget.d.ts +6 -1
- package/dist/scrollbar-widget.d.ts.map +1 -1
- package/dist/scrollbar-widget.js +12 -3
- package/dist/scrollbar-widget.js.map +1 -1
- package/dist/selector-widget.d.ts +2 -0
- package/dist/selector-widget.d.ts.map +1 -1
- package/dist/selector-widget.js +2 -1
- package/dist/selector-widget.js.map +1 -1
- package/dist/splitter-widget.d.ts.map +1 -1
- package/dist/stylesheet.css +102 -116
- package/dist/theme-widget.d.ts +4 -0
- package/dist/theme-widget.d.ts.map +1 -1
- package/dist/theme-widget.js +4 -2
- package/dist/theme-widget.js.map +1 -1
- package/dist/themes.d.ts +5 -0
- package/dist/themes.d.ts.map +1 -1
- package/dist/themes.js +4 -0
- package/dist/themes.js.map +1 -1
- package/dist/timeline-widget.d.ts +4 -0
- package/dist/timeline-widget.d.ts.map +1 -1
- package/dist/timeline-widget.js +5 -3
- package/dist/timeline-widget.js.map +1 -1
- package/dist/toggle-widget.d.ts +4 -0
- package/dist/toggle-widget.d.ts.map +1 -1
- package/dist/toggle-widget.js +4 -2
- package/dist/toggle-widget.js.map +1 -1
- package/dist/zoom-widget.d.ts +4 -0
- package/dist/zoom-widget.d.ts.map +1 -1
- package/dist/zoom-widget.js +3 -1
- package/dist/zoom-widget.js.map +1 -1
- package/dist.min.js +2 -2
- package/package.json +4 -4
- package/src/compass-widget.tsx +31 -23
- package/src/fullscreen-widget.tsx +7 -0
- package/src/gimbal-widget.tsx +62 -54
- package/src/icon-widget.tsx +5 -1
- package/src/icons/add.svg +1 -0
- package/src/icons/chevron-down.svg +1 -0
- package/src/icons/chevron-left.svg +1 -0
- package/src/icons/chevron-right.svg +1 -0
- package/src/icons/chevron-up.svg +1 -0
- package/src/icons/close.svg +1 -0
- package/src/icons/dark-mode.svg +1 -0
- package/src/icons/dropdown.svg +1 -0
- package/src/icons/fullscreen-exit.svg +1 -0
- package/src/icons/fullscreen.svg +1 -0
- package/src/icons/light-mode.svg +1 -0
- package/src/icons/loading.svg +1 -0
- package/src/icons/pause.svg +1 -0
- package/src/icons/photo-camera.svg +1 -0
- package/src/icons/play-arrow.svg +1 -0
- package/src/icons/remove.svg +1 -0
- package/src/icons/reset-focus.svg +1 -0
- package/src/index.ts +1 -0
- package/src/lib/components/icon-button.tsx +17 -9
- package/src/lib/components/tooltip.tsx +116 -0
- package/src/loading-widget.tsx +4 -0
- package/src/reset-view-widget.tsx +4 -0
- package/src/screenshot-widget.tsx +4 -0
- package/src/scrollbar-widget.tsx +30 -4
- package/src/selector-widget.tsx +4 -0
- package/src/stylesheet.css +67 -114
- package/src/theme-widget.tsx +8 -1
- package/src/themes.ts +5 -0
- package/src/timeline-widget.tsx +10 -2
- package/src/toggle-widget.tsx +9 -0
- package/src/zoom-widget.tsx +8 -0
package/dist/index.cjs
CHANGED
|
@@ -15,11 +15,11 @@ var __copyProps = (to, from, except, desc) => {
|
|
|
15
15
|
}
|
|
16
16
|
return to;
|
|
17
17
|
};
|
|
18
|
-
var __toCommonJS = (
|
|
18
|
+
var __toCommonJS = (mod2) => __copyProps(__defProp({}, "__esModule", { value: true }), mod2);
|
|
19
19
|
|
|
20
20
|
// dist/index.js
|
|
21
|
-
var
|
|
22
|
-
__export(
|
|
21
|
+
var index_exports = {};
|
|
22
|
+
__export(index_exports, {
|
|
23
23
|
CompassWidget: () => CompassWidget,
|
|
24
24
|
ContextMenuWidget: () => ContextMenuWidget,
|
|
25
25
|
DarkGlassTheme: () => DarkGlassTheme,
|
|
@@ -54,13 +54,3162 @@ __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(
|
|
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 mod(value, divisor) {
|
|
130
|
+
const modulus = value % divisor;
|
|
131
|
+
return modulus < 0 ? divisor + modulus : modulus;
|
|
132
|
+
}
|
|
133
|
+
function getCameraPosition(viewMatrixInverse) {
|
|
134
|
+
return [viewMatrixInverse[12], viewMatrixInverse[13], viewMatrixInverse[14]];
|
|
135
|
+
}
|
|
136
|
+
function getFrustumPlanes(viewProjectionMatrix) {
|
|
137
|
+
return {
|
|
138
|
+
left: getFrustumPlane(
|
|
139
|
+
viewProjectionMatrix[3] + viewProjectionMatrix[0],
|
|
140
|
+
viewProjectionMatrix[7] + viewProjectionMatrix[4],
|
|
141
|
+
viewProjectionMatrix[11] + viewProjectionMatrix[8],
|
|
142
|
+
viewProjectionMatrix[15] + viewProjectionMatrix[12]
|
|
143
|
+
),
|
|
144
|
+
right: getFrustumPlane(
|
|
145
|
+
viewProjectionMatrix[3] - viewProjectionMatrix[0],
|
|
146
|
+
viewProjectionMatrix[7] - viewProjectionMatrix[4],
|
|
147
|
+
viewProjectionMatrix[11] - viewProjectionMatrix[8],
|
|
148
|
+
viewProjectionMatrix[15] - viewProjectionMatrix[12]
|
|
149
|
+
),
|
|
150
|
+
bottom: getFrustumPlane(
|
|
151
|
+
viewProjectionMatrix[3] + viewProjectionMatrix[1],
|
|
152
|
+
viewProjectionMatrix[7] + viewProjectionMatrix[5],
|
|
153
|
+
viewProjectionMatrix[11] + viewProjectionMatrix[9],
|
|
154
|
+
viewProjectionMatrix[15] + viewProjectionMatrix[13]
|
|
155
|
+
),
|
|
156
|
+
top: getFrustumPlane(
|
|
157
|
+
viewProjectionMatrix[3] - viewProjectionMatrix[1],
|
|
158
|
+
viewProjectionMatrix[7] - viewProjectionMatrix[5],
|
|
159
|
+
viewProjectionMatrix[11] - viewProjectionMatrix[9],
|
|
160
|
+
viewProjectionMatrix[15] - viewProjectionMatrix[13]
|
|
161
|
+
),
|
|
162
|
+
near: getFrustumPlane(
|
|
163
|
+
viewProjectionMatrix[3] + viewProjectionMatrix[2],
|
|
164
|
+
viewProjectionMatrix[7] + viewProjectionMatrix[6],
|
|
165
|
+
viewProjectionMatrix[11] + viewProjectionMatrix[10],
|
|
166
|
+
viewProjectionMatrix[15] + viewProjectionMatrix[14]
|
|
167
|
+
),
|
|
168
|
+
far: getFrustumPlane(
|
|
169
|
+
viewProjectionMatrix[3] - viewProjectionMatrix[2],
|
|
170
|
+
viewProjectionMatrix[7] - viewProjectionMatrix[6],
|
|
171
|
+
viewProjectionMatrix[11] - viewProjectionMatrix[10],
|
|
172
|
+
viewProjectionMatrix[15] - viewProjectionMatrix[14]
|
|
173
|
+
)
|
|
174
|
+
};
|
|
175
|
+
}
|
|
176
|
+
var scratchVector = new import_core.Vector3();
|
|
177
|
+
function getFrustumPlane(a, b, c, d) {
|
|
178
|
+
scratchVector.set(a, b, c);
|
|
179
|
+
const L = scratchVector.len();
|
|
180
|
+
return { distance: d / L, normal: new import_core.Vector3(-a / L, -b / L, -c / L) };
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
// ../core/src/viewports/viewport.ts
|
|
184
|
+
var import_core2 = require("@math.gl/core");
|
|
185
|
+
var import_web_mercator = require("@math.gl/web-mercator");
|
|
186
|
+
var DEGREES_TO_RADIANS = Math.PI / 180;
|
|
187
|
+
var IDENTITY = createMat4();
|
|
188
|
+
var ZERO_VECTOR = [0, 0, 0];
|
|
189
|
+
var DEFAULT_DISTANCE_SCALES = {
|
|
190
|
+
unitsPerMeter: [1, 1, 1],
|
|
191
|
+
metersPerUnit: [1, 1, 1]
|
|
192
|
+
};
|
|
193
|
+
function createProjectionMatrix({
|
|
194
|
+
width,
|
|
195
|
+
height,
|
|
196
|
+
orthographic,
|
|
197
|
+
fovyRadians,
|
|
198
|
+
focalDistance,
|
|
199
|
+
padding,
|
|
200
|
+
near,
|
|
201
|
+
far
|
|
202
|
+
}) {
|
|
203
|
+
const aspect = width / height;
|
|
204
|
+
const matrix = orthographic ? new import_core2.Matrix4().orthographic({ fovy: fovyRadians, aspect, focalDistance, near, far }) : new import_core2.Matrix4().perspective({ fovy: fovyRadians, aspect, near, far });
|
|
205
|
+
if (padding) {
|
|
206
|
+
const { left = 0, right = 0, top = 0, bottom = 0 } = padding;
|
|
207
|
+
const offsetX = (0, import_core2.clamp)((left + width - right) / 2, 0, width) - width / 2;
|
|
208
|
+
const offsetY = (0, import_core2.clamp)((top + height - bottom) / 2, 0, height) - height / 2;
|
|
209
|
+
matrix[8] -= offsetX * 2 / width;
|
|
210
|
+
matrix[9] += offsetY * 2 / height;
|
|
211
|
+
}
|
|
212
|
+
return matrix;
|
|
213
|
+
}
|
|
214
|
+
var _Viewport = class _Viewport {
|
|
215
|
+
// eslint-disable-next-line complexity
|
|
216
|
+
constructor(opts = {}) {
|
|
217
|
+
this._frustumPlanes = {};
|
|
218
|
+
this.id = opts.id || this.constructor.displayName || "viewport";
|
|
219
|
+
this.x = opts.x || 0;
|
|
220
|
+
this.y = opts.y || 0;
|
|
221
|
+
this.width = opts.width || 1;
|
|
222
|
+
this.height = opts.height || 1;
|
|
223
|
+
this.zoom = opts.zoom || 0;
|
|
224
|
+
this.padding = opts.padding;
|
|
225
|
+
this.distanceScales = opts.distanceScales || DEFAULT_DISTANCE_SCALES;
|
|
226
|
+
this.focalDistance = opts.focalDistance || 1;
|
|
227
|
+
this.position = opts.position || ZERO_VECTOR;
|
|
228
|
+
this.modelMatrix = opts.modelMatrix || null;
|
|
229
|
+
const { longitude, latitude } = opts;
|
|
230
|
+
this.isGeospatial = Number.isFinite(latitude) && Number.isFinite(longitude);
|
|
231
|
+
this._initProps(opts);
|
|
232
|
+
this._initMatrices(opts);
|
|
233
|
+
this.equals = this.equals.bind(this);
|
|
234
|
+
this.project = this.project.bind(this);
|
|
235
|
+
this.unproject = this.unproject.bind(this);
|
|
236
|
+
this.projectPosition = this.projectPosition.bind(this);
|
|
237
|
+
this.unprojectPosition = this.unprojectPosition.bind(this);
|
|
238
|
+
this.projectFlat = this.projectFlat.bind(this);
|
|
239
|
+
this.unprojectFlat = this.unprojectFlat.bind(this);
|
|
240
|
+
}
|
|
241
|
+
get subViewports() {
|
|
242
|
+
return null;
|
|
243
|
+
}
|
|
244
|
+
get metersPerPixel() {
|
|
245
|
+
return this.distanceScales.metersPerUnit[2] / this.scale;
|
|
246
|
+
}
|
|
247
|
+
get projectionMode() {
|
|
248
|
+
if (this.isGeospatial) {
|
|
249
|
+
return this.zoom < 12 ? PROJECTION_MODE.WEB_MERCATOR : PROJECTION_MODE.WEB_MERCATOR_AUTO_OFFSET;
|
|
250
|
+
}
|
|
251
|
+
return PROJECTION_MODE.IDENTITY;
|
|
252
|
+
}
|
|
253
|
+
// Two viewports are equal if their dimensions, common-space scale, and
|
|
254
|
+
// view and projection matrices are (approximately) equal.
|
|
255
|
+
equals(viewport) {
|
|
256
|
+
if (!(viewport instanceof _Viewport)) {
|
|
257
|
+
return false;
|
|
258
|
+
}
|
|
259
|
+
if (this === viewport) {
|
|
260
|
+
return true;
|
|
261
|
+
}
|
|
262
|
+
return viewport.width === this.width && viewport.height === this.height && viewport.scale === this.scale && viewport.projectionMode === this.projectionMode && viewport.resolution === this.resolution && (0, import_core2.equals)(viewport.distanceScales.unitsPerMeter, this.distanceScales.unitsPerMeter) && (0, import_core2.equals)(viewport.projectionMatrix, this.projectionMatrix) && (0, import_core2.equals)(viewport.viewMatrix, this.viewMatrix);
|
|
263
|
+
}
|
|
264
|
+
/**
|
|
265
|
+
* Projects xyz (possibly latitude and longitude) to pixel coordinates in window
|
|
266
|
+
* using viewport projection parameters
|
|
267
|
+
* - [longitude, latitude] to [x, y]
|
|
268
|
+
* - [longitude, latitude, Z] => [x, y, z]
|
|
269
|
+
* Note: By default, returns top-left coordinates for canvas/SVG type render
|
|
270
|
+
*
|
|
271
|
+
* @param {Array} lngLatZ - [lng, lat] or [lng, lat, Z]
|
|
272
|
+
* @param {Object} opts - options
|
|
273
|
+
* @param {Object} opts.topLeft=true - Whether projected coords are top left
|
|
274
|
+
* @return {Array} - [x, y] or [x, y, z] in top left coords
|
|
275
|
+
*/
|
|
276
|
+
project(xyz, { topLeft = true } = {}) {
|
|
277
|
+
const worldPosition = this.projectPosition(xyz);
|
|
278
|
+
const coord = (0, import_web_mercator.worldToPixels)(worldPosition, this.pixelProjectionMatrix);
|
|
279
|
+
const [x, y] = coord;
|
|
280
|
+
const y2 = topLeft ? y : this.height - y;
|
|
281
|
+
return xyz.length === 2 ? [x, y2] : [x, y2, coord[2]];
|
|
282
|
+
}
|
|
283
|
+
/**
|
|
284
|
+
* Unproject pixel coordinates on screen onto world coordinates,
|
|
285
|
+
* (possibly [lon, lat]) on map.
|
|
286
|
+
* - [x, y] => [lng, lat]
|
|
287
|
+
* - [x, y, z] => [lng, lat, Z]
|
|
288
|
+
* @param {Array} xyz -
|
|
289
|
+
* @param {Object} opts - options
|
|
290
|
+
* @param {Object} opts.topLeft=true - Whether origin is top left
|
|
291
|
+
* @return {Array|null} - [lng, lat, Z] or [X, Y, Z]
|
|
292
|
+
*/
|
|
293
|
+
unproject(xyz, { topLeft = true, targetZ } = {}) {
|
|
294
|
+
const [x, y, z] = xyz;
|
|
295
|
+
const y2 = topLeft ? y : this.height - y;
|
|
296
|
+
const targetZWorld = targetZ && targetZ * this.distanceScales.unitsPerMeter[2];
|
|
297
|
+
const coord = (0, import_web_mercator.pixelsToWorld)([x, y2, z], this.pixelUnprojectionMatrix, targetZWorld);
|
|
298
|
+
const [X, Y, Z] = this.unprojectPosition(coord);
|
|
299
|
+
if (Number.isFinite(z)) {
|
|
300
|
+
return [X, Y, Z];
|
|
301
|
+
}
|
|
302
|
+
return Number.isFinite(targetZ) ? [X, Y, targetZ] : [X, Y];
|
|
303
|
+
}
|
|
304
|
+
// NON_LINEAR PROJECTION HOOKS
|
|
305
|
+
// Used for web meractor projection
|
|
306
|
+
projectPosition(xyz) {
|
|
307
|
+
const [X, Y] = this.projectFlat(xyz);
|
|
308
|
+
const Z = (xyz[2] || 0) * this.distanceScales.unitsPerMeter[2];
|
|
309
|
+
return [X, Y, Z];
|
|
310
|
+
}
|
|
311
|
+
unprojectPosition(xyz) {
|
|
312
|
+
const [X, Y] = this.unprojectFlat(xyz);
|
|
313
|
+
const Z = (xyz[2] || 0) * this.distanceScales.metersPerUnit[2];
|
|
314
|
+
return [X, Y, Z];
|
|
315
|
+
}
|
|
316
|
+
/**
|
|
317
|
+
* Project [lng,lat] on sphere onto [x,y] on 512*512 Mercator Zoom 0 tile.
|
|
318
|
+
* Performs the nonlinear part of the web mercator projection.
|
|
319
|
+
* Remaining projection is done with 4x4 matrices which also handles
|
|
320
|
+
* perspective.
|
|
321
|
+
* @param {Array} lngLat - [lng, lat] coordinates
|
|
322
|
+
* Specifies a point on the sphere to project onto the map.
|
|
323
|
+
* @return {Array} [x,y] coordinates.
|
|
324
|
+
*/
|
|
325
|
+
projectFlat(xyz) {
|
|
326
|
+
if (this.isGeospatial) {
|
|
327
|
+
const result = (0, import_web_mercator.lngLatToWorld)(xyz);
|
|
328
|
+
result[1] = (0, import_core2.clamp)(result[1], -318, 830);
|
|
329
|
+
return result;
|
|
330
|
+
}
|
|
331
|
+
return xyz;
|
|
332
|
+
}
|
|
333
|
+
/**
|
|
334
|
+
* Unproject world point [x,y] on map onto {lat, lon} on sphere
|
|
335
|
+
* @param {object|Vector} xy - object with {x,y} members
|
|
336
|
+
* representing point on projected map plane
|
|
337
|
+
* @return {GeoCoordinates} - object with {lat,lon} of point on sphere.
|
|
338
|
+
* Has toArray method if you need a GeoJSON Array.
|
|
339
|
+
* Per cartographic tradition, lat and lon are specified as degrees.
|
|
340
|
+
*/
|
|
341
|
+
unprojectFlat(xyz) {
|
|
342
|
+
if (this.isGeospatial) {
|
|
343
|
+
return (0, import_web_mercator.worldToLngLat)(xyz);
|
|
344
|
+
}
|
|
345
|
+
return xyz;
|
|
346
|
+
}
|
|
347
|
+
/**
|
|
348
|
+
* Get bounds of the current viewport
|
|
349
|
+
* @return {Array} - [minX, minY, maxX, maxY]
|
|
350
|
+
*/
|
|
351
|
+
getBounds(options = {}) {
|
|
352
|
+
const unprojectOption = { targetZ: options.z || 0 };
|
|
353
|
+
const topLeft = this.unproject([0, 0], unprojectOption);
|
|
354
|
+
const topRight = this.unproject([this.width, 0], unprojectOption);
|
|
355
|
+
const bottomLeft = this.unproject([0, this.height], unprojectOption);
|
|
356
|
+
const bottomRight = this.unproject([this.width, this.height], unprojectOption);
|
|
357
|
+
return [
|
|
358
|
+
Math.min(topLeft[0], topRight[0], bottomLeft[0], bottomRight[0]),
|
|
359
|
+
Math.min(topLeft[1], topRight[1], bottomLeft[1], bottomRight[1]),
|
|
360
|
+
Math.max(topLeft[0], topRight[0], bottomLeft[0], bottomRight[0]),
|
|
361
|
+
Math.max(topLeft[1], topRight[1], bottomLeft[1], bottomRight[1])
|
|
362
|
+
];
|
|
363
|
+
}
|
|
364
|
+
getDistanceScales(coordinateOrigin) {
|
|
365
|
+
if (coordinateOrigin && this.isGeospatial) {
|
|
366
|
+
return (0, import_web_mercator.getDistanceScales)({
|
|
367
|
+
longitude: coordinateOrigin[0],
|
|
368
|
+
latitude: coordinateOrigin[1],
|
|
369
|
+
highPrecision: true
|
|
370
|
+
});
|
|
371
|
+
}
|
|
372
|
+
return this.distanceScales;
|
|
373
|
+
}
|
|
374
|
+
containsPixel({
|
|
375
|
+
x,
|
|
376
|
+
y,
|
|
377
|
+
width = 1,
|
|
378
|
+
height = 1
|
|
379
|
+
}) {
|
|
380
|
+
return x < this.x + this.width && this.x < x + width && y < this.y + this.height && this.y < y + height;
|
|
381
|
+
}
|
|
382
|
+
// Extract frustum planes in common space
|
|
383
|
+
getFrustumPlanes() {
|
|
384
|
+
if (this._frustumPlanes.near) {
|
|
385
|
+
return this._frustumPlanes;
|
|
386
|
+
}
|
|
387
|
+
Object.assign(this._frustumPlanes, getFrustumPlanes(this.viewProjectionMatrix));
|
|
388
|
+
return this._frustumPlanes;
|
|
389
|
+
}
|
|
390
|
+
// EXPERIMENTAL METHODS
|
|
391
|
+
/**
|
|
392
|
+
* Needed by panning and linear transition
|
|
393
|
+
* Pan the viewport to place a given world coordinate at screen point [x, y]
|
|
394
|
+
*
|
|
395
|
+
* @param {Array} coords - world coordinates
|
|
396
|
+
* @param {Array} pixel - [x,y] coordinates on screen
|
|
397
|
+
* @param {Array} startPixel - [x,y] screen position where pan started (optional, for delta-based panning)
|
|
398
|
+
* @return {Object} props of the new viewport
|
|
399
|
+
*/
|
|
400
|
+
panByPosition(coords, pixel, startPixel) {
|
|
401
|
+
return null;
|
|
402
|
+
}
|
|
403
|
+
// INTERNAL METHODS
|
|
404
|
+
/* eslint-disable complexity, max-statements */
|
|
405
|
+
_initProps(opts) {
|
|
406
|
+
const longitude = opts.longitude;
|
|
407
|
+
const latitude = opts.latitude;
|
|
408
|
+
if (this.isGeospatial) {
|
|
409
|
+
if (!Number.isFinite(opts.zoom)) {
|
|
410
|
+
this.zoom = (0, import_web_mercator.getMeterZoom)({ latitude }) + Math.log2(this.focalDistance);
|
|
411
|
+
}
|
|
412
|
+
this.distanceScales = opts.distanceScales || (0, import_web_mercator.getDistanceScales)({ latitude, longitude });
|
|
413
|
+
}
|
|
414
|
+
const scale = Math.pow(2, this.zoom);
|
|
415
|
+
this.scale = scale;
|
|
416
|
+
const { position, modelMatrix } = opts;
|
|
417
|
+
let meterOffset = ZERO_VECTOR;
|
|
418
|
+
if (position) {
|
|
419
|
+
meterOffset = modelMatrix ? new import_core2.Matrix4(modelMatrix).transformAsVector(position, []) : position;
|
|
420
|
+
}
|
|
421
|
+
if (this.isGeospatial) {
|
|
422
|
+
const center = this.projectPosition([longitude, latitude, 0]);
|
|
423
|
+
this.center = new import_core2.Vector3(meterOffset).scale(this.distanceScales.unitsPerMeter).add(center);
|
|
424
|
+
} else {
|
|
425
|
+
this.center = this.projectPosition(meterOffset);
|
|
426
|
+
}
|
|
427
|
+
}
|
|
428
|
+
/* eslint-enable complexity, max-statements */
|
|
429
|
+
_initMatrices(opts) {
|
|
430
|
+
const {
|
|
431
|
+
// View matrix
|
|
432
|
+
viewMatrix: viewMatrix2 = IDENTITY,
|
|
433
|
+
// Projection matrix
|
|
434
|
+
projectionMatrix = null,
|
|
435
|
+
// Projection matrix parameters, used if projectionMatrix not supplied
|
|
436
|
+
orthographic = false,
|
|
437
|
+
fovyRadians,
|
|
438
|
+
fovy = 75,
|
|
439
|
+
near = 0.1,
|
|
440
|
+
// Distance of near clipping plane
|
|
441
|
+
far = 1e3,
|
|
442
|
+
// Distance of far clipping plane
|
|
443
|
+
padding = null,
|
|
444
|
+
// Center offset in pixels
|
|
445
|
+
focalDistance = 1
|
|
446
|
+
} = opts;
|
|
447
|
+
this.viewMatrixUncentered = viewMatrix2;
|
|
448
|
+
this.viewMatrix = new import_core2.Matrix4().multiplyRight(viewMatrix2).translate(new import_core2.Vector3(this.center).negate());
|
|
449
|
+
this.projectionMatrix = projectionMatrix || createProjectionMatrix({
|
|
450
|
+
width: this.width,
|
|
451
|
+
height: this.height,
|
|
452
|
+
orthographic,
|
|
453
|
+
fovyRadians: fovyRadians || fovy * DEGREES_TO_RADIANS,
|
|
454
|
+
focalDistance,
|
|
455
|
+
padding,
|
|
456
|
+
near,
|
|
457
|
+
far
|
|
458
|
+
});
|
|
459
|
+
const vpm = createMat4();
|
|
460
|
+
import_core2.mat4.multiply(vpm, vpm, this.projectionMatrix);
|
|
461
|
+
import_core2.mat4.multiply(vpm, vpm, this.viewMatrix);
|
|
462
|
+
this.viewProjectionMatrix = vpm;
|
|
463
|
+
this.viewMatrixInverse = import_core2.mat4.invert([], this.viewMatrix) || this.viewMatrix;
|
|
464
|
+
this.cameraPosition = getCameraPosition(this.viewMatrixInverse);
|
|
465
|
+
const viewportMatrix = createMat4();
|
|
466
|
+
const pixelProjectionMatrix = createMat4();
|
|
467
|
+
import_core2.mat4.scale(viewportMatrix, viewportMatrix, [this.width / 2, -this.height / 2, 1]);
|
|
468
|
+
import_core2.mat4.translate(viewportMatrix, viewportMatrix, [1, -1, 0]);
|
|
469
|
+
import_core2.mat4.multiply(pixelProjectionMatrix, viewportMatrix, this.viewProjectionMatrix);
|
|
470
|
+
this.pixelProjectionMatrix = pixelProjectionMatrix;
|
|
471
|
+
this.pixelUnprojectionMatrix = import_core2.mat4.invert(createMat4(), this.pixelProjectionMatrix);
|
|
472
|
+
if (!this.pixelUnprojectionMatrix) {
|
|
473
|
+
log_default.warn("Pixel project matrix not invertible")();
|
|
474
|
+
}
|
|
475
|
+
}
|
|
476
|
+
};
|
|
477
|
+
_Viewport.displayName = "Viewport";
|
|
478
|
+
var Viewport = _Viewport;
|
|
479
|
+
|
|
480
|
+
// ../core/src/viewports/web-mercator-viewport.ts
|
|
481
|
+
var import_web_mercator2 = require("@math.gl/web-mercator");
|
|
482
|
+
var import_core3 = require("@math.gl/core");
|
|
483
|
+
var _WebMercatorViewport = class _WebMercatorViewport extends Viewport {
|
|
484
|
+
/* eslint-disable complexity, max-statements */
|
|
485
|
+
constructor(opts = {}) {
|
|
486
|
+
const {
|
|
487
|
+
latitude = 0,
|
|
488
|
+
longitude = 0,
|
|
489
|
+
zoom = 0,
|
|
490
|
+
pitch = 0,
|
|
491
|
+
bearing = 0,
|
|
492
|
+
nearZMultiplier = 0.1,
|
|
493
|
+
farZMultiplier = 1.01,
|
|
494
|
+
nearZ,
|
|
495
|
+
farZ,
|
|
496
|
+
orthographic = false,
|
|
497
|
+
projectionMatrix,
|
|
498
|
+
repeat = false,
|
|
499
|
+
worldOffset = 0,
|
|
500
|
+
position,
|
|
501
|
+
padding,
|
|
502
|
+
// backward compatibility
|
|
503
|
+
// TODO: remove in v9
|
|
504
|
+
legacyMeterSizes = false
|
|
505
|
+
} = opts;
|
|
506
|
+
let { width, height, altitude = 1.5 } = opts;
|
|
507
|
+
const scale = Math.pow(2, zoom);
|
|
508
|
+
width = width || 1;
|
|
509
|
+
height = height || 1;
|
|
510
|
+
let fovy;
|
|
511
|
+
let projectionParameters = null;
|
|
512
|
+
if (projectionMatrix) {
|
|
513
|
+
altitude = projectionMatrix[5] / 2;
|
|
514
|
+
fovy = (0, import_web_mercator2.altitudeToFovy)(altitude);
|
|
515
|
+
} else {
|
|
516
|
+
if (opts.fovy) {
|
|
517
|
+
fovy = opts.fovy;
|
|
518
|
+
altitude = (0, import_web_mercator2.fovyToAltitude)(fovy);
|
|
519
|
+
} else {
|
|
520
|
+
fovy = (0, import_web_mercator2.altitudeToFovy)(altitude);
|
|
521
|
+
}
|
|
522
|
+
let offset3;
|
|
523
|
+
if (padding) {
|
|
524
|
+
const { top = 0, bottom = 0 } = padding;
|
|
525
|
+
offset3 = [0, (0, import_core3.clamp)((top + height - bottom) / 2, 0, height) - height / 2];
|
|
526
|
+
}
|
|
527
|
+
projectionParameters = (0, import_web_mercator2.getProjectionParameters)({
|
|
528
|
+
width,
|
|
529
|
+
height,
|
|
530
|
+
scale,
|
|
531
|
+
center: position && [0, 0, position[2] * (0, import_web_mercator2.unitsPerMeter)(latitude)],
|
|
532
|
+
offset: offset3,
|
|
533
|
+
pitch,
|
|
534
|
+
fovy,
|
|
535
|
+
nearZMultiplier,
|
|
536
|
+
farZMultiplier
|
|
537
|
+
});
|
|
538
|
+
if (Number.isFinite(nearZ)) {
|
|
539
|
+
projectionParameters.near = nearZ;
|
|
540
|
+
}
|
|
541
|
+
if (Number.isFinite(farZ)) {
|
|
542
|
+
projectionParameters.far = farZ;
|
|
543
|
+
}
|
|
544
|
+
}
|
|
545
|
+
let viewMatrixUncentered = (0, import_web_mercator2.getViewMatrix)({
|
|
546
|
+
height,
|
|
547
|
+
pitch,
|
|
548
|
+
bearing,
|
|
549
|
+
scale,
|
|
550
|
+
altitude
|
|
551
|
+
});
|
|
552
|
+
if (worldOffset) {
|
|
553
|
+
const viewOffset = new import_core3.Matrix4().translate([512 * worldOffset, 0, 0]);
|
|
554
|
+
viewMatrixUncentered = viewOffset.multiplyLeft(viewMatrixUncentered);
|
|
555
|
+
}
|
|
556
|
+
super({
|
|
557
|
+
...opts,
|
|
558
|
+
// x, y,
|
|
559
|
+
width,
|
|
560
|
+
height,
|
|
561
|
+
// view matrix
|
|
562
|
+
viewMatrix: viewMatrixUncentered,
|
|
563
|
+
longitude,
|
|
564
|
+
latitude,
|
|
565
|
+
zoom,
|
|
566
|
+
// projection matrix parameters
|
|
567
|
+
...projectionParameters,
|
|
568
|
+
fovy,
|
|
569
|
+
focalDistance: altitude
|
|
570
|
+
});
|
|
571
|
+
this.latitude = latitude;
|
|
572
|
+
this.longitude = longitude;
|
|
573
|
+
this.zoom = zoom;
|
|
574
|
+
this.pitch = pitch;
|
|
575
|
+
this.bearing = bearing;
|
|
576
|
+
this.altitude = altitude;
|
|
577
|
+
this.fovy = fovy;
|
|
578
|
+
this.orthographic = orthographic;
|
|
579
|
+
this._subViewports = repeat ? [] : null;
|
|
580
|
+
this._pseudoMeters = legacyMeterSizes;
|
|
581
|
+
Object.freeze(this);
|
|
582
|
+
}
|
|
583
|
+
/* eslint-enable complexity, max-statements */
|
|
584
|
+
get subViewports() {
|
|
585
|
+
if (this._subViewports && !this._subViewports.length) {
|
|
586
|
+
const bounds = this.getBounds();
|
|
587
|
+
const minOffset = Math.floor((bounds[0] + 180) / 360);
|
|
588
|
+
const maxOffset = Math.ceil((bounds[2] - 180) / 360);
|
|
589
|
+
for (let x = minOffset; x <= maxOffset; x++) {
|
|
590
|
+
const offsetViewport = x ? new _WebMercatorViewport({
|
|
591
|
+
...this,
|
|
592
|
+
worldOffset: x
|
|
593
|
+
}) : this;
|
|
594
|
+
this._subViewports.push(offsetViewport);
|
|
595
|
+
}
|
|
596
|
+
}
|
|
597
|
+
return this._subViewports;
|
|
598
|
+
}
|
|
599
|
+
/** Returns whether two Web Mercator viewports use the same projection settings. */
|
|
600
|
+
equals(viewport) {
|
|
601
|
+
return viewport instanceof _WebMercatorViewport && viewport._pseudoMeters === this._pseudoMeters && super.equals(viewport);
|
|
602
|
+
}
|
|
603
|
+
projectPosition(xyz) {
|
|
604
|
+
if (this._pseudoMeters) {
|
|
605
|
+
return super.projectPosition(xyz);
|
|
606
|
+
}
|
|
607
|
+
const [X, Y] = this.projectFlat(xyz);
|
|
608
|
+
const Z = (xyz[2] || 0) * (0, import_web_mercator2.unitsPerMeter)(xyz[1]);
|
|
609
|
+
return [X, Y, Z];
|
|
610
|
+
}
|
|
611
|
+
unprojectPosition(xyz) {
|
|
612
|
+
if (this._pseudoMeters) {
|
|
613
|
+
return super.unprojectPosition(xyz);
|
|
614
|
+
}
|
|
615
|
+
const [X, Y] = this.unprojectFlat(xyz);
|
|
616
|
+
const Z = (xyz[2] || 0) / (0, import_web_mercator2.unitsPerMeter)(Y);
|
|
617
|
+
return [X, Y, Z];
|
|
618
|
+
}
|
|
619
|
+
/**
|
|
620
|
+
* Add a meter delta to a base lnglat coordinate, returning a new lnglat array
|
|
621
|
+
*
|
|
622
|
+
* Note: Uses simple linear approximation around the viewport center
|
|
623
|
+
* Error increases with size of offset (roughly 1% per 100km)
|
|
624
|
+
*
|
|
625
|
+
* @param {[Number,Number]|[Number,Number,Number]) lngLatZ - base coordinate
|
|
626
|
+
* @param {[Number,Number]|[Number,Number,Number]) xyz - array of meter deltas
|
|
627
|
+
* @return {[Number,Number]|[Number,Number,Number]) array of [lng,lat,z] deltas
|
|
628
|
+
*/
|
|
629
|
+
addMetersToLngLat(lngLatZ, xyz) {
|
|
630
|
+
return (0, import_web_mercator2.addMetersToLngLat)(lngLatZ, xyz);
|
|
631
|
+
}
|
|
632
|
+
panByPosition(coords, pixel, startPixel) {
|
|
633
|
+
const fromLocation = (0, import_web_mercator2.pixelsToWorld)(pixel, this.pixelUnprojectionMatrix);
|
|
634
|
+
const toLocation = this.projectFlat(coords);
|
|
635
|
+
const translate = import_core3.vec2.add([], toLocation, import_core3.vec2.negate([], fromLocation));
|
|
636
|
+
const newCenter = import_core3.vec2.add([], this.center, translate);
|
|
637
|
+
const [longitude, latitude] = this.unprojectFlat(newCenter);
|
|
638
|
+
return { longitude, latitude };
|
|
639
|
+
}
|
|
640
|
+
/**
|
|
641
|
+
* Returns a new longitude and latitude that keeps a 3D world coordinate at a given screen pixel
|
|
642
|
+
* This version handles the z-component (altitude) properly for cameras positioned above ground
|
|
643
|
+
*/
|
|
644
|
+
panByPosition3D(coords, pixel) {
|
|
645
|
+
const targetZ = coords[2] || 0;
|
|
646
|
+
const deltaLngLat = import_core3.vec2.sub([], coords, this.unproject(pixel, { targetZ }));
|
|
647
|
+
return { longitude: this.longitude + deltaLngLat[0], latitude: this.latitude + deltaLngLat[1] };
|
|
648
|
+
}
|
|
649
|
+
getBounds(options = {}) {
|
|
650
|
+
const corners = (0, import_web_mercator2.getBounds)(this, options.z || 0);
|
|
651
|
+
return [
|
|
652
|
+
Math.min(corners[0][0], corners[1][0], corners[2][0], corners[3][0]),
|
|
653
|
+
Math.min(corners[0][1], corners[1][1], corners[2][1], corners[3][1]),
|
|
654
|
+
Math.max(corners[0][0], corners[1][0], corners[2][0], corners[3][0]),
|
|
655
|
+
Math.max(corners[0][1], corners[1][1], corners[2][1], corners[3][1])
|
|
656
|
+
];
|
|
657
|
+
}
|
|
658
|
+
/**
|
|
659
|
+
* Returns a new viewport that fit around the given rectangle.
|
|
660
|
+
* Only supports non-perspective mode.
|
|
661
|
+
*/
|
|
662
|
+
fitBounds(bounds, options = {}) {
|
|
663
|
+
const { width, height } = this;
|
|
664
|
+
const { longitude, latitude, zoom } = (0, import_web_mercator2.fitBounds)({ width, height, bounds, ...options });
|
|
665
|
+
return new _WebMercatorViewport({ width, height, longitude, latitude, zoom });
|
|
666
|
+
}
|
|
667
|
+
};
|
|
668
|
+
_WebMercatorViewport.displayName = "WebMercatorViewport";
|
|
669
|
+
var WebMercatorViewport = _WebMercatorViewport;
|
|
670
|
+
|
|
671
|
+
// ../core/src/utils/deep-equal.ts
|
|
672
|
+
function deepEqual(a, b, depth) {
|
|
673
|
+
if (a === b) {
|
|
674
|
+
return true;
|
|
675
|
+
}
|
|
676
|
+
if (!depth || !a || !b) {
|
|
677
|
+
return false;
|
|
678
|
+
}
|
|
679
|
+
if (Array.isArray(a)) {
|
|
680
|
+
if (!Array.isArray(b) || a.length !== b.length) {
|
|
681
|
+
return false;
|
|
682
|
+
}
|
|
683
|
+
for (let i = 0; i < a.length; i++) {
|
|
684
|
+
if (!deepEqual(a[i], b[i], depth - 1)) {
|
|
685
|
+
return false;
|
|
686
|
+
}
|
|
687
|
+
}
|
|
688
|
+
return true;
|
|
689
|
+
}
|
|
690
|
+
if (Array.isArray(b)) {
|
|
691
|
+
return false;
|
|
692
|
+
}
|
|
693
|
+
if (typeof a === "object" && typeof b === "object") {
|
|
694
|
+
const aKeys = Object.keys(a);
|
|
695
|
+
const bKeys = Object.keys(b);
|
|
696
|
+
if (aKeys.length !== bKeys.length) {
|
|
697
|
+
return false;
|
|
698
|
+
}
|
|
699
|
+
for (const key of aKeys) {
|
|
700
|
+
if (!b.hasOwnProperty(key)) {
|
|
701
|
+
return false;
|
|
702
|
+
}
|
|
703
|
+
if (!deepEqual(a[key], b[key], depth - 1)) {
|
|
704
|
+
return false;
|
|
705
|
+
}
|
|
706
|
+
}
|
|
707
|
+
return true;
|
|
708
|
+
}
|
|
709
|
+
return false;
|
|
710
|
+
}
|
|
711
|
+
|
|
712
|
+
// ../core/src/utils/positions.ts
|
|
713
|
+
var NUMBER_REGEX = /^(?:\d+\.?\d*|\.\d+)$/;
|
|
714
|
+
function parsePosition(value) {
|
|
715
|
+
switch (typeof value) {
|
|
716
|
+
case "number":
|
|
717
|
+
if (!Number.isFinite(value)) {
|
|
718
|
+
throw new Error(`Could not parse position string ${value}`);
|
|
719
|
+
}
|
|
720
|
+
return { type: "literal", value };
|
|
721
|
+
case "string":
|
|
722
|
+
try {
|
|
723
|
+
const tokens = tokenize(value);
|
|
724
|
+
const parser = new LayoutExpressionParser(tokens);
|
|
725
|
+
return parser.parseExpression();
|
|
726
|
+
} catch (error) {
|
|
727
|
+
const reason = error instanceof Error ? error.message : String(error);
|
|
728
|
+
throw new Error(`Could not parse position string ${value}: ${reason}`);
|
|
729
|
+
}
|
|
730
|
+
default:
|
|
731
|
+
throw new Error(`Could not parse position string ${value}`);
|
|
732
|
+
}
|
|
733
|
+
}
|
|
734
|
+
function evaluateLayoutExpression(expression, extent) {
|
|
735
|
+
switch (expression.type) {
|
|
736
|
+
case "literal":
|
|
737
|
+
return expression.value;
|
|
738
|
+
case "percentage":
|
|
739
|
+
return Math.round(expression.value * extent);
|
|
740
|
+
case "binary":
|
|
741
|
+
const left = evaluateLayoutExpression(expression.left, extent);
|
|
742
|
+
const right = evaluateLayoutExpression(expression.right, extent);
|
|
743
|
+
return expression.operator === "+" ? left + right : left - right;
|
|
744
|
+
default:
|
|
745
|
+
throw new Error("Unknown layout expression type");
|
|
746
|
+
}
|
|
747
|
+
}
|
|
748
|
+
function getPosition(expression, extent) {
|
|
749
|
+
return evaluateLayoutExpression(expression, extent);
|
|
750
|
+
}
|
|
751
|
+
function tokenize(input) {
|
|
752
|
+
const tokens = [];
|
|
753
|
+
let index = 0;
|
|
754
|
+
while (index < input.length) {
|
|
755
|
+
const char = input[index];
|
|
756
|
+
if (/\s/.test(char)) {
|
|
757
|
+
index++;
|
|
758
|
+
continue;
|
|
759
|
+
}
|
|
760
|
+
if (char === "+" || char === "-" || char === "(" || char === ")" || char === "%") {
|
|
761
|
+
tokens.push({ type: "symbol", value: char });
|
|
762
|
+
index++;
|
|
763
|
+
continue;
|
|
764
|
+
}
|
|
765
|
+
if (isDigit(char) || char === ".") {
|
|
766
|
+
const start = index;
|
|
767
|
+
let hasDecimal = char === ".";
|
|
768
|
+
index++;
|
|
769
|
+
while (index < input.length) {
|
|
770
|
+
const next = input[index];
|
|
771
|
+
if (isDigit(next)) {
|
|
772
|
+
index++;
|
|
773
|
+
continue;
|
|
774
|
+
}
|
|
775
|
+
if (next === "." && !hasDecimal) {
|
|
776
|
+
hasDecimal = true;
|
|
777
|
+
index++;
|
|
778
|
+
continue;
|
|
779
|
+
}
|
|
780
|
+
break;
|
|
781
|
+
}
|
|
782
|
+
const numberString = input.slice(start, index);
|
|
783
|
+
if (!NUMBER_REGEX.test(numberString)) {
|
|
784
|
+
throw new Error("Invalid number token");
|
|
785
|
+
}
|
|
786
|
+
tokens.push({ type: "number", value: parseFloat(numberString) });
|
|
787
|
+
continue;
|
|
788
|
+
}
|
|
789
|
+
if (isAlpha(char)) {
|
|
790
|
+
const start = index;
|
|
791
|
+
while (index < input.length && isAlpha(input[index])) {
|
|
792
|
+
index++;
|
|
793
|
+
}
|
|
794
|
+
const word = input.slice(start, index).toLowerCase();
|
|
795
|
+
tokens.push({ type: "word", value: word });
|
|
796
|
+
continue;
|
|
797
|
+
}
|
|
798
|
+
throw new Error("Invalid token in position string");
|
|
799
|
+
}
|
|
800
|
+
return tokens;
|
|
801
|
+
}
|
|
802
|
+
var LayoutExpressionParser = class {
|
|
803
|
+
constructor(tokens) {
|
|
804
|
+
this.index = 0;
|
|
805
|
+
this.tokens = tokens;
|
|
806
|
+
}
|
|
807
|
+
parseExpression() {
|
|
808
|
+
const expression = this.parseBinaryExpression();
|
|
809
|
+
if (this.index < this.tokens.length) {
|
|
810
|
+
throw new Error("Unexpected token at end of expression");
|
|
811
|
+
}
|
|
812
|
+
return expression;
|
|
813
|
+
}
|
|
814
|
+
parseBinaryExpression() {
|
|
815
|
+
let expression = this.parseFactor();
|
|
816
|
+
let token = this.peek();
|
|
817
|
+
while (isAddSubSymbol(token)) {
|
|
818
|
+
this.index++;
|
|
819
|
+
const right = this.parseFactor();
|
|
820
|
+
expression = { type: "binary", operator: token.value, left: expression, right };
|
|
821
|
+
token = this.peek();
|
|
822
|
+
}
|
|
823
|
+
return expression;
|
|
824
|
+
}
|
|
825
|
+
parseFactor() {
|
|
826
|
+
const token = this.peek();
|
|
827
|
+
if (!token) {
|
|
828
|
+
throw new Error("Unexpected end of expression");
|
|
829
|
+
}
|
|
830
|
+
if (token.type === "symbol" && token.value === "+") {
|
|
831
|
+
this.index++;
|
|
832
|
+
return this.parseFactor();
|
|
833
|
+
}
|
|
834
|
+
if (token.type === "symbol" && token.value === "-") {
|
|
835
|
+
this.index++;
|
|
836
|
+
const factor = this.parseFactor();
|
|
837
|
+
return { type: "binary", operator: "-", left: { type: "literal", value: 0 }, right: factor };
|
|
838
|
+
}
|
|
839
|
+
if (token.type === "symbol" && token.value === "(") {
|
|
840
|
+
this.index++;
|
|
841
|
+
const expression = this.parseBinaryExpression();
|
|
842
|
+
if (!this.consumeSymbol(")")) {
|
|
843
|
+
throw new Error("Missing closing parenthesis");
|
|
844
|
+
}
|
|
845
|
+
return expression;
|
|
846
|
+
}
|
|
847
|
+
if (token.type === "word" && token.value === "calc") {
|
|
848
|
+
this.index++;
|
|
849
|
+
if (!this.consumeSymbol("(")) {
|
|
850
|
+
throw new Error("Missing opening parenthesis after calc");
|
|
851
|
+
}
|
|
852
|
+
const expression = this.parseBinaryExpression();
|
|
853
|
+
if (!this.consumeSymbol(")")) {
|
|
854
|
+
throw new Error("Missing closing parenthesis");
|
|
855
|
+
}
|
|
856
|
+
return expression;
|
|
857
|
+
}
|
|
858
|
+
if (token.type === "number") {
|
|
859
|
+
this.index++;
|
|
860
|
+
const numberValue = token.value;
|
|
861
|
+
const nextToken = this.peek();
|
|
862
|
+
if (nextToken && nextToken.type === "symbol" && nextToken.value === "%") {
|
|
863
|
+
this.index++;
|
|
864
|
+
return { type: "percentage", value: numberValue / 100 };
|
|
865
|
+
}
|
|
866
|
+
if (nextToken && nextToken.type === "word" && nextToken.value === "px") {
|
|
867
|
+
this.index++;
|
|
868
|
+
return { type: "literal", value: numberValue };
|
|
869
|
+
}
|
|
870
|
+
return { type: "literal", value: numberValue };
|
|
871
|
+
}
|
|
872
|
+
throw new Error("Unexpected token in expression");
|
|
873
|
+
}
|
|
874
|
+
consumeSymbol(value) {
|
|
875
|
+
const token = this.peek();
|
|
876
|
+
if (token && token.type === "symbol" && token.value === value) {
|
|
877
|
+
this.index++;
|
|
878
|
+
return true;
|
|
879
|
+
}
|
|
880
|
+
return false;
|
|
881
|
+
}
|
|
882
|
+
peek() {
|
|
883
|
+
return this.tokens[this.index] || null;
|
|
884
|
+
}
|
|
885
|
+
};
|
|
886
|
+
function isDigit(char) {
|
|
887
|
+
return char >= "0" && char <= "9";
|
|
888
|
+
}
|
|
889
|
+
function isAlpha(char) {
|
|
890
|
+
return char >= "a" && char <= "z" || char >= "A" && char <= "Z";
|
|
891
|
+
}
|
|
892
|
+
function isAddSubSymbol(token) {
|
|
893
|
+
return Boolean(token && token.type === "symbol" && (token.value === "+" || token.value === "-"));
|
|
894
|
+
}
|
|
895
|
+
|
|
896
|
+
// ../core/src/utils/deep-merge.ts
|
|
897
|
+
function deepMergeViewState(a, b) {
|
|
898
|
+
const result = { ...a };
|
|
899
|
+
for (const key in b) {
|
|
900
|
+
if (key === "id") continue;
|
|
901
|
+
if (Array.isArray(result[key]) && Array.isArray(b[key])) {
|
|
902
|
+
result[key] = mergeNumericArray(result[key], b[key]);
|
|
903
|
+
} else {
|
|
904
|
+
result[key] = b[key];
|
|
905
|
+
}
|
|
906
|
+
}
|
|
907
|
+
return result;
|
|
908
|
+
}
|
|
909
|
+
function mergeNumericArray(target, source) {
|
|
910
|
+
target = target.slice();
|
|
911
|
+
for (let i = 0; i < source.length; i++) {
|
|
912
|
+
const v = source[i];
|
|
913
|
+
if (Number.isFinite(v)) {
|
|
914
|
+
target[i] = v;
|
|
915
|
+
}
|
|
916
|
+
}
|
|
917
|
+
return target;
|
|
918
|
+
}
|
|
919
|
+
|
|
920
|
+
// ../core/src/views/view.ts
|
|
921
|
+
var View = class {
|
|
922
|
+
constructor(props) {
|
|
923
|
+
const { id, x = 0, y = 0, width = "100%", height = "100%", padding = null } = props;
|
|
924
|
+
this.id = id || this.constructor.displayName || "view";
|
|
925
|
+
this.props = { ...props, id: this.id };
|
|
926
|
+
this._x = parsePosition(x);
|
|
927
|
+
this._y = parsePosition(y);
|
|
928
|
+
this._width = parsePosition(width);
|
|
929
|
+
this._height = parsePosition(height);
|
|
930
|
+
this._padding = padding && {
|
|
931
|
+
left: parsePosition(padding.left || 0),
|
|
932
|
+
right: parsePosition(padding.right || 0),
|
|
933
|
+
top: parsePosition(padding.top || 0),
|
|
934
|
+
bottom: parsePosition(padding.bottom || 0)
|
|
935
|
+
};
|
|
936
|
+
this.equals = this.equals.bind(this);
|
|
937
|
+
Object.seal(this);
|
|
938
|
+
}
|
|
939
|
+
equals(view) {
|
|
940
|
+
if (this === view) {
|
|
941
|
+
return true;
|
|
942
|
+
}
|
|
943
|
+
return this.constructor === view.constructor && deepEqual(this.props, view.props, 2);
|
|
944
|
+
}
|
|
945
|
+
/** Clone this view with modified props */
|
|
946
|
+
clone(newProps) {
|
|
947
|
+
const ViewConstructor = this.constructor;
|
|
948
|
+
return new ViewConstructor({ ...this.props, ...newProps });
|
|
949
|
+
}
|
|
950
|
+
/** Make viewport from canvas dimensions and view state */
|
|
951
|
+
makeViewport({ width, height, viewState }) {
|
|
952
|
+
viewState = this.filterViewState(viewState);
|
|
953
|
+
const viewportDimensions = this.getDimensions({ width, height });
|
|
954
|
+
if (!viewportDimensions.height || !viewportDimensions.width) {
|
|
955
|
+
return null;
|
|
956
|
+
}
|
|
957
|
+
const ViewportType = this.getViewportType(viewState);
|
|
958
|
+
return new ViewportType({ ...viewState, ...this.props, ...viewportDimensions });
|
|
959
|
+
}
|
|
960
|
+
getViewStateId() {
|
|
961
|
+
const { viewState } = this.props;
|
|
962
|
+
if (typeof viewState === "string") {
|
|
963
|
+
return viewState;
|
|
964
|
+
}
|
|
965
|
+
return (viewState == null ? void 0 : viewState.id) || this.id;
|
|
966
|
+
}
|
|
967
|
+
// Allows view to override (or completely define) viewState
|
|
968
|
+
filterViewState(viewState) {
|
|
969
|
+
if (this.props.viewState && typeof this.props.viewState === "object") {
|
|
970
|
+
if (!this.props.viewState.id) {
|
|
971
|
+
return this.props.viewState;
|
|
972
|
+
}
|
|
973
|
+
return deepMergeViewState(viewState, this.props.viewState);
|
|
974
|
+
}
|
|
975
|
+
return viewState;
|
|
976
|
+
}
|
|
977
|
+
/** Resolve the dimensions of the view from overall canvas dimensions */
|
|
978
|
+
getDimensions({ width, height }) {
|
|
979
|
+
const dimensions = {
|
|
980
|
+
x: getPosition(this._x, width),
|
|
981
|
+
y: getPosition(this._y, height),
|
|
982
|
+
width: getPosition(this._width, width),
|
|
983
|
+
height: getPosition(this._height, height)
|
|
984
|
+
};
|
|
985
|
+
if (this._padding) {
|
|
986
|
+
dimensions.padding = {
|
|
987
|
+
left: getPosition(this._padding.left, width),
|
|
988
|
+
top: getPosition(this._padding.top, height),
|
|
989
|
+
right: getPosition(this._padding.right, width),
|
|
990
|
+
bottom: getPosition(this._padding.bottom, height)
|
|
991
|
+
};
|
|
992
|
+
}
|
|
993
|
+
return dimensions;
|
|
994
|
+
}
|
|
995
|
+
// Used by sub classes to resolve controller props
|
|
996
|
+
get controller() {
|
|
997
|
+
const opts = this.props.controller;
|
|
998
|
+
if (!opts) {
|
|
999
|
+
return null;
|
|
1000
|
+
}
|
|
1001
|
+
if (opts === true) {
|
|
1002
|
+
return { type: this.ControllerType };
|
|
1003
|
+
}
|
|
1004
|
+
if (typeof opts === "function") {
|
|
1005
|
+
return { type: opts };
|
|
1006
|
+
}
|
|
1007
|
+
return { type: this.ControllerType, ...opts };
|
|
1008
|
+
}
|
|
1009
|
+
};
|
|
1010
|
+
|
|
1011
|
+
// ../core/src/transitions/transition.ts
|
|
1012
|
+
var Transition = class {
|
|
1013
|
+
/**
|
|
1014
|
+
* @params timeline {Timeline}
|
|
1015
|
+
*/
|
|
1016
|
+
constructor(timeline) {
|
|
1017
|
+
this._inProgress = false;
|
|
1018
|
+
this._handle = null;
|
|
1019
|
+
this.time = 0;
|
|
1020
|
+
// @ts-expect-error
|
|
1021
|
+
this.settings = {
|
|
1022
|
+
duration: 0
|
|
1023
|
+
};
|
|
1024
|
+
this._timeline = timeline;
|
|
1025
|
+
}
|
|
1026
|
+
/* Public API */
|
|
1027
|
+
get inProgress() {
|
|
1028
|
+
return this._inProgress;
|
|
1029
|
+
}
|
|
1030
|
+
/**
|
|
1031
|
+
* (re)start this transition.
|
|
1032
|
+
* @params props {object} - optional overriding props. see constructor
|
|
1033
|
+
*/
|
|
1034
|
+
start(settings) {
|
|
1035
|
+
var _a, _b;
|
|
1036
|
+
this.cancel();
|
|
1037
|
+
this.settings = settings;
|
|
1038
|
+
this._inProgress = true;
|
|
1039
|
+
(_b = (_a = this.settings).onStart) == null ? void 0 : _b.call(_a, this);
|
|
1040
|
+
}
|
|
1041
|
+
/**
|
|
1042
|
+
* end this transition if it is in progress.
|
|
1043
|
+
*/
|
|
1044
|
+
end() {
|
|
1045
|
+
var _a, _b;
|
|
1046
|
+
if (this._inProgress) {
|
|
1047
|
+
this._timeline.removeChannel(this._handle);
|
|
1048
|
+
this._handle = null;
|
|
1049
|
+
this._inProgress = false;
|
|
1050
|
+
(_b = (_a = this.settings).onEnd) == null ? void 0 : _b.call(_a, this);
|
|
1051
|
+
}
|
|
1052
|
+
}
|
|
1053
|
+
/**
|
|
1054
|
+
* cancel this transition if it is in progress.
|
|
1055
|
+
*/
|
|
1056
|
+
cancel() {
|
|
1057
|
+
var _a, _b;
|
|
1058
|
+
if (this._inProgress) {
|
|
1059
|
+
(_b = (_a = this.settings).onInterrupt) == null ? void 0 : _b.call(_a, this);
|
|
1060
|
+
this._timeline.removeChannel(this._handle);
|
|
1061
|
+
this._handle = null;
|
|
1062
|
+
this._inProgress = false;
|
|
1063
|
+
}
|
|
1064
|
+
}
|
|
1065
|
+
/**
|
|
1066
|
+
* update this transition. Returns `true` if updated.
|
|
1067
|
+
*/
|
|
1068
|
+
update() {
|
|
1069
|
+
var _a, _b;
|
|
1070
|
+
if (!this._inProgress) {
|
|
1071
|
+
return false;
|
|
1072
|
+
}
|
|
1073
|
+
if (this._handle === null) {
|
|
1074
|
+
const { _timeline: timeline, settings } = this;
|
|
1075
|
+
this._handle = timeline.addChannel({
|
|
1076
|
+
delay: timeline.getTime(),
|
|
1077
|
+
duration: settings.duration
|
|
1078
|
+
});
|
|
1079
|
+
}
|
|
1080
|
+
this.time = this._timeline.getTime(this._handle);
|
|
1081
|
+
this._onUpdate();
|
|
1082
|
+
(_b = (_a = this.settings).onUpdate) == null ? void 0 : _b.call(_a, this);
|
|
1083
|
+
if (this._timeline.isFinished(this._handle)) {
|
|
1084
|
+
this.end();
|
|
1085
|
+
}
|
|
1086
|
+
return true;
|
|
1087
|
+
}
|
|
1088
|
+
/* Private API */
|
|
1089
|
+
_onUpdate() {
|
|
1090
|
+
}
|
|
1091
|
+
};
|
|
1092
|
+
|
|
1093
|
+
// ../core/src/controllers/transition-manager.ts
|
|
1094
|
+
var noop = () => {
|
|
1095
|
+
};
|
|
1096
|
+
var PRESERVE_CONSTRAINT_CONTEXT = { mode: "preserve" };
|
|
1097
|
+
var HARD_CONSTRAINT_CONTEXT = { mode: "hard" };
|
|
1098
|
+
var TRANSITION_EVENTS = {
|
|
1099
|
+
BREAK: 1,
|
|
1100
|
+
SNAP_TO_END: 2,
|
|
1101
|
+
IGNORE: 3
|
|
1102
|
+
};
|
|
1103
|
+
var DEFAULT_EASING = (t) => t;
|
|
1104
|
+
var DEFAULT_INTERRUPTION = TRANSITION_EVENTS.BREAK;
|
|
1105
|
+
var TransitionManager = class {
|
|
1106
|
+
constructor(opts) {
|
|
1107
|
+
this._onTransitionUpdate = (transition) => {
|
|
1108
|
+
const {
|
|
1109
|
+
time,
|
|
1110
|
+
settings: { interpolator, startProps, endProps, duration, easing }
|
|
1111
|
+
} = transition;
|
|
1112
|
+
const t = easing(time / duration);
|
|
1113
|
+
const viewport = interpolator.interpolateProps(startProps, endProps, t);
|
|
1114
|
+
this.propsInTransition = this.getControllerState(
|
|
1115
|
+
{
|
|
1116
|
+
...this.props,
|
|
1117
|
+
...viewport
|
|
1118
|
+
},
|
|
1119
|
+
PRESERVE_CONSTRAINT_CONTEXT
|
|
1120
|
+
).getViewportProps();
|
|
1121
|
+
this.onViewStateChange({
|
|
1122
|
+
viewState: this.propsInTransition,
|
|
1123
|
+
oldViewState: this.props
|
|
1124
|
+
});
|
|
1125
|
+
};
|
|
1126
|
+
this.getControllerState = opts.getControllerState;
|
|
1127
|
+
this.propsInTransition = null;
|
|
1128
|
+
this.transition = new Transition(opts.timeline);
|
|
1129
|
+
this.onViewStateChange = opts.onViewStateChange || noop;
|
|
1130
|
+
this.onStateChange = opts.onStateChange || noop;
|
|
1131
|
+
}
|
|
1132
|
+
finalize() {
|
|
1133
|
+
this.transition.cancel();
|
|
1134
|
+
}
|
|
1135
|
+
// Returns current transitioned viewport.
|
|
1136
|
+
getViewportInTransition() {
|
|
1137
|
+
return this.propsInTransition;
|
|
1138
|
+
}
|
|
1139
|
+
// Process the vewiport change, either ignore or trigger a new transition.
|
|
1140
|
+
// Return true if a new transition is triggered, false otherwise.
|
|
1141
|
+
processViewStateChange(nextProps) {
|
|
1142
|
+
let transitionTriggered = false;
|
|
1143
|
+
const currentProps = this.props;
|
|
1144
|
+
this.props = nextProps;
|
|
1145
|
+
if (!currentProps || this._shouldIgnoreViewportChange(currentProps, nextProps)) {
|
|
1146
|
+
return false;
|
|
1147
|
+
}
|
|
1148
|
+
if (this._isTransitionEnabled(nextProps)) {
|
|
1149
|
+
let startProps = currentProps;
|
|
1150
|
+
if (this.transition.inProgress) {
|
|
1151
|
+
const { interruption, endProps } = this.transition.settings;
|
|
1152
|
+
startProps = {
|
|
1153
|
+
...currentProps,
|
|
1154
|
+
...interruption === TRANSITION_EVENTS.SNAP_TO_END ? endProps : this.propsInTransition || currentProps
|
|
1155
|
+
};
|
|
1156
|
+
}
|
|
1157
|
+
this._triggerTransition(startProps, nextProps);
|
|
1158
|
+
transitionTriggered = true;
|
|
1159
|
+
} else {
|
|
1160
|
+
this.transition.cancel();
|
|
1161
|
+
}
|
|
1162
|
+
return transitionTriggered;
|
|
1163
|
+
}
|
|
1164
|
+
updateTransition() {
|
|
1165
|
+
this.transition.update();
|
|
1166
|
+
}
|
|
1167
|
+
// Helper methods
|
|
1168
|
+
_isTransitionEnabled(props) {
|
|
1169
|
+
const { transitionDuration, transitionInterpolator } = props;
|
|
1170
|
+
return (transitionDuration > 0 || transitionDuration === "auto") && Boolean(transitionInterpolator);
|
|
1171
|
+
}
|
|
1172
|
+
_isUpdateDueToCurrentTransition(props) {
|
|
1173
|
+
if (this.transition.inProgress && this.propsInTransition) {
|
|
1174
|
+
return this.transition.settings.interpolator.arePropsEqual(
|
|
1175
|
+
props,
|
|
1176
|
+
this.propsInTransition
|
|
1177
|
+
);
|
|
1178
|
+
}
|
|
1179
|
+
return false;
|
|
1180
|
+
}
|
|
1181
|
+
_shouldIgnoreViewportChange(currentProps, nextProps) {
|
|
1182
|
+
if (this.transition.inProgress) {
|
|
1183
|
+
const transitionSettings = this.transition.settings;
|
|
1184
|
+
return transitionSettings.interruption === TRANSITION_EVENTS.IGNORE || // Ignore update if it is due to current active transition.
|
|
1185
|
+
this._isUpdateDueToCurrentTransition(nextProps);
|
|
1186
|
+
}
|
|
1187
|
+
if (this._isTransitionEnabled(nextProps)) {
|
|
1188
|
+
return nextProps.transitionInterpolator.arePropsEqual(
|
|
1189
|
+
currentProps,
|
|
1190
|
+
nextProps
|
|
1191
|
+
);
|
|
1192
|
+
}
|
|
1193
|
+
return true;
|
|
1194
|
+
}
|
|
1195
|
+
_triggerTransition(startProps, endProps) {
|
|
1196
|
+
const startViewstate = this.getControllerState(startProps, PRESERVE_CONSTRAINT_CONTEXT);
|
|
1197
|
+
const endViewStateProps = this.getControllerState(
|
|
1198
|
+
endProps,
|
|
1199
|
+
HARD_CONSTRAINT_CONTEXT
|
|
1200
|
+
).shortestPathFrom(startViewstate);
|
|
1201
|
+
const transitionInterpolator = endProps.transitionInterpolator;
|
|
1202
|
+
const duration = transitionInterpolator.getDuration ? transitionInterpolator.getDuration(startProps, endProps) : endProps.transitionDuration;
|
|
1203
|
+
if (duration === 0) {
|
|
1204
|
+
return;
|
|
1205
|
+
}
|
|
1206
|
+
const initialProps = transitionInterpolator.initializeProps(startProps, endViewStateProps);
|
|
1207
|
+
this.propsInTransition = {};
|
|
1208
|
+
const transitionSettings = {
|
|
1209
|
+
duration,
|
|
1210
|
+
easing: endProps.transitionEasing || DEFAULT_EASING,
|
|
1211
|
+
interpolator: transitionInterpolator,
|
|
1212
|
+
interruption: endProps.transitionInterruption || DEFAULT_INTERRUPTION,
|
|
1213
|
+
startProps: initialProps.start,
|
|
1214
|
+
endProps: initialProps.end,
|
|
1215
|
+
onStart: endProps.onTransitionStart,
|
|
1216
|
+
onUpdate: this._onTransitionUpdate,
|
|
1217
|
+
onInterrupt: this._onTransitionEnd(endProps.onTransitionInterrupt),
|
|
1218
|
+
onEnd: this._onTransitionEnd(endProps.onTransitionEnd)
|
|
1219
|
+
};
|
|
1220
|
+
this.transition.start(transitionSettings);
|
|
1221
|
+
this.onStateChange({ inTransition: true });
|
|
1222
|
+
this.updateTransition();
|
|
1223
|
+
}
|
|
1224
|
+
_onTransitionEnd(callback) {
|
|
1225
|
+
return (transition) => {
|
|
1226
|
+
this.propsInTransition = null;
|
|
1227
|
+
this.onStateChange({
|
|
1228
|
+
inTransition: false,
|
|
1229
|
+
isZooming: false,
|
|
1230
|
+
isPanning: false,
|
|
1231
|
+
isRotating: false
|
|
1232
|
+
});
|
|
1233
|
+
callback == null ? void 0 : callback(transition);
|
|
1234
|
+
};
|
|
1235
|
+
}
|
|
1236
|
+
};
|
|
1237
|
+
|
|
1238
|
+
// ../core/src/transitions/transition-interpolator.ts
|
|
1239
|
+
var import_core4 = require("@math.gl/core");
|
|
1240
|
+
|
|
1241
|
+
// ../core/src/utils/assert.ts
|
|
1242
|
+
function assert(condition, message) {
|
|
1243
|
+
if (!condition) {
|
|
1244
|
+
throw new Error(message || "deck.gl: assertion failed.");
|
|
1245
|
+
}
|
|
1246
|
+
}
|
|
1247
|
+
|
|
1248
|
+
// ../core/src/transitions/transition-interpolator.ts
|
|
1249
|
+
var TransitionInterpolator = class {
|
|
1250
|
+
/**
|
|
1251
|
+
* @param opts {array|object}
|
|
1252
|
+
* @param opts.compare {array} - prop names used in equality check
|
|
1253
|
+
* @param opts.extract {array} - prop names needed for interpolation
|
|
1254
|
+
* @param opts.required {array} - prop names that must be supplied
|
|
1255
|
+
* alternatively, supply one list of prop names as `opts` if all of the above are the same.
|
|
1256
|
+
*/
|
|
1257
|
+
constructor(opts) {
|
|
1258
|
+
const { compare, extract, required } = opts;
|
|
1259
|
+
this._propsToCompare = compare;
|
|
1260
|
+
this._propsToExtract = extract || compare;
|
|
1261
|
+
this._requiredProps = required;
|
|
1262
|
+
}
|
|
1263
|
+
/**
|
|
1264
|
+
* Checks if two sets of props need transition in between
|
|
1265
|
+
* @param currentProps {object} - a list of viewport props
|
|
1266
|
+
* @param nextProps {object} - a list of viewport props
|
|
1267
|
+
* @returns {bool} - true if two props are equivalent
|
|
1268
|
+
*/
|
|
1269
|
+
arePropsEqual(currentProps, nextProps) {
|
|
1270
|
+
for (const key of this._propsToCompare) {
|
|
1271
|
+
if (!(key in currentProps) || !(key in nextProps) || !(0, import_core4.equals)(currentProps[key], nextProps[key])) {
|
|
1272
|
+
return false;
|
|
1273
|
+
}
|
|
1274
|
+
}
|
|
1275
|
+
return true;
|
|
1276
|
+
}
|
|
1277
|
+
/**
|
|
1278
|
+
* Called before transition starts to validate/pre-process start and end props
|
|
1279
|
+
* @param startProps {object} - a list of starting viewport props
|
|
1280
|
+
* @param endProps {object} - a list of target viewport props
|
|
1281
|
+
* @returns {Object} {start, end} - start and end props to be passed
|
|
1282
|
+
* to `interpolateProps`
|
|
1283
|
+
*/
|
|
1284
|
+
initializeProps(startProps, endProps) {
|
|
1285
|
+
const startViewStateProps = {};
|
|
1286
|
+
const endViewStateProps = {};
|
|
1287
|
+
for (const key of this._propsToExtract) {
|
|
1288
|
+
if (key in startProps || key in endProps) {
|
|
1289
|
+
startViewStateProps[key] = startProps[key];
|
|
1290
|
+
endViewStateProps[key] = endProps[key];
|
|
1291
|
+
}
|
|
1292
|
+
}
|
|
1293
|
+
this._checkRequiredProps(startViewStateProps);
|
|
1294
|
+
this._checkRequiredProps(endViewStateProps);
|
|
1295
|
+
return { start: startViewStateProps, end: endViewStateProps };
|
|
1296
|
+
}
|
|
1297
|
+
/**
|
|
1298
|
+
* Returns transition duration
|
|
1299
|
+
* @param startProps {object} - a list of starting viewport props
|
|
1300
|
+
* @param endProps {object} - a list of target viewport props
|
|
1301
|
+
* @returns {Number} - transition duration in milliseconds
|
|
1302
|
+
*/
|
|
1303
|
+
getDuration(startProps, endProps) {
|
|
1304
|
+
return endProps.transitionDuration;
|
|
1305
|
+
}
|
|
1306
|
+
_checkRequiredProps(props) {
|
|
1307
|
+
if (!this._requiredProps) {
|
|
1308
|
+
return;
|
|
1309
|
+
}
|
|
1310
|
+
this._requiredProps.forEach((propName) => {
|
|
1311
|
+
const value = props[propName];
|
|
1312
|
+
assert(
|
|
1313
|
+
Number.isFinite(value) || Array.isArray(value),
|
|
1314
|
+
`${propName} is required for transition`
|
|
1315
|
+
);
|
|
1316
|
+
});
|
|
1317
|
+
}
|
|
1318
|
+
};
|
|
1319
|
+
|
|
1320
|
+
// ../core/src/transitions/linear-interpolator.ts
|
|
1321
|
+
var import_core5 = require("@math.gl/core");
|
|
1322
|
+
var DEFAULT_PROPS = ["longitude", "latitude", "zoom", "bearing", "pitch"];
|
|
1323
|
+
var DEFAULT_REQUIRED_PROPS = ["longitude", "latitude", "zoom"];
|
|
1324
|
+
var LinearInterpolator = class extends TransitionInterpolator {
|
|
1325
|
+
/**
|
|
1326
|
+
* @param {Object} opts
|
|
1327
|
+
* @param {Array} opts.transitionProps - list of props to apply linear transition to.
|
|
1328
|
+
* @param {Array} opts.around - a screen point to zoom/rotate around.
|
|
1329
|
+
* @param {Function} opts.makeViewport - construct a viewport instance with given props.
|
|
1330
|
+
*/
|
|
1331
|
+
constructor(opts = {}) {
|
|
1332
|
+
const transitionProps = Array.isArray(opts) ? opts : opts.transitionProps;
|
|
1333
|
+
const normalizedOpts = Array.isArray(opts) ? {} : opts;
|
|
1334
|
+
normalizedOpts.transitionProps = Array.isArray(transitionProps) ? {
|
|
1335
|
+
compare: transitionProps,
|
|
1336
|
+
required: transitionProps
|
|
1337
|
+
} : transitionProps || {
|
|
1338
|
+
compare: DEFAULT_PROPS,
|
|
1339
|
+
required: DEFAULT_REQUIRED_PROPS
|
|
1340
|
+
};
|
|
1341
|
+
super(normalizedOpts.transitionProps);
|
|
1342
|
+
this.opts = normalizedOpts;
|
|
1343
|
+
}
|
|
1344
|
+
initializeProps(startProps, endProps) {
|
|
1345
|
+
const result = super.initializeProps(startProps, endProps);
|
|
1346
|
+
const { makeViewport, around } = this.opts;
|
|
1347
|
+
if (makeViewport && around) {
|
|
1348
|
+
const startViewport = makeViewport(startProps);
|
|
1349
|
+
const endViewport = makeViewport(endProps);
|
|
1350
|
+
const aroundPosition = startViewport.unproject(around);
|
|
1351
|
+
result.start.around = around;
|
|
1352
|
+
Object.assign(result.end, {
|
|
1353
|
+
around: endViewport.project(aroundPosition),
|
|
1354
|
+
aroundPosition,
|
|
1355
|
+
width: endProps.width,
|
|
1356
|
+
height: endProps.height
|
|
1357
|
+
});
|
|
1358
|
+
}
|
|
1359
|
+
return result;
|
|
1360
|
+
}
|
|
1361
|
+
interpolateProps(startProps, endProps, t) {
|
|
1362
|
+
const propsInTransition = {};
|
|
1363
|
+
for (const key of this._propsToExtract) {
|
|
1364
|
+
propsInTransition[key] = (0, import_core5.lerp)(startProps[key] || 0, endProps[key] || 0, t);
|
|
1365
|
+
}
|
|
1366
|
+
if (endProps.aroundPosition && this.opts.makeViewport) {
|
|
1367
|
+
const viewport = this.opts.makeViewport({ ...endProps, ...propsInTransition });
|
|
1368
|
+
Object.assign(
|
|
1369
|
+
propsInTransition,
|
|
1370
|
+
viewport.panByPosition(
|
|
1371
|
+
endProps.aroundPosition,
|
|
1372
|
+
// anchor point in current screen coordinates
|
|
1373
|
+
(0, import_core5.lerp)(startProps.around, endProps.around, t)
|
|
1374
|
+
)
|
|
1375
|
+
);
|
|
1376
|
+
}
|
|
1377
|
+
return propsInTransition;
|
|
1378
|
+
}
|
|
1379
|
+
};
|
|
1380
|
+
|
|
1381
|
+
// ../core/src/controllers/controller.ts
|
|
1382
|
+
var import_web_mercator3 = require("@math.gl/web-mercator");
|
|
1383
|
+
var NO_TRANSITION_PROPS = {
|
|
1384
|
+
transitionDuration: 0
|
|
1385
|
+
};
|
|
1386
|
+
var DEFAULT_INERTIA = 300;
|
|
1387
|
+
var REBOUND_DURATION = 300;
|
|
1388
|
+
var INERTIA_EASING = (t) => 1 - (1 - t) * (1 - t);
|
|
1389
|
+
var EASE_OUT_EXPONENTIAL = (t) => t === 1 ? 1 : 1 - Math.pow(2, -10 * t);
|
|
1390
|
+
var EVENT_TYPES = {
|
|
1391
|
+
WHEEL: ["wheel"],
|
|
1392
|
+
PAN: ["panstart", "panmove", "panend"],
|
|
1393
|
+
PINCH: ["pinchstart", "pinchmove", "pinchend"],
|
|
1394
|
+
MULTI_PAN: ["multipanstart", "multipanmove", "multipanend"],
|
|
1395
|
+
DOUBLE_CLICK: ["dblclick"],
|
|
1396
|
+
DOUBLE_CLICK_DRAG: [
|
|
1397
|
+
"dblclickdragstart",
|
|
1398
|
+
"dblclickdragmove",
|
|
1399
|
+
"dblclickdragend",
|
|
1400
|
+
"dblclickdragcancel"
|
|
1401
|
+
],
|
|
1402
|
+
KEYBOARD: ["keydown"]
|
|
1403
|
+
};
|
|
1404
|
+
var pinchEventWorkaround = {};
|
|
1405
|
+
var Controller = class {
|
|
1406
|
+
constructor(opts) {
|
|
1407
|
+
this.state = {};
|
|
1408
|
+
this._events = {};
|
|
1409
|
+
this._interactionState = {
|
|
1410
|
+
isDragging: false
|
|
1411
|
+
};
|
|
1412
|
+
this._customEvents = [];
|
|
1413
|
+
this._eventStartBlocked = null;
|
|
1414
|
+
this._panMove = false;
|
|
1415
|
+
this._multiPanMode = null;
|
|
1416
|
+
this._multiPanStartCenter = null;
|
|
1417
|
+
this._doubleClickDragAnchor = null;
|
|
1418
|
+
this._suppressDoubleClickUntil = 0;
|
|
1419
|
+
this.invertPan = false;
|
|
1420
|
+
this.dragMode = "rotate";
|
|
1421
|
+
this.inertia = 0;
|
|
1422
|
+
this.scrollZoom = true;
|
|
1423
|
+
this.dragPan = true;
|
|
1424
|
+
this.dragRotate = true;
|
|
1425
|
+
this.doubleClickZoom = true;
|
|
1426
|
+
this.doubleClickDragZoom = true;
|
|
1427
|
+
this.touchZoom = true;
|
|
1428
|
+
this.touchRotate = false;
|
|
1429
|
+
this.multiTouchDrag = null;
|
|
1430
|
+
this.trackpadGesture = false;
|
|
1431
|
+
this.zoomAround = "pointer";
|
|
1432
|
+
this.keyboard = true;
|
|
1433
|
+
this.transitionManager = new TransitionManager({
|
|
1434
|
+
...opts,
|
|
1435
|
+
getControllerState: (props, constraintContext) => new this.ControllerState({
|
|
1436
|
+
...props,
|
|
1437
|
+
constraintContext,
|
|
1438
|
+
makeViewport: opts.makeViewport
|
|
1439
|
+
}),
|
|
1440
|
+
onViewStateChange: this._onTransition.bind(this),
|
|
1441
|
+
onStateChange: this._setInteractionState.bind(this)
|
|
1442
|
+
});
|
|
1443
|
+
this.handleEvent = this.handleEvent.bind(this);
|
|
1444
|
+
this.eventManager = opts.eventManager;
|
|
1445
|
+
this.onViewStateChange = opts.onViewStateChange || (() => {
|
|
1446
|
+
});
|
|
1447
|
+
this.onStateChange = opts.onStateChange || (() => {
|
|
1448
|
+
});
|
|
1449
|
+
this.makeViewport = opts.makeViewport;
|
|
1450
|
+
this.pickPosition = opts.pickPosition;
|
|
1451
|
+
}
|
|
1452
|
+
set events(customEvents) {
|
|
1453
|
+
this.toggleEvents(this._customEvents, false);
|
|
1454
|
+
this.toggleEvents(customEvents, true);
|
|
1455
|
+
this._customEvents = customEvents;
|
|
1456
|
+
if (this.props) {
|
|
1457
|
+
this.setProps(this.props);
|
|
1458
|
+
}
|
|
1459
|
+
}
|
|
1460
|
+
finalize() {
|
|
1461
|
+
var _a;
|
|
1462
|
+
for (const eventName in this._events) {
|
|
1463
|
+
if (this._events[eventName]) {
|
|
1464
|
+
(_a = this.eventManager) == null ? void 0 : _a.off(eventName, this.handleEvent);
|
|
1465
|
+
}
|
|
1466
|
+
}
|
|
1467
|
+
this.transitionManager.finalize();
|
|
1468
|
+
}
|
|
1469
|
+
/**
|
|
1470
|
+
* Callback for events
|
|
1471
|
+
*/
|
|
1472
|
+
handleEvent(event) {
|
|
1473
|
+
this._controllerState = void 0;
|
|
1474
|
+
const eventStartBlocked = this._eventStartBlocked;
|
|
1475
|
+
switch (event.type) {
|
|
1476
|
+
case "panstart":
|
|
1477
|
+
return eventStartBlocked ? false : this._onPanStart(event);
|
|
1478
|
+
case "panmove":
|
|
1479
|
+
return this._onPan(event);
|
|
1480
|
+
case "panend":
|
|
1481
|
+
return this._onPanEnd(event);
|
|
1482
|
+
case "pinchstart":
|
|
1483
|
+
return eventStartBlocked || !this._isTrackpadGestureAllowed(event) ? false : this._onPinchStart(event);
|
|
1484
|
+
case "pinchmove":
|
|
1485
|
+
return this._isTrackpadGestureAllowed(event) ? this._onPinch(event) : false;
|
|
1486
|
+
case "pinchend":
|
|
1487
|
+
return this._isTrackpadGestureAllowed(event) ? this._onPinchEnd(event) : false;
|
|
1488
|
+
case "multipanstart":
|
|
1489
|
+
return eventStartBlocked ? false : this._onMultiPanStart(event);
|
|
1490
|
+
case "multipanmove":
|
|
1491
|
+
return this._onMultiPan(event);
|
|
1492
|
+
case "multipanend":
|
|
1493
|
+
return this._onMultiPanEnd(event);
|
|
1494
|
+
case "dblclick":
|
|
1495
|
+
return this._onDoubleClick(event);
|
|
1496
|
+
case "dblclickdragstart":
|
|
1497
|
+
return eventStartBlocked ? false : this._onDoubleClickDragStart(event);
|
|
1498
|
+
case "dblclickdragmove":
|
|
1499
|
+
return this._onDoubleClickDrag(event);
|
|
1500
|
+
case "dblclickdragend":
|
|
1501
|
+
case "dblclickdragcancel":
|
|
1502
|
+
return this._onDoubleClickDragEnd(event);
|
|
1503
|
+
case "wheel":
|
|
1504
|
+
return this._onWheel(event);
|
|
1505
|
+
case "keydown":
|
|
1506
|
+
return this._onKeyDown(event);
|
|
1507
|
+
default:
|
|
1508
|
+
return false;
|
|
1509
|
+
}
|
|
1510
|
+
}
|
|
1511
|
+
/* Event utils */
|
|
1512
|
+
// Event object: http://hammerjs.github.io/api/#event-object
|
|
1513
|
+
get controllerState() {
|
|
1514
|
+
this._controllerState = this._controllerState || new this.ControllerState({
|
|
1515
|
+
makeViewport: this.makeViewport,
|
|
1516
|
+
...this.props,
|
|
1517
|
+
...this.state
|
|
1518
|
+
});
|
|
1519
|
+
return this._controllerState;
|
|
1520
|
+
}
|
|
1521
|
+
getCenter(event) {
|
|
1522
|
+
const { x, y } = this.props;
|
|
1523
|
+
const { offsetCenter } = event;
|
|
1524
|
+
return [offsetCenter.x - x, offsetCenter.y - y];
|
|
1525
|
+
}
|
|
1526
|
+
/** Resolves the zoom anchor for pointer-based controls. */
|
|
1527
|
+
getZoomPosition(position) {
|
|
1528
|
+
if (this.zoomAround === "pointer") {
|
|
1529
|
+
return position;
|
|
1530
|
+
}
|
|
1531
|
+
const viewport = this.makeViewport(this.controllerState.getViewportProps());
|
|
1532
|
+
const [centerX, centerY] = (0, import_web_mercator3.worldToPixels)(viewport.center, viewport.pixelProjectionMatrix);
|
|
1533
|
+
return [centerX, centerY];
|
|
1534
|
+
}
|
|
1535
|
+
isPointInBounds(pos, event) {
|
|
1536
|
+
const { width, height } = this.props;
|
|
1537
|
+
if (event && event.handled) {
|
|
1538
|
+
return false;
|
|
1539
|
+
}
|
|
1540
|
+
const inside = pos[0] >= 0 && pos[0] <= width && pos[1] >= 0 && pos[1] <= height;
|
|
1541
|
+
if (inside && event) {
|
|
1542
|
+
event.stopPropagation();
|
|
1543
|
+
}
|
|
1544
|
+
return inside;
|
|
1545
|
+
}
|
|
1546
|
+
isFunctionKeyPressed(event) {
|
|
1547
|
+
const { srcEvent } = event;
|
|
1548
|
+
return Boolean(srcEvent.metaKey || srcEvent.altKey || srcEvent.ctrlKey || srcEvent.shiftKey);
|
|
1549
|
+
}
|
|
1550
|
+
isDragging() {
|
|
1551
|
+
return this._interactionState.isDragging || false;
|
|
1552
|
+
}
|
|
1553
|
+
// When a multi-touch event ends, e.g. pinch, not all pointers are lifted at the same time.
|
|
1554
|
+
// This triggers a brief `pan` event.
|
|
1555
|
+
// Calling this method will temporarily disable *start events to avoid conflicting transitions.
|
|
1556
|
+
blockEvents(timeout) {
|
|
1557
|
+
const timer = setTimeout(() => {
|
|
1558
|
+
if (this._eventStartBlocked === timer) {
|
|
1559
|
+
this._eventStartBlocked = null;
|
|
1560
|
+
}
|
|
1561
|
+
}, timeout);
|
|
1562
|
+
this._eventStartBlocked = timer;
|
|
1563
|
+
}
|
|
1564
|
+
/**
|
|
1565
|
+
* Extract interactivity options
|
|
1566
|
+
*/
|
|
1567
|
+
setProps(props) {
|
|
1568
|
+
if (props.maxBoundsPadding === void 0) {
|
|
1569
|
+
props.maxBoundsPadding = null;
|
|
1570
|
+
}
|
|
1571
|
+
if (props.dragMode) {
|
|
1572
|
+
this.dragMode = props.dragMode;
|
|
1573
|
+
}
|
|
1574
|
+
const oldProps = this.props;
|
|
1575
|
+
this.props = props;
|
|
1576
|
+
if (!("transitionInterpolator" in props)) {
|
|
1577
|
+
props.transitionInterpolator = this._getTransitionProps().transitionInterpolator;
|
|
1578
|
+
}
|
|
1579
|
+
this.transitionManager.processViewStateChange(props);
|
|
1580
|
+
const { inertia } = props;
|
|
1581
|
+
this.inertia = Number.isFinite(inertia) ? inertia : inertia === true ? DEFAULT_INERTIA : 0;
|
|
1582
|
+
const {
|
|
1583
|
+
scrollZoom = true,
|
|
1584
|
+
dragPan = true,
|
|
1585
|
+
dragRotate = true,
|
|
1586
|
+
doubleClickZoom = true,
|
|
1587
|
+
doubleClickDragZoom = false,
|
|
1588
|
+
touchZoom = true,
|
|
1589
|
+
touchRotate = false,
|
|
1590
|
+
multiTouchDrag = touchRotate ? "rotate" : null,
|
|
1591
|
+
trackpadGesture = false,
|
|
1592
|
+
zoomAround = "pointer",
|
|
1593
|
+
keyboard = true
|
|
1594
|
+
} = props;
|
|
1595
|
+
const isInteractive = Boolean(this.onViewStateChange);
|
|
1596
|
+
this.toggleEvents(EVENT_TYPES.WHEEL, isInteractive && scrollZoom);
|
|
1597
|
+
this.toggleEvents(EVENT_TYPES.PAN, isInteractive);
|
|
1598
|
+
this.toggleEvents(
|
|
1599
|
+
EVENT_TYPES.PINCH,
|
|
1600
|
+
isInteractive && (touchZoom || multiTouchDrag === "rotate")
|
|
1601
|
+
);
|
|
1602
|
+
this.toggleEvents(EVENT_TYPES.MULTI_PAN, isInteractive && Boolean(multiTouchDrag));
|
|
1603
|
+
this.toggleEvents(EVENT_TYPES.DOUBLE_CLICK, isInteractive && doubleClickZoom);
|
|
1604
|
+
this.toggleEvents(EVENT_TYPES.DOUBLE_CLICK_DRAG, isInteractive && doubleClickDragZoom);
|
|
1605
|
+
this.toggleEvents(EVENT_TYPES.KEYBOARD, isInteractive && keyboard);
|
|
1606
|
+
this.scrollZoom = scrollZoom;
|
|
1607
|
+
this.dragPan = dragPan;
|
|
1608
|
+
this.dragRotate = dragRotate;
|
|
1609
|
+
this.doubleClickZoom = doubleClickZoom;
|
|
1610
|
+
this.doubleClickDragZoom = doubleClickDragZoom;
|
|
1611
|
+
this.touchZoom = touchZoom;
|
|
1612
|
+
this.touchRotate = multiTouchDrag === "rotate";
|
|
1613
|
+
this.multiTouchDrag = multiTouchDrag;
|
|
1614
|
+
this.trackpadGesture = trackpadGesture;
|
|
1615
|
+
this.zoomAround = zoomAround;
|
|
1616
|
+
this.keyboard = keyboard;
|
|
1617
|
+
const constraintChanged = !oldProps || oldProps.height !== props.height || oldProps.width !== props.width || oldProps.maxBounds !== props.maxBounds || oldProps.maxBoundsPadding !== props.maxBoundsPadding;
|
|
1618
|
+
if (constraintChanged && props.maxBounds) {
|
|
1619
|
+
const controllerState = new this.ControllerState({ ...props, makeViewport: this.makeViewport });
|
|
1620
|
+
const normalizedProps = controllerState.getViewportProps();
|
|
1621
|
+
const changed = Object.keys(normalizedProps).some(
|
|
1622
|
+
(key) => !deepEqual(normalizedProps[key], props[key], 1)
|
|
1623
|
+
);
|
|
1624
|
+
if (changed) {
|
|
1625
|
+
this.updateViewport(controllerState);
|
|
1626
|
+
}
|
|
1627
|
+
}
|
|
1628
|
+
}
|
|
1629
|
+
updateTransition() {
|
|
1630
|
+
this.transitionManager.updateTransition();
|
|
1631
|
+
}
|
|
1632
|
+
toggleEvents(eventNames, enabled) {
|
|
1633
|
+
if (this.eventManager) {
|
|
1634
|
+
eventNames.forEach((eventName) => {
|
|
1635
|
+
if (this._events[eventName] !== enabled) {
|
|
1636
|
+
this._events[eventName] = enabled;
|
|
1637
|
+
if (enabled) {
|
|
1638
|
+
this.eventManager.on(eventName, this.handleEvent);
|
|
1639
|
+
} else {
|
|
1640
|
+
this.eventManager.off(eventName, this.handleEvent);
|
|
1641
|
+
}
|
|
1642
|
+
}
|
|
1643
|
+
});
|
|
1644
|
+
}
|
|
1645
|
+
}
|
|
1646
|
+
// Private Methods
|
|
1647
|
+
/* Callback util */
|
|
1648
|
+
// formats map state and invokes callback function
|
|
1649
|
+
updateViewport(newControllerState, extraProps = null, interactionState = {}) {
|
|
1650
|
+
const viewState = { ...newControllerState.getViewportProps(), ...extraProps };
|
|
1651
|
+
const changed = this.controllerState !== newControllerState;
|
|
1652
|
+
this.state = newControllerState.getState();
|
|
1653
|
+
this._setInteractionState(interactionState);
|
|
1654
|
+
if (changed) {
|
|
1655
|
+
const oldViewState = this.controllerState && this.controllerState.getViewportProps();
|
|
1656
|
+
if (this.onViewStateChange) {
|
|
1657
|
+
this.onViewStateChange({
|
|
1658
|
+
viewState,
|
|
1659
|
+
interactionState: this._interactionState,
|
|
1660
|
+
oldViewState,
|
|
1661
|
+
viewId: this.props.id
|
|
1662
|
+
});
|
|
1663
|
+
}
|
|
1664
|
+
}
|
|
1665
|
+
}
|
|
1666
|
+
_onTransition(params) {
|
|
1667
|
+
this.onViewStateChange({
|
|
1668
|
+
...params,
|
|
1669
|
+
interactionState: this._interactionState,
|
|
1670
|
+
viewId: this.props.id
|
|
1671
|
+
});
|
|
1672
|
+
}
|
|
1673
|
+
_setInteractionState(newStates) {
|
|
1674
|
+
Object.assign(this._interactionState, newStates);
|
|
1675
|
+
this.onStateChange(this._interactionState);
|
|
1676
|
+
}
|
|
1677
|
+
/** Maps a semantic input lifecycle to the constraint policy seen by controller state. */
|
|
1678
|
+
_getConstraintContext(_action, phase) {
|
|
1679
|
+
if (!this.props.rubberBand) {
|
|
1680
|
+
return { mode: "hard" };
|
|
1681
|
+
}
|
|
1682
|
+
return { mode: phase === "update" ? "elastic" : phase === "end" ? "rebound" : "hard" };
|
|
1683
|
+
}
|
|
1684
|
+
/** Returns a rebound transition when hard resolution changed the displayed viewport props. */
|
|
1685
|
+
_getReboundTransition(constraintContext, nextControllerState) {
|
|
1686
|
+
if (constraintContext.mode !== "rebound") {
|
|
1687
|
+
return null;
|
|
1688
|
+
}
|
|
1689
|
+
const nextViewportProps = nextControllerState.getViewportProps();
|
|
1690
|
+
const shouldRebound = Object.keys(nextViewportProps).some(
|
|
1691
|
+
(key) => !deepEqual(this.props[key], nextViewportProps[key], 1)
|
|
1692
|
+
);
|
|
1693
|
+
return shouldRebound ? {
|
|
1694
|
+
...this._getTransitionProps(),
|
|
1695
|
+
transitionDuration: REBOUND_DURATION,
|
|
1696
|
+
transitionEasing: EASE_OUT_EXPONENTIAL
|
|
1697
|
+
} : null;
|
|
1698
|
+
}
|
|
1699
|
+
/* Event handlers */
|
|
1700
|
+
// Default handler for the `panstart` event.
|
|
1701
|
+
_onPanStart(event) {
|
|
1702
|
+
const pos = this.getCenter(event);
|
|
1703
|
+
if (!this.isPointInBounds(pos, event)) {
|
|
1704
|
+
return false;
|
|
1705
|
+
}
|
|
1706
|
+
let alternateMode = this.isFunctionKeyPressed(event) || event.rightButton || false;
|
|
1707
|
+
if (this.invertPan || this.dragMode === "pan") {
|
|
1708
|
+
alternateMode = !alternateMode;
|
|
1709
|
+
}
|
|
1710
|
+
const action = alternateMode ? "pan" : "rotate";
|
|
1711
|
+
const constraintContext = this._getConstraintContext(action, "start");
|
|
1712
|
+
const newControllerState = alternateMode ? this.controllerState.panStart({ pos }, constraintContext) : this.controllerState.rotateStart({ pos }, constraintContext);
|
|
1713
|
+
this._panMove = alternateMode;
|
|
1714
|
+
this.updateViewport(newControllerState, NO_TRANSITION_PROPS, { isDragging: true });
|
|
1715
|
+
return true;
|
|
1716
|
+
}
|
|
1717
|
+
// Default handler for the `panmove` and `panend` event.
|
|
1718
|
+
_onPan(event) {
|
|
1719
|
+
if (!this.isDragging()) {
|
|
1720
|
+
return false;
|
|
1721
|
+
}
|
|
1722
|
+
return this._panMove ? this._onPanMove(event) : this._onPanRotate(event);
|
|
1723
|
+
}
|
|
1724
|
+
_onPanEnd(event) {
|
|
1725
|
+
if (!this.isDragging()) {
|
|
1726
|
+
return false;
|
|
1727
|
+
}
|
|
1728
|
+
return this._panMove ? this._onPanMoveEnd(event) : this._onPanRotateEnd(event);
|
|
1729
|
+
}
|
|
1730
|
+
// Default handler for panning to move.
|
|
1731
|
+
// Called by `_onPan` when panning without function key pressed.
|
|
1732
|
+
_onPanMove(event) {
|
|
1733
|
+
if (!this.dragPan) {
|
|
1734
|
+
return false;
|
|
1735
|
+
}
|
|
1736
|
+
const pos = this.getCenter(event);
|
|
1737
|
+
const newControllerState = this.controllerState.pan(
|
|
1738
|
+
{ pos },
|
|
1739
|
+
this._getConstraintContext("pan", "update")
|
|
1740
|
+
);
|
|
1741
|
+
this.updateViewport(newControllerState, NO_TRANSITION_PROPS, {
|
|
1742
|
+
isDragging: true,
|
|
1743
|
+
isPanning: true
|
|
1744
|
+
});
|
|
1745
|
+
return true;
|
|
1746
|
+
}
|
|
1747
|
+
_onPanMoveEnd(event) {
|
|
1748
|
+
const { inertia } = this;
|
|
1749
|
+
if (this.dragPan && inertia && event.velocity) {
|
|
1750
|
+
const pos = this.getCenter(event);
|
|
1751
|
+
const endPos = [
|
|
1752
|
+
pos[0] + event.velocityX * inertia / 2,
|
|
1753
|
+
pos[1] + event.velocityY * inertia / 2
|
|
1754
|
+
];
|
|
1755
|
+
const newControllerState = this.controllerState.pan({ pos: endPos }).panEnd();
|
|
1756
|
+
this.updateViewport(
|
|
1757
|
+
newControllerState,
|
|
1758
|
+
{
|
|
1759
|
+
...this._getTransitionProps(),
|
|
1760
|
+
transitionDuration: inertia,
|
|
1761
|
+
transitionEasing: INERTIA_EASING
|
|
1762
|
+
},
|
|
1763
|
+
{
|
|
1764
|
+
isDragging: false,
|
|
1765
|
+
isPanning: true
|
|
1766
|
+
}
|
|
1767
|
+
);
|
|
1768
|
+
} else {
|
|
1769
|
+
const currentControllerState = this.controllerState;
|
|
1770
|
+
const constraintContext = this._getConstraintContext("pan", "end");
|
|
1771
|
+
const newControllerState = currentControllerState.panEnd(constraintContext);
|
|
1772
|
+
const reboundTransition = this._getReboundTransition(constraintContext, newControllerState);
|
|
1773
|
+
this.updateViewport(newControllerState, reboundTransition, {
|
|
1774
|
+
isDragging: false,
|
|
1775
|
+
isPanning: Boolean(reboundTransition)
|
|
1776
|
+
});
|
|
1777
|
+
}
|
|
1778
|
+
return true;
|
|
1779
|
+
}
|
|
1780
|
+
// Default handler for panning to rotate.
|
|
1781
|
+
// Called by `_onPan` when panning with function key pressed.
|
|
1782
|
+
_onPanRotate(event) {
|
|
1783
|
+
if (!this.dragRotate) {
|
|
1784
|
+
return false;
|
|
1785
|
+
}
|
|
1786
|
+
const pos = this.getCenter(event);
|
|
1787
|
+
const newControllerState = this.controllerState.rotate(
|
|
1788
|
+
{ pos },
|
|
1789
|
+
this._getConstraintContext("rotate", "update")
|
|
1790
|
+
);
|
|
1791
|
+
this.updateViewport(newControllerState, NO_TRANSITION_PROPS, {
|
|
1792
|
+
isDragging: true,
|
|
1793
|
+
isRotating: true
|
|
1794
|
+
});
|
|
1795
|
+
return true;
|
|
1796
|
+
}
|
|
1797
|
+
_onPanRotateEnd(event) {
|
|
1798
|
+
const { inertia } = this;
|
|
1799
|
+
if (this.dragRotate && inertia && event.velocity) {
|
|
1800
|
+
const pos = this.getCenter(event);
|
|
1801
|
+
const endPos = [
|
|
1802
|
+
pos[0] + event.velocityX * inertia / 2,
|
|
1803
|
+
pos[1] + event.velocityY * inertia / 2
|
|
1804
|
+
];
|
|
1805
|
+
const newControllerState = this.controllerState.rotate({ pos: endPos }).rotateEnd();
|
|
1806
|
+
this.updateViewport(
|
|
1807
|
+
newControllerState,
|
|
1808
|
+
{
|
|
1809
|
+
...this._getTransitionProps(),
|
|
1810
|
+
transitionDuration: inertia,
|
|
1811
|
+
transitionEasing: INERTIA_EASING
|
|
1812
|
+
},
|
|
1813
|
+
{
|
|
1814
|
+
isDragging: false,
|
|
1815
|
+
isRotating: true
|
|
1816
|
+
}
|
|
1817
|
+
);
|
|
1818
|
+
} else {
|
|
1819
|
+
const currentControllerState = this.controllerState;
|
|
1820
|
+
const constraintContext = this._getConstraintContext("rotate", "end");
|
|
1821
|
+
const newControllerState = currentControllerState.rotateEnd(constraintContext);
|
|
1822
|
+
const reboundTransition = this._getReboundTransition(constraintContext, newControllerState);
|
|
1823
|
+
this.updateViewport(newControllerState, reboundTransition, {
|
|
1824
|
+
isDragging: false,
|
|
1825
|
+
isRotating: Boolean(reboundTransition)
|
|
1826
|
+
});
|
|
1827
|
+
}
|
|
1828
|
+
return true;
|
|
1829
|
+
}
|
|
1830
|
+
// Default handler for the `wheel` event.
|
|
1831
|
+
_onWheel(event) {
|
|
1832
|
+
if (!this.scrollZoom) {
|
|
1833
|
+
return false;
|
|
1834
|
+
}
|
|
1835
|
+
if (this.trackpadGesture && event.device !== "mouse") {
|
|
1836
|
+
return false;
|
|
1837
|
+
}
|
|
1838
|
+
const pos = this.getCenter(event);
|
|
1839
|
+
if (!this.isPointInBounds(pos, event)) {
|
|
1840
|
+
return false;
|
|
1841
|
+
}
|
|
1842
|
+
event.srcEvent.preventDefault();
|
|
1843
|
+
const { speed = 0.01, smooth = false } = this.scrollZoom === true ? {} : this.scrollZoom;
|
|
1844
|
+
const { delta } = event;
|
|
1845
|
+
let scale = 2 / (1 + Math.exp(-Math.abs(delta * speed)));
|
|
1846
|
+
if (delta < 0 && scale !== 0) {
|
|
1847
|
+
scale = 1 / scale;
|
|
1848
|
+
}
|
|
1849
|
+
const zoomPosition = this.getZoomPosition(pos);
|
|
1850
|
+
const transitionProps = smooth ? { ...this._getTransitionProps({ around: zoomPosition }), transitionDuration: 250 } : NO_TRANSITION_PROPS;
|
|
1851
|
+
const newControllerState = this.controllerState.zoom({ pos: zoomPosition, scale });
|
|
1852
|
+
this.updateViewport(newControllerState, transitionProps, {
|
|
1853
|
+
isZooming: true,
|
|
1854
|
+
isPanning: true
|
|
1855
|
+
});
|
|
1856
|
+
if (!smooth) {
|
|
1857
|
+
this._setInteractionState({ isZooming: false, isPanning: false });
|
|
1858
|
+
}
|
|
1859
|
+
return true;
|
|
1860
|
+
}
|
|
1861
|
+
_onMultiPanStart(event) {
|
|
1862
|
+
const { multiTouchDrag } = this;
|
|
1863
|
+
if (!multiTouchDrag || !this._isMultiPanEventAllowed(event, multiTouchDrag)) {
|
|
1864
|
+
return false;
|
|
1865
|
+
}
|
|
1866
|
+
const currentCenter = event.offsetCenter;
|
|
1867
|
+
if (!this.isPointInBounds(this.getCenter(event), event)) {
|
|
1868
|
+
return false;
|
|
1869
|
+
}
|
|
1870
|
+
const isTrackpad = event.pointerType === "trackpad";
|
|
1871
|
+
const startCenter = {
|
|
1872
|
+
x: currentCenter.x - (isTrackpad ? 0 : event.deltaX),
|
|
1873
|
+
y: currentCenter.y - (isTrackpad ? 0 : event.deltaY)
|
|
1874
|
+
};
|
|
1875
|
+
const startEvent = { ...event, offsetCenter: startCenter };
|
|
1876
|
+
const pos = this.getCenter(startEvent);
|
|
1877
|
+
const newControllerState = multiTouchDrag === "pan" ? this.controllerState.panStart({ pos }, this._getConstraintContext("pan", "start")) : this.controllerState.rotateStart({ pos }, this._getConstraintContext("rotate", "start"));
|
|
1878
|
+
this._multiPanMode = multiTouchDrag;
|
|
1879
|
+
this._multiPanStartCenter = startCenter;
|
|
1880
|
+
this.updateViewport(newControllerState, NO_TRANSITION_PROPS, { isDragging: true });
|
|
1881
|
+
return true;
|
|
1882
|
+
}
|
|
1883
|
+
_onMultiPan(event) {
|
|
1884
|
+
const { mode, event: panEvent } = this._getMultiPanEvent(event);
|
|
1885
|
+
if (!mode || !panEvent || !this.isDragging()) {
|
|
1886
|
+
return false;
|
|
1887
|
+
}
|
|
1888
|
+
return mode === "pan" ? this._onPanMove(panEvent) : this._onPanRotate(panEvent);
|
|
1889
|
+
}
|
|
1890
|
+
_onMultiPanEnd(event) {
|
|
1891
|
+
const { mode, event: panEvent } = this._getMultiPanEvent(event);
|
|
1892
|
+
if (!mode || !panEvent || !this.isDragging()) {
|
|
1893
|
+
this._resetMultiPan();
|
|
1894
|
+
return false;
|
|
1895
|
+
}
|
|
1896
|
+
const handled = mode === "pan" ? this._onPanMoveEnd(panEvent) : this._onPanRotateEnd(panEvent);
|
|
1897
|
+
this._resetMultiPan();
|
|
1898
|
+
return handled;
|
|
1899
|
+
}
|
|
1900
|
+
_isTrackpadGestureAllowed(event) {
|
|
1901
|
+
return event.pointerType !== "trackpad" || this.trackpadGesture;
|
|
1902
|
+
}
|
|
1903
|
+
_isMultiPanEventAllowed(event, mode) {
|
|
1904
|
+
if (event.pointerType === "trackpad") {
|
|
1905
|
+
return this.trackpadGesture && (mode === "pan" ? this.dragPan : this.dragRotate);
|
|
1906
|
+
}
|
|
1907
|
+
return event.pointerType === "touch" && (mode === "pan" ? this.dragPan : this.dragRotate);
|
|
1908
|
+
}
|
|
1909
|
+
_getMultiPanEvent(event) {
|
|
1910
|
+
const mode = this._multiPanMode;
|
|
1911
|
+
const startCenter = this._multiPanStartCenter;
|
|
1912
|
+
if (!mode || !startCenter) {
|
|
1913
|
+
return { mode: null, event: null };
|
|
1914
|
+
}
|
|
1915
|
+
return {
|
|
1916
|
+
mode,
|
|
1917
|
+
event: {
|
|
1918
|
+
...event,
|
|
1919
|
+
offsetCenter: {
|
|
1920
|
+
x: startCenter.x + event.deltaX,
|
|
1921
|
+
y: startCenter.y + event.deltaY
|
|
1922
|
+
}
|
|
1923
|
+
}
|
|
1924
|
+
};
|
|
1925
|
+
}
|
|
1926
|
+
_resetMultiPan() {
|
|
1927
|
+
this._multiPanMode = null;
|
|
1928
|
+
this._multiPanStartCenter = null;
|
|
1929
|
+
}
|
|
1930
|
+
// Default handler for the `pinchstart` event.
|
|
1931
|
+
_onPinchStart(event) {
|
|
1932
|
+
this._doubleClickDragAnchor = null;
|
|
1933
|
+
const pos = this.getCenter(event);
|
|
1934
|
+
if (!this.isPointInBounds(pos, event)) {
|
|
1935
|
+
return false;
|
|
1936
|
+
}
|
|
1937
|
+
const newControllerState = this.controllerState.zoomStart({ pos: this.getZoomPosition(pos) }, this._getConstraintContext("zoom", "start")).rotateStart({ pos }, this._getConstraintContext("rotate", "start"));
|
|
1938
|
+
pinchEventWorkaround._startPinchRotation = event.rotation;
|
|
1939
|
+
pinchEventWorkaround._lastPinchEvent = event;
|
|
1940
|
+
this.updateViewport(newControllerState, NO_TRANSITION_PROPS, { isDragging: true });
|
|
1941
|
+
return true;
|
|
1942
|
+
}
|
|
1943
|
+
// Default handler for the `pinchmove` and `pinchend` events.
|
|
1944
|
+
_onPinch(event) {
|
|
1945
|
+
if (!this.touchZoom && !this.touchRotate) {
|
|
1946
|
+
return false;
|
|
1947
|
+
}
|
|
1948
|
+
if (!this.isDragging()) {
|
|
1949
|
+
return false;
|
|
1950
|
+
}
|
|
1951
|
+
let newControllerState = this.controllerState;
|
|
1952
|
+
if (this.touchZoom) {
|
|
1953
|
+
const { scale } = event;
|
|
1954
|
+
const pos = this.getCenter(event);
|
|
1955
|
+
newControllerState = newControllerState.zoom(
|
|
1956
|
+
{ pos: this.getZoomPosition(pos), scale },
|
|
1957
|
+
this._getConstraintContext("zoom", "update")
|
|
1958
|
+
);
|
|
1959
|
+
}
|
|
1960
|
+
if (this.touchRotate) {
|
|
1961
|
+
const { rotation } = event;
|
|
1962
|
+
newControllerState = newControllerState.rotate(
|
|
1963
|
+
{ deltaAngleX: pinchEventWorkaround._startPinchRotation - rotation },
|
|
1964
|
+
this._getConstraintContext("rotate", "update")
|
|
1965
|
+
);
|
|
1966
|
+
}
|
|
1967
|
+
this.updateViewport(newControllerState, NO_TRANSITION_PROPS, {
|
|
1968
|
+
isDragging: true,
|
|
1969
|
+
isPanning: this.touchZoom,
|
|
1970
|
+
isZooming: this.touchZoom,
|
|
1971
|
+
isRotating: this.touchRotate
|
|
1972
|
+
});
|
|
1973
|
+
pinchEventWorkaround._lastPinchEvent = event;
|
|
1974
|
+
return true;
|
|
1975
|
+
}
|
|
1976
|
+
_onPinchEnd(event) {
|
|
1977
|
+
if (!this.isDragging()) {
|
|
1978
|
+
return false;
|
|
1979
|
+
}
|
|
1980
|
+
const { inertia } = this;
|
|
1981
|
+
const { _lastPinchEvent } = pinchEventWorkaround;
|
|
1982
|
+
if (this.touchZoom && inertia && _lastPinchEvent && event.scale !== _lastPinchEvent.scale) {
|
|
1983
|
+
const pos = this.getCenter(event);
|
|
1984
|
+
const zoomPosition = this.getZoomPosition(pos);
|
|
1985
|
+
let newControllerState = this.controllerState.rotateEnd();
|
|
1986
|
+
const z = Math.log2(event.scale);
|
|
1987
|
+
const velocityZ = (z - Math.log2(_lastPinchEvent.scale)) / (event.deltaTime - _lastPinchEvent.deltaTime);
|
|
1988
|
+
const endScale = Math.pow(2, z + velocityZ * inertia / 2);
|
|
1989
|
+
newControllerState = newControllerState.zoom({ pos: zoomPosition, scale: endScale }).zoomEnd();
|
|
1990
|
+
this.updateViewport(
|
|
1991
|
+
newControllerState,
|
|
1992
|
+
{
|
|
1993
|
+
...this._getTransitionProps({ around: zoomPosition }),
|
|
1994
|
+
transitionDuration: inertia,
|
|
1995
|
+
transitionEasing: INERTIA_EASING
|
|
1996
|
+
},
|
|
1997
|
+
{
|
|
1998
|
+
isDragging: false,
|
|
1999
|
+
isPanning: this.touchZoom,
|
|
2000
|
+
isZooming: this.touchZoom,
|
|
2001
|
+
isRotating: false
|
|
2002
|
+
}
|
|
2003
|
+
);
|
|
2004
|
+
this.blockEvents(inertia);
|
|
2005
|
+
} else {
|
|
2006
|
+
const currentControllerState = this.controllerState;
|
|
2007
|
+
const zoomConstraintContext = this._getConstraintContext("zoom", "end");
|
|
2008
|
+
const rotateConstraintContext = this._getConstraintContext("rotate", "end");
|
|
2009
|
+
const newControllerState = currentControllerState.zoomEnd(zoomConstraintContext).rotateEnd(rotateConstraintContext);
|
|
2010
|
+
const reboundTransition = this._getReboundTransition(
|
|
2011
|
+
this.touchZoom ? zoomConstraintContext : rotateConstraintContext,
|
|
2012
|
+
newControllerState
|
|
2013
|
+
);
|
|
2014
|
+
this.updateViewport(newControllerState, reboundTransition, {
|
|
2015
|
+
isDragging: false,
|
|
2016
|
+
isPanning: Boolean(reboundTransition) && this.touchZoom,
|
|
2017
|
+
isZooming: Boolean(reboundTransition) && this.touchZoom,
|
|
2018
|
+
isRotating: Boolean(reboundTransition) && this.touchRotate
|
|
2019
|
+
});
|
|
2020
|
+
}
|
|
2021
|
+
pinchEventWorkaround._startPinchRotation = null;
|
|
2022
|
+
pinchEventWorkaround._lastPinchEvent = null;
|
|
2023
|
+
return true;
|
|
2024
|
+
}
|
|
2025
|
+
// Default handler for the `dblclick` event.
|
|
2026
|
+
_onDoubleClick(event) {
|
|
2027
|
+
if (!this.doubleClickZoom) {
|
|
2028
|
+
return false;
|
|
2029
|
+
}
|
|
2030
|
+
if (Date.now() < this._suppressDoubleClickUntil) {
|
|
2031
|
+
return false;
|
|
2032
|
+
}
|
|
2033
|
+
const pos = this.getCenter(event);
|
|
2034
|
+
if (!this.isPointInBounds(pos, event)) {
|
|
2035
|
+
return false;
|
|
2036
|
+
}
|
|
2037
|
+
const isZoomOut = this.isFunctionKeyPressed(event);
|
|
2038
|
+
const zoomPosition = this.getZoomPosition(pos);
|
|
2039
|
+
const newControllerState = this.controllerState.zoom({
|
|
2040
|
+
pos: zoomPosition,
|
|
2041
|
+
scale: isZoomOut ? 0.5 : 2
|
|
2042
|
+
});
|
|
2043
|
+
this.updateViewport(newControllerState, this._getTransitionProps({ around: zoomPosition }), {
|
|
2044
|
+
isZooming: true,
|
|
2045
|
+
isPanning: true
|
|
2046
|
+
});
|
|
2047
|
+
this.blockEvents(100);
|
|
2048
|
+
return true;
|
|
2049
|
+
}
|
|
2050
|
+
_onDoubleClickDragStart(event) {
|
|
2051
|
+
if (!this.doubleClickDragZoom) {
|
|
2052
|
+
this._doubleClickDragAnchor = null;
|
|
2053
|
+
return false;
|
|
2054
|
+
}
|
|
2055
|
+
const pos = this.getCenter(event);
|
|
2056
|
+
if (!this.isPointInBounds(pos, event)) {
|
|
2057
|
+
this._doubleClickDragAnchor = null;
|
|
2058
|
+
return false;
|
|
2059
|
+
}
|
|
2060
|
+
this._doubleClickDragAnchor = this.getZoomPosition(pos);
|
|
2061
|
+
let newControllerState = this.controllerState.zoomStart(
|
|
2062
|
+
{ pos: this._doubleClickDragAnchor },
|
|
2063
|
+
this._getConstraintContext("zoom", "start")
|
|
2064
|
+
);
|
|
2065
|
+
if (event.scale !== 1) {
|
|
2066
|
+
newControllerState = newControllerState.zoom(
|
|
2067
|
+
{ pos: this._doubleClickDragAnchor, scale: event.scale },
|
|
2068
|
+
this._getConstraintContext("zoom", "update")
|
|
2069
|
+
);
|
|
2070
|
+
}
|
|
2071
|
+
this.updateViewport(newControllerState, NO_TRANSITION_PROPS, {
|
|
2072
|
+
isDragging: true,
|
|
2073
|
+
isPanning: true,
|
|
2074
|
+
isZooming: true
|
|
2075
|
+
});
|
|
2076
|
+
return true;
|
|
2077
|
+
}
|
|
2078
|
+
_onDoubleClickDrag(event) {
|
|
2079
|
+
const pos = this._doubleClickDragAnchor;
|
|
2080
|
+
if (!pos) {
|
|
2081
|
+
return false;
|
|
2082
|
+
}
|
|
2083
|
+
const newControllerState = this.controllerState.zoom(
|
|
2084
|
+
{ pos, scale: event.scale },
|
|
2085
|
+
this._getConstraintContext("zoom", "update")
|
|
2086
|
+
);
|
|
2087
|
+
this.updateViewport(newControllerState, NO_TRANSITION_PROPS, {
|
|
2088
|
+
isDragging: true,
|
|
2089
|
+
isPanning: true,
|
|
2090
|
+
isZooming: true
|
|
2091
|
+
});
|
|
2092
|
+
return true;
|
|
2093
|
+
}
|
|
2094
|
+
_onDoubleClickDragEnd(_event) {
|
|
2095
|
+
const pos = this._doubleClickDragAnchor;
|
|
2096
|
+
if (!pos) {
|
|
2097
|
+
return false;
|
|
2098
|
+
}
|
|
2099
|
+
this._doubleClickDragAnchor = null;
|
|
2100
|
+
const currentControllerState = this.controllerState;
|
|
2101
|
+
const constraintContext = this._getConstraintContext("zoom", "end");
|
|
2102
|
+
const newControllerState = currentControllerState.zoomEnd(constraintContext);
|
|
2103
|
+
const reboundTransition = this._getReboundTransition(constraintContext, newControllerState);
|
|
2104
|
+
this.updateViewport(newControllerState, reboundTransition, {
|
|
2105
|
+
isDragging: false,
|
|
2106
|
+
isPanning: Boolean(reboundTransition),
|
|
2107
|
+
isZooming: Boolean(reboundTransition)
|
|
2108
|
+
});
|
|
2109
|
+
this._suppressDoubleClickUntil = Date.now() + 100;
|
|
2110
|
+
this.blockEvents(100);
|
|
2111
|
+
return true;
|
|
2112
|
+
}
|
|
2113
|
+
// Default handler for the `keydown` event
|
|
2114
|
+
_onKeyDown(event) {
|
|
2115
|
+
if (!this.keyboard) {
|
|
2116
|
+
return false;
|
|
2117
|
+
}
|
|
2118
|
+
const funcKey = this.isFunctionKeyPressed(event);
|
|
2119
|
+
const { zoomSpeed, moveSpeed, rotateSpeedX, rotateSpeedY } = this.keyboard === true ? {} : this.keyboard;
|
|
2120
|
+
const { controllerState } = this;
|
|
2121
|
+
let newControllerState;
|
|
2122
|
+
const interactionState = {};
|
|
2123
|
+
switch (event.srcEvent.code) {
|
|
2124
|
+
case "Minus":
|
|
2125
|
+
newControllerState = funcKey ? controllerState.zoomOut(zoomSpeed).zoomOut(zoomSpeed) : controllerState.zoomOut(zoomSpeed);
|
|
2126
|
+
interactionState.isZooming = true;
|
|
2127
|
+
break;
|
|
2128
|
+
case "Equal":
|
|
2129
|
+
newControllerState = funcKey ? controllerState.zoomIn(zoomSpeed).zoomIn(zoomSpeed) : controllerState.zoomIn(zoomSpeed);
|
|
2130
|
+
interactionState.isZooming = true;
|
|
2131
|
+
break;
|
|
2132
|
+
case "ArrowLeft":
|
|
2133
|
+
if (funcKey) {
|
|
2134
|
+
newControllerState = controllerState.rotateLeft(rotateSpeedX);
|
|
2135
|
+
interactionState.isRotating = true;
|
|
2136
|
+
} else {
|
|
2137
|
+
newControllerState = controllerState.moveLeft(moveSpeed);
|
|
2138
|
+
interactionState.isPanning = true;
|
|
2139
|
+
}
|
|
2140
|
+
break;
|
|
2141
|
+
case "ArrowRight":
|
|
2142
|
+
if (funcKey) {
|
|
2143
|
+
newControllerState = controllerState.rotateRight(rotateSpeedX);
|
|
2144
|
+
interactionState.isRotating = true;
|
|
2145
|
+
} else {
|
|
2146
|
+
newControllerState = controllerState.moveRight(moveSpeed);
|
|
2147
|
+
interactionState.isPanning = true;
|
|
2148
|
+
}
|
|
2149
|
+
break;
|
|
2150
|
+
case "ArrowUp":
|
|
2151
|
+
if (funcKey) {
|
|
2152
|
+
newControllerState = controllerState.rotateUp(rotateSpeedY);
|
|
2153
|
+
interactionState.isRotating = true;
|
|
2154
|
+
} else {
|
|
2155
|
+
newControllerState = controllerState.moveUp(moveSpeed);
|
|
2156
|
+
interactionState.isPanning = true;
|
|
2157
|
+
}
|
|
2158
|
+
break;
|
|
2159
|
+
case "ArrowDown":
|
|
2160
|
+
if (funcKey) {
|
|
2161
|
+
newControllerState = controllerState.rotateDown(rotateSpeedY);
|
|
2162
|
+
interactionState.isRotating = true;
|
|
2163
|
+
} else {
|
|
2164
|
+
newControllerState = controllerState.moveDown(moveSpeed);
|
|
2165
|
+
interactionState.isPanning = true;
|
|
2166
|
+
}
|
|
2167
|
+
break;
|
|
2168
|
+
default:
|
|
2169
|
+
return false;
|
|
2170
|
+
}
|
|
2171
|
+
this.updateViewport(newControllerState, this._getTransitionProps(), interactionState);
|
|
2172
|
+
return true;
|
|
2173
|
+
}
|
|
2174
|
+
_getTransitionProps(opts) {
|
|
2175
|
+
const { transition } = this;
|
|
2176
|
+
if (!transition || !transition.transitionInterpolator) {
|
|
2177
|
+
return NO_TRANSITION_PROPS;
|
|
2178
|
+
}
|
|
2179
|
+
return opts ? {
|
|
2180
|
+
...transition,
|
|
2181
|
+
transitionInterpolator: new LinearInterpolator({
|
|
2182
|
+
...opts,
|
|
2183
|
+
...transition.transitionInterpolator.opts,
|
|
2184
|
+
makeViewport: this.controllerState.makeViewport
|
|
2185
|
+
})
|
|
2186
|
+
} : transition;
|
|
2187
|
+
}
|
|
2188
|
+
};
|
|
2189
|
+
|
|
2190
|
+
// ../core/src/controllers/view-state.ts
|
|
2191
|
+
var CONSTRAINT_AROUND = /* @__PURE__ */ Symbol("constraintAround");
|
|
2192
|
+
var ViewState = class {
|
|
2193
|
+
constructor(props, state, makeViewport, constraintContext) {
|
|
2194
|
+
this.makeViewport = makeViewport;
|
|
2195
|
+
this._viewportProps = this.applyConstraints(props, constraintContext);
|
|
2196
|
+
this._state = state;
|
|
2197
|
+
}
|
|
2198
|
+
getViewportProps() {
|
|
2199
|
+
return this._viewportProps;
|
|
2200
|
+
}
|
|
2201
|
+
getState() {
|
|
2202
|
+
return this._state;
|
|
2203
|
+
}
|
|
2204
|
+
};
|
|
2205
|
+
|
|
2206
|
+
// ../core/src/controllers/utils.ts
|
|
2207
|
+
function applyRubberBand(value, constrainedValue, range) {
|
|
2208
|
+
const overshoot = value - constrainedValue;
|
|
2209
|
+
return overshoot && Number.isFinite(overshoot) ? constrainedValue + overshoot * range / (range + Math.abs(overshoot)) : constrainedValue;
|
|
2210
|
+
}
|
|
2211
|
+
function getMaxBoundsRect(width, height, padding) {
|
|
2212
|
+
const left = getPosition(parsePosition((padding == null ? void 0 : padding.left) ?? 0), width);
|
|
2213
|
+
const right = getPosition(parsePosition((padding == null ? void 0 : padding.right) ?? 0), width);
|
|
2214
|
+
const top = getPosition(parsePosition((padding == null ? void 0 : padding.top) ?? 0), height);
|
|
2215
|
+
const bottom = getPosition(parsePosition((padding == null ? void 0 : padding.bottom) ?? 0), height);
|
|
2216
|
+
return {
|
|
2217
|
+
x: left,
|
|
2218
|
+
y: top,
|
|
2219
|
+
width: width - left - right,
|
|
2220
|
+
height: height - top - bottom
|
|
2221
|
+
};
|
|
2222
|
+
}
|
|
2223
|
+
function getMaxBoundsExtents(viewport, target, rect) {
|
|
2224
|
+
let [x, y] = viewport.project(target);
|
|
2225
|
+
x = Number.isFinite(x) ? x : viewport.width / 2;
|
|
2226
|
+
y = Number.isFinite(y) ? y : viewport.height / 2;
|
|
2227
|
+
return {
|
|
2228
|
+
left: x - rect.x,
|
|
2229
|
+
right: rect.x + rect.width - x,
|
|
2230
|
+
top: y - rect.y,
|
|
2231
|
+
bottom: rect.y + rect.height - y
|
|
2232
|
+
};
|
|
2233
|
+
}
|
|
2234
|
+
|
|
2235
|
+
// ../core/src/utils/apply-styles.ts
|
|
2236
|
+
function applyStyles(element, style) {
|
|
2237
|
+
if (style) {
|
|
2238
|
+
Object.entries(style).map(([key, value]) => {
|
|
2239
|
+
if (key.startsWith("--")) {
|
|
2240
|
+
element.style.setProperty(key, value);
|
|
2241
|
+
} else {
|
|
2242
|
+
element.style[key] = value;
|
|
2243
|
+
}
|
|
2244
|
+
});
|
|
2245
|
+
}
|
|
2246
|
+
}
|
|
2247
|
+
function removeStyles(element, style) {
|
|
2248
|
+
if (style) {
|
|
2249
|
+
Object.keys(style).map((key) => {
|
|
2250
|
+
if (key.startsWith("--")) {
|
|
2251
|
+
element.style.removeProperty(key);
|
|
2252
|
+
} else {
|
|
2253
|
+
element.style[key] = "";
|
|
2254
|
+
}
|
|
2255
|
+
});
|
|
2256
|
+
}
|
|
2257
|
+
}
|
|
2258
|
+
|
|
2259
|
+
// ../core/src/lib/widget.ts
|
|
2260
|
+
var Widget = class {
|
|
2261
|
+
constructor(props) {
|
|
2262
|
+
/**
|
|
2263
|
+
* The view id that this widget controls and is positioned relative to. Default `null`.
|
|
2264
|
+
* If assigned, this widget only responds to events inside the matching view. In multi-canvas
|
|
2265
|
+
* mode, the view's `canvasId` determines the positioning offset, but the widget DOM remains
|
|
2266
|
+
* under the shared widget root.
|
|
2267
|
+
*/
|
|
2268
|
+
this.viewId = null;
|
|
2269
|
+
this.props = {
|
|
2270
|
+
// @ts-expect-error `defaultProps` may not exist on constructor
|
|
2271
|
+
...this.constructor.defaultProps,
|
|
2272
|
+
...props
|
|
2273
|
+
};
|
|
2274
|
+
this.id = this.props.id;
|
|
2275
|
+
}
|
|
2276
|
+
/** Called to update widget options */
|
|
2277
|
+
setProps(props) {
|
|
2278
|
+
const oldProps = this.props;
|
|
2279
|
+
const el = this.rootElement;
|
|
2280
|
+
if (el && oldProps.className !== props.className) {
|
|
2281
|
+
if (oldProps.className) el.classList.remove(oldProps.className);
|
|
2282
|
+
if (props.className) el.classList.add(props.className);
|
|
2283
|
+
}
|
|
2284
|
+
if (el && !deepEqual(oldProps.style, props.style, 1)) {
|
|
2285
|
+
removeStyles(el, oldProps.style);
|
|
2286
|
+
applyStyles(el, props.style);
|
|
2287
|
+
}
|
|
2288
|
+
Object.assign(this.props, props);
|
|
2289
|
+
this.updateHTML();
|
|
2290
|
+
}
|
|
2291
|
+
/** Update the HTML to reflect latest props and state */
|
|
2292
|
+
updateHTML() {
|
|
2293
|
+
if (this.rootElement) {
|
|
2294
|
+
this.onRenderHTML(this.rootElement);
|
|
2295
|
+
}
|
|
2296
|
+
}
|
|
2297
|
+
// VIEW STATE HELPERS
|
|
2298
|
+
get viewIds() {
|
|
2299
|
+
var _a;
|
|
2300
|
+
return this.viewId ? [this.viewId] : ((_a = this.deck) == null ? void 0 : _a.getViews().map((v) => v.id)) ?? [];
|
|
2301
|
+
}
|
|
2302
|
+
/** Returns the current view state for the given view */
|
|
2303
|
+
getViewState(viewId) {
|
|
2304
|
+
var _a, _b;
|
|
2305
|
+
return ((_b = (_a = this.deck) == null ? void 0 : _a.viewManager) == null ? void 0 : _b.getViewState(viewId)) || {};
|
|
2306
|
+
}
|
|
2307
|
+
/** Updates the view state for the given view */
|
|
2308
|
+
setViewState(viewId, viewState) {
|
|
2309
|
+
var _a;
|
|
2310
|
+
(_a = this.deck) == null ? void 0 : _a._onViewStateChange({ viewId, viewState, interactionState: {} });
|
|
2311
|
+
}
|
|
2312
|
+
// @note empty method calls have an overhead in V8 but it is very low, ~1ns
|
|
2313
|
+
/**
|
|
2314
|
+
* Common utility to create the root DOM element for this widget
|
|
2315
|
+
* Configures the top-level styles and adds basic class names for theming
|
|
2316
|
+
* @returns an UI element that should be appended to the Deck container
|
|
2317
|
+
*/
|
|
2318
|
+
onCreateRootElement() {
|
|
2319
|
+
const CLASS_NAMES = [
|
|
2320
|
+
// Add class names for theming
|
|
2321
|
+
"deck-widget",
|
|
2322
|
+
this.className,
|
|
2323
|
+
// plus any app-supplied class name
|
|
2324
|
+
this.props.className
|
|
2325
|
+
];
|
|
2326
|
+
const element = document.createElement("div");
|
|
2327
|
+
CLASS_NAMES.filter((cls) => typeof cls === "string" && cls.length > 0).forEach(
|
|
2328
|
+
(className) => element.classList.add(className)
|
|
2329
|
+
);
|
|
2330
|
+
applyStyles(element, this.props.style);
|
|
2331
|
+
return element;
|
|
2332
|
+
}
|
|
2333
|
+
/** Internal API called by Deck when the widget is first added to a Deck instance */
|
|
2334
|
+
_onAdd(params) {
|
|
2335
|
+
return this.onAdd(params) ?? this.onCreateRootElement();
|
|
2336
|
+
}
|
|
2337
|
+
/** Overridable by subclass - called when the widget is first added to a Deck instance
|
|
2338
|
+
* @returns an optional UI element that should be appended to the Deck container
|
|
2339
|
+
*/
|
|
2340
|
+
onAdd(params) {
|
|
2341
|
+
}
|
|
2342
|
+
/** Called when the widget is removed */
|
|
2343
|
+
onRemove() {
|
|
2344
|
+
}
|
|
2345
|
+
// deck integration - Event hooks
|
|
2346
|
+
/** Called when the containing view is changed */
|
|
2347
|
+
onViewportChange(viewport) {
|
|
2348
|
+
}
|
|
2349
|
+
/** Called when the containing view is redrawn */
|
|
2350
|
+
onRedraw(params) {
|
|
2351
|
+
}
|
|
2352
|
+
/** Called when a hover event occurs */
|
|
2353
|
+
onHover(info, event) {
|
|
2354
|
+
}
|
|
2355
|
+
/** Called when a click event occurs */
|
|
2356
|
+
onClick(info, event) {
|
|
2357
|
+
}
|
|
2358
|
+
/** Called when a drag event occurs */
|
|
2359
|
+
onDrag(info, event) {
|
|
2360
|
+
}
|
|
2361
|
+
/** Called when a dragstart event occurs */
|
|
2362
|
+
onDragStart(info, event) {
|
|
2363
|
+
}
|
|
2364
|
+
/** Called when a dragend event occurs */
|
|
2365
|
+
onDragEnd(info, event) {
|
|
2366
|
+
}
|
|
2367
|
+
};
|
|
2368
|
+
Widget.defaultProps = {
|
|
2369
|
+
id: "widget",
|
|
2370
|
+
style: {},
|
|
2371
|
+
_container: null,
|
|
2372
|
+
className: ""
|
|
2373
|
+
};
|
|
2374
|
+
|
|
2375
|
+
// ../core/src/viewports/globe-viewport.ts
|
|
2376
|
+
var import_core6 = require("@math.gl/core");
|
|
2377
|
+
var import_web_mercator4 = require("@math.gl/web-mercator");
|
|
2378
|
+
var DEGREES_TO_RADIANS2 = Math.PI / 180;
|
|
2379
|
+
var RADIANS_TO_DEGREES = 180 / Math.PI;
|
|
2380
|
+
var NORTH_UP_BEARING_THRESHOLD = 1;
|
|
2381
|
+
var EARTH_RADIUS = 6370972;
|
|
2382
|
+
var GLOBE_RADIUS = 256;
|
|
2383
|
+
var GLOBE_ZOOM_ANCHOR_DAMPING_START_RATIO = 0.75;
|
|
2384
|
+
var GLOBE_ZOOM_ANCHOR_MAX_DISTANCE_RATIO = 1.15;
|
|
2385
|
+
function isGlobeNorthUp(bearing) {
|
|
2386
|
+
const normalizedBearing = mod(bearing + 180, 360) - 180;
|
|
2387
|
+
return Math.abs(normalizedBearing) < NORTH_UP_BEARING_THRESHOLD;
|
|
2388
|
+
}
|
|
2389
|
+
function getDistanceScales2() {
|
|
2390
|
+
const unitsPerMeter2 = GLOBE_RADIUS / EARTH_RADIUS;
|
|
2391
|
+
const unitsPerDegree = Math.PI / 180 * GLOBE_RADIUS;
|
|
2392
|
+
return {
|
|
2393
|
+
unitsPerMeter: [unitsPerMeter2, unitsPerMeter2, unitsPerMeter2],
|
|
2394
|
+
unitsPerMeter2: [0, 0, 0],
|
|
2395
|
+
metersPerUnit: [1 / unitsPerMeter2, 1 / unitsPerMeter2, 1 / unitsPerMeter2],
|
|
2396
|
+
unitsPerDegree: [unitsPerDegree, unitsPerDegree, unitsPerMeter2],
|
|
2397
|
+
unitsPerDegree2: [0, 0, 0],
|
|
2398
|
+
degreesPerUnit: [1 / unitsPerDegree, 1 / unitsPerDegree, 1 / unitsPerMeter2]
|
|
2399
|
+
};
|
|
2400
|
+
}
|
|
2401
|
+
var GlobeViewport = class extends Viewport {
|
|
2402
|
+
constructor(opts = {}) {
|
|
2403
|
+
const {
|
|
2404
|
+
longitude = 0,
|
|
2405
|
+
bearing = 0,
|
|
2406
|
+
pitch = 0,
|
|
2407
|
+
zoom = 0,
|
|
2408
|
+
// Matches Maplibre defaults
|
|
2409
|
+
// https://github.com/maplibre/maplibre-gl-js/blob/f8ab4b48d59ab8fe7b068b102538793bbdd4c848/src/geo/projection/globe_transform.ts#L632-L633
|
|
2410
|
+
nearZMultiplier = 0.5,
|
|
2411
|
+
farZMultiplier = 1,
|
|
2412
|
+
resolution = 10
|
|
2413
|
+
} = opts;
|
|
2414
|
+
let { latitude = 0, height, altitude = 1.5, fovy } = opts;
|
|
2415
|
+
latitude = Math.max(Math.min(latitude, 90), -90);
|
|
2416
|
+
height = height || 1;
|
|
2417
|
+
if (fovy) {
|
|
2418
|
+
altitude = (0, import_web_mercator4.fovyToAltitude)(fovy);
|
|
2419
|
+
} else {
|
|
2420
|
+
fovy = (0, import_web_mercator4.altitudeToFovy)(altitude);
|
|
2421
|
+
}
|
|
2422
|
+
const scaleLatitude = Math.max(Math.min(latitude, import_web_mercator4.MAX_LATITUDE), -import_web_mercator4.MAX_LATITUDE);
|
|
2423
|
+
const scale = Math.pow(2, zoom - zoomAdjust(scaleLatitude));
|
|
2424
|
+
const pitchRadians = pitch * DEGREES_TO_RADIANS2;
|
|
2425
|
+
const nearZ = opts.nearZ ?? nearZMultiplier;
|
|
2426
|
+
const farZ = opts.farZ ?? (altitude + GLOBE_RADIUS * 2 * scale / height / Math.max(Math.cos(pitchRadians), 0.1)) * farZMultiplier;
|
|
2427
|
+
const viewMatrix2 = new import_core6.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);
|
|
2428
|
+
super({
|
|
2429
|
+
...opts,
|
|
2430
|
+
// x, y, width,
|
|
2431
|
+
height,
|
|
2432
|
+
// view matrix
|
|
2433
|
+
viewMatrix: viewMatrix2,
|
|
2434
|
+
longitude,
|
|
2435
|
+
latitude,
|
|
2436
|
+
zoom,
|
|
2437
|
+
// projection matrix parameters
|
|
2438
|
+
distanceScales: getDistanceScales2(),
|
|
2439
|
+
fovy,
|
|
2440
|
+
focalDistance: altitude,
|
|
2441
|
+
near: nearZ,
|
|
2442
|
+
far: farZ
|
|
2443
|
+
});
|
|
2444
|
+
this.scale = scale;
|
|
2445
|
+
this.latitude = latitude;
|
|
2446
|
+
this.longitude = longitude;
|
|
2447
|
+
this.bearing = bearing;
|
|
2448
|
+
this.pitch = pitch;
|
|
2449
|
+
this.fovy = fovy;
|
|
2450
|
+
this.resolution = resolution;
|
|
2451
|
+
}
|
|
2452
|
+
get projectionMode() {
|
|
2453
|
+
return PROJECTION_MODE.GLOBE;
|
|
2454
|
+
}
|
|
2455
|
+
getDistanceScales() {
|
|
2456
|
+
return this.distanceScales;
|
|
2457
|
+
}
|
|
2458
|
+
getBounds(options = {}) {
|
|
2459
|
+
const unprojectOption = { targetZ: options.z || 0 };
|
|
2460
|
+
const left = this.unproject([0, this.height / 2], unprojectOption);
|
|
2461
|
+
const top = this.unproject([this.width / 2, 0], unprojectOption);
|
|
2462
|
+
const right = this.unproject([this.width, this.height / 2], unprojectOption);
|
|
2463
|
+
const bottom = this.unproject([this.width / 2, this.height], unprojectOption);
|
|
2464
|
+
if (right[0] < this.longitude) right[0] += 360;
|
|
2465
|
+
if (left[0] > this.longitude) left[0] -= 360;
|
|
2466
|
+
return [
|
|
2467
|
+
Math.min(left[0], right[0], top[0], bottom[0]),
|
|
2468
|
+
Math.min(left[1], right[1], top[1], bottom[1]),
|
|
2469
|
+
Math.max(left[0], right[0], top[0], bottom[0]),
|
|
2470
|
+
Math.max(left[1], right[1], top[1], bottom[1])
|
|
2471
|
+
];
|
|
2472
|
+
}
|
|
2473
|
+
/**
|
|
2474
|
+
* Builds the screen-pixel → globe-center ray and the intermediate ray/sphere
|
|
2475
|
+
* math reused by `unproject` and anchored zoom. One function so the same
|
|
2476
|
+
* pixelUnprojectionMatrix work isn't duplicated.
|
|
2477
|
+
*/
|
|
2478
|
+
_getRayToGlobe(screenPosition, { topLeft = true, targetZ } = {}) {
|
|
2479
|
+
const [screenX, screenY] = screenPosition;
|
|
2480
|
+
const adjustedScreenY = topLeft ? screenY : this.height - screenY;
|
|
2481
|
+
const { pixelUnprojectionMatrix } = this;
|
|
2482
|
+
const rayStartPosition = transformVector(pixelUnprojectionMatrix, [
|
|
2483
|
+
screenX,
|
|
2484
|
+
adjustedScreenY,
|
|
2485
|
+
-1,
|
|
2486
|
+
1
|
|
2487
|
+
]);
|
|
2488
|
+
const rayEndPosition = transformVector(pixelUnprojectionMatrix, [
|
|
2489
|
+
screenX,
|
|
2490
|
+
adjustedScreenY,
|
|
2491
|
+
1,
|
|
2492
|
+
1
|
|
2493
|
+
]);
|
|
2494
|
+
const radius = ((targetZ || 0) / EARTH_RADIUS + 1) * GLOBE_RADIUS;
|
|
2495
|
+
const rayLengthSquared = import_core6.vec3.sqrLen(import_core6.vec3.sub([], rayStartPosition, rayEndPosition));
|
|
2496
|
+
const rayStartDistanceSquared = import_core6.vec3.sqrLen(rayStartPosition);
|
|
2497
|
+
const rayEndDistanceSquared = import_core6.vec3.sqrLen(rayEndPosition);
|
|
2498
|
+
const triangleAreaSquared = (4 * rayStartDistanceSquared * rayEndDistanceSquared - (rayLengthSquared - rayStartDistanceSquared - rayEndDistanceSquared) ** 2) / 16;
|
|
2499
|
+
const distanceToCenterSquared = 4 * triangleAreaSquared / rayLengthSquared;
|
|
2500
|
+
return {
|
|
2501
|
+
rayStartPosition,
|
|
2502
|
+
rayEndPosition,
|
|
2503
|
+
radius,
|
|
2504
|
+
rayLengthSquared,
|
|
2505
|
+
rayStartDistanceSquared,
|
|
2506
|
+
distanceToCenterSquared
|
|
2507
|
+
};
|
|
2508
|
+
}
|
|
2509
|
+
_getRayDistanceToGlobeCenterRatio(screenPosition, options) {
|
|
2510
|
+
const { distanceToCenterSquared, radius } = this._getRayToGlobe(screenPosition, options);
|
|
2511
|
+
return Math.sqrt(Math.max(0, distanceToCenterSquared)) / radius;
|
|
2512
|
+
}
|
|
2513
|
+
/**
|
|
2514
|
+
* Returns how strongly a screen position should anchor zoom on the visible globe.
|
|
2515
|
+
* A value of `0` means that the controller should fall back to center zoom.
|
|
2516
|
+
* @param screenPosition - Screen position to evaluate.
|
|
2517
|
+
* @returns Anchor strength from `0` to `1`.
|
|
2518
|
+
*/
|
|
2519
|
+
getZoomAnchorStrength(screenPosition) {
|
|
2520
|
+
const distanceRatio = this._getRayDistanceToGlobeCenterRatio(screenPosition);
|
|
2521
|
+
if (distanceRatio >= GLOBE_ZOOM_ANCHOR_MAX_DISTANCE_RATIO) {
|
|
2522
|
+
return 0;
|
|
2523
|
+
}
|
|
2524
|
+
const edgeProgress = Math.max(
|
|
2525
|
+
0,
|
|
2526
|
+
Math.min(
|
|
2527
|
+
1,
|
|
2528
|
+
(distanceRatio - GLOBE_ZOOM_ANCHOR_DAMPING_START_RATIO) / (GLOBE_ZOOM_ANCHOR_MAX_DISTANCE_RATIO - GLOBE_ZOOM_ANCHOR_DAMPING_START_RATIO)
|
|
2529
|
+
)
|
|
2530
|
+
);
|
|
2531
|
+
const smoothProgress = edgeProgress * edgeProgress * (3 - 2 * edgeProgress);
|
|
2532
|
+
return 1 - smoothProgress;
|
|
2533
|
+
}
|
|
2534
|
+
unproject(xyz, { topLeft = true, targetZ } = {}) {
|
|
2535
|
+
const [x, y, z] = xyz;
|
|
2536
|
+
const y2 = topLeft ? y : this.height - y;
|
|
2537
|
+
const { pixelUnprojectionMatrix } = this;
|
|
2538
|
+
let coord;
|
|
2539
|
+
if (Number.isFinite(z)) {
|
|
2540
|
+
coord = transformVector(pixelUnprojectionMatrix, [x, y2, z, 1]);
|
|
2541
|
+
} else {
|
|
2542
|
+
const {
|
|
2543
|
+
rayStartPosition,
|
|
2544
|
+
rayEndPosition,
|
|
2545
|
+
radius,
|
|
2546
|
+
rayLengthSquared,
|
|
2547
|
+
rayStartDistanceSquared,
|
|
2548
|
+
distanceToCenterSquared
|
|
2549
|
+
} = this._getRayToGlobe(xyz, { topLeft, targetZ });
|
|
2550
|
+
const rayStartToClosestApproach = Math.sqrt(
|
|
2551
|
+
rayStartDistanceSquared - distanceToCenterSquared
|
|
2552
|
+
);
|
|
2553
|
+
const closestApproachToIntersection = Math.sqrt(
|
|
2554
|
+
Math.max(0, radius * radius - distanceToCenterSquared)
|
|
2555
|
+
);
|
|
2556
|
+
const intersectionRatio = (rayStartToClosestApproach - closestApproachToIntersection) / Math.sqrt(rayLengthSquared);
|
|
2557
|
+
coord = import_core6.vec3.lerp([], rayStartPosition, rayEndPosition, intersectionRatio);
|
|
2558
|
+
}
|
|
2559
|
+
const [X, Y, Z] = this.unprojectPosition(coord);
|
|
2560
|
+
if (Number.isFinite(z)) {
|
|
2561
|
+
return [X, Y, Z];
|
|
2562
|
+
}
|
|
2563
|
+
return Number.isFinite(targetZ) ? [X, Y, targetZ] : [X, Y];
|
|
2564
|
+
}
|
|
2565
|
+
projectPosition(xyz) {
|
|
2566
|
+
const [lng, lat, Z = 0] = xyz;
|
|
2567
|
+
const lambda = lng * DEGREES_TO_RADIANS2;
|
|
2568
|
+
const phi = lat * DEGREES_TO_RADIANS2;
|
|
2569
|
+
const cosPhi = Math.cos(phi);
|
|
2570
|
+
const D = (Z / EARTH_RADIUS + 1) * GLOBE_RADIUS;
|
|
2571
|
+
return [Math.sin(lambda) * cosPhi * D, -Math.cos(lambda) * cosPhi * D, Math.sin(phi) * D];
|
|
2572
|
+
}
|
|
2573
|
+
unprojectPosition(xyz) {
|
|
2574
|
+
const [x, y, z] = xyz;
|
|
2575
|
+
const D = import_core6.vec3.len(xyz);
|
|
2576
|
+
const phi = Math.asin(z / D);
|
|
2577
|
+
const lambda = Math.atan2(x, -y);
|
|
2578
|
+
const lng = lambda * RADIANS_TO_DEGREES;
|
|
2579
|
+
const lat = phi * RADIANS_TO_DEGREES;
|
|
2580
|
+
const Z = (D / GLOBE_RADIUS - 1) * EARTH_RADIUS;
|
|
2581
|
+
return [lng, lat, Z];
|
|
2582
|
+
}
|
|
2583
|
+
projectFlat(xyz) {
|
|
2584
|
+
return xyz;
|
|
2585
|
+
}
|
|
2586
|
+
unprojectFlat(xyz) {
|
|
2587
|
+
return xyz;
|
|
2588
|
+
}
|
|
2589
|
+
/**
|
|
2590
|
+
* Pan the globe to place geographic coordinates at a screen pixel.
|
|
2591
|
+
* When `dragStartPosition` is supplied, applies the delta-based movement used by globe dragging.
|
|
2592
|
+
* @param coordinates - Geographic anchor, or the starting longitude, latitude and zoom.
|
|
2593
|
+
* @param screenPosition - Current screen position.
|
|
2594
|
+
* @param dragStartPosition - Screen position where a drag started.
|
|
2595
|
+
* @returns Updated viewport options.
|
|
2596
|
+
*/
|
|
2597
|
+
panByPosition(coordinates, screenPosition, dragStartPosition) {
|
|
2598
|
+
if (!dragStartPosition) {
|
|
2599
|
+
let anchorStrength = this.getZoomAnchorStrength(screenPosition);
|
|
2600
|
+
if (anchorStrength === 0) {
|
|
2601
|
+
return { longitude: this.longitude, latitude: this.latitude };
|
|
2602
|
+
}
|
|
2603
|
+
const currentCoordinates = this.unproject(screenPosition);
|
|
2604
|
+
const longitudeDelta = mod(coordinates[0] - currentCoordinates[0] + 180, 360) - 180;
|
|
2605
|
+
const latitudeDelta = coordinates[1] - currentCoordinates[1];
|
|
2606
|
+
const crossesPole = Math.abs(currentCoordinates[1]) > import_web_mercator4.MAX_LATITUDE || Math.abs(longitudeDelta) > 90;
|
|
2607
|
+
if (isGlobeNorthUp(this.bearing) && crossesPole) {
|
|
2608
|
+
return { longitude: this.longitude, latitude: this.latitude };
|
|
2609
|
+
}
|
|
2610
|
+
if (isGlobeNorthUp(this.bearing) && latitudeDelta !== 0) {
|
|
2611
|
+
const latitudeLimit = latitudeDelta > 0 ? import_web_mercator4.MAX_LATITUDE : -import_web_mercator4.MAX_LATITUDE;
|
|
2612
|
+
const latitudeConstraintStrength = (latitudeLimit - this.latitude) / latitudeDelta;
|
|
2613
|
+
anchorStrength = Math.min(anchorStrength, Math.max(0, latitudeConstraintStrength));
|
|
2614
|
+
}
|
|
2615
|
+
const longitude2 = this.longitude + longitudeDelta * anchorStrength;
|
|
2616
|
+
const latitude2 = Math.max(Math.min(this.latitude + latitudeDelta * anchorStrength, 90), -90);
|
|
2617
|
+
return { longitude: longitude2, latitude: latitude2 };
|
|
2618
|
+
}
|
|
2619
|
+
const [startLongitude, startLatitude, startZoom] = coordinates;
|
|
2620
|
+
const scale = Math.pow(2, this.zoom - zoomAdjust(this.latitude));
|
|
2621
|
+
const rotationSpeed = 0.25 / scale;
|
|
2622
|
+
const longitude = startLongitude + rotationSpeed * (dragStartPosition[0] - screenPosition[0]);
|
|
2623
|
+
let latitude = startLatitude - rotationSpeed * (dragStartPosition[1] - screenPosition[1]);
|
|
2624
|
+
latitude = Math.max(Math.min(latitude, 90), -90);
|
|
2625
|
+
const nextViewState = { longitude, latitude, zoom: startZoom - zoomAdjust(startLatitude) };
|
|
2626
|
+
nextViewState.zoom += zoomAdjust(nextViewState.latitude);
|
|
2627
|
+
return nextViewState;
|
|
2628
|
+
}
|
|
2629
|
+
};
|
|
2630
|
+
GlobeViewport.displayName = "GlobeViewport";
|
|
2631
|
+
function zoomAdjust(latitude, clampToPoles) {
|
|
2632
|
+
if (clampToPoles) {
|
|
2633
|
+
latitude = Math.max(Math.min(latitude, import_web_mercator4.MAX_LATITUDE), -import_web_mercator4.MAX_LATITUDE);
|
|
2634
|
+
}
|
|
2635
|
+
const scaleAdjust = Math.PI * Math.cos(latitude * Math.PI / 180);
|
|
2636
|
+
return Math.log2(scaleAdjust);
|
|
2637
|
+
}
|
|
2638
|
+
function transformVector(matrix, vector) {
|
|
2639
|
+
const result = import_core6.vec4.transformMat4([], vector, matrix);
|
|
2640
|
+
import_core6.vec4.scale(result, result, 1 / result[3]);
|
|
2641
|
+
return result;
|
|
2642
|
+
}
|
|
2643
|
+
|
|
2644
|
+
// ../core/src/viewports/orthographic-viewport.ts
|
|
2645
|
+
var import_core7 = require("@math.gl/core");
|
|
2646
|
+
var import_web_mercator5 = require("@math.gl/web-mercator");
|
|
2647
|
+
var viewMatrix = new import_core7.Matrix4().lookAt({ eye: [0, 0, 1] });
|
|
2648
|
+
function getProjectionMatrix({
|
|
2649
|
+
width,
|
|
2650
|
+
height,
|
|
2651
|
+
near,
|
|
2652
|
+
far,
|
|
2653
|
+
padding
|
|
2654
|
+
}) {
|
|
2655
|
+
let left = -width / 2;
|
|
2656
|
+
let right = width / 2;
|
|
2657
|
+
let bottom = -height / 2;
|
|
2658
|
+
let top = height / 2;
|
|
2659
|
+
if (padding) {
|
|
2660
|
+
const { left: l = 0, right: r = 0, top: t = 0, bottom: b = 0 } = padding;
|
|
2661
|
+
const offsetX = (0, import_core7.clamp)((l + width - r) / 2, 0, width) - width / 2;
|
|
2662
|
+
const offsetY = (0, import_core7.clamp)((t + height - b) / 2, 0, height) - height / 2;
|
|
2663
|
+
left -= offsetX;
|
|
2664
|
+
right -= offsetX;
|
|
2665
|
+
bottom += offsetY;
|
|
2666
|
+
top += offsetY;
|
|
2667
|
+
}
|
|
2668
|
+
return new import_core7.Matrix4().ortho({
|
|
2669
|
+
left,
|
|
2670
|
+
right,
|
|
2671
|
+
bottom,
|
|
2672
|
+
top,
|
|
2673
|
+
near,
|
|
2674
|
+
far
|
|
2675
|
+
});
|
|
2676
|
+
}
|
|
2677
|
+
var OrthographicViewport = class extends Viewport {
|
|
2678
|
+
constructor(props) {
|
|
2679
|
+
const {
|
|
2680
|
+
width,
|
|
2681
|
+
height,
|
|
2682
|
+
near = 0.1,
|
|
2683
|
+
far = 1e3,
|
|
2684
|
+
zoom = 0,
|
|
2685
|
+
target = [0, 0, 0],
|
|
2686
|
+
padding = null,
|
|
2687
|
+
flipY = true
|
|
2688
|
+
} = props;
|
|
2689
|
+
const zoomX = props.zoomX ?? (Array.isArray(zoom) ? zoom[0] : zoom);
|
|
2690
|
+
const zoomY = props.zoomY ?? (Array.isArray(zoom) ? zoom[1] : zoom);
|
|
2691
|
+
const zoom_ = Number.isFinite(props.zoom) ? props.zoom : Math.min(zoomX, zoomY);
|
|
2692
|
+
const scale = Math.pow(2, zoom_);
|
|
2693
|
+
let distanceScales;
|
|
2694
|
+
if (zoomX !== zoom_ || zoomY !== zoom_) {
|
|
2695
|
+
const scaleX = Math.pow(2, zoomX);
|
|
2696
|
+
const scaleY = Math.pow(2, zoomY);
|
|
2697
|
+
distanceScales = {
|
|
2698
|
+
unitsPerMeter: [scaleX / scale, scaleY / scale, 1],
|
|
2699
|
+
metersPerUnit: [scale / scaleX, scale / scaleY, 1]
|
|
2700
|
+
};
|
|
2701
|
+
}
|
|
2702
|
+
super({
|
|
2703
|
+
...props,
|
|
2704
|
+
// in case viewState contains longitude/latitude values,
|
|
2705
|
+
// make sure that the base Viewport class does not treat this as a geospatial viewport
|
|
2706
|
+
longitude: void 0,
|
|
2707
|
+
position: target,
|
|
2708
|
+
viewMatrix: viewMatrix.clone().scale([scale, scale * (flipY ? -1 : 1), scale]),
|
|
2709
|
+
projectionMatrix: getProjectionMatrix({
|
|
2710
|
+
width: width || 1,
|
|
2711
|
+
height: height || 1,
|
|
2712
|
+
padding,
|
|
2713
|
+
near,
|
|
2714
|
+
far
|
|
2715
|
+
}),
|
|
2716
|
+
zoom: zoom_,
|
|
2717
|
+
distanceScales
|
|
2718
|
+
});
|
|
2719
|
+
this.target = target;
|
|
2720
|
+
this.zoomX = zoomX;
|
|
2721
|
+
this.zoomY = zoomY;
|
|
2722
|
+
this.flipY = flipY;
|
|
2723
|
+
}
|
|
2724
|
+
projectFlat([X, Y]) {
|
|
2725
|
+
const { unitsPerMeter: unitsPerMeter2 } = this.distanceScales;
|
|
2726
|
+
return [X * unitsPerMeter2[0], Y * unitsPerMeter2[1]];
|
|
2727
|
+
}
|
|
2728
|
+
unprojectFlat([x, y]) {
|
|
2729
|
+
const { metersPerUnit } = this.distanceScales;
|
|
2730
|
+
return [x * metersPerUnit[0], y * metersPerUnit[1]];
|
|
2731
|
+
}
|
|
2732
|
+
/* Needed by LinearInterpolator */
|
|
2733
|
+
panByPosition(coords, pixel, startPixel) {
|
|
2734
|
+
const fromLocation = (0, import_web_mercator5.pixelsToWorld)(pixel, this.pixelUnprojectionMatrix);
|
|
2735
|
+
const toLocation = this.projectFlat(coords);
|
|
2736
|
+
const translate = import_core7.vec2.add([], toLocation, import_core7.vec2.negate([], fromLocation));
|
|
2737
|
+
const newCenter = import_core7.vec2.add([], this.center, translate);
|
|
2738
|
+
return { target: this.unprojectFlat(newCenter) };
|
|
2739
|
+
}
|
|
2740
|
+
};
|
|
2741
|
+
OrthographicViewport.displayName = "OrthographicViewport";
|
|
2742
|
+
|
|
2743
|
+
// ../core/src/controllers/orthographic-controller.ts
|
|
2744
|
+
var import_core8 = require("@math.gl/core");
|
|
2745
|
+
var ZOOM_RUBBER_BAND_RANGE = 1;
|
|
2746
|
+
function normalizeZoom({
|
|
2747
|
+
zoom = 0,
|
|
2748
|
+
zoomX,
|
|
2749
|
+
zoomY
|
|
2750
|
+
}) {
|
|
2751
|
+
zoomX = zoomX ?? (Array.isArray(zoom) ? zoom[0] : zoom);
|
|
2752
|
+
zoomY = zoomY ?? (Array.isArray(zoom) ? zoom[1] : zoom);
|
|
2753
|
+
return { zoomX, zoomY };
|
|
2754
|
+
}
|
|
2755
|
+
function getAxisBounds(maxBounds, index, negativeExtent, positiveExtent, target) {
|
|
2756
|
+
const minimum = maxBounds[0][index] + negativeExtent;
|
|
2757
|
+
const maximum = maxBounds[1][index] - positiveExtent;
|
|
2758
|
+
const midpoint = (minimum + maximum) / 2;
|
|
2759
|
+
return {
|
|
2760
|
+
minimum,
|
|
2761
|
+
maximum,
|
|
2762
|
+
midpoint,
|
|
2763
|
+
settledTarget: Number.isFinite(negativeExtent) && Number.isFinite(positiveExtent) && minimum <= maximum ? (0, import_core8.clamp)(target, minimum, maximum) : midpoint
|
|
2764
|
+
};
|
|
2765
|
+
}
|
|
2766
|
+
var OrthographicState = class extends ViewState {
|
|
2767
|
+
constructor(options) {
|
|
2768
|
+
const {
|
|
2769
|
+
/* Viewport arguments */
|
|
2770
|
+
width,
|
|
2771
|
+
// Width of viewport
|
|
2772
|
+
height,
|
|
2773
|
+
// Height of viewport
|
|
2774
|
+
target = [0, 0, 0],
|
|
2775
|
+
zoom = 0,
|
|
2776
|
+
zoomAxis = "all",
|
|
2777
|
+
/* Viewport constraints */
|
|
2778
|
+
minZoom = -Infinity,
|
|
2779
|
+
maxZoom = Infinity,
|
|
2780
|
+
minZoomX = minZoom,
|
|
2781
|
+
maxZoomX = maxZoom,
|
|
2782
|
+
minZoomY = minZoom,
|
|
2783
|
+
maxZoomY = maxZoom,
|
|
2784
|
+
maxBounds = null,
|
|
2785
|
+
maxBoundsPadding = null,
|
|
2786
|
+
rubberBand = false,
|
|
2787
|
+
/** Interaction states, required to calculate change during transform */
|
|
2788
|
+
// Model state when the pan operation first started
|
|
2789
|
+
startPanPosition,
|
|
2790
|
+
// Model state when the zoom operation first started
|
|
2791
|
+
startZoomPosition,
|
|
2792
|
+
startZoom
|
|
2793
|
+
} = options;
|
|
2794
|
+
const { [CONSTRAINT_AROUND]: constraintAround } = options;
|
|
2795
|
+
const { zoomX, zoomY } = normalizeZoom(options);
|
|
2796
|
+
super(
|
|
2797
|
+
{
|
|
2798
|
+
width,
|
|
2799
|
+
height,
|
|
2800
|
+
target,
|
|
2801
|
+
zoom,
|
|
2802
|
+
zoomX,
|
|
2803
|
+
zoomY,
|
|
2804
|
+
zoomAxis,
|
|
2805
|
+
minZoomX,
|
|
2806
|
+
maxZoomX,
|
|
2807
|
+
minZoomY,
|
|
2808
|
+
maxZoomY,
|
|
2809
|
+
maxBounds,
|
|
2810
|
+
maxBoundsPadding,
|
|
2811
|
+
rubberBand,
|
|
2812
|
+
...{ [CONSTRAINT_AROUND]: constraintAround }
|
|
2813
|
+
},
|
|
2814
|
+
{
|
|
2815
|
+
startPanPosition,
|
|
2816
|
+
startZoomPosition,
|
|
2817
|
+
startZoom
|
|
2818
|
+
},
|
|
2819
|
+
options.makeViewport,
|
|
2820
|
+
options.constraintContext
|
|
2821
|
+
);
|
|
2822
|
+
}
|
|
2823
|
+
/**
|
|
2824
|
+
* Start panning
|
|
2825
|
+
* @param {[Number, Number]} pos - position on screen where the pointer grabs
|
|
2826
|
+
*/
|
|
2827
|
+
panStart({ pos }, constraintContext) {
|
|
2828
|
+
return this._getUpdatedState({ startPanPosition: this._unproject(pos) }, constraintContext);
|
|
2829
|
+
}
|
|
2830
|
+
/**
|
|
2831
|
+
* Pan
|
|
2832
|
+
* @param {[Number, Number]} pos - position on screen where the pointer is
|
|
2833
|
+
*/
|
|
2834
|
+
pan({ pos, startPosition }, constraintContext) {
|
|
2835
|
+
const startPanPosition = this.getState().startPanPosition || startPosition;
|
|
2836
|
+
if (!startPanPosition) {
|
|
2837
|
+
return this;
|
|
2838
|
+
}
|
|
2839
|
+
const viewport = this.makeViewport(this.getViewportProps());
|
|
2840
|
+
const newProps = viewport.panByPosition(startPanPosition, pos);
|
|
2841
|
+
return this._getUpdatedState(newProps, constraintContext);
|
|
2842
|
+
}
|
|
2843
|
+
/**
|
|
2844
|
+
* End panning
|
|
2845
|
+
* Must call if `panStart()` was called
|
|
2846
|
+
*/
|
|
2847
|
+
panEnd(constraintContext) {
|
|
2848
|
+
return this._getUpdatedState({ startPanPosition: null }, constraintContext);
|
|
2849
|
+
}
|
|
2850
|
+
/**
|
|
2851
|
+
* Start rotating
|
|
2852
|
+
*/
|
|
2853
|
+
rotateStart() {
|
|
2854
|
+
return this;
|
|
2855
|
+
}
|
|
2856
|
+
/**
|
|
2857
|
+
* Rotate
|
|
2858
|
+
*/
|
|
2859
|
+
rotate() {
|
|
2860
|
+
return this;
|
|
2861
|
+
}
|
|
2862
|
+
/**
|
|
2863
|
+
* End rotating
|
|
2864
|
+
*/
|
|
2865
|
+
rotateEnd() {
|
|
2866
|
+
return this;
|
|
2867
|
+
}
|
|
2868
|
+
// shortest path between two view states
|
|
2869
|
+
shortestPathFrom(viewState) {
|
|
2870
|
+
const fromProps = viewState.getViewportProps();
|
|
2871
|
+
const props = { ...this.getViewportProps() };
|
|
2872
|
+
return props;
|
|
2873
|
+
}
|
|
2874
|
+
/**
|
|
2875
|
+
* Start zooming
|
|
2876
|
+
* @param {[Number, Number]} pos - position on screen where the pointer grabs
|
|
2877
|
+
*/
|
|
2878
|
+
zoomStart({ pos }, constraintContext) {
|
|
2879
|
+
const { zoomX, zoomY } = this.getViewportProps();
|
|
2880
|
+
return this._getUpdatedState(
|
|
2881
|
+
{
|
|
2882
|
+
startZoomPosition: this._unproject(pos),
|
|
2883
|
+
startZoom: [zoomX, zoomY]
|
|
2884
|
+
},
|
|
2885
|
+
constraintContext
|
|
2886
|
+
);
|
|
2887
|
+
}
|
|
2888
|
+
/**
|
|
2889
|
+
* Zoom
|
|
2890
|
+
* @param {[Number, Number]} pos - position on screen where the current target is
|
|
2891
|
+
* @param {[Number, Number]} startPos - the target position at
|
|
2892
|
+
* the start of the operation. Must be supplied of `zoomStart()` was not called
|
|
2893
|
+
* @param {Number} scale - a number between [0, 1] specifying the accumulated
|
|
2894
|
+
* relative scale.
|
|
2895
|
+
*/
|
|
2896
|
+
zoom({
|
|
2897
|
+
pos,
|
|
2898
|
+
startPos,
|
|
2899
|
+
scale
|
|
2900
|
+
}, constraintContext) {
|
|
2901
|
+
let { startZoom, startZoomPosition } = this.getState();
|
|
2902
|
+
if (!startZoomPosition) {
|
|
2903
|
+
const { zoomX, zoomY } = this.getViewportProps();
|
|
2904
|
+
startZoom = [zoomX, zoomY];
|
|
2905
|
+
startZoomPosition = this._unproject(startPos || pos);
|
|
2906
|
+
}
|
|
2907
|
+
if (!startZoomPosition) {
|
|
2908
|
+
return this;
|
|
2909
|
+
}
|
|
2910
|
+
const newZoomProps = this._calculateNewZoom({ scale, startZoom });
|
|
2911
|
+
return this._getUpdatedState(
|
|
2912
|
+
{
|
|
2913
|
+
...newZoomProps,
|
|
2914
|
+
[CONSTRAINT_AROUND]: { position: startZoomPosition, screenPosition: pos }
|
|
2915
|
+
},
|
|
2916
|
+
constraintContext
|
|
2917
|
+
);
|
|
2918
|
+
}
|
|
2919
|
+
/**
|
|
2920
|
+
* End zooming
|
|
2921
|
+
* Must call if `zoomStart()` was called
|
|
2922
|
+
*/
|
|
2923
|
+
zoomEnd(constraintContext) {
|
|
2924
|
+
return this._getUpdatedState(
|
|
2925
|
+
{
|
|
2926
|
+
startZoomPosition: null,
|
|
2927
|
+
startZoom: null
|
|
2928
|
+
},
|
|
2929
|
+
constraintContext
|
|
2930
|
+
);
|
|
2931
|
+
}
|
|
2932
|
+
zoomIn(speed = 2, constraintContext) {
|
|
2933
|
+
return this._getUpdatedState(this._calculateNewZoom({ scale: speed }), constraintContext);
|
|
2934
|
+
}
|
|
2935
|
+
zoomOut(speed = 2, constraintContext) {
|
|
2936
|
+
return this._getUpdatedState(this._calculateNewZoom({ scale: 1 / speed }), constraintContext);
|
|
2937
|
+
}
|
|
2938
|
+
moveLeft(speed = 50, constraintContext) {
|
|
2939
|
+
return this._panFromCenter([-speed, 0], constraintContext);
|
|
2940
|
+
}
|
|
2941
|
+
moveRight(speed = 50, constraintContext) {
|
|
2942
|
+
return this._panFromCenter([speed, 0], constraintContext);
|
|
2943
|
+
}
|
|
2944
|
+
moveUp(speed = 50, constraintContext) {
|
|
2945
|
+
return this._panFromCenter([0, -speed], constraintContext);
|
|
2946
|
+
}
|
|
2947
|
+
moveDown(speed = 50, constraintContext) {
|
|
2948
|
+
return this._panFromCenter([0, speed], constraintContext);
|
|
2949
|
+
}
|
|
2950
|
+
rotateLeft(speed = 15) {
|
|
2951
|
+
return this;
|
|
2952
|
+
}
|
|
2953
|
+
rotateRight(speed = 15) {
|
|
2954
|
+
return this;
|
|
2955
|
+
}
|
|
2956
|
+
rotateUp(speed = 10) {
|
|
2957
|
+
return this;
|
|
2958
|
+
}
|
|
2959
|
+
rotateDown(speed = 10) {
|
|
2960
|
+
return this;
|
|
2961
|
+
}
|
|
2962
|
+
/* Private methods */
|
|
2963
|
+
_project(pos) {
|
|
2964
|
+
const viewport = this.makeViewport(this.getViewportProps());
|
|
2965
|
+
return viewport.project(pos);
|
|
2966
|
+
}
|
|
2967
|
+
_unproject(pos) {
|
|
2968
|
+
const viewport = this.makeViewport(this.getViewportProps());
|
|
2969
|
+
const [x, y] = viewport.unproject(pos);
|
|
2970
|
+
return [x, y];
|
|
2971
|
+
}
|
|
2972
|
+
// Calculates new zoom
|
|
2973
|
+
_calculateNewZoom({ scale, startZoom }) {
|
|
2974
|
+
const { zoomX, zoomY, zoomAxis } = this.getViewportProps();
|
|
2975
|
+
if (startZoom === void 0) {
|
|
2976
|
+
startZoom = [zoomX, zoomY];
|
|
2977
|
+
}
|
|
2978
|
+
const deltaZoom = Math.log2(scale);
|
|
2979
|
+
let [newZoomX, newZoomY] = startZoom;
|
|
2980
|
+
switch (zoomAxis) {
|
|
2981
|
+
case "X":
|
|
2982
|
+
newZoomX += deltaZoom;
|
|
2983
|
+
break;
|
|
2984
|
+
case "Y":
|
|
2985
|
+
newZoomY += deltaZoom;
|
|
2986
|
+
break;
|
|
2987
|
+
default:
|
|
2988
|
+
newZoomX += deltaZoom;
|
|
2989
|
+
newZoomY += deltaZoom;
|
|
2990
|
+
}
|
|
2991
|
+
return {
|
|
2992
|
+
zoomX: newZoomX,
|
|
2993
|
+
zoomY: newZoomY
|
|
2994
|
+
};
|
|
2995
|
+
}
|
|
2996
|
+
_panFromCenter(offset3, constraintContext) {
|
|
2997
|
+
const { target } = this.getViewportProps();
|
|
2998
|
+
const center = this._project(target);
|
|
2999
|
+
return this.pan(
|
|
3000
|
+
{
|
|
3001
|
+
startPosition: target,
|
|
3002
|
+
pos: [center[0] + offset3[0], center[1] + offset3[1]]
|
|
3003
|
+
},
|
|
3004
|
+
constraintContext
|
|
3005
|
+
);
|
|
3006
|
+
}
|
|
3007
|
+
_getUpdatedState(newProps, constraintContext) {
|
|
3008
|
+
return new this.constructor({
|
|
3009
|
+
makeViewport: this.makeViewport,
|
|
3010
|
+
...this.getViewportProps(),
|
|
3011
|
+
...this.getState(),
|
|
3012
|
+
...newProps,
|
|
3013
|
+
constraintContext
|
|
3014
|
+
});
|
|
3015
|
+
}
|
|
3016
|
+
// Apply any constraints (mathematical or defined by _viewportProps) to map state
|
|
3017
|
+
applyConstraints(props, constraintContext) {
|
|
3018
|
+
const internalProps = props;
|
|
3019
|
+
const constraintAround = internalProps[CONSTRAINT_AROUND];
|
|
3020
|
+
delete internalProps[CONSTRAINT_AROUND];
|
|
3021
|
+
const normalizedZoom = normalizeZoom(props);
|
|
3022
|
+
const constrainedZoom = this._constrainZoom(normalizedZoom, props);
|
|
3023
|
+
const shouldRubberBand = props.rubberBand && (constraintContext == null ? void 0 : constraintContext.mode) === "elastic";
|
|
3024
|
+
const { zoomX, zoomY } = (constraintContext == null ? void 0 : constraintContext.mode) === "preserve" ? normalizedZoom : shouldRubberBand ? {
|
|
3025
|
+
zoomX: applyRubberBand(
|
|
3026
|
+
normalizedZoom.zoomX,
|
|
3027
|
+
constrainedZoom.zoomX,
|
|
3028
|
+
ZOOM_RUBBER_BAND_RANGE
|
|
3029
|
+
),
|
|
3030
|
+
zoomY: applyRubberBand(
|
|
3031
|
+
normalizedZoom.zoomY,
|
|
3032
|
+
constrainedZoom.zoomY,
|
|
3033
|
+
ZOOM_RUBBER_BAND_RANGE
|
|
3034
|
+
)
|
|
3035
|
+
} : constrainedZoom;
|
|
3036
|
+
props.zoomX = zoomX;
|
|
3037
|
+
props.zoomY = zoomY;
|
|
3038
|
+
if (constraintAround) {
|
|
3039
|
+
const viewport = this.makeViewport({ ...props, zoomX, zoomY });
|
|
3040
|
+
Object.assign(
|
|
3041
|
+
props,
|
|
3042
|
+
viewport.panByPosition(constraintAround.position, constraintAround.screenPosition)
|
|
3043
|
+
);
|
|
3044
|
+
}
|
|
3045
|
+
props.zoom = Array.isArray(props.zoom) || props.zoomX !== props.zoomY ? [props.zoomX, props.zoomY] : props.zoomX;
|
|
3046
|
+
const { maxBounds, rubberBand, target } = props;
|
|
3047
|
+
if (maxBounds) {
|
|
3048
|
+
const maxBoundsRect = getMaxBoundsRect(props.width, props.height, props.maxBoundsPadding);
|
|
3049
|
+
const viewport = this.makeViewport(props);
|
|
3050
|
+
const screenExtents = getMaxBoundsExtents(viewport, target, maxBoundsRect);
|
|
3051
|
+
const projectedTarget = viewport.project(target);
|
|
3052
|
+
const pixelsPerUnit = [0, 1].map((index) => {
|
|
3053
|
+
const sampleTarget = target.slice();
|
|
3054
|
+
sampleTarget[index] += 1;
|
|
3055
|
+
const projectedDelta = viewport.project(sampleTarget)[index] - projectedTarget[index];
|
|
3056
|
+
return Number.isFinite(projectedDelta) ? projectedDelta : 2 ** (index === 0 ? zoomX : zoomY) * (index === 0 ? 1 : -1);
|
|
3057
|
+
});
|
|
3058
|
+
const worldExtents = pixelsPerUnit.map((projectedDelta, index) => {
|
|
3059
|
+
const negativeScreenExtent = index === 0 ? screenExtents.left : screenExtents.top;
|
|
3060
|
+
const positiveScreenExtent = index === 0 ? screenExtents.right : screenExtents.bottom;
|
|
3061
|
+
const scale = Math.abs(projectedDelta);
|
|
3062
|
+
return projectedDelta >= 0 ? [negativeScreenExtent / scale, positiveScreenExtent / scale] : [positiveScreenExtent / scale, negativeScreenExtent / scale];
|
|
3063
|
+
});
|
|
3064
|
+
const constrainedTarget = target.slice();
|
|
3065
|
+
const targetDimensions = [maxBoundsRect.width, maxBoundsRect.height];
|
|
3066
|
+
for (const [index, [negativeExtent, positiveExtent]] of worldExtents.entries()) {
|
|
3067
|
+
if (targetDimensions[index] < 0) {
|
|
3068
|
+
continue;
|
|
3069
|
+
}
|
|
3070
|
+
const { minimum, maximum, midpoint, settledTarget } = getAxisBounds(
|
|
3071
|
+
maxBounds,
|
|
3072
|
+
index,
|
|
3073
|
+
negativeExtent,
|
|
3074
|
+
positiveExtent,
|
|
3075
|
+
target[index]
|
|
3076
|
+
);
|
|
3077
|
+
if ((constraintContext == null ? void 0 : constraintContext.mode) !== "preserve" && rubberBand && (!Number.isFinite(negativeExtent) || !Number.isFinite(positiveExtent))) {
|
|
3078
|
+
constrainedTarget[index] = midpoint;
|
|
3079
|
+
continue;
|
|
3080
|
+
}
|
|
3081
|
+
const constrained = rubberBand ? settledTarget : (0, import_core8.clamp)(target[index], minimum, maximum);
|
|
3082
|
+
constrainedTarget[index] = (constraintContext == null ? void 0 : constraintContext.mode) === "preserve" ? target[index] : shouldRubberBand ? applyRubberBand(
|
|
3083
|
+
target[index],
|
|
3084
|
+
constrained,
|
|
3085
|
+
(index === 0 ? maxBoundsRect.width : maxBoundsRect.height) / 2 / Math.abs(pixelsPerUnit[index])
|
|
3086
|
+
) : constrained;
|
|
3087
|
+
}
|
|
3088
|
+
if (constrainedTarget[0] !== target[0] || constrainedTarget[1] !== target[1]) {
|
|
3089
|
+
props.target = constrainedTarget;
|
|
3090
|
+
}
|
|
3091
|
+
}
|
|
3092
|
+
return props;
|
|
3093
|
+
}
|
|
3094
|
+
_constrainZoom({ zoomX, zoomY }, props) {
|
|
3095
|
+
props ||= this.getViewportProps();
|
|
3096
|
+
const { zoomAxis, maxZoomX, maxZoomY, maxBounds } = props;
|
|
3097
|
+
let { minZoomX, minZoomY } = props;
|
|
3098
|
+
const shouldApplyMaxBounds = maxBounds !== null && props.width > 0 && props.height > 0;
|
|
3099
|
+
if (shouldApplyMaxBounds) {
|
|
3100
|
+
const maxBoundsRect = getMaxBoundsRect(props.width, props.height, props.maxBoundsPadding);
|
|
3101
|
+
const bl = maxBounds[0];
|
|
3102
|
+
const tr = maxBounds[1];
|
|
3103
|
+
const w = tr[0] - bl[0];
|
|
3104
|
+
const h = tr[1] - bl[1];
|
|
3105
|
+
if (maxBoundsRect.width > 0 && Number.isFinite(w) && w > 0) {
|
|
3106
|
+
minZoomX = Math.max(minZoomX, Math.log2(maxBoundsRect.width / w));
|
|
3107
|
+
if (minZoomX > maxZoomX) minZoomX = maxZoomX;
|
|
3108
|
+
}
|
|
3109
|
+
if (maxBoundsRect.height > 0 && Number.isFinite(h) && h > 0) {
|
|
3110
|
+
minZoomY = Math.max(minZoomY, Math.log2(maxBoundsRect.height / h));
|
|
3111
|
+
if (minZoomY > maxZoomY) minZoomY = maxZoomY;
|
|
3112
|
+
}
|
|
3113
|
+
}
|
|
3114
|
+
switch (zoomAxis) {
|
|
3115
|
+
case "X":
|
|
3116
|
+
zoomX = (0, import_core8.clamp)(zoomX, minZoomX, maxZoomX);
|
|
3117
|
+
break;
|
|
3118
|
+
case "Y":
|
|
3119
|
+
zoomY = (0, import_core8.clamp)(zoomY, minZoomY, maxZoomY);
|
|
3120
|
+
break;
|
|
3121
|
+
default:
|
|
3122
|
+
let delta = Math.min(maxZoomX - zoomX, maxZoomY - zoomY, 0);
|
|
3123
|
+
if (delta === 0) {
|
|
3124
|
+
delta = Math.max(minZoomX - zoomX, minZoomY - zoomY, 0);
|
|
3125
|
+
}
|
|
3126
|
+
if (delta !== 0) {
|
|
3127
|
+
zoomX += delta;
|
|
3128
|
+
zoomY += delta;
|
|
3129
|
+
}
|
|
3130
|
+
}
|
|
3131
|
+
return { zoomX, zoomY };
|
|
3132
|
+
}
|
|
3133
|
+
};
|
|
3134
|
+
var OrthographicController = class extends Controller {
|
|
3135
|
+
constructor() {
|
|
3136
|
+
super(...arguments);
|
|
3137
|
+
this.ControllerState = OrthographicState;
|
|
3138
|
+
this.transition = {
|
|
3139
|
+
transitionDuration: 300,
|
|
3140
|
+
transitionInterpolator: new LinearInterpolator(["target", "zoomX", "zoomY"])
|
|
3141
|
+
};
|
|
3142
|
+
this.dragMode = "pan";
|
|
3143
|
+
}
|
|
3144
|
+
setProps(props) {
|
|
3145
|
+
Object.assign(props, normalizeZoom(props));
|
|
3146
|
+
super.setProps(props);
|
|
3147
|
+
}
|
|
3148
|
+
_onMultiPanStart(event) {
|
|
3149
|
+
return this.multiTouchDrag === "pan" && super._onMultiPanStart(event);
|
|
3150
|
+
}
|
|
3151
|
+
_onPanRotate() {
|
|
3152
|
+
return false;
|
|
3153
|
+
}
|
|
3154
|
+
};
|
|
3155
|
+
|
|
3156
|
+
// ../core/src/views/orthographic-view.ts
|
|
3157
|
+
var OrthographicView = class extends View {
|
|
3158
|
+
constructor(props = {}) {
|
|
3159
|
+
super(props);
|
|
3160
|
+
}
|
|
3161
|
+
getViewportType() {
|
|
3162
|
+
return OrthographicViewport;
|
|
3163
|
+
}
|
|
3164
|
+
get ControllerType() {
|
|
3165
|
+
return OrthographicController;
|
|
3166
|
+
}
|
|
3167
|
+
};
|
|
3168
|
+
OrthographicView.displayName = "OrthographicView";
|
|
3169
|
+
|
|
3170
|
+
// ../core/src/transitions/fly-to-interpolator.ts
|
|
3171
|
+
var import_core9 = require("@math.gl/core");
|
|
3172
|
+
var import_web_mercator6 = require("@math.gl/web-mercator");
|
|
3173
|
+
var LINEARLY_INTERPOLATED_PROPS = {
|
|
3174
|
+
bearing: 0,
|
|
3175
|
+
pitch: 0,
|
|
3176
|
+
position: [0, 0, 0]
|
|
3177
|
+
};
|
|
3178
|
+
var DEFAULT_OPTS = {
|
|
3179
|
+
speed: 1.2,
|
|
3180
|
+
curve: 1.414
|
|
3181
|
+
};
|
|
3182
|
+
var FlyToInterpolator = class extends TransitionInterpolator {
|
|
3183
|
+
constructor(opts = {}) {
|
|
3184
|
+
super({
|
|
3185
|
+
compare: ["longitude", "latitude", "zoom", "bearing", "pitch", "position"],
|
|
3186
|
+
extract: ["width", "height", "longitude", "latitude", "zoom", "bearing", "pitch", "position"],
|
|
3187
|
+
required: ["width", "height", "latitude", "longitude", "zoom"]
|
|
3188
|
+
});
|
|
3189
|
+
this.opts = { ...DEFAULT_OPTS, ...opts };
|
|
3190
|
+
}
|
|
3191
|
+
interpolateProps(startProps, endProps, t) {
|
|
3192
|
+
const viewport = (0, import_web_mercator6.flyToViewport)(startProps, endProps, t, this.opts);
|
|
3193
|
+
for (const key in LINEARLY_INTERPOLATED_PROPS) {
|
|
3194
|
+
viewport[key] = (0, import_core9.lerp)(
|
|
3195
|
+
startProps[key] || LINEARLY_INTERPOLATED_PROPS[key],
|
|
3196
|
+
endProps[key] || LINEARLY_INTERPOLATED_PROPS[key],
|
|
3197
|
+
t
|
|
3198
|
+
);
|
|
3199
|
+
}
|
|
3200
|
+
return viewport;
|
|
3201
|
+
}
|
|
3202
|
+
// computes the transition duration
|
|
3203
|
+
getDuration(startProps, endProps) {
|
|
3204
|
+
let { transitionDuration } = endProps;
|
|
3205
|
+
if (transitionDuration === "auto") {
|
|
3206
|
+
transitionDuration = (0, import_web_mercator6.getFlyToDuration)(startProps, endProps, this.opts);
|
|
3207
|
+
}
|
|
3208
|
+
return transitionDuration;
|
|
3209
|
+
}
|
|
3210
|
+
};
|
|
60
3211
|
|
|
61
3212
|
// dist/zoom-widget.js
|
|
62
|
-
var import_jsx_runtime3 = require("preact/jsx-runtime");
|
|
63
|
-
var import_core = require("@deck.gl/core");
|
|
64
3213
|
var import_preact = require("preact");
|
|
65
3214
|
|
|
66
3215
|
// dist/lib/components/button-group.js
|
|
@@ -71,8 +3220,8 @@ var ButtonGroup = (props) => {
|
|
|
71
3220
|
};
|
|
72
3221
|
|
|
73
3222
|
// dist/lib/components/icon-button.js
|
|
74
|
-
var
|
|
75
|
-
var
|
|
3223
|
+
var import_jsx_runtime3 = require("preact/jsx-runtime");
|
|
3224
|
+
var import_hooks2 = require("preact/hooks");
|
|
76
3225
|
|
|
77
3226
|
// dist/lib/data-url.js
|
|
78
3227
|
function getCSSMask(imageUrl) {
|
|
@@ -82,20 +3231,87 @@ function getCSSMask(imageUrl) {
|
|
|
82
3231
|
return { maskImage: cssUrl, WebkitMaskImage: cssUrl };
|
|
83
3232
|
}
|
|
84
3233
|
|
|
3234
|
+
// dist/lib/components/tooltip.js
|
|
3235
|
+
var import_jsx_runtime2 = require("preact/jsx-runtime");
|
|
3236
|
+
var import_hooks = require("preact/hooks");
|
|
3237
|
+
var import_dom = require("@floating-ui/dom");
|
|
3238
|
+
var Tooltip = ({ content, placement = "right", children }) => {
|
|
3239
|
+
const wrapperRef = (0, import_hooks.useRef)(null);
|
|
3240
|
+
const tooltipRef = (0, import_hooks.useRef)(null);
|
|
3241
|
+
const [visible, setVisible] = (0, import_hooks.useState)(false);
|
|
3242
|
+
const delayRef = (0, import_hooks.useRef)();
|
|
3243
|
+
const show = (0, import_hooks.useCallback)(() => {
|
|
3244
|
+
clearTimeout(delayRef.current);
|
|
3245
|
+
setVisible(true);
|
|
3246
|
+
}, []);
|
|
3247
|
+
const hide = (0, import_hooks.useCallback)(() => {
|
|
3248
|
+
clearTimeout(delayRef.current);
|
|
3249
|
+
setVisible(false);
|
|
3250
|
+
}, []);
|
|
3251
|
+
const onKeyDown = (0, import_hooks.useCallback)((e) => {
|
|
3252
|
+
if (e.key === "Escape")
|
|
3253
|
+
hide();
|
|
3254
|
+
}, [hide]);
|
|
3255
|
+
(0, import_hooks.useEffect)(() => {
|
|
3256
|
+
var _a;
|
|
3257
|
+
const tooltip = tooltipRef.current;
|
|
3258
|
+
const trigger = (_a = wrapperRef.current) == null ? void 0 : _a.firstElementChild;
|
|
3259
|
+
if (!visible || !tooltip || !trigger)
|
|
3260
|
+
return void 0;
|
|
3261
|
+
const updatePosition = () => {
|
|
3262
|
+
(0, import_dom.computePosition)(trigger, tooltip, {
|
|
3263
|
+
placement,
|
|
3264
|
+
strategy: "fixed",
|
|
3265
|
+
middleware: [(0, import_dom.offset)(8), (0, import_dom.flip)(), (0, import_dom.shift)({ padding: 4 })]
|
|
3266
|
+
}).then(({ x, y }) => {
|
|
3267
|
+
if (tooltipRef.current === tooltip) {
|
|
3268
|
+
Object.assign(tooltip.style, { left: `${x}px`, top: `${y}px`, opacity: "1" });
|
|
3269
|
+
}
|
|
3270
|
+
});
|
|
3271
|
+
};
|
|
3272
|
+
return (0, import_dom.autoUpdate)(trigger, tooltip, updatePosition);
|
|
3273
|
+
}, [visible, placement]);
|
|
3274
|
+
(0, import_hooks.useEffect)(() => {
|
|
3275
|
+
return () => clearTimeout(delayRef.current);
|
|
3276
|
+
}, []);
|
|
3277
|
+
const htmlRef = (0, import_hooks.useCallback)((el) => {
|
|
3278
|
+
if (el && content instanceof HTMLElement) {
|
|
3279
|
+
el.replaceChildren(content.cloneNode(true));
|
|
3280
|
+
}
|
|
3281
|
+
}, [content]);
|
|
3282
|
+
const renderContent = () => {
|
|
3283
|
+
if (content instanceof HTMLElement) {
|
|
3284
|
+
return (0, import_jsx_runtime2.jsx)("div", { ref: htmlRef });
|
|
3285
|
+
}
|
|
3286
|
+
return content;
|
|
3287
|
+
};
|
|
3288
|
+
if (content === null || content === void 0 || content === false || content === "") {
|
|
3289
|
+
return (0, import_jsx_runtime2.jsx)(import_jsx_runtime2.Fragment, { children });
|
|
3290
|
+
}
|
|
3291
|
+
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: {
|
|
3292
|
+
position: "fixed",
|
|
3293
|
+
opacity: 0,
|
|
3294
|
+
fontSize: "12px",
|
|
3295
|
+
padding: "4px 8px"
|
|
3296
|
+
}, children: renderContent() })] });
|
|
3297
|
+
};
|
|
3298
|
+
|
|
85
3299
|
// dist/lib/components/icon-button.js
|
|
86
3300
|
var IconButton = (props) => {
|
|
87
|
-
const { className = "", style, color, icon, label, onClick, children } = props;
|
|
88
|
-
const
|
|
3301
|
+
const { className = "", style, color, icon, label, tooltip, onClick, children } = props;
|
|
3302
|
+
const tooltipContent = tooltip === false ? void 0 : tooltip ?? label;
|
|
3303
|
+
const iconStyle = (0, import_hooks2.useMemo)(() => {
|
|
89
3304
|
const css = getCSSMask(icon);
|
|
90
3305
|
if (!color)
|
|
91
3306
|
return css;
|
|
92
3307
|
return { ...css, backgroundColor: color };
|
|
93
3308
|
}, [color, icon]);
|
|
94
|
-
|
|
3309
|
+
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 }) });
|
|
3310
|
+
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
3311
|
};
|
|
96
3312
|
|
|
97
3313
|
// dist/zoom-widget.js
|
|
98
|
-
var ZoomWidget = class extends
|
|
3314
|
+
var ZoomWidget = class extends Widget {
|
|
99
3315
|
constructor(props = {}) {
|
|
100
3316
|
super(props);
|
|
101
3317
|
this.className = "deck-widget-zoom";
|
|
@@ -108,13 +3324,13 @@ var ZoomWidget = class extends import_core.Widget {
|
|
|
108
3324
|
super.setProps(props);
|
|
109
3325
|
}
|
|
110
3326
|
onRenderHTML(rootElement) {
|
|
111
|
-
const ui = (0,
|
|
3327
|
+
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
3328
|
(0, import_preact.render)(ui, rootElement);
|
|
113
3329
|
}
|
|
114
3330
|
isOrthographicView(viewId) {
|
|
115
3331
|
const deck = this.deck;
|
|
116
3332
|
const view = (deck == null ? void 0 : deck.isInitialized) && deck.getView(viewId);
|
|
117
|
-
return view instanceof
|
|
3333
|
+
return view instanceof OrthographicView;
|
|
118
3334
|
}
|
|
119
3335
|
handleZoom(viewId, delta) {
|
|
120
3336
|
var _a, _b, _c, _d;
|
|
@@ -126,13 +3342,13 @@ var ZoomWidget = class extends import_core.Widget {
|
|
|
126
3342
|
let nextZoom;
|
|
127
3343
|
let nextZoomY;
|
|
128
3344
|
if (zoomAxis === "X") {
|
|
129
|
-
nextZoom =
|
|
3345
|
+
nextZoom = clamp5(zoomX + delta, minZoomX, maxZoomX);
|
|
130
3346
|
nextZoomY = zoomY;
|
|
131
3347
|
} else if (zoomAxis === "Y") {
|
|
132
3348
|
nextZoom = zoomX;
|
|
133
|
-
nextZoomY =
|
|
3349
|
+
nextZoomY = clamp5(zoomY + delta, minZoomY, maxZoomY);
|
|
134
3350
|
} else {
|
|
135
|
-
const clampedDelta =
|
|
3351
|
+
const clampedDelta = clamp5(delta, Math.max(minZoomX - zoomX, minZoomY - zoomY), Math.min(maxZoomX - zoomX, maxZoomY - zoomY));
|
|
136
3352
|
nextZoom = zoomX + clampedDelta;
|
|
137
3353
|
nextZoomY = zoomY + clampedDelta;
|
|
138
3354
|
}
|
|
@@ -149,7 +3365,7 @@ var ZoomWidget = class extends import_core.Widget {
|
|
|
149
3365
|
});
|
|
150
3366
|
} else {
|
|
151
3367
|
const { zoom = 0, minZoom, maxZoom } = viewState;
|
|
152
|
-
const nextZoom =
|
|
3368
|
+
const nextZoom = clamp5(zoom + delta, minZoom, maxZoom);
|
|
153
3369
|
newViewState.zoom = nextZoom;
|
|
154
3370
|
(_d = (_c = this.props).onZoom) == null ? void 0 : _d.call(_c, {
|
|
155
3371
|
viewId,
|
|
@@ -163,7 +3379,7 @@ var ZoomWidget = class extends import_core.Widget {
|
|
|
163
3379
|
};
|
|
164
3380
|
if (this.props.transitionDuration > 0) {
|
|
165
3381
|
nextViewState.transitionDuration = this.props.transitionDuration;
|
|
166
|
-
nextViewState.transitionInterpolator = "latitude" in nextViewState ? new
|
|
3382
|
+
nextViewState.transitionInterpolator = "latitude" in nextViewState ? new FlyToInterpolator() : new LinearInterpolator({
|
|
167
3383
|
transitionProps: "zoomX" in newViewState ? ["zoomX", "zoomY"] : ["zoom"]
|
|
168
3384
|
});
|
|
169
3385
|
}
|
|
@@ -181,7 +3397,7 @@ var ZoomWidget = class extends import_core.Widget {
|
|
|
181
3397
|
}
|
|
182
3398
|
};
|
|
183
3399
|
ZoomWidget.defaultProps = {
|
|
184
|
-
...
|
|
3400
|
+
...Widget.defaultProps,
|
|
185
3401
|
id: "zoom",
|
|
186
3402
|
placement: "top-left",
|
|
187
3403
|
orientation: "vertical",
|
|
@@ -189,12 +3405,14 @@ ZoomWidget.defaultProps = {
|
|
|
189
3405
|
zoomStep: 1,
|
|
190
3406
|
zoomInLabel: "Zoom In",
|
|
191
3407
|
zoomOutLabel: "Zoom Out",
|
|
3408
|
+
zoomInTooltip: void 0,
|
|
3409
|
+
zoomOutTooltip: void 0,
|
|
192
3410
|
zoomAxis: "all",
|
|
193
3411
|
viewId: null,
|
|
194
3412
|
onZoom: () => {
|
|
195
3413
|
}
|
|
196
3414
|
};
|
|
197
|
-
function
|
|
3415
|
+
function clamp5(zoom, minZoom, maxZoom) {
|
|
198
3416
|
return zoom < minZoom ? minZoom : zoom > maxZoom ? maxZoom : zoom;
|
|
199
3417
|
}
|
|
200
3418
|
function normalizeOrthographicViewState({ zoom = 0, zoomX, zoomY, minZoom = -Infinity, maxZoom = Infinity, minZoomX = minZoom, maxZoomX = maxZoom, minZoomY = minZoom, maxZoomY = maxZoom }) {
|
|
@@ -204,10 +3422,9 @@ function normalizeOrthographicViewState({ zoom = 0, zoomX, zoomY, minZoom = -Inf
|
|
|
204
3422
|
}
|
|
205
3423
|
|
|
206
3424
|
// dist/reset-view-widget.js
|
|
207
|
-
var
|
|
3425
|
+
var import_jsx_runtime5 = require("preact/jsx-runtime");
|
|
208
3426
|
var import_preact2 = require("preact");
|
|
209
|
-
var
|
|
210
|
-
var ResetViewWidget = class extends import_core2.Widget {
|
|
3427
|
+
var ResetViewWidget = class extends Widget {
|
|
211
3428
|
constructor(props = {}) {
|
|
212
3429
|
super(props);
|
|
213
3430
|
this.className = "deck-widget-reset-view";
|
|
@@ -220,7 +3437,7 @@ var ResetViewWidget = class extends import_core2.Widget {
|
|
|
220
3437
|
super.setProps(props);
|
|
221
3438
|
}
|
|
222
3439
|
onRenderHTML(rootElement) {
|
|
223
|
-
(0, import_preact2.render)((0,
|
|
3440
|
+
(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
3441
|
}
|
|
225
3442
|
handleClick() {
|
|
226
3443
|
var _a;
|
|
@@ -242,10 +3459,11 @@ var ResetViewWidget = class extends import_core2.Widget {
|
|
|
242
3459
|
}
|
|
243
3460
|
};
|
|
244
3461
|
ResetViewWidget.defaultProps = {
|
|
245
|
-
...
|
|
3462
|
+
...Widget.defaultProps,
|
|
246
3463
|
id: "reset-view",
|
|
247
3464
|
placement: "top-left",
|
|
248
3465
|
label: "Reset View",
|
|
3466
|
+
tooltip: void 0,
|
|
249
3467
|
initialViewState: void 0,
|
|
250
3468
|
viewId: null,
|
|
251
3469
|
onReset: () => {
|
|
@@ -253,10 +3471,9 @@ ResetViewWidget.defaultProps = {
|
|
|
253
3471
|
};
|
|
254
3472
|
|
|
255
3473
|
// dist/gimbal-widget.js
|
|
256
|
-
var
|
|
257
|
-
var import_core3 = require("@deck.gl/core");
|
|
3474
|
+
var import_jsx_runtime6 = require("preact/jsx-runtime");
|
|
258
3475
|
var import_preact3 = require("preact");
|
|
259
|
-
var GimbalWidget = class extends
|
|
3476
|
+
var GimbalWidget = class extends Widget {
|
|
260
3477
|
constructor(props = {}) {
|
|
261
3478
|
super(props);
|
|
262
3479
|
this.className = "deck-widget-gimbal";
|
|
@@ -274,21 +3491,22 @@ var GimbalWidget = class extends import_core3.Widget {
|
|
|
274
3491
|
const viewId = this.viewId || ((_a = Object.values(this.viewports)[0]) == null ? void 0 : _a.id) || "default-view";
|
|
275
3492
|
const widgetViewport = this.viewports[viewId];
|
|
276
3493
|
const { rotationOrbit, rotationX } = this.getNormalizedRotation(widgetViewport);
|
|
277
|
-
const
|
|
3494
|
+
const tooltipContent = this.props.tooltip === false ? void 0 : this.props.tooltip ?? this.props.label;
|
|
3495
|
+
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
3496
|
for (const viewport of Object.values(this.viewports)) {
|
|
279
3497
|
this.resetOrbitView(viewport);
|
|
280
3498
|
}
|
|
281
|
-
},
|
|
3499
|
+
}, "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
3500
|
position: "absolute",
|
|
283
3501
|
top: 0,
|
|
284
3502
|
left: 0,
|
|
285
3503
|
transform: `rotateY(${rotationOrbit}deg)`
|
|
286
|
-
}, children: (0,
|
|
3504
|
+
}, 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
3505
|
position: "absolute",
|
|
288
3506
|
top: 0,
|
|
289
3507
|
left: 0,
|
|
290
3508
|
transform: `rotateX(${rotationX}deg)`
|
|
291
|
-
}, children: (0,
|
|
3509
|
+
}, 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
3510
|
(0, import_preact3.render)(ui, rootElement);
|
|
293
3511
|
}
|
|
294
3512
|
onViewportChange(viewport) {
|
|
@@ -306,7 +3524,7 @@ var GimbalWidget = class extends import_core3.Widget {
|
|
|
306
3524
|
rotationOrbit: 0,
|
|
307
3525
|
rotationX: 0,
|
|
308
3526
|
transitionDuration: this.props.transitionDuration,
|
|
309
|
-
transitionInterpolator: new
|
|
3527
|
+
transitionInterpolator: new LinearInterpolator({
|
|
310
3528
|
transitionProps: ["rotationOrbit", "rotationX"]
|
|
311
3529
|
})
|
|
312
3530
|
};
|
|
@@ -329,11 +3547,12 @@ var GimbalWidget = class extends import_core3.Widget {
|
|
|
329
3547
|
}
|
|
330
3548
|
};
|
|
331
3549
|
GimbalWidget.defaultProps = {
|
|
332
|
-
...
|
|
3550
|
+
...Widget.defaultProps,
|
|
333
3551
|
id: "gimbal",
|
|
334
3552
|
placement: "top-left",
|
|
335
3553
|
viewId: null,
|
|
336
3554
|
label: "Gimbal",
|
|
3555
|
+
tooltip: void 0,
|
|
337
3556
|
strokeWidth: 1.5,
|
|
338
3557
|
transitionDuration: 200,
|
|
339
3558
|
onReset: () => {
|
|
@@ -354,10 +3573,9 @@ function normalizeAndClampAngle(angle) {
|
|
|
354
3573
|
}
|
|
355
3574
|
|
|
356
3575
|
// dist/compass-widget.js
|
|
357
|
-
var
|
|
358
|
-
var import_core4 = require("@deck.gl/core");
|
|
3576
|
+
var import_jsx_runtime7 = require("preact/jsx-runtime");
|
|
359
3577
|
var import_preact4 = require("preact");
|
|
360
|
-
var CompassWidget = class extends
|
|
3578
|
+
var CompassWidget = class extends Widget {
|
|
361
3579
|
constructor(props = {}) {
|
|
362
3580
|
super(props);
|
|
363
3581
|
this.className = "deck-widget-compass";
|
|
@@ -375,11 +3593,12 @@ var CompassWidget = class extends import_core4.Widget {
|
|
|
375
3593
|
const viewId = this.viewId || ((_a = Object.values(this.viewports)[0]) == null ? void 0 : _a.id);
|
|
376
3594
|
const widgetViewport = this.viewports[viewId];
|
|
377
3595
|
const [rz, rx] = this.getRotation(widgetViewport);
|
|
378
|
-
const
|
|
3596
|
+
const tooltipContent = this.props.tooltip === false ? void 0 : this.props.tooltip ?? this.props.label;
|
|
3597
|
+
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
3598
|
for (const viewport of Object.values(this.viewports)) {
|
|
380
3599
|
this.handleCompassReset(viewport);
|
|
381
3600
|
}
|
|
382
|
-
},
|
|
3601
|
+
}, "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
3602
|
(0, import_preact4.render)(ui, rootElement);
|
|
384
3603
|
}
|
|
385
3604
|
onViewportChange(viewport) {
|
|
@@ -389,9 +3608,9 @@ var CompassWidget = class extends import_core4.Widget {
|
|
|
389
3608
|
}
|
|
390
3609
|
}
|
|
391
3610
|
getRotation(viewport) {
|
|
392
|
-
if (viewport instanceof
|
|
3611
|
+
if (viewport instanceof WebMercatorViewport) {
|
|
393
3612
|
return [-viewport.bearing, viewport.pitch];
|
|
394
|
-
} else if (viewport instanceof
|
|
3613
|
+
} else if (viewport instanceof GlobeViewport) {
|
|
395
3614
|
return [0, Math.max(-80, Math.min(80, viewport.latitude))];
|
|
396
3615
|
}
|
|
397
3616
|
return [0, 0];
|
|
@@ -399,7 +3618,7 @@ var CompassWidget = class extends import_core4.Widget {
|
|
|
399
3618
|
handleCompassReset(viewport) {
|
|
400
3619
|
var _a, _b;
|
|
401
3620
|
const viewId = this.viewId || viewport.id;
|
|
402
|
-
if (viewport instanceof
|
|
3621
|
+
if (viewport instanceof WebMercatorViewport) {
|
|
403
3622
|
const viewState = this.getViewState(viewId);
|
|
404
3623
|
const resetPitch = this.getRotation(viewport)[0] === 0;
|
|
405
3624
|
const nextBearing = 0;
|
|
@@ -410,28 +3629,28 @@ var CompassWidget = class extends import_core4.Widget {
|
|
|
410
3629
|
bearing: nextBearing,
|
|
411
3630
|
...resetPitch ? { pitch: nextPitch } : {},
|
|
412
3631
|
transitionDuration: this.props.transitionDuration,
|
|
413
|
-
transitionInterpolator: new
|
|
3632
|
+
transitionInterpolator: new FlyToInterpolator()
|
|
414
3633
|
};
|
|
415
3634
|
this.setViewState(viewId, nextViewState);
|
|
416
3635
|
}
|
|
417
3636
|
}
|
|
418
3637
|
};
|
|
419
3638
|
CompassWidget.defaultProps = {
|
|
420
|
-
...
|
|
3639
|
+
...Widget.defaultProps,
|
|
421
3640
|
id: "compass",
|
|
422
3641
|
placement: "top-left",
|
|
423
3642
|
viewId: null,
|
|
424
3643
|
label: "Reset Compass",
|
|
3644
|
+
tooltip: void 0,
|
|
425
3645
|
transitionDuration: 200,
|
|
426
3646
|
onReset: () => {
|
|
427
3647
|
}
|
|
428
3648
|
};
|
|
429
3649
|
|
|
430
3650
|
// dist/scale-widget.js
|
|
431
|
-
var
|
|
3651
|
+
var import_jsx_runtime8 = require("preact/jsx-runtime");
|
|
432
3652
|
var import_preact5 = require("preact");
|
|
433
|
-
var
|
|
434
|
-
var ScaleWidget = class extends import_core5.Widget {
|
|
3653
|
+
var ScaleWidget = class extends Widget {
|
|
435
3654
|
constructor(props = {}) {
|
|
436
3655
|
super(props);
|
|
437
3656
|
this.className = "deck-widget-scale";
|
|
@@ -450,7 +3669,7 @@ var ScaleWidget = class extends import_core5.Widget {
|
|
|
450
3669
|
const lineOffsetX = 50;
|
|
451
3670
|
const svgWidth = lineOffsetX + this.scaleWidth;
|
|
452
3671
|
const tickHeight = 10;
|
|
453
|
-
(0, import_preact5.render)((0,
|
|
3672
|
+
(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
3673
|
}
|
|
455
3674
|
onViewportChange(viewport) {
|
|
456
3675
|
if (!("latitude" in viewport))
|
|
@@ -471,7 +3690,7 @@ var ScaleWidget = class extends import_core5.Widget {
|
|
|
471
3690
|
}
|
|
472
3691
|
};
|
|
473
3692
|
ScaleWidget.defaultProps = {
|
|
474
|
-
...
|
|
3693
|
+
...Widget.defaultProps,
|
|
475
3694
|
id: "scale",
|
|
476
3695
|
placement: "bottom-left",
|
|
477
3696
|
label: "Scale",
|
|
@@ -513,14 +3732,12 @@ function computeScaleCandidate(metersPerPixel) {
|
|
|
513
3732
|
}
|
|
514
3733
|
|
|
515
3734
|
// dist/geocoder-widget.js
|
|
516
|
-
var
|
|
517
|
-
var import_core6 = require("@deck.gl/core");
|
|
518
|
-
var import_core7 = require("@deck.gl/core");
|
|
3735
|
+
var import_jsx_runtime10 = require("preact/jsx-runtime");
|
|
519
3736
|
var import_preact6 = require("preact");
|
|
520
3737
|
|
|
521
3738
|
// dist/lib/components/dropdown-menu.js
|
|
522
|
-
var
|
|
523
|
-
var
|
|
3739
|
+
var import_jsx_runtime9 = require("preact/jsx-runtime");
|
|
3740
|
+
var import_hooks3 = require("preact/hooks");
|
|
524
3741
|
function getMenuItemValue(item) {
|
|
525
3742
|
return typeof item === "string" ? item : item.value;
|
|
526
3743
|
}
|
|
@@ -531,12 +3748,12 @@ function getMenuItemIcon(item) {
|
|
|
531
3748
|
return typeof item === "string" ? void 0 : item.icon;
|
|
532
3749
|
}
|
|
533
3750
|
var DropdownMenu = (props) => {
|
|
534
|
-
const [isOpen, setIsOpen] = (0,
|
|
535
|
-
return (0,
|
|
3751
|
+
const [isOpen, setIsOpen] = (0, import_hooks3.useState)(false);
|
|
3752
|
+
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
3753
|
};
|
|
537
3754
|
var SimpleMenu = (props) => {
|
|
538
|
-
const dropdownRef = (0,
|
|
539
|
-
(0,
|
|
3755
|
+
const dropdownRef = (0, import_hooks3.useRef)(null);
|
|
3756
|
+
(0, import_hooks3.useEffect)(() => {
|
|
540
3757
|
const handleClickOutside = (event) => {
|
|
541
3758
|
if (dropdownRef.current && !dropdownRef.current.contains(event.target)) {
|
|
542
3759
|
props.onClose();
|
|
@@ -560,10 +3777,10 @@ var SimpleMenu = (props) => {
|
|
|
560
3777
|
if (props.menuItems.length === 0) {
|
|
561
3778
|
return null;
|
|
562
3779
|
}
|
|
563
|
-
return (0,
|
|
3780
|
+
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
3781
|
const value = getMenuItemValue(item);
|
|
565
3782
|
const icon = getMenuItemIcon(item);
|
|
566
|
-
return (0,
|
|
3783
|
+
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
3784
|
}) })] });
|
|
568
3785
|
};
|
|
569
3786
|
|
|
@@ -770,7 +3987,7 @@ var CURRENT_LOCATION_ITEM = {
|
|
|
770
3987
|
value: CURRENT_LOCATION2,
|
|
771
3988
|
icon: LOCATION_ICON
|
|
772
3989
|
};
|
|
773
|
-
var GeocoderWidget = class extends
|
|
3990
|
+
var GeocoderWidget = class extends Widget {
|
|
774
3991
|
constructor(props = {}) {
|
|
775
3992
|
super(props);
|
|
776
3993
|
this.className = "deck-widget-geocoder";
|
|
@@ -839,7 +4056,7 @@ var GeocoderWidget = class extends import_core6.Widget {
|
|
|
839
4056
|
}
|
|
840
4057
|
onRenderHTML(rootElement) {
|
|
841
4058
|
const menuItems = this.props._geolocation ? [CURRENT_LOCATION_ITEM, ...this.geocodeHistory.addressHistory] : [...this.geocodeHistory.addressHistory];
|
|
842
|
-
(0, import_preact6.render)((0,
|
|
4059
|
+
(0, import_preact6.render)((0, import_jsx_runtime10.jsxs)("div", { className: "deck-widget-geocoder", children: [(0, import_jsx_runtime10.jsx)("input", {
|
|
843
4060
|
className: "deck-widget-geocoder-input",
|
|
844
4061
|
type: "text",
|
|
845
4062
|
placeholder: this.isGettingLocation ? "Finding your location..." : this.geocoder.placeholderLocation ?? "Enter address or location",
|
|
@@ -850,7 +4067,7 @@ var GeocoderWidget = class extends import_core6.Widget {
|
|
|
850
4067
|
return this.setInput(((_a = e.target) == null ? void 0 : _a.value) || "");
|
|
851
4068
|
},
|
|
852
4069
|
onKeyPress: this.handleKeyPress
|
|
853
|
-
}), (0,
|
|
4070
|
+
}), (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
4071
|
}
|
|
855
4072
|
flyTo(viewState) {
|
|
856
4073
|
var _a, _b;
|
|
@@ -872,14 +4089,14 @@ var GeocoderWidget = class extends import_core6.Widget {
|
|
|
872
4089
|
};
|
|
873
4090
|
if (this.props.transitionDuration > 0) {
|
|
874
4091
|
nextViewState.transitionDuration = this.props.transitionDuration;
|
|
875
|
-
nextViewState.transitionInterpolator = "latitude" in nextViewState ? new
|
|
4092
|
+
nextViewState.transitionInterpolator = "latitude" in nextViewState ? new FlyToInterpolator() : new LinearInterpolator();
|
|
876
4093
|
}
|
|
877
4094
|
this.setViewState(viewId, nextViewState);
|
|
878
4095
|
}
|
|
879
4096
|
}
|
|
880
4097
|
};
|
|
881
4098
|
GeocoderWidget.defaultProps = {
|
|
882
|
-
...
|
|
4099
|
+
...Widget.defaultProps,
|
|
883
4100
|
id: "geocoder",
|
|
884
4101
|
viewId: null,
|
|
885
4102
|
placement: "top-left",
|
|
@@ -913,10 +4130,9 @@ function getGeocoder(props) {
|
|
|
913
4130
|
}
|
|
914
4131
|
|
|
915
4132
|
// dist/fullscreen-widget.js
|
|
916
|
-
var
|
|
917
|
-
var import_core8 = require("@deck.gl/core");
|
|
4133
|
+
var import_jsx_runtime11 = require("preact/jsx-runtime");
|
|
918
4134
|
var import_preact7 = require("preact");
|
|
919
|
-
var FullscreenWidget = class extends
|
|
4135
|
+
var FullscreenWidget = class extends Widget {
|
|
920
4136
|
constructor(props = {}) {
|
|
921
4137
|
super(props);
|
|
922
4138
|
this.className = "deck-widget-fullscreen";
|
|
@@ -932,9 +4148,9 @@ var FullscreenWidget = class extends import_core8.Widget {
|
|
|
932
4148
|
}
|
|
933
4149
|
onRenderHTML(rootElement) {
|
|
934
4150
|
const isFullscreen = this.getFullscreen();
|
|
935
|
-
(0, import_preact7.render)((0,
|
|
936
|
-
this.handleClick().catch((err) =>
|
|
937
|
-
}, label: isFullscreen ? this.props.exitLabel : this.props.enterLabel, className: isFullscreen ? "deck-widget-fullscreen-exit" : "deck-widget-fullscreen-enter" }), rootElement);
|
|
4151
|
+
(0, import_preact7.render)((0, import_jsx_runtime11.jsx)(IconButton, { onClick: () => {
|
|
4152
|
+
this.handleClick().catch((err) => log_default.error(err)());
|
|
4153
|
+
}, 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
4154
|
}
|
|
939
4155
|
setProps(props) {
|
|
940
4156
|
this.placement = props.placement ?? this.placement;
|
|
@@ -989,29 +4205,29 @@ var FullscreenWidget = class extends import_core8.Widget {
|
|
|
989
4205
|
}
|
|
990
4206
|
};
|
|
991
4207
|
FullscreenWidget.defaultProps = {
|
|
992
|
-
...
|
|
4208
|
+
...Widget.defaultProps,
|
|
993
4209
|
id: "fullscreen",
|
|
994
4210
|
placement: "top-left",
|
|
995
4211
|
viewId: null,
|
|
996
4212
|
enterLabel: "Enter Fullscreen",
|
|
997
4213
|
exitLabel: "Exit Fullscreen",
|
|
4214
|
+
enterTooltip: void 0,
|
|
4215
|
+
exitTooltip: void 0,
|
|
998
4216
|
container: void 0,
|
|
999
4217
|
onFullscreenChange: () => {
|
|
1000
4218
|
}
|
|
1001
4219
|
};
|
|
1002
4220
|
|
|
1003
4221
|
// dist/splitter-widget.js
|
|
1004
|
-
var
|
|
4222
|
+
var import_jsx_runtime12 = require("preact/jsx-runtime");
|
|
1005
4223
|
var import_preact8 = require("preact");
|
|
1006
|
-
var
|
|
1007
|
-
var import_core10 = require("@deck.gl/core");
|
|
4224
|
+
var import_hooks4 = require("preact/hooks");
|
|
1008
4225
|
|
|
1009
4226
|
// dist/view-layout/view-layout.js
|
|
1010
|
-
var import_core9 = require("@deck.gl/core");
|
|
1011
4227
|
var VIEW_LAYOUT_TYPES = /* @__PURE__ */ new Set(["row", "column", "overlay", "spacer"]);
|
|
1012
4228
|
var VIEW_LAYOUT_ORIENTATIONS = /* @__PURE__ */ new Set(["horizontal", "vertical"]);
|
|
1013
4229
|
function isViewLayout(child) {
|
|
1014
|
-
return Boolean(child && typeof child === "object" && !(child instanceof
|
|
4230
|
+
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
4231
|
}
|
|
1016
4232
|
function getViewLayoutType(item) {
|
|
1017
4233
|
if ("orientation" in item) {
|
|
@@ -1061,7 +4277,7 @@ function assertViewLayoutChild(child) {
|
|
|
1061
4277
|
assertViewLayout(child);
|
|
1062
4278
|
return;
|
|
1063
4279
|
}
|
|
1064
|
-
if (child instanceof
|
|
4280
|
+
if (child instanceof View) {
|
|
1065
4281
|
return;
|
|
1066
4282
|
}
|
|
1067
4283
|
throw new Error("ViewLayout children must be deck.gl View instances or layout objects.");
|
|
@@ -1563,7 +4779,7 @@ function evaluateViews(layout, viewLayouts, splitValues) {
|
|
|
1563
4779
|
height: `${view.props.height}%`
|
|
1564
4780
|
}));
|
|
1565
4781
|
}
|
|
1566
|
-
var SplitterWidget = class extends
|
|
4782
|
+
var SplitterWidget = class extends Widget {
|
|
1567
4783
|
constructor(props) {
|
|
1568
4784
|
super(props);
|
|
1569
4785
|
this.className = "deck-widget-splitter";
|
|
@@ -1573,7 +4789,7 @@ var SplitterWidget = class extends import_core10.Widget {
|
|
|
1573
4789
|
this.updateViewLayout(this.props.viewLayout);
|
|
1574
4790
|
}
|
|
1575
4791
|
setProps(props) {
|
|
1576
|
-
if (props.viewLayout && !(
|
|
4792
|
+
if (props.viewLayout && !deepEqual(props.viewLayout, this.props.viewLayout, -1)) {
|
|
1577
4793
|
this.updateViewLayout(props.viewLayout);
|
|
1578
4794
|
this.views = void 0;
|
|
1579
4795
|
}
|
|
@@ -1621,11 +4837,11 @@ var SplitterWidget = class extends import_core10.Widget {
|
|
|
1621
4837
|
this.doUpdate();
|
|
1622
4838
|
}
|
|
1623
4839
|
onRenderHTML(rootElement) {
|
|
1624
|
-
(0, import_preact8.render)((0,
|
|
4840
|
+
(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
4841
|
}
|
|
1626
4842
|
};
|
|
1627
4843
|
SplitterWidget.defaultProps = {
|
|
1628
|
-
...
|
|
4844
|
+
...Widget.defaultProps,
|
|
1629
4845
|
id: "splitter-widget",
|
|
1630
4846
|
viewLayout: void 0,
|
|
1631
4847
|
onChange: () => {
|
|
@@ -1636,9 +4852,9 @@ SplitterWidget.defaultProps = {
|
|
|
1636
4852
|
}
|
|
1637
4853
|
};
|
|
1638
4854
|
function Splitter({ orientation, x, y, width, height, split, minSplit, maxSplit, onChange, onDragStart, onDragEnd }) {
|
|
1639
|
-
const [dragging, setDragging] = (0,
|
|
1640
|
-
const containerRef = (0,
|
|
1641
|
-
(0,
|
|
4855
|
+
const [dragging, setDragging] = (0, import_hooks4.useState)(false);
|
|
4856
|
+
const containerRef = (0, import_hooks4.useRef)(null);
|
|
4857
|
+
(0, import_hooks4.useEffect)(() => {
|
|
1642
4858
|
if (!dragging) {
|
|
1643
4859
|
return void 0;
|
|
1644
4860
|
}
|
|
@@ -1681,33 +4897,32 @@ function Splitter({ orientation, x, y, width, height, split, minSplit, maxSplit,
|
|
|
1681
4897
|
width: `${width}%`,
|
|
1682
4898
|
height: `${height}%`
|
|
1683
4899
|
};
|
|
1684
|
-
return (0,
|
|
4900
|
+
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
4901
|
}
|
|
1686
4902
|
|
|
1687
4903
|
// dist/info-widget.js
|
|
1688
|
-
var
|
|
1689
|
-
var import_core11 = require("@deck.gl/core");
|
|
4904
|
+
var import_jsx_runtime15 = require("preact/jsx-runtime");
|
|
1690
4905
|
var import_preact9 = require("preact");
|
|
1691
4906
|
|
|
1692
4907
|
// dist/lib/components/popover.js
|
|
1693
|
-
var
|
|
1694
|
-
var
|
|
1695
|
-
var
|
|
4908
|
+
var import_jsx_runtime13 = require("preact/jsx-runtime");
|
|
4909
|
+
var import_hooks5 = require("preact/hooks");
|
|
4910
|
+
var import_dom2 = require("@floating-ui/dom");
|
|
1696
4911
|
var Popover = ({ x, y, placement = "right", offset: pixelOffset = 0, arrow: arrowSize = false, arrowColor = "white", children }) => {
|
|
1697
|
-
const anchorRef = (0,
|
|
1698
|
-
const contentRef = (0,
|
|
1699
|
-
const arrowRef = (0,
|
|
1700
|
-
const updaterRef = (0,
|
|
4912
|
+
const anchorRef = (0, import_hooks5.useRef)(null);
|
|
4913
|
+
const contentRef = (0, import_hooks5.useRef)(null);
|
|
4914
|
+
const arrowRef = (0, import_hooks5.useRef)(null);
|
|
4915
|
+
const updaterRef = (0, import_hooks5.useRef)();
|
|
1701
4916
|
updaterRef.current = () => {
|
|
1702
4917
|
if (!anchorRef.current || !contentRef.current)
|
|
1703
4918
|
return;
|
|
1704
4919
|
const arrowWidth = Array.isArray(arrowSize) ? arrowSize[0] : arrowSize || 0;
|
|
1705
4920
|
const arrowHeight = Array.isArray(arrowSize) ? arrowSize[1] : arrowSize || 0;
|
|
1706
4921
|
const padding = pixelOffset + Math.max(arrowHeight, arrowWidth);
|
|
1707
|
-
const middleware = placement.includes("-") ? [(0,
|
|
4922
|
+
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
4923
|
if (arrowRef.current)
|
|
1709
|
-
middleware.push((0,
|
|
1710
|
-
(0,
|
|
4924
|
+
middleware.push((0, import_dom2.arrow)({ element: arrowRef.current }));
|
|
4925
|
+
(0, import_dom2.computePosition)(anchorRef.current, contentRef.current, {
|
|
1711
4926
|
placement,
|
|
1712
4927
|
strategy: "fixed",
|
|
1713
4928
|
middleware
|
|
@@ -1726,18 +4941,18 @@ var Popover = ({ x, y, placement = "right", offset: pixelOffset = 0, arrow: arro
|
|
|
1726
4941
|
}
|
|
1727
4942
|
});
|
|
1728
4943
|
};
|
|
1729
|
-
(0,
|
|
4944
|
+
(0, import_hooks5.useMemo)(() => {
|
|
1730
4945
|
var _a;
|
|
1731
4946
|
(_a = updaterRef.current) == null ? void 0 : _a.call(updaterRef);
|
|
1732
4947
|
}, [x, y, placement, arrowSize, pixelOffset]);
|
|
1733
|
-
(0,
|
|
4948
|
+
(0, import_hooks5.useEffect)(() => {
|
|
1734
4949
|
const anchor = anchorRef.current;
|
|
1735
4950
|
const content = contentRef.current;
|
|
1736
4951
|
if (!anchor || !content) {
|
|
1737
4952
|
return void 0;
|
|
1738
4953
|
}
|
|
1739
4954
|
content.style.visibility = "visible";
|
|
1740
|
-
const cleanup = (0,
|
|
4955
|
+
const cleanup = (0, import_dom2.autoUpdate)(anchor, content, () => {
|
|
1741
4956
|
var _a;
|
|
1742
4957
|
return (_a = updaterRef.current) == null ? void 0 : _a.call(updaterRef);
|
|
1743
4958
|
});
|
|
@@ -1745,7 +4960,7 @@ var Popover = ({ x, y, placement = "right", offset: pixelOffset = 0, arrow: arro
|
|
|
1745
4960
|
cleanup();
|
|
1746
4961
|
};
|
|
1747
4962
|
}, []);
|
|
1748
|
-
return (0,
|
|
4963
|
+
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
4964
|
};
|
|
1750
4965
|
function createArrow(width, height, color, placement) {
|
|
1751
4966
|
const result = {
|
|
@@ -1785,11 +5000,11 @@ function createArrow(width, height, color, placement) {
|
|
|
1785
5000
|
}
|
|
1786
5001
|
|
|
1787
5002
|
// dist/lib/components/user-content.js
|
|
1788
|
-
var
|
|
1789
|
-
var
|
|
5003
|
+
var import_jsx_runtime14 = require("preact/jsx-runtime");
|
|
5004
|
+
var import_hooks6 = require("preact/hooks");
|
|
1790
5005
|
var UserContent = ({ text, html, element, ...props }) => {
|
|
1791
|
-
const containerRef = (0,
|
|
1792
|
-
(0,
|
|
5006
|
+
const containerRef = (0, import_hooks6.useRef)(null);
|
|
5007
|
+
(0, import_hooks6.useEffect)(() => {
|
|
1793
5008
|
if (containerRef.current && element) {
|
|
1794
5009
|
containerRef.current.append(element);
|
|
1795
5010
|
}
|
|
@@ -1797,11 +5012,11 @@ var UserContent = ({ text, html, element, ...props }) => {
|
|
|
1797
5012
|
element == null ? void 0 : element.remove();
|
|
1798
5013
|
};
|
|
1799
5014
|
}, [element]);
|
|
1800
|
-
return (0,
|
|
5015
|
+
return (0, import_jsx_runtime14.jsx)("div", { ref: containerRef, ...props, dangerouslySetInnerHTML: html ? { __html: html } : void 0, children: text });
|
|
1801
5016
|
};
|
|
1802
5017
|
|
|
1803
5018
|
// dist/info-widget.js
|
|
1804
|
-
var InfoWidget = class extends
|
|
5019
|
+
var InfoWidget = class extends Widget {
|
|
1805
5020
|
constructor(props) {
|
|
1806
5021
|
super(props);
|
|
1807
5022
|
this.className = "deck-widget-info";
|
|
@@ -1867,12 +5082,12 @@ var InfoWidget = class extends import_core11.Widget {
|
|
|
1867
5082
|
...this.tooltip.style
|
|
1868
5083
|
};
|
|
1869
5084
|
const [x, y] = this.viewport.project(this.tooltip.position);
|
|
1870
|
-
const ui = (0,
|
|
5085
|
+
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
5086
|
(0, import_preact9.render)(ui, rootElement);
|
|
1872
5087
|
}
|
|
1873
5088
|
};
|
|
1874
5089
|
InfoWidget.defaultProps = {
|
|
1875
|
-
...
|
|
5090
|
+
...Widget.defaultProps,
|
|
1876
5091
|
id: "info",
|
|
1877
5092
|
viewId: null,
|
|
1878
5093
|
mode: "hover",
|
|
@@ -1883,10 +5098,9 @@ InfoWidget.defaultProps = {
|
|
|
1883
5098
|
};
|
|
1884
5099
|
|
|
1885
5100
|
// dist/popup-widget.js
|
|
1886
|
-
var
|
|
1887
|
-
var import_core12 = require("@deck.gl/core");
|
|
5101
|
+
var import_jsx_runtime16 = require("preact/jsx-runtime");
|
|
1888
5102
|
var import_preact10 = require("preact");
|
|
1889
|
-
var PopupWidget = class extends
|
|
5103
|
+
var PopupWidget = class extends Widget {
|
|
1890
5104
|
constructor(props) {
|
|
1891
5105
|
super(props);
|
|
1892
5106
|
this.className = "deck-widget-popup";
|
|
@@ -1930,12 +5144,12 @@ var PopupWidget = class extends import_core12.Widget {
|
|
|
1930
5144
|
}
|
|
1931
5145
|
const { marker, content, style } = this.props;
|
|
1932
5146
|
const [x, y] = this.viewport.project(this.props.position);
|
|
1933
|
-
const ui = (0,
|
|
5147
|
+
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
5148
|
(0, import_preact10.render)(ui, rootElement);
|
|
1935
5149
|
}
|
|
1936
5150
|
};
|
|
1937
5151
|
PopupWidget.defaultProps = {
|
|
1938
|
-
...
|
|
5152
|
+
...Widget.defaultProps,
|
|
1939
5153
|
id: "info",
|
|
1940
5154
|
viewId: null,
|
|
1941
5155
|
position: [0, 0],
|
|
@@ -1952,10 +5166,9 @@ PopupWidget.defaultProps = {
|
|
|
1952
5166
|
};
|
|
1953
5167
|
|
|
1954
5168
|
// dist/context-menu-widget.js
|
|
1955
|
-
var
|
|
1956
|
-
var import_core13 = require("@deck.gl/core");
|
|
5169
|
+
var import_jsx_runtime17 = require("preact/jsx-runtime");
|
|
1957
5170
|
var import_preact11 = require("preact");
|
|
1958
|
-
var ContextMenuWidget = class extends
|
|
5171
|
+
var ContextMenuWidget = class extends Widget {
|
|
1959
5172
|
constructor(props) {
|
|
1960
5173
|
super(props);
|
|
1961
5174
|
this.className = "deck-widget-context-menu";
|
|
@@ -2000,7 +5213,7 @@ var ContextMenuWidget = class extends import_core13.Widget {
|
|
|
2000
5213
|
position: "static",
|
|
2001
5214
|
...this.props.style
|
|
2002
5215
|
};
|
|
2003
|
-
const ui = (0,
|
|
5216
|
+
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
5217
|
(0, import_preact11.render)(ui, rootElement);
|
|
2005
5218
|
}
|
|
2006
5219
|
hide() {
|
|
@@ -2009,7 +5222,7 @@ var ContextMenuWidget = class extends import_core13.Widget {
|
|
|
2009
5222
|
}
|
|
2010
5223
|
};
|
|
2011
5224
|
ContextMenuWidget.defaultProps = {
|
|
2012
|
-
...
|
|
5225
|
+
...Widget.defaultProps,
|
|
2013
5226
|
id: "context",
|
|
2014
5227
|
viewId: null,
|
|
2015
5228
|
menuItems: [],
|
|
@@ -2022,15 +5235,14 @@ ContextMenuWidget.defaultProps = {
|
|
|
2022
5235
|
};
|
|
2023
5236
|
|
|
2024
5237
|
// dist/scrollbar-widget.js
|
|
2025
|
-
var
|
|
2026
|
-
var import_core14 = require("@deck.gl/core");
|
|
5238
|
+
var import_jsx_runtime19 = require("preact/jsx-runtime");
|
|
2027
5239
|
var import_preact12 = require("preact");
|
|
2028
5240
|
|
|
2029
5241
|
// dist/lib/components/range-input.js
|
|
2030
|
-
var
|
|
2031
|
-
var
|
|
5242
|
+
var import_jsx_runtime18 = require("preact/jsx-runtime");
|
|
5243
|
+
var import_hooks7 = require("preact/hooks");
|
|
2032
5244
|
var wheelListenerOptions = { passive: false };
|
|
2033
|
-
var
|
|
5245
|
+
var clamp6 = (value, min, max) => {
|
|
2034
5246
|
if (value < min) {
|
|
2035
5247
|
return min;
|
|
2036
5248
|
}
|
|
@@ -2064,16 +5276,16 @@ var getEffectivePage = (pageSize, rangeSize) => {
|
|
|
2064
5276
|
function RangeInput(props) {
|
|
2065
5277
|
const { className = "", min, max, step, value, orientation, pageSize, stepButtons = false, startButtonAriaLabel, endButtonAriaLabel, eventTarget, decorations = [], onChange } = props;
|
|
2066
5278
|
const vertical = orientation !== "horizontal";
|
|
2067
|
-
const rootRef = (0,
|
|
2068
|
-
const trackRef = (0,
|
|
2069
|
-
const thumbRef = (0,
|
|
2070
|
-
const dragStateRef = (0,
|
|
2071
|
-
const [trackLength, setTrackLength] = (0,
|
|
5279
|
+
const rootRef = (0, import_hooks7.useRef)(null);
|
|
5280
|
+
const trackRef = (0, import_hooks7.useRef)(null);
|
|
5281
|
+
const thumbRef = (0, import_hooks7.useRef)(null);
|
|
5282
|
+
const dragStateRef = (0, import_hooks7.useRef)(null);
|
|
5283
|
+
const [trackLength, setTrackLength] = (0, import_hooks7.useState)(0);
|
|
2072
5284
|
const range = max - min;
|
|
2073
5285
|
const rangeSize = Math.max(0, value[1] - value[0]);
|
|
2074
5286
|
const maxStart = Math.max(0, range - rangeSize);
|
|
2075
|
-
const clampedStart =
|
|
2076
|
-
const { thumbLength, thumbOffset } = (0,
|
|
5287
|
+
const clampedStart = clamp6(value[0], min, min + maxStart);
|
|
5288
|
+
const { thumbLength, thumbOffset } = (0, import_hooks7.useMemo)(() => {
|
|
2077
5289
|
if (trackLength <= 0 || range <= 0) {
|
|
2078
5290
|
return { thumbLength: 0, thumbOffset: 0 };
|
|
2079
5291
|
}
|
|
@@ -2082,28 +5294,28 @@ function RangeInput(props) {
|
|
|
2082
5294
|
}
|
|
2083
5295
|
const nextThumbLength = rangeSize / range;
|
|
2084
5296
|
const travel = Math.max(0, 1 - nextThumbLength);
|
|
2085
|
-
const ratio = maxStart <= 0 ? 0 :
|
|
5297
|
+
const ratio = maxStart <= 0 ? 0 : clamp6((clampedStart - min) / maxStart, 0, 1);
|
|
2086
5298
|
return {
|
|
2087
5299
|
thumbLength: Math.max(0, Math.min(nextThumbLength, 1)),
|
|
2088
5300
|
thumbOffset: travel * ratio
|
|
2089
5301
|
};
|
|
2090
5302
|
}, [trackLength, range, rangeSize, maxStart, clampedStart, min]);
|
|
2091
|
-
const emitRange = (0,
|
|
5303
|
+
const emitRange = (0, import_hooks7.useCallback)((nextStart) => {
|
|
2092
5304
|
if (!onChange) {
|
|
2093
5305
|
return;
|
|
2094
5306
|
}
|
|
2095
|
-
const clamped =
|
|
5307
|
+
const clamped = clamp6(nextStart, min, min + maxStart);
|
|
2096
5308
|
onChange([clamped, clamped + rangeSize]);
|
|
2097
5309
|
}, [onChange, min, maxStart, rangeSize]);
|
|
2098
|
-
const handleStepNegative = (0,
|
|
5310
|
+
const handleStepNegative = (0, import_hooks7.useCallback)((event) => {
|
|
2099
5311
|
event.stopPropagation();
|
|
2100
5312
|
emitRange(clampedStart - getEffectiveStep(step, range));
|
|
2101
5313
|
}, [emitRange, clampedStart, step, range]);
|
|
2102
|
-
const handleStepPositive = (0,
|
|
5314
|
+
const handleStepPositive = (0, import_hooks7.useCallback)((event) => {
|
|
2103
5315
|
event.stopPropagation();
|
|
2104
5316
|
emitRange(clampedStart + getEffectiveStep(step, range));
|
|
2105
5317
|
}, [emitRange, clampedStart, step, range]);
|
|
2106
|
-
const handleTrackClick = (0,
|
|
5318
|
+
const handleTrackClick = (0, import_hooks7.useCallback)((event) => {
|
|
2107
5319
|
if (event.button !== 0) {
|
|
2108
5320
|
return;
|
|
2109
5321
|
}
|
|
@@ -2121,7 +5333,7 @@ function RangeInput(props) {
|
|
|
2121
5333
|
const coordinate = vertical ? event.clientY - trackStart : event.clientX - trackStart;
|
|
2122
5334
|
const span = Math.max(1, 1 - thumbLength) * trackLength;
|
|
2123
5335
|
const thumbCenter = thumbLength / 2 * trackLength;
|
|
2124
|
-
const ratio = span <= 0 ? 0 :
|
|
5336
|
+
const ratio = span <= 0 ? 0 : clamp6((coordinate - thumbCenter) / span, 0, 1);
|
|
2125
5337
|
emitRange(min + ratio * maxStart);
|
|
2126
5338
|
}, [vertical, trackLength, thumbLength, emitRange, min, maxStart]);
|
|
2127
5339
|
const handleThumbPointerDown = (event) => {
|
|
@@ -2144,7 +5356,7 @@ function RangeInput(props) {
|
|
|
2144
5356
|
event.preventDefault();
|
|
2145
5357
|
event.stopPropagation();
|
|
2146
5358
|
};
|
|
2147
|
-
const handleThumbPointerMove = (0,
|
|
5359
|
+
const handleThumbPointerMove = (0, import_hooks7.useCallback)((event) => {
|
|
2148
5360
|
const state = dragStateRef.current;
|
|
2149
5361
|
if (!state || state.pointerId !== event.pointerId) {
|
|
2150
5362
|
return;
|
|
@@ -2153,11 +5365,11 @@ function RangeInput(props) {
|
|
|
2153
5365
|
const coordinate = vertical ? event.clientY : event.clientX;
|
|
2154
5366
|
const delta = coordinate - state.startCoord;
|
|
2155
5367
|
const ratio = state.startRatio + delta / trackLength2;
|
|
2156
|
-
const nextStart =
|
|
5368
|
+
const nextStart = clamp6(ratio * (state.max - state.min), 0, state.maxStart) + state.min;
|
|
2157
5369
|
emitRange(nextStart);
|
|
2158
5370
|
event.preventDefault();
|
|
2159
5371
|
}, [emitRange, vertical]);
|
|
2160
|
-
const handleThumbPointerUp = (0,
|
|
5372
|
+
const handleThumbPointerUp = (0, import_hooks7.useCallback)((event) => {
|
|
2161
5373
|
var _a;
|
|
2162
5374
|
const state = dragStateRef.current;
|
|
2163
5375
|
if (state && state.pointerId === event.pointerId) {
|
|
@@ -2166,7 +5378,7 @@ function RangeInput(props) {
|
|
|
2166
5378
|
event.preventDefault();
|
|
2167
5379
|
}
|
|
2168
5380
|
}, []);
|
|
2169
|
-
const handleKeyDown = (0,
|
|
5381
|
+
const handleKeyDown = (0, import_hooks7.useCallback)((event) => {
|
|
2170
5382
|
switch (event.key) {
|
|
2171
5383
|
case "ArrowUp":
|
|
2172
5384
|
case "ArrowLeft":
|
|
@@ -2202,7 +5414,7 @@ function RangeInput(props) {
|
|
|
2202
5414
|
break;
|
|
2203
5415
|
}
|
|
2204
5416
|
}, [vertical, emitRange, clampedStart, step, range, pageSize, rangeSize, min, maxStart]);
|
|
2205
|
-
const handleWheel = (0,
|
|
5417
|
+
const handleWheel = (0, import_hooks7.useCallback)((event) => {
|
|
2206
5418
|
event.preventDefault();
|
|
2207
5419
|
event.stopPropagation();
|
|
2208
5420
|
if (maxStart === 0) {
|
|
@@ -2222,10 +5434,10 @@ function RangeInput(props) {
|
|
|
2222
5434
|
}
|
|
2223
5435
|
emitRange(clampedStart + delta);
|
|
2224
5436
|
}, [emitRange, clampedStart, maxStart, vertical, step, range, pageSize, rangeSize]);
|
|
2225
|
-
(0,
|
|
5437
|
+
(0, import_hooks7.useLayoutEffect)(() => {
|
|
2226
5438
|
setTrackLength(getTrackDimension(trackRef.current, vertical)[1]);
|
|
2227
5439
|
}, [vertical]);
|
|
2228
|
-
(0,
|
|
5440
|
+
(0, import_hooks7.useLayoutEffect)(() => {
|
|
2229
5441
|
const track = trackRef.current;
|
|
2230
5442
|
if (!track) {
|
|
2231
5443
|
return void 0;
|
|
@@ -2245,7 +5457,7 @@ function RangeInput(props) {
|
|
|
2245
5457
|
}
|
|
2246
5458
|
return void 0;
|
|
2247
5459
|
}, [vertical]);
|
|
2248
|
-
(0,
|
|
5460
|
+
(0, import_hooks7.useEffect)(() => {
|
|
2249
5461
|
const eventRoot = eventTarget ?? rootRef.current;
|
|
2250
5462
|
if (!eventRoot)
|
|
2251
5463
|
return void 0;
|
|
@@ -2256,7 +5468,7 @@ function RangeInput(props) {
|
|
|
2256
5468
|
eventRoot.removeEventListener("wheel", handleWheel, wheelListenerOptions);
|
|
2257
5469
|
};
|
|
2258
5470
|
}, [eventTarget, handleKeyDown, handleWheel]);
|
|
2259
|
-
const decorationElements = (0,
|
|
5471
|
+
const decorationElements = (0, import_hooks7.useMemo)(() => {
|
|
2260
5472
|
if (!decorations.length || range <= 0) {
|
|
2261
5473
|
return [];
|
|
2262
5474
|
}
|
|
@@ -2277,14 +5489,14 @@ function RangeInput(props) {
|
|
|
2277
5489
|
left: `${offsetPct}%`,
|
|
2278
5490
|
width: `${sizePct}%`
|
|
2279
5491
|
};
|
|
2280
|
-
return (0,
|
|
5492
|
+
return (0, import_jsx_runtime18.jsx)("div", { className: "deck-widget-range__decoration", style, children: decoration.element }, `decoration-${index}`);
|
|
2281
5493
|
});
|
|
2282
5494
|
}, [decorations, range, min, vertical]);
|
|
2283
|
-
return (0,
|
|
5495
|
+
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
5496
|
}
|
|
2285
5497
|
|
|
2286
5498
|
// dist/scrollbar-widget.js
|
|
2287
|
-
var
|
|
5499
|
+
var clamp7 = (value, min, max) => {
|
|
2288
5500
|
if (value < min) {
|
|
2289
5501
|
return min;
|
|
2290
5502
|
}
|
|
@@ -2293,10 +5505,10 @@ var clamp3 = (value, min, max) => {
|
|
|
2293
5505
|
}
|
|
2294
5506
|
return value;
|
|
2295
5507
|
};
|
|
2296
|
-
var ScrollbarWidget = class extends
|
|
5508
|
+
var ScrollbarWidget = class _ScrollbarWidget extends Widget {
|
|
2297
5509
|
constructor(props) {
|
|
2298
5510
|
const resolved = {
|
|
2299
|
-
...
|
|
5511
|
+
..._ScrollbarWidget.defaultProps,
|
|
2300
5512
|
...props
|
|
2301
5513
|
};
|
|
2302
5514
|
super(resolved);
|
|
@@ -2328,7 +5540,7 @@ var ScrollbarWidget = class extends import_core14.Widget {
|
|
|
2328
5540
|
const isVertical = this.isVertical();
|
|
2329
5541
|
const startLabel = this.props.startButtonAriaLabel ?? (isVertical ? "Scroll up" : "Scroll left");
|
|
2330
5542
|
const endLabel = this.props.endButtonAriaLabel ?? (isVertical ? "Scroll down" : "Scroll right");
|
|
2331
|
-
const ui = (0,
|
|
5543
|
+
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
5544
|
(0, import_preact12.render)(ui, element);
|
|
2333
5545
|
}
|
|
2334
5546
|
onRemove() {
|
|
@@ -2341,6 +5553,10 @@ var ScrollbarWidget = class extends import_core14.Widget {
|
|
|
2341
5553
|
var _a, _b, _c;
|
|
2342
5554
|
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
5555
|
}
|
|
5556
|
+
getContentBoundsPadding(viewId) {
|
|
5557
|
+
var _a, _b, _c;
|
|
5558
|
+
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;
|
|
5559
|
+
}
|
|
2344
5560
|
updateViewport(viewport) {
|
|
2345
5561
|
if (!viewport) {
|
|
2346
5562
|
this.contentSize = 0;
|
|
@@ -2351,9 +5567,12 @@ var ScrollbarWidget = class extends import_core14.Widget {
|
|
|
2351
5567
|
const contentBounds = this.getContentBounds(viewport.id);
|
|
2352
5568
|
const isVertical = this.isVertical();
|
|
2353
5569
|
const projectedBounds = contentBounds ? projectBounds(contentBounds, viewport, isVertical) : [0, 0];
|
|
5570
|
+
const contentRect = getMaxBoundsRect(viewport.width, viewport.height, this.getContentBoundsPadding(viewport.id));
|
|
5571
|
+
const contentStart = isVertical ? contentRect.y : contentRect.x;
|
|
5572
|
+
const viewportSize = isVertical ? contentRect.height : contentRect.width;
|
|
2354
5573
|
this.contentSize = projectedBounds[1] - projectedBounds[0];
|
|
2355
|
-
this.scrollOffset = -projectedBounds[0];
|
|
2356
|
-
this.viewportSize =
|
|
5574
|
+
this.scrollOffset = contentStart - projectedBounds[0];
|
|
5575
|
+
this.viewportSize = Math.max(0, viewportSize);
|
|
2357
5576
|
}
|
|
2358
5577
|
getDecorations(viewport) {
|
|
2359
5578
|
const { decorations = [] } = this.props;
|
|
@@ -2378,7 +5597,7 @@ var ScrollbarWidget = class extends import_core14.Widget {
|
|
|
2378
5597
|
} : void 0;
|
|
2379
5598
|
return {
|
|
2380
5599
|
position: [start - contentStart, end - contentStart],
|
|
2381
|
-
element: (0,
|
|
5600
|
+
element: (0, import_jsx_runtime19.jsx)("div", { style: {
|
|
2382
5601
|
pointerEvents: onClick ? "all" : "none",
|
|
2383
5602
|
width: "100%",
|
|
2384
5603
|
height: "100%",
|
|
@@ -2400,7 +5619,7 @@ var ScrollbarWidget = class extends import_core14.Widget {
|
|
|
2400
5619
|
}
|
|
2401
5620
|
getClampedOffset() {
|
|
2402
5621
|
const maxScroll = this.getMaxScroll();
|
|
2403
|
-
return
|
|
5622
|
+
return clamp7(this.scrollOffset, 0, maxScroll);
|
|
2404
5623
|
}
|
|
2405
5624
|
isVertical() {
|
|
2406
5625
|
return this.props.orientation !== "horizontal";
|
|
@@ -2419,7 +5638,7 @@ var ScrollbarWidget = class extends import_core14.Widget {
|
|
|
2419
5638
|
}
|
|
2420
5639
|
emitScroll(next) {
|
|
2421
5640
|
const maxScroll = this.getMaxScroll();
|
|
2422
|
-
const target =
|
|
5641
|
+
const target = clamp7(Math.round(next), 0, maxScroll);
|
|
2423
5642
|
const viewport = this.viewport;
|
|
2424
5643
|
if (viewport && target !== this.getClampedOffset()) {
|
|
2425
5644
|
const pixel = viewport.project(viewport.position);
|
|
@@ -2441,8 +5660,9 @@ var ScrollbarWidget = class extends import_core14.Widget {
|
|
|
2441
5660
|
}
|
|
2442
5661
|
};
|
|
2443
5662
|
ScrollbarWidget.defaultProps = {
|
|
2444
|
-
...
|
|
5663
|
+
...Widget.defaultProps,
|
|
2445
5664
|
contentBounds: null,
|
|
5665
|
+
contentBoundsPadding: null,
|
|
2446
5666
|
placement: "top-right",
|
|
2447
5667
|
viewId: null,
|
|
2448
5668
|
orientation: "vertical",
|
|
@@ -2463,10 +5683,9 @@ function projectBounds(bounds, viewport, isVertical) {
|
|
|
2463
5683
|
}
|
|
2464
5684
|
|
|
2465
5685
|
// dist/icon-widget.js
|
|
2466
|
-
var
|
|
5686
|
+
var import_jsx_runtime20 = require("preact/jsx-runtime");
|
|
2467
5687
|
var import_preact13 = require("preact");
|
|
2468
|
-
var
|
|
2469
|
-
var IconWidget = class extends import_core15.Widget {
|
|
5688
|
+
var IconWidget = class extends Widget {
|
|
2470
5689
|
constructor(props) {
|
|
2471
5690
|
super(props);
|
|
2472
5691
|
this.className = "";
|
|
@@ -2479,26 +5698,26 @@ var IconWidget = class extends import_core15.Widget {
|
|
|
2479
5698
|
super.setProps(props);
|
|
2480
5699
|
}
|
|
2481
5700
|
onRenderHTML(rootElement) {
|
|
2482
|
-
const { className, style, icon, color, label, onClick } = this.props;
|
|
2483
|
-
(0, import_preact13.render)((0,
|
|
5701
|
+
const { className, style, icon, color, label, tooltip, onClick } = this.props;
|
|
5702
|
+
(0, import_preact13.render)((0, import_jsx_runtime20.jsx)(IconButton, { className, style, color, icon, label, tooltip, onClick }), rootElement);
|
|
2484
5703
|
}
|
|
2485
5704
|
};
|
|
2486
5705
|
IconWidget.defaultProps = {
|
|
2487
|
-
...
|
|
5706
|
+
...Widget.defaultProps,
|
|
2488
5707
|
id: "icon",
|
|
2489
5708
|
placement: "top-left",
|
|
2490
5709
|
viewId: null,
|
|
2491
5710
|
icon: "",
|
|
2492
5711
|
label: "",
|
|
5712
|
+
tooltip: void 0,
|
|
2493
5713
|
color: "",
|
|
2494
5714
|
onClick: void 0
|
|
2495
5715
|
};
|
|
2496
5716
|
|
|
2497
5717
|
// dist/toggle-widget.js
|
|
2498
|
-
var
|
|
5718
|
+
var import_jsx_runtime21 = require("preact/jsx-runtime");
|
|
2499
5719
|
var import_preact14 = require("preact");
|
|
2500
|
-
var
|
|
2501
|
-
var ToggleWidget = class extends import_core16.Widget {
|
|
5720
|
+
var ToggleWidget = class extends Widget {
|
|
2502
5721
|
constructor(props) {
|
|
2503
5722
|
super(props);
|
|
2504
5723
|
this.className = "deck-widget-toggle";
|
|
@@ -2518,14 +5737,14 @@ var ToggleWidget = class extends import_core16.Widget {
|
|
|
2518
5737
|
super.setProps(props);
|
|
2519
5738
|
}
|
|
2520
5739
|
onRenderHTML(rootElement) {
|
|
2521
|
-
const { className, style, icon, label, color, onIcon = icon, onLabel = label, onColor = color } = this.props;
|
|
5740
|
+
const { className, style, icon, label, tooltip, color, onIcon = icon, onLabel = label, onTooltip, onColor = color } = this.props;
|
|
2522
5741
|
const on = this.checked;
|
|
2523
5742
|
rootElement.dataset.checked = String(on);
|
|
2524
|
-
(0, import_preact14.render)((0,
|
|
5743
|
+
(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
5744
|
}
|
|
2526
5745
|
};
|
|
2527
5746
|
ToggleWidget.defaultProps = {
|
|
2528
|
-
...
|
|
5747
|
+
...Widget.defaultProps,
|
|
2529
5748
|
id: "icon",
|
|
2530
5749
|
placement: "top-left",
|
|
2531
5750
|
viewId: null,
|
|
@@ -2533,17 +5752,18 @@ ToggleWidget.defaultProps = {
|
|
|
2533
5752
|
icon: "",
|
|
2534
5753
|
onIcon: void 0,
|
|
2535
5754
|
label: "",
|
|
5755
|
+
tooltip: void 0,
|
|
2536
5756
|
onLabel: void 0,
|
|
5757
|
+
onTooltip: void 0,
|
|
2537
5758
|
color: "",
|
|
2538
5759
|
onColor: void 0,
|
|
2539
5760
|
onChange: void 0
|
|
2540
5761
|
};
|
|
2541
5762
|
|
|
2542
5763
|
// dist/selector-widget.js
|
|
2543
|
-
var
|
|
5764
|
+
var import_jsx_runtime22 = require("preact/jsx-runtime");
|
|
2544
5765
|
var import_preact15 = require("preact");
|
|
2545
|
-
var
|
|
2546
|
-
var SelectorWidget = class extends import_core17.Widget {
|
|
5766
|
+
var SelectorWidget = class extends Widget {
|
|
2547
5767
|
constructor(props) {
|
|
2548
5768
|
super(props);
|
|
2549
5769
|
this.className = "deck-widget-selector";
|
|
@@ -2576,25 +5796,25 @@ var SelectorWidget = class extends import_core17.Widget {
|
|
|
2576
5796
|
}
|
|
2577
5797
|
onRenderHTML(rootElement) {
|
|
2578
5798
|
const selectedOption = this.props.options.find((opt) => opt.value === this.value) ?? this.props.options[0];
|
|
2579
|
-
(0, import_preact15.render)((0,
|
|
5799
|
+
(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
5800
|
}
|
|
2581
5801
|
};
|
|
2582
5802
|
SelectorWidget.defaultProps = {
|
|
2583
|
-
...
|
|
5803
|
+
...Widget.defaultProps,
|
|
2584
5804
|
id: "view-selector",
|
|
2585
5805
|
placement: "top-left",
|
|
2586
5806
|
viewId: null,
|
|
2587
5807
|
initialValue: "",
|
|
2588
5808
|
options: [],
|
|
5809
|
+
tooltip: void 0,
|
|
2589
5810
|
onChange: () => {
|
|
2590
5811
|
}
|
|
2591
5812
|
};
|
|
2592
5813
|
|
|
2593
5814
|
// dist/timeline-widget.js
|
|
2594
|
-
var
|
|
2595
|
-
var import_core18 = require("@deck.gl/core");
|
|
5815
|
+
var import_jsx_runtime23 = require("preact/jsx-runtime");
|
|
2596
5816
|
var import_preact16 = require("preact");
|
|
2597
|
-
var TimelineWidget = class extends
|
|
5817
|
+
var TimelineWidget = class extends Widget {
|
|
2598
5818
|
/**
|
|
2599
5819
|
* Returns the current time value.
|
|
2600
5820
|
* In controlled mode, returns the time prop.
|
|
@@ -2708,14 +5928,14 @@ var TimelineWidget = class extends import_core18.Widget {
|
|
|
2708
5928
|
this.stop();
|
|
2709
5929
|
}
|
|
2710
5930
|
onRenderHTML(rootElement) {
|
|
2711
|
-
const { timeRange, step, formatLabel } = this.props;
|
|
5931
|
+
const { timeRange, step, formatLabel, playTooltip, pauseTooltip } = this.props;
|
|
2712
5932
|
const isPlaying = this.getPlaying();
|
|
2713
5933
|
const currentTime = this.getTime();
|
|
2714
5934
|
rootElement.dataset.placement = this.props.placement;
|
|
2715
|
-
(0, import_preact16.render)((0,
|
|
5935
|
+
(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
5936
|
{
|
|
2717
5937
|
position: [currentTime, currentTime + step],
|
|
2718
|
-
element: (0,
|
|
5938
|
+
element: (0, import_jsx_runtime23.jsx)("div", { className: "deck-widget-timeline-label deck-widget-timeline-label--current", children: formatLabel(currentTime) })
|
|
2719
5939
|
}
|
|
2720
5940
|
] })] }), rootElement);
|
|
2721
5941
|
}
|
|
@@ -2750,7 +5970,7 @@ var TimelineWidget = class extends import_core18.Widget {
|
|
|
2750
5970
|
}
|
|
2751
5971
|
};
|
|
2752
5972
|
TimelineWidget.defaultProps = {
|
|
2753
|
-
...
|
|
5973
|
+
...Widget.defaultProps,
|
|
2754
5974
|
id: "timeline",
|
|
2755
5975
|
placement: "bottom-left",
|
|
2756
5976
|
viewId: null,
|
|
@@ -2767,14 +5987,15 @@ TimelineWidget.defaultProps = {
|
|
|
2767
5987
|
playing: void 0,
|
|
2768
5988
|
onPlayingChange: () => {
|
|
2769
5989
|
},
|
|
2770
|
-
formatLabel: String
|
|
5990
|
+
formatLabel: String,
|
|
5991
|
+
playTooltip: void 0,
|
|
5992
|
+
pauseTooltip: void 0
|
|
2771
5993
|
};
|
|
2772
5994
|
|
|
2773
5995
|
// dist/screenshot-widget.js
|
|
2774
|
-
var
|
|
5996
|
+
var import_jsx_runtime24 = require("preact/jsx-runtime");
|
|
2775
5997
|
var import_preact17 = require("preact");
|
|
2776
|
-
var
|
|
2777
|
-
var ScreenshotWidget = class extends import_core19.Widget {
|
|
5998
|
+
var ScreenshotWidget = class extends Widget {
|
|
2778
5999
|
constructor(props = {}) {
|
|
2779
6000
|
super(props);
|
|
2780
6001
|
this.className = "deck-widget-screenshot";
|
|
@@ -2787,7 +6008,7 @@ var ScreenshotWidget = class extends import_core19.Widget {
|
|
|
2787
6008
|
super.setProps(props);
|
|
2788
6009
|
}
|
|
2789
6010
|
onRenderHTML(rootElement) {
|
|
2790
|
-
(0, import_preact17.render)((0,
|
|
6011
|
+
(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
6012
|
}
|
|
2792
6013
|
handleClick() {
|
|
2793
6014
|
if (this.props.onCapture) {
|
|
@@ -2814,26 +6035,26 @@ var ScreenshotWidget = class extends import_core19.Widget {
|
|
|
2814
6035
|
}
|
|
2815
6036
|
};
|
|
2816
6037
|
ScreenshotWidget.defaultProps = {
|
|
2817
|
-
...
|
|
6038
|
+
...Widget.defaultProps,
|
|
2818
6039
|
id: "screenshot",
|
|
2819
6040
|
placement: "top-left",
|
|
2820
6041
|
viewId: null,
|
|
2821
6042
|
label: "Screenshot",
|
|
6043
|
+
tooltip: void 0,
|
|
2822
6044
|
filename: "screenshot.png",
|
|
2823
6045
|
imageFormat: "image/png",
|
|
2824
6046
|
onCapture: void 0
|
|
2825
6047
|
};
|
|
2826
6048
|
|
|
2827
6049
|
// dist/theme-widget.js
|
|
2828
|
-
var
|
|
2829
|
-
var import_core20 = require("@deck.gl/core");
|
|
2830
|
-
var import_core21 = require("@deck.gl/core");
|
|
6050
|
+
var import_jsx_runtime25 = require("preact/jsx-runtime");
|
|
2831
6051
|
var import_preact18 = require("preact");
|
|
2832
6052
|
|
|
2833
6053
|
// dist/themes.js
|
|
2834
6054
|
var LightTheme = {
|
|
2835
6055
|
"--widget-margin": "12px",
|
|
2836
6056
|
"--button-size": "28px",
|
|
6057
|
+
"--icon-size": "75%",
|
|
2837
6058
|
"--button-corner-radius": "8px",
|
|
2838
6059
|
"--button-background": "#fff",
|
|
2839
6060
|
"--button-stroke": "rgba(255, 255, 255, 0.3)",
|
|
@@ -2862,6 +6083,7 @@ var LightTheme = {
|
|
|
2862
6083
|
var DarkTheme = {
|
|
2863
6084
|
"--widget-margin": "12px",
|
|
2864
6085
|
"--button-size": "28px",
|
|
6086
|
+
"--icon-size": "75%",
|
|
2865
6087
|
"--button-corner-radius": "8px",
|
|
2866
6088
|
"--button-background": "rgba(18, 18, 20, 1)",
|
|
2867
6089
|
"--button-stroke": "rgba(18, 18, 20, 0.30)",
|
|
@@ -2890,6 +6112,7 @@ var DarkTheme = {
|
|
|
2890
6112
|
var LightGlassTheme = {
|
|
2891
6113
|
"--widget-margin": "12px",
|
|
2892
6114
|
"--button-size": "28px",
|
|
6115
|
+
"--icon-size": "75%",
|
|
2893
6116
|
"--button-corner-radius": "8px",
|
|
2894
6117
|
"--button-background": "rgba(255, 255, 255, 0.6)",
|
|
2895
6118
|
"--button-stroke": "rgba(255, 255, 255, 0.3)",
|
|
@@ -2918,6 +6141,7 @@ var LightGlassTheme = {
|
|
|
2918
6141
|
var DarkGlassTheme = {
|
|
2919
6142
|
"--widget-margin": "12px",
|
|
2920
6143
|
"--button-size": "28px",
|
|
6144
|
+
"--icon-size": "75%",
|
|
2921
6145
|
"--button-corner-radius": "8px",
|
|
2922
6146
|
"--button-background": "rgba(18, 18, 20, 0.75)",
|
|
2923
6147
|
"--button-stroke": "rgba(18, 18, 20, 0.30)",
|
|
@@ -2945,7 +6169,7 @@ var DarkGlassTheme = {
|
|
|
2945
6169
|
};
|
|
2946
6170
|
|
|
2947
6171
|
// dist/theme-widget.js
|
|
2948
|
-
var ThemeWidget = class extends
|
|
6172
|
+
var ThemeWidget = class extends Widget {
|
|
2949
6173
|
constructor(props = {}) {
|
|
2950
6174
|
super(props);
|
|
2951
6175
|
this.className = "deck-widget-theme";
|
|
@@ -2962,10 +6186,10 @@ var ThemeWidget = class extends import_core21.Widget {
|
|
|
2962
6186
|
super.setProps(props);
|
|
2963
6187
|
}
|
|
2964
6188
|
onRenderHTML(rootElement) {
|
|
2965
|
-
const { lightModeLabel, darkModeLabel } = this.props;
|
|
6189
|
+
const { lightModeLabel, darkModeLabel, lightModeTooltip, darkModeTooltip } = this.props;
|
|
2966
6190
|
const currentMode = this.getThemeMode();
|
|
2967
6191
|
this._applyTheme(currentMode, rootElement);
|
|
2968
|
-
(0, import_preact18.render)((0,
|
|
6192
|
+
(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
6193
|
}
|
|
2970
6194
|
/**
|
|
2971
6195
|
* Returns the current theme mode.
|
|
@@ -2988,16 +6212,16 @@ var ThemeWidget = class extends import_core21.Widget {
|
|
|
2988
6212
|
/** Apply theme styling without changing internal state */
|
|
2989
6213
|
_applyTheme(themeMode, rootElement) {
|
|
2990
6214
|
const themeStyle = themeMode === "dark" ? this.props.darkModeTheme : this.props.lightModeTheme;
|
|
2991
|
-
if ((
|
|
6215
|
+
if (deepEqual(themeStyle, this.appliedTheme, 1)) {
|
|
2992
6216
|
return;
|
|
2993
6217
|
}
|
|
2994
6218
|
const container = rootElement.closest(".deck-widget-container");
|
|
2995
6219
|
if (!container)
|
|
2996
6220
|
return;
|
|
2997
|
-
(
|
|
6221
|
+
applyStyles(container, themeStyle);
|
|
2998
6222
|
this.appliedTheme = themeStyle;
|
|
2999
6223
|
const label = themeMode === "dark" ? this.props.darkModeLabel : this.props.lightModeLabel;
|
|
3000
|
-
|
|
6224
|
+
log_default.log(1, `Switched theme to ${label}`, themeStyle)();
|
|
3001
6225
|
}
|
|
3002
6226
|
/** Read browser preference */
|
|
3003
6227
|
_getInitialThemeMode() {
|
|
@@ -3012,13 +6236,15 @@ var ThemeWidget = class extends import_core21.Widget {
|
|
|
3012
6236
|
}
|
|
3013
6237
|
};
|
|
3014
6238
|
ThemeWidget.defaultProps = {
|
|
3015
|
-
...
|
|
6239
|
+
...Widget.defaultProps,
|
|
3016
6240
|
id: "theme",
|
|
3017
6241
|
placement: "top-left",
|
|
3018
6242
|
viewId: null,
|
|
3019
6243
|
lightModeLabel: "Light Mode",
|
|
6244
|
+
lightModeTooltip: void 0,
|
|
3020
6245
|
lightModeTheme: LightGlassTheme,
|
|
3021
6246
|
darkModeLabel: "Dark Mode",
|
|
6247
|
+
darkModeTooltip: void 0,
|
|
3022
6248
|
darkModeTheme: DarkGlassTheme,
|
|
3023
6249
|
initialThemeMode: "auto",
|
|
3024
6250
|
themeMode: void 0,
|
|
@@ -3027,10 +6253,9 @@ ThemeWidget.defaultProps = {
|
|
|
3027
6253
|
};
|
|
3028
6254
|
|
|
3029
6255
|
// dist/loading-widget.js
|
|
3030
|
-
var
|
|
6256
|
+
var import_jsx_runtime26 = require("preact/jsx-runtime");
|
|
3031
6257
|
var import_preact19 = require("preact");
|
|
3032
|
-
var
|
|
3033
|
-
var LoadingWidget = class extends import_core22.Widget {
|
|
6258
|
+
var LoadingWidget = class extends Widget {
|
|
3034
6259
|
constructor(props = {}) {
|
|
3035
6260
|
super(props);
|
|
3036
6261
|
this.className = "deck-widget-loading";
|
|
@@ -3046,7 +6271,7 @@ var LoadingWidget = class extends import_core22.Widget {
|
|
|
3046
6271
|
onRenderHTML(rootElement) {
|
|
3047
6272
|
(0, import_preact19.render)(
|
|
3048
6273
|
// 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,
|
|
6274
|
+
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
6275
|
rootElement
|
|
3051
6276
|
);
|
|
3052
6277
|
}
|
|
@@ -3064,21 +6289,21 @@ var LoadingWidget = class extends import_core22.Widget {
|
|
|
3064
6289
|
}
|
|
3065
6290
|
};
|
|
3066
6291
|
LoadingWidget.defaultProps = {
|
|
3067
|
-
...
|
|
6292
|
+
...Widget.defaultProps,
|
|
3068
6293
|
id: "loading",
|
|
3069
6294
|
placement: "top-left",
|
|
3070
6295
|
viewId: null,
|
|
3071
6296
|
label: "Loading layer data",
|
|
6297
|
+
tooltip: void 0,
|
|
3072
6298
|
onLoadingChange: () => {
|
|
3073
6299
|
}
|
|
3074
6300
|
};
|
|
3075
6301
|
|
|
3076
6302
|
// dist/stats-widget.js
|
|
3077
|
-
var
|
|
3078
|
-
var
|
|
3079
|
-
var import_core24 = require("@luma.gl/core");
|
|
6303
|
+
var import_jsx_runtime27 = require("preact/jsx-runtime");
|
|
6304
|
+
var import_core33 = require("@luma.gl/core");
|
|
3080
6305
|
var import_preact20 = require("preact");
|
|
3081
|
-
var
|
|
6306
|
+
var import_hooks8 = require("preact/hooks");
|
|
3082
6307
|
var DEFAULT_COUNT_FORMATTER = (stat) => `${stat.name}: ${stat.count}`;
|
|
3083
6308
|
function formatTime(time) {
|
|
3084
6309
|
return time < 1e3 ? `${time.toFixed(2)}ms` : `${(time / 1e3).toFixed(2)}s`;
|
|
@@ -3094,7 +6319,7 @@ var DEFAULT_FORMATTERS = {
|
|
|
3094
6319
|
fps: (stat) => `${stat.name}: ${Math.round(stat.getHz())}fps`,
|
|
3095
6320
|
memory: (stat) => `${stat.name}: ${formatMemory(stat.count)}`
|
|
3096
6321
|
};
|
|
3097
|
-
var StatsWidget = class extends
|
|
6322
|
+
var StatsWidget = class extends Widget {
|
|
3098
6323
|
/**
|
|
3099
6324
|
* Returns the current expanded state.
|
|
3100
6325
|
* In controlled mode, returns the expanded prop.
|
|
@@ -3149,7 +6374,7 @@ var StatsWidget = class extends import_core23.Widget {
|
|
|
3149
6374
|
onRenderHTML(rootElement) {
|
|
3150
6375
|
const isExpanded = this.getExpanded();
|
|
3151
6376
|
if (!isExpanded) {
|
|
3152
|
-
(0, import_preact20.render)((0,
|
|
6377
|
+
(0, import_preact20.render)((0, import_jsx_runtime27.jsx)(FpsIcon, { getFps: this._getFps, onClick: this._toggleExpanded }), rootElement);
|
|
3153
6378
|
return;
|
|
3154
6379
|
}
|
|
3155
6380
|
const stats = this._getStats();
|
|
@@ -3163,11 +6388,11 @@ var StatsWidget = class extends import_core23.Widget {
|
|
|
3163
6388
|
stat.reset();
|
|
3164
6389
|
}
|
|
3165
6390
|
lines.forEach((line, i) => {
|
|
3166
|
-
items.push((0,
|
|
6391
|
+
items.push((0, import_jsx_runtime27.jsx)("div", { style: { whiteSpace: "pre" }, children: line }, `${stat.name}-${i}`));
|
|
3167
6392
|
});
|
|
3168
6393
|
});
|
|
3169
6394
|
}
|
|
3170
|
-
(0, import_preact20.render)((0,
|
|
6395
|
+
(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
6396
|
}
|
|
3172
6397
|
onRedraw() {
|
|
3173
6398
|
if (this.getExpanded()) {
|
|
@@ -3184,7 +6409,7 @@ var StatsWidget = class extends import_core23.Widget {
|
|
|
3184
6409
|
const metrics = ((_a = this.deck) == null ? void 0 : _a.metrics) ?? {};
|
|
3185
6410
|
return Object.entries(metrics);
|
|
3186
6411
|
case "luma":
|
|
3187
|
-
return Array.from(
|
|
6412
|
+
return Array.from(import_core33.luma.stats.stats.values())[0];
|
|
3188
6413
|
case "device":
|
|
3189
6414
|
const device = (_b = this.deck) == null ? void 0 : _b.device;
|
|
3190
6415
|
const stats = device == null ? void 0 : device.statsManager.stats.values();
|
|
@@ -3221,7 +6446,7 @@ var StatsWidget = class extends import_core23.Widget {
|
|
|
3221
6446
|
}
|
|
3222
6447
|
};
|
|
3223
6448
|
StatsWidget.defaultProps = {
|
|
3224
|
-
...
|
|
6449
|
+
...Widget.defaultProps,
|
|
3225
6450
|
type: "deck",
|
|
3226
6451
|
placement: "top-left",
|
|
3227
6452
|
viewId: null,
|
|
@@ -3237,8 +6462,8 @@ StatsWidget.defaultProps = {
|
|
|
3237
6462
|
}
|
|
3238
6463
|
};
|
|
3239
6464
|
function FpsIcon({ getFps, onClick }) {
|
|
3240
|
-
const [fps, setFps] = (0,
|
|
3241
|
-
(0,
|
|
6465
|
+
const [fps, setFps] = (0, import_hooks8.useState)(getFps());
|
|
6466
|
+
(0, import_hooks8.useEffect)(() => {
|
|
3242
6467
|
const onUpdate = () => {
|
|
3243
6468
|
setFps(getFps());
|
|
3244
6469
|
timer = requestAnimationFrame(onUpdate);
|
|
@@ -3248,6 +6473,6 @@ function FpsIcon({ getFps, onClick }) {
|
|
|
3248
6473
|
cancelAnimationFrame(timer);
|
|
3249
6474
|
};
|
|
3250
6475
|
}, [getFps]);
|
|
3251
|
-
return (0,
|
|
6476
|
+
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
6477
|
}
|
|
3253
6478
|
//# sourceMappingURL=index.cjs.map
|