@sketch-hq/sketch-web-renderer 14.12.2 → 14.13.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (27) hide show
  1. package/out/web-renderer/WasmModule-b06ee9c9.js +921 -0
  2. package/out/web-renderer/export-worker.js +11670 -0
  3. package/out/web-renderer/index.js +1 -1
  4. package/out/web-renderer/ts/canvas-renderer/CanvasRenderer.d.ts +2 -0
  5. package/out/web-renderer/ts/canvas-renderer/CanvasRenderer.d.ts.map +1 -1
  6. package/out/web-renderer/ts/canvas-renderer/CanvasSettings.d.ts +2 -0
  7. package/out/web-renderer/ts/canvas-renderer/CanvasSettings.d.ts.map +1 -1
  8. package/out/web-renderer/ts/canvas-renderer/react/CanvasRendererProvider.d.ts.map +1 -1
  9. package/out/web-renderer/ts/canvas-renderer/react/hooks/actions.d.ts +7 -0
  10. package/out/web-renderer/ts/canvas-renderer/react/hooks/actions.d.ts.map +1 -1
  11. package/out/web-renderer/ts/export-worker/ExportWorker.d.ts +2 -0
  12. package/out/web-renderer/ts/export-worker/ExportWorker.d.ts.map +1 -0
  13. package/out/web-renderer/ts/export-worker/ExportWorkerClient.d.ts +31 -0
  14. package/out/web-renderer/ts/export-worker/ExportWorkerClient.d.ts.map +1 -0
  15. package/out/web-renderer/ts/export-worker/ExportWorkerMessageData.d.ts +42 -0
  16. package/out/web-renderer/ts/export-worker/ExportWorkerMessageData.d.ts.map +1 -0
  17. package/out/web-renderer/ts/export-worker/worker-shims.d.ts +1 -0
  18. package/out/web-renderer/ts/export-worker/worker-shims.d.ts.map +1 -0
  19. package/out/web-renderer/ts/types/Events.d.ts +1 -0
  20. package/out/web-renderer/ts/types/Events.d.ts.map +1 -1
  21. package/out/web-renderer/wasm/Debug/web-renderer-debug.wasm +0 -0
  22. package/out/web-renderer/wasm/Debug/web-renderer.d.ts +1 -1
  23. package/out/web-renderer/wasm/Release/web-renderer-release.mjs +6 -6
  24. package/out/web-renderer/wasm/Release/web-renderer-release.wasm +0 -0
  25. package/out/web-renderer/web-renderer-release-988811bf.js +4309 -0
  26. package/out/web-renderer/web-renderer-release-bac26995.js +1 -0
  27. 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 };