Compare commits

...
Author SHA1 Message Date
Mark Tolmacs bfa4941ad1 fix: More robust mobile and tablet detection
Signed-off-by: Mark Tolmacs <mark@lazycat.hu>
2025-12-08 09:45:26 +00:00
Márk TolmácsandGitHub 8d18078f5c fix: Box selection of arrows (#10451) 2025-12-03 12:47:30 +01:00
David LuzarandGitHub d080833f4d chore: bump typescript@5.9.3 (#10431) 2025-12-01 22:37:42 +01:00
451bcac0b7 fix: Ctrl/Alt elbow arrow jumps (#10432)
* fix: Ctrl/Alt elbow arrow jumps

Signed-off-by: Mark Tolmacs <mark@lazycat.hu>

* chore: Trigger build

* style

---------

Signed-off-by: Mark Tolmacs <mark@lazycat.hu>
Co-authored-by: dwelle <5153846+dwelle@users.noreply.github.com>
2025-12-01 17:06:08 +00:00
22 changed files with 149 additions and 115 deletions
+2 -2
View File
@@ -441,7 +441,7 @@ class Collab extends PureComponent<CollabProps, CollabState> {
}; };
private decryptPayload = async ( private decryptPayload = async (
iv: Uint8Array, iv: Uint8Array<ArrayBuffer>,
encryptedData: ArrayBuffer, encryptedData: ArrayBuffer,
decryptionKey: string, decryptionKey: string,
): Promise<ValueOf<SocketUpdateDataSource>> => { ): Promise<ValueOf<SocketUpdateDataSource>> => {
@@ -562,7 +562,7 @@ class Collab extends PureComponent<CollabProps, CollabState> {
// All socket listeners are moving to Portal // All socket listeners are moving to Portal
this.portal.socket.on( this.portal.socket.on(
"client-broadcast", "client-broadcast",
async (encryptedData: ArrayBuffer, iv: Uint8Array) => { async (encryptedData: ArrayBuffer, iv: Uint8Array<ArrayBuffer>) => {
if (!this.portal.roomKey) { if (!this.portal.roomKey) {
return; return;
} }
+2 -2
View File
@@ -105,8 +105,8 @@ const decryptElements = async (
data: FirebaseStoredScene, data: FirebaseStoredScene,
roomKey: string, roomKey: string,
): Promise<readonly ExcalidrawElement[]> => { ): Promise<readonly ExcalidrawElement[]> => {
const ciphertext = data.ciphertext.toUint8Array(); const ciphertext = data.ciphertext.toUint8Array() as Uint8Array<ArrayBuffer>;
const iv = data.iv.toUint8Array(); const iv = data.iv.toUint8Array() as Uint8Array<ArrayBuffer>;
const decrypted = await decryptData(iv, ciphertext, roomKey); const decrypted = await decryptData(iv, ciphertext, roomKey);
const decodedData = new TextDecoder("utf-8").decode( const decodedData = new TextDecoder("utf-8").decode(
+1 -1
View File
@@ -34,7 +34,7 @@
"prettier": "2.6.2", "prettier": "2.6.2",
"rewire": "6.0.0", "rewire": "6.0.0",
"rimraf": "^5.0.0", "rimraf": "^5.0.0",
"typescript": "4.9.4", "typescript": "5.9.3",
"vite": "5.0.12", "vite": "5.0.12",
"vite-plugin-checker": "0.7.2", "vite-plugin-checker": "0.7.2",
"vite-plugin-ejs": "1.7.0", "vite-plugin-ejs": "1.7.0",
+7 -4
View File
@@ -1,3 +1,5 @@
import mobile from "is-mobile";
export type StylesPanelMode = "compact" | "full" | "mobile"; export type StylesPanelMode = "compact" | "full" | "mobile";
export type EditorInterface = Readonly<{ export type EditorInterface = Readonly<{
@@ -139,12 +141,13 @@ export const getFormFactor = (
editorWidth: number, editorWidth: number,
editorHeight: number, editorHeight: number,
): EditorInterface["formFactor"] => { ): EditorInterface["formFactor"] => {
if (isMobileBreakpoint(editorWidth, editorHeight)) { if (mobile()) {
return "phone"; return "phone";
} } else if (mobile({ tablet: true })) {
if (isTabletBreakpoint(editorWidth, editorHeight)) {
return "tablet"; return "tablet";
} else if (isMobileBreakpoint(editorWidth, editorHeight)) {
// NOTE: Very small editor sizes should be treated as phone
return "phone";
} }
return "desktop"; return "desktop";
+1
View File
@@ -493,6 +493,7 @@ describe("binding for simple arrows", () => {
expect(arrow.endBinding?.elementId).toBe(rectRight.id); expect(arrow.endBinding?.elementId).toBe(rectRight.id);
mouse.downAt(-100, -100); mouse.downAt(-100, -100);
mouse.moveTo(0, 0);
mouse.moveTo(650, 750); mouse.moveTo(650, 750);
mouse.up(0, 0); mouse.up(0, 0);
+26 -20
View File
@@ -11463,7 +11463,11 @@ class App extends React.Component<AppProps, AppState> {
): void => { ): void => {
const selectionElement = this.state.selectionElement; const selectionElement = this.state.selectionElement;
const pointerCoords = pointerDownState.lastCoords; const pointerCoords = pointerDownState.lastCoords;
if (selectionElement && this.state.activeTool.type !== "eraser") { if (
selectionElement &&
pointerDownState.boxSelection.hasOccurred &&
this.state.activeTool.type !== "eraser"
) {
dragNewElement({ dragNewElement({
newElement: selectionElement, newElement: selectionElement,
elementType: this.state.activeTool.type, elementType: this.state.activeTool.type,
@@ -11527,25 +11531,27 @@ class App extends React.Component<AppProps, AppState> {
snapLines, snapLines,
}); });
dragNewElement({ if (!isBindingElement(newElement)) {
newElement, dragNewElement({
elementType: this.state.activeTool.type, newElement,
originX: pointerDownState.originInGrid.x, elementType: this.state.activeTool.type,
originY: pointerDownState.originInGrid.y, originX: pointerDownState.originInGrid.x,
x: gridX, originY: pointerDownState.originInGrid.y,
y: gridY, x: gridX,
width: distance(pointerDownState.originInGrid.x, gridX), y: gridY,
height: distance(pointerDownState.originInGrid.y, gridY), width: distance(pointerDownState.originInGrid.x, gridX),
shouldMaintainAspectRatio: isImageElement(newElement) height: distance(pointerDownState.originInGrid.y, gridY),
? !shouldMaintainAspectRatio(event) shouldMaintainAspectRatio: isImageElement(newElement)
: shouldMaintainAspectRatio(event), ? !shouldMaintainAspectRatio(event)
shouldResizeFromCenter: shouldResizeFromCenter(event), : shouldMaintainAspectRatio(event),
zoom: this.state.zoom.value, shouldResizeFromCenter: shouldResizeFromCenter(event),
scene: this.scene, zoom: this.state.zoom.value,
widthAspectRatio: aspectRatio, scene: this.scene,
originOffset: this.state.originSnapOffset, widthAspectRatio: aspectRatio,
informMutation, originOffset: this.state.originSnapOffset,
}); informMutation,
});
}
this.setState({ this.setState({
newElement, newElement,
+6 -6
View File
@@ -222,7 +222,7 @@ function dataView(
* *
* @param buffers each buffer (chunk) must be at most 2^32 bits large (~4GB) * @param buffers each buffer (chunk) must be at most 2^32 bits large (~4GB)
*/ */
const concatBuffers = (...buffers: Uint8Array[]) => { const concatBuffers = (...buffers: Uint8Array[]): Uint8Array<ArrayBuffer> => {
const bufferView = new Uint8Array( const bufferView = new Uint8Array(
VERSION_DATAVIEW_BYTES + VERSION_DATAVIEW_BYTES +
NEXT_CHUNK_SIZE_DATAVIEW_BYTES * buffers.length + NEXT_CHUNK_SIZE_DATAVIEW_BYTES * buffers.length +
@@ -295,12 +295,12 @@ const splitBuffers = (concatenatedBuffer: Uint8Array) => {
/** @private */ /** @private */
const _encryptAndCompress = async ( const _encryptAndCompress = async (
data: Uint8Array | string, data: Uint8Array<ArrayBuffer> | string,
encryptionKey: string, encryptionKey: string,
) => { ) => {
const { encryptedBuffer, iv } = await encryptData( const { encryptedBuffer, iv } = await encryptData(
encryptionKey, encryptionKey,
deflate(data), deflate(data) as Uint8Array<ArrayBuffer>,
); );
return { iv, buffer: new Uint8Array(encryptedBuffer) }; return { iv, buffer: new Uint8Array(encryptedBuffer) };
@@ -330,7 +330,7 @@ export const compressData = async <T extends Record<string, any> = never>(
: { : {
metadata: T; metadata: T;
}), }),
): Promise<Uint8Array> => { ): Promise<Uint8Array<ArrayBuffer>> => {
const fileInfo: FileEncodingInfo = { const fileInfo: FileEncodingInfo = {
version: 2, version: 2,
compression: "pako@1", compression: "pako@1",
@@ -355,8 +355,8 @@ export const compressData = async <T extends Record<string, any> = never>(
/** @private */ /** @private */
const _decryptAndDecompress = async ( const _decryptAndDecompress = async (
iv: Uint8Array, iv: Uint8Array<ArrayBuffer>,
decryptedBuffer: Uint8Array, decryptedBuffer: Uint8Array<ArrayBuffer>,
decryptionKey: string, decryptionKey: string,
isCompressed: boolean, isCompressed: boolean,
) => { ) => {
+7 -7
View File
@@ -4,7 +4,7 @@ import { blobToArrayBuffer } from "./blob";
export const IV_LENGTH_BYTES = 12; export const IV_LENGTH_BYTES = 12;
export const createIV = () => { export const createIV = (): Uint8Array<ArrayBuffer> => {
const arr = new Uint8Array(IV_LENGTH_BYTES); const arr = new Uint8Array(IV_LENGTH_BYTES);
return window.crypto.getRandomValues(arr); return window.crypto.getRandomValues(arr);
}; };
@@ -49,12 +49,12 @@ export const getCryptoKey = (key: string, usage: KeyUsage) =>
export const encryptData = async ( export const encryptData = async (
key: string | CryptoKey, key: string | CryptoKey,
data: Uint8Array | ArrayBuffer | Blob | File | string, data: Uint8Array<ArrayBuffer> | ArrayBuffer | Blob | File | string,
): Promise<{ encryptedBuffer: ArrayBuffer; iv: Uint8Array }> => { ): Promise<{ encryptedBuffer: ArrayBuffer; iv: Uint8Array<ArrayBuffer> }> => {
const importedKey = const importedKey =
typeof key === "string" ? await getCryptoKey(key, "encrypt") : key; typeof key === "string" ? await getCryptoKey(key, "encrypt") : key;
const iv = createIV(); const iv = createIV();
const buffer: ArrayBuffer | Uint8Array = const buffer: ArrayBuffer | Uint8Array<ArrayBuffer> =
typeof data === "string" typeof data === "string"
? new TextEncoder().encode(data) ? new TextEncoder().encode(data)
: data instanceof Uint8Array : data instanceof Uint8Array
@@ -71,15 +71,15 @@ export const encryptData = async (
iv, iv,
}, },
importedKey, importedKey,
buffer as ArrayBuffer | Uint8Array, buffer,
); );
return { encryptedBuffer, iv }; return { encryptedBuffer, iv };
}; };
export const decryptData = async ( export const decryptData = async (
iv: Uint8Array, iv: Uint8Array<ArrayBuffer>,
encrypted: Uint8Array | ArrayBuffer, encrypted: Uint8Array<ArrayBuffer> | ArrayBuffer,
privateKey: string, privateKey: string,
): Promise<ArrayBuffer> => { ): Promise<ArrayBuffer> => {
const key = await getCryptoKey(privateKey, "decrypt"); const key = await getCryptoKey(privateKey, "decrypt");
+1 -1
View File
@@ -42,7 +42,7 @@ declare module "png-chunk-text" {
function decode(data: Uint8Array): { keyword: string; text: string }; function decode(data: Uint8Array): { keyword: string; text: string };
} }
declare module "png-chunks-encode" { declare module "png-chunks-encode" {
function encode(chunks: TEXtChunk[]): Uint8Array; function encode(chunks: TEXtChunk[]): Uint8Array<ArrayBuffer>;
export = encode; export = encode;
} }
declare module "png-chunks-extract" { declare module "png-chunks-extract" {
+1 -1
View File
@@ -18,7 +18,7 @@ export function useOutsideClick<T extends HTMLElement>(
* Returning `undefined` will fallback to the default behavior. * Returning `undefined` will fallback to the default behavior.
*/ */
isInside?: ( isInside?: (
event: Event & { target: HTMLElement }, event: Event & { target: T },
/** the element of the passed ref */ /** the element of the passed ref */
container: T, container: T,
) => boolean | undefined, ) => boolean | undefined,
+2 -1
View File
@@ -95,6 +95,7 @@
"fractional-indexing": "3.2.0", "fractional-indexing": "3.2.0",
"fuzzy": "0.1.3", "fuzzy": "0.1.3",
"image-blob-reduce": "3.0.1", "image-blob-reduce": "3.0.1",
"is-mobile": "5.0.0",
"jotai": "2.11.0", "jotai": "2.11.0",
"jotai-scope": "0.7.2", "jotai-scope": "0.7.2",
"lodash.debounce": "4.0.8", "lodash.debounce": "4.0.8",
@@ -133,6 +134,6 @@
"fonteditor-core": "2.4.1", "fonteditor-core": "2.4.1",
"harfbuzzjs": "0.3.6", "harfbuzzjs": "0.3.6",
"jest-diff": "29.7.0", "jest-diff": "29.7.0",
"typescript": "4.9.4" "typescript": "5.9.3"
} }
} }
@@ -20,7 +20,7 @@ const load = (): Promise<{
subset: ( subset: (
fontBuffer: ArrayBuffer, fontBuffer: ArrayBuffer,
codePoints: ReadonlySet<number>, codePoints: ReadonlySet<number>,
) => Uint8Array; ) => Uint8Array<ArrayBuffer>;
}> => { }> => {
return new Promise(async (resolve, reject) => { return new Promise(async (resolve, reject) => {
try { try {
@@ -18,7 +18,7 @@ type Vector = any;
let loadedWasm: ReturnType<typeof load> | null = null; let loadedWasm: ReturnType<typeof load> | null = null;
// re-map from internal vector into byte array // re-map from internal vector into byte array
function convertFromVecToUint8Array(vector: Vector): Uint8Array { function convertFromVecToUint8Array(vector: Vector): Uint8Array<ArrayBuffer> {
const arr = []; const arr = [];
for (let i = 0, l = vector.size(); i < l; i++) { for (let i = 0, l = vector.size(); i < l; i++) {
arr.push(vector.get(i)); arr.push(vector.get(i));
@@ -29,8 +29,8 @@ function convertFromVecToUint8Array(vector: Vector): Uint8Array {
// TODO: consider adding support for fetching the wasm from an URL (external CDN, data URL, etc.) // TODO: consider adding support for fetching the wasm from an URL (external CDN, data URL, etc.)
const load = (): Promise<{ const load = (): Promise<{
compress: (buffer: ArrayBuffer) => Uint8Array; compress: (buffer: ArrayBuffer) => Uint8Array<ArrayBuffer>;
decompress: (buffer: ArrayBuffer) => Uint8Array; decompress: (buffer: ArrayBuffer) => Uint8Array<ArrayBuffer>;
}> => { }> => {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
try { try {
@@ -1223,7 +1223,7 @@ exports[`contextMenu element > selecting 'Add to library' in context menu adds e
"type": "rectangle", "type": "rectangle",
"updated": 1, "updated": 1,
"version": 3, "version": 3,
"versionNonce": 2019559783, "versionNonce": 401146281,
"width": 10, "width": 10,
"x": -20, "x": -20,
"y": -10, "y": -10,
@@ -1431,14 +1431,14 @@ exports[`contextMenu element > selecting 'Bring forward' in context menu brings
"opacity": 100, "opacity": 100,
"roughness": 1, "roughness": 1,
"roundness": null, "roundness": null,
"seed": 238820263, "seed": 1014066025,
"strokeColor": "#1e1e1e", "strokeColor": "#1e1e1e",
"strokeStyle": "solid", "strokeStyle": "solid",
"strokeWidth": 2, "strokeWidth": 2,
"type": "rectangle", "type": "rectangle",
"updated": 1, "updated": 1,
"version": 3, "version": 3,
"versionNonce": 1505387817, "versionNonce": 1604849351,
"width": 20, "width": 20,
"x": 20, "x": 20,
"y": 30, "y": 30,
@@ -1463,14 +1463,14 @@ exports[`contextMenu element > selecting 'Bring forward' in context menu brings
"opacity": 100, "opacity": 100,
"roughness": 1, "roughness": 1,
"roundness": null, "roundness": null,
"seed": 449462985, "seed": 1278240551,
"strokeColor": "#1e1e1e", "strokeColor": "#1e1e1e",
"strokeStyle": "solid", "strokeStyle": "solid",
"strokeWidth": 2, "strokeWidth": 2,
"type": "rectangle", "type": "rectangle",
"updated": 1, "updated": 1,
"version": 4, "version": 4,
"versionNonce": 915032327, "versionNonce": 493213705,
"width": 20, "width": 20,
"x": -10, "x": -10,
"y": 0, "y": 0,
@@ -1765,14 +1765,14 @@ exports[`contextMenu element > selecting 'Bring to front' in context menu brings
"opacity": 100, "opacity": 100,
"roughness": 1, "roughness": 1,
"roundness": null, "roundness": null,
"seed": 238820263, "seed": 1014066025,
"strokeColor": "#1e1e1e", "strokeColor": "#1e1e1e",
"strokeStyle": "solid", "strokeStyle": "solid",
"strokeWidth": 2, "strokeWidth": 2,
"type": "rectangle", "type": "rectangle",
"updated": 1, "updated": 1,
"version": 3, "version": 3,
"versionNonce": 1505387817, "versionNonce": 1604849351,
"width": 20, "width": 20,
"x": 20, "x": 20,
"y": 30, "y": 30,
@@ -1797,14 +1797,14 @@ exports[`contextMenu element > selecting 'Bring to front' in context menu brings
"opacity": 100, "opacity": 100,
"roughness": 1, "roughness": 1,
"roundness": null, "roundness": null,
"seed": 449462985, "seed": 1278240551,
"strokeColor": "#1e1e1e", "strokeColor": "#1e1e1e",
"strokeStyle": "solid", "strokeStyle": "solid",
"strokeWidth": 2, "strokeWidth": 2,
"type": "rectangle", "type": "rectangle",
"updated": 1, "updated": 1,
"version": 4, "version": 4,
"versionNonce": 915032327, "versionNonce": 493213705,
"width": 20, "width": 20,
"x": -10, "x": -10,
"y": 0, "y": 0,
@@ -2108,7 +2108,7 @@ exports[`contextMenu element > selecting 'Copy styles' in context menu copies st
"type": "rectangle", "type": "rectangle",
"updated": 1, "updated": 1,
"version": 3, "version": 3,
"versionNonce": 2019559783, "versionNonce": 401146281,
"width": 10, "width": 10,
"x": -20, "x": -20,
"y": -10, "y": -10,
@@ -2321,7 +2321,7 @@ exports[`contextMenu element > selecting 'Delete' in context menu deletes elemen
"type": "rectangle", "type": "rectangle",
"updated": 1, "updated": 1,
"version": 4, "version": 4,
"versionNonce": 1014066025, "versionNonce": 1116226695,
"width": 10, "width": 10,
"x": -20, "x": -20,
"y": -10, "y": -10,
@@ -2567,7 +2567,7 @@ exports[`contextMenu element > selecting 'Duplicate' in context menu duplicates
"type": "rectangle", "type": "rectangle",
"updated": 1, "updated": 1,
"version": 3, "version": 3,
"versionNonce": 2019559783, "versionNonce": 401146281,
"width": 10, "width": 10,
"x": -20, "x": -20,
"y": -10, "y": -10,
@@ -2592,14 +2592,14 @@ exports[`contextMenu element > selecting 'Duplicate' in context menu duplicates
"opacity": 100, "opacity": 100,
"roughness": 1, "roughness": 1,
"roundness": null, "roundness": null,
"seed": 238820263, "seed": 1014066025,
"strokeColor": "#1e1e1e", "strokeColor": "#1e1e1e",
"strokeStyle": "solid", "strokeStyle": "solid",
"strokeWidth": 2, "strokeWidth": 2,
"type": "rectangle", "type": "rectangle",
"updated": 1, "updated": 1,
"version": 5, "version": 5,
"versionNonce": 1604849351, "versionNonce": 400692809,
"width": 10, "width": 10,
"x": -10, "x": -10,
"y": 0, "y": 0,
@@ -2868,14 +2868,14 @@ exports[`contextMenu element > selecting 'Group selection' in context menu group
"opacity": 100, "opacity": 100,
"roughness": 1, "roughness": 1,
"roundness": null, "roundness": null,
"seed": 449462985, "seed": 1278240551,
"strokeColor": "#1e1e1e", "strokeColor": "#1e1e1e",
"strokeStyle": "solid", "strokeStyle": "solid",
"strokeWidth": 2, "strokeWidth": 2,
"type": "rectangle", "type": "rectangle",
"updated": 1, "updated": 1,
"version": 4, "version": 4,
"versionNonce": 81784553, "versionNonce": 915032327,
"width": 20, "width": 20,
"x": -10, "x": -10,
"y": 0, "y": 0,
@@ -2902,14 +2902,14 @@ exports[`contextMenu element > selecting 'Group selection' in context menu group
"opacity": 100, "opacity": 100,
"roughness": 1, "roughness": 1,
"roundness": null, "roundness": null,
"seed": 238820263, "seed": 1014066025,
"strokeColor": "#1e1e1e", "strokeColor": "#1e1e1e",
"strokeStyle": "solid", "strokeStyle": "solid",
"strokeWidth": 2, "strokeWidth": 2,
"type": "rectangle", "type": "rectangle",
"updated": 1, "updated": 1,
"version": 4, "version": 4,
"versionNonce": 747212839, "versionNonce": 81784553,
"width": 20, "width": 20,
"x": 20, "x": 20,
"y": 30, "y": 30,
@@ -3238,14 +3238,14 @@ exports[`contextMenu element > selecting 'Paste styles' in context menu pastes s
"opacity": 60, "opacity": 60,
"roughness": 2, "roughness": 2,
"roundness": null, "roundness": null,
"seed": 449462985, "seed": 1278240551,
"strokeColor": "#e03131", "strokeColor": "#e03131",
"strokeStyle": "dotted", "strokeStyle": "dotted",
"strokeWidth": 2, "strokeWidth": 2,
"type": "rectangle", "type": "rectangle",
"updated": 1, "updated": 1,
"version": 4, "version": 4,
"versionNonce": 1359939303, "versionNonce": 1402203177,
"width": 20, "width": 20,
"x": -10, "x": -10,
"y": 0, "y": 0,
@@ -3270,14 +3270,14 @@ exports[`contextMenu element > selecting 'Paste styles' in context menu pastes s
"opacity": 60, "opacity": 60,
"roughness": 2, "roughness": 2,
"roundness": null, "roundness": null,
"seed": 640725609, "seed": 1898319239,
"strokeColor": "#e03131", "strokeColor": "#e03131",
"strokeStyle": "dotted", "strokeStyle": "dotted",
"strokeWidth": 2, "strokeWidth": 2,
"type": "rectangle", "type": "rectangle",
"updated": 1, "updated": 1,
"version": 9, "version": 9,
"versionNonce": 908564423, "versionNonce": 941653321,
"width": 20, "width": 20,
"x": 20, "x": 20,
"y": 30, "y": 30,
@@ -3732,14 +3732,14 @@ exports[`contextMenu element > selecting 'Send backward' in context menu sends e
"opacity": 100, "opacity": 100,
"roughness": 1, "roughness": 1,
"roundness": null, "roundness": null,
"seed": 400692809, "seed": 238820263,
"strokeColor": "#1e1e1e", "strokeColor": "#1e1e1e",
"strokeStyle": "solid", "strokeStyle": "solid",
"strokeWidth": 2, "strokeWidth": 2,
"type": "rectangle", "type": "rectangle",
"updated": 1, "updated": 1,
"version": 4, "version": 4,
"versionNonce": 81784553, "versionNonce": 915032327,
"width": 20, "width": 20,
"x": 20, "x": 20,
"y": 30, "y": 30,
@@ -3764,14 +3764,14 @@ exports[`contextMenu element > selecting 'Send backward' in context menu sends e
"opacity": 100, "opacity": 100,
"roughness": 1, "roughness": 1,
"roundness": null, "roundness": null,
"seed": 449462985, "seed": 1278240551,
"strokeColor": "#1e1e1e", "strokeColor": "#1e1e1e",
"strokeStyle": "solid", "strokeStyle": "solid",
"strokeWidth": 2, "strokeWidth": 2,
"type": "rectangle", "type": "rectangle",
"updated": 1, "updated": 1,
"version": 3, "version": 3,
"versionNonce": 1150084233, "versionNonce": 2019559783,
"width": 20, "width": 20,
"x": -10, "x": -10,
"y": 0, "y": 0,
@@ -4058,14 +4058,14 @@ exports[`contextMenu element > selecting 'Send to back' in context menu sends el
"opacity": 100, "opacity": 100,
"roughness": 1, "roughness": 1,
"roundness": null, "roundness": null,
"seed": 238820263, "seed": 1014066025,
"strokeColor": "#1e1e1e", "strokeColor": "#1e1e1e",
"strokeStyle": "solid", "strokeStyle": "solid",
"strokeWidth": 2, "strokeWidth": 2,
"type": "rectangle", "type": "rectangle",
"updated": 1, "updated": 1,
"version": 4, "version": 4,
"versionNonce": 915032327, "versionNonce": 493213705,
"width": 20, "width": 20,
"x": 20, "x": 20,
"y": 30, "y": 30,
@@ -4090,14 +4090,14 @@ exports[`contextMenu element > selecting 'Send to back' in context menu sends el
"opacity": 100, "opacity": 100,
"roughness": 1, "roughness": 1,
"roundness": null, "roundness": null,
"seed": 449462985, "seed": 1278240551,
"strokeColor": "#1e1e1e", "strokeColor": "#1e1e1e",
"strokeStyle": "solid", "strokeStyle": "solid",
"strokeWidth": 2, "strokeWidth": 2,
"type": "rectangle", "type": "rectangle",
"updated": 1, "updated": 1,
"version": 3, "version": 3,
"versionNonce": 1150084233, "versionNonce": 2019559783,
"width": 20, "width": 20,
"x": -10, "x": -10,
"y": 0, "y": 0,
@@ -4387,14 +4387,14 @@ exports[`contextMenu element > selecting 'Ungroup selection' in context menu ung
"opacity": 100, "opacity": 100,
"roughness": 1, "roughness": 1,
"roundness": null, "roundness": null,
"seed": 449462985, "seed": 1278240551,
"strokeColor": "#1e1e1e", "strokeColor": "#1e1e1e",
"strokeStyle": "solid", "strokeStyle": "solid",
"strokeWidth": 2, "strokeWidth": 2,
"type": "rectangle", "type": "rectangle",
"updated": 1, "updated": 1,
"version": 5, "version": 5,
"versionNonce": 1006504105, "versionNonce": 760410951,
"width": 20, "width": 20,
"x": -10, "x": -10,
"y": 0, "y": 0,
@@ -4419,14 +4419,14 @@ exports[`contextMenu element > selecting 'Ungroup selection' in context menu ung
"opacity": 100, "opacity": 100,
"roughness": 1, "roughness": 1,
"roundness": null, "roundness": null,
"seed": 400692809, "seed": 238820263,
"strokeColor": "#1e1e1e", "strokeColor": "#1e1e1e",
"strokeStyle": "solid", "strokeStyle": "solid",
"strokeWidth": 2, "strokeWidth": 2,
"type": "rectangle", "type": "rectangle",
"updated": 1, "updated": 1,
"version": 5, "version": 5,
"versionNonce": 289600103, "versionNonce": 1006504105,
"width": 20, "width": 20,
"x": 20, "x": 20,
"y": 30, "y": 30,
@@ -5675,14 +5675,14 @@ exports[`contextMenu element > shows 'Group selection' in context menu for multi
"opacity": 100, "opacity": 100,
"roughness": 1, "roughness": 1,
"roundness": null, "roundness": null,
"seed": 453191, "seed": 1278240551,
"strokeColor": "#1e1e1e", "strokeColor": "#1e1e1e",
"strokeStyle": "solid", "strokeStyle": "solid",
"strokeWidth": 2, "strokeWidth": 2,
"type": "rectangle", "type": "rectangle",
"updated": 1, "updated": 1,
"version": 3, "version": 3,
"versionNonce": 1014066025, "versionNonce": 1150084233,
"width": 10, "width": 10,
"x": -10, "x": -10,
"y": 0, "y": 0,
@@ -5707,14 +5707,14 @@ exports[`contextMenu element > shows 'Group selection' in context menu for multi
"opacity": 100, "opacity": 100,
"roughness": 1, "roughness": 1,
"roundness": null, "roundness": null,
"seed": 1505387817, "seed": 400692809,
"strokeColor": "#1e1e1e", "strokeColor": "#1e1e1e",
"strokeStyle": "solid", "strokeStyle": "solid",
"strokeWidth": 2, "strokeWidth": 2,
"type": "rectangle", "type": "rectangle",
"updated": 1, "updated": 1,
"version": 3, "version": 3,
"versionNonce": 915032327, "versionNonce": 23633383,
"width": 10, "width": 10,
"x": 12, "x": 12,
"y": 0, "y": 0,
@@ -6899,14 +6899,14 @@ exports[`contextMenu element > shows 'Ungroup selection' in context menu for gro
"opacity": 100, "opacity": 100,
"roughness": 1, "roughness": 1,
"roundness": null, "roundness": null,
"seed": 449462985, "seed": 1278240551,
"strokeColor": "#1e1e1e", "strokeColor": "#1e1e1e",
"strokeStyle": "solid", "strokeStyle": "solid",
"strokeWidth": 2, "strokeWidth": 2,
"type": "rectangle", "type": "rectangle",
"updated": 1, "updated": 1,
"version": 4, "version": 4,
"versionNonce": 1723083209, "versionNonce": 747212839,
"width": 10, "width": 10,
"x": -10, "x": -10,
"y": 0, "y": 0,
@@ -6933,14 +6933,14 @@ exports[`contextMenu element > shows 'Ungroup selection' in context menu for gro
"opacity": 100, "opacity": 100,
"roughness": 1, "roughness": 1,
"roundness": null, "roundness": null,
"seed": 400692809, "seed": 238820263,
"strokeColor": "#1e1e1e", "strokeColor": "#1e1e1e",
"strokeStyle": "solid", "strokeStyle": "solid",
"strokeWidth": 2, "strokeWidth": 2,
"type": "rectangle", "type": "rectangle",
"updated": 1, "updated": 1,
"version": 4, "version": 4,
"versionNonce": 760410951, "versionNonce": 1723083209,
"width": 10, "width": 10,
"x": 12, "x": 12,
"y": 0, "y": 0,
@@ -9837,7 +9837,7 @@ exports[`contextMenu element > shows context menu for element > [end of test] el
"type": "rectangle", "type": "rectangle",
"updated": 1, "updated": 1,
"version": 3, "version": 3,
"versionNonce": 2019559783, "versionNonce": 401146281,
"width": 10, "width": 10,
"x": -20, "x": -20,
"y": -10, "y": -10,
@@ -13935,7 +13935,7 @@ exports[`regression tests > switches from group of selected elements to another
"opacity": 100, "opacity": 100,
"roughness": 1, "roughness": 1,
"roundness": null, "roundness": null,
"seed": 289600103, "seed": 1006504105,
"strokeColor": "#1e1e1e", "strokeColor": "#1e1e1e",
"strokeStyle": "solid", "strokeStyle": "solid",
"strokeWidth": 2, "strokeWidth": 2,
@@ -41,8 +41,8 @@ exports[`select single element on the scene > arrow 1`] = `
"strokeWidth": 2, "strokeWidth": 2,
"type": "arrow", "type": "arrow",
"updated": 1, "updated": 1,
"version": 4, "version": 5,
"versionNonce": 2019559783, "versionNonce": 1116226695,
"width": 30, "width": 30,
"x": 10, "x": 10,
"y": 10, "y": 10,
@@ -88,8 +88,8 @@ exports[`select single element on the scene > arrow escape 1`] = `
"strokeWidth": 2, "strokeWidth": 2,
"type": "line", "type": "line",
"updated": 1, "updated": 1,
"version": 4, "version": 5,
"versionNonce": 2019559783, "versionNonce": 1116226695,
"width": 30, "width": 30,
"x": 10, "x": 10,
"y": 10, "y": 10,
@@ -120,8 +120,8 @@ exports[`select single element on the scene > diamond 1`] = `
"strokeWidth": 2, "strokeWidth": 2,
"type": "diamond", "type": "diamond",
"updated": 1, "updated": 1,
"version": 3, "version": 4,
"versionNonce": 401146281, "versionNonce": 2019559783,
"width": 30, "width": 30,
"x": 10, "x": 10,
"y": 10, "y": 10,
@@ -152,8 +152,8 @@ exports[`select single element on the scene > ellipse 1`] = `
"strokeWidth": 2, "strokeWidth": 2,
"type": "ellipse", "type": "ellipse",
"updated": 1, "updated": 1,
"version": 3, "version": 4,
"versionNonce": 401146281, "versionNonce": 2019559783,
"width": 30, "width": 30,
"x": 10, "x": 10,
"y": 10, "y": 10,
@@ -184,8 +184,8 @@ exports[`select single element on the scene > rectangle 1`] = `
"strokeWidth": 2, "strokeWidth": 2,
"type": "rectangle", "type": "rectangle",
"updated": 1, "updated": 1,
"version": 3, "version": 4,
"versionNonce": 401146281, "versionNonce": 2019559783,
"width": 30, "width": 30,
"x": 10, "x": 10,
"y": 10, "y": 10,
+1 -1
View File
@@ -464,7 +464,7 @@ export class API {
static readFile = async <T extends "utf8" | null>( static readFile = async <T extends "utf8" | null>(
filepath: string, filepath: string,
encoding?: T, encoding?: T,
): Promise<T extends "utf8" ? string : Buffer> => { ): Promise<T extends "utf8" ? string : ArrayBuffer> => {
filepath = path.isAbsolute(filepath) filepath = path.isAbsolute(filepath)
? filepath ? filepath
: path.resolve(path.join(__dirname, "../", filepath)); : path.resolve(path.join(__dirname, "../", filepath));
@@ -315,6 +315,7 @@ describe("history", () => {
]); ]);
mouse.downAt(0, 0); mouse.downAt(0, 0);
mouse.moveTo(25, 25);
mouse.moveTo(50, 50); mouse.moveTo(50, 50);
mouse.upAt(50, 50); mouse.upAt(50, 50);
expect(API.getUndoStack().length).toBe(3); expect(API.getUndoStack().length).toBe(3);
@@ -467,6 +467,7 @@ describe("regression tests", () => {
mouse.reset(); mouse.reset();
mouse.down(); mouse.down();
mouse.move(-1000, -1000);
mouse.restorePosition(...end); mouse.restorePosition(...end);
mouse.up(); mouse.up();
@@ -517,6 +518,7 @@ describe("regression tests", () => {
mouse.reset(); mouse.reset();
mouse.down(); mouse.down();
mouse.move(-1000, -1000);
mouse.restorePosition(...end); mouse.restorePosition(...end);
mouse.up(); mouse.up();
@@ -534,6 +536,7 @@ describe("regression tests", () => {
mouse.moveTo(-10, -10); // the NW resizing handle is at [0, 0], so moving further mouse.moveTo(-10, -10); // the NW resizing handle is at [0, 0], so moving further
mouse.down(); mouse.down();
mouse.move(-1000, -1000);
mouse.restorePosition(...end); mouse.restorePosition(...end);
mouse.up(); mouse.up();
+20 -6
View File
@@ -65,6 +65,7 @@ describe("box-selection", () => {
API.setElements([rect1, rect2]); API.setElements([rect1, rect2]);
mouse.downAt(175, -20); mouse.downAt(175, -20);
mouse.move(-1000, -1000);
mouse.moveTo(85, 70); mouse.moveTo(85, 70);
mouse.up(); mouse.up();
@@ -72,6 +73,7 @@ describe("box-selection", () => {
Keyboard.withModifierKeys({ shift: true }, () => { Keyboard.withModifierKeys({ shift: true }, () => {
mouse.downAt(75, -20); mouse.downAt(75, -20);
mouse.move(-1000, -1000);
mouse.moveTo(-15, 70); mouse.moveTo(-15, 70);
mouse.up(); mouse.up();
}); });
@@ -93,6 +95,7 @@ describe("box-selection", () => {
API.setElements([rect1]); API.setElements([rect1]);
mouse.downAt(75, -20); mouse.downAt(75, -20);
mouse.move(-1000, -1000);
mouse.moveTo(-15, 70); mouse.moveTo(-15, 70);
assertSelectedElements([rect1.id]); assertSelectedElements([rect1.id]);
@@ -138,6 +141,7 @@ describe("inner box-selection", () => {
API.setElements([rect1, rect2, rect3]); API.setElements([rect1, rect2, rect3]);
Keyboard.withModifierKeys({ ctrl: true }, () => { Keyboard.withModifierKeys({ ctrl: true }, () => {
mouse.downAt(40, 40); mouse.downAt(40, 40);
mouse.move(-1000, -1000);
mouse.moveTo(290, 290); mouse.moveTo(290, 290);
mouse.up(); mouse.up();
@@ -175,6 +179,7 @@ describe("inner box-selection", () => {
Keyboard.withModifierKeys({ ctrl: true }, () => { Keyboard.withModifierKeys({ ctrl: true }, () => {
mouse.downAt(40, 40); mouse.downAt(40, 40);
mouse.move(-1000, -1000);
mouse.moveTo(rect2.x + rect2.width + 10, rect2.y + rect2.height + 10); mouse.moveTo(rect2.x + rect2.width + 10, rect2.y + rect2.height + 10);
mouse.up(); mouse.up();
@@ -212,6 +217,7 @@ describe("inner box-selection", () => {
API.setElements([rect1, rect2, rect3]); API.setElements([rect1, rect2, rect3]);
Keyboard.withModifierKeys({ ctrl: true }, () => { Keyboard.withModifierKeys({ ctrl: true }, () => {
mouse.downAt(rect2.x - 20, rect2.y - 20); mouse.downAt(rect2.x - 20, rect2.y - 20);
mouse.move(-1000, -1000);
mouse.moveTo(rect2.x + rect2.width + 10, rect2.y + rect2.height + 10); mouse.moveTo(rect2.x + rect2.width + 10, rect2.y + rect2.height + 10);
assertSelectedElements([rect2.id, rect3.id]); assertSelectedElements([rect2.id, rect3.id]);
expect(h.state.selectedGroupIds).toEqual({ A: true }); expect(h.state.selectedGroupIds).toEqual({ A: true });
@@ -253,9 +259,10 @@ describe("selection element", () => {
const canvas = container.querySelector("canvas.interactive")!; const canvas = container.querySelector("canvas.interactive")!;
fireEvent.pointerDown(canvas, { clientX: 60, clientY: 100 }); fireEvent.pointerDown(canvas, { clientX: 60, clientY: 100 });
fireEvent.pointerMove(canvas, { clientX: -1000, clientY: -1000 });
fireEvent.pointerMove(canvas, { clientX: 150, clientY: 30 }); fireEvent.pointerMove(canvas, { clientX: 150, clientY: 30 });
expect(renderInteractiveScene).toHaveBeenCalledTimes(4); expect(renderInteractiveScene).toHaveBeenCalledTimes(5);
expect(renderStaticScene).toHaveBeenCalledTimes(3); expect(renderStaticScene).toHaveBeenCalledTimes(3);
const selectionElement = h.state.selectionElement!; const selectionElement = h.state.selectionElement!;
expect(selectionElement).not.toBeNull(); expect(selectionElement).not.toBeNull();
@@ -275,10 +282,11 @@ describe("selection element", () => {
const canvas = container.querySelector("canvas.interactive")!; const canvas = container.querySelector("canvas.interactive")!;
fireEvent.pointerDown(canvas, { clientX: 60, clientY: 100 }); fireEvent.pointerDown(canvas, { clientX: 60, clientY: 100 });
fireEvent.pointerMove(canvas, { clientX: -1000, clientY: -1000 });
fireEvent.pointerMove(canvas, { clientX: 150, clientY: 30 }); fireEvent.pointerMove(canvas, { clientX: 150, clientY: 30 });
fireEvent.pointerUp(canvas); fireEvent.pointerUp(canvas);
expect(renderInteractiveScene).toHaveBeenCalledTimes(5); expect(renderInteractiveScene).toHaveBeenCalledTimes(6);
expect(renderStaticScene).toHaveBeenCalledTimes(3); expect(renderStaticScene).toHaveBeenCalledTimes(3);
expect(h.state.selectionElement).toBeNull(); expect(h.state.selectionElement).toBeNull();
}); });
@@ -303,6 +311,7 @@ describe("select single element on the scene", () => {
const tool = getByToolName("rectangle"); const tool = getByToolName("rectangle");
fireEvent.click(tool); fireEvent.click(tool);
fireEvent.pointerDown(canvas, { clientX: 30, clientY: 20 }); fireEvent.pointerDown(canvas, { clientX: 30, clientY: 20 });
fireEvent.pointerMove(canvas, { clientX: -1000, clientY: -1000 });
fireEvent.pointerMove(canvas, { clientX: 60, clientY: 70 }); fireEvent.pointerMove(canvas, { clientX: 60, clientY: 70 });
fireEvent.pointerUp(canvas); fireEvent.pointerUp(canvas);
fireEvent.keyDown(document, { fireEvent.keyDown(document, {
@@ -335,6 +344,7 @@ describe("select single element on the scene", () => {
const tool = getByToolName("diamond"); const tool = getByToolName("diamond");
fireEvent.click(tool); fireEvent.click(tool);
fireEvent.pointerDown(canvas, { clientX: 30, clientY: 20 }); fireEvent.pointerDown(canvas, { clientX: 30, clientY: 20 });
fireEvent.pointerMove(canvas, { clientX: -1000, clientY: -1000 });
fireEvent.pointerMove(canvas, { clientX: 60, clientY: 70 }); fireEvent.pointerMove(canvas, { clientX: 60, clientY: 70 });
fireEvent.pointerUp(canvas); fireEvent.pointerUp(canvas);
fireEvent.keyDown(document, { fireEvent.keyDown(document, {
@@ -367,6 +377,7 @@ describe("select single element on the scene", () => {
const tool = getByToolName("ellipse"); const tool = getByToolName("ellipse");
fireEvent.click(tool); fireEvent.click(tool);
fireEvent.pointerDown(canvas, { clientX: 30, clientY: 20 }); fireEvent.pointerDown(canvas, { clientX: 30, clientY: 20 });
fireEvent.pointerMove(canvas, { clientX: -1000, clientY: -1000 });
fireEvent.pointerMove(canvas, { clientX: 60, clientY: 70 }); fireEvent.pointerMove(canvas, { clientX: 60, clientY: 70 });
fireEvent.pointerUp(canvas); fireEvent.pointerUp(canvas);
fireEvent.keyDown(document, { fireEvent.keyDown(document, {
@@ -399,6 +410,7 @@ describe("select single element on the scene", () => {
const tool = getByToolName("arrow"); const tool = getByToolName("arrow");
fireEvent.click(tool); fireEvent.click(tool);
fireEvent.pointerDown(canvas, { clientX: 30, clientY: 20 }); fireEvent.pointerDown(canvas, { clientX: 30, clientY: 20 });
fireEvent.pointerMove(canvas, { clientX: -1000, clientY: -1000 });
fireEvent.pointerMove(canvas, { clientX: 60, clientY: 70 }); fireEvent.pointerMove(canvas, { clientX: 60, clientY: 70 });
fireEvent.pointerUp(canvas); fireEvent.pointerUp(canvas);
fireEvent.keyDown(document, { fireEvent.keyDown(document, {
@@ -425,8 +437,8 @@ describe("select single element on the scene", () => {
fireEvent.pointerDown(canvas, { clientX: 40, clientY: 40 }); fireEvent.pointerDown(canvas, { clientX: 40, clientY: 40 });
fireEvent.pointerUp(canvas); fireEvent.pointerUp(canvas);
expect(renderInteractiveScene).toHaveBeenCalledTimes(9); expect(renderInteractiveScene).toHaveBeenCalledTimes(10);
expect(renderStaticScene).toHaveBeenCalledTimes(7); expect(renderStaticScene).toHaveBeenCalledTimes(8);
expect(h.state.selectionElement).toBeNull(); expect(h.state.selectionElement).toBeNull();
expect(h.elements.length).toEqual(1); expect(h.elements.length).toEqual(1);
expect(h.state.selectedElementIds[h.elements[0].id]).toBeTruthy(); expect(h.state.selectedElementIds[h.elements[0].id]).toBeTruthy();
@@ -443,6 +455,7 @@ describe("select single element on the scene", () => {
const tool = getByToolName("line"); const tool = getByToolName("line");
fireEvent.click(tool); fireEvent.click(tool);
fireEvent.pointerDown(canvas, { clientX: 30, clientY: 20 }); fireEvent.pointerDown(canvas, { clientX: 30, clientY: 20 });
fireEvent.pointerMove(canvas, { clientX: -1000, clientY: -1000 });
fireEvent.pointerMove(canvas, { clientX: 60, clientY: 70 }); fireEvent.pointerMove(canvas, { clientX: 60, clientY: 70 });
fireEvent.pointerUp(canvas); fireEvent.pointerUp(canvas);
fireEvent.keyDown(document, { fireEvent.keyDown(document, {
@@ -469,8 +482,8 @@ describe("select single element on the scene", () => {
fireEvent.pointerDown(canvas, { clientX: 40, clientY: 40 }); fireEvent.pointerDown(canvas, { clientX: 40, clientY: 40 });
fireEvent.pointerUp(canvas); fireEvent.pointerUp(canvas);
expect(renderInteractiveScene).toHaveBeenCalledTimes(9); expect(renderInteractiveScene).toHaveBeenCalledTimes(10);
expect(renderStaticScene).toHaveBeenCalledTimes(7); expect(renderStaticScene).toHaveBeenCalledTimes(8);
expect(h.state.selectionElement).toBeNull(); expect(h.state.selectionElement).toBeNull();
expect(h.elements.length).toEqual(1); expect(h.elements.length).toEqual(1);
expect(h.state.selectedElementIds[h.elements[0].id]).toBeTruthy(); expect(h.state.selectedElementIds[h.elements[0].id]).toBeTruthy();
@@ -525,6 +538,7 @@ describe("selectedElementIds stability", () => {
expect(h.state.selectedElementIds).toBe(selectedElementIds_1); expect(h.state.selectedElementIds).toBe(selectedElementIds_1);
mouse.downAt(-50, -50); mouse.downAt(-50, -50);
mouse.move(-1000, -1000);
mouse.moveTo(50, 50); mouse.moveTo(50, 50);
const selectedElementIds_2 = h.state.selectedElementIds; const selectedElementIds_2 = h.state.selectedElementIds;
+1 -1
View File
@@ -62,7 +62,7 @@
"devDependencies": { "devDependencies": {
"cross-env": "7.0.3", "cross-env": "7.0.3",
"fonteditor-core": "2.4.0", "fonteditor-core": "2.4.0",
"typescript": "4.9.4", "typescript": "5.9.3",
"wawoff2": "2.0.1", "wawoff2": "2.0.1",
"which": "4.0.0" "which": "4.0.0"
}, },
+9 -4
View File
@@ -6398,6 +6398,11 @@ is-map@^2.0.3:
resolved "https://registry.yarnpkg.com/is-map/-/is-map-2.0.3.tgz#ede96b7fe1e270b3c4465e3a465658764926d62e" resolved "https://registry.yarnpkg.com/is-map/-/is-map-2.0.3.tgz#ede96b7fe1e270b3c4465e3a465658764926d62e"
integrity sha512-1Qed0/Hr2m+YqxnM09CjA2d/i6YZNfF6R2oRAOj36eUdS6qIV/huPJNSEpKbupewFs+ZsJlxsjjPbc0/afW6Lw== integrity sha512-1Qed0/Hr2m+YqxnM09CjA2d/i6YZNfF6R2oRAOj36eUdS6qIV/huPJNSEpKbupewFs+ZsJlxsjjPbc0/afW6Lw==
is-mobile@5.0.0:
version "5.0.0"
resolved "https://registry.yarnpkg.com/is-mobile/-/is-mobile-5.0.0.tgz#1e08a0ef2c38a67bff84a52af68d67bcef445333"
integrity sha512-Tz/yndySvLAEXh+Uk8liFCxOwVH6YutuR74utvOcu7I9Di+DwM0mtdPVZNaVvvBUM2OXxne/NhOs1zAO7riusQ==
is-module@^1.0.0: is-module@^1.0.0:
version "1.0.0" version "1.0.0"
resolved "https://registry.yarnpkg.com/is-module/-/is-module-1.0.0.tgz#3258fb69f78c14d5b815d664336b4cffb6441591" resolved "https://registry.yarnpkg.com/is-module/-/is-module-1.0.0.tgz#3258fb69f78c14d5b815d664336b4cffb6441591"
@@ -9290,10 +9295,10 @@ typed-array-length@^1.0.7:
possible-typed-array-names "^1.0.0" possible-typed-array-names "^1.0.0"
reflect.getprototypeof "^1.0.6" reflect.getprototypeof "^1.0.6"
typescript@4.9.4: typescript@5.9.3:
version "4.9.4" version "5.9.3"
resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.9.4.tgz#a2a3d2756c079abda241d75f149df9d561091e78" resolved "https://registry.yarnpkg.com/typescript/-/typescript-5.9.3.tgz#5b4f59e15310ab17a216f5d6cf53ee476ede670f"
integrity sha512-Uz+dTXYzxXXbsFpM86Wh3dKCxrQqUcVMxwU54orwlJjOpO3ao8L7j5lH+dWfTwgCwIuM9GQ2kvVotzYJMXTBZg== integrity sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==
typescript@^5: typescript@^5:
version "5.8.2" version "5.8.2"