Selaa lähdekoodia

Adds text again

main
Steve Ruiz 4 vuotta sitten
vanhempi
commit
8fe83ef6c3

+ 4
- 0
packages/dev/esbuild.config.mjs Näytä tiedosto

@@ -21,6 +21,10 @@ esbuild
21 21
     minify: false,
22 22
     sourcemap: true,
23 23
     incremental: isDevServer,
24
+    assetNames: 'assets/[name]-[hash]',
25
+    loader: {
26
+      '.woff': 'file',
27
+    },
24 28
     target: ['chrome58', 'firefox57', 'safari11', 'edge18'],
25 29
     define: {
26 30
       'process.env.NODE_ENV': isDevServer ? '"development"' : '"production"',

+ 1
- 1
packages/dev/package.json Näytä tiedosto

@@ -34,4 +34,4 @@
34 34
     "typescript": "4.2.3"
35 35
   },
36 36
   "gitHead": "a7dac0f83ad998e205c2aab58182cb4ba4e099a6"
37
-}
37
+}

BIN
packages/dev/src/assets/VerveineRegular.woff Näytä tiedosto


+ 1
- 105
packages/dev/src/components/editor.tsx Näytä tiedosto

@@ -1,110 +1,6 @@
1 1
 import * as React from 'react'
2
-import {
3
-  TLDraw,
4
-  TLDrawDocument,
5
-  ColorStyle,
6
-  DashStyle,
7
-  SizeStyle,
8
-  TLDrawShapeType,
9
-  TLDrawState,
10
-  TLDrawPatch,
11
-} from '@tldraw/tldraw'
12
-import { usePersistence } from '../hooks/usePersistence'
13
-
14
-const initialDoc: TLDrawDocument = {
15
-  id: 'doc',
16
-  pages: {
17
-    page1: {
18
-      id: 'page1',
19
-      shapes: {
20
-        rect1: {
21
-          id: 'rect1',
22
-          parentId: 'page1',
23
-          name: 'Rectangle',
24
-          childIndex: 1,
25
-          type: TLDrawShapeType.Rectangle,
26
-          point: [32, 32],
27
-          size: [100, 100],
28
-          style: {
29
-            dash: DashStyle.Draw,
30
-            size: SizeStyle.Medium,
31
-            color: ColorStyle.Blue,
32
-          },
33
-        },
34
-        ellipse1: {
35
-          id: 'ellipse1',
36
-          parentId: 'page1',
37
-          name: 'Ellipse',
38
-          childIndex: 2,
39
-          type: TLDrawShapeType.Ellipse,
40
-          point: [132, 132],
41
-          radius: [50, 50],
42
-          style: {
43
-            dash: DashStyle.Draw,
44
-            size: SizeStyle.Medium,
45
-            color: ColorStyle.Cyan,
46
-          },
47
-        },
48
-        draw1: {
49
-          id: 'draw1',
50
-          parentId: 'page1',
51
-          name: 'Draw',
52
-          childIndex: 3,
53
-          type: TLDrawShapeType.Draw,
54
-          point: [232, 232],
55
-          points: [
56
-            [50, 0],
57
-            [100, 100],
58
-            [0, 100],
59
-            [50, 0],
60
-            [100, 100],
61
-            [0, 100],
62
-            [50, 0],
63
-            [56, 5],
64
-          ],
65
-          style: {
66
-            dash: DashStyle.Draw,
67
-            size: SizeStyle.Medium,
68
-            color: ColorStyle.Green,
69
-          },
70
-        },
71
-      },
72
-      bindings: {},
73
-    },
74
-  },
75
-  pageStates: {
76
-    page1: {
77
-      id: 'page1',
78
-      selectedIds: [],
79
-      currentParentId: 'page1',
80
-      camera: {
81
-        point: [0, 0],
82
-        zoom: 1,
83
-      },
84
-    },
85
-  },
86
-}
2
+import { TLDraw } from '@tldraw/tldraw'
87 3
 
