From d52d91b36777d1cf81a23650b3ae4f9c4d3f27ba Mon Sep 17 00:00:00 2001 From: Steve Ruiz Date: Thu, 9 Jun 2022 16:00:47 +0100 Subject: [PATCH] Enforce readonly mode (#714) * Enforce readonly mode * Fix test for React 18 * Move to dev --- packages/tldraw/package.json | 5 +- packages/tldraw/src/Tldraw.tsx | 5 + packages/tldraw/src/state/TldrawApp.ts | 4 + .../src/state/tools/DrawTool/DrawTool.ts | 5 +- .../state/tools/EllipseTool/EllipseTool.ts | 1 + .../src/state/tools/EraseTool/EraseTool.ts | 3 + .../src/state/tools/LineTool/LineTool.ts | 1 + .../tools/RectangleTool/RectangleTool.ts | 1 + .../src/state/tools/SelectTool/SelectTool.ts | 42 +++--- .../src/state/tools/StickyTool/StickyTool.ts | 2 + .../src/state/tools/TextTool/TextTool.ts | 2 + .../state/tools/TriangleTool/TriangleTool.ts | 1 + yarn.lock | 129 +++++++++++++++++- 13 files changed, 179 insertions(+), 22 deletions(-) diff --git a/packages/tldraw/package.json b/packages/tldraw/package.json index e3b405eec..4d1dd7364 100644 --- a/packages/tldraw/package.json +++ b/packages/tldraw/package.json @@ -47,6 +47,7 @@ "@radix-ui/react-icons": "^1.1.1", "@radix-ui/react-tooltip": "^0.1.7", "@stitches/react": "^1.2.8", + "@testing-library/react": "^13.3.0", "@tldraw/core": "^1.14.0-next.0", "@tldraw/intersect": "^1.7.1", "@tldraw/vec": "^1.7.0", @@ -61,7 +62,7 @@ }, "devDependencies": { "@swc-node/jest": "^1.4.3", - "@testing-library/jest-dom": "^5.16.2", + "@testing-library/jest-dom": "^5.16.4", "@testing-library/react": "^12.1.2", "@tldraw/core": "*", "@tldraw/intersect": "*", @@ -105,4 +106,4 @@ } }, "gitHead": "4b1137849ad07da36fc8f0f19cb64e7535a79296" -} \ No newline at end of file +} diff --git a/packages/tldraw/src/Tldraw.tsx b/packages/tldraw/src/Tldraw.tsx index 646973771..7ae1e4615 100644 --- a/packages/tldraw/src/Tldraw.tsx +++ b/packages/tldraw/src/Tldraw.tsx @@ -223,6 +223,11 @@ export function Tldraw({ // Toggle the app's readOnly mode when the `readOnly` prop changes. React.useEffect(() => { app.readOnly = readOnly + if (!readOnly) { + app.selectNone() + app.cancelSession() + app.setEditingId() + } }, [app, readOnly]) // Toggle the app's darkMode when the `darkMode` prop changes. diff --git a/packages/tldraw/src/state/TldrawApp.ts b/packages/tldraw/src/state/TldrawApp.ts index f8976b8d7..d30046392 100644 --- a/packages/tldraw/src/state/TldrawApp.ts +++ b/packages/tldraw/src/state/TldrawApp.ts @@ -1758,9 +1758,11 @@ export class TldrawApp extends StateManager { e?.preventDefault() this.copy(ids, e) + if (!this.readOnly) { this.delete(ids) } + return this } @@ -1769,6 +1771,8 @@ export class TldrawApp extends StateManager { * @param ids The ids of the shapes to copy. */ copy = (ids = this.selectedIds, e?: ClipboardEvent): this => { + // Allow when in readOnly mode + e?.preventDefault() this.clipboard = this.getClipboard(ids) diff --git a/packages/tldraw/src/state/tools/DrawTool/DrawTool.ts b/packages/tldraw/src/state/tools/DrawTool/DrawTool.ts index 30af4d22f..4d5771822 100644 --- a/packages/tldraw/src/state/tools/DrawTool/DrawTool.ts +++ b/packages/tldraw/src/state/tools/DrawTool/DrawTool.ts @@ -36,8 +36,9 @@ export class DrawTool extends BaseTool { /* ----------------- Event Handlers ----------------- */ - onPointerDown: TLPointerEventHandler = (info) => { + onPointerDown: TLPointerEventHandler = info => { if (this.status !== Status.Idle) return + if (this.app.readOnly) return const { currentPoint, appState: { currentPageId, currentStyle }, @@ -66,6 +67,8 @@ export class DrawTool extends BaseTool { } onPointerMove: TLPointerEventHandler = () => { + if (this.app.readOnly) return + switch (this.status) { case Status.Extending: case Status.Creating: { diff --git a/packages/tldraw/src/state/tools/EllipseTool/EllipseTool.ts b/packages/tldraw/src/state/tools/EllipseTool/EllipseTool.ts index bca039543..8a8f2a8bd 100644 --- a/packages/tldraw/src/state/tools/EllipseTool/EllipseTool.ts +++ b/packages/tldraw/src/state/tools/EllipseTool/EllipseTool.ts @@ -10,6 +10,7 @@ export class EllipseTool extends BaseTool { /* ----------------- Event Handlers ----------------- */ onPointerDown: TLPointerEventHandler = () => { + if (this.app.readOnly) return if (this.status !== Status.Idle) return const { diff --git a/packages/tldraw/src/state/tools/EraseTool/EraseTool.ts b/packages/tldraw/src/state/tools/EraseTool/EraseTool.ts index 541532d87..e5d710420 100644 --- a/packages/tldraw/src/state/tools/EraseTool/EraseTool.ts +++ b/packages/tldraw/src/state/tools/EraseTool/EraseTool.ts @@ -18,12 +18,14 @@ export class EraseTool extends BaseTool { /* ----------------- Event Handlers ----------------- */ onPointerDown: TLPointerEventHandler = () => { + if (this.app.readOnly) return if (this.status !== Status.Idle) return this.setStatus(Status.Pointing) } onPointerMove: TLPointerEventHandler = (info) => { + if (this.app.readOnly) return switch (this.status) { case Status.Pointing: { if (Vec.dist(info.origin, info.point) > DEAD_ZONE) { @@ -40,6 +42,7 @@ export class EraseTool extends BaseTool { } onPointerUp: TLPointerEventHandler = () => { + if (this.app.readOnly) return switch (this.status) { case Status.Pointing: { const shapeIdsAtPoint = this.app.shapes diff --git a/packages/tldraw/src/state/tools/LineTool/LineTool.ts b/packages/tldraw/src/state/tools/LineTool/LineTool.ts index 2a74b3399..a7c8087dd 100644 --- a/packages/tldraw/src/state/tools/LineTool/LineTool.ts +++ b/packages/tldraw/src/state/tools/LineTool/LineTool.ts @@ -10,6 +10,7 @@ export class LineTool extends BaseTool { /* ----------------- Event Handlers ----------------- */ onPointerDown: TLPointerEventHandler = () => { + if (this.app.readOnly) return if (this.status !== Status.Idle) return const { diff --git a/packages/tldraw/src/state/tools/RectangleTool/RectangleTool.ts b/packages/tldraw/src/state/tools/RectangleTool/RectangleTool.ts index a28d07eb4..c366d56f0 100644 --- a/packages/tldraw/src/state/tools/RectangleTool/RectangleTool.ts +++ b/packages/tldraw/src/state/tools/RectangleTool/RectangleTool.ts @@ -10,6 +10,7 @@ export class RectangleTool extends BaseTool { /* ----------------- Event Handlers ----------------- */ onPointerDown: TLPointerEventHandler = () => { + if (this.app.readOnly) return if (this.status !== Status.Idle) return const { diff --git a/packages/tldraw/src/state/tools/SelectTool/SelectTool.ts b/packages/tldraw/src/state/tools/SelectTool/SelectTool.ts index 687f8b16b..f9f3dc59f 100644 --- a/packages/tldraw/src/state/tools/SelectTool/SelectTool.ts +++ b/packages/tldraw/src/state/tools/SelectTool/SelectTool.ts @@ -50,7 +50,7 @@ export class SelectTool extends BaseTool { /* --------------------- Methods -------------------- */ private deselect(id: string) { - this.app.select(...this.app.selectedIds.filter((oid) => oid !== id)) + this.app.select(...this.app.selectedIds.filter(oid => oid !== id)) } private select(id: string) { @@ -59,7 +59,7 @@ export class SelectTool extends BaseTool { private pushSelect(id: string) { const shape = this.app.getShape(id) - this.app.select(...this.app.selectedIds.filter((oid) => oid !== shape.parentId), id) + this.app.select(...this.app.selectedIds.filter(oid => oid !== shape.parentId), id) } private selectNone() { @@ -77,7 +77,7 @@ export class SelectTool extends BaseTool { clonePaint = (point: number[]) => { if (this.app.selectedIds.length === 0) return - const shapes = this.app.selectedIds.map((id) => this.app.getShape(id)) + const shapes = this.app.selectedIds.map(id => this.app.getShape(id)) const bounds = Utils.expandBounds(Utils.getCommonBounds(shapes.map(TLDR.getBounds)), 16) @@ -92,7 +92,7 @@ export class SelectTool extends BaseTool { const centeredBounds = Utils.centerBounds(bounds, gridPoint) - const hit = this.app.shapes.some((shape) => + const hit = this.app.shapes.some(shape => TLDR.getShapeUtil(shape).hitTestBounds(shape, centeredBounds) ) @@ -187,6 +187,8 @@ export class SelectTool extends BaseTool { break } case 'Tab': { + if (this.app.readOnly) return + if ( !this.app.pageState.editingId && this.status === Status.Idle && @@ -213,6 +215,8 @@ export class SelectTool extends BaseTool { break } case 'Enter': { + if (this.app.readOnly) return + const { pageState } = this.app if (pageState.selectedIds.length === 1 && !pageState.editingId) { this.app.setEditingId(pageState.selectedIds[0]) @@ -239,7 +243,8 @@ export class SelectTool extends BaseTool { // Pointer Events (generic) - onPointerMove: TLPointerEventHandler = (info, e) => { + onPointerMove: TLPointerEventHandler = () => { + if (this.app.readOnly) return const { originPoint, currentPoint } = this.app switch (this.status) { @@ -260,7 +265,7 @@ export class SelectTool extends BaseTool { } else { // Stat a transform session this.setStatus(Status.Transforming) - const idsToTransform = this.app.selectedIds.flatMap((id) => + const idsToTransform = this.app.selectedIds.flatMap(id => TLDR.getDocumentBranch(this.app.state, id, this.app.currentPageId) ) if (idsToTransform.length === 1) { @@ -367,7 +372,7 @@ export class SelectTool extends BaseTool { } } - onPointerUp: TLPointerEventHandler = (info) => { + onPointerUp: TLPointerEventHandler = info => { if (this.status === Status.TranslatingClone || this.status === Status.PointingClone) { if (this.pointedId) { this.app.completeSession() @@ -420,6 +425,7 @@ export class SelectTool extends BaseTool { // Canvas onDoubleClickCanvas: TLCanvasEventHandler = () => { + if (this.app.readOnly) return // Needs debugging // const { currentPoint } = this.app // this.app.selectTool(TDShapeType.Text) @@ -523,7 +529,9 @@ export class SelectTool extends BaseTool { } } - onDoubleClickShape: TLPointerEventHandler = (info) => { + onDoubleClickShape: TLPointerEventHandler = info => { + if (this.app.readOnly) return + const shape = this.app.getShape(info.target) if (shape.isLocked) { @@ -548,17 +556,17 @@ export class SelectTool extends BaseTool { this.app.select(info.target) } - onRightPointShape: TLPointerEventHandler = (info) => { + onRightPointShape: TLPointerEventHandler = info => { if (!this.app.isSelected(info.target)) { this.app.select(info.target) } } - onHoverShape: TLPointerEventHandler = (info) => { + onHoverShape: TLPointerEventHandler = info => { this.app.setHoveredId(info.target) } - onUnhoverShape: TLPointerEventHandler = (info) => { + onUnhoverShape: TLPointerEventHandler = info => { const { currentPageId: oldCurrentPageId } = this.app // Wait a frame; and if we haven't changed the hovered id, @@ -575,7 +583,7 @@ export class SelectTool extends BaseTool { /* --------------------- Bounds --------------------- */ - onPointBounds: TLBoundsEventHandler = (info) => { + onPointBounds: TLBoundsEventHandler = info => { if (info.metaKey) { if (!info.shiftKey) { this.selectNone() @@ -604,12 +612,12 @@ export class SelectTool extends BaseTool { /* ----------------- Bounds Handles ----------------- */ - onPointBoundsHandle: TLBoundsHandleEventHandler = (info) => { + onPointBoundsHandle: TLBoundsHandleEventHandler = info => { this.pointedBoundsHandle = info.target this.setStatus(Status.PointingBoundsHandle) } - onDoubleClickBoundsHandle: TLBoundsHandleEventHandler = (info) => { + onDoubleClickBoundsHandle: TLBoundsHandleEventHandler = info => { switch (info.target) { case 'center': case 'left': @@ -642,12 +650,12 @@ export class SelectTool extends BaseTool { /* --------------------- Handles -------------------- */ - onPointHandle: TLPointerEventHandler = (info) => { + onPointHandle: TLPointerEventHandler = info => { this.pointedHandleId = info.target as 'start' | 'end' this.setStatus(Status.PointingHandle) } - onDoubleClickHandle: TLPointerEventHandler = (info) => { + onDoubleClickHandle: TLPointerEventHandler = info => { if (info.target === 'bend') { const { selectedIds } = this.app if (selectedIds.length !== 1) return @@ -670,7 +678,7 @@ export class SelectTool extends BaseTool { /* ---------------------- Misc ---------------------- */ - onShapeClone: TLShapeCloneHandler = (info) => { + onShapeClone: TLShapeCloneHandler = info => { const selectedShapeId = this.app.selectedIds[0] const clonedShape = this.getShapeClone(selectedShapeId, info.target) diff --git a/packages/tldraw/src/state/tools/StickyTool/StickyTool.ts b/packages/tldraw/src/state/tools/StickyTool/StickyTool.ts index ac6cd9490..b84ed3f6b 100644 --- a/packages/tldraw/src/state/tools/StickyTool/StickyTool.ts +++ b/packages/tldraw/src/state/tools/StickyTool/StickyTool.ts @@ -13,6 +13,7 @@ export class StickyTool extends BaseTool { /* ----------------- Event Handlers ----------------- */ onPointerDown: TLPointerEventHandler = () => { + if (this.app.readOnly) return if (this.status === Status.Creating) { this.setStatus(Status.Idle) @@ -58,6 +59,7 @@ export class StickyTool extends BaseTool { } onPointerUp: TLPointerEventHandler = () => { + if (this.app.readOnly) return if (this.status === Status.Creating) { this.setStatus(Status.Idle) this.app.completeSession() diff --git a/packages/tldraw/src/state/tools/TextTool/TextTool.ts b/packages/tldraw/src/state/tools/TextTool/TextTool.ts index 30a0a300b..b5739a04e 100644 --- a/packages/tldraw/src/state/tools/TextTool/TextTool.ts +++ b/packages/tldraw/src/state/tools/TextTool/TextTool.ts @@ -51,6 +51,7 @@ export class TextTool extends BaseTool { } onPointShape: TLPointerEventHandler = (info) => { + if (this.app.readOnly) return const shape = this.app.getShape(info.target) if (shape.type === TDShapeType.Text) { this.setStatus(Status.Idle) @@ -59,6 +60,7 @@ export class TextTool extends BaseTool { } onShapeBlur = () => { + if (this.app.readOnly) return this.stopEditingShape() } } diff --git a/packages/tldraw/src/state/tools/TriangleTool/TriangleTool.ts b/packages/tldraw/src/state/tools/TriangleTool/TriangleTool.ts index 4a33329c6..53794df02 100644 --- a/packages/tldraw/src/state/tools/TriangleTool/TriangleTool.ts +++ b/packages/tldraw/src/state/tools/TriangleTool/TriangleTool.ts @@ -10,6 +10,7 @@ export class TriangleTool extends BaseTool { /* ----------------- Event Handlers ----------------- */ onPointerDown: TLPointerEventHandler = () => { + if (this.app.readOnly) return if (this.status !== Status.Idle) return const { diff --git a/yarn.lock b/yarn.lock index 3fa5bcf2f..995a5e38e 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2193,6 +2193,22 @@ "@babel/runtime" "^7.13.10" "@radix-ui/react-primitive" "0.1.4" +"@radix-ui/react-checkbox@^0.1.5": + version "0.1.5" + resolved "https://registry.yarnpkg.com/@radix-ui/react-checkbox/-/react-checkbox-0.1.5.tgz#3a6bd54ba1720c8e5c03852acf460e35dfbe9da3" + integrity sha512-M8Y4dSXsKSbF+FryG5VvZKr/1MukMVG7swq9p5s7wYb8Rvn0UM0rQ5w8BWmSWSV4BL/gbJdhwVCznwXXlgZRZg== + dependencies: + "@babel/runtime" "^7.13.10" + "@radix-ui/primitive" "0.1.0" + "@radix-ui/react-compose-refs" "0.1.0" + "@radix-ui/react-context" "0.1.1" + "@radix-ui/react-label" "0.1.5" + "@radix-ui/react-presence" "0.1.2" + "@radix-ui/react-primitive" "0.1.4" + "@radix-ui/react-use-controllable-state" "0.1.0" + "@radix-ui/react-use-previous" "0.1.1" + "@radix-ui/react-use-size" "0.1.1" + "@radix-ui/react-collection@0.1.4": version "0.1.4" resolved "https://registry.yarnpkg.com/@radix-ui/react-collection/-/react-collection-0.1.4.tgz#734061ffd5bb93e88889d49b87391a73a63824c9" @@ -2308,6 +2324,17 @@ "@babel/runtime" "^7.13.10" "@radix-ui/react-use-layout-effect" "0.1.0" +"@radix-ui/react-label@0.1.5": + version "0.1.5" + resolved "https://registry.yarnpkg.com/@radix-ui/react-label/-/react-label-0.1.5.tgz#12cd965bfc983e0148121d4c99fb8e27a917c45c" + integrity sha512-Au9+n4/DhvjR0IHhvZ1LPdx/OW+3CGDie30ZyCkbSHIuLp4/CV4oPPGBwJ1vY99Jog3zyQhsGww9MXj8O9Aj/A== + dependencies: + "@babel/runtime" "^7.13.10" + "@radix-ui/react-compose-refs" "0.1.0" + "@radix-ui/react-context" "0.1.1" + "@radix-ui/react-id" "0.1.5" + "@radix-ui/react-primitive" "0.1.4" + "@radix-ui/react-menu@0.1.6": version "0.1.6" resolved "https://registry.yarnpkg.com/@radix-ui/react-menu/-/react-menu-0.1.6.tgz#7f9521a10f6a9cd819b33b33d5ed9538d79b2e75" @@ -2373,6 +2400,23 @@ "@babel/runtime" "^7.13.10" "@radix-ui/react-slot" "0.1.2" +"@radix-ui/react-radio-group@^0.1.5": + version "0.1.5" + resolved "https://registry.yarnpkg.com/@radix-ui/react-radio-group/-/react-radio-group-0.1.5.tgz#ca8a676123a18b44804aff10af46129e2c2b37c3" + integrity sha512-ybgHsmh/V2crKvK6xZ56dpPul7b+vyxcq7obWqHbr5W6Ca11wdm0E7lS0i/Y6pgfIKYOWIARmZYDpRMEeRCPOw== + dependencies: + "@babel/runtime" "^7.13.10" + "@radix-ui/primitive" "0.1.0" + "@radix-ui/react-compose-refs" "0.1.0" + "@radix-ui/react-context" "0.1.1" + "@radix-ui/react-label" "0.1.5" + "@radix-ui/react-presence" "0.1.2" + "@radix-ui/react-primitive" "0.1.4" + "@radix-ui/react-roving-focus" "0.1.5" + "@radix-ui/react-use-controllable-state" "0.1.0" + "@radix-ui/react-use-previous" "0.1.1" + "@radix-ui/react-use-size" "0.1.1" + "@radix-ui/react-roving-focus@0.1.5": version "0.1.5" resolved "https://registry.yarnpkg.com/@radix-ui/react-roving-focus/-/react-roving-focus-0.1.5.tgz#cc48d17a36b56f253d54905b0fd60ee134cb97ee" @@ -2851,6 +2895,20 @@ lz-string "^1.4.4" pretty-format "^27.0.2" +"@testing-library/dom@^8.5.0": + version "8.13.0" + resolved "https://registry.yarnpkg.com/@testing-library/dom/-/dom-8.13.0.tgz#bc00bdd64c7d8b40841e27a70211399ad3af46f5" + integrity sha512-9VHgfIatKNXQNaZTtLnalIy0jNZzY35a4S3oi08YAt9Hv1VsfZ/DfA45lM8D/UhtHBGJ4/lGwp0PZkVndRkoOQ== + dependencies: + "@babel/code-frame" "^7.10.4" + "@babel/runtime" "^7.12.5" + "@types/aria-query" "^4.2.0" + aria-query "^5.0.0" + chalk "^4.1.0" + dom-accessibility-api "^0.5.9" + lz-string "^1.4.4" + pretty-format "^27.0.2" + "@testing-library/jest-dom@^5.16.2": version "5.16.2" resolved "https://registry.yarnpkg.com/@testing-library/jest-dom/-/jest-dom-5.16.2.tgz#f329b36b44aa6149cd6ced9adf567f8b6aa1c959" @@ -2866,6 +2924,21 @@ lodash "^4.17.15" redent "^3.0.0" +"@testing-library/jest-dom@^5.16.4": + version "5.16.4" + resolved "https://registry.yarnpkg.com/@testing-library/jest-dom/-/jest-dom-5.16.4.tgz#938302d7b8b483963a3ae821f1c0808f872245cd" + integrity sha512-Gy+IoFutbMQcky0k+bqqumXZ1cTGswLsFqmNLzNdSKkU9KGV2u9oXhukCbbJ9/LRPKiqwxEE8VpV/+YZlfkPUA== + dependencies: + "@babel/runtime" "^7.9.2" + "@types/testing-library__jest-dom" "^5.9.1" + aria-query "^5.0.0" + chalk "^3.0.0" + css "^3.0.0" + css.escape "^1.5.1" + dom-accessibility-api "^0.5.6" + lodash "^4.17.15" + redent "^3.0.0" + "@testing-library/react@^12.1.2": version "12.1.2" resolved "https://registry.yarnpkg.com/@testing-library/react/-/react-12.1.2.tgz#f1bc9a45943461fa2a598bb4597df1ae044cfc76" @@ -2874,6 +2947,53 @@ "@babel/runtime" "^7.12.5" "@testing-library/dom" "^8.0.0" +"@testing-library/react@^13.3.0": + version "13.3.0" + resolved "https://registry.yarnpkg.com/@testing-library/react/-/react-13.3.0.tgz#bf298bfbc5589326bbcc8052b211f3bb097a97c5" + integrity sha512-DB79aA426+deFgGSjnf5grczDPiL4taK3hFaa+M5q7q20Kcve9eQottOG5kZ74KEr55v0tU2CQormSSDK87zYQ== + dependencies: + "@babel/runtime" "^7.12.5" + "@testing-library/dom" "^8.5.0" + "@types/react-dom" "^18.0.0" + +"@tldraw/core@*", "@tldraw/core@^1.13.1": + version "1.13.1" + resolved "https://registry.yarnpkg.com/@tldraw/core/-/core-1.13.1.tgz#b56f919b23f941dfe1842238131ccee7da19e2cd" + integrity sha512-tvQGi5Up2WriLVTtJbWNanchd03hUX5e3g/iRPptOacDlygQTX6XtfBa+4VA0F3vDwzoxeCTe2smpNMTbhKM1g== + dependencies: + "@tldraw/intersect" "^1.7.1" + "@tldraw/vec" "^1.7.0" + "@use-gesture/react" "^10.2.14" + mobx-react-lite "^3.2.3" + perfect-freehand "^1.1.0" + resize-observer-polyfill "^1.5.1" + +"@tldraw/tldraw@*": + version "1.15.1" + resolved "https://registry.yarnpkg.com/@tldraw/tldraw/-/tldraw-1.15.1.tgz#f27cd992e96dd68f1ad3243e04c5964a19db6b2b" + integrity sha512-76RBv5urQAi/PBKfnENxfS/pZkwkJD5/LfCioreWAo8+ZYit0wRGzF8e5uii1INEibPpz/hgQz6W/4SU64m8vA== + dependencies: + "@radix-ui/react-alert-dialog" "^0.1.7" + "@radix-ui/react-checkbox" "^0.1.5" + "@radix-ui/react-context-menu" "^0.1.6" + "@radix-ui/react-dropdown-menu" "^0.1.6" + "@radix-ui/react-icons" "^1.1.1" + "@radix-ui/react-radio-group" "^0.1.5" + "@radix-ui/react-tooltip" "^0.1.7" + "@stitches/react" "^1.2.8" + "@tldraw/core" "^1.13.1" + "@tldraw/intersect" "^1.7.1" + "@tldraw/vec" "^1.7.0" + "@types/lz-string" "^1.3.34" + idb-keyval "^6.1.0" + lz-string "^1.4.4" + perfect-freehand "^1.1.0" + react-error-boundary "^3.1.4" + react-hotkey-hook "^1.0.2" + react-hotkeys-hook "^3.4.4" + tslib "^2.3.1" + zustand "^3.6.9" + "@tootallnate/once@1": version "1.1.2" resolved "https://registry.yarnpkg.com/@tootallnate/once/-/once-1.1.2.tgz#ccb91445360179a04e7fe6aff78c00ffc1eeaf82" @@ -3116,7 +3236,7 @@ dependencies: "@types/react" "*" -"@types/react-dom@^18.0.5": +"@types/react-dom@^18.0.0", "@types/react-dom@^18.0.5": version "18.0.5" resolved "https://registry.yarnpkg.com/@types/react-dom/-/react-dom-18.0.5.tgz#330b2d472c22f796e5531446939eacef8378444a" integrity sha512-OWPWTUrY/NIrjsAPkAk1wW9LZeIjSvkXRhclsFO8CZcZGCOg2G0YZy4ft+rOyYxy8B7ui5iZzi9OkDebZ7/QSA== @@ -9509,6 +9629,11 @@ react-feather@^2.0.9: dependencies: prop-types "^15.7.2" +react-hotkey-hook@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/react-hotkey-hook/-/react-hotkey-hook-1.0.2.tgz#ca17a3f806092027eaaf41fd2f111afd9926e3ab" + integrity sha512-95GiOW8ORMqbBQ23+VHMF0giRmpiI8sFHPjbOR/e64zWI0QT+QO3Q/022c0HNBS/LrQsbGdjm64BNMah0WvlnA== + react-hotkeys-hook@^3.4.4: version "3.4.4" resolved "https://registry.yarnpkg.com/react-hotkeys-hook/-/react-hotkeys-hook-3.4.4.tgz#52ba5d8ef5e47cc2e776c70a9036d518e0993d51" @@ -10861,7 +10986,7 @@ tsconfig-replace-paths@^0.0.11: globby "^10.0.1" json5 "^2.2.0" -tslib@2.4.0, tslib@^2.4.0: +tslib@2.4.0, tslib@^2.3.1, tslib@^2.4.0: version "2.4.0" resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.4.0.tgz#7cecaa7f073ce680a05847aa77be941098f36dc3" integrity sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ==