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