浏览代码

Improves types and imports!

main
Steve Ruiz 3 年前
父节点
当前提交
8c02e0df84
共有 100 个文件被更改,包括 660 次插入1224 次删除
  1. 2
    1
      packages/core/package.json
  2. 1
    1
      packages/core/src/components/binding/binding.tsx
  3. 0
    0
      packages/core/src/components/binding/index.ts
  4. 3
    3
      packages/core/src/components/bounds/bounds-bg.tsx
  5. 2
    2
      packages/core/src/components/bounds/bounds.tsx
  6. 20
    0
      packages/core/src/components/bounds/center-handle.tsx
  7. 2
    2
      packages/core/src/components/bounds/corner-handle.tsx
  8. 2
    2
      packages/core/src/components/bounds/edge-handle.tsx
  9. 0
    0
      packages/core/src/components/bounds/index.ts
  10. 2
    2
      packages/core/src/components/bounds/rotate-handle.tsx
  11. 1
    1
      packages/core/src/components/brush/BrushUpdater.ts
  12. 0
    1
      packages/core/src/components/brush/brush.tsx
  13. 0
    0
      packages/core/src/components/brush/index.ts
  14. 8
    4
      packages/core/src/components/canvas.tsx
  15. 0
    0
      packages/core/src/components/defs.tsx
  16. 0
    0
      packages/core/src/components/error-fallback.tsx
  17. 1
    1
      packages/core/src/components/handles/handle.tsx
  18. 35
    0
      packages/core/src/components/handles/handles.tsx
  19. 0
    0
      packages/core/src/components/handles/index.ts
  20. 2
    0
      packages/core/src/components/index.tsx
  21. 2
    3
      packages/core/src/components/page.tsx
  22. 2
    3
      packages/core/src/components/renderer.tsx
  23. 3
    9
      packages/core/src/components/shape/editing-text-shape.tsx
  24. 0
    0
      packages/core/src/components/shape/index.ts
  25. 1
    1
      packages/core/src/components/shape/rendered-shape.tsx
  26. 4
    14
      packages/core/src/components/shape/shape.tsx
  27. 2
    0
      packages/core/src/hooks/index.ts
  28. 1
    1
      packages/core/src/hooks/useBoundsEvents.tsx
  29. 3
    5
      packages/core/src/hooks/useBoundsHandleEvents.tsx
  30. 3
    9
      packages/core/src/hooks/useCameraCss.tsx
  31. 1
    1
      packages/core/src/hooks/useCanvasEvents.tsx
  32. 1
    1
      packages/core/src/hooks/useHandleEvents.tsx
  33. 1
    1
      packages/core/src/hooks/useHandles.ts
  34. 0
    0
      packages/core/src/hooks/usePreventNavigation.tsx
  35. 2
    2
      packages/core/src/hooks/useRenderOnResize.tsx
  36. 1
    1
      packages/core/src/hooks/useSafariFocusOutFix.tsx
  37. 3
    3
      packages/core/src/hooks/useSelection.tsx
  38. 2
    2
      packages/core/src/hooks/useShapeEvents.tsx
  39. 2
    2
      packages/core/src/hooks/useShapeTree.tsx
  40. 1
    1
      packages/core/src/hooks/useStyle.tsx
  41. 1
    7
      packages/core/src/hooks/useTLContext.tsx
  42. 7
    5
      packages/core/src/hooks/useZoomEvents.ts
  43. 1
    1
      packages/core/src/index.ts
  44. 7
    34
      packages/core/src/inputs.ts
  45. 0
    22
      packages/core/src/renderer/components/bounds/center-handle.tsx
  46. 0
    37
      packages/core/src/renderer/components/handles/handles.tsx
  47. 0
    2
      packages/core/src/renderer/index.tsx
  48. 7
    25
      packages/core/src/shapes/example-shape.tsx
  49. 0
    257
      packages/core/src/types.d.ts
  50. 21
    21
      packages/core/src/types.ts
  51. 0
    1
      packages/core/src/utils/index.ts
  52. 8
    0
      packages/core/src/utils/intersect.ts
  53. 1
    3
      packages/core/src/utils/polyfills.ts
  54. 3
    5
      packages/core/src/utils/utils.ts
  55. 33
    3
      packages/core/tsconfig.json
  56. 9
    2
      packages/dev/src/components/editor.tsx
  57. 2
    1
      packages/tldraw/package.json
  58. 156
    163
      packages/tldraw/src/components/context-menu/context-menu.tsx
  59. 0
    4
      packages/tldraw/src/components/icons/Redo.svg
  60. 0
    6
      packages/tldraw/src/components/icons/Trash.svg
  61. 0
    4
      packages/tldraw/src/components/icons/Undo.svg
  62. 1
    1
      packages/tldraw/src/components/kbd.tsx
  63. 6
    31
      packages/tldraw/src/components/shared.tsx
  64. 2
    2
      packages/tldraw/src/components/style-panel/align-distribute.tsx
  65. 42
    48
      packages/tldraw/src/components/style-panel/quick-color-select.tsx
  66. 36
    41
      packages/tldraw/src/components/style-panel/quick-dash-select.tsx
  67. 30
    32
      packages/tldraw/src/components/style-panel/quick-fill-select.tsx
  68. 38
    41
      packages/tldraw/src/components/style-panel/quick-size-select.tsx
  69. 5
    15
      packages/tldraw/src/components/style-panel/shapes-functions.tsx
  70. 1
    1
      packages/tldraw/src/components/style-panel/shared.tsx
  71. 12
    17
      packages/tldraw/src/components/style-panel/style-panel.tsx
  72. 4
    5
      packages/tldraw/src/components/tldraw.tsx
  73. 3
    3
      packages/tldraw/src/components/tools-panel/back-to-content.tsx
  74. 1
    1
      packages/tldraw/src/components/tools-panel/shared.tsx
  75. 3
    3
      packages/tldraw/src/components/tools-panel/status-bar.tsx
  76. 9
    8
      packages/tldraw/src/components/tools-panel/tools-panel.tsx
  77. 23
    25
      packages/tldraw/src/components/tools-panel/undo-redo.tsx
  78. 16
    18
      packages/tldraw/src/components/tools-panel/zoom.tsx
  79. 2
    7
      packages/tldraw/src/components/tooltip.tsx
  80. 2
    2
      packages/tldraw/src/hooks/useKeyboardShortcuts.tsx
  81. 3
    5
      packages/tldraw/src/hooks/useTLDrawContext.tsx
  82. 1
    1
      packages/tldraw/src/hooks/useTheme.ts
  83. 0
    1
      packages/tldraw/src/shape/index.ts
  84. 1
    1
      packages/tldraw/src/shape/shape-styles.ts
  85. 0
    160
      packages/tldraw/src/shape/shape-types.ts
  86. 1
    1
      packages/tldraw/src/shape/shape-utils.tsx
  87. 10
    5
      packages/tldraw/src/shape/shapes/arrow/arrow.tsx
  88. 2
    8
      packages/tldraw/src/shape/shapes/draw/draw.tsx
  89. 2
    8
      packages/tldraw/src/shape/shapes/ellipse/ellipse.tsx
  90. 3
    9
      packages/tldraw/src/shape/shapes/rectangle/rectangle.tsx
  91. 3
    3
      packages/tldraw/src/shape/shapes/text/text.tsx
  92. 3
    3
      packages/tldraw/src/state/command/align/align.command.spec.ts
  93. 4
    6
      packages/tldraw/src/state/command/align/align.command.ts
  94. 2
    2
      packages/tldraw/src/state/command/create/create.command.spec.ts
  95. 1
    2
      packages/tldraw/src/state/command/create/create.command.ts
  96. 4
    4
      packages/tldraw/src/state/command/delete/delete.command.spec.ts
  97. 1
    1
      packages/tldraw/src/state/command/delete/delete.command.ts
  98. 3
    3
      packages/tldraw/src/state/command/distribute/distribute.command.spec.ts
  99. 8
    18
      packages/tldraw/src/state/command/distribute/distribute.command.ts
  100. 0
    0
      packages/tldraw/src/state/command/duplicate/duplicate.command.spec.ts

+ 2
- 1
packages/core/package.json 查看文件

@@ -18,7 +18,7 @@
18 18
   "main": "./dist/cjs/index.js",
19 19
   "types": "./dist/types/index.d.ts",
20 20
   "scripts": {
21
-    "dev": "node scripts/dev & tsc --watch --incremental --emitDeclarationOnly --outDir dist/types",
21
+    "dev": "node scripts/dev & tsc --watch --incremental --emitDeclarationOnly --declarationMap --outDir dist/types",
22 22
     "build": "yarn clean && node scripts/build && tsc --emitDeclarationOnly --outDir dist/types",
23 23
     "lint": "eslint src/ --ext .ts,.tsx",
24 24
     "clean": "rm -rf dist",
@@ -26,6 +26,7 @@
26 26
     "docs": "typedoc --entryPoints src/index.ts"
27 27
   },
