@sketch-hq/sketch-web-renderer 14.12.2 → 14.13.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/out/web-renderer/WasmModule-b06ee9c9.js +921 -0
- package/out/web-renderer/export-worker.js +11670 -0
- package/out/web-renderer/index.js +1 -1
- package/out/web-renderer/ts/canvas-renderer/CanvasRenderer.d.ts +2 -0
- package/out/web-renderer/ts/canvas-renderer/CanvasRenderer.d.ts.map +1 -1
- package/out/web-renderer/ts/canvas-renderer/CanvasSettings.d.ts +2 -0
- package/out/web-renderer/ts/canvas-renderer/CanvasSettings.d.ts.map +1 -1
- package/out/web-renderer/ts/canvas-renderer/react/CanvasRendererProvider.d.ts.map +1 -1
- package/out/web-renderer/ts/canvas-renderer/react/hooks/actions.d.ts +7 -0
- package/out/web-renderer/ts/canvas-renderer/react/hooks/actions.d.ts.map +1 -1
- package/out/web-renderer/ts/export-worker/ExportWorker.d.ts +2 -0
- package/out/web-renderer/ts/export-worker/ExportWorker.d.ts.map +1 -0
- package/out/web-renderer/ts/export-worker/ExportWorkerClient.d.ts +31 -0
- package/out/web-renderer/ts/export-worker/ExportWorkerClient.d.ts.map +1 -0
- package/out/web-renderer/ts/export-worker/ExportWorkerMessageData.d.ts +42 -0
- package/out/web-renderer/ts/export-worker/ExportWorkerMessageData.d.ts.map +1 -0
- package/out/web-renderer/ts/export-worker/worker-shims.d.ts +1 -0
- package/out/web-renderer/ts/export-worker/worker-shims.d.ts.map +1 -0
- package/out/web-renderer/ts/types/Events.d.ts +1 -0
- package/out/web-renderer/ts/types/Events.d.ts.map +1 -1
- package/out/web-renderer/wasm/Debug/web-renderer-debug.wasm +0 -0
- package/out/web-renderer/wasm/Debug/web-renderer.d.ts +1 -1
- package/out/web-renderer/wasm/Release/web-renderer-release.mjs +6 -6
- package/out/web-renderer/wasm/Release/web-renderer-release.wasm +0 -0
- package/out/web-renderer/web-renderer-release-988811bf.js +4309 -0
- package/out/web-renderer/web-renderer-release-bac26995.js +1 -0
- package/package.json +2 -2
|
@@ -0,0 +1,921 @@
|
|
|
1
|
+
import 'react';
|
|
2
|
+
|
|
3
|
+
/******************************************************************************
|
|
4
|
+
Copyright (c) Microsoft Corporation.
|
|
5
|
+
|
|
6
|
+
Permission to use, copy, modify, and/or distribute this software for any
|
|
7
|
+
purpose with or without fee is hereby granted.
|
|
8
|
+
|
|
9
|
+
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
|
|
10
|
+
REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
|
|
11
|
+
AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
|
|
12
|
+
INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
|
|
13
|
+
LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
|
|
14
|
+
OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
|
15
|
+
PERFORMANCE OF THIS SOFTWARE.
|
|
16
|
+
***************************************************************************** */
|
|
17
|
+
/* global Reflect, Promise */
|
|
18
|
+
|
|
19
|
+
var extendStatics = function(d, b) {
|
|
20
|
+
extendStatics = Object.setPrototypeOf ||
|
|
21
|
+
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
|
|
22
|
+
function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; };
|
|
23
|
+
return extendStatics(d, b);
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
function __extends(d, b) {
|
|
27
|
+
if (typeof b !== "function" && b !== null)
|
|
28
|
+
throw new TypeError("Class extends value " + String(b) + " is not a constructor or null");
|
|
29
|
+
extendStatics(d, b);
|
|
30
|
+
function __() { this.constructor = d; }
|
|
31
|
+
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
var __assign = function() {
|
|
35
|
+
__assign = Object.assign || function __assign(t) {
|
|
36
|
+
for (var s, i = 1, n = arguments.length; i < n; i++) {
|
|
37
|
+
s = arguments[i];
|
|
38
|
+
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p];
|
|
39
|
+
}
|
|
40
|
+
return t;
|
|
41
|
+
};
|
|
42
|
+
return __assign.apply(this, arguments);
|
|
43
|
+
};
|
|
44
|
+
|
|
45
|
+
function __awaiter(thisArg, _arguments, P, generator) {
|
|
46
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
47
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
48
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
49
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
50
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
51
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
52
|
+
});
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
function __generator(thisArg, body) {
|
|
56
|
+
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
|
|
57
|
+
return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
|
|
58
|
+
function verb(n) { return function (v) { return step([n, v]); }; }
|
|
59
|
+
function step(op) {
|
|
60
|
+
if (f) throw new TypeError("Generator is already executing.");
|
|
61
|
+
while (g && (g = 0, op[0] && (_ = 0)), _) try {
|
|
62
|
+
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
|
|
63
|
+
if (y = 0, t) op = [op[0] & 2, t.value];
|
|
64
|
+
switch (op[0]) {
|
|
65
|
+
case 0: case 1: t = op; break;
|
|
66
|
+
case 4: _.label++; return { value: op[1], done: false };
|
|
67
|
+
case 5: _.label++; y = op[1]; op = [0]; continue;
|
|
68
|
+
case 7: op = _.ops.pop(); _.trys.pop(); continue;
|
|
69
|
+
default:
|
|
70
|
+
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
|
|
71
|
+
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
|
|
72
|
+
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
|
|
73
|
+
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
|
|
74
|
+
if (t[2]) _.ops.pop();
|
|
75
|
+
_.trys.pop(); continue;
|
|
76
|
+
}
|
|
77
|
+
op = body.call(thisArg, _);
|
|
78
|
+
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
|
|
79
|
+
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
function __spreadArray(to, from, pack) {
|
|
84
|
+
if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) {
|
|
85
|
+
if (ar || !(i in from)) {
|
|
86
|
+
if (!ar) ar = Array.prototype.slice.call(from, 0, i);
|
|
87
|
+
ar[i] = from[i];
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
return to.concat(ar || Array.prototype.slice.call(from));
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
var WebRendererError = /** @class */ (function (_super) {
|
|
94
|
+
__extends(WebRendererError, _super);
|
|
95
|
+
function WebRendererError(code, message, cause) {
|
|
96
|
+
var _newTarget = this.constructor;
|
|
97
|
+
var _this = _super.call(this, "(".concat(code, ") ").concat(message)) || this;
|
|
98
|
+
_this.code = code;
|
|
99
|
+
_this.cause = cause;
|
|
100
|
+
_this.name = WebRendererError.name;
|
|
101
|
+
Object.setPrototypeOf(_this, _newTarget.prototype);
|
|
102
|
+
return _this;
|
|
103
|
+
}
|
|
104
|
+
return WebRendererError;
|
|
105
|
+
}(Error));
|
|
106
|
+
|
|
107
|
+
var WebRendererMode;
|
|
108
|
+
(function (WebRendererMode) {
|
|
109
|
+
WebRendererMode["debug"] = "debug";
|
|
110
|
+
WebRendererMode["release"] = "release";
|
|
111
|
+
})(WebRendererMode || (WebRendererMode = {}));
|
|
112
|
+
|
|
113
|
+
var PrototypeResizeMode;
|
|
114
|
+
(function (PrototypeResizeMode) {
|
|
115
|
+
PrototypeResizeMode["Fit"] = "Fit";
|
|
116
|
+
PrototypeResizeMode["FillWidth"] = "FillWidth";
|
|
117
|
+
PrototypeResizeMode["ActualSize"] = "ActualSize";
|
|
118
|
+
})(PrototypeResizeMode || (PrototypeResizeMode = {}));
|
|
119
|
+
|
|
120
|
+
/**
|
|
121
|
+
* Very simple event emitter that can be extended from any class
|
|
122
|
+
*/
|
|
123
|
+
var EventEmitter = /** @class */ (function () {
|
|
124
|
+
function EventEmitter() {
|
|
125
|
+
this.listeners = {};
|
|
126
|
+
}
|
|
127
|
+
EventEmitter.prototype.on = function (event, callback) {
|
|
128
|
+
var _a, _b;
|
|
129
|
+
this.listeners[event] = (_a = this.listeners[event]) !== null && _a !== void 0 ? _a : new Set();
|
|
130
|
+
(_b = this.listeners[event]) === null || _b === void 0 ? void 0 : _b.add(callback);
|
|
131
|
+
};
|
|
132
|
+
EventEmitter.prototype.off = function (event, callback) {
|
|
133
|
+
var _a;
|
|
134
|
+
(_a = this.listeners[event]) === null || _a === void 0 ? void 0 : _a.delete(callback);
|
|
135
|
+
};
|
|
136
|
+
/**
|
|
137
|
+
* Forward a specific event to the given target
|
|
138
|
+
*/
|
|
139
|
+
EventEmitter.prototype.forwardEvent = function (target, event) {
|
|
140
|
+
var callback = function () {
|
|
141
|
+
var args = [];
|
|
142
|
+
for (var _i = 0; _i < arguments.length; _i++) {
|
|
143
|
+
args[_i] = arguments[_i];
|
|
144
|
+
}
|
|
145
|
+
target.emit.apply(target, __spreadArray([event], args, false));
|
|
146
|
+
};
|
|
147
|
+
this.on(event, callback);
|
|
148
|
+
};
|
|
149
|
+
EventEmitter.prototype.emit = function (event) {
|
|
150
|
+
var args = [];
|
|
151
|
+
for (var _i = 1; _i < arguments.length; _i++) {
|
|
152
|
+
args[_i - 1] = arguments[_i];
|
|
153
|
+
}
|
|
154
|
+
var listeners = this.listeners[event];
|
|
155
|
+
if (listeners === null || listeners === void 0 ? void 0 : listeners.size) {
|
|
156
|
+
listeners.forEach(function (listener) {
|
|
157
|
+
// Invoke listeners on next tick. This helps avoid tricky situations
|
|
158
|
+
// where handlers potentially syncronously dispose the renderer or
|
|
159
|
+
// trigger other large internal state changes in the same call stack as
|
|
160
|
+
// emit(...) is invoked.
|
|
161
|
+
Promise.resolve().then(function () {
|
|
162
|
+
listener.apply(void 0, args);
|
|
163
|
+
});
|
|
164
|
+
});
|
|
165
|
+
}
|
|
166
|
+
};
|
|
167
|
+
EventEmitter.prototype.detachAllListeners = function () {
|
|
168
|
+
this.listeners = {};
|
|
169
|
+
};
|
|
170
|
+
return EventEmitter;
|
|
171
|
+
}());
|
|
172
|
+
|
|
173
|
+
/**
|
|
174
|
+
* ListenersCollector
|
|
175
|
+
* It's a wrapper around addEventListener, which collects
|
|
176
|
+
* all the callbacks, and provides a way to remove all of them
|
|
177
|
+
*/
|
|
178
|
+
var ListenersCollector = /** @class */ (function () {
|
|
179
|
+
function ListenersCollector(disabled) {
|
|
180
|
+
if (disabled === void 0) { disabled = false; }
|
|
181
|
+
this.removeListenerCallbacks = [];
|
|
182
|
+
this.disabled = disabled;
|
|
183
|
+
}
|
|
184
|
+
ListenersCollector.prototype.add = function (scope, event, callback, options) {
|
|
185
|
+
var _this = this;
|
|
186
|
+
var safeguardedCallback = function () {
|
|
187
|
+
var args = [];
|
|
188
|
+
for (var _i = 0; _i < arguments.length; _i++) {
|
|
189
|
+
args[_i] = arguments[_i];
|
|
190
|
+
}
|
|
191
|
+
if (_this.disabled) {
|
|
192
|
+
return;
|
|
193
|
+
}
|
|
194
|
+
callback.apply(void 0, args);
|
|
195
|
+
};
|
|
196
|
+
scope.addEventListener(event, safeguardedCallback, options);
|
|
197
|
+
var remove = function () {
|
|
198
|
+
scope.removeEventListener(event, safeguardedCallback, options);
|
|
199
|
+
};
|
|
200
|
+
this.removeListenerCallbacks.push(remove);
|
|
201
|
+
// Returns the function to remove the event
|
|
202
|
+
return remove;
|
|
203
|
+
};
|
|
204
|
+
ListenersCollector.prototype.dispose = function () {
|
|
205
|
+
this.removeListenerCallbacks.forEach(function (remove) { return remove(); });
|
|
206
|
+
};
|
|
207
|
+
ListenersCollector.prototype.setDisabled = function (disabled) {
|
|
208
|
+
this.disabled = disabled;
|
|
209
|
+
};
|
|
210
|
+
return ListenersCollector;
|
|
211
|
+
}());
|
|
212
|
+
|
|
213
|
+
/**
|
|
214
|
+
* Initial dummy structure for feature flags
|
|
215
|
+
*/
|
|
216
|
+
var DefaultFeatureFlags = {
|
|
217
|
+
delayedDraw: true,
|
|
218
|
+
offscreenCanvas: false,
|
|
219
|
+
useDirtyRectsRendering: true,
|
|
220
|
+
safariWebGL2: false,
|
|
221
|
+
// When this is true, the canvas won't allow to pan/zoom outside the page boundaries
|
|
222
|
+
pageBoundariesLimit: false,
|
|
223
|
+
// When this is true, the canvas will send user events through the rendering scene.
|
|
224
|
+
// This is useful to check which layer was clicked/hovered, etc.
|
|
225
|
+
canvasLayersEvents: false,
|
|
226
|
+
};
|
|
227
|
+
|
|
228
|
+
// Taken from https://gist.github.com/Craga89/2829457
|
|
229
|
+
var getiOSVersion = function (userAgent) {
|
|
230
|
+
return parseFloat(('' +
|
|
231
|
+
(/CPU.*OS ([0-9_]{1,5})|(CPU like).*AppleWebKit.*Mobile/i.exec(userAgent) || [0, ''])[1])
|
|
232
|
+
.replace('undefined', '3_2')
|
|
233
|
+
.replace('_', '.')
|
|
234
|
+
.replace('_', '')) || false;
|
|
235
|
+
};
|
|
236
|
+
var SAFARI_USER_AGENT_REGEX = /(iPhone|Macintosh|iPad)(.*)(Version)\/(0|[1-9]\d*)\.(0|[1-9]\d*)\.?(0|[1-9]\d*)?/;
|
|
237
|
+
/**
|
|
238
|
+
* Parses a Safari user agent string into structured data. If the user agent string
|
|
239
|
+
* isn't for a Safari browser, null is returned.
|
|
240
|
+
*
|
|
241
|
+
* User Agent parsing is generally discouraged and can never be 100% reliable. So favour
|
|
242
|
+
* feature detection when possible, and do not use this method for critical functionality.
|
|
243
|
+
*/
|
|
244
|
+
var parseSafariUserAgent = function (userAgent) {
|
|
245
|
+
if (userAgent === void 0) { userAgent = window.navigator.userAgent; }
|
|
246
|
+
if (userAgent.includes('Chrome/') ||
|
|
247
|
+
userAgent.includes('Chromium/') ||
|
|
248
|
+
userAgent.includes('Opera/') ||
|
|
249
|
+
userAgent.includes('Firefox/'))
|
|
250
|
+
return null;
|
|
251
|
+
var match = userAgent.match(SAFARI_USER_AGENT_REGEX);
|
|
252
|
+
if (!match)
|
|
253
|
+
return null;
|
|
254
|
+
var hardware = match[1];
|
|
255
|
+
if (hardware !== 'Macintosh' && hardware !== 'iPad' && hardware !== 'iPhone')
|
|
256
|
+
return null;
|
|
257
|
+
return {
|
|
258
|
+
hardware: hardware,
|
|
259
|
+
version: {
|
|
260
|
+
major: parseInt(match[4]) || 0,
|
|
261
|
+
minor: parseInt(match[5]) || 0,
|
|
262
|
+
patch: parseInt(match[6]) || 0,
|
|
263
|
+
},
|
|
264
|
+
};
|
|
265
|
+
};
|
|
266
|
+
|
|
267
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
268
|
+
function debounce(callback, delayMs) {
|
|
269
|
+
var timeoutId;
|
|
270
|
+
function debouncedCallback() {
|
|
271
|
+
var args = [];
|
|
272
|
+
for (var _i = 0; _i < arguments.length; _i++) {
|
|
273
|
+
args[_i] = arguments[_i];
|
|
274
|
+
}
|
|
275
|
+
clearTimeout(timeoutId);
|
|
276
|
+
timeoutId = setTimeout(function () {
|
|
277
|
+
callback.apply(void 0, args);
|
|
278
|
+
}, delayMs);
|
|
279
|
+
}
|
|
280
|
+
/**
|
|
281
|
+
* Cancel the potentially scheduled execution.
|
|
282
|
+
* Call this function to clean things up properly.
|
|
283
|
+
*/
|
|
284
|
+
debouncedCallback.cancel = function () {
|
|
285
|
+
if (timeoutId) {
|
|
286
|
+
clearTimeout(timeoutId);
|
|
287
|
+
}
|
|
288
|
+
};
|
|
289
|
+
return debouncedCallback;
|
|
290
|
+
}
|
|
291
|
+
/**
|
|
292
|
+
* Extract the correct mouse position
|
|
293
|
+
* @param e: The type can be MouseEvent or TouchEvent or GestureEvent, but we are using any because for some reason the pageX/Y is not included inside the TouchEvent type definition.
|
|
294
|
+
*/
|
|
295
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
296
|
+
function extractPointer(e) {
|
|
297
|
+
var _a, _b, _c, _d, _e;
|
|
298
|
+
// If the touches array is empty, but the changedTouches is not, it means that all the fingers were lifted from the screen,
|
|
299
|
+
// and the changed touches contains the position of the last finger that was lifted.
|
|
300
|
+
// The changed touches might contain more fingers, in case multiple fingers were lifted at the same time,
|
|
301
|
+
// in that case we would need to find the mid point, but we don't really need to handle that, because no user interaction depends on that
|
|
302
|
+
var touch = (_b = (_a = e.touches) === null || _a === void 0 ? void 0 : _a[0]) !== null && _b !== void 0 ? _b : (_c = e.changedTouches) === null || _c === void 0 ? void 0 : _c[0];
|
|
303
|
+
return {
|
|
304
|
+
x: (_d = touch === null || touch === void 0 ? void 0 : touch.clientX) !== null && _d !== void 0 ? _d : e.clientX,
|
|
305
|
+
y: (_e = touch === null || touch === void 0 ? void 0 : touch.clientY) !== null && _e !== void 0 ? _e : e.clientY,
|
|
306
|
+
};
|
|
307
|
+
}
|
|
308
|
+
function clamp(value, min, max) {
|
|
309
|
+
return Math.max(min, Math.min(max, value));
|
|
310
|
+
}
|
|
311
|
+
function getSupportedWebGLVersion(deviceInfo) {
|
|
312
|
+
// We are forcing WebGL 1 on AMD Radeon Pro 5xxx series
|
|
313
|
+
// On macs with this GPU, Chrome scrambles the vertices of the triangles sent to the gpu
|
|
314
|
+
// causing incorrect renderings. See https://bugs.chromium.org/p/chromium/issues/detail?id=1301748&q=webgl&can=2
|
|
315
|
+
// GH ticket: https://github.com/sketch-hq/Cloud/issues/17439
|
|
316
|
+
var amdRadeonRegex = /amd\sradeon\s(pro|rx)\s5\d\d\d/gi;
|
|
317
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
318
|
+
var isChrome = Boolean(window.chrome);
|
|
319
|
+
if (isChrome && deviceInfo.gpu && amdRadeonRegex.test(deviceInfo.gpu)) {
|
|
320
|
+
return 1;
|
|
321
|
+
}
|
|
322
|
+
// Safari 15 has support for WebGL 2, but their implementation
|
|
323
|
+
// is still slow and filled with bugs, so we are forcing WebGL 1
|
|
324
|
+
// until we see that WebGL 2 starts working correctly on Safari
|
|
325
|
+
if (parseSafariUserAgent() && !DefaultFeatureFlags.safariWebGL2)
|
|
326
|
+
return 1;
|
|
327
|
+
if (typeof WebGL2RenderingContext !== 'undefined')
|
|
328
|
+
return 2;
|
|
329
|
+
return 1;
|
|
330
|
+
}
|
|
331
|
+
function convertEmbindVectorToArray(vector) {
|
|
332
|
+
if (!vector)
|
|
333
|
+
return [];
|
|
334
|
+
var result = [];
|
|
335
|
+
for (var i = 0; i < vector.size(); i++) {
|
|
336
|
+
result.push(vector.get(i));
|
|
337
|
+
}
|
|
338
|
+
return result;
|
|
339
|
+
}
|
|
340
|
+
/**
|
|
341
|
+
* Keep in mind that this check is not entirely accurate on Windows machines.
|
|
342
|
+
* On Safari for MacOS, it's fairly accurate. That's where we use it.
|
|
343
|
+
* @see: https://stackoverflow.com/questions/4817029/whats-the-best-way-to-detect-a-touch-screen-device-using-javascript
|
|
344
|
+
*/
|
|
345
|
+
function isTouchDevice() {
|
|
346
|
+
return ('ontouchstart' in window ||
|
|
347
|
+
navigator.maxTouchPoints > 0 ||
|
|
348
|
+
navigator.msMaxTouchPoints > 0);
|
|
349
|
+
}
|
|
350
|
+
/**
|
|
351
|
+
* Remove all the keys that have an undefined value.
|
|
352
|
+
* The function doesn't edit the given object directly, but it creates and returns a copy
|
|
353
|
+
*/
|
|
354
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
355
|
+
function removeUndefinedKeys(targetObject) {
|
|
356
|
+
var copiedObject = __assign({}, targetObject);
|
|
357
|
+
Object.keys(copiedObject).forEach(function (key) {
|
|
358
|
+
if (typeof copiedObject[key] !== 'undefined')
|
|
359
|
+
return;
|
|
360
|
+
delete copiedObject[key];
|
|
361
|
+
});
|
|
362
|
+
return copiedObject;
|
|
363
|
+
}
|
|
364
|
+
/**
|
|
365
|
+
* Prevent to bind both onClick and touchEnd events by only binding the required event based on the device.
|
|
366
|
+
* The function is designed to be used with React.
|
|
367
|
+
*
|
|
368
|
+
* How to use:
|
|
369
|
+
*
|
|
370
|
+
* <div {...touchableClick(myCallback) />
|
|
371
|
+
*/
|
|
372
|
+
function touchableClick(callback) {
|
|
373
|
+
return isTouchDevice() ? { onTouchEnd: callback } : { onClick: callback };
|
|
374
|
+
}
|
|
375
|
+
var safePtrAccess = function (embindPtr) {
|
|
376
|
+
/**
|
|
377
|
+
* We are preventing JS to throw an error when accessing
|
|
378
|
+
* the internal methods of a pointer when it is deleted.
|
|
379
|
+
*
|
|
380
|
+
* Given "$$.count.value" are internal properties of emscripten
|
|
381
|
+
* we re-type prFile as any
|
|
382
|
+
*/
|
|
383
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
384
|
+
if ((embindPtr === null || embindPtr === void 0 ? void 0 : embindPtr.$$.count.value) === 0) {
|
|
385
|
+
return null;
|
|
386
|
+
}
|
|
387
|
+
return embindPtr;
|
|
388
|
+
};
|
|
389
|
+
|
|
390
|
+
var GestureManager = /** @class */ (function (_super) {
|
|
391
|
+
__extends(GestureManager, _super);
|
|
392
|
+
function GestureManager(target, invertedWheelZoom, disabled) {
|
|
393
|
+
if (invertedWheelZoom === void 0) { invertedWheelZoom = false; }
|
|
394
|
+
if (disabled === void 0) { disabled = false; }
|
|
395
|
+
var _this = _super.call(this) || this;
|
|
396
|
+
_this.state = {
|
|
397
|
+
// The distance between the 2 fingers used to pinch to zoom
|
|
398
|
+
pinchToZoomLastDistance: 0,
|
|
399
|
+
lastGestureScale: 1,
|
|
400
|
+
isCtrlPressed: false,
|
|
401
|
+
};
|
|
402
|
+
_this.handleGestureStart = function (e) {
|
|
403
|
+
e.preventDefault();
|
|
404
|
+
_this.state.lastGestureScale = e.scale;
|
|
405
|
+
};
|
|
406
|
+
_this.handleGestureChange = function (e) {
|
|
407
|
+
e.preventDefault();
|
|
408
|
+
var delta = e.scale / _this.state.lastGestureScale;
|
|
409
|
+
_this.state.lastGestureScale = e.scale;
|
|
410
|
+
var center = _this.getCorrectPointerPosition(e);
|
|
411
|
+
_this.emitZoomEvent(delta, center);
|
|
412
|
+
};
|
|
413
|
+
_this.handleGestureEnd = function (e) {
|
|
414
|
+
e.preventDefault();
|
|
415
|
+
};
|
|
416
|
+
/**
|
|
417
|
+
* Update the mouse position and emit the mousemove event
|
|
418
|
+
*/
|
|
419
|
+
_this.updateMousePosition = function (e) {
|
|
420
|
+
_this.emit('pointermove', {
|
|
421
|
+
type: 'mouse',
|
|
422
|
+
position: _this.getCorrectPointerPosition(e),
|
|
423
|
+
button: e.button,
|
|
424
|
+
touchesCount: 0,
|
|
425
|
+
});
|
|
426
|
+
};
|
|
427
|
+
_this.updateGlobalMousePosition = function (e) {
|
|
428
|
+
_this.emit('globalpointermove', {
|
|
429
|
+
type: 'mouse',
|
|
430
|
+
position: _this.getCorrectPointerPosition(e),
|
|
431
|
+
button: e.button,
|
|
432
|
+
touchesCount: 0,
|
|
433
|
+
});
|
|
434
|
+
};
|
|
435
|
+
_this.handleTouchStart = function (e) {
|
|
436
|
+
e.preventDefault();
|
|
437
|
+
_this.handleTouchPinchToZoomStart(e);
|
|
438
|
+
_this.emit('pointerdown', {
|
|
439
|
+
type: 'touch',
|
|
440
|
+
position: _this.getCorrectPointerPosition(e),
|
|
441
|
+
button: 0,
|
|
442
|
+
touchesCount: e.touches.length,
|
|
443
|
+
});
|
|
444
|
+
};
|
|
445
|
+
_this.handleMouseDown = function (e) {
|
|
446
|
+
// Preventing dragging while keeping the CTRL key pressed.
|
|
447
|
+
// When holding the CTRL key the user is expected to zoom, so it might cause conflicts with the pan.
|
|
448
|
+
// But also, on macOS left-clicking while holding the CTRL key opens the context menu,
|
|
449
|
+
// and when the context menu is open, no mouseup event is triggered after releasing the left click.
|
|
450
|
+
// We would also need to track the context menu event and treat it as a mouseup, bringing more complexity,
|
|
451
|
+
// for our own sanity, let's just prevent dragging when this key is pressed
|
|
452
|
+
if (e.ctrlKey)
|
|
453
|
+
return;
|
|
454
|
+
e.preventDefault();
|
|
455
|
+
_this.emit('pointerdown', {
|
|
456
|
+
type: 'mouse',
|
|
457
|
+
position: _this.getCorrectPointerPosition(e),
|
|
458
|
+
button: e.button,
|
|
459
|
+
touchesCount: 0,
|
|
460
|
+
});
|
|
461
|
+
};
|
|
462
|
+
_this.handleTouchMove = function (e) {
|
|
463
|
+
_this.handleTouchPinchToZoomChange(e);
|
|
464
|
+
_this.emit('pointermove', {
|
|
465
|
+
type: 'touch',
|
|
466
|
+
position: _this.getCorrectPointerPosition(e),
|
|
467
|
+
button: 0,
|
|
468
|
+
touchesCount: e.touches.length,
|
|
469
|
+
});
|
|
470
|
+
};
|
|
471
|
+
_this.handleMouseMove = function (e) {
|
|
472
|
+
_this.updateMousePosition(e);
|
|
473
|
+
};
|
|
474
|
+
_this.handleGlobalTouchMove = function (e) {
|
|
475
|
+
_this.emit('globalpointermove', {
|
|
476
|
+
type: 'touch',
|
|
477
|
+
position: _this.getCorrectPointerPosition(e),
|
|
478
|
+
button: 0,
|
|
479
|
+
touchesCount: e.touches.length,
|
|
480
|
+
});
|
|
481
|
+
};
|
|
482
|
+
_this.handleGlobalMouseMove = function (e) {
|
|
483
|
+
_this.updateGlobalMousePosition(e);
|
|
484
|
+
};
|
|
485
|
+
_this.handleTouchPinchToZoomStart = function (e) {
|
|
486
|
+
var _a;
|
|
487
|
+
if (!e.touches || ((_a = e.touches) === null || _a === void 0 ? void 0 : _a.length) < 2)
|
|
488
|
+
return;
|
|
489
|
+
_this.state.pinchToZoomLastDistance = _this.calculateDistanceBetweenTouches(e.touches[0], e.touches[1]);
|
|
490
|
+
};
|
|
491
|
+
/**
|
|
492
|
+
* Handle the pinch to zoom scale calculation on touch devices, using the distance
|
|
493
|
+
* between the first 2 fingers on screen and the middle point between them as zoom center
|
|
494
|
+
*/
|
|
495
|
+
_this.handleTouchPinchToZoomChange = function (e) {
|
|
496
|
+
var _a;
|
|
497
|
+
if (!e.touches || ((_a = e.touches) === null || _a === void 0 ? void 0 : _a.length) < 2)
|
|
498
|
+
return;
|
|
499
|
+
var distance = _this.calculateDistanceBetweenTouches(e.touches[0], e.touches[1]);
|
|
500
|
+
var middlePoint = _this.getCorrectPointerPosition(e);
|
|
501
|
+
var distanceDelta = distance - _this.state.pinchToZoomLastDistance;
|
|
502
|
+
var normalisedDelta = 1 + distanceDelta * 0.004;
|
|
503
|
+
_this.state.pinchToZoomLastDistance = distance;
|
|
504
|
+
// The pinch to zoom is triggered by the touchstart/touchmove/touched events, and the start/end events are emitted by the touchstart/end.
|
|
505
|
+
_this.emitZoomEvent(normalisedDelta, middlePoint);
|
|
506
|
+
};
|
|
507
|
+
_this.handleTouchEnd = function (e) {
|
|
508
|
+
var position = _this.getCorrectPointerPosition(e);
|
|
509
|
+
_this.emit('pointerup', {
|
|
510
|
+
position: position,
|
|
511
|
+
type: 'touch',
|
|
512
|
+
button: 0,
|
|
513
|
+
touchesCount: e.touches.length,
|
|
514
|
+
});
|
|
515
|
+
};
|
|
516
|
+
_this.handleMouseUp = function (e) {
|
|
517
|
+
_this.emit('pointerup', {
|
|
518
|
+
type: 'mouse',
|
|
519
|
+
position: _this.getCorrectPointerPosition(e),
|
|
520
|
+
button: e.button,
|
|
521
|
+
touchesCount: 0,
|
|
522
|
+
});
|
|
523
|
+
};
|
|
524
|
+
_this.debouncedUpdateMousePosition = debounce(_this.updateMousePosition, 40);
|
|
525
|
+
_this.debouncedUpdateGlobalMousePosition = debounce(_this.updateGlobalMousePosition, 40);
|
|
526
|
+
_this.handleMouseWheel = function (e) {
|
|
527
|
+
// Preventing the mousewheel by default when in the canvas,
|
|
528
|
+
// so we don't get unwanted scrolls, bounces, etc
|
|
529
|
+
e.preventDefault();
|
|
530
|
+
// crtlKey is true when the user is using pinch to zoom
|
|
531
|
+
// not very intuitive, but that's how chrome and firefox work.
|
|
532
|
+
// BUT, the keydown event for the ctrlKey won't be triggered when
|
|
533
|
+
// pinching to zoom, so we can track the key pressed and understand
|
|
534
|
+
// if the user is really pressing the key or pinching to zoom
|
|
535
|
+
var isPinchToZoom = e.ctrlKey && !_this.state.isCtrlPressed;
|
|
536
|
+
var isZooming = e.metaKey || isPinchToZoom || _this.state.isCtrlPressed;
|
|
537
|
+
// The mouse wheel event can be triggered only by a mouse like device,
|
|
538
|
+
// so we update only the mouse position, we ignore the touch.
|
|
539
|
+
// The emitted event is debounced, so we don't keep emitting mouse events at a high rate while scrolling.
|
|
540
|
+
// But also, it's common UX in apps/browsers that while the user scrolls, events are not triggered
|
|
541
|
+
_this.debouncedUpdateMousePosition(e);
|
|
542
|
+
_this.debouncedUpdateGlobalMousePosition(e);
|
|
543
|
+
if (isZooming) {
|
|
544
|
+
// When the user is pinching to zoom, the deltaY is inverted
|
|
545
|
+
var invert = isPinchToZoom || _this.invertedWheelZoom ? -1 : 1;
|
|
546
|
+
var center = _this.getCorrectPointerPosition(e);
|
|
547
|
+
var zoomDelta = 1 + e.deltaY * 0.005 * invert;
|
|
548
|
+
_this.emitZoomEvent(zoomDelta, center);
|
|
549
|
+
}
|
|
550
|
+
else {
|
|
551
|
+
_this.emit('wheel',
|
|
552
|
+
/* delta */ {
|
|
553
|
+
x: -e.deltaX,
|
|
554
|
+
y: -e.deltaY,
|
|
555
|
+
},
|
|
556
|
+
/* pointerInfo */ {
|
|
557
|
+
type: 'mouse',
|
|
558
|
+
position: _this.getCorrectPointerPosition(e),
|
|
559
|
+
button: e.button,
|
|
560
|
+
touchesCount: 0,
|
|
561
|
+
});
|
|
562
|
+
}
|
|
563
|
+
};
|
|
564
|
+
_this.target = target;
|
|
565
|
+
_this.invertedWheelZoom = invertedWheelZoom;
|
|
566
|
+
_this.targetBounds = target.getBoundingClientRect();
|
|
567
|
+
_this.listenersCollector = new ListenersCollector(disabled);
|
|
568
|
+
_this.addListeners();
|
|
569
|
+
_this.targetResizeObserver = new ResizeObserver(_this.updateTargetBounds.bind(_this));
|
|
570
|
+
_this.targetResizeObserver.observe(_this.target);
|
|
571
|
+
return _this;
|
|
572
|
+
}
|
|
573
|
+
GestureManager.prototype.updateTargetBounds = function () {
|
|
574
|
+
this.targetBounds = this.target.getBoundingClientRect();
|
|
575
|
+
};
|
|
576
|
+
GestureManager.prototype.addListeners = function () {
|
|
577
|
+
this.addTouchEventListeners();
|
|
578
|
+
this.addMouseEventListeners();
|
|
579
|
+
this.addKeyboardEventListeners();
|
|
580
|
+
this.addSafariGesturesEventListeners();
|
|
581
|
+
};
|
|
582
|
+
GestureManager.prototype.addKeyboardEventListeners = function () {
|
|
583
|
+
var _this = this;
|
|
584
|
+
this.listenersCollector.add(document, 'keydown', function (e) {
|
|
585
|
+
// Tracking the CTRL key, so we can understand when it's really pressed or not.
|
|
586
|
+
// Chrome and firefox sets the Event.ctrlKey boolean to true when pinching to zoom, even if that's not true.
|
|
587
|
+
if (e.key === 'Control')
|
|
588
|
+
_this.state.isCtrlPressed = true;
|
|
589
|
+
});
|
|
590
|
+
this.listenersCollector.add(document, 'keyup', function (e) {
|
|
591
|
+
if (e.key === 'Control')
|
|
592
|
+
_this.state.isCtrlPressed = false;
|
|
593
|
+
});
|
|
594
|
+
this.listenersCollector.add(document, 'contextmenu', function (e) {
|
|
595
|
+
// On macOS, if the context menu was opened by using: CTRL + left click, the keyup event wouldn't be triggered
|
|
596
|
+
if (e.ctrlKey) {
|
|
597
|
+
_this.state.isCtrlPressed = false;
|
|
598
|
+
}
|
|
599
|
+
});
|
|
600
|
+
};
|
|
601
|
+
GestureManager.prototype.addMouseEventListeners = function () {
|
|
602
|
+
this.listenersCollector.add(this.target, 'mousedown', this.handleMouseDown);
|
|
603
|
+
this.listenersCollector.add(this.target, 'mousemove', this.handleMouseMove);
|
|
604
|
+
this.listenersCollector.add(document, 'mousemove', this.handleGlobalMouseMove);
|
|
605
|
+
// Attaching the mouseup listener to the document itself, so we never miss a mouseup event to invalidate a dragging session
|
|
606
|
+
this.listenersCollector.add(document, 'mouseup', this.handleMouseUp);
|
|
607
|
+
this.listenersCollector.add(this.target, 'wheel', this.handleMouseWheel);
|
|
608
|
+
};
|
|
609
|
+
GestureManager.prototype.addTouchEventListeners = function () {
|
|
610
|
+
this.listenersCollector.add(this.target, 'touchstart', this.handleTouchStart);
|
|
611
|
+
this.listenersCollector.add(document, 'touchmove', this.handleGlobalTouchMove, {
|
|
612
|
+
passive: true,
|
|
613
|
+
capture: true,
|
|
614
|
+
});
|
|
615
|
+
this.listenersCollector.add(this.target, 'touchmove', this.handleTouchMove, { passive: true, capture: true });
|
|
616
|
+
// Attaching to the document to never miss a touchcancel or touchend event
|
|
617
|
+
this.listenersCollector.add(document, 'touchcancel', this.handleTouchEnd);
|
|
618
|
+
this.listenersCollector.add(document, 'touchend', this.handleTouchEnd);
|
|
619
|
+
};
|
|
620
|
+
GestureManager.prototype.addSafariGesturesEventListeners = function () {
|
|
621
|
+
// Add the gesture listeners only for Safari Desktop
|
|
622
|
+
// These listeners are used for the pinch to zoom gesture
|
|
623
|
+
// and on touch devices, we use the touch events instead
|
|
624
|
+
if (isTouchDevice())
|
|
625
|
+
return;
|
|
626
|
+
this.listenersCollector.add(this.target, 'gesturestart', this.handleGestureStart, { capture: true });
|
|
627
|
+
this.listenersCollector.add(this.target, 'gesturechange', this.handleGestureChange, { capture: true });
|
|
628
|
+
this.listenersCollector.add(this.target, 'gestureend', this.handleGestureEnd, { capture: true });
|
|
629
|
+
};
|
|
630
|
+
GestureManager.prototype.clampPointerToTargetBounds = function (pointer) {
|
|
631
|
+
return {
|
|
632
|
+
x: pointer.x - this.targetBounds.x,
|
|
633
|
+
y: pointer.y - this.targetBounds.y,
|
|
634
|
+
};
|
|
635
|
+
};
|
|
636
|
+
/**
|
|
637
|
+
* Extract the pointer position from the event
|
|
638
|
+
* and makes sure that the pointer position is correct even if the target has margins
|
|
639
|
+
*/
|
|
640
|
+
GestureManager.prototype.getCorrectPointerPosition = function (e) {
|
|
641
|
+
var _a;
|
|
642
|
+
var pointer = { x: 0, y: 0 };
|
|
643
|
+
// If there are multiple touches on the screen, we use the middle
|
|
644
|
+
// point between the first two touches as the pointer position,
|
|
645
|
+
// so panning while pinching to zoom works correctly, by using the point between the 2 fingers
|
|
646
|
+
if (((_a = e.touches) === null || _a === void 0 ? void 0 : _a.length) > 1) {
|
|
647
|
+
var touchEv = e;
|
|
648
|
+
var firstTouch = touchEv.touches[0];
|
|
649
|
+
var secTouch = touchEv.touches[1];
|
|
650
|
+
// Finding the middle point
|
|
651
|
+
pointer = {
|
|
652
|
+
x: (firstTouch.clientX + secTouch.clientX) / 2,
|
|
653
|
+
y: (firstTouch.clientY + secTouch.clientY) / 2,
|
|
654
|
+
};
|
|
655
|
+
}
|
|
656
|
+
else {
|
|
657
|
+
pointer = extractPointer(e);
|
|
658
|
+
}
|
|
659
|
+
return this.clampPointerToTargetBounds(pointer);
|
|
660
|
+
};
|
|
661
|
+
GestureManager.prototype.calculateDistanceBetweenTouches = function (firstTouch, secTouch) {
|
|
662
|
+
return Math.hypot(firstTouch.clientX - secTouch.clientX, firstTouch.clientY - secTouch.clientY);
|
|
663
|
+
};
|
|
664
|
+
GestureManager.prototype.emitZoomEvent = function (zoomDelta, zoomCenter) {
|
|
665
|
+
this.emit('pinchToZoom', zoomDelta, zoomCenter);
|
|
666
|
+
};
|
|
667
|
+
GestureManager.prototype.dispose = function () {
|
|
668
|
+
this.listenersCollector.dispose();
|
|
669
|
+
this.targetResizeObserver.disconnect();
|
|
670
|
+
};
|
|
671
|
+
GestureManager.prototype.setDisable = function (disable) {
|
|
672
|
+
this.listenersCollector.setDisabled(disable);
|
|
673
|
+
};
|
|
674
|
+
GestureManager.prototype.setInvertedWheelZoom = function (inverted) {
|
|
675
|
+
this.invertedWheelZoom = inverted;
|
|
676
|
+
};
|
|
677
|
+
return GestureManager;
|
|
678
|
+
}(EventEmitter));
|
|
679
|
+
|
|
680
|
+
/**
|
|
681
|
+
* A class to manage all kinds of keyboard events
|
|
682
|
+
* The class exposes a .dispose function that can be invoked when all the listeners should be detached
|
|
683
|
+
*/
|
|
684
|
+
var KeyboardManager = /** @class */ (function (_super) {
|
|
685
|
+
__extends(KeyboardManager, _super);
|
|
686
|
+
function KeyboardManager(target) {
|
|
687
|
+
var _this = _super.call(this) || this;
|
|
688
|
+
_this.listenersCollector = new ListenersCollector();
|
|
689
|
+
_this.handleKeyUp = function (e) {
|
|
690
|
+
_this.emit('keyUp', e.code);
|
|
691
|
+
};
|
|
692
|
+
_this.target = target;
|
|
693
|
+
_this.addListeners();
|
|
694
|
+
return _this;
|
|
695
|
+
}
|
|
696
|
+
KeyboardManager.prototype.addListeners = function () {
|
|
697
|
+
this.listenersCollector.add(this.target, 'keyup', this.handleKeyUp);
|
|
698
|
+
};
|
|
699
|
+
KeyboardManager.prototype.dispose = function () {
|
|
700
|
+
this.listenersCollector.dispose();
|
|
701
|
+
};
|
|
702
|
+
return KeyboardManager;
|
|
703
|
+
}(EventEmitter));
|
|
704
|
+
|
|
705
|
+
var Performance = /** @class */ (function () {
|
|
706
|
+
function Performance(label) {
|
|
707
|
+
this.label = label;
|
|
708
|
+
this.startTime = performance.now();
|
|
709
|
+
this.startTimestamp = Date.now();
|
|
710
|
+
}
|
|
711
|
+
Performance.prototype.measure = function () {
|
|
712
|
+
var duration = performance.now() - this.startTime;
|
|
713
|
+
return {
|
|
714
|
+
duration: duration,
|
|
715
|
+
end: Date.now(),
|
|
716
|
+
start: this.startTimestamp,
|
|
717
|
+
id: this.label,
|
|
718
|
+
};
|
|
719
|
+
};
|
|
720
|
+
Performance.prototype.printMeasurement = function () {
|
|
721
|
+
var duration = this.measure().duration;
|
|
722
|
+
if (duration < 1000) {
|
|
723
|
+
var formatted = duration.toFixed(2);
|
|
724
|
+
return "[Performance] ".concat(this.label, " -> ").concat(formatted, " ms");
|
|
725
|
+
}
|
|
726
|
+
else {
|
|
727
|
+
var seconds = (duration / 1000).toFixed(2);
|
|
728
|
+
return "[Performance] ".concat(this.label, " -> ").concat(seconds, " s");
|
|
729
|
+
}
|
|
730
|
+
};
|
|
731
|
+
return Performance;
|
|
732
|
+
}());
|
|
733
|
+
|
|
734
|
+
var Logger = /** @class */ (function (_super) {
|
|
735
|
+
__extends(Logger, _super);
|
|
736
|
+
function Logger() {
|
|
737
|
+
return _super !== null && _super.apply(this, arguments) || this;
|
|
738
|
+
}
|
|
739
|
+
Logger.prototype.logDebug = function () {
|
|
740
|
+
var args = [];
|
|
741
|
+
for (var _i = 0; _i < arguments.length; _i++) {
|
|
742
|
+
args[_i] = arguments[_i];
|
|
743
|
+
}
|
|
744
|
+
this.emit.apply(this, __spreadArray(['log', 'debug'], args, false));
|
|
745
|
+
};
|
|
746
|
+
Logger.prototype.logWarning = function () {
|
|
747
|
+
var args = [];
|
|
748
|
+
for (var _i = 0; _i < arguments.length; _i++) {
|
|
749
|
+
args[_i] = arguments[_i];
|
|
750
|
+
}
|
|
751
|
+
this.emit.apply(this, __spreadArray(['log', 'warn'], args, false));
|
|
752
|
+
};
|
|
753
|
+
Logger.prototype.logError = function () {
|
|
754
|
+
var args = [];
|
|
755
|
+
for (var _i = 0; _i < arguments.length; _i++) {
|
|
756
|
+
args[_i] = arguments[_i];
|
|
757
|
+
}
|
|
758
|
+
this.emit.apply(this, __spreadArray(['log', 'error'], args, false));
|
|
759
|
+
};
|
|
760
|
+
return Logger;
|
|
761
|
+
}(EventEmitter));
|
|
762
|
+
var logger = new Logger();
|
|
763
|
+
|
|
764
|
+
/**
|
|
765
|
+
* This class responsibility is to initialise the WASM module created by emscripten,
|
|
766
|
+
* and provide utility functions to access the objects exposed through Embind, which are attached to the main wasm module
|
|
767
|
+
*/
|
|
768
|
+
var WasmModule = /** @class */ (function () {
|
|
769
|
+
function WasmModule(settings) {
|
|
770
|
+
this.settings = settings;
|
|
771
|
+
}
|
|
772
|
+
WasmModule.prototype.isReleaseMode = function () {
|
|
773
|
+
return this.settings.mode === WebRendererMode.release;
|
|
774
|
+
};
|
|
775
|
+
WasmModule.prototype.init = function () {
|
|
776
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
777
|
+
var emscriptenJsModule, factory, _a, error_1;
|
|
778
|
+
var _b;
|
|
779
|
+
var _this = this;
|
|
780
|
+
return __generator(this, function (_c) {
|
|
781
|
+
switch (_c.label) {
|
|
782
|
+
case 0: return [4 /*yield*/, this.importModule()];
|
|
783
|
+
case 1:
|
|
784
|
+
emscriptenJsModule = _c.sent();
|
|
785
|
+
factory = emscriptenJsModule.default;
|
|
786
|
+
_c.label = 2;
|
|
787
|
+
case 2:
|
|
788
|
+
_c.trys.push([2, 4, , 5]);
|
|
789
|
+
_a = this;
|
|
790
|
+
return [4 /*yield*/, factory({
|
|
791
|
+
FeatureFlags: this.settings.featureFlags,
|
|
792
|
+
currentWebGLVersion: this.settings.webglVersion,
|
|
793
|
+
bridge: this.settings.jsBridge,
|
|
794
|
+
locateFile: function (file) {
|
|
795
|
+
return _this.settings.locateFile.replace('{file}', file);
|
|
796
|
+
},
|
|
797
|
+
})];
|
|
798
|
+
case 3:
|
|
799
|
+
_a.instance = _c.sent();
|
|
800
|
+
return [3 /*break*/, 5];
|
|
801
|
+
case 4:
|
|
802
|
+
error_1 = _c.sent();
|
|
803
|
+
throw new WebRendererError('WASM_ERROR', 'An error occurred while trying to create the wasm module.', error_1);
|
|
804
|
+
case 5:
|
|
805
|
+
// Updating the pointer info map. We use it to convert Js pointer types to WASM
|
|
806
|
+
this.pointerTypeToWASMMap = {
|
|
807
|
+
unset: this.instance.PRUserPointerTypeEnum.Unset,
|
|
808
|
+
mouse: this.instance.PRUserPointerTypeEnum.Mouse,
|
|
809
|
+
touch: this.instance.PRUserPointerTypeEnum.Touch,
|
|
810
|
+
};
|
|
811
|
+
// Mapping the PRCursorType to the TS Enum
|
|
812
|
+
this.prCursorTypeToCSSCursorMap = (_b = {},
|
|
813
|
+
_b[this.instance.PRCursorTypeEnum.Auto.value] = "auto" /* CSSCursor.Auto */,
|
|
814
|
+
_b[this.instance.PRCursorTypeEnum.Default.value] = "default" /* CSSCursor.Default */,
|
|
815
|
+
_b[this.instance.PRCursorTypeEnum.Pointer.value] = "pointer" /* CSSCursor.Pointer */,
|
|
816
|
+
_b[this.instance.PRCursorTypeEnum.Grab.value] = "grab" /* CSSCursor.Grab */,
|
|
817
|
+
_b[this.instance.PRCursorTypeEnum.Grabbing.value] = "grabbing" /* CSSCursor.Grabbing */,
|
|
818
|
+
_b);
|
|
819
|
+
this.prototypeResizeModeToWASMMap = {
|
|
820
|
+
Fit: this.instance.PrototypeResizeModeWasmEnum.Fit,
|
|
821
|
+
FillWidth: this.instance.PrototypeResizeModeWasmEnum.FillWidth,
|
|
822
|
+
ActualSize: this.instance.PrototypeResizeModeWasmEnum.ActualSize,
|
|
823
|
+
};
|
|
824
|
+
return [2 /*return*/];
|
|
825
|
+
}
|
|
826
|
+
});
|
|
827
|
+
});
|
|
828
|
+
};
|
|
829
|
+
WasmModule.prototype.makeWebGLContext = function (canvas, webGLContextAttributes) {
|
|
830
|
+
var _a;
|
|
831
|
+
if (webGLContextAttributes === void 0) { webGLContextAttributes = {}; }
|
|
832
|
+
var ctxSettings = __assign({ antialias: false, alpha: false, stencil: false, depth: false, powerPreference: 'high-performance', preserveDrawingBuffer: false, desynchronized: true }, webGLContextAttributes);
|
|
833
|
+
var ctxHandle = this.instance.GL.createContext(canvas, ctxSettings);
|
|
834
|
+
if (!ctxHandle) {
|
|
835
|
+
throw new WebRendererError('WEBGL_ERROR', 'Unable to create WebGL context. WebGL might be unsupported, disabled, or this device is not able to run WebGL correctly.');
|
|
836
|
+
}
|
|
837
|
+
var gl = (_a = this.instance.GL.getContext(ctxHandle)) === null || _a === void 0 ? void 0 : _a.GLctx;
|
|
838
|
+
if (gl) {
|
|
839
|
+
// Enabling the WEBGL_debug_renderer_info extension if available
|
|
840
|
+
// so that we can retrieve debug info about the GPU
|
|
841
|
+
// We do that using the detect-gpu npm package
|
|
842
|
+
gl.getExtension('WEBGL_debug_renderer_info');
|
|
843
|
+
}
|
|
844
|
+
return ctxHandle;
|
|
845
|
+
};
|
|
846
|
+
WasmModule.prototype.createWebGLTextureFromImage = function (image, webGLCtxHandle) {
|
|
847
|
+
var GL = this.instance.GL;
|
|
848
|
+
var ctxHandle = GL.getContext(webGLCtxHandle);
|
|
849
|
+
if (!ctxHandle) {
|
|
850
|
+
throw new Error('Unable to retrieve emscripten WebGL context from handle');
|
|
851
|
+
}
|
|
852
|
+
var ctx = ctxHandle.GLctx;
|
|
853
|
+
if (!ctx) {
|
|
854
|
+
throw new Error('WebGL context is null');
|
|
855
|
+
}
|
|
856
|
+
// First, create a WebGL texture
|
|
857
|
+
var texture = ctx.createTexture();
|
|
858
|
+
ctx.bindTexture(ctx.TEXTURE_2D, texture);
|
|
859
|
+
ctx.pixelStorei(ctx.UNPACK_PREMULTIPLY_ALPHA_WEBGL, true);
|
|
860
|
+
// Now we generate a texture id using emscripten
|
|
861
|
+
var textureHandle = GL.getNewId(GL.textures);
|
|
862
|
+
// Adding the texture into the correct slot
|
|
863
|
+
GL.textures[textureHandle] = texture;
|
|
864
|
+
// And finally, we upload the image to the texture
|
|
865
|
+
ctx.texImage2D(ctx.TEXTURE_2D, 0, ctx.RGBA, ctx.RGBA, ctx.UNSIGNED_BYTE, image);
|
|
866
|
+
// Unbinding the current texture, so that we don't accidentally modify it
|
|
867
|
+
ctx.bindTexture(ctx.TEXTURE_2D, null);
|
|
868
|
+
return textureHandle;
|
|
869
|
+
};
|
|
870
|
+
/**
|
|
871
|
+
* Forcefully releasing the WebGL context
|
|
872
|
+
*/
|
|
873
|
+
WasmModule.prototype.destroyWebGLContext = function (webGLCtxHandle) {
|
|
874
|
+
var _a;
|
|
875
|
+
logger.logDebug('Destroying WebGL context');
|
|
876
|
+
var ctx = (_a = this.instance) === null || _a === void 0 ? void 0 : _a.GL.getContext(webGLCtxHandle);
|
|
877
|
+
if (!ctx) {
|
|
878
|
+
logger.logError('WebGL context not found while trying to destroy it');
|
|
879
|
+
return;
|
|
880
|
+
}
|
|
881
|
+
this.instance.GL.deleteContext(webGLCtxHandle);
|
|
882
|
+
var loseContextExt = ctx.GLctx.getExtension('WEBGL_lose_context');
|
|
883
|
+
if (!loseContextExt) {
|
|
884
|
+
logger.logError('WEBGL_lose_context not available. Not possible to destroy WebGL context manually.');
|
|
885
|
+
return;
|
|
886
|
+
}
|
|
887
|
+
loseContextExt.loseContext();
|
|
888
|
+
logger.logDebug('WebGL destroyed');
|
|
889
|
+
return true;
|
|
890
|
+
};
|
|
891
|
+
/**
|
|
892
|
+
* Imports the emscripten generated JavaScript using a dynamic import. By using
|
|
893
|
+
* a dynamic import the user only has to download the JS needed for their use
|
|
894
|
+
* case (debug or release), and not both. How the dynamic import is handled
|
|
895
|
+
* during the build is the responsibility of our bundler Rollup - the result is
|
|
896
|
+
* a bundle employing code splitting and dynamic chunk loading. As such there
|
|
897
|
+
* are implications for downstream build tools too, for example Webpack in
|
|
898
|
+
* cloud-frontend.
|
|
899
|
+
*/
|
|
900
|
+
WasmModule.prototype.importModule = function () {
|
|
901
|
+
return this.isReleaseMode()
|
|
902
|
+
? import('./web-renderer-release-988811bf.js')
|
|
903
|
+
: import('./web-renderer-debug-ceaf0a83.js');
|
|
904
|
+
};
|
|
905
|
+
WasmModule.prototype.mapToCSSCursor = function (prCursorType) {
|
|
906
|
+
return this.prCursorTypeToCSSCursorMap[prCursorType.value];
|
|
907
|
+
};
|
|
908
|
+
WasmModule.prototype.mapToPRPointerType = function (pointerType) {
|
|
909
|
+
var _a;
|
|
910
|
+
return ((_a = this.pointerTypeToWASMMap[pointerType]) !== null && _a !== void 0 ? _a : this.instance.PRUserPointerTypeEnum.Unset);
|
|
911
|
+
};
|
|
912
|
+
WasmModule.prototype.mapPointerInfo = function (pointerInfo) {
|
|
913
|
+
return __assign(__assign({}, pointerInfo), { type: this.mapToPRPointerType(pointerInfo.type) });
|
|
914
|
+
};
|
|
915
|
+
WasmModule.prototype.mapResizeMode = function (resizeMode) {
|
|
916
|
+
return this.prototypeResizeModeToWASMMap[resizeMode];
|
|
917
|
+
};
|
|
918
|
+
return WasmModule;
|
|
919
|
+
}());
|
|
920
|
+
|
|
921
|
+
export { DefaultFeatureFlags as D, EventEmitter as E, GestureManager as G, KeyboardManager as K, ListenersCollector as L, Performance as P, WebRendererMode as W, __extends as _, __awaiter as a, __generator as b, clamp as c, debounce as d, convertEmbindVectorToArray as e, WebRendererError as f, getSupportedWebGLVersion as g, __assign as h, WasmModule as i, __spreadArray as j, PrototypeResizeMode as k, logger as l, extractPointer as m, isTouchDevice as n, getiOSVersion as o, parseSafariUserAgent as p, removeUndefinedKeys as r, safePtrAccess as s, touchableClick as t };
|