From e2814943e945d2b0b0cd3bbf83c43af1da3e8b5c Mon Sep 17 00:00:00 2001 From: Christian Petersen Date: Fri, 26 Nov 2021 15:14:10 +0000 Subject: [PATCH] [feature] Add grids (#344) * [feature] grids * Shows relative grids at different zoom levels * Update colors * Restores vec and intersect to monorepo, changes vec.round to vec.toFixed, adds vec.snap * Snapping in translate and transforms, fix shortcut * fix bugs in build * use grid size for nudge too * update scripts * Update grid.tsx * Update grid.tsx * Fixed! * Update grid.tsx * Fix package imports * Update Editor.tsx * Improve tsconfigs, imports * Fix tiny arrow bugs, snap starting points to grid * Update tsconfig.base.json * Update shape-styles.ts * Fix example tsconfig * Fix translate type error * Fix types, paths Co-authored-by: Steve Ruiz --- .vscode/tasks.json | 13 - apps/www/components/Editor.tsx | 10 +- apps/www/components/MultiplayerEditor.tsx | 6 +- apps/www/hooks/useMultiplayerState.ts | 23 +- apps/www/package.json | 3 +- apps/www/pages/_app.tsx | 8 +- apps/www/pages/_document.tsx | 34 +- apps/www/pages/api/auth/[...nextauth].ts | 16 +- apps/www/pages/api/sponsors.ts | 2 +- apps/www/pages/index.tsx | 4 +- apps/www/pages/r/[id].tsx | 2 +- apps/www/pages/sponsorware.tsx | 2 +- apps/www/tsconfig.json | 27 +- apps/www/types.ts | 7 +- apps/www/utils/sentry.ts | 6 +- examples/core-example-advanced/package.json | 8 +- .../src/shapes/CustomShapeUtil.ts | 2 + .../src/state/actions/camera/pinchCamera.ts | 2 +- .../src/state/actions/camera/zoomIn.ts | 2 +- .../src/state/actions/camera/zoomOut.ts | 2 +- .../src/state/helpers.ts | 2 +- examples/core-example-advanced/tsconfig.json | 3 +- examples/core-example/package.json | 8 +- examples/core-example/tsconfig.json | 3 +- examples/tldraw-example/tsconfig.json | 4 +- package.json | 10 +- packages/core/package.json | 8 +- packages/core/src/TLShapeUtil/TLShapeUtil.tsx | 2 +- .../core/src/components/canvas/canvas.tsx | 6 + packages/core/src/components/grid/grid.tsx | 42 + packages/core/src/components/grid/index.ts | 1 + .../core/src/components/renderer/renderer.tsx | 12 + packages/core/src/hooks/useStyle.tsx | 14 + packages/core/src/inputs.ts | 2 +- packages/core/src/types.ts | 1 + packages/core/src/utils/utils.ts | 24 +- packages/core/tsconfig.build.json | 9 +- packages/core/tsconfig.json | 6 +- packages/intersect/CHANGELOG.md | 9 + packages/intersect/LICENSE.md | 21 + packages/intersect/README.md | 477 +++++++ packages/intersect/card-repo.png | Bin 0 -> 64086 bytes packages/intersect/package.json | 39 + packages/intersect/scripts/build.js | 63 + packages/intersect/scripts/dev.js | 29 + packages/intersect/src/index.d.ts | 430 ++++++ packages/intersect/src/index.ts | 1241 +++++++++++++++++ packages/intersect/tsconfig.build.json | 21 + packages/intersect/tsconfig.json | 14 + packages/tldraw/package.json | 10 +- packages/tldraw/src/Tldraw.tsx | 7 +- .../src/components/FocusButton/index.ts | 1 + .../PreferencesMenu/PreferencesMenu.tsx | 7 + packages/tldraw/src/constants.ts | 1 + .../tldraw/src/hooks/useKeyboardShortcuts.tsx | 10 + packages/tldraw/src/state/TLDR.ts | 4 +- packages/tldraw/src/state/TldrawApp.ts | 68 +- .../state/commands/alignShapes/alignShapes.ts | 3 +- .../moveShapesToPage/moveShapesToPage.ts | 2 +- .../state/commands/styleShapes/styleShapes.ts | 2 +- .../translateShapes/translateShapes.ts | 2 +- .../sessions/ArrowSession/ArrowSession.ts | 38 +- .../state/sessions/DrawSession/DrawSession.ts | 8 +- .../sessions/EraseSession/EraseSession.ts | 2 +- .../RotateSession/RotateSession.spec.ts | 12 +- .../TransformSession/TransformSession.ts | 20 +- .../TransformSingleSession.ts | 18 +- .../TranslateSession/TranslateSession.spec.ts | 13 +- .../TranslateSession/TranslateSession.ts | 63 +- .../src/state/shapes/ArrowUtil/ArrowUtil.tsx | 18 +- .../state/shapes/ArrowUtil/arrowHelpers.ts | 6 +- .../state/shapes/EllipseUtil/EllipseUtil.tsx | 2 +- .../state/shapes/StickyUtil/StickyUtil.tsx | 2 +- .../src/state/shapes/TextUtil/TextUtil.tsx | 4 +- .../src/state/shapes/shared/shape-styles.ts | 3 +- .../state/shapes/shared/transformRectangle.ts | 10 +- .../shapes/shared/transformSingleRectangle.ts | 4 +- .../src/state/tools/ArrowTool/ArrowTool.ts | 5 +- packages/tldraw/src/state/tools/BaseTool.ts | 2 - .../state/tools/EllipseTool/EllipseTool.ts | 5 +- .../src/state/tools/LineTool/LineTool.ts | 5 +- .../tools/RectangleTool/RectangleTool.ts | 5 +- .../state/tools/SelectTool/SelectTool.spec.ts | 9 +- .../src/state/tools/StickyTool/StickyTool.ts | 4 +- .../src/state/tools/TextTool/TextTool.ts | 10 +- packages/tldraw/src/test/TldrawTestApp.tsx | 12 + packages/tldraw/src/types.ts | 32 +- packages/tldraw/tsconfig.build.json | 11 +- packages/tldraw/tsconfig.json | 9 +- packages/vec/CHANGELOG.md | 86 ++ packages/vec/LICENSE.md | 21 + packages/vec/README.md | 477 +++++++ packages/vec/card-repo.png | Bin 0 -> 64086 bytes packages/vec/package.json | 35 + packages/vec/scripts/build.js | 61 + packages/vec/scripts/dev.js | 29 + packages/vec/src/index.d.ts | 311 +++++ packages/vec/src/index.d.ts.map | 1 + packages/vec/src/index.ts | 499 +++++++ packages/vec/tsconfig.build.json | 20 + packages/vec/tsconfig.json | 14 + replace-paths.ts | 338 +++++ tsconfig.base.json | 6 +- tsconfig.json | 12 +- yarn.lock | 56 +- 105 files changed, 4795 insertions(+), 300 deletions(-) delete mode 100644 .vscode/tasks.json create mode 100644 packages/core/src/components/grid/grid.tsx create mode 100644 packages/core/src/components/grid/index.ts create mode 100644 packages/intersect/CHANGELOG.md create mode 100644 packages/intersect/LICENSE.md create mode 100644 packages/intersect/README.md create mode 100644 packages/intersect/card-repo.png create mode 100644 packages/intersect/package.json create mode 100644 packages/intersect/scripts/build.js create mode 100644 packages/intersect/scripts/dev.js create mode 100644 packages/intersect/src/index.d.ts create mode 100644 packages/intersect/src/index.ts create mode 100644 packages/intersect/tsconfig.build.json create mode 100644 packages/intersect/tsconfig.json create mode 100644 packages/vec/CHANGELOG.md create mode 100644 packages/vec/LICENSE.md create mode 100644 packages/vec/README.md create mode 100644 packages/vec/card-repo.png create mode 100644 packages/vec/package.json create mode 100644 packages/vec/scripts/build.js create mode 100644 packages/vec/scripts/dev.js create mode 100644 packages/vec/src/index.d.ts create mode 100644 packages/vec/src/index.d.ts.map create mode 100644 packages/vec/src/index.ts create mode 100644 packages/vec/tsconfig.build.json create mode 100644 packages/vec/tsconfig.json create mode 100644 replace-paths.ts diff --git a/.vscode/tasks.json b/.vscode/tasks.json deleted file mode 100644 index a96ff102a..000000000 --- a/.vscode/tasks.json +++ /dev/null @@ -1,13 +0,0 @@ -{ - "version": "2.0.0", - "tasks": [ - { - "label": "Check for type errors", - "type": "typescript", - "tsconfig": "tsconfig.json", - "option": "watch", - "problemMatcher": ["$tsc-watch"], - "group": "build" - } - ] -} diff --git a/apps/www/components/Editor.tsx b/apps/www/components/Editor.tsx index cd6ec81e3..c54887113 100644 --- a/apps/www/components/Editor.tsx +++ b/apps/www/components/Editor.tsx @@ -1,7 +1,7 @@ -import { Tldraw, TldrawApp, useFileSystem } from '@tldraw/tldraw' -import * as gtag from '-utils/gtag' import React from 'react' -import { useAccountHandlers } from '-hooks/useAccountHandlers' +import * as gtag from 'utils/gtag' +import { Tldraw, TldrawApp, useFileSystem } from '@tldraw/tldraw' +import { useAccountHandlers } from 'hooks/useAccountHandlers' declare const window: Window & { app: TldrawApp } @@ -19,9 +19,9 @@ export default function Editor({ id = 'home', isUser = false, isSponsor = false // Send events to gtag as actions. const handlePersist = React.useCallback((_app: TldrawApp, reason?: string) => { gtag.event({ - action: reason, + action: reason ?? '', category: 'editor', - label: reason || 'persist', + label: reason ?? 'persist', value: 0, }) }, []) diff --git a/apps/www/components/MultiplayerEditor.tsx b/apps/www/components/MultiplayerEditor.tsx index c59f73d8f..bce6d387b 100644 --- a/apps/www/components/MultiplayerEditor.tsx +++ b/apps/www/components/MultiplayerEditor.tsx @@ -3,9 +3,9 @@ import * as React from 'react' import { Tldraw, TldrawApp, useFileSystem } from '@tldraw/tldraw' import { createClient } from '@liveblocks/client' import { LiveblocksProvider, RoomProvider } from '@liveblocks/react' -import { useAccountHandlers } from '-hooks/useAccountHandlers' -import { styled } from '-styles' -import { useMultiplayerState } from '-hooks/useMultiplayerState' +import { useAccountHandlers } from 'hooks/useAccountHandlers' +import { styled } from 'styles' +import { useMultiplayerState } from 'hooks/useMultiplayerState' const client = createClient({ publicApiKey: process.env.NEXT_PUBLIC_LIVEBLOCKS_PUBLIC_API_KEY || '', diff --git a/apps/www/hooks/useMultiplayerState.ts b/apps/www/hooks/useMultiplayerState.ts index 6e0849e9e..bb97ebbc9 100644 --- a/apps/www/hooks/useMultiplayerState.ts +++ b/apps/www/hooks/useMultiplayerState.ts @@ -129,10 +129,17 @@ export function useMultiplayerState(roomId: string) { page: { shapes, bindings }, }, }, - } = doc.toObject() + } = doc.toObject() as { document: TDDocument } - Object.values(shapes).forEach((shape) => lShapes.set(shape.id, shape)) - Object.values(bindings).forEach((binding) => lBindings.set(binding.id, binding)) + for (const key in shapes) { + const shape = shapes[key] + lShapes.set(shape.id, shape) + } + + for (const key in bindings) { + const binding = bindings[key] + lBindings.set(binding.id, binding) + } } } @@ -175,21 +182,23 @@ export function useMultiplayerState(roomId: string) { if (!(lShapes && lBindings)) return - Object.entries(shapes).forEach(([id, shape]) => { + for (const id in shapes) { + const shape = shapes[id] if (!shape) { lShapes.delete(id) } else { lShapes.set(shape.id, shape) } - }) + } - Object.entries(bindings).forEach(([id, binding]) => { + for (const id in bindings) { + const binding = bindings[id] if (!binding) { lBindings.delete(id) } else { lBindings.set(binding.id, binding) } - }) + } rExpectingUpdate.current = true }) diff --git a/apps/www/package.json b/apps/www/package.json index 1aade9c66..e62c5b7ad 100644 --- a/apps/www/package.json +++ b/apps/www/package.json @@ -25,6 +25,7 @@ "@sentry/react": "^6.13.2", "@sentry/tracing": "^6.13.2", "@stitches/react": "^1.2.5", + "@tldraw/core": "^1.1.4", "@tldraw/tldraw": "^1.1.4", "@types/next-auth": "^3.15.0", "next": "^12.0.1", @@ -42,7 +43,7 @@ "cors": "^2.8.5", "eslint": "7.32.0", "eslint-config-next": "11.1.2", - "typescript": "^4.4.2" + "typescript": "^4.5.2" }, "gitHead": "838fabdbff1a66d4d7ee8aa5c5d117bc55acbff2" } diff --git a/apps/www/pages/_app.tsx b/apps/www/pages/_app.tsx index 1ba10f5a8..a84700ac6 100644 --- a/apps/www/pages/_app.tsx +++ b/apps/www/pages/_app.tsx @@ -1,7 +1,9 @@ import '../styles/globals.css' -import { init } from '-utils/sentry' import Head from 'next/head' -import useGtag from '-utils/useGtag' +import useGtag from 'utils/useGtag' +import { init } from 'utils/sentry' +import type { AppProps } from 'next/app' +import type React from 'react' init() @@ -10,7 +12,7 @@ const APP_DESCRIPTION = 'A tiny little drawing app.' const APP_URL = 'https://tldraw.com' const IMAGE = 'https://tldraw.com/social-image.png' -function MyApp({ Component, pageProps }) { +function MyApp({ Component, pageProps }: AppProps) { useGtag() return ( diff --git a/apps/www/pages/_document.tsx b/apps/www/pages/_document.tsx index f1b73b987..dbfaba7d8 100644 --- a/apps/www/pages/_document.tsx +++ b/apps/www/pages/_document.tsx @@ -1,29 +1,19 @@ import NextDocument, { Html, Head, Main, NextScript, DocumentContext } from 'next/document' -import { getCssText } from '../styles' -import { GA_TRACKING_ID } from '../utils/gtag' +import { getCssText } from 'styles' +import { GA_TRACKING_ID } from 'utils/gtag' class MyDocument extends NextDocument { - static async getInitialProps(ctx: DocumentContext): Promise<{ - styles: JSX.Element - html: string - head?: JSX.Element[] - }> { - try { - const initialProps = await NextDocument.getInitialProps(ctx) + static async getInitialProps(ctx: DocumentContext) { + const initialProps = await NextDocument.getInitialProps(ctx) - return { - ...initialProps, - styles: ( - <> - {initialProps.styles} -