28 28
   "devDependencies": {
29
+    "@types/jest": "^27.0.1",
29 30
     "@types/node": "^15.0.1",
30 31
     "@types/react": "^17.0.16",
31 32
     "@types/react-dom": "^17.0.9",

packages/core/src/renderer/components/binding/binding.tsx → packages/core/src/components/binding/binding.tsx 查看文件

@@ -1,4 +1,4 @@
1
-import type { TLBinding } from '@tldraw/core/src/types'
1
+import type { TLBinding } from '~types'
2 2
 
3 3
 interface BindingProps {
4 4
   point: number[]

packages/core/src/renderer/components/binding/index.ts → packages/core/src/components/binding/index.ts 查看文件


packages/core/src/renderer/components/bounds/bounds-bg.tsx → packages/core/src/components/bounds/bounds-bg.tsx 查看文件

@@ -1,7 +1,7 @@
1 1
 import * as React from 'react'
2
-import type { TLBounds } from '../../../types'
3
-import { Utils } from '../../../utils'
4
-import { useBoundsEvents } from '../../hooks/useBoundsEvents'
2
+import type { TLBounds } from '~types'
3
+import { Utils } from '~utils'
4
+import { useBoundsEvents } from '~hooks'
5 5
 
6 6
 interface BoundsBgProps {
7 7
   bounds: TLBounds

packages/core/src/renderer/components/bounds/bounds.tsx → packages/core/src/components/bounds/bounds.tsx 查看文件

@@ -1,6 +1,6 @@
1 1
 import * as React from 'react'
2
-import { TLBoundsEdge, TLBoundsCorner, TLBounds } from '../../../types'
3
-import { Utils } from '../../../utils'
2
+import { TLBoundsEdge, TLBoundsCorner, TLBounds } from '~types'
3
+import { Utils } from '~utils'
4 4
 import { CenterHandle } from './center-handle'
5 5
 import { RotateHandle } from './rotate-handle'
6 6
 import { CornerHandle } from './corner-handle'

+ 20
- 0
packages/core/src/components/bounds/center-handle.tsx 查看文件

@@ -0,0 +1,20 @@
1
+import * as React from 'react'
2
+import type { TLBounds } from '~types'
3
+
4
+export interface CenterHandleProps {
5
+  bounds: TLBounds
6
+  isLocked: boolean
7
+}
8
+
9
+export const CenterHandle = React.memo(({ bounds, isLocked }: CenterHandleProps): JSX.Element => {
10
+  return (
11
+    <rect
12
+      className={isLocked ? 'tl-bounds-center tl-dashed' : 'tl-bounds-center'}
13
+      x={-1}
14
+      y={-1}
15
+      width={bounds.width + 2}
16
+      height={bounds.height + 2}
17
+      pointerEvents="none"
18
+    />
19
+  )
20
+})

packages/core/src/renderer/components/bounds/corner-handle.tsx → packages/core/src/components/bounds/corner-handle.tsx 查看文件

@@ -1,6 +1,6 @@
1 1
 import * as React from 'react'
2
-import { useBoundsHandleEvents } from '../../hooks'
3
-import { TLBoundsCorner, TLBounds } from '../../../types'
2
+import { useBoundsHandleEvents } from '~hooks'
3
+import { TLBoundsCorner, TLBounds } from '~types'
4 4
 
5 5
 const cornerBgClassnames = {
6 6
   [TLBoundsCorner.TopLeft]: 'tl-transparent tl-cursor-nwse',

packages/core/src/renderer/components/bounds/edge-handle.tsx → packages/core/src/components/bounds/edge-handle.tsx 查看文件

@@ -1,6 +1,6 @@
1 1
 import * as React from 'react'
2
-import { useBoundsHandleEvents } from '../../hooks'
3
-import { TLBoundsEdge, TLBounds } from '../../../types'
2
+import { useBoundsHandleEvents } from '~hooks'
3
+import { TLBoundsEdge, TLBounds } from '~types'
4 4
 
5 5
 const edgeClassnames = {
6 6
   [TLBoundsEdge.Top]: 'tl-transparent tl-cursor-ns',

packages/core/src/renderer/components/bounds/index.ts → packages/core/src/components/bounds/index.ts 查看文件


packages/core/src/renderer/components/bounds/rotate-handle.tsx → packages/core/src/components/bounds/rotate-handle.tsx 查看文件

@@ -1,6 +1,6 @@
1 1
 import * as React from 'react'
2
-import { useBoundsHandleEvents } from '../../hooks'
3
-import type { TLBounds } from '../../../types'
2
+import { useBoundsHandleEvents } from '~hooks'
3
+import type { TLBounds } from '~types'
4 4
 
5 5
 export const RotateHandle = React.memo(
6 6
   ({ bounds, size }: { bounds: TLBounds; size: number }): JSX.Element => {

packages/core/src/renderer/components/brush/BrushUpdater.ts → packages/core/src/components/brush/BrushUpdater.ts 查看文件

@@ -1,5 +1,5 @@
1 1
 import * as React from 'react'
2
-import type { TLBounds } from '../../../types'
2
+import type { TLBounds } from '~types'
3 3
 
4 4
 export class BrushUpdater {
5 5
   ref = React.createRef<SVGRectElement>()

packages/core/src/renderer/components/brush/brush.tsx → packages/core/src/components/brush/brush.tsx 查看文件

@@ -1,5 +1,4 @@
1 1
 import * as React from 'react'
2
-import { TLBounds } from '../../../types'
3 2
 import { BrushUpdater } from './BrushUpdater'
4 3
 
5 4
 export const brushUpdater = new BrushUpdater()

packages/core/src/renderer/components/brush/index.ts → packages/core/src/components/brush/index.ts 查看文件


packages/core/src/renderer/components/canvas.tsx → packages/core/src/components/canvas.tsx 查看文件

@@ -1,13 +1,17 @@
1 1
 import * as React from 'react'
2 2
 import { ErrorBoundary } from 'react-error-boundary'
3
-import { useZoomEvents, useSafariFocusOutFix, useCanvasEvents, useCameraCss } from '../hooks'
3
+import {
4
+  usePreventNavigation,
5
+  useZoomEvents,
6
+  useSafariFocusOutFix,
7
+  useCanvasEvents,
8
+  useCameraCss,
9
+} from '~hooks'
10
+import type { TLBinding, TLPage, TLPageState, TLShape } from '~types'
4 11
 import { ErrorFallback } from './error-fallback'
5
-import type { TLBinding, TLPage, TLPageState, TLShape } from '../../types'
6
-
7 12
 import { Brush } from './brush'
8 13
 import { Defs } from './defs'
9 14
 import { Page } from './page'
10
-import { usePreventNavigation } from '../hooks/usePreventNavigation'
11 15
 
12 16
 function resetError() {
13 17
   void null

packages/core/src/renderer/components/defs.tsx → packages/core/src/components/defs.tsx 查看文件


packages/core/src/renderer/components/error-fallback.tsx → packages/core/src/components/error-fallback.tsx 查看文件


packages/core/src/renderer/components/handles/handle.tsx → packages/core/src/components/handles/handle.tsx 查看文件

@@ -1,5 +1,5 @@
1 1
 import * as React from 'react'
2
-import { useHandleEvents } from '../../hooks'
2
+import { useHandleEvents } from '~hooks'
3 3
 
4 4
 interface HandleProps {
5 5
   id: string

+ 35
- 0
packages/core/src/components/handles/handles.tsx 查看文件

@@ -0,0 +1,35 @@
1
+import * as React from 'react'
2
+import { Vec } from '~utils'
3
+import type { TLShape } from '~types'
4
+import { useTLContext } from '~hooks'
5
+import { Handle } from './handle'
6
+
7
+interface HandlesProps {
8
+  shape: TLShape
9
+  zoom: number
10
+}
11
+
12
+const toAngle = 180 / Math.PI
13
+
14
+export const Handles = React.memo(({ shape, zoom }: HandlesProps): JSX.Element | null => {
15
+  const { shapeUtils } = useTLContext()
16
+
17
+  const center = shapeUtils[shape.type].getCenter(shape)
18
+
19
+  if (shape.handles === undefined) {
20
+    return null
21
+  }
22
+
23
+  return (
24
+    <g transform={`rotate(${(shape.rotation || 0) * toAngle},${center})`}>
25
+      {Object.values(shape.handles).map((handle) => (
26
+        <Handle
27
+          key={shape.id + '_' + handle.id}
28
+          id={handle.id}
29
+          point={Vec.add(handle.point, shape.point)}
30
+          zoom={zoom}
31
+        />
32
+      ))}
33
+    </g>
34
+  )
35
+})

packages/core/src/renderer/components/handles/index.ts → packages/core/src/components/handles/index.ts 查看文件


+ 2
- 0
packages/core/src/components/index.tsx 查看文件

@@ -0,0 +1,2 @@
1
+export * from './renderer'
2
+export { brushUpdater } from './brush'

packages/core/src/renderer/components/page.tsx → packages/core/src/components/page.tsx 查看文件

@@ -1,8 +1,7 @@
1 1
 import * as React from 'react'
2
-import { useShapeTree } from '../hooks/useShapeTree'
3
-import type { IShapeTreeNode, TLBinding, TLPage, TLPageState, TLShape } from '../../types'
2
+import type { IShapeTreeNode, TLBinding, TLPage, TLPageState, TLShape } from '~types'
4 3
 import { Shape as ShapeComponent } from './shape'
5
-import { useHandles, useRenderOnResize, useTLContext } from '../hooks'
4
+import { useShapeTree, useHandles, useRenderOnResize, useTLContext } from '../hooks'
6 5
 import { Bounds } from './bounds'
7 6
 import { BoundsBg } from './bounds/bounds-bg'
8 7
 import { useSelection } from '../hooks'

packages/core/src/renderer/renderer.tsx → packages/core/src/components/renderer.tsx 查看文件

@@ -10,9 +10,8 @@ import type {
10 10
   TLBounds,
11 11
   TLBinding,
12 12
 } from '../types'
13
-import { Canvas } from './components/canvas'
14
-import { useTLTheme } from './hooks/useStyle'
15
-import { TLContext } from './hooks/useTLContext'
13
+import { Canvas } from '../components/canvas'
14
+import { useTLTheme, TLContext } from '../hooks'
16 15
 
17 16
 export interface RendererProps<T extends TLShape>
18 17
   extends Partial<TLSettings>,

packages/core/src/renderer/components/shape/editing-text-shape.tsx → packages/core/src/components/shape/editing-text-shape.tsx 查看文件

@@ -1,6 +1,6 @@
1
-import { useTLContext } from '../../hooks'
1
+import { useTLContext } from '~hooks'
2 2
 import * as React from 'react'
3
-import type { TLShapeUtil, TLRenderInfo, TLShape } from '../../../types'
3
+import type { TLShapeUtil, TLRenderInfo, TLShape } from '~types'
4 4
 
5 5
 interface EditingShapeProps<T extends TLShape> extends TLRenderInfo {
6 6
   shape: T
@@ -16,13 +16,7 @@ export function EditingTextShape({
16 16
   isCurrentParent,
17 17
 }: EditingShapeProps<TLShape>) {
18 18
   const {
19
-    callbacks: {
20
-      onTextChange,
21
-      onTextBlur,
22
-      onTextFocus,
23
-      onTextKeyDown,
24
-      onTextKeyUp,
25
-    },
19
+    callbacks: { onTextChange, onTextBlur, onTextFocus, onTextKeyDown, onTextKeyUp },
26 20
   } = useTLContext()
27 21
 
28 22
   const ref = React.useRef<HTMLElement>(null)

packages/core/src/renderer/components/shape/index.ts → packages/core/src/components/shape/index.ts 查看文件


packages/core/src/renderer/components/shape/rendered-shape.tsx → packages/core/src/components/shape/rendered-shape.tsx 查看文件

@@ -1,5 +1,5 @@
1 1
 import * as React from 'react'
2
-import type { TLShapeUtil, TLRenderInfo, TLShape } from '../../../types'
2
+import type { TLShapeUtil, TLRenderInfo, TLShape } from '~types'
3 3
 
4 4
 interface RenderedShapeProps<T extends TLShape> extends TLRenderInfo {
5 5
   shape: T

packages/core/src/renderer/components/shape/shape.tsx → packages/core/src/components/shape/shape.tsx 查看文件

@@ -1,17 +1,11 @@
1 1
 import * as React from 'react'
2
-import { useShapeEvents, useTLContext } from '../../hooks'
3
-import type { IShapeTreeNode } from '../../../types'
2
+import { useShapeEvents, useTLContext } from '~hooks'
3
+import type { IShapeTreeNode } from '~types'
4 4
 import { RenderedShape } from './rendered-shape'
5 5
 import { EditingTextShape } from './editing-text-shape'
6 6
 
7 7
 export const Shape = React.memo(
8
-  ({
9
-    shape,
10
-    isEditing,
11
-    isBinding,
12
-    isDarkMode,
13
-    isCurrentParent,
14
-  }: IShapeTreeNode) => {
8
+  ({ shape, isEditing, isBinding, isDarkMode, isCurrentParent }: IShapeTreeNode) => {
15 9
     const { shapeUtils } = useTLContext()
16 10
     const events = useShapeEvents(shape.id, isCurrentParent)
17 11
     const utils = shapeUtils[shape.type]
@@ -22,11 +16,7 @@ export const Shape = React.memo(
22 16
 
23 17
     return (
24 18
       <g
25
-        className={
26
-          isCurrentParent
27
-            ? 'tl-shape-group tl-current-parent'
28
-            : 'tl-shape-group'
29
-        }
19
+        className={isCurrentParent ? 'tl-shape-group tl-current-parent' : 'tl-shape-group'}
30 20
         id={shape.id}
31 21
         transform={transform}
32 22
         {...events}

packages/core/src/renderer/hooks/index.ts → packages/core/src/hooks/index.ts 查看文件

@@ -12,3 +12,5 @@ export * from './useRenderOnResize'
12 12
 export * from './useSelection'
13 13
 export * from './useHandleEvents'
14 14
 export * from './useHandles'
15
+export * from './usePreventNavigation'
16
+export * from './useBoundsEvents'

packages/core/src/renderer/hooks/useBoundsEvents.tsx → packages/core/src/hooks/useBoundsEvents.tsx 查看文件

@@ -1,5 +1,5 @@
1 1
 import * as React from 'react'
2
-import { inputs } from '../../inputs'
2
+import { inputs } from '~inputs'
3 3
 import { useTLContext } from './useTLContext'
4 4
 
5 5
 export function useBoundsEvents() {

packages/core/src/renderer/hooks/useBoundsHandleEvents.tsx → packages/core/src/hooks/useBoundsHandleEvents.tsx 查看文件

@@ -1,11 +1,9 @@
1 1
 import * as React from 'react'
2
-import { inputs } from '../../inputs'
3
-import type { TLBoundsEdge, TLBoundsCorner } from '../../types'
2
+import { inputs } from '~inputs'
3
+import type { TLBoundsEdge, TLBoundsCorner } from '~types'
4 4
 import { useTLContext } from './useTLContext'
5 5
 
6
-export function useBoundsHandleEvents(
7
-  id: TLBoundsCorner | TLBoundsEdge | 'rotate'
8
-) {
6
+export function useBoundsHandleEvents(id: TLBoundsCorner | TLBoundsEdge | 'rotate') {
9 7
   const { callbacks } = useTLContext()
10 8
 
11 9
   const onPointerDown = React.useCallback(

packages/core/src/renderer/hooks/useCameraCss.tsx → packages/core/src/hooks/useCameraCss.tsx 查看文件

@@ -1,15 +1,12 @@
1 1
 import * as React from 'react'
2
-import type { TLPageState } from '../../types'
2
+import type { TLPageState } from '~types'
3 3
 
4 4
 export function useCameraCss(pageState: TLPageState) {
5 5
   const rGroup = React.useRef<SVGGElement>(null)
6 6
 
7 7
   // Update the tl-zoom CSS variable when the zoom changes
8 8
   React.useEffect(() => {
9
-    document.documentElement.style.setProperty(
10
-      '--tl-zoom',
11
-      pageState.camera.zoom.toString()
12
-    )
9
+    document.documentElement.style.setProperty('--tl-zoom', pageState.camera.zoom.toString())
13 10
   }, [pageState.camera.zoom])
14 11
 
15 12
   // Update the group's position when the camera moves or zooms
@@ -18,10 +15,7 @@ export function useCameraCss(pageState: TLPageState) {
18 15
       zoom,
19 16
       point: [x = 0, y = 0],
20 17
     } = pageState.camera
21
-    rGroup.current?.setAttribute(
22
-      'transform',
23
-      `scale(${zoom}) translate(${x} ${y})`
24
-    )
18
+    rGroup.current?.setAttribute('transform', `scale(${zoom}) translate(${x} ${y})`)
25 19
   }, [pageState.camera])
26 20
 
27 21
   return rGroup

packages/core/src/renderer/hooks/useCanvasEvents.tsx → packages/core/src/hooks/useCanvasEvents.tsx 查看文件

@@ -1,6 +1,6 @@
1 1
 import * as React from 'react'
2 2
 import { useTLContext } from './useTLContext'
3
-import { inputs } from '../../inputs'
3
+import { inputs } from '~inputs'
4 4
 
5 5
 export function useCanvasEvents() {
6 6
   const { callbacks } = useTLContext()

packages/core/src/renderer/hooks/useHandleEvents.tsx → packages/core/src/hooks/useHandleEvents.tsx 查看文件

@@ -1,5 +1,5 @@
1 1
 import * as React from 'react'
2
-import { inputs } from '../../inputs'
2
+import { inputs } from '~inputs'
3 3
 import { useTLContext } from './useTLContext'
4 4
 
5 5
 export function useHandleEvents(id: string) {

packages/core/src/renderer/hooks/useHandles.ts → packages/core/src/hooks/useHandles.ts 查看文件

@@ -1,4 +1,4 @@
1
-import type { TLBinding, TLPage, TLPageState, TLShape } from '../../types'
1
+import type { TLBinding, TLPage, TLPageState, TLShape } from '~types'
2 2
 
3 3
 export function useHandles<T extends TLShape>(page: TLPage<T, TLBinding>, pageState: TLPageState) {
4 4
   const { selectedIds } = pageState

packages/core/src/renderer/hooks/usePreventNavigation.tsx → packages/core/src/hooks/usePreventNavigation.tsx 查看文件


packages/core/src/renderer/hooks/useRenderOnResize.tsx → packages/core/src/hooks/useRenderOnResize.tsx 查看文件

@@ -1,8 +1,8 @@
1 1
 import * as React from 'react'
2
-import Utils from '../../utils'
2
+import Utils from '~utils'
3 3
 
4 4
 export function useRenderOnResize() {
5
-  const forceUpdate = React.useReducer(x => x + 1, 0)[1]
5
+  const forceUpdate = React.useReducer((x) => x + 1, 0)[1]
6 6
 
7 7
   React.useEffect(() => {
8 8
     const debouncedUpdate = Utils.debounce(forceUpdate, 96)

packages/core/src/renderer/hooks/useSafariFocusOutFix.tsx → packages/core/src/hooks/useSafariFocusOutFix.tsx 查看文件

@@ -1,5 +1,5 @@
1
-import Utils from '../../utils'
2 1
 import { useEffect } from 'react'
2
+import Utils from '~utils'
3 3
 import { useTLContext } from './useTLContext'
4 4
 
5 5
 // Send event on iOS when a user presses the "Done" key while editing a text element.

packages/core/src/renderer/hooks/useSelection.tsx → packages/core/src/hooks/useSelection.tsx 查看文件

@@ -1,6 +1,6 @@
1
-import type { TLPage, TLPageState, TLShape, TLBounds, TLShapeUtils, TLBinding } from '../../types'
2
-import Utils from '../../utils'
3
-import { useTLContext } from '../hooks/useTLContext'
1
+import type { TLPage, TLPageState, TLShape, TLBounds, TLShapeUtils, TLBinding } from '~types'
2
+import Utils from '~utils'
3
+import { useTLContext } from '~hooks'
4 4
 
5 5
 function canvasToScreen(point: number[], camera: TLPageState['camera']): number[] {
6 6
   return [(point[0] + camera.point[0]) * camera.zoom, (point[1] + camera.point[1]) * camera.zoom]

packages/core/src/renderer/hooks/useShapeEvents.tsx → packages/core/src/hooks/useShapeEvents.tsx 查看文件

@@ -1,7 +1,7 @@
1 1
 import * as React from 'react'
2
-import { inputs } from '../../inputs'
2
+import { inputs } from '~inputs'
3 3
 import { useTLContext } from './useTLContext'
4
-import { Utils } from '../../utils'
4
+import { Utils } from '~utils'
5 5
 
6 6
 export function useShapeEvents(id: string, disable = false) {
7 7
   const { rPageState, rScreenBounds, callbacks } = useTLContext()

packages/core/src/renderer/hooks/useShapeTree.tsx → packages/core/src/hooks/useShapeTree.tsx 查看文件

@@ -7,8 +7,8 @@ import type {
7 7
   TLShapeUtils,
8 8
   TLCallbacks,
9 9
   TLBinding,
10
-} from '../../types'
11
-import Utils, { Vec } from '../../utils'
10
+} from '~types'
11
+import { Utils, Vec } from '~utils'
12 12
 
13 13
 function addToShapeTree<T extends TLShape>(
14 14
   shape: TLShape,

packages/core/src/renderer/hooks/useStyle.tsx → packages/core/src/hooks/useStyle.tsx 查看文件

@@ -1,5 +1,5 @@
1 1
 import * as React from 'react'
2
-import type { TLTheme } from '../../types'
2
+import type { TLTheme } from '~types'
3 3
 
4 4
 const styles = new Map<string, HTMLStyleElement>()
5 5
 

packages/core/src/renderer/hooks/useTLContext.tsx → packages/core/src/hooks/useTLContext.tsx 查看文件

@@ -1,11 +1,5 @@
1 1
 import * as React from 'react'
2
-import type {
3
-  TLCallbacks,
4
-  TLShape,
5
-  TLBounds,
6
-  TLPageState,
7
-  TLShapeUtils,
8
-} from '../../types'
2
+import type { TLCallbacks, TLShape, TLBounds, TLPageState, TLShapeUtils } from '~types'
9 3
 
10 4
 export interface TLContextType {
11 5
   callbacks: Partial<TLCallbacks>

packages/core/src/renderer/hooks/useZoomEvents.ts → packages/core/src/hooks/useZoomEvents.ts 查看文件

@@ -1,9 +1,9 @@
1 1
 /* eslint-disable @typescript-eslint/explicit-module-boundary-types */
2 2
 import { useRef } from 'react'
3 3
 import { useTLContext } from './useTLContext'
4
-import { Vec } from '../../utils'
4
+import { Vec } from '~utils'
5 5
 import { useWheel, usePinch } from 'react-use-gesture'
6
-import { inputs } from '../../inputs'
6
+import { inputs } from '~inputs'
7 7
 
8 8
 // Capture zoom gestures (pinches, wheels and pans)
9 9
 export function useZoomEvents() {
@@ -54,8 +54,10 @@ export function useZoomEvents() {
54 54
         rOriginPoint.current = origin
55 55
       }
56 56
 
57
-      // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
58
-      const [distanceDelta] = Vec.sub(rPinchDa.current!, da)
57
+      if (!rPinchDa.current) throw Error('No pinch direction!')
58
+      if (!rOriginPoint.current) throw Error('No origin point!')
59
+
60
+      const [distanceDelta] = Vec.sub(rPinchDa.current, da)
59 61
 
60 62
       const info = inputs.pinch(rPinchPoint.current, origin)
61 63
 
@@ -63,7 +65,7 @@ export function useZoomEvents() {
63 65
         {
64 66
           ...info,
65 67
           point: origin,
66
-          origin: rOriginPoint.current!,
68
+          origin: rOriginPoint.current,
67 69
           delta: [...info.delta, distanceDelta],
68 70
         },
69 71
         e as React.WheelEvent<Element> | WheelEvent | React.TouchEvent<Element> | TouchEvent

+ 1
- 1
packages/core/src/index.ts 查看文件

@@ -1,4 +1,4 @@
1
-export * from './renderer'
1
+export * from './components'
2 2
 export * from './types'
3 3
 export * from './utils'
4 4
 export * from './inputs'

packages/core/src/inputs.tsx → packages/core/src/inputs.ts 查看文件

@@ -11,10 +11,7 @@ class Inputs {
11 11
 
12 12
   pointerUpTime = 0
13 13
 
14
-  touchStart<T extends string>(
15
-    e: TouchEvent | React.TouchEvent,
16
-    target: T
17
-  ): TLPointerInfo<T> {
14
+  touchStart<T extends string>(e: TouchEvent | React.TouchEvent, target: T): TLPointerInfo<T> {
18 15
     const { shiftKey, ctrlKey, metaKey, altKey } = e
19 16
     e.preventDefault()
20 17
 
@@ -38,10 +35,7 @@ class Inputs {
38 35
     return info
39 36
   }
40 37
 
41
-  touchMove<T extends string>(
42
-    e: TouchEvent | React.TouchEvent,
43
-    target: T
44
-  ): TLPointerInfo<T> {
38
+  touchMove<T extends string>(e: TouchEvent | React.TouchEvent, target: T): TLPointerInfo<T> {
45 39
     const { shiftKey, ctrlKey, metaKey, altKey } = e
46 40
     e.preventDefault()
47 41
 
@@ -72,10 +66,7 @@ class Inputs {
72 66
     return info
73 67
   }
74 68
 
75
-  pointerDown<T extends string>(
76
-    e: PointerEvent | React.PointerEvent,
77
-    target: T
78
-  ): TLPointerInfo<T> {
69
+  pointerDown<T extends string>(e: PointerEvent | React.PointerEvent, target: T): TLPointerInfo<T> {
79 70
     const { shiftKey, ctrlKey, metaKey, altKey } = e
80 71
 
81 72
     const point = Inputs.getPoint(e)
@@ -124,10 +115,7 @@ class Inputs {
124 115
     return info
125 116
   }
126 117
 
127
-  pointerMove<T extends string>(
128
-    e: PointerEvent | React.PointerEvent,
129
-    target: T
130
-  ): TLPointerInfo<T> {
118
+  pointerMove<T extends string>(e: PointerEvent | React.PointerEvent, target: T): TLPointerInfo<T> {
131 119
     const { shiftKey, ctrlKey, metaKey, altKey } = e
132 120
 
133 121
     const prev = this.pointer
@@ -155,10 +143,7 @@ class Inputs {
155 143
     return info
156 144
   }
157 145
 
158
-  pointerUp<T extends string>(
159
-    e: PointerEvent | React.PointerEvent,
160
-    target: T
161
-  ): TLPointerInfo<T> {
146
+  pointerUp<T extends string>(e: PointerEvent | React.PointerEvent, target: T): TLPointerInfo<T> {
162 147
     const { shiftKey, ctrlKey, metaKey, altKey } = e
163 148
 
164 149
     const prev = this.pointer
@@ -236,22 +221,12 @@ class Inputs {
236 221
     return info
237 222
   }
238 223
 
239
-  canAccept = (_pointerId: PointerEvent['pointerId']): boolean => {
240
-    return true
241
-    //   return (
242
-    //     this.activePointerId === undefined || this.activePointerId === pointerId
243
-    //   )
244
-  }
245
-
246 224
   isDoubleClick() {
247 225
     if (!this.pointer) return false
248 226
 
249 227
     const { origin, point } = this.pointer
250 228
 
251
-    return (
252
-      Date.now() - this.pointerUpTime < DOUBLE_CLICK_DURATION &&
253
-      Vec.dist(origin, point) < 4
254
-    )
229
+    return Date.now() - this.pointerUpTime < DOUBLE_CLICK_DURATION && Vec.dist(origin, point) < 4
255 230
   }
256 231
 
257 232
   clear() {
@@ -334,9 +309,7 @@ class Inputs {
334 309
     return [Number(e.clientX.toPrecision(5)), Number(e.clientY.toPrecision(5))]
335 310
   }
336 311
 
337
-  static getPressure(
338
-    e: PointerEvent | React.PointerEvent | Touch | React.Touch | WheelEvent
339
-  ) {
312
+  static getPressure(e: PointerEvent | React.PointerEvent | Touch | React.Touch | WheelEvent) {
340 313
     return 'pressure' in e ? Number(e.pressure.toPrecision(5)) || 0.5 : 0.5
341 314
   }
342 315
 

+ 0
- 22
packages/core/src/renderer/components/bounds/center-handle.tsx 查看文件

@@ -1,22 +0,0 @@
1
-import * as React from 'react'
2
-import type { TLBounds } from '../../../types'
3
-
4
-export interface CenterHandleProps {
5
-  bounds: TLBounds
6
-  isLocked: boolean
7
-}
8
-
9
-export const CenterHandle = React.memo(
10
-  ({ bounds, isLocked }: CenterHandleProps): JSX.Element => {
11
-    return (
12
-      <rect
13
-        className={isLocked ? 'tl-bounds-center tl-dashed' : 'tl-bounds-center'}
14
-        x={-1}
15
-        y={-1}
16
-        width={bounds.width + 2}
17
-        height={bounds.height + 2}
18
-        pointerEvents="none"
19
-      />
20
-    )
21
-  }
22
-)

+ 0
- 37
packages/core/src/renderer/components/handles/handles.tsx 查看文件

@@ -1,37 +0,0 @@
1
-import * as React from 'react'
2
-import { Vec } from '../../../utils'
3
-import type { TLShape } from '../../../types'
4
-import { useTLContext } from '../../hooks'
5
-import { Handle } from './handle'
6
-
7
-interface HandlesProps {
8
-  shape: TLShape
9
-  zoom: number
10
-}
11
-
12
-const toAngle = 180 / Math.PI
13
-
14
-export const Handles = React.memo(
15
-  ({ shape, zoom }: HandlesProps): JSX.Element | null => {
16
-    const { shapeUtils } = useTLContext()
17
-
18
-    const center = shapeUtils[shape.type].getCenter(shape)
19
-
20
-    if (shape.handles === undefined) {
21
-      return null
22
-    }
23
-
24
-    return (
25
-      <g transform={`rotate(${(shape.rotation || 0) * toAngle},${center})`}>
26
-        {Object.values(shape.handles).map((handle) => (
27
-          <Handle
28
-            key={shape.id + '_' + handle.id}
29
-            id={handle.id}
30
-            point={Vec.add(handle.point, shape.point)}
31
-            zoom={zoom}
32
-          />
33
-        ))}
34
-      </g>
35
-    )
36
-  }
37
-)

+ 0
- 2
packages/core/src/renderer/index.tsx 查看文件

@@ -1,2 +0,0 @@
1
-export * from './renderer'
2
-export { brushUpdater } from './components/brush'

+ 7
- 25
packages/core/src/shapes/example-shape.tsx 查看文件

@@ -1,12 +1,7 @@
1
+/* eslint-disable @typescript-eslint/no-unused-vars */
1 2
 import * as React from 'react'
2
-import {
3
-  TLShapeUtil,
4
-  TLShape,
5
-  TLBounds,
6
-  TLRenderInfo,
7
-  TLTransformInfo,
8
-} from '../types'
9
-import Utils, { Intersect } from '../utils'
3
+import { TLShapeUtil, TLShape, TLBounds, TLRenderInfo, TLTransformInfo } from '~types'
4
+import Utils, { Intersect } from '~utils'
10 5
 
11 6
 export class ExampleShape extends TLShapeUtil<TLShape> {
12 7
   type = 'shape-type'
@@ -49,9 +44,7 @@ export class ExampleShape extends TLShapeUtil<TLShape> {
49 44
   }
50 45
 
51 46
   getRotatedBounds(shape: TLShape) {
52
-    return Utils.getBoundsFromPoints(
53
-      Utils.getRotatedCorners(this.getBounds(shape), shape.rotation)
54
-    )
47
+    return Utils.getBoundsFromPoints(Utils.getRotatedCorners(this.getBounds(shape), shape.rotation))
55 48
   }
56 49
 
57 50
   getCenter(shape: TLShape): number[] {
@@ -63,10 +56,7 @@ export class ExampleShape extends TLShapeUtil<TLShape> {
63 56
   }
64 57
 
65 58
   hitTestBounds(shape: TLShape, bounds: TLBounds) {
66
-    const rotatedCorners = Utils.getRotatedCorners(
67
-      this.getBounds(shape),
68
-      shape.rotation
69
-    )
59
+    const rotatedCorners = Utils.getRotatedCorners(this.getBounds(shape), shape.rotation)
70 60
 
71 61
     return (
72 62
       rotatedCorners.every((point) => Utils.pointInBounds(point, bounds)) ||
@@ -74,19 +64,11 @@ export class ExampleShape extends TLShapeUtil<TLShape> {
74 64
     )
75 65
   }
76 66
 
77
-  transform(
78
-    shape: TLShape,
79
-    bounds: TLBounds,
80
-    _info: TLTransformInfo<TLShape>
81
-  ): TLShape {
67
+  transform(shape: TLShape, bounds: TLBounds, _info: TLTransformInfo<TLShape>): TLShape {
82 68
     return { ...shape, point: [bounds.minX, bounds.minY] }
83 69
   }
84 70
 
85
-  transformSingle(
86
-    shape: TLShape,
87
-    bounds: TLBounds,
88
-    info: TLTransformInfo<TLShape>
89
-  ): TLShape {
71
+  transformSingle(shape: TLShape, bounds: TLBounds, info: TLTransformInfo<TLShape>): TLShape {
90 72
     return this.transform(shape, bounds, info)
91 73
   }
92 74
 }

+ 0
- 257
packages/core/src/types.d.ts 查看文件

@@ -1,257 +0,0 @@
1
-/// <reference types="react" />
2
-export interface TLPage<T extends TLShape> {
3
-    id: string;
4
-    name?: string;
5
-    childIndex?: number;
6
-    shapes: Record<string, T>;
7
-    bindings: Record<string, TLBinding>;
8
-    backgroundColor?: string;
9
-}
10
-export interface TLPageState {
11
-    id: string;
12
-    brush?: TLBounds;
13
-    pointedId?: string;
14
-    hoveredId?: string;
15
-    editingId?: string;
16
-    bindingId?: string;
17
-    boundsRotation?: number;
18
-    currentParentId?: string;
19
-    selectedIds: string[];
20
-    camera: {
21
-        point: number[];
22
-        zoom: number;
23
-    };
24
-}
25
-export interface TLHandle {
26
-    id: string;
27
-    index: number;
28
-    point: number[];
29
-    canBind?: boolean;
30
-    bindingId?: string;
31
-}
32
-export interface TLShape {
33
-    id: string;
34
-    type: string;
35
-    parentId: string;
36
-    childIndex: number;
37
-    name: string;
38
-    point: number[];
39
-    rotation?: number;
40
-    children?: string[];
41
-    handles?: Record<string, TLHandle>;
42
-    isLocked?: boolean;
43
-    isHidden?: boolean;
44
-    isEditing?: boolean;
45
-    isGenerated?: boolean;
46
-    isAspectRatioLocked?: boolean;
47
-}
48
-export declare type TLShapeUtils<T extends TLShape> = Record<string, TLShapeUtil<T>>;
49
-export interface TLRenderInfo<T extends SVGElement | HTMLElement = any> {
50
-    isEditing: boolean;
51
-    isBinding: boolean;
52
-    isDarkMode: boolean;
53
-    isCurrentParent: boolean;
54
-    ref?: React.RefObject<T>;
55
-    onTextChange?: TLCallbacks['onTextChange'];
56
-    onTextBlur?: TLCallbacks['onTextBlur'];
57
-    onTextFocus?: TLCallbacks['onTextFocus'];
58
-    onTextKeyDown?: TLCallbacks['onTextKeyDown'];
59
-    onTextKeyUp?: TLCallbacks['onTextKeyUp'];
60
-}
61
-export interface TLTool {
62
-    id: string;
63
-    name: string;
64
-}
65
-export interface TLBinding {
66
-    id: string;
67
-    type: string;
68
-    toId: string;
69
-    fromId: string;
70
-}
71
-export interface TLSettings {
72
-    isDebugMode: boolean;
73
-    isDarkMode: boolean;
74
-    isPenMode: boolean;
75
-}
76
-export interface TLTheme {
77
-    brushFill?: string;
78
-    brushStroke?: string;
79
-    selectFill?: string;
80
-    selectStroke?: string;
81
-    background?: string;
82
-    foreground?: string;
83
-}
84
-export declare type TLWheelEventHandler = (info: TLPointerInfo<string>, e: React.WheelEvent<Element> | WheelEvent) => void;
85
-export declare type TLPinchEventHandler = (info: TLPointerInfo<string>, e: React.WheelEvent<Element> | WheelEvent | React.TouchEvent<Element> | TouchEvent) => void;
86
-export declare type TLPointerEventHandler = (info: TLPointerInfo<string>, e: React.PointerEvent) => void;
87
-export declare type TLCanvasEventHandler = (info: TLPointerInfo<'canvas'>, e: React.PointerEvent) => void;
88
-export declare type TLBoundsEventHandler = (info: TLPointerInfo<'bounds'>, e: React.PointerEvent) => void;
89
-export declare type TLBoundsHandleEventHandler = (info: TLPointerInfo<TLBoundsCorner | TLBoundsEdge | 'rotate'>, e: React.PointerEvent) => void;
90
-export interface TLCallbacks {
91
-    onChange: (ids: string[]) => void;
92
-    onPinchStart: TLPinchEventHandler;
93
-    onPinchEnd: TLPinchEventHandler;
94
-    onPinch: TLPinchEventHandler;
95
-    onPan: TLWheelEventHandler;
96
-    onZoom: TLWheelEventHandler;
97
-    onPointerMove: TLPointerEventHandler;
98
-    onPointerUp: TLPointerEventHandler;
99
-    onPointerDown: TLPointerEventHandler;
100
-    onPointCanvas: TLCanvasEventHandler;
101
-    onDoubleClickCanvas: TLCanvasEventHandler;
102
-    onRightPointCanvas: TLCanvasEventHandler;
103
-    onDragCanvas: TLCanvasEventHandler;
104
-    onReleaseCanvas: TLCanvasEventHandler;
105
-    onPointShape: TLPointerEventHandler;
106
-    onDoubleClickShape: TLPointerEventHandler;
107
-    onRightPointShape: TLPointerEventHandler;
108
-    onDragShape: TLPointerEventHandler;
109
-    onHoverShape: TLPointerEventHandler;
110
-    onUnhoverShape: TLPointerEventHandler;
111
-    onReleaseShape: TLPointerEventHandler;
112
-    onPointBounds: TLBoundsEventHandler;
113
-    onDoubleClickBounds: TLBoundsEventHandler;
114
-    onRightPointBounds: TLBoundsEventHandler;
115
-    onDragBounds: TLBoundsEventHandler;
116
-    onHoverBounds: TLBoundsEventHandler;
117
-    onUnhoverBounds: TLBoundsEventHandler;
118
-    onReleaseBounds: TLBoundsEventHandler;
119
-    onPointBoundsHandle: TLBoundsHandleEventHandler;
120
-    onDoubleClickBoundsHandle: TLBoundsHandleEventHandler;
121
-    onRightPointBoundsHandle: TLBoundsHandleEventHandler;
122
-    onDragBoundsHandle: TLBoundsHandleEventHandler;
123
-    onHoverBoundsHandle: TLBoundsHandleEventHandler;
124
-    onUnhoverBoundsHandle: TLBoundsHandleEventHandler;
125
-    onReleaseBoundsHandle: TLBoundsHandleEventHandler;
126
-    onPointHandle: TLPointerEventHandler;
127
-    onDoubleClickHandle: TLPointerEventHandler;
128
-    onRightPointHandle: TLPointerEventHandler;
129
-    onDragHandle: TLPointerEventHandler;
130
-    onHoverHandle: TLPointerEventHandler;
131
-    onUnhoverHandle: TLPointerEventHandler;
132
-    onReleaseHandle: TLPointerEventHandler;
133
-    onTextChange: (id: string, text: string) => void;
134
-    onTextBlur: (id: string) => void;
135
-    onTextFocus: (id: string) => void;
136
-    onTextKeyDown: (id: string, key: string) => void;
137
-    onTextKeyUp: (id: string, key: string) => void;
138
-    onBlurEditingShape: () => void;
139
-    onError: (error: Error) => void;
140
-}
141
-export interface TLBounds {
142
-    minX: number;
143
-    minY: number;
144
-    maxX: number;
145
-    maxY: number;
146
-    width: number;
147
-    height: number;
148
-    rotation?: number;
149
-}
150
-export declare type TLIntersection = {
151
-    didIntersect: boolean;
152
-    message: string;
153
-    points: number[][];
154
-};
155
-export declare enum TLBoundsEdge {
156
-    Top = "top_edge",
157
-    Right = "right_edge",
158
-    Bottom = "bottom_edge",
159
-    Left = "left_edge"
160
-}
161
-export declare enum TLBoundsCorner {
162
-    TopLeft = "top_left_corner",
163
-    TopRight = "top_right_corner",
164
-    BottomRight = "bottom_right_corner",
165
-    BottomLeft = "bottom_left_corner"
166
-}
167
-export interface TLPointerInfo<T extends string = string> {
168
-    target: T;
169
-    pointerId: number;
170
-    origin: number[];
171
-    point: number[];
172
-    delta: number[];
173
-    pressure: number;
174
-    shiftKey: boolean;
175
-    ctrlKey: boolean;
176
-    metaKey: boolean;
177
-    altKey: boolean;
178
-}
179
-export interface TLKeyboardInfo {
180
-    origin: number[];
181
-    point: number[];
182
-    key: string;
183
-    keys: string[];
184
-    shiftKey: boolean;
185
-    ctrlKey: boolean;
186
-    metaKey: boolean;
187
-    altKey: boolean;
188
-}
189
-export interface TLTransformInfo<T extends TLShape> {
190
-    type: TLBoundsEdge | TLBoundsCorner;
191
-    initialShape: T;
192
-    scaleX: number;
193
-    scaleY: number;
194
-    transformOrigin: number[];
195
-}
196
-export interface TLBezierCurveSegment {
197
-    start: number[];
198
-    tangentStart: number[];
199
-    normalStart: number[];
200
-    pressureStart: number;
201
-    end: number[];
202
-    tangentEnd: number[];
203
-    normalEnd: number[];
204
-    pressureEnd: number;
205
-}
206
-export declare abstract class TLShapeUtil<T extends TLShape> {
207
-    boundsCache: WeakMap<TLShape, TLBounds>;
208
-    isEditableText: boolean;
209
-    isAspectRatioLocked: boolean;
210
-    canEdit: boolean;
211
-    canBind: boolean;
212
-    abstract type: T['type'];
213
-    abstract defaultProps: T;
214
-    abstract render(shape: T, info: TLRenderInfo): JSX.Element;
215
-    abstract renderIndicator(shape: T): JSX.Element | null;
216
-    abstract getBounds(shape: T): TLBounds;
217
-    abstract getRotatedBounds(shape: T): TLBounds;
218
-    abstract hitTest(shape: T, point: number[]): boolean;
219
-    abstract hitTestBounds(shape: T, bounds: TLBounds): boolean;
220
-    abstract transform(shape: T, bounds: TLBounds, info: TLTransformInfo<T>): Partial<T>;
221
-    transformSingle(shape: T, bounds: TLBounds, info: TLTransformInfo<T>): Partial<T>;
222
-    shouldRender(_prev: T, _next: T): boolean;
223
-    shouldDelete(_shape: T): boolean;
224
-    getCenter(shape: T): number[];
225
-    getBindingPoint(shape: T, point: number[], origin: number[], direction: number[], padding: number, anywhere: boolean): {
226
-        point: number[];
227
-        distance: number;
228
-    } | undefined;
229
-    create(props: Partial<T>): T;
230
-    mutate(shape: T, props: Partial<T>): T;
231
-    updateChildren<K extends TLShape>(_shape: T, _children: K[]): Partial<K>[] | void;
232
-    onChildrenChange(_shape: T, _children: TLShape[]): Partial<T> | void;
233
-    onBindingChange(_shape: T, _binding: TLBinding, _target: TLShape, _targetBounds: TLBounds, _center: number[]): Partial<T> | void;
234
-    onHandleChange(_shape: T, _handle: Partial<T['handles']>, _info: Partial<TLPointerInfo>): Partial<T> | void;
235
-    onRightPointHandle(_shape: T, _handle: Partial<T['handles']>, _info: Partial<TLPointerInfo>): Partial<T> | void;
236
-    onDoubleClickHandle(_shape: T, _handle: Partial<T['handles']>, _info: Partial<TLPointerInfo>): Partial<T> | void;
237
-    onSessionComplete(_shape: T): Partial<T> | void;
238
-    onBoundsReset(_shape: T): Partial<T> | void;
239
-    onStyleChange(_shape: T): Partial<T> | void;
240
-}
241
-export interface IShapeTreeNode {
242
-    shape: TLShape;
243
-    children?: IShapeTreeNode[];
244
-    isEditing: boolean;
245
-    isBinding: boolean;
246
-    isDarkMode: boolean;
247
-    isCurrentParent: boolean;
248
-}
249
-export declare type MappedByType<T extends {
250
-    type: string;
251
-}> = {
252
-    [P in T['type']]: T extends any ? (P extends T['type'] ? T : never) : never;
253
-};
254
-export declare type RequiredKeys<T> = {
255
-    [K in keyof T]-?: Record<string, unknown> extends Pick<T, K> ? never : K;
256
-}[keyof T];
257
-export {};

packages/core/src/types.tsx → packages/core/src/types.ts 查看文件

@@ -1,3 +1,5 @@
1
+/* eslint-disable @typescript-eslint/no-unused-vars */
2
+/* eslint-disable @typescript-eslint/no-explicit-any */
1 3
 /* --------------------- Primary -------------------- */
2 4
 
3 5
 export interface TLPage<T extends TLShape, B extends TLBinding> {
@@ -316,57 +318,57 @@ export abstract class TLShapeUtil<T extends TLShape> {
316 318
     return { ...shape, ...props }
317 319
   }
318 320
 
319
-  updateChildren<K extends TLShape>(_shape: T, _children: K[]): Partial<K>[] | void {
321
+  updateChildren<K extends TLShape>(shape: T, children: K[]): Partial<K>[] | void {
320 322
     return
321 323
   }
322 324
 
323
-  onChildrenChange(_shape: T, _children: TLShape[]): Partial<T> | void {
325
+  onChildrenChange(shape: T, children: TLShape[]): Partial<T> | void {
324 326
     return
325 327
   }
326 328
 
327 329
   onBindingChange(
328
-    _shape: T,
329
-    _binding: TLBinding,
330
-    _target: TLShape,
331
-    _targetBounds: TLBounds,
332
-    _center: number[]
330
+    shape: T,
331
+    binding: TLBinding,
332
+    target: TLShape,
333
+    targetBounds: TLBounds,
334
+    center: number[]
333 335
   ): Partial<T> | void {
334 336
     return undefined
335 337
   }
336 338
 
337 339
   onHandleChange(
338
-    _shape: T,
339
-    _handle: Partial<T['handles']>,
340
-    _info: Partial<TLPointerInfo>
340
+    shape: T,
341
+    handle: Partial<T['handles']>,
342
+    info: Partial<TLPointerInfo>
341 343
   ): Partial<T> | void {
342 344
     return
343 345
   }
344 346
 
345 347
   onRightPointHandle(
346
-    _shape: T,
347
-    _handle: Partial<T['handles']>,
348
-    _info: Partial<TLPointerInfo>
348
+    shape: T,
349
+    handle: Partial<T['handles']>,
350
+    info: Partial<TLPointerInfo>
349 351
   ): Partial<T> | void {
350 352
     return
351 353
   }
352 354
 
353 355
   onDoubleClickHandle(
354
-    _shape: T,
355
-    _handle: Partial<T['handles']>,
356
-    _info: Partial<TLPointerInfo>
356
+    shape: T,
357
+    handle: Partial<T['handles']>,
358
+    info: Partial<TLPointerInfo>
357 359
   ): Partial<T> | void {
358 360
     return
359 361
   }
360 362
 
361
-  onSessionComplete(_shape: T): Partial<T> | void {
363
+  onSessionComplete(shape: T): Partial<T> | void {
362 364
     return
363 365
   }
364 366
 
365
-  onBoundsReset(_shape: T): Partial<T> | void {
367
+  onBoundsReset(shape: T): Partial<T> | void {
366 368
     return
367 369
   }
368 370
 
369
-  onStyleChange(_shape: T): Partial<T> | void {
371
+  onStyleChange(shape: T): Partial<T> | void {
370 372
     return
371 373
   }
372 374
 }
@@ -394,5 +396,3 @@ export type MappedByType<T extends { type: string }> = {
394 396
 export type RequiredKeys<T> = {
395 397
   [K in keyof T]-?: Record<string, unknown> extends Pick<T, K> ? never : K
396 398
 }[keyof T]
397
-
398
-export {}

+ 0
- 1
packages/core/src/utils/index.ts 查看文件

@@ -1,5 +1,4 @@
1 1
 import { Utils } from './utils'
2
-
3 2
 export { Intersect } from './intersect'
4 3
 export { Utils } from './utils'
5 4
 export { Svg } from './svg'

+ 8
- 0
packages/core/src/utils/intersect.ts 查看文件

@@ -559,13 +559,21 @@ export class Intersect {
559 559
     // Get an intersection between an ellipse and a second ellipse.
560 560
     // Adapted from https://gist.github.com/drawable/92792f59b6ff8869d8b1
561 561
     ellipse(
562
+      // eslint-disable-next-line @typescript-eslint/no-unused-vars
562 563
       _c1: number[],
564
+      // eslint-disable-next-line @typescript-eslint/no-unused-vars
563 565
       _rx1: number,
566
+      // eslint-disable-next-line @typescript-eslint/no-unused-vars
564 567
       _ry1: number,
568
+      // eslint-disable-next-line @typescript-eslint/no-unused-vars
565 569
       _r1: number,
570
+      // eslint-disable-next-line @typescript-eslint/no-unused-vars
566 571
       _c2: number[],
572
+      // eslint-disable-next-line @typescript-eslint/no-unused-vars
567 573
       _rx2: number,
574
+      // eslint-disable-next-line @typescript-eslint/no-unused-vars
568 575
       _ry2: number,
576
+      // eslint-disable-next-line @typescript-eslint/no-unused-vars
569 577
       _r2: number
570 578
     ): TLIntersection {
571 579
       // TODO

+ 1
- 3
packages/core/src/utils/polyfills.ts 查看文件

@@ -9,7 +9,7 @@
9 9
  */
10 10
 if (!String.prototype.replaceAll) {
11 11
   // @ts-ignore
12
-  String.prototype.replaceAll = function(str: string, newStr: string) {
12
+  String.prototype.replaceAll = function (str: string, newStr: string) {
13 13
     // If a regex pattern
14 14
     if (Object.prototype.toString.call(str).toLowerCase() === '[object regexp]') {
15 15
       return this.replace(str, newStr)
@@ -19,5 +19,3 @@ if (!String.prototype.replaceAll) {
19 19
     return this.replace(new RegExp(str, 'g'), newStr)
20 20
   }
21 21
 }
22
-
23
-export {}

+ 3
- 5
packages/core/src/utils/utils.ts 查看文件

@@ -1,3 +1,4 @@
1
+/* eslint-disable @typescript-eslint/no-extra-semi */
1 2
 /* eslint-disable @typescript-eslint/ban-types */
2 3
 /* eslint-disable @typescript-eslint/no-explicit-any */
3 4
 /* eslint-disable no-redeclare */
@@ -1634,16 +1635,13 @@ left past the initial left edge) then swap points on that axis.
1634 1635
     let inThrottle: boolean
1635 1636
     let lastResult: ReturnType<T>
1636 1637
 
1637
-    return function (this: any): ReturnType<T> {
1638
-      const args = arguments
1639
-      const context = this
1640
-
1638
+    return function (this: any, ...args: any[]): ReturnType<T> {
1641 1639
       if (!inThrottle) {
1642 1640
         inThrottle = true
1643 1641
 
1644 1642
         setTimeout(() => (inThrottle = false), limit)
1645 1643
 
1646
-        lastResult = func.apply(context, args as any)
1644
+        lastResult = func.apply(this, ...args)
1647 1645
       }
1648 1646
 
1649 1647
       return lastResult

+ 33
- 3
packages/core/tsconfig.json 查看文件

@@ -1,12 +1,42 @@
1 1
 {
2
-  "extends": "../../tsconfig.json",
3 2
   "include": ["src"],
4 3
   "exclude": ["node_modules", "**/*.test.ts", "dist"],
5 4
   "compilerOptions": {
6
-    "baseUrl": "src",
5
+    "allowSyntheticDefaultImports": true,
6
+    "declaration": true,
7
+    "esModuleInterop": true,
8
+    "experimentalDecorators": true,
9
+    "forceConsistentCasingInFileNames": true,
10
+    "importsNotUsedAsValues": "error",
11
+    "incremental": true,
12
+    "importHelpers": true,
13
+    "moduleResolution": "node",
14
+    "noEmit": false,
15
+    "noFallthroughCasesInSwitch": true /* Report errors for fallthrough cases in switch statement. */,
16
+    "noImplicitAny": true /* Raise error on expressions and declarations with an implied 'any' type. */,
17
+    "noImplicitReturns": true /* Report error when not all code paths in function return a value. */,
18
+    "noUnusedLocals": false /* Report errors on unused locals. */,
19
+    "noUnusedParameters": false /* Report errors on unused parameters. */,
20
+    "skipLibCheck": true,
21
+    "sourceMap": true,
22
+    "strict": false,
23
+    "strictFunctionTypes": true /* Enable strict checking of function types. */,
24
+    "strictNullChecks": true /* Enable strict null checks. */,
25
+    "target": "es5",
26
+    "typeRoots": ["node_modules/@types", "node_modules/jest"],
27
+    "types": ["node", "jest"],
28
+    //
29
+    "rootDir": "src",
7 30
     "jsx": "preserve",
8 31
     "lib": ["dom", "esnext"],
9 32
     "module": "esnext",
10
-    "outDir": "./dist/types"
33
+    "outDir": "./dist/types",
34
+    "baseUrl": "src",
35
+    "paths": {
36
+      "~utils": ["./utils/index.ts"],
37
+      "~types": ["./types.ts"],
38
+      "~inputs": ["./inputs.ts"],
39
+      "~hooks": ["./hooks/index.ts"]
40
+    }
11 41
   }
12 42
 }

+ 9
- 2
packages/dev/src/components/editor.tsx 查看文件

@@ -1,6 +1,13 @@
1 1
 import * as React from 'react'
2
-import { ColorStyle, DashStyle, SizeStyle, TLDrawShapeType, TLDrawState } from '@tldraw/tldraw'
3
-import { TLDraw, TLDrawDocument } from '@tldraw/tldraw'
2
+import {
3
+  TLDraw,
4
+  TLDrawDocument,
5
+  ColorStyle,
6
+  DashStyle,
7
+  SizeStyle,
8
+  TLDrawShapeType,
9
+  TLDrawState,
10
+} from '@tldraw/tldraw'
4 11
 import { usePersistence } from '../hooks/usePersistence'
5 12
 
6 13
 const initialDoc: TLDrawDocument = {

+ 2
- 1
packages/tldraw/package.json 查看文件

@@ -19,7 +19,7 @@
19 19
   "types": "./dist/types/index.d.ts",
20 20
   "typings": "./dist/types/index.d.ts",
21 21
   "scripts": {
22
-    "dev": "node scripts/dev & tsc --watch --incremental --emitDeclarationOnly --outDir dist/types",
22
+    "dev": "node scripts/dev & tsc --watch --incremental --emitDeclarationOnly --declarationMap --outDir dist/types",
23 23
     "build": "yarn clean && node scripts/build && tsc --emitDeclarationOnly --outDir dist/types",
24 24
     "lint": "eslint src/ --ext .ts,.tsx",
25 25
     "clean": "rm -rf dist",
@@ -28,6 +28,7 @@
28 28
   },
29 29
   "devDependencies": {
30 30
     "@tldraw/core": "*",
31
+    "@types/jest": "^27.0.1",
31 32
     "@types/node": "^15.0.1",
32 33
     "@types/react": "^17.0.16",
33 34
     "@types/react-dom": "^17.0.9",

+ 156
- 163
packages/tldraw/src/components/context-menu/context-menu.tsx 查看文件

@@ -1,9 +1,9 @@
1 1
 import * as React from 'react'
2 2
 import { Utils } from '@tldraw/core'
3 3
 import * as RadixContextMenu from '@radix-ui/react-context-menu'
4
-import styled from '../../styles'
5
-import { useTLDrawContext } from '../../hooks'
6
-import type { Data } from '../../state/state-types'
4
+import styled from '~styles'
5
+import { useTLDrawContext } from '~hooks'
6
+import type { Data } from '~types'
7 7
 import { Kbd } from '../kbd'
8 8
 import {
9 9
   IconWrapper,
@@ -17,7 +17,7 @@ import {
17 17
   ContextMenuRoot,
18 18
   MenuContent,
19 19
 } from '../shared'
20
-import { AlignType, DistributeType, StretchType } from '../../types'
20
+import { AlignType, DistributeType, StretchType } from '~types'
21 21
 import {
22 22
   ChevronRightIcon,
23 23
   AlignBottomIcon,
@@ -47,176 +47,169 @@ const isDebugModeSelector = (s: Data) => {
47 47
 }
48 48
 
49 49
 const hasGroupSelectedSelector = (s: Data) => {
50
-  return s.pageState.selectedIds.some(
51
-    (id) => s.page.shapes[id].children !== undefined
52
-  )
50
+  return s.pageState.selectedIds.some((id) => s.page.shapes[id].children !== undefined)
53 51
 }
54 52
 
55 53
 interface ContextMenuProps {
56 54
   children: React.ReactNode
57 55
 }
58 56
 
59
-export const ContextMenu = React.memo(
60
-  ({ children }: ContextMenuProps): JSX.Element => {
61
-    const { tlstate, useSelector } = useTLDrawContext()
62
-    const hasSelection = useSelector(has1SelectedIdsSelector)
63
-    const hasTwoOrMore = useSelector(has2SelectedIdsSelector)
64
-    const hasThreeOrMore = useSelector(has3SelectedIdsSelector)
65
-    const isDebugMode = useSelector(isDebugModeSelector)
66
-    const hasGroupSelected = useSelector(hasGroupSelectedSelector)
67
-
68
-    const rContent = React.useRef<HTMLDivElement>(null)
69
-
70
-    const handleFlipHorizontal = React.useCallback(() => {
71
-      tlstate.flipHorizontal()
72
-    }, [tlstate])
73
-
74
-    const handleFlipVertical = React.useCallback(() => {
75
-      tlstate.flipVertical()
76
-    }, [tlstate])
77
-
78
-    const handleDuplicate = React.useCallback(() => {
79
-      tlstate.duplicate()
80
-    }, [tlstate])
81
-
82
-    const handleGroup = React.useCallback(() => {
83
-      tlstate.group()
84
-    }, [tlstate])
85
-
86
-    const handleMoveToBack = React.useCallback(() => {
87
-      tlstate.moveToBack()
88
-    }, [tlstate])
89
-
90
-    const handleMoveBackward = React.useCallback(() => {
91
-      tlstate.moveBackward()
92
-    }, [tlstate])
93
-
94
-    const handleMoveForward = React.useCallback(() => {
95
-      tlstate.moveForward()
96
-    }, [tlstate])
97
-
98
-    const handleMoveToFront = React.useCallback(() => {
99
-      tlstate.moveToFront()
100
-    }, [tlstate])
101
-
102
-    const handleDelete = React.useCallback(() => {
103
-      tlstate.delete()
104
-    }, [tlstate])
105
-
106
-    const handleCopyAsJson = React.useCallback(() => {
107
-      tlstate.copyAsJson()
108
-    }, [tlstate])
109
-
110
-    const handleCopyAsSvg = React.useCallback(() => {
111
-      tlstate.copyAsSvg()
112
-    }, [tlstate])
113
-
114
-    const handleUndo = React.useCallback(() => {
115
-      tlstate.undo()
116
-    }, [tlstate])
117
-
118
-    const handleRedo = React.useCallback(() => {
119
-      tlstate.redo()
120
-    }, [tlstate])
121
-
122
-    if (Utils.isMobile()) {
123
-      return <>{children}</>
124
-    }
125
-
126
-    return (
127
-      <ContextMenuRoot>
128
-        <RadixContextMenu.Trigger>{children}</RadixContextMenu.Trigger>
129
-        <MenuContent as={RadixContextMenu.Content} ref={rContent}>
130
-          {hasSelection ? (
131
-            <>
132
-              <ContextMenuButton onSelect={handleFlipHorizontal}>
133
-                <span>Flip Horizontal</span>
134
-                <Kbd variant="menu">⇧H</Kbd>
135
-              </ContextMenuButton>
136
-              <ContextMenuButton onSelect={handleFlipVertical}>
137
-                <span>Flip Vertical</span>
138
-                <Kbd variant="menu">⇧V</Kbd>
139
-              </ContextMenuButton>
140
-              <ContextMenuButton onSelect={handleDuplicate}>
141
-                <span>Duplicate</span>
142
-                <Kbd variant="menu">#D</Kbd>
57
+export const ContextMenu = React.memo(({ children }: ContextMenuProps): JSX.Element => {
58
+  const { tlstate, useSelector } = useTLDrawContext()
59
+  const hasSelection = useSelector(has1SelectedIdsSelector)
60
+  const hasTwoOrMore = useSelector(has2SelectedIdsSelector)
61
+  const hasThreeOrMore = useSelector(has3SelectedIdsSelector)
62
+  const isDebugMode = useSelector(isDebugModeSelector)
63
+  const hasGroupSelected = useSelector(hasGroupSelectedSelector)
64
+
65
+  const rContent = React.useRef<HTMLDivElement>(null)
66
+
67
+  const handleFlipHorizontal = React.useCallback(() => {
68
+    tlstate.flipHorizontal()
69
+  }, [tlstate])
70
+
71
+  const handleFlipVertical = React.useCallback(() => {
72
+    tlstate.flipVertical()
73
+  }, [tlstate])
74
+
75
+  const handleDuplicate = React.useCallback(() => {
76
+    tlstate.duplicate()
77
+  }, [tlstate])
78
+
79
+  const handleGroup = React.useCallback(() => {
80
+    tlstate.group()
81
+  }, [tlstate])
82
+
83
+  const handleMoveToBack = React.useCallback(() => {
84
+    tlstate.moveToBack()
85
+  }, [tlstate])
86
+
87
+  const handleMoveBackward = React.useCallback(() => {
88
+    tlstate.moveBackward()
89
+  }, [tlstate])
90
+
91
+  const handleMoveForward = React.useCallback(() => {
92
+    tlstate.moveForward()
93
+  }, [tlstate])
94
+
95
+  const handleMoveToFront = React.useCallback(() => {
96
+    tlstate.moveToFront()
97
+  }, [tlstate])
98
+
99
+  const handleDelete = React.useCallback(() => {
100
+    tlstate.delete()
101
+  }, [tlstate])
102
+
103
+  const handleCopyAsJson = React.useCallback(() => {
104
+    tlstate.copyAsJson()
105
+  }, [tlstate])
106
+
107
+  const handleCopyAsSvg = React.useCallback(() => {
108
+    tlstate.copyAsSvg()
109
+  }, [tlstate])
110
+
111
+  const handleUndo = React.useCallback(() => {
112
+    tlstate.undo()
113
+  }, [tlstate])
114
+
115
+  const handleRedo = React.useCallback(() => {
116
+    tlstate.redo()
117
+  }, [tlstate])
118
+
119
+  if (Utils.isMobile()) {
120
+    return <>{children}</>
121
+  }
122
+
123
+  return (
124
+    <ContextMenuRoot>
125
+      <RadixContextMenu.Trigger>{children}</RadixContextMenu.Trigger>
126
+      <MenuContent as={RadixContextMenu.Content} ref={rContent}>
127
+        {hasSelection ? (
128
+          <>
129
+            <ContextMenuButton onSelect={handleFlipHorizontal}>
130
+              <span>Flip Horizontal</span>
131
+              <Kbd variant="menu">⇧H</Kbd>
132
+            </ContextMenuButton>
133
+            <ContextMenuButton onSelect={handleFlipVertical}>
134
+              <span>Flip Vertical</span>
135
+              <Kbd variant="menu">⇧V</Kbd>
136
+            </ContextMenuButton>
137
+            <ContextMenuButton onSelect={handleDuplicate}>
138
+              <span>Duplicate</span>
139
+              <Kbd variant="menu">#D</Kbd>
140
+            </ContextMenuButton>
141
+            <ContextMenuDivider />
142
+            {hasGroupSelected ||
143
+              (hasTwoOrMore && (
144
+                <>
145
+                  {hasGroupSelected && (
146
+                    <ContextMenuButton onSelect={handleGroup}>
147
+                      <span>Ungroup</span>
148
+                      <Kbd variant="menu">#⇧G</Kbd>
149
+                    </ContextMenuButton>
150
+                  )}
151
+                  {hasTwoOrMore && (
152
+                    <ContextMenuButton onSelect={handleGroup}>
153
+                      <span>Group</span>
154
+                      <Kbd variant="menu">#G</Kbd>
155
+                    </ContextMenuButton>
156
+                  )}
157
+                </>
158
+              ))}
159
+            <ContextMenuSubMenu label="Move">
160
+              <ContextMenuButton onSelect={handleMoveToFront}>
161
+                <span>To Front</span>
162
+                <Kbd variant="menu"># ⇧ ]</Kbd>
143 163
               </ContextMenuButton>
144
-              <ContextMenuDivider />
145
-              {hasGroupSelected ||
146
-                (hasTwoOrMore && (
147
-                  <>
148
-                    {hasGroupSelected && (
149
-                      <ContextMenuButton onSelect={handleGroup}>
150
-                        <span>Ungroup</span>
151
-                        <Kbd variant="menu">#⇧G</Kbd>
152
-                      </ContextMenuButton>
153
-                    )}
154
-                    {hasTwoOrMore && (
155
-                      <ContextMenuButton onSelect={handleGroup}>
156
-                        <span>Group</span>
157
-                        <Kbd variant="menu">#G</Kbd>
158
-                      </ContextMenuButton>
159
-                    )}
160
-                  </>
161
-                ))}
162
-              <ContextMenuSubMenu label="Move">
163
-                <ContextMenuButton onSelect={handleMoveToFront}>
164
-                  <span>To Front</span>
165
-                  <Kbd variant="menu"># ⇧ ]</Kbd>
166
-                </ContextMenuButton>
167
-                <ContextMenuButton onSelect={handleMoveForward}>
168
-                  <span>Forward</span>
169
-                  <Kbd variant="menu"># ]</Kbd>
170
-                </ContextMenuButton>
171
-                <ContextMenuButton onSelect={handleMoveBackward}>
172
-                  <span>Backward</span>
173
-                  <Kbd variant="menu"># [</Kbd>
174
-                </ContextMenuButton>
175
-                <ContextMenuButton onSelect={handleMoveToBack}>
176
-                  <span>To Back</span>
177
-                  <Kbd variant="menu"># ⇧ [</Kbd>
178
-                </ContextMenuButton>
179
-              </ContextMenuSubMenu>
180
-              {hasTwoOrMore && (
181
-                <AlignDistributeSubMenu
182
-                  hasTwoOrMore={hasTwoOrMore}
183
-                  hasThreeOrMore={hasThreeOrMore}
184
-                />
185
-              )}
186
-              {/* <MoveToPageMenu /> */}
187
-              {isDebugMode && (
188
-                <ContextMenuButton onSelect={handleCopyAsJson}>
189
-                  <span>Copy Data</span>
190
-                  <Kbd variant="menu"># ⇧ C</Kbd>
191
-                </ContextMenuButton>
192
-              )}
193
-              <ContextMenuButton onSelect={handleCopyAsSvg}>
194
-                <span>Copy to SVG</span>
195
-                <Kbd variant="menu"># ⇧ C</Kbd>
164
+              <ContextMenuButton onSelect={handleMoveForward}>
165
+                <span>Forward</span>
166
+                <Kbd variant="menu"># ]</Kbd>
196 167
               </ContextMenuButton>
197
-              <ContextMenuDivider />
198
-              <ContextMenuButton onSelect={handleDelete}>
199
-                <span>Delete</span>
200
-                <Kbd variant="menu">⌫</Kbd>
168
+              <ContextMenuButton onSelect={handleMoveBackward}>
169
+                <span>Backward</span>
170
+                <Kbd variant="menu"># [</Kbd>
201 171
               </ContextMenuButton>
202
-            </>
203
-          ) : (
204
-            <>
205
-              <ContextMenuButton onSelect={handleUndo}>
206
-                <span>Undo</span>
207
-                <Kbd variant="menu"># Z</Kbd>
172
+              <ContextMenuButton onSelect={handleMoveToBack}>
173
+                <span>To Back</span>
174
+                <Kbd variant="menu"># ⇧ [</Kbd>
208 175
               </ContextMenuButton>
209
-              <ContextMenuButton onSelect={handleRedo}>
210
-                <span>Redo</span>
211
-                <Kbd variant="menu"># ⇧ Z</Kbd>
176
+            </ContextMenuSubMenu>
177
+            {hasTwoOrMore && (
178
+              <AlignDistributeSubMenu hasTwoOrMore={hasTwoOrMore} hasThreeOrMore={hasThreeOrMore} />
179
+            )}
180
+            {/* <MoveToPageMenu /> */}
181
+            {isDebugMode && (
182
+              <ContextMenuButton onSelect={handleCopyAsJson}>
183
+                <span>Copy Data</span>
184
+                <Kbd variant="menu"># ⇧ C</Kbd>
212 185
               </ContextMenuButton>
213
-            </>
214
-          )}
215
-        </MenuContent>
216
-      </ContextMenuRoot>
217
-    )
218
-  }
219
-)
186
+            )}
187
+            <ContextMenuButton onSelect={handleCopyAsSvg}>
188
+              <span>Copy to SVG</span>
189
+              <Kbd variant="menu"># ⇧ C</Kbd>
190
+            </ContextMenuButton>
191
+            <ContextMenuDivider />
192
+            <ContextMenuButton onSelect={handleDelete}>
193
+              <span>Delete</span>
194
+              <Kbd variant="menu">⌫</Kbd>
195
+            </ContextMenuButton>
196
+          </>
197
+        ) : (
198
+          <>
199
+            <ContextMenuButton onSelect={handleUndo}>
200
+              <span>Undo</span>
201
+              <Kbd variant="menu"># Z</Kbd>
202
+            </ContextMenuButton>
203
+            <ContextMenuButton onSelect={handleRedo}>
204
+              <span>Redo</span>
205
+              <Kbd variant="menu"># ⇧ Z</Kbd>
206
+            </ContextMenuButton>
207
+          </>
208
+        )}
209
+      </MenuContent>
210
+    </ContextMenuRoot>
211
+  )
212
+})
220 213
 
221 214
 function AlignDistributeSubMenu({
222 215
   hasThreeOrMore,

+ 0
- 4
packages/tldraw/src/components/icons/Redo.svg 查看文件

@@ -1,4 +0,0 @@
1
-<svg width="15" height="15" viewBox="0 0 15 15" fill="none" xmlns="http://www.w3.org/2000/svg">
2
-<path fill-rule="evenodd" clip-rule="evenodd" d="M12.5 2.49538C12.2239 2.49538 12 2.71923 12 2.99538V5.49559H9.49979C9.22364 5.49559 8.99979 5.71945 8.99979 5.99559C8.99979 6.27173 9.22364 6.49559 9.49979 6.49559H12.5C12.7761 6.49559 13 6.27173 13 5.99559V2.99538C13 2.71923 12.7761 2.49538 12.5 2.49538Z" fill="black"/>
3
-<path fill-rule="evenodd" clip-rule="evenodd" d="M7.69698 2.04877C6.62345 1.89773 5.52991 2.09968 4.58113 2.62417C3.63236 3.14867 2.87973 3.9673 2.43667 4.95673C1.99361 5.94616 1.8841 7.05278 2.12465 8.10985C2.3652 9.16693 2.94278 10.1172 3.77036 10.8175C4.59794 11.5177 5.63069 11.9301 6.713 11.9924C7.79531 12.0547 8.86855 11.7635 9.77101 11.1628C10.6735 10.5621 11.3563 9.68441 11.7165 8.66191C11.8083 8.40146 11.6715 8.11593 11.4111 8.02417C11.1506 7.93241 10.8651 8.06916 10.7733 8.32961C10.4851 9.14762 9.93888 9.84981 9.21691 10.3304C8.49493 10.811 7.63632 11.0439 6.77046 10.994C5.9046 10.9442 5.07839 10.6143 4.41631 10.0541C3.75424 9.49386 3.29217 8.73363 3.09972 7.88796C2.90728 7.04229 2.99488 6.15698 3.34934 5.36542C3.7038 4.57387 4.30591 3.91895 5.06494 3.49935C5.82398 3.07974 6.69882 2.91819 7.55765 3.03902C8.41649 3.15985 9.21279 3.55653 9.82658 4.16928L9.83745 4.17981L12.1576 6.35996C12.3588 6.54906 12.6753 6.53921 12.8644 6.33797C13.0535 6.13673 13.0436 5.8203 12.8424 5.63121L10.5276 3.4561C9.76111 2.69329 8.76794 2.19945 7.69698 2.04877Z" fill="black"/>
4
-</svg>

+ 0
- 6
packages/tldraw/src/components/icons/Trash.svg 查看文件

@@ -1,6 +0,0 @@
1
-<svg width="15" height="15" viewBox="0 0 15 15" fill="none" xmlns="http://www.w3.org/2000/svg">
2
-<path fill-rule="evenodd" clip-rule="evenodd" d="M2 4.65555C2 4.37941 2.22386 4.15555 2.5 4.15555H12.2C12.4761 4.15555 12.7 4.37941 12.7 4.65555C12.7 4.93169 12.4761 5.15555 12.2 5.15555H2.5C2.22386 5.15555 2 4.93169 2 4.65555Z" fill="black"/>
3
-<path fill-rule="evenodd" clip-rule="evenodd" d="M6.27208 3C6.11885 3 5.97189 3.06087 5.86353 3.16923C5.75518 3.27758 5.6943 3.42454 5.6943 3.57778V4.15556H9.00542V3.57778C9.00542 3.42454 8.94454 3.27758 8.83619 3.16923C8.72783 3.06087 8.58087 3 8.42764 3H6.27208ZM10.0054 4.15556V3.57778C10.0054 3.15933 9.83919 2.75801 9.54329 2.46212C9.2474 2.16623 8.84609 2 8.42764 2H6.27208C5.85363 2 5.45232 2.16623 5.15642 2.46212C4.86053 2.75801 4.6943 3.15933 4.6943 3.57778V4.15556H3.57764C3.30149 4.15556 3.07764 4.37941 3.07764 4.65556V12.2C3.07764 12.6185 3.24387 13.0198 3.53976 13.3157C3.83565 13.6115 4.23696 13.7778 4.65541 13.7778H10.0443C10.4628 13.7778 10.8641 13.6115 11.16 13.3157C11.4559 13.0198 11.6221 12.6185 11.6221 12.2V4.65556C11.6221 4.37941 11.3982 4.15556 11.1221 4.15556H10.0054ZM4.07764 5.15556V12.2C4.07764 12.3532 4.13851 12.5002 4.24686 12.6086C4.35522 12.7169 4.50218 12.7778 4.65541 12.7778H10.0443C10.1975 12.7778 10.3445 12.7169 10.4529 12.6086C10.5612 12.5002 10.6221 12.3532 10.6221 12.2V5.15556H4.07764Z" fill="black"/>
4
-<path fill-rule="evenodd" clip-rule="evenodd" d="M6.27246 6.85001C6.5486 6.85001 6.77246 7.07386 6.77246 7.35001V10.5833C6.77246 10.8595 6.5486 11.0833 6.27246 11.0833C5.99632 11.0833 5.77246 10.8595 5.77246 10.5833V7.35001C5.77246 7.07386 5.99632 6.85001 6.27246 6.85001Z" fill="black"/>
5
-<path fill-rule="evenodd" clip-rule="evenodd" d="M8.42773 6.85001C8.70388 6.85001 8.92773 7.07386 8.92773 7.35001V10.5833C8.92773 10.8595 8.70388 11.0833 8.42773 11.0833C8.15159 11.0833 7.92773 10.8595 7.92773 10.5833V7.35001C7.92773 7.07386 8.15159 6.85001 8.42773 6.85001Z" fill="black"/>
6
-</svg>

+ 0
- 4
packages/tldraw/src/components/icons/Undo.svg 查看文件

@@ -1,4 +0,0 @@
1
-<svg width="15" height="15" viewBox="0 0 15 15" fill="none" xmlns="http://www.w3.org/2000/svg">
2
-<path fill-rule="evenodd" clip-rule="evenodd" d="M2.5 2.49538C2.77614 2.49538 3 2.71923 3 2.99538V5.49559H5.50021C5.77636 5.49559 6.00021 5.71945 6.00021 5.99559C6.00021 6.27173 5.77636 6.49559 5.50021 6.49559H2.5C2.22386 6.49559 2 6.27173 2 5.99559V2.99538C2 2.71923 2.22386 2.49538 2.5 2.49538Z" fill="black"/>
3
-<path fill-rule="evenodd" clip-rule="evenodd" d="M7.30302 2.04877C8.37655 1.89773 9.47009 2.09968 10.4189 2.62417C11.3676 3.14867 12.1203 3.9673 12.5633 4.95673C13.0064 5.94616 13.1159 7.05278 12.8753 8.10985C12.6348 9.16693 12.0572 10.1172 11.2296 10.8175C10.4021 11.5177 9.36931 11.9301 8.287 11.9924C7.20469 12.0547 6.13145 11.7635 5.22899 11.1628C4.32653 10.5621 3.64374 9.68441 3.2835 8.66191C3.19174 8.40146 3.32849 8.11593 3.58894 8.02417C3.84939 7.93241 4.13492 8.06916 4.22668 8.32961C4.51488 9.14762 5.06112 9.84981 5.78309 10.3304C6.50507 10.811 7.36368 11.0439 8.22954 10.994C9.0954 10.9442 9.92161 10.6143 10.5837 10.0541C11.2458 9.49386 11.7078 8.73363 11.9003 7.88796C12.0927 7.04229 12.0051 6.15698 11.6507 5.36542C11.2962 4.57387 10.6941 3.91895 9.93506 3.49935C9.17602 3.07974 8.30118 2.91819 7.44235 3.03902C6.58351 3.15985 5.78721 3.55653 5.17342 4.16928L5.16255 4.17981L2.84239 6.35996C2.64115 6.54906 2.32472 6.53921 2.13562 6.33797C1.94653 6.13673 1.95637 5.8203 2.15761 5.63121L4.47241 3.4561C5.23889 2.69329 6.23206 2.19945 7.30302 2.04877Z" fill="black"/>
4
-</svg>

+ 1
- 1
packages/tldraw/src/components/kbd.tsx 查看文件

@@ -1,5 +1,5 @@
1 1
 import * as React from 'react'
2
-import styled from '../styles'
2
+import styled from '~styles'
3 3
 import { Utils } from '@tldraw/core'
4 4
 
5 5
 export function commandKey(): string {

+ 6
- 31
packages/tldraw/src/components/shared.tsx 查看文件

@@ -24,7 +24,7 @@ import {
24 24
 } from '@radix-ui/react-dropdown-menu'
25 25
 import { Root as RGRoot } from '@radix-ui/react-radio-group'
26 26
 import { CheckIcon, ChevronRightIcon } from '@radix-ui/react-icons'
27
-import styled from '../styles'
27
+import styled from '~styles'
28 28
 
29 29
 export const breakpoints: any = { '@initial': 'mobile', '@sm': 'small' }
30 30
 
@@ -408,12 +408,7 @@ export function MenuButton({
408 408
   children: React.ReactNode
409 409
 }): JSX.Element {
410 410
   return (
411
-    <RowButton
412
-      bp={breakpoints}
413
-      disabled={disabled}
414
-      warn={warn}
415
-      onSelect={onSelect}
416
-    >
411
+    <RowButton bp={breakpoints} disabled={disabled} warn={warn} onSelect={onSelect}>
417 412
       {children}
418 413
     </RowButton>
419 414
   )
@@ -499,12 +494,7 @@ export function DropdownMenuButton({
499 494
   children: React.ReactNode
500 495
 }): JSX.Element {
501 496
   return (
502
-    <DMItem
503
-      as={RowButton}
504
-      bp={breakpoints}
505
-      disabled={disabled}
506
-      onSelect={onSelect}
507
-    >
497
+    <DMItem as={RowButton} bp={breakpoints} disabled={disabled} onSelect={onSelect}>
508 498
       {children}
509 499
     </DMItem>
510 500
   )
@@ -522,12 +512,7 @@ export function DropdownMenuIconButton({
522 512
   disabled = false,
523 513
 }: DropdownMenuIconButtonProps): JSX.Element {
524 514
   return (
525
-    <DMItem
526
-      as={IconButton}
527
-      bp={breakpoints}
528
-      disabled={disabled}
529
-      onSelect={onSelect}
530
-    >
515
+    <DMItem as={IconButton} bp={breakpoints} disabled={disabled} onSelect={onSelect}>
531 516
       {children}
532 517
     </DMItem>
533 518
   )
@@ -646,12 +631,7 @@ export function ContextMenuButton({
646 631
   children: React.ReactNode
647 632
 }): JSX.Element {
648 633
   return (
649
-    <RowButton
650
-      as={CMItem}
651
-      bp={breakpoints}
652
-      disabled={disabled}
653
-      onSelect={onSelect}
654
-    >
634
+    <RowButton as={CMItem} bp={breakpoints} disabled={disabled} onSelect={onSelect}>
655 635
       {children}
656 636
     </RowButton>
657 637
   )
@@ -667,12 +647,7 @@ export function ContextMenuIconButton({
667 647
   children: React.ReactNode
668 648
 }): JSX.Element {
669 649
   return (
670
-    <CMItem
671
-      as={IconButton}
672
-      bp={breakpoints}
673
-      disabled={disabled}
674
-      onSelect={onSelect}
675
-    >
650
+    <CMItem as={IconButton} bp={breakpoints} disabled={disabled} onSelect={onSelect}>
676 651
       {children}
677 652
     </CMItem>
678 653
   )

+ 2
- 2
packages/tldraw/src/components/style-panel/align-distribute.tsx 查看文件

@@ -11,9 +11,9 @@ import {
11 11
   StretchHorizontallyIcon,
12 12
   StretchVerticallyIcon,
13 13
 } from '@radix-ui/react-icons'
14
-import { AlignType, DistributeType, StretchType } from '../../types'
14
+import { AlignType, DistributeType, StretchType } from '~types'
15
+import { useTLDrawContext } from '~hooks'
15 16
 import { breakpoints, ButtonsRow, IconButton } from '../shared'
16
-import { useTLDrawContext } from '../../hooks'
17 17
 
18 18
 export interface AlignDistributeProps {
19 19
   hasTwoOrMore: boolean

+ 42
- 48
packages/tldraw/src/components/style-panel/quick-color-select.tsx 查看文件

@@ -2,56 +2,50 @@ import * as React from 'react'
2 2
 import * as DropdownMenu from '@radix-ui/react-dropdown-menu'
3 3
 import { BoxIcon, StyleDropdownItem, StyleDropdownContent } from './shared'
4 4
 import { DropdownMenuIconTriggerButton } from '../shared'
5
-import { ColorStyle, strokes } from '../../shape'
6
-import { useTheme } from '../../hooks/useTheme'
7
-import { useTLDrawContext } from '../../hooks'
8
-import type { Data } from '../../state'
5
+import { strokes } from '~shape'
6
+import { useTheme, useTLDrawContext } from '~hooks'
7
+import type { Data, ColorStyle } from '~types'
9 8
 
10 9
 const selectColor = (data: Data) => data.appState.selectedStyle.color
11 10
 
12
-export const QuickColorSelect = React.memo(
13
-  (): JSX.Element => {
14
-    const { theme } = useTheme()
15
-    const { tlstate, useSelector } = useTLDrawContext()
16
-    const color = useSelector(selectColor)
11
+export const QuickColorSelect = React.memo((): JSX.Element => {
12
+  const { theme } = useTheme()
13
+  const { tlstate, useSelector } = useTLDrawContext()
14
+  const color = useSelector(selectColor)
17 15
 
18
-    const handleColorChange = React.useCallback(
19
-      (color) => {
20
-        tlstate.style({ color: color as ColorStyle })
21
-      },
22
-      [tlstate]
23
-    )
16
+  const handleColorChange = React.useCallback(
17
+    (color) => {
18
+      tlstate.style({ color: color as ColorStyle })
19
+    },
20
+    [tlstate]
21
+  )
24 22
 
25
-    return (
26
-      <DropdownMenu.Root dir="ltr">
27
-        <DropdownMenuIconTriggerButton label="Color">
28
-          <BoxIcon
29
-            fill={strokes[theme][color]}
30
-            stroke={strokes[theme][color]}
31
-          />
32
-        </DropdownMenuIconTriggerButton>
33
-        <DropdownMenu.Content sideOffset={8}>
34
-          <DropdownMenu.DropdownMenuRadioGroup
35
-            value={color as string}
36
-            onValueChange={handleColorChange}
37
-            as={StyleDropdownContent}
38
-          >
39
-            {Object.keys(strokes[theme]).map((colorStyle: string) => (
40
-              <DropdownMenu.DropdownMenuRadioItem
41
-                as={StyleDropdownItem}
42
-                key={colorStyle}
43
-                title={colorStyle}
44
-                value={colorStyle}
45
-              >
46
-                <BoxIcon
47
-                  fill={strokes[theme][colorStyle as ColorStyle]}
48
-                  stroke={strokes[theme][colorStyle as ColorStyle]}
49
-                />
50
-              </DropdownMenu.DropdownMenuRadioItem>
51
-            ))}
52
-          </DropdownMenu.DropdownMenuRadioGroup>
53
-        </DropdownMenu.Content>
54
-      </DropdownMenu.Root>
55
-    )
56
-  }
57
-)
23
+  return (
24
+    <DropdownMenu.Root dir="ltr">
25
+      <DropdownMenuIconTriggerButton label="Color">
26
+        <BoxIcon fill={strokes[theme][color]} stroke={strokes[theme][color]} />
27
+      </DropdownMenuIconTriggerButton>
28
+      <DropdownMenu.Content sideOffset={8}>
29
+        <DropdownMenu.DropdownMenuRadioGroup
30
+          value={color as string}
31
+          onValueChange={handleColorChange}
32
+          as={StyleDropdownContent}
33
+        >
34
+          {Object.keys(strokes[theme]).map((colorStyle: string) => (
35
+            <DropdownMenu.DropdownMenuRadioItem
36
+              as={StyleDropdownItem}
37
+              key={colorStyle}
38
+              title={colorStyle}
39
+              value={colorStyle}
40
+            >
41
+              <BoxIcon
42
+                fill={strokes[theme][colorStyle as ColorStyle]}
43
+                stroke={strokes[theme][colorStyle as ColorStyle]}
44
+              />
45
+            </DropdownMenu.DropdownMenuRadioItem>
46
+          ))}
47
+        </DropdownMenu.DropdownMenuRadioGroup>
48
+      </DropdownMenu.Content>
49
+    </DropdownMenu.Root>
50
+  )
51
+})

+ 36
- 41
packages/tldraw/src/components/style-panel/quick-dash-select.tsx 查看文件

@@ -9,9 +9,8 @@ import {
9 9
   StyleDropdownContent,
10 10
   StyleDropdownItem,
11 11
 } from './shared'
12
-import { DashStyle } from '../../shape'
13
-import { useTLDrawContext } from '../../hooks'
14
-import type { Data } from '../../state'
12
+import { useTLDrawContext } from '~hooks'
13
+import { DashStyle, Data } from '~types'
15 14
 
16 15
 const dashes = {
17 16
   [DashStyle.Draw]: <DashDrawIcon />,
@@ -22,43 +21,39 @@ const dashes = {
22 21
 
23 22
 const selectDash = (data: Data) => data.appState.selectedStyle.dash
24 23
 
25
-export const QuickDashSelect = React.memo(
26
-  (): JSX.Element => {
27
-    const { tlstate, useSelector } = useTLDrawContext()
28
-    const dash = useSelector(selectDash)
24
+export const QuickDashSelect = React.memo((): JSX.Element => {
25
+  const { tlstate, useSelector } = useTLDrawContext()
26
+  const dash = useSelector(selectDash)
29 27
 
30
-    const changeDashStyle = React.useCallback(
31
-      (dash) => {
32
-        tlstate.style({ dash: dash as DashStyle })
33
-      },
34
-      [tlstate]
35
-    )
28
+  const changeDashStyle = React.useCallback(
29
+    (dash) => {
30
+      tlstate.style({ dash: dash as DashStyle })
31
+    },
32
+    [tlstate]
33
+  )
36 34
 
37
-    return (
38
-      <DropdownMenu.Root dir="ltr">
39
-        <DropdownMenuIconTriggerButton label="Dash">
40
-          {dashes[dash]}
41
-        </DropdownMenuIconTriggerButton>
42
-        <DropdownMenu.Content sideOffset={8}>
43
-          <DropdownMenu.DropdownMenuRadioGroup
44
-            as={StyleDropdownContent}
45
-            direction="vertical"
46
-            value={dash}
47
-            onValueChange={changeDashStyle}
48
-          >
49
-            {Object.keys(DashStyle).map((dashStyle: string) => (
50
-              <DropdownMenu.DropdownMenuRadioItem
51
-                as={StyleDropdownItem}
52
-                key={dashStyle}
53
-                isActive={dash === dashStyle}
54
-                value={dashStyle}
55
-              >
56
-                {dashes[dashStyle as DashStyle]}
57
-              </DropdownMenu.DropdownMenuRadioItem>
58
-            ))}
59
-          </DropdownMenu.DropdownMenuRadioGroup>
60
-        </DropdownMenu.Content>
61
-      </DropdownMenu.Root>
62
-    )
63
-  }
64
-)
35
+  return (
36
+    <DropdownMenu.Root dir="ltr">
37
+      <DropdownMenuIconTriggerButton label="Dash">{dashes[dash]}</DropdownMenuIconTriggerButton>
38
+      <DropdownMenu.Content sideOffset={8}>
39
+        <DropdownMenu.DropdownMenuRadioGroup
40
+          as={StyleDropdownContent}
41
+          direction="vertical"
42
+          value={dash}
43
+          onValueChange={changeDashStyle}
44
+        >
45
+          {Object.keys(DashStyle).map((dashStyle: string) => (
46
+            <DropdownMenu.DropdownMenuRadioItem
47
+              as={StyleDropdownItem}
48
+              key={dashStyle}
49
+              isActive={dash === dashStyle}
50
+              value={dashStyle}
51
+            >
52
+              {dashes[dashStyle as DashStyle]}
53
+            </DropdownMenu.DropdownMenuRadioItem>
54
+          ))}
55
+        </DropdownMenu.DropdownMenuRadioGroup>
56
+      </DropdownMenu.Content>
57
+    </DropdownMenu.Root>
58
+  )
59
+})

+ 30
- 32
packages/tldraw/src/components/style-panel/quick-fill-select.tsx 查看文件

@@ -3,41 +3,39 @@ import * as Checkbox from '@radix-ui/react-checkbox'
3 3
 import { breakpoints, IconButton, IconWrapper } from '../shared'
4 4
 import { BoxIcon, IsFilledFillIcon } from './shared'
5 5
 import { Tooltip } from '../tooltip'
6
-import { useTLDrawContext } from '../../hooks'
7
-import type { Data } from '../../state'
6
+import { useTLDrawContext } from '~hooks'
7
+import type { Data } from '~types'
8 8
 
9 9
 const isFilledSelector = (data: Data) => data.appState.selectedStyle.isFilled
10 10
 
11
-export const QuickFillSelect = React.memo(
12
-  (): JSX.Element => {
13
-    const { tlstate, useSelector } = useTLDrawContext()
11
+export const QuickFillSelect = React.memo((): JSX.Element => {
12
+  const { tlstate, useSelector } = useTLDrawContext()
14 13
 
15
-    const isFilled = useSelector(isFilledSelector)
14
+  const isFilled = useSelector(isFilledSelector)
16 15
 
17
-    const handleIsFilledChange = React.useCallback(
18
-      (isFilled: boolean) => {
19
-        tlstate.style({ isFilled })
20
-      },
21
-      [tlstate]
22
-    )
16
+  const handleIsFilledChange = React.useCallback(
17
+    (isFilled: boolean) => {
18
+      tlstate.style({ isFilled })
19
+    },
20
+    [tlstate]
21
+  )
23 22
 
24
-    return (
25
-      <Checkbox.Root
26
-        dir="ltr"
27
-        as={IconButton}
28
-        bp={breakpoints}
29
-        checked={isFilled}
30
-        onCheckedChange={handleIsFilledChange}
31
-      >
32
-        <Tooltip label="Fill">
33
-          <IconWrapper>
34
-            <BoxIcon />
35
-            <Checkbox.Indicator>
36
-              <IsFilledFillIcon />
37
-            </Checkbox.Indicator>
38
-          </IconWrapper>
39
-        </Tooltip>
40
-      </Checkbox.Root>
41
-    )
42
-  }
43
-)
23
+  return (
24
+    <Checkbox.Root
25
+      dir="ltr"
26
+      as={IconButton}
27
+      bp={breakpoints}
28
+      checked={isFilled}
29
+      onCheckedChange={handleIsFilledChange}
30
+    >
31
+      <Tooltip label="Fill">
32
+        <IconWrapper>
33
+          <BoxIcon />
34
+          <Checkbox.Indicator>
35
+            <IsFilledFillIcon />
36
+          </Checkbox.Indicator>
37
+        </IconWrapper>
38
+      </Tooltip>
39
+    </Checkbox.Root>
40
+  )
41
+})

+ 38
- 41
packages/tldraw/src/components/style-panel/quick-size-select.tsx 查看文件

@@ -2,9 +2,8 @@ import * as React from 'react'
2 2
 import * as DropdownMenu from '@radix-ui/react-dropdown-menu'
3 3
 import { DropdownMenuIconTriggerButton, CircleIcon } from '../shared'
4 4
 import { StyleDropdownContent, StyleDropdownItem } from './shared'
5
-import { SizeStyle } from '../../shape'
6
-import type { Data } from '../../state'
7
-import { useTLDrawContext } from '../../hooks'
5
+import { Data, SizeStyle } from '~types'
6
+import { useTLDrawContext } from '~hooks'
8 7
 
9 8
 const sizes = {
10 9
   [SizeStyle.Small]: 6,
@@ -14,44 +13,42 @@ const sizes = {
14 13
 
15 14
 const selectSize = (data: Data) => data.appState.selectedStyle.size
16 15
 
17
-export const QuickSizeSelect = React.memo(
18
-  (): JSX.Element => {
19
-    const { tlstate, useSelector } = useTLDrawContext()
16
+export const QuickSizeSelect = React.memo((): JSX.Element => {
17
+  const { tlstate, useSelector } = useTLDrawContext()
20 18
 
21
-    const size = useSelector(selectSize)
19
+  const size = useSelector(selectSize)
22 20
 
23
-    const changeSizeStyle = React.useCallback(
24
-      (size: string) => {
25
-        tlstate.style({ size: size as SizeStyle })
26
-      },
27
-      [tlstate]
28
-    )
21
+  const changeSizeStyle = React.useCallback(
22
+    (size: string) => {
23
+      tlstate.style({ size: size as SizeStyle })
24
+    },
25
+    [tlstate]
26
+  )
29 27
 
30
-    return (
31
-      <DropdownMenu.Root dir="ltr">
32
-        <DropdownMenuIconTriggerButton label="Size">
33
-          <CircleIcon size={sizes[size]} stroke="none" fill="currentColor" />
34
-        </DropdownMenuIconTriggerButton>
35
-        <DropdownMenu.Content sideOffset={8}>
36
-          <DropdownMenu.DropdownMenuRadioGroup
37
-            as={StyleDropdownContent}
38
-            direction="vertical"
39
-            value={size}
40
-            onValueChange={changeSizeStyle}
41
-          >
42
-            {Object.keys(SizeStyle).map((sizeStyle: string) => (
43
-              <DropdownMenu.DropdownMenuRadioItem
44
-                key={sizeStyle}
45
-                as={StyleDropdownItem}
46
-                isActive={size === sizeStyle}
47
-                value={sizeStyle}
48
-              >
49
-                <CircleIcon size={sizes[sizeStyle as SizeStyle]} />
50
-              </DropdownMenu.DropdownMenuRadioItem>
51
-            ))}
52
-          </DropdownMenu.DropdownMenuRadioGroup>
53
-        </DropdownMenu.Content>
54
-      </DropdownMenu.Root>
55
-    )
56
-  }
57
-)
28
+  return (
29
+    <DropdownMenu.Root dir="ltr">
30
+      <DropdownMenuIconTriggerButton label="Size">
31
+        <CircleIcon size={sizes[size]} stroke="none" fill="currentColor" />
32
+      </DropdownMenuIconTriggerButton>
33
+      <DropdownMenu.Content sideOffset={8}>
34
+        <DropdownMenu.DropdownMenuRadioGroup
35
+          as={StyleDropdownContent}
36
+          direction="vertical"
37
+          value={size}
38
+          onValueChange={changeSizeStyle}
39
+        >
40
+          {Object.keys(SizeStyle).map((sizeStyle: string) => (
41
+            <DropdownMenu.DropdownMenuRadioItem
42
+              key={sizeStyle}
43
+              as={StyleDropdownItem}
44
+              isActive={size === sizeStyle}
45
+              value={sizeStyle}
46
+            >
47
+              <CircleIcon size={sizes[sizeStyle as SizeStyle]} />
48
+            </DropdownMenu.DropdownMenuRadioItem>
49
+          ))}
50
+        </DropdownMenu.DropdownMenuRadioGroup>
51
+      </DropdownMenu.Content>
52
+    </DropdownMenu.Root>
53
+  )
54
+})

+ 5
- 15
packages/tldraw/src/components/style-panel/shapes-functions.tsx 查看文件

@@ -14,8 +14,8 @@ import {
14 14
   PinTopIcon,
15 15
   RotateCounterClockwiseIcon,
16 16
 } from '@radix-ui/react-icons'
17
-import { useTLDrawContext } from '../../hooks'
18
-import type { Data } from '../../state'
17
+import { useTLDrawContext } from '~hooks'
18
+import type { Data } from '~types'
19 19
 
20 20
 const isAllLockedSelector = (s: Data) => {
21 21
   const { selectedIds } = s.pageState
@@ -39,8 +39,7 @@ const isAllGroupedSelector = (s: Data) => {
39 39
 
40 40
 const hasSelectionSelector = (s: Data) => s.pageState.selectedIds.length > 0
41 41
 
42
-const hasMultipleSelectionSelector = (s: Data) =>
43
-  s.pageState.selectedIds.length > 1
42
+const hasMultipleSelectionSelector = (s: Data) => s.pageState.selectedIds.length > 1
44 43
 
45 44
 export const ShapesFunctions = React.memo(() => {
46 45
   const { tlstate, useSelector } = useTLDrawContext()
@@ -109,11 +108,7 @@ export const ShapesFunctions = React.memo(() => {
109 108
           </Tooltip>
110 109
         </IconButton>
111 110
 
112
-        <IconButton
113
-          disabled={!hasSelection}
114
-          size="small"
115
-          onClick={handleRotate}
116
-        >
111
+        <IconButton disabled={!hasSelection} size="small" onClick={handleRotate}>
117 112
           <Tooltip label="Rotate">
118 113
             <RotateCounterClockwiseIcon />
119 114
           </Tooltip>
@@ -197,12 +192,7 @@ export const ShapesFunctions = React.memo(() => {
197 192
           </Tooltip>
198 193
         </IconButton>
199 194
 
200
-        <IconButton
201
-          bp={breakpoints}
202
-          disabled={!hasSelection}
203
-          size="small"
204
-          onClick={handleDelete}
205
-        >
195
+        <IconButton bp={breakpoints} disabled={!hasSelection} size="small" onClick={handleDelete}>
206 196
           <Tooltip label="Delete" kbd="⌫">
207 197
             <Trash />
208 198
           </Tooltip>

+ 1
- 1
packages/tldraw/src/components/style-panel/shared.tsx 查看文件

@@ -1,5 +1,5 @@
1 1
 import * as React from 'react'
2
-import styled from '../../styles'
2
+import styled from '~styles'
3 3
 
4 4
 export const StyleDropdownContent = styled('div', {
5 5
   display: 'grid',

+ 12
- 17
packages/tldraw/src/components/style-panel/style-panel.tsx 查看文件

@@ -1,4 +1,15 @@
1 1
 import * as React from 'react'
2
+import { Utils } from '@tldraw/core'
3
+import { DotsHorizontalIcon, Cross2Icon } from '@radix-ui/react-icons'
4
+import { useTLDrawContext } from '~hooks'
5
+import type { Data } from '~types'
6
+import { ShapesFunctions } from './shapes-functions'
7
+import { AlignDistribute } from './align-distribute'
8
+import { QuickColorSelect } from './quick-color-select'
9
+import { QuickSizeSelect } from './quick-size-select'
10
+import { QuickDashSelect } from './quick-dash-select'
11
+import { QuickFillSelect } from './quick-fill-select'
12
+import { Tooltip } from '../tooltip'
2 13
 import { Kbd } from '../kbd'
3 14
 import {
4 15
   IconButton,
@@ -9,18 +20,6 @@ import {
9 20
   Divider,
10 21
 } from '../shared'
11 22
 
12
-import type { Data } from '../../state'
13
-import { ShapesFunctions } from './shapes-functions'
14
-import { AlignDistribute } from './align-distribute'
15
-import { QuickColorSelect } from './quick-color-select'
16
-import { QuickSizeSelect } from './quick-size-select'
17
-import { QuickDashSelect } from './quick-dash-select'
18
-import { QuickFillSelect } from './quick-fill-select'
19
-import { Tooltip } from '../tooltip'
20
-import { DotsHorizontalIcon, Cross2Icon } from '@radix-ui/react-icons'
21
-import { Utils } from '@tldraw/core'
22
-import { useTLDrawContext } from '../../hooks'
23
-
24 23
 const isStyleOpenSelector = (s: Data) => s.appState.isStyleOpen
25 24
 
26 25
 export function StylePanel(): JSX.Element {
@@ -79,11 +78,7 @@ function SelectedShapeContent(): JSX.Element {
79 78
         hasThreeOrMore={selectedShapesCount > 2}
80 79
       />
81 80
       <Divider />
82
-      <RowButton
83
-        bp={breakpoints}
84
-        disabled={selectedShapesCount === 0}
85
-        onClick={handleCopy}
86
-      >
81
+      <RowButton bp={breakpoints} disabled={selectedShapesCount === 0} onClick={handleCopy}>
87 82
         <span>Copy</span>
88 83
         {showKbds && <Kbd variant="menu">#C</Kbd>}
89 84
       </RowButton>

+ 4
- 5
packages/tldraw/src/components/tldraw.tsx 查看文件

@@ -1,15 +1,14 @@
1 1
 import * as React from 'react'
2 2
 import { IdProvider } from '@radix-ui/react-id'
3 3
 import { Renderer } from '@tldraw/core'
4
+import styled from '~styles'
5
+import type { Data, TLDrawDocument } from '~types'
6
+import { TLDrawState } from '~state'
7
+import { useKeyboardShortcuts, TLDrawContext } from '~hooks'
4 8
 import { tldrawShapeUtils } from '../shape'
5
-import type { TLDrawDocument } from '../types'
6
-import { useKeyboardShortcuts } from '../hooks'
7
-import styled from '../styles'
8 9
 import { ContextMenu } from './context-menu'
9 10
 import { StylePanel } from './style-panel'
10 11
 import { ToolsPanel } from './tools-panel'
11
-import { Data, TLDrawState } from '../state'
12
-import { TLDrawContext } from '../hooks'
13 12
 
14 13
 export interface TLDrawProps {
15 14
   document?: TLDrawDocument

+ 3
- 3
packages/tldraw/src/components/tools-panel/back-to-content.tsx 查看文件

@@ -1,8 +1,8 @@
1 1
 import * as React from 'react'
2 2
 import { FloatingContainer, RowButton } from '../shared'
3
-import styled from '../../styles'
4
-import type { Data } from '../../state'
5
-import { useTLDrawContext } from '../../hooks'
3
+import styled from '~styles'
4
+import type { Data } from '~types'
5
+import { useTLDrawContext } from '~hooks'
6 6
 
7 7
 const isEmptyCanvasSelector = (s: Data) =>
8 8
   Object.keys(s.page.shapes).length > 0 && s.appState.isEmptyCanvas

+ 1
- 1
packages/tldraw/src/components/tools-panel/shared.tsx 查看文件

@@ -1,7 +1,7 @@
1 1
 import * as React from 'react'
2 2
 import { FloatingContainer } from '../shared'
3 3
 import { Tooltip } from '../tooltip'
4
-import styled from '../../styles'
4
+import styled from '~styles'
5 5
 
6 6
 export const ToolButton = styled('button', {
7 7
   position: 'relative',

+ 3
- 3
packages/tldraw/src/components/tools-panel/status-bar.tsx 查看文件

@@ -1,7 +1,7 @@
1 1
 import * as React from 'react'
2
-import { useTLDrawContext } from '../../hooks'
3
-import type { Data } from '../../state'
4
-import styled from '../../styles'
2
+import { useTLDrawContext } from '~hooks'
3
+import type { Data } from '~types'
4
+import styled from '~styles'
5 5
 
6 6
 const activeToolSelector = (s: Data) => s.appState.activeTool
7 7
 

+ 9
- 8
packages/tldraw/src/components/tools-panel/tools-panel.tsx 查看文件

@@ -1,3 +1,4 @@
1
+import * as React from 'react'
1 2
 import {
2 3
   ArrowTopRightIcon,
3 4
   CircleIcon,
@@ -8,17 +9,15 @@ import {
8 9
   SquareIcon,
9 10
   TextIcon,
10 11
 } from '@radix-ui/react-icons'
11
-import * as React from 'react'
12
+import styled from '~styles'
13
+import { Data, TLDrawShapeType } from '~types'
14
+import { useTLDrawContext } from '~hooks'
12 15
 import { StatusBar } from './status-bar'
13 16
 import { FloatingContainer } from '../shared'
14 17
 import { PrimaryButton, SecondaryButton } from './shared'
15
-import styled from '../../styles'
16 18
 import { UndoRedo } from './undo-redo'
17 19
 import { Zoom } from './zoom'
18 20
 import { BackToContent } from './back-to-content'
19
-import { TLDrawShapeType } from '../../shape'
20
-import { useTLDrawContext } from '../../hooks'
21
-import type { Data } from '../../state'
22 21
 
23 22
 const activeToolSelector = (s: Data) => s.appState.activeTool
24 23
 const isToolLockedSelector = (s: Data) => s.appState.isToolLocked
@@ -130,9 +129,11 @@ export const ToolsPanel = React.memo((): JSX.Element => {
130 129
         </FloatingContainer>
131 130
         <UndoRedo />
132 131
       </RightWrap>
133
-      <StatusWrap>
134
-        <StatusBar />
135
-      </StatusWrap>
132
+      {isDebugMode && (
133
+        <StatusWrap>
134
+          <StatusBar />
135
+        </StatusWrap>
136
+      )}
136 137
     </ToolsPanelContainer>
137 138
   )
138 139
 })

+ 23
- 25
packages/tldraw/src/components/tools-panel/undo-redo.tsx 查看文件

@@ -1,32 +1,30 @@
1 1
 import * as React from 'react'
2
+import { useTLDrawContext } from '~hooks'
2 3
 import { TertiaryButton, TertiaryButtonsContainer } from './shared'
3 4
 import { Undo, Redo, Trash } from '../icons'
4
-import { useTLDrawContext } from '../../hooks'
5 5
 
6
-export const UndoRedo = React.memo(
7
-  (): JSX.Element => {
8
-    const { tlstate } = useTLDrawContext()
6
+export const UndoRedo = React.memo((): JSX.Element => {
7
+  const { tlstate } = useTLDrawContext()
9 8
 
10
-    const handleDelete = React.useCallback(() => {
11
-      tlstate.delete()
12
-    }, [tlstate])
9
+  const handleDelete = React.useCallback(() => {
10
+    tlstate.delete()
11
+  }, [tlstate])
13 12
 
14
-    const handleClear = React.useCallback(() => {
15
-      tlstate.clear()
16
-    }, [tlstate])
13
+  const handleClear = React.useCallback(() => {
14
+    tlstate.clear()
15
+  }, [tlstate])
17 16
 
18
-    return (
19
-      <TertiaryButtonsContainer bp={{ '@initial': 'mobile', '@sm': 'small' }}>
20
-        <TertiaryButton label="Undo" kbd="#Z" onClick={tlstate.undo}>
21
-          <Undo />
22
-        </TertiaryButton>
23
-        <TertiaryButton label="Redo" kbd="#⇧" onClick={tlstate.redo}>
24
-          <Redo />
25
-        </TertiaryButton>
26
-        <TertiaryButton label="Delete" kbd="⌫" onClick={handleDelete} onDoubleClick={handleClear}>
27
-          <Trash />
28
-        </TertiaryButton>
29
-      </TertiaryButtonsContainer>
30
-    )
31
-  }
32
-)
17
+  return (
18
+    <TertiaryButtonsContainer bp={{ '@initial': 'mobile', '@sm': 'small' }}>
19
+      <TertiaryButton label="Undo" kbd="#Z" onClick={tlstate.undo}>
20
+        <Undo />
21
+      </TertiaryButton>
22
+      <TertiaryButton label="Redo" kbd="#⇧" onClick={tlstate.redo}>
23
+        <Redo />
24
+      </TertiaryButton>
25
+      <TertiaryButton label="Delete" kbd="⌫" onClick={handleDelete} onDoubleClick={handleClear}>
26
+        <Trash />
27
+      </TertiaryButton>
28
+    </TertiaryButtonsContainer>
29
+  )
30
+})

+ 16
- 18
packages/tldraw/src/components/tools-panel/zoom.tsx 查看文件

@@ -1,26 +1,24 @@
1 1
 import * as React from 'react'
2 2
 import { ZoomInIcon, ZoomOutIcon } from '@radix-ui/react-icons'
3 3
 import { TertiaryButton, TertiaryButtonsContainer } from './shared'
4
-import { useTLDrawContext } from '../../hooks'
5
-import type { Data } from '../../state'
4
+import { useTLDrawContext } from '~hooks'
5
+import type { Data } from '~types'
6 6
 
7
-export const Zoom = React.memo(
8
-  (): JSX.Element => {
9
-    const { tlstate } = useTLDrawContext()
7
+export const Zoom = React.memo((): JSX.Element => {
8
+  const { tlstate } = useTLDrawContext()
10 9
 
11
-    return (
12
-      <TertiaryButtonsContainer bp={{ '@initial': 'mobile', '@sm': 'small' }}>
13
-        <TertiaryButton label="Zoom Out" kbd={`#−`} onClick={tlstate.zoomOut}>
14
-          <ZoomOutIcon />
15
-        </TertiaryButton>
16
-        <TertiaryButton label="Zoom In" kbd={`#+`} onClick={tlstate.zoomIn}>
17
-          <ZoomInIcon />
18
-        </TertiaryButton>
19
-        <ZoomCounter />
20
-      </TertiaryButtonsContainer>
21
-    )
22
-  }
23
-)
10
+  return (
11
+    <TertiaryButtonsContainer bp={{ '@initial': 'mobile', '@sm': 'small' }}>
12
+      <TertiaryButton label="Zoom Out" kbd={`#−`} onClick={tlstate.zoomOut}>
13
+        <ZoomOutIcon />
14
+      </TertiaryButton>
15
+      <TertiaryButton label="Zoom In" kbd={`#+`} onClick={tlstate.zoomIn}>
16
+        <ZoomInIcon />
17
+      </TertiaryButton>
18
+      <ZoomCounter />
19
+    </TertiaryButtonsContainer>
20
+  )
21
+})
24 22
 
25 23
 const zoomSelector = (s: Data) => s.pageState.camera.zoom
26 24
 

+ 2
- 7
packages/tldraw/src/components/tooltip.tsx 查看文件

@@ -1,6 +1,6 @@
1 1
 import * as RadixTooltip from '@radix-ui/react-tooltip'
2 2
 import * as React from 'react'
3
-import styled from '../styles'
3
+import styled from '~styles'
4 4
 import { Kbd } from './kbd'
5 5
 
6 6
 interface TooltipProps {
@@ -10,12 +10,7 @@ interface TooltipProps {
10 10
   side?: 'bottom' | 'left' | 'right' | 'top'
11 11
 }
12 12
 
13
-export function Tooltip({
14
-  children,
15
-  label,
16
-  kbd,
17
-  side = 'top',
18
-}: TooltipProps): JSX.Element {
13
+export function Tooltip({ children, label, kbd, side = 'top' }: TooltipProps): JSX.Element {
19 14
   return (
20 15
     <RadixTooltip.Root>
21 16
       <RadixTooltip.Trigger as="span">{children}</RadixTooltip.Trigger>

+ 2
- 2
packages/tldraw/src/hooks/useKeyboardShortcuts.tsx 查看文件

@@ -1,8 +1,8 @@
1 1
 import * as React from 'react'
2 2
 import { inputs } from '@tldraw/core'
3 3
 import { useHotkeys } from 'react-hotkeys-hook'
4
-import { TLDrawShapeType } from '../shape'
5
-import type { TLDrawState } from '../state'
4
+import { TLDrawShapeType } from '~types'
5
+import type { TLDrawState } from '~state'
6 6
 
7 7
 export function useKeyboardShortcuts(tlstate: TLDrawState) {
8 8
   React.useEffect(() => {

+ 3
- 5
packages/tldraw/src/hooks/useTLDrawContext.tsx 查看文件

@@ -1,16 +1,14 @@
1 1
 import * as React from 'react'
2
-import type { Data } from '../state/state-types'
2
+import type { Data } from '~types'
3 3
 import type { UseStore } from 'zustand'
4
-import type { TLDrawState } from '../state'
4
+import type { TLDrawState } from '~state'
5 5
 
6 6
 export interface TLDrawContextType {
7 7
   tlstate: TLDrawState
8 8
   useSelector: UseStore<Data>
9 9
 }
10 10
 
11
-export const TLDrawContext = React.createContext<TLDrawContextType>(
12
-  {} as TLDrawContextType
13
-)
11
+export const TLDrawContext = React.createContext<TLDrawContextType>({} as TLDrawContextType)
14 12
 
15 13
 export function useTLDrawContext() {
16 14
   const context = React.useContext(TLDrawContext)

+ 1
- 1
packages/tldraw/src/hooks/useTheme.ts 查看文件

@@ -1,4 +1,4 @@
1
-import type { Theme } from '../shape'
1
+import type { Theme } from '~types'
2 2
 
3 3
 export function useTheme() {
4 4
   return {

+ 0
- 1
packages/tldraw/src/shape/index.ts 查看文件

@@ -1,3 +1,2 @@
1 1
 export * from './shape-utils'
2
-export * from './shape-types'
3 2
 export * from './shape-styles'

+ 1
- 1
packages/tldraw/src/shape/shape-styles.ts 查看文件

@@ -1,5 +1,5 @@
1 1
 import { Utils } from '@tldraw/core'
2
-import { Theme, ColorStyle, DashStyle, ShapeStyles, SizeStyle } from './shape-types'
2
+import { Theme, ColorStyle, DashStyle, ShapeStyles, SizeStyle } from '~types'
3 3
 
4 4
 const canvasLight = '#fafafa'
5 5
 

+ 0
- 160
packages/tldraw/src/shape/shape-types.ts 查看文件

@@ -1,160 +0,0 @@
1
-import type { TLBinding } from '@tldraw/core'
2
-import { TLShape, TLShapeUtil, TLHandle } from '@tldraw/core'
3
-
4
-export enum TLDrawToolType {
5
-  Draw = 'draw',
6
-  Bounds = 'bounds',
7
-  Point = 'point',
8
-  Handle = 'handle',
9
-  Points = 'points',
10
-  Text = 'text',
11
-}
12
-
13
-export enum TLDrawShapeType {
14
-  Ellipse = 'ellipse',
15
-  Rectangle = 'rectangle',
16
-  Draw = 'draw',
17
-  Arrow = 'arrow',
18
-  Text = 'text',
19
-}
20
-
21
-export enum Decoration {
22
-  Arrow = 'Arrow',
23
-}
24
-
25
-export interface TLDrawBaseShape extends TLShape {
26
-  style: ShapeStyles
27
-  type: TLDrawShapeType
28
-}
29
-
30
-export interface DrawShape extends TLDrawBaseShape {
31
-  type: TLDrawShapeType.Draw
32
-  points: number[][]
33
-}
34
-
35
-export interface ArrowShape extends TLDrawBaseShape {
36
-  type: TLDrawShapeType.Arrow
37
-  bend: number
38
-  handles: {
39
-    start: TLHandle
40
-    bend: TLHandle
41
-    end: TLHandle
42
-  }
43
-  decorations?: {
44
-    start?: Decoration
45
-    end?: Decoration
46
-    middle?: Decoration
47
-  }
48
-}
49
-export interface EllipseShape extends TLDrawBaseShape {
50
-  type: TLDrawShapeType.Ellipse
51
-  radius: number[]
52
-}
53
-
54
-export interface RectangleShape extends TLDrawBaseShape {
55
-  type: TLDrawShapeType.Rectangle
56
-  size: number[]
57
-}
58
-
59
-export interface TextShape extends TLDrawBaseShape {
60
-  type: TLDrawShapeType.Text
61
-  text: string
62
-}
63
-
64
-export type TLDrawShape = RectangleShape | EllipseShape | DrawShape | ArrowShape | TextShape
65
-
66
-export abstract class TLDrawShapeUtil<T extends TLDrawShape> extends TLShapeUtil<T> {
67
-  abstract toolType: TLDrawToolType
68
-}
69
-
70
-export type TLDrawShapeUtils = Record<TLDrawShapeType, TLDrawShapeUtil<TLDrawShape>>
71
-
72
-export interface ArrowBinding extends TLBinding {
73
-  type: 'arrow'
74
-  handleId: keyof ArrowShape['handles']
75
-  distance: number
76
-  point: number[]
77
-}
78
-
79
-export type TLDrawBinding = ArrowBinding
80
-
81
-export enum ColorStyle {
82
-  White = 'White',
83
-  LightGray = 'LightGray',
84
-  Gray = 'Gray',
85
-  Black = 'Black',
86
-  Green = 'Green',
87
-  Cyan = 'Cyan',
88
-  Blue = 'Blue',
89
-  Indigo = 'Indigo',
90
-  Violet = 'Violet',
91
-  Red = 'Red',
92
-  Orange = 'Orange',
93
-  Yellow = 'Yellow',
94
-}
95
-
96
-export enum SizeStyle {
97
-  Small = 'Small',
98
-  Medium = 'Medium',
99
-  Large = 'Large',
100
-}
101
-
102
-export enum DashStyle {
103
-  Draw = 'Draw',
104
-  Solid = 'Solid',
105
-  Dashed = 'Dashed',
106
-  Dotted = 'Dotted',
107
-}
108
-
109
-export enum FontSize {
110
-  Small = 'Small',
111
-  Medium = 'Medium',
112
-  Large = 'Large',
113
-  ExtraLarge = 'ExtraLarge',
114
-}
115
-
116
-export type ShapeStyles = {
117
-  color: ColorStyle
118
-  size: SizeStyle
119
-  dash: DashStyle
120
-  isFilled?: boolean
121
-  scale?: number
122
-}
123
-
124
-export type PropsOfType<U> = {
125
-  // eslint-disable-next-line @typescript-eslint/no-explicit-any
126
-  [K in keyof TLDrawShape]: TLDrawShape[K] extends any
127
-    ? TLDrawShape[K] extends U
128
-      ? K
129
-      : never
130
-    : never
131
-}[keyof TLDrawShape]
132
-
133
-export type Theme = 'dark' | 'light'
134
-
135
-export type Difference<A, B, C = A> = A extends B ? never : C
136
-
137
-export type Intersection<A, B, C = A> = A extends B ? C : never
138
-
139
-export type FilteredKeys<T, U> = {
140
-  [P in keyof T]: T[P] extends U ? P : never
141
-}[keyof T]
142
-
143
-export type RequiredKeys<T> = {
144
-  [K in keyof T]-?: Difference<Record<string, unknown>, Pick<T, K>, K>
145
-}[keyof T]
146
-
147
-export type MembersWithRequiredKey<T, U> = {
148
-  [P in keyof T]: Intersection<U, RequiredKeys<T[P]>, T[P]>
149
-}[keyof T]
150
-
151
-export type MappedByType<U extends string, T extends { type: U }> = {
152
-  [P in T['type']]: T extends any ? (P extends T['type'] ? T : never) : never
153
-}
154
-
155
-export type ShapesWithProp<U> = MembersWithRequiredKey<
156
-  MappedByType<TLDrawShapeType, TLDrawShape>,
157
-  U
158
->
159
-
160
-export {}

+ 1
- 1
packages/tldraw/src/shape/shape-utils.tsx 查看文件

@@ -1,5 +1,5 @@
1 1
 import { Rectangle, Ellipse, Arrow, Draw, Text } from './shapes'
2
-import { TLDrawShapeType, TLDrawShape, TLDrawShapeUtil, TLDrawShapeUtils } from './shape-types'
2
+import { TLDrawShapeType, TLDrawShape, TLDrawShapeUtil, TLDrawShapeUtils } from '~types'
3 3
 
4 4
 export const tldrawShapeUtils: TLDrawShapeUtils = {
5 5
   [TLDrawShapeType.Rectangle]: new Rectangle(),

+ 10
- 5
packages/tldraw/src/shape/shapes/arrow/arrow.tsx 查看文件

@@ -8,11 +8,9 @@ import {
8 8
   Intersect,
9 9
   TLHandle,
10 10
   TLPointerInfo,
11
-  TLBinding,
12
-  TLShapeUtil,
13 11
 } from '@tldraw/core'
14 12
 import getStroke from 'perfect-freehand'
15
-import { defaultStyle, getPerfectDashProps, getShapeStyle } from '../../shape-styles'
13
+import { defaultStyle, getPerfectDashProps, getShapeStyle } from '~shape'
16 14
 import {
17 15
   ArrowShape,
18 16
   Decoration,
@@ -22,7 +20,7 @@ import {
22 20
   DashStyle,
23 21
   TLDrawShape,
24 22
   ArrowBinding,
25
-} from '../../shape-types'
23
+} from '~types'
26 24
 
27 25
 export class Arrow extends TLDrawShapeUtil<ArrowShape> {
28 26
   type = TLDrawShapeType.Arrow as const
@@ -122,6 +120,7 @@ export class Arrow extends TLDrawShapeUtil<ArrowShape> {
122 120
             strokeDashoffset="none"
123 121
             strokeLinecap="round"
124 122
             strokeLinejoin="round"
123
+            pointerEvents="stroke"
125 124
           />
126 125
           <path
127 126
             d={path}
@@ -132,6 +131,7 @@ export class Arrow extends TLDrawShapeUtil<ArrowShape> {
132 131
             strokeDashoffset={strokeDashoffset}
133 132
             strokeLinecap="round"
134 133
             strokeLinejoin="round"
134
+            pointerEvents="stroke"
135 135
           />
136 136
         </>
137 137
       )
@@ -181,6 +181,7 @@ export class Arrow extends TLDrawShapeUtil<ArrowShape> {
181 181
             strokeDashoffset="none"
182 182
             strokeLinecap="round"
183 183
             strokeLinejoin="round"
184
+            pointerEvents="stroke"
184 185
           />
185 186
           <path
186 187
             d={path}
@@ -191,6 +192,7 @@ export class Arrow extends TLDrawShapeUtil<ArrowShape> {
191 192
             strokeDashoffset={strokeDashoffset}
192 193
             strokeLinecap="round"
193 194
             strokeLinejoin="round"
195
+            pointerEvents="stroke"
194 196
           />
195 197
         </>
196 198
       )
@@ -199,7 +201,7 @@ export class Arrow extends TLDrawShapeUtil<ArrowShape> {
199 201
     const sw = strokeWidth * 1.618
200 202
 
201 203
     return (
202
-      <g pointerEvents="all">
204
+      <g pointerEvents="none">
203 205
         {shaftPath}
204 206
         {shape.decorations?.start === Decoration.Arrow && (
205 207
           <path
@@ -586,6 +588,9 @@ export class Arrow extends TLDrawShapeUtil<ArrowShape> {
586 588
       },
587 589
     }
588 590
 
591
+    // Zero out the handles to prevent handles with negative points. If a handle's x or y
592
+    // is below zero, we need to move the shape left or up to make it zero.
593
+
589 594
     const bounds = Utils.getBoundsFromPoints(
590 595
       Object.values(nextShape.handles).map((handle) => handle.point)
591 596
     )

+ 2
- 8
packages/tldraw/src/shape/shapes/draw/draw.tsx 查看文件

@@ -1,14 +1,8 @@
1 1
 import * as React from 'react'
2 2
 import { TLBounds, Utils, Vec, TLTransformInfo, TLRenderInfo, Intersect } from '@tldraw/core'
3 3
 import getStroke, { getStrokePoints } from 'perfect-freehand'
4
-import { defaultStyle, getShapeStyle } from '../../shape-styles'
5
-import {
6
-  DrawShape,
7
-  DashStyle,
8
-  TLDrawShapeUtil,
9
-  TLDrawShapeType,
10
-  TLDrawToolType,
11
-} from '../../shape-types'
4
+import { defaultStyle, getShapeStyle } from '~shape'
5
+import { DrawShape, DashStyle, TLDrawShapeUtil, TLDrawShapeType, TLDrawToolType } from '~types'
12 6
 
13 7
 export class Draw extends TLDrawShapeUtil<DrawShape> {
14 8
   type = TLDrawShapeType.Draw as const

+ 2
- 8
packages/tldraw/src/shape/shapes/ellipse/ellipse.tsx 查看文件

@@ -1,13 +1,7 @@
1 1
 import * as React from 'react'
2 2
 import { Utils, TLTransformInfo, TLBounds, Intersect, Vec, TLRenderInfo } from '@tldraw/core'
3
-import {
4
-  DashStyle,
5
-  EllipseShape,
6
-  TLDrawShapeType,
7
-  TLDrawShapeUtil,
8
-  TLDrawToolType,
9
-} from '../../shape-types'
10
-import { defaultStyle, getPerfectDashProps, getShapeStyle } from '../../shape-styles'
3
+import { DashStyle, EllipseShape, TLDrawShapeType, TLDrawShapeUtil, TLDrawToolType } from '~types'
4
+import { defaultStyle, getPerfectDashProps, getShapeStyle } from '~shape'
11 5
 import getStroke from 'perfect-freehand'
12 6
 
13 7
 export class Ellipse extends TLDrawShapeUtil<EllipseShape> {

+ 3
- 9
packages/tldraw/src/shape/shapes/rectangle/rectangle.tsx 查看文件

@@ -1,14 +1,8 @@
1 1
 import * as React from 'react'
2 2
 import { TLBounds, Utils, Vec, TLTransformInfo, TLRenderInfo, Intersect } from '@tldraw/core'
3 3
 import getStroke from 'perfect-freehand'
4
-import { getPerfectDashProps, defaultStyle, getShapeStyle } from '../../shape-styles'
5
-import {
6
-  RectangleShape,
7
-  DashStyle,
8
-  TLDrawShapeUtil,
9
-  TLDrawShapeType,
10
-  TLDrawToolType,
11
-} from '../../shape-types'
4
+import { getPerfectDashProps, defaultStyle, getShapeStyle } from '~shape'
5
+import { RectangleShape, DashStyle, TLDrawShapeUtil, TLDrawShapeType, TLDrawToolType } from '~types'
12 6
 
13 7
 export class Rectangle extends TLDrawShapeUtil<RectangleShape> {
14 8
   type = TLDrawShapeType.Rectangle as const
@@ -308,7 +302,7 @@ export class Rectangle extends TLDrawShapeUtil<RectangleShape> {
308 302
     }
309 303
   }
310 304
 
311
-  transformSingle(shape: RectangleShape, bounds: TLBounds, info: TLTransformInfo<RectangleShape>) {
305
+  transformSingle(shape: RectangleShape, bounds: TLBounds) {
312 306
     return {
313 307
       size: Vec.round([bounds.width, bounds.height]),
314 308
       point: Vec.round([bounds.minX, bounds.minY]),

+ 3
- 3
packages/tldraw/src/shape/shapes/text/text.tsx 查看文件

@@ -1,8 +1,8 @@
1 1
 import * as React from 'react'
2 2
 import { TLBounds, Utils, Vec, TLTransformInfo, TLRenderInfo, Intersect } from '@tldraw/core'
3
-import { defaultStyle, getShapeStyle, getFontSize, getFontStyle } from '../../shape-styles'
4
-import { TextShape, TLDrawShapeUtil, TLDrawShapeType, TLDrawToolType } from '../../shape-types'
5
-import styled from '../../../styles'
3
+import { defaultStyle, getShapeStyle, getFontSize, getFontStyle } from '~shape'
4
+import { TextShape, TLDrawShapeUtil, TLDrawShapeType, TLDrawToolType } from '~types'
5
+import styled from '~styles'
6 6
 import TextAreaUtils from './text-utils'
7 7
 
8 8
 function normalizeText(text: string) {

+ 3
- 3
packages/tldraw/src/state/command/align/align.command.spec.ts 查看文件

@@ -1,6 +1,6 @@
1
-import { TLDrawState } from '../../tlstate'
2
-import { mockDocument } from '../../test-helpers'
3
-import { AlignType } from '../../../types'
1
+import { TLDrawState } from '~state'
2
+import { mockDocument } from '~state/test-helpers'
3
+import { AlignType } from '~types'
4 4
 
5 5
 describe('Align command', () => {
6 6
   const tlstate = new TLDrawState()

+ 4
- 6
packages/tldraw/src/state/command/align/align.command.ts 查看文件

@@ -1,7 +1,7 @@
1 1
 import { Utils } from '@tldraw/core'
2
-import { AlignType } from '../../../types'
3
-import type { Data, Command } from '../../state-types'
4
-import { TLDR } from '../../tldr'
2
+import { AlignType } from '~types'
3
+import type { Data, Command } from '~types'
4
+import { TLDR } from '~state/tldr'
5 5
 
6 6
 export function align(data: Data, ids: string[], type: AlignType): Command {
7 7
   const initialShapes = ids.map((id) => TLDR.getShape(data, id))
@@ -14,9 +14,7 @@ export function align(data: Data, ids: string[], type: AlignType): Command {
14 14
     }
15 15
   })
16 16
 
17
-  const commonBounds = Utils.getCommonBounds(
18
-    boundsForShapes.map(({ bounds }) => bounds)
19
-  )
17
+  const commonBounds = Utils.getCommonBounds(boundsForShapes.map(({ bounds }) => bounds))
20 18
 
21 19
   const midX = commonBounds.minX + commonBounds.width / 2
22 20
   const midY = commonBounds.minY + commonBounds.height / 2

+ 2
- 2
packages/tldraw/src/state/command/create/create.command.spec.ts 查看文件

@@ -1,5 +1,5 @@
1
-import { TLDrawState } from '../../tlstate'
2
-import { mockDocument } from '../../test-helpers'
1
+import { TLDrawState } from '~state'
2
+import { mockDocument } from '~state/test-helpers'
3 3
 
4 4
 describe('Create command', () => {
5 5
   const tlstate = new TLDrawState()

+ 1
- 2
packages/tldraw/src/state/command/create/create.command.ts 查看文件

@@ -1,5 +1,4 @@
1
-import type { TLDrawShape } from '../../../shape'
2
-import type { Data, Command } from '../../state-types'
1
+import type { TLDrawShape, Data, Command } from '~types'
3 2
 
4 3
 export function create(data: Data, shapes: TLDrawShape[]): Command {
5 4
   return {

+ 4
- 4
packages/tldraw/src/state/command/delete/delete.command.spec.ts 查看文件

@@ -1,7 +1,7 @@
1
-import { TLDR } from './../../tldr'
2
-import { TLDrawState } from '../../tlstate'
3
-import { mockDocument } from '../../test-helpers'
4
-import type { TLDrawShape } from '../../../shape'
1
+import { TLDR } from '~state/tldr'
2
+import { TLDrawState } from '~state'
3
+import { mockDocument } from '~state/test-helpers'
4
+import type { TLDrawShape } from '~types'
5 5
 
6 6
 describe('Delete command', () => {
7 7
   const tlstate = new TLDrawState()

+ 1
- 1
packages/tldraw/src/state/command/delete/delete.command.ts 查看文件

@@ -1,4 +1,4 @@
1
-import type { Data, Command, PagePartial } from '../../state-types'
1
+import type { Data, Command, PagePartial } from '~types'
2 2
 
3 3
 // - [x] Delete shapes
4 4
 // - [x] Delete bindings too

+ 3
- 3
packages/tldraw/src/state/command/distribute/distribute.command.spec.ts 查看文件

@@ -1,6 +1,6 @@
1
-import { TLDrawState } from '../../tlstate'
2
-import { mockDocument } from '../../test-helpers'
3
-import { DistributeType } from '../../../types'
1
+import { TLDrawState } from '~state'
2
+import { mockDocument } from '~state/test-helpers'
3
+import { DistributeType } from '~types'
4 4
 
5 5
 describe('Distribute command', () => {
6 6
   const tlstate = new TLDrawState()

+ 8
- 18
packages/tldraw/src/state/command/distribute/distribute.command.ts 查看文件

@@ -1,18 +1,10 @@
1 1
 import { Utils } from '@tldraw/core'
2
-import type { TLDrawShape } from '../../../shape'
3
-import { DistributeType } from '../../../types'
4
-import type { Data, Command } from '../../state-types'
5
-import { TLDR } from '../../tldr'
6
-
7
-export function distribute(
8
-  data: Data,
9
-  ids: string[],
10
-  type: DistributeType
11
-): Command {
2
+import { DistributeType, TLDrawShape, Data, Command } from '~types'
3
+import { TLDR } from '~state/tldr'
4
+
5
+export function distribute(data: Data, ids: string[], type: DistributeType): Command {
12 6
   const initialShapes = ids.map((id) => data.page.shapes[id])
13
-  const deltaMap = Object.fromEntries(
14
-    getDistributions(initialShapes, type).map((d) => [d.id, d])
15
-  )
7
+  const deltaMap = Object.fromEntries(getDistributions(initialShapes, type).map((d) => [d.id, d]))
16 8
 
17 9
   const { before, after } = TLDR.mutateShapes(data, ids, (shape) => {
18 10
     if (!deltaMap[shape.id]) return shape
@@ -50,9 +42,7 @@ function getDistributions(initialShapes: TLDrawShape[], type: DistributeType) {
50 42
   })
51 43
 
52 44
   const len = entries.length
53
-  const commonBounds = Utils.getCommonBounds(
54
-    entries.map(({ bounds }) => bounds)
55
-  )
45
+  const commonBounds = Utils.getCommonBounds(entries.map(({ bounds }) => bounds))
56 46
 
57 47
   const results: { id: string; prev: number[]; next: number[] }[] = []
58 48
 
@@ -86,7 +76,7 @@ function getDistributions(initialShapes: TLDrawShape[], type: DistributeType) {
86 76
         let x = commonBounds.minX
87 77
         const step = (commonBounds.width - span) / (len - 1)
88 78
 
89
-        entriesToMove.forEach(({ id, point, bounds }, i) => {
79
+        entriesToMove.forEach(({ id, point, bounds }) => {
90 80
           results.push({ id, prev: point, next: [x, bounds.minY] })
91 81
           x += bounds.width + step
92 82
         })
@@ -122,7 +112,7 @@ function getDistributions(initialShapes: TLDrawShape[], type: DistributeType) {
122 112
         let y = commonBounds.minY
123 113
         const step = (commonBounds.height - span) / (len - 1)
124 114
 
125
-        entriesToMove.forEach(({ id, point, bounds }, i) => {
115
+        entriesToMove.forEach(({ id, point, bounds }) => {
126 116
           results.push({ id, prev: point, next: [bounds.minX, y] })
127 117
           y += bounds.height + step
128 118
         })

+ 0
- 0
packages/tldraw/src/state/command/duplicate/duplicate.command.spec.ts 查看文件


部分文件因为文件数量过多而无法显示

正在加载...
取消
保存