88 4
 export default function Editor(): JSX.Element {
89
-  // const { value, setValue, status } = usePersistence('doc', initialDoc)
90
-
91
-  // const handleChange = React.useCallback(
92
-  //   (tlstate: TLDrawState, patch: TLDrawPatch, reason: string) => {
93
-  //     if (reason.startsWith('session')) {
94
-  //       return
95
-  //     }
96
-
97
-  //     setValue(tlstate.document)
98
-  //   },
99
-  //   [setValue]
100
-  // )
101
-
102
-  // if (status === 'loading' || value === null) {
103
-  //   return <div />
104
-  // }
105
-
106
-  // return <TLDraw document={value} onChange={handleChange} />
107
-
108
-  // Will automatically persist data under the provided id, too
109 5
   return <TLDraw id="tldraw" />
110 6
 }

+ 8
- 7
packages/tldraw/scripts/build.js Näytä tiedosto

@@ -9,6 +9,14 @@ async function main() {
9 9
     fs.mkdirSync('./dist')
10 10
   }
11 11
 
12
+  fs.copyFileSync('package.json', 'dist/package.json', (err) => {
13
+    if (err) throw err
14
+  })
15
+
16
+  fs.copyFileSync('README.md', 'dist/README.md', (err) => {
17
+    if (err) throw err
18
+  })
19
+
12 20
   try {
13 21
     esbuild.buildSync({
14 22
       entryPoints: ['./src/index.ts'],
@@ -36,13 +44,6 @@ async function main() {
36 44
       external: ['react', 'react-dom'],
37 45
     })
38 46
 
39
-    fs.copyFile('package.json', 'dist/package.json', (err) => {
40
-      if (err) throw err
41
-    })
42
-    fs.copyFile('README.md', 'dist/README.md', (err) => {
43
-      if (err) throw err
44
-    })
45
-
46 47
     console.log(`✔ ${name}: Built package.`)
47 48
   } catch (e) {
48 49
     console.log(`× ${name}: Build failed due to an error.`)

+ 2
- 2
packages/tldraw/scripts/dev.js Näytä tiedosto

@@ -9,8 +9,8 @@ async function main() {
9 9
     outdir: 'dist/cjs',
10 10
     minify: false,
11 11
     bundle: true,
12
-    format: 'esm',
13
-    target: 'cjs',
12
+    format: 'cjs',
13
+    target: 'es6',
14 14
     jsxFactory: 'React.createElement',
15 15
     jsxFragment: 'React.Fragment',
16 16
     tsconfig: './tsconfig.build.json',

+ 7
- 0
packages/tldraw/scripts/pre-dev.js Näytä tiedosto

@@ -1,5 +1,6 @@
1 1
 /* eslint-disable */
2 2
 const fs = require('fs')
3
+const path = require('path')
3 4
 const esbuild = require('esbuild')
4 5
 
5 6
 async function main() {
@@ -21,6 +22,12 @@ async function main() {
21 22
     tsconfig: './tsconfig.build.json',
22 23
     external: ['react', 'react-dom'],
23 24
   })
25
+
26
+  var files = fs.readdirSync('src/assets')
27
+
28
+  for (var i = 0; i < files.length; i++) {
29
+    fs.copyFileSync(path.join('src/assets', files[i]), path.join('dist', files[i]))
30
+  }
24 31
 }
25 32
 
26 33
 main()

BIN
packages/tldraw/src/assets/VerveineRegular.woff Näytä tiedosto


+ 3
- 1
packages/tldraw/src/components/tldraw/tldraw.tsx Näytä tiedosto

@@ -4,7 +4,7 @@ import { Renderer } from '@tldraw/core'
4 4
 import styled from '~styles'
5 5
 import type { Data, TLDrawDocument } from '~types'
6 6
 import { TLDrawState } from '~state'
7
-import { useKeyboardShortcuts, TLDrawContext } from '~hooks'
7
+import { useKeyboardShortcuts, TLDrawContext, useCustomFonts } from '~hooks'
8 8
 import { tldrawShapeUtils } from '~shape'
9 9
 import { ContextMenu } from '~components/context-menu'
10 10
 import { StylePanel } from '~components/style-panel'
@@ -63,6 +63,8 @@ export function TLDraw({ id, document, currentPageId, onMount, onChange: _onChan
63 63
 
64 64
   useKeyboardShortcuts(tlstate)
65 65
 
66
+  useCustomFonts()
67
+
66 68
   const page = context.useSelector(pageSelector)
67 69
 
68 70
   const pageState = context.useSelector(pageStateSelector)

+ 1
- 0
packages/tldraw/src/hooks/index.ts Näytä tiedosto

@@ -1,3 +1,4 @@
1 1
 export * from './useKeyboardShortcuts'
2 2
 export * from './useTLDrawContext'
3 3
 export * from './useTheme'
4
+export * from './useCustomFonts'

+ 18
- 0
packages/tldraw/src/hooks/useCustomFonts.ts Näytä tiedosto

@@ -0,0 +1,18 @@
1
+import { useStyle, css } from '~hooks/useStyle'
2
+
3
+// const customFonts = css`
4
+//   @font-face {
5
+//     font-family: 'Verveine Regular';
6
+//     font-style: normal;
7
+//     font-weight: normal;
8
+//     src: local('Verveine Regular'), url('/VerveineRegular.woff') format('woff');
9
+//   }
10
+// `
11
+
12
+const customFonts = css`
13
+  @import url('https://fonts.googleapis.com/css2?family=Caveat+Brush&display=swap');
14
+`
15
+
16
+export function useCustomFonts() {
17
+  useStyle('tldraw-fonts', customFonts)
18
+}

+ 30
- 0
packages/tldraw/src/hooks/useStyle.ts Näytä tiedosto

@@ -0,0 +1,30 @@
1
+import * as React from 'react'
2
+
3
+const styles = new Map<string, HTMLStyleElement>()
4
+
5
+export const css = (strings: TemplateStringsArray, ...args: unknown[]) =>
6
+  strings.reduce(
7
+    (acc, string, index) => acc + string + (index < args.length ? args[index] : ''),
8
+    ''
9
+  )
10
+
11
+export function useStyle(uid: string, rules: string) {
12
+  React.useLayoutEffect(() => {
13
+    if (styles.get(uid)) {
14
+      return () => void null
15
+    }
16
+
17
+    const style = document.createElement('style')
18
+    style.innerHTML = rules
19
+    style.setAttribute('id', uid)
20
+    document.head.appendChild(style)
21
+    styles.set(uid, style)
22
+
23
+    return () => {
24
+      if (style && document.head.contains(style)) {
25
+        document.head.removeChild(style)
26
+        styles.delete(uid)
27
+      }
28
+    }
29
+  }, [uid, rules])
30
+}

+ 1
- 1
packages/tldraw/src/shape/shape-styles.ts Näytä tiedosto

@@ -69,7 +69,7 @@ export function getFontStyle(style: ShapeStyles): string {
69 69
   const fontSize = getFontSize(style.size)
70 70
   const { scale = 1 } = style
71 71
 
72
-  return `${fontSize * scale}px/1.4 Verveine Regular`
72
+  return `${fontSize * scale}px/1.3 "Caveat Brush"`
73 73
 }
74 74
 
75 75
 export function getShapeStyle(

+ 23
- 15
packages/tldraw/src/shape/shapes/text/text.tsx Näytä tiedosto

@@ -16,16 +16,16 @@ function normalizeText(text: string) {
16 16
 }
17 17
 
18 18
 // eslint-disable-next-line @typescript-eslint/no-explicit-any
19
-let mdiv: any
19
+let melm: any
20 20
 
21 21
 function getMeasurementDiv() {
22 22
   // A div used for measurement
23 23
   document.getElementById('__textMeasure')?.remove()
24 24
 
25
-  const mdiv = document.createElement('pre')
26
-  mdiv.id = '__textMeasure'
25
+  const pre = document.createElement('pre')
26
+  pre.id = '__textMeasure'
27 27
 
28
-  Object.assign(mdiv.style, {
28
+  Object.assign(pre.style, {
29 29
     whiteSpace: 'pre',
30 30
     width: 'auto',
31 31
     border: '1px solid red',
@@ -42,14 +42,14 @@ function getMeasurementDiv() {
42 42
     dominantBaseline: 'mathematical',
43 43
   })
44 44
 
45
-  mdiv.tabIndex = -1
45
+  pre.tabIndex = -1
46 46
 
47
-  document.body.appendChild(mdiv)
48
-  return mdiv
47
+  document.body.appendChild(pre)
48
+  return pre
49 49
 }
50 50
 
51 51
 if (typeof window !== 'undefined') {
52
-  getMeasurementDiv()
52
+  melm = getMeasurementDiv()
53 53
 }
54 54
 
55 55
 export class Text extends TLDrawShapeUtil<TextShape> {
@@ -69,10 +69,17 @@ export class Text extends TLDrawShapeUtil<TextShape> {
69 69
     childIndex: 1,
70 70
     point: [0, 0],
71 71
     rotation: 0,
72
-    text: 'hi',
72
+    text: ' ',
73 73
     style: defaultStyle,
74 74
   }
75 75
 
76
+  create(props: Partial<TextShape>): TextShape {
77
+    const shape = { ...this.defaultProps, ...props }
78
+    const bounds = this.getBounds(shape)
79
+    shape.point = Vec.sub(shape.point, [bounds.width / 2, bounds.height / 2])
80
+    return shape
81
+  }
82
+
76 83
   shouldRender(prev: TextShape, next: TextShape): boolean {
77 84
     return (
78 85
       next.text !== prev.text || next.style.scale !== prev.style.scale || next.style !== prev.style
@@ -149,7 +156,7 @@ export class Text extends TLDrawShapeUtil<TextShape> {
149 156
     }
150 157
 
151 158
     const fontSize = getFontSize(shape.style.size) * (shape.style.scale || 1)
152
-    const lineHeight = fontSize * 1.4
159
+    const lineHeight = fontSize * 1.3
153 160
 
154 161
     if (!isEditing) {
155 162
       return (
@@ -168,7 +175,7 @@ export class Text extends TLDrawShapeUtil<TextShape> {
168 175
               key={i}
169 176
               x={4}
170 177
               y={4 + fontSize / 2 + i * lineHeight}
171
-              fontFamily="Verveine Regular"
178
+              fontFamily="Caveat Brush"
172 179
               fontStyle="normal"
173 180
               fontWeight="500"
174 181
               fontSize={fontSize}
@@ -237,15 +244,16 @@ export class Text extends TLDrawShapeUtil<TextShape> {
237 244
 
238 245
   getBounds(shape: TextShape): TLBounds {
239 246
     const bounds = Utils.getFromCache(this.boundsCache, shape, () => {
240
-      if (!mdiv) {
247
+      if (!melm) {
248
+        console.log('no melm!')
241 249
         // We're in SSR
242 250
         return { minX: 0, minY: 0, maxX: 0, maxY: 0, width: 0, height: 0 }
243 251
       }
244 252
 
245
-      mdiv.innerHTML = `${shape.text}&zwj;`
246
-      mdiv.style.font = getFontStyle(shape.style)
253
+      melm.innerHTML = `${shape.text}&zwj;`
254
+      melm.style.font = getFontStyle(shape.style)
247 255
 
248
-      const [width, height] = [mdiv.offsetWidth, mdiv.offsetHeight]
256
+      const [width, height] = [melm.offsetWidth, melm.offsetHeight]
249 257
 
250 258
       return {
251 259
         minX: 0,

+ 2
- 2
packages/tldraw/src/state/session/sessions/text/text.session.spec.ts Näytä tiedosto

@@ -16,7 +16,7 @@ describe('Text session', () => {
16 16
         })
17 17
       )
18 18
       .select('text1')
19
-      .startTextSession()
19
+      .startTextSession('text1')
20 20
       .updateTextSession('Hello world')
21 21
       .completeSession()
22 22
       .undo()
@@ -35,7 +35,7 @@ describe('Text session', () => {
35 35
         })
36 36
       )
37 37
       .select('text1')
38
-      .startTextSession()
38
+      .startTextSession('text1')
39 39
       .updateTextSession('Hello world')
40 40
       .cancelSession()
41 41
 

+ 46
- 0
packages/tldraw/src/state/session/sessions/text/text.session.ts Näytä tiedosto

@@ -85,6 +85,51 @@ export class TextSession implements Session {
85 85
 
86 86
     const shape = TLDR.getShape<TextShape>(data, initialShape.id, pageId)
87 87
 
88
+    // TODO: Delete text shape if its content is empty
89
+    // TODO: ...and prevent `isCreating` from selecting the deleted shape
90
+
91
+    // if (initialShape.text.trim() === '' && shape.text.trim() === '') {
92
+    //   // delete shape
93
+    //   console.log('deleting shape')
94
+    //   return {
95
+    //     id: 'text',
96
+    //     before: {
97
+    //       document: {
98
+    //         pages: {
99
+    //           [pageId]: {
100
+    //             shapes: {
101
+    //               [initialShape.id]: undefined,
102
+    //             },
103
+    //           },
104
+    //         },
105
+    //         pageState: {
106
+    //           [pageId]: {
107
+    //             editingId: undefined,
108
+    //             selectedIds: [initialShape.id],
109
+    //           },
110
+    //         },
111
+    //       },
112
+    //     },
113
+    //     after: {
114
+    //       document: {
115
+    //         pages: {
116
+    //           [pageId]: {
117
+    //             shapes: {
118
+    //               [initialShape.id]: undefined,
119
+    //             },
120
+    //           },
121
+    //         },
122
+    //         pageState: {
123
+    //           [pageId]: {
124
+    //             editingId: undefined,
125
+    //             selectedIds: [],
126
+    //           },
127
+    //         },
128
+    //       },
129
+    //     },
130
+    //   }
131
+    // }
132
+
88 133
     if (shape.text === initialShape.text) return undefined
89 134
 
90 135
     return {
@@ -121,6 +166,7 @@ export class TextSession implements Session {
121 166
           pageState: {
122 167
             [pageId]: {
123 168
               editingId: undefined,
169
+              selectedIds: [initialShape.id],
124 170
             },
125 171
           },
126 172
         },

+ 59
- 26
packages/tldraw/src/state/tlstate.ts Näytä tiedosto

@@ -91,15 +91,48 @@ const initialData: Data = {
91 91
 export class TLDrawState extends StateManager<Data> {
92 92
   _onChange?: (tlstate: TLDrawState, data: Data, reason: string) => void
93 93
 
94
-  constructor(id = Utils.uniqueId()) {
95
-    super(initialData, id, 1)
96
-  }
97
-
98 94
   selectHistory: SelectHistory = {
99 95
     stack: [[]],
100 96
     pointer: 0,
101 97
   }
102 98
 
99
+  clipboard?: TLDrawShape[]
100
+
101
+  session?: Session
102
+
103
+  pointedId?: string
104
+
105
+  pointedHandle?: string
106
+
107
+  pointedBoundsHandle?: TLBoundsCorner | TLBoundsEdge | 'rotate'
108
+
109
+  isCreating = false
110
+
111
+  constructor(id = Utils.uniqueId()) {
112
+    super(initialData, id, 1)
113
+
114
+    this.session = undefined
115
+    this.pointedId = undefined
116
+
117
+    this.patchState({
118
+      appState: {
119
+        status: {
120
+          current: TLDrawStatus.Idle,
121
+          previous: TLDrawStatus.Idle,
122
+        },
123
+      },
124
+      document: {
125
+        pageStates: {
126
+          [this.currentPageId]: {
127
+            bindingId: undefined,
128
+            editingId: undefined,
129
+            hoveredId: undefined,
130
+            pointedId: undefined,
131
+          },
132
+        },
133
+      },
134
+    })
135
+  }
103 136
   /* -------------------- Internal -------------------- */
104 137
 
105 138
   protected onStateWillChange = (_state: Data, id: string): void => {
@@ -232,18 +265,6 @@ export class TLDrawState extends StateManager<Data> {
232 265
     })
233 266
   }
234 267
 
235
-  clipboard?: TLDrawShape[]
236
-
237
-  session?: Session
238
-
239
-  pointedId?: string
240
-
241
-  pointedHandle?: string
242
-
243
-  pointedBoundsHandle?: TLBoundsCorner | TLBoundsEdge | 'rotate'
244
-
245
-  isCreating = false
246
-
247 268
   /* -------------------- Settings -------------------- */
248 269
 
249 270
   togglePenMode = (): this => {
@@ -787,6 +808,7 @@ export class TLDrawState extends StateManager<Data> {
787 808
 
788 809
   completeSession<T extends Session>(...args: ParametersExceptFirst<T['complete']>) {
789 810
     const { session } = this
811
+
790 812
     if (!session) return this
791 813
 
792 814
     const result = session.complete(this.state, ...args)
@@ -1531,6 +1553,11 @@ export class TLDrawState extends StateManager<Data> {
1531 1553
             break
1532 1554
           }
1533 1555
         }
1556
+        break
1557
+      }
1558
+      case TLDrawStatus.EditingText: {
1559
+        this.completeSession()
1560
+        break
1534 1561
       }
1535 1562
     }
1536 1563
   }
@@ -1624,10 +1651,6 @@ export class TLDrawState extends StateManager<Data> {
1624 1651
         }
1625 1652
         break
1626 1653
       }
1627
-      case TLDrawStatus.EditingText: {
1628
-        this.completeSession()
1629
-        break
1630
-      }
1631 1654
     }
1632 1655
   }
1633 1656
 
@@ -1698,8 +1721,18 @@ export class TLDrawState extends StateManager<Data> {
1698 1721
     // Unused
1699 1722
   }
1700 1723
 
1701
-  onDoubleClickShape: TLPointerEventHandler = () => {
1702
-    // TODO (drill into group)
1724
+  onDoubleClickShape: TLPointerEventHandler = (info) => {
1725
+    switch (this.appState.status.current) {
1726
+      case TLDrawStatus.PointingBounds: {
1727
+        switch (this.appState.activeTool) {
1728
+          case 'select': {
1729
+            this.startTextSession(info.target)
1730
+            break
1731
+          }
1732
+        }
1733
+        break
1734
+      }
1735
+    }
1703 1736
   }
1704 1737
 
1705 1738
   onRightPointShape: TLPointerEventHandler = (info) => {
@@ -1753,11 +1786,11 @@ export class TLDrawState extends StateManager<Data> {
1753 1786
   }
1754 1787
 
1755 1788
   onDoubleClickBounds: TLBoundsEventHandler = () => {
1756
-    // TODO
1789
+    // Unused
1757 1790
   }
1758 1791
 
1759 1792
   onRightPointBounds: TLBoundsEventHandler = () => {
1760
-    // TODO
1793
+    // Unused
1761 1794
   }
1762 1795
 
1763 1796
   onDragBounds: TLBoundsEventHandler = () => {
@@ -1765,11 +1798,11 @@ export class TLDrawState extends StateManager<Data> {
1765 1798
   }
1766 1799
 
1767 1800
   onHoverBounds: TLBoundsEventHandler = () => {
1768
-    // TODO
1801
+    // Unused
1769 1802
   }
1770 1803
 
1771 1804
   onUnhoverBounds: TLBoundsEventHandler = () => {
1772
-    // TODO
1805
+    // Unused
1773 1806
   }
1774 1807
 
1775 1808
   onReleaseBounds: TLBoundsEventHandler = (info) => {

+ 1
- 3
packages/tldraw/src/styles/stitches.config.ts Näytä tiedosto

@@ -99,8 +99,6 @@ const { styled, css, theme, getCssString } = createCss({
99 99
   },
100 100
 })
101 101
 
102
-const light = theme({})
103
-
104 102
 const dark = theme({
105 103
   colors: {
106 104
     brushFill: 'rgba(180, 180, 180, .05)',
@@ -138,4 +136,4 @@ const dark = theme({
138 136
 
139 137
 export default styled
140 138
 
141
-export { css, getCssString, light, dark }
139
+export { css, getCssString, dark }

Loading…
Peruuta
Tallenna