@tldraw/tlschema 4.1.0-canary.e4499a57ef5b → 4.1.0-canary.e87046ba1a0c
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist-cjs/TLStore.js +3 -10
- package/dist-cjs/TLStore.js.map +2 -2
- package/dist-cjs/assets/TLBaseAsset.js.map +2 -2
- package/dist-cjs/assets/TLBookmarkAsset.js.map +2 -2
- package/dist-cjs/assets/TLImageAsset.js.map +2 -2
- package/dist-cjs/assets/TLVideoAsset.js.map +2 -2
- package/dist-cjs/bindings/TLArrowBinding.js.map +2 -2
- package/dist-cjs/bindings/TLBaseBinding.js.map +2 -2
- package/dist-cjs/createPresenceStateDerivation.js.map +2 -2
- package/dist-cjs/createTLSchema.js.map +2 -2
- package/dist-cjs/index.d.ts +4416 -223
- package/dist-cjs/index.js +1 -1
- package/dist-cjs/index.js.map +2 -2
- package/dist-cjs/misc/TLColor.js.map +2 -2
- package/dist-cjs/misc/TLCursor.js.map +2 -2
- package/dist-cjs/misc/TLHandle.js.map +2 -2
- package/dist-cjs/misc/TLOpacity.js.map +2 -2
- package/dist-cjs/misc/TLRichText.js.map +2 -2
- package/dist-cjs/misc/TLScribble.js.map +2 -2
- package/dist-cjs/misc/geometry-types.js.map +2 -2
- package/dist-cjs/misc/id-validator.js.map +2 -2
- package/dist-cjs/records/TLAsset.js.map +2 -2
- package/dist-cjs/records/TLBinding.js.map +2 -2
- package/dist-cjs/records/TLCamera.js.map +2 -2
- package/dist-cjs/records/TLDocument.js.map +2 -2
- package/dist-cjs/records/TLInstance.js.map +2 -2
- package/dist-cjs/records/TLPage.js.map +2 -2
- package/dist-cjs/records/TLPageState.js.map +2 -2
- package/dist-cjs/records/TLPointer.js.map +2 -2
- package/dist-cjs/records/TLPresence.js.map +2 -2
- package/dist-cjs/records/TLRecord.js.map +1 -1
- package/dist-cjs/records/TLShape.js.map +2 -2
- package/dist-cjs/recordsWithProps.js.map +2 -2
- package/dist-cjs/shapes/ShapeWithCrop.js.map +1 -1
- package/dist-cjs/shapes/TLArrowShape.js.map +2 -2
- package/dist-cjs/shapes/TLBaseShape.js.map +2 -2
- package/dist-cjs/shapes/TLBookmarkShape.js.map +2 -2
- package/dist-cjs/shapes/TLDrawShape.js.map +2 -2
- package/dist-cjs/shapes/TLEmbedShape.js +0 -10
- package/dist-cjs/shapes/TLEmbedShape.js.map +2 -2
- package/dist-cjs/shapes/TLFrameShape.js.map +2 -2
- package/dist-cjs/shapes/TLGeoShape.js.map +2 -2
- package/dist-cjs/shapes/TLGroupShape.js.map +2 -2
- package/dist-cjs/shapes/TLHighlightShape.js.map +2 -2
- package/dist-cjs/shapes/TLImageShape.js.map +2 -2
- package/dist-cjs/shapes/TLLineShape.js.map +2 -2
- package/dist-cjs/shapes/TLNoteShape.js.map +2 -2
- package/dist-cjs/shapes/TLTextShape.js.map +2 -2
- package/dist-cjs/shapes/TLVideoShape.js.map +2 -2
- package/dist-cjs/store-migrations.js.map +2 -2
- package/dist-cjs/styles/TLColorStyle.js.map +2 -2
- package/dist-cjs/styles/TLDashStyle.js.map +2 -2
- package/dist-cjs/styles/TLFillStyle.js.map +2 -2
- package/dist-cjs/styles/TLFontStyle.js.map +2 -2
- package/dist-cjs/styles/TLHorizontalAlignStyle.js.map +2 -2
- package/dist-cjs/styles/TLSizeStyle.js.map +2 -2
- package/dist-cjs/styles/TLTextAlignStyle.js.map +2 -2
- package/dist-cjs/styles/TLVerticalAlignStyle.js.map +2 -2
- package/dist-cjs/translations/translations.js +1 -1
- package/dist-cjs/translations/translations.js.map +2 -2
- package/dist-cjs/util-types.js.map +1 -1
- package/dist-esm/TLStore.mjs +3 -10
- package/dist-esm/TLStore.mjs.map +2 -2
- package/dist-esm/assets/TLBaseAsset.mjs.map +2 -2
- package/dist-esm/assets/TLBookmarkAsset.mjs.map +2 -2
- package/dist-esm/assets/TLImageAsset.mjs.map +2 -2
- package/dist-esm/assets/TLVideoAsset.mjs.map +2 -2
- package/dist-esm/bindings/TLArrowBinding.mjs.map +2 -2
- package/dist-esm/bindings/TLBaseBinding.mjs.map +2 -2
- package/dist-esm/createPresenceStateDerivation.mjs.map +2 -2
- package/dist-esm/createTLSchema.mjs.map +2 -2
- package/dist-esm/index.d.mts +4416 -223
- package/dist-esm/index.mjs +1 -1
- package/dist-esm/index.mjs.map +2 -2
- package/dist-esm/misc/TLColor.mjs.map +2 -2
- package/dist-esm/misc/TLCursor.mjs.map +2 -2
- package/dist-esm/misc/TLHandle.mjs.map +2 -2
- package/dist-esm/misc/TLOpacity.mjs.map +2 -2
- package/dist-esm/misc/TLRichText.mjs.map +2 -2
- package/dist-esm/misc/TLScribble.mjs.map +2 -2
- package/dist-esm/misc/geometry-types.mjs.map +2 -2
- package/dist-esm/misc/id-validator.mjs.map +2 -2
- package/dist-esm/records/TLAsset.mjs.map +2 -2
- package/dist-esm/records/TLBinding.mjs.map +2 -2
- package/dist-esm/records/TLCamera.mjs.map +2 -2
- package/dist-esm/records/TLDocument.mjs.map +2 -2
- package/dist-esm/records/TLInstance.mjs.map +2 -2
- package/dist-esm/records/TLPage.mjs.map +2 -2
- package/dist-esm/records/TLPageState.mjs.map +2 -2
- package/dist-esm/records/TLPointer.mjs.map +2 -2
- package/dist-esm/records/TLPresence.mjs.map +2 -2
- package/dist-esm/records/TLShape.mjs.map +2 -2
- package/dist-esm/recordsWithProps.mjs.map +2 -2
- package/dist-esm/shapes/TLArrowShape.mjs.map +2 -2
- package/dist-esm/shapes/TLBaseShape.mjs.map +2 -2
- package/dist-esm/shapes/TLBookmarkShape.mjs.map +2 -2
- package/dist-esm/shapes/TLDrawShape.mjs.map +2 -2
- package/dist-esm/shapes/TLEmbedShape.mjs +0 -10
- package/dist-esm/shapes/TLEmbedShape.mjs.map +2 -2
- package/dist-esm/shapes/TLFrameShape.mjs.map +2 -2
- package/dist-esm/shapes/TLGeoShape.mjs.map +2 -2
- package/dist-esm/shapes/TLGroupShape.mjs.map +2 -2
- package/dist-esm/shapes/TLHighlightShape.mjs.map +2 -2
- package/dist-esm/shapes/TLImageShape.mjs.map +2 -2
- package/dist-esm/shapes/TLLineShape.mjs.map +2 -2
- package/dist-esm/shapes/TLNoteShape.mjs.map +2 -2
- package/dist-esm/shapes/TLTextShape.mjs.map +2 -2
- package/dist-esm/shapes/TLVideoShape.mjs.map +2 -2
- package/dist-esm/store-migrations.mjs.map +2 -2
- package/dist-esm/styles/TLColorStyle.mjs.map +2 -2
- package/dist-esm/styles/TLDashStyle.mjs.map +2 -2
- package/dist-esm/styles/TLFillStyle.mjs.map +2 -2
- package/dist-esm/styles/TLFontStyle.mjs.map +2 -2
- package/dist-esm/styles/TLHorizontalAlignStyle.mjs.map +2 -2
- package/dist-esm/styles/TLSizeStyle.mjs.map +2 -2
- package/dist-esm/styles/TLTextAlignStyle.mjs.map +2 -2
- package/dist-esm/styles/TLVerticalAlignStyle.mjs.map +2 -2
- package/dist-esm/translations/translations.mjs +1 -1
- package/dist-esm/translations/translations.mjs.map +2 -2
- package/package.json +5 -5
- package/src/TLStore.test.ts +644 -0
- package/src/TLStore.ts +205 -20
- package/src/assets/TLBaseAsset.ts +90 -7
- package/src/assets/TLBookmarkAsset.test.ts +96 -0
- package/src/assets/TLBookmarkAsset.ts +52 -2
- package/src/assets/TLImageAsset.test.ts +213 -0
- package/src/assets/TLImageAsset.ts +60 -2
- package/src/assets/TLVideoAsset.test.ts +105 -0
- package/src/assets/TLVideoAsset.ts +93 -4
- package/src/bindings/TLArrowBinding.test.ts +55 -0
- package/src/bindings/TLArrowBinding.ts +132 -10
- package/src/bindings/TLBaseBinding.ts +140 -3
- package/src/createPresenceStateDerivation.test.ts +158 -0
- package/src/createPresenceStateDerivation.ts +71 -2
- package/src/createTLSchema.test.ts +181 -0
- package/src/createTLSchema.ts +164 -7
- package/src/index.ts +32 -0
- package/src/misc/TLColor.ts +50 -6
- package/src/misc/TLCursor.ts +110 -8
- package/src/misc/TLHandle.ts +86 -6
- package/src/misc/TLOpacity.ts +51 -2
- package/src/misc/TLRichText.ts +56 -3
- package/src/misc/TLScribble.ts +105 -5
- package/src/misc/geometry-types.ts +30 -2
- package/src/misc/id-validator.test.ts +50 -0
- package/src/misc/id-validator.ts +20 -1
- package/src/records/TLAsset.test.ts +234 -0
- package/src/records/TLAsset.ts +165 -8
- package/src/records/TLBinding.test.ts +22 -0
- package/src/records/TLBinding.ts +277 -11
- package/src/records/TLCamera.test.ts +19 -0
- package/src/records/TLCamera.ts +118 -7
- package/src/records/TLDocument.test.ts +35 -0
- package/src/records/TLDocument.ts +148 -8
- package/src/records/TLInstance.test.ts +201 -0
- package/src/records/TLInstance.ts +117 -9
- package/src/records/TLPage.test.ts +110 -0
- package/src/records/TLPage.ts +106 -8
- package/src/records/TLPageState.test.ts +228 -0
- package/src/records/TLPageState.ts +88 -7
- package/src/records/TLPointer.test.ts +63 -0
- package/src/records/TLPointer.ts +105 -7
- package/src/records/TLPresence.test.ts +190 -0
- package/src/records/TLPresence.ts +99 -5
- package/src/records/TLRecord.test.ts +70 -0
- package/src/records/TLRecord.ts +43 -1
- package/src/records/TLShape.test.ts +232 -0
- package/src/records/TLShape.ts +289 -12
- package/src/recordsWithProps.test.ts +188 -0
- package/src/recordsWithProps.ts +131 -2
- package/src/shapes/ShapeWithCrop.test.ts +18 -0
- package/src/shapes/ShapeWithCrop.ts +64 -2
- package/src/shapes/TLArrowShape.test.ts +505 -0
- package/src/shapes/TLArrowShape.ts +188 -10
- package/src/shapes/TLBaseShape.test.ts +142 -0
- package/src/shapes/TLBaseShape.ts +103 -4
- package/src/shapes/TLBookmarkShape.test.ts +122 -0
- package/src/shapes/TLBookmarkShape.ts +58 -4
- package/src/shapes/TLDrawShape.test.ts +177 -0
- package/src/shapes/TLDrawShape.ts +97 -6
- package/src/shapes/TLEmbedShape.test.ts +286 -0
- package/src/shapes/TLEmbedShape.ts +57 -14
- package/src/shapes/TLFrameShape.test.ts +71 -0
- package/src/shapes/TLFrameShape.ts +59 -4
- package/src/shapes/TLGeoShape.test.ts +247 -0
- package/src/shapes/TLGeoShape.ts +103 -7
- package/src/shapes/TLGroupShape.test.ts +59 -0
- package/src/shapes/TLGroupShape.ts +52 -4
- package/src/shapes/TLHighlightShape.test.ts +325 -0
- package/src/shapes/TLHighlightShape.ts +79 -4
- package/src/shapes/TLImageShape.test.ts +534 -0
- package/src/shapes/TLImageShape.ts +105 -5
- package/src/shapes/TLLineShape.test.ts +269 -0
- package/src/shapes/TLLineShape.ts +128 -8
- package/src/shapes/TLNoteShape.test.ts +1568 -0
- package/src/shapes/TLNoteShape.ts +97 -4
- package/src/shapes/TLTextShape.test.ts +407 -0
- package/src/shapes/TLTextShape.ts +94 -4
- package/src/shapes/TLVideoShape.test.ts +112 -0
- package/src/shapes/TLVideoShape.ts +99 -4
- package/src/store-migrations.test.ts +88 -0
- package/src/store-migrations.ts +47 -1
- package/src/styles/TLColorStyle.test.ts +439 -0
- package/src/styles/TLColorStyle.ts +228 -10
- package/src/styles/TLDashStyle.ts +54 -2
- package/src/styles/TLFillStyle.ts +54 -2
- package/src/styles/TLFontStyle.ts +72 -3
- package/src/styles/TLHorizontalAlignStyle.ts +55 -2
- package/src/styles/TLSizeStyle.ts +54 -2
- package/src/styles/TLTextAlignStyle.ts +52 -2
- package/src/styles/TLVerticalAlignStyle.ts +52 -2
- package/src/translations/translations.test.ts +378 -35
- package/src/translations/translations.ts +157 -10
- package/src/util-types.ts +51 -1
package/src/misc/TLHandle.ts
CHANGED
|
@@ -2,30 +2,110 @@ import { IndexKey } from '@tldraw/utils'
|
|
|
2
2
|
import { SetValue } from '../util-types'
|
|
3
3
|
|
|
4
4
|
/**
|
|
5
|
-
*
|
|
5
|
+
* All available handle types used by shapes in the tldraw editor.
|
|
6
6
|
*
|
|
7
|
-
*
|
|
7
|
+
* Handles are interactive control points on shapes that allow users to
|
|
8
|
+
* modify the shape's geometry. Different handle types serve different purposes:
|
|
9
|
+
*
|
|
10
|
+
* - `vertex`: A control point that defines a vertex of the shape
|
|
11
|
+
* - `virtual`: A handle that exists between vertices for adding new points
|
|
12
|
+
* - `create`: A handle for creating new geometry (like extending a line)
|
|
13
|
+
* - `clone`: A handle for duplicating or cloning shape elements
|
|
14
|
+
*
|
|
15
|
+
* @example
|
|
16
|
+
* ```ts
|
|
17
|
+
* // Check if a handle type is valid
|
|
18
|
+
* if (TL_HANDLE_TYPES.has('vertex')) {
|
|
19
|
+
* console.log('Valid handle type')
|
|
20
|
+
* }
|
|
21
|
+
*
|
|
22
|
+
* // Get all available handle types
|
|
23
|
+
* const allHandleTypes = Array.from(TL_HANDLE_TYPES)
|
|
24
|
+
* ```
|
|
25
|
+
*
|
|
26
|
+
* @public
|
|
27
|
+
*/
|
|
8
28
|
export const TL_HANDLE_TYPES = new Set(['vertex', 'virtual', 'create', 'clone'] as const)
|
|
9
29
|
|
|
10
30
|
/**
|
|
11
|
-
* A type
|
|
31
|
+
* A union type representing all available handle types.
|
|
32
|
+
*
|
|
33
|
+
* Handle types determine how a handle behaves when interacted with and
|
|
34
|
+
* what kind of shape modification it enables.
|
|
12
35
|
*
|
|
13
|
-
* @
|
|
36
|
+
* @example
|
|
37
|
+
* ```ts
|
|
38
|
+
* const vertexHandle: TLHandleType = 'vertex'
|
|
39
|
+
* const virtualHandle: TLHandleType = 'virtual'
|
|
40
|
+
* const createHandle: TLHandleType = 'create'
|
|
41
|
+
* const cloneHandle: TLHandleType = 'clone'
|
|
42
|
+
* ```
|
|
43
|
+
*
|
|
44
|
+
* @public
|
|
45
|
+
*/
|
|
14
46
|
export type TLHandleType = SetValue<typeof TL_HANDLE_TYPES>
|
|
15
47
|
|
|
16
48
|
/**
|
|
17
|
-
* A
|
|
49
|
+
* A handle object representing an interactive control point on a shape.
|
|
50
|
+
*
|
|
51
|
+
* Handles allow users to manipulate shape geometry by dragging control points.
|
|
52
|
+
* Each handle has a position, type, and various properties that control its
|
|
53
|
+
* behavior during interactions.
|
|
54
|
+
*
|
|
55
|
+
* @example
|
|
56
|
+
* ```ts
|
|
57
|
+
* // A vertex handle for a line endpoint
|
|
58
|
+
* const lineEndHandle: TLHandle = {
|
|
59
|
+
* id: 'end',
|
|
60
|
+
* label: 'End point',
|
|
61
|
+
* type: 'vertex',
|
|
62
|
+
* canSnap: true,
|
|
63
|
+
* index: 'a1',
|
|
64
|
+
* x: 100,
|
|
65
|
+
* y: 50
|
|
66
|
+
* }
|
|
67
|
+
*
|
|
68
|
+
* // A virtual handle for adding new points
|
|
69
|
+
* const virtualHandle: TLHandle = {
|
|
70
|
+
* id: 'virtual-1',
|
|
71
|
+
* type: 'virtual',
|
|
72
|
+
* canSnap: false,
|
|
73
|
+
* index: 'a1V',
|
|
74
|
+
* x: 75,
|
|
75
|
+
* y: 25
|
|
76
|
+
* }
|
|
77
|
+
*
|
|
78
|
+
* // A create handle for extending geometry
|
|
79
|
+
* const createHandle: TLHandle = {
|
|
80
|
+
* id: 'create',
|
|
81
|
+
* type: 'create',
|
|
82
|
+
* canSnap: true,
|
|
83
|
+
* index: 'a2',
|
|
84
|
+
* x: 200,
|
|
85
|
+
* y: 100
|
|
86
|
+
* }
|
|
87
|
+
* ```
|
|
18
88
|
*
|
|
19
89
|
* @public
|
|
20
90
|
*/
|
|
21
91
|
export interface TLHandle {
|
|
22
|
-
/** A unique identifier for the handle
|
|
92
|
+
/** A unique identifier for the handle within the shape */
|
|
23
93
|
id: string
|
|
94
|
+
/** Optional human-readable label for the handle */
|
|
24
95
|
// TODO(mime): this needs to be required.
|
|
25
96
|
label?: string
|
|
97
|
+
/** The type of handle, determining its behavior and interaction mode */
|
|
26
98
|
type: TLHandleType
|
|
99
|
+
/**
|
|
100
|
+
* @deprecated Use `snapType` instead. Whether this handle should snap to other geometry during interactions.
|
|
101
|
+
*/
|
|
27
102
|
canSnap?: boolean
|
|
103
|
+
/** The type of snap to use for this handle */
|
|
104
|
+
snapType?: 'point' | 'align'
|
|
105
|
+
/** The fractional index used for ordering handles */
|
|
28
106
|
index: IndexKey
|
|
107
|
+
/** The x-coordinate of the handle in the shape's local coordinate system */
|
|
29
108
|
x: number
|
|
109
|
+
/** The y-coordinate of the handle in the shape's local coordinate system */
|
|
30
110
|
y: number
|
|
31
111
|
}
|
package/src/misc/TLOpacity.ts
CHANGED
|
@@ -1,9 +1,58 @@
|
|
|
1
1
|
import { T } from '@tldraw/validate'
|
|
2
2
|
|
|
3
|
-
/**
|
|
3
|
+
/**
|
|
4
|
+
* A type representing opacity values in tldraw.
|
|
5
|
+
*
|
|
6
|
+
* Opacity values are numbers between 0 and 1, where 0 is fully transparent
|
|
7
|
+
* and 1 is fully opaque. This type is used throughout the editor to control
|
|
8
|
+
* the transparency of shapes, UI elements, and other visual components.
|
|
9
|
+
*
|
|
10
|
+
* @example
|
|
11
|
+
* ```ts
|
|
12
|
+
* const fullyOpaque: TLOpacityType = 1.0
|
|
13
|
+
* const halfTransparent: TLOpacityType = 0.5
|
|
14
|
+
* const fullyTransparent: TLOpacityType = 0.0
|
|
15
|
+
* const quarterOpaque: TLOpacityType = 0.25
|
|
16
|
+
* ```
|
|
17
|
+
*
|
|
18
|
+
* @public
|
|
19
|
+
*/
|
|
4
20
|
export type TLOpacityType = number
|
|
5
21
|
|
|
6
|
-
/**
|
|
22
|
+
/**
|
|
23
|
+
* A validator for opacity values.
|
|
24
|
+
*
|
|
25
|
+
* This validator ensures that opacity values are numbers between 0 and 1 (inclusive).
|
|
26
|
+
* Values outside this range will cause a validation error. The validator provides
|
|
27
|
+
* runtime type checking for opacity properties throughout the editor.
|
|
28
|
+
*
|
|
29
|
+
* @param n - The number to validate as an opacity value
|
|
30
|
+
* @throws T.ValidationError When the value is not between 0 and 1
|
|
31
|
+
*
|
|
32
|
+
* @example
|
|
33
|
+
* ```ts
|
|
34
|
+
* import { opacityValidator } from '@tldraw/tlschema'
|
|
35
|
+
*
|
|
36
|
+
* // Valid opacity values
|
|
37
|
+
* try {
|
|
38
|
+
* const validOpacity1 = opacityValidator.validate(0.5) // ✓
|
|
39
|
+
* const validOpacity2 = opacityValidator.validate(1.0) // ✓
|
|
40
|
+
* const validOpacity3 = opacityValidator.validate(0.0) // ✓
|
|
41
|
+
* } catch (error) {
|
|
42
|
+
* console.error('Validation failed:', error.message)
|
|
43
|
+
* }
|
|
44
|
+
*
|
|
45
|
+
* // Invalid opacity values
|
|
46
|
+
* try {
|
|
47
|
+
* opacityValidator.validate(-0.1) // ✗ Throws error
|
|
48
|
+
* opacityValidator.validate(1.5) // ✗ Throws error
|
|
49
|
+
* } catch (error) {
|
|
50
|
+
* console.error('Invalid opacity:', error.message)
|
|
51
|
+
* }
|
|
52
|
+
* ```
|
|
53
|
+
*
|
|
54
|
+
* @public
|
|
55
|
+
*/
|
|
7
56
|
export const opacityValidator = T.number.check((n) => {
|
|
8
57
|
if (n < 0 || n > 1) {
|
|
9
58
|
throw new T.ValidationError('Opacity must be between 0 and 1')
|
package/src/misc/TLRichText.ts
CHANGED
|
@@ -1,12 +1,65 @@
|
|
|
1
1
|
import { T } from '@tldraw/validate'
|
|
2
2
|
|
|
3
|
-
/**
|
|
3
|
+
/**
|
|
4
|
+
* Validator for TLRichText objects that ensures they have the correct structure
|
|
5
|
+
* for document-based rich text content. Validates a document with a type field
|
|
6
|
+
* and an array of content blocks.
|
|
7
|
+
*
|
|
8
|
+
* @public
|
|
9
|
+
* @example
|
|
10
|
+
* ```ts
|
|
11
|
+
* const richText = { type: 'doc', content: [{ type: 'paragraph', content: [{ type: 'text', text: 'Hello' }] }] }
|
|
12
|
+
* const isValid = richTextValidator.check(richText) // true
|
|
13
|
+
* ```
|
|
14
|
+
*/
|
|
4
15
|
export const richTextValidator = T.object({ type: T.string, content: T.arrayOf(T.unknown) })
|
|
5
16
|
|
|
6
|
-
/**
|
|
17
|
+
/**
|
|
18
|
+
* Type representing rich text content in tldraw. Rich text follows a document-based
|
|
19
|
+
* structure with a root document containing an array of content blocks (paragraphs,
|
|
20
|
+
* text nodes, etc.). This enables formatted text with support for multiple paragraphs,
|
|
21
|
+
* styling, and other rich content.
|
|
22
|
+
*
|
|
23
|
+
* @public
|
|
24
|
+
* @example
|
|
25
|
+
* ```ts
|
|
26
|
+
* const richText: TLRichText = {
|
|
27
|
+
* type: 'doc',
|
|
28
|
+
* content: [
|
|
29
|
+
* {
|
|
30
|
+
* type: 'paragraph',
|
|
31
|
+
* content: [{ type: 'text', text: 'Hello world!' }]
|
|
32
|
+
* }
|
|
33
|
+
* ]
|
|
34
|
+
* }
|
|
35
|
+
* ```
|
|
36
|
+
*/
|
|
7
37
|
export type TLRichText = T.TypeOf<typeof richTextValidator>
|
|
8
38
|
|
|
9
|
-
/**
|
|
39
|
+
/**
|
|
40
|
+
* Converts a plain text string into a TLRichText object. Each line of the input
|
|
41
|
+
* text becomes a separate paragraph in the rich text document. Empty lines are
|
|
42
|
+
* preserved as empty paragraphs to maintain the original text structure.
|
|
43
|
+
*
|
|
44
|
+
* @param text - The plain text string to convert to rich text
|
|
45
|
+
* @returns A TLRichText object with the text content structured as paragraphs
|
|
46
|
+
* @public
|
|
47
|
+
* @example
|
|
48
|
+
* ```ts
|
|
49
|
+
* const richText = toRichText('Hello\nWorld')
|
|
50
|
+
* // Returns:
|
|
51
|
+
* // {
|
|
52
|
+
* // type: 'doc',
|
|
53
|
+
* // content: [
|
|
54
|
+
* // { type: 'paragraph', content: [{ type: 'text', text: 'Hello' }] },
|
|
55
|
+
* // { type: 'paragraph', content: [{ type: 'text', text: 'World' }] }
|
|
56
|
+
* // ]
|
|
57
|
+
* // }
|
|
58
|
+
*
|
|
59
|
+
* const emptyLine = toRichText('Line 1\n\nLine 3')
|
|
60
|
+
* // Creates three paragraphs, with the middle one being empty
|
|
61
|
+
* ```
|
|
62
|
+
*/
|
|
10
63
|
export function toRichText(text: string): TLRichText {
|
|
11
64
|
const lines = text.split('\n')
|
|
12
65
|
const content = lines.map((text) => {
|
package/src/misc/TLScribble.ts
CHANGED
|
@@ -4,28 +4,128 @@ import { TLCanvasUiColor, canvasUiColorTypeValidator } from './TLColor'
|
|
|
4
4
|
import { VecModel, vecModelValidator } from './geometry-types'
|
|
5
5
|
|
|
6
6
|
/**
|
|
7
|
-
*
|
|
7
|
+
* All available scribble states used by the tldraw drawing system.
|
|
8
8
|
*
|
|
9
|
-
*
|
|
9
|
+
* Scribble states represent the different phases of a drawing stroke:
|
|
10
|
+
*
|
|
11
|
+
* - `starting`: The scribble is being initiated
|
|
12
|
+
* - `paused`: The scribble is temporarily paused
|
|
13
|
+
* - `active`: The scribble is actively being drawn
|
|
14
|
+
* - `stopping`: The scribble is being finished
|
|
15
|
+
*
|
|
16
|
+
* These states help manage the drawing lifecycle and apply appropriate
|
|
17
|
+
* visual effects during different phases of the stroke.
|
|
18
|
+
*
|
|
19
|
+
* @example
|
|
20
|
+
* ```ts
|
|
21
|
+
* // Check if a scribble state is valid
|
|
22
|
+
* if (TL_SCRIBBLE_STATES.has('active')) {
|
|
23
|
+
* console.log('Valid scribble state')
|
|
24
|
+
* }
|
|
25
|
+
*
|
|
26
|
+
* // Get all available scribble states
|
|
27
|
+
* const allStates = Array.from(TL_SCRIBBLE_STATES)
|
|
28
|
+
* ```
|
|
29
|
+
*
|
|
30
|
+
* @public
|
|
31
|
+
*/
|
|
10
32
|
export const TL_SCRIBBLE_STATES = new Set(['starting', 'paused', 'active', 'stopping'] as const)
|
|
11
33
|
|
|
12
34
|
/**
|
|
13
|
-
* A
|
|
35
|
+
* A scribble object representing a drawing stroke in tldraw.
|
|
36
|
+
*
|
|
37
|
+
* Scribbles are temporary drawing strokes that appear during freehand drawing
|
|
38
|
+
* operations. They provide visual feedback as the user draws and can be styled
|
|
39
|
+
* with various properties like size, color, and effects.
|
|
40
|
+
*
|
|
41
|
+
* @example
|
|
42
|
+
* ```ts
|
|
43
|
+
* // A basic scribble stroke
|
|
44
|
+
* const scribble: TLScribble = {
|
|
45
|
+
* id: 'scribble-123',
|
|
46
|
+
* points: [
|
|
47
|
+
* { x: 0, y: 0, z: 0.5 },
|
|
48
|
+
* { x: 10, y: 5, z: 0.7 },
|
|
49
|
+
* { x: 20, y: 10, z: 0.6 }
|
|
50
|
+
* ],
|
|
51
|
+
* size: 4,
|
|
52
|
+
* color: 'black',
|
|
53
|
+
* opacity: 0.8,
|
|
54
|
+
* state: 'active',
|
|
55
|
+
* delay: 0,
|
|
56
|
+
* shrink: 0.1,
|
|
57
|
+
* taper: true
|
|
58
|
+
* }
|
|
14
59
|
*
|
|
15
|
-
*
|
|
60
|
+
* // A laser pointer scribble
|
|
61
|
+
* const laserScribble: TLScribble = {
|
|
62
|
+
* id: 'laser-pointer',
|
|
63
|
+
* points: [{ x: 50, y: 50, z: 1.0 }],
|
|
64
|
+
* size: 8,
|
|
65
|
+
* color: 'laser',
|
|
66
|
+
* opacity: 1.0,
|
|
67
|
+
* state: 'active',
|
|
68
|
+
* delay: 100,
|
|
69
|
+
* shrink: 0,
|
|
70
|
+
* taper: false
|
|
71
|
+
* }
|
|
72
|
+
* ```
|
|
73
|
+
*
|
|
74
|
+
* @public
|
|
75
|
+
*/
|
|
16
76
|
export interface TLScribble {
|
|
77
|
+
/** Unique identifier for the scribble */
|
|
17
78
|
id: string
|
|
79
|
+
/** Array of points that make up the scribble path */
|
|
18
80
|
points: VecModel[]
|
|
81
|
+
/** The brush size/width of the scribble stroke */
|
|
19
82
|
size: number
|
|
83
|
+
/** The color of the scribble using canvas UI color types */
|
|
20
84
|
color: TLCanvasUiColor
|
|
85
|
+
/** The opacity of the scribble (0-1) */
|
|
21
86
|
opacity: number
|
|
87
|
+
/** The current state of the scribble drawing */
|
|
22
88
|
state: SetValue<typeof TL_SCRIBBLE_STATES>
|
|
89
|
+
/** Time delay in milliseconds for animation effects */
|
|
23
90
|
delay: number
|
|
91
|
+
/** Amount the stroke should shrink over time (0-1) */
|
|
24
92
|
shrink: number
|
|
93
|
+
/** Whether the stroke should taper at the ends */
|
|
25
94
|
taper: boolean
|
|
26
95
|
}
|
|
27
96
|
|
|
28
|
-
/**
|
|
97
|
+
/**
|
|
98
|
+
* A validator for TLScribble objects.
|
|
99
|
+
*
|
|
100
|
+
* This validator ensures that scribble objects have all required properties
|
|
101
|
+
* with valid types and values. It validates the points array, size constraints,
|
|
102
|
+
* color types, and state values according to the scribble system requirements.
|
|
103
|
+
*
|
|
104
|
+
* @example
|
|
105
|
+
* ```ts
|
|
106
|
+
* import { scribbleValidator } from '@tldraw/tlschema'
|
|
107
|
+
*
|
|
108
|
+
* // Validate a scribble object
|
|
109
|
+
* try {
|
|
110
|
+
* const validScribble = scribbleValidator.validate({
|
|
111
|
+
* id: 'scribble-1',
|
|
112
|
+
* points: [{ x: 0, y: 0, z: 1 }, { x: 10, y: 10, z: 1 }],
|
|
113
|
+
* size: 3,
|
|
114
|
+
* color: 'black',
|
|
115
|
+
* opacity: 0.8,
|
|
116
|
+
* state: 'active',
|
|
117
|
+
* delay: 0,
|
|
118
|
+
* shrink: 0.05,
|
|
119
|
+
* taper: true
|
|
120
|
+
* })
|
|
121
|
+
* console.log('Valid scribble:', validScribble)
|
|
122
|
+
* } catch (error) {
|
|
123
|
+
* console.error('Invalid scribble:', error.message)
|
|
124
|
+
* }
|
|
125
|
+
* ```
|
|
126
|
+
*
|
|
127
|
+
* @public
|
|
128
|
+
*/
|
|
29
129
|
export const scribbleValidator: T.ObjectValidator<TLScribble> = T.object({
|
|
30
130
|
id: T.string,
|
|
31
131
|
points: T.arrayOf(vecModelValidator),
|
|
@@ -21,14 +21,42 @@ export interface VecModel {
|
|
|
21
21
|
z?: number
|
|
22
22
|
}
|
|
23
23
|
|
|
24
|
-
/**
|
|
24
|
+
/**
|
|
25
|
+
* Validator for VecModel objects that ensures they have numeric x and y coordinates,
|
|
26
|
+
* with an optional z coordinate for 3D vectors. Used throughout the schema to
|
|
27
|
+
* validate point and vector data structures.
|
|
28
|
+
*
|
|
29
|
+
* @public
|
|
30
|
+
* @example
|
|
31
|
+
* ```ts
|
|
32
|
+
* const vector2D = { x: 10, y: 20 }
|
|
33
|
+
* const isValid = vecModelValidator.check(vector2D) // true
|
|
34
|
+
*
|
|
35
|
+
* const vector3D = { x: 10, y: 20, z: 30 }
|
|
36
|
+
* const isValid3D = vecModelValidator.check(vector3D) // true
|
|
37
|
+
* ```
|
|
38
|
+
*/
|
|
25
39
|
export const vecModelValidator: T.ObjectValidator<VecModel> = T.object({
|
|
26
40
|
x: T.number,
|
|
27
41
|
y: T.number,
|
|
28
42
|
z: T.number.optional(),
|
|
29
43
|
})
|
|
30
44
|
|
|
31
|
-
/**
|
|
45
|
+
/**
|
|
46
|
+
* Validator for BoxModel objects that ensures they have numeric x, y coordinates
|
|
47
|
+
* for position and w, h values for width and height. Used throughout the schema
|
|
48
|
+
* to validate bounding box and rectangular area data structures.
|
|
49
|
+
*
|
|
50
|
+
* @public
|
|
51
|
+
* @example
|
|
52
|
+
* ```ts
|
|
53
|
+
* const box = { x: 10, y: 20, w: 100, h: 50 }
|
|
54
|
+
* const isValid = boxModelValidator.check(box) // true
|
|
55
|
+
*
|
|
56
|
+
* const invalidBox = { x: 10, y: 20, w: -5, h: 50 }
|
|
57
|
+
* const isValidNegative = boxModelValidator.check(invalidBox) // true (validator allows negative values)
|
|
58
|
+
* ```
|
|
59
|
+
*/
|
|
32
60
|
export const boxModelValidator: T.ObjectValidator<BoxModel> = T.object({
|
|
33
61
|
x: T.number,
|
|
34
62
|
y: T.number,
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import type { RecordId, UnknownRecord } from '@tldraw/store'
|
|
2
|
+
import { describe, expect, it } from 'vitest'
|
|
3
|
+
import { idValidator } from './id-validator'
|
|
4
|
+
|
|
5
|
+
// Mock record types for testing
|
|
6
|
+
interface MockShapeRecord extends UnknownRecord {
|
|
7
|
+
typeName: 'shape'
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
interface MockPageRecord extends UnknownRecord {
|
|
11
|
+
typeName: 'page'
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
type MockShapeId = RecordId<MockShapeRecord>
|
|
15
|
+
type MockPageId = RecordId<MockPageRecord>
|
|
16
|
+
|
|
17
|
+
describe('idValidator', () => {
|
|
18
|
+
it('should validate correct IDs with proper prefix', () => {
|
|
19
|
+
const shapeValidator = idValidator<MockShapeId>('shape')
|
|
20
|
+
const pageValidator = idValidator<MockPageId>('page')
|
|
21
|
+
|
|
22
|
+
expect(shapeValidator.validate('shape:abc123')).toBe('shape:abc123')
|
|
23
|
+
expect(shapeValidator.validate('shape:')).toBe('shape:')
|
|
24
|
+
expect(pageValidator.validate('page:main')).toBe('page:main')
|
|
25
|
+
})
|
|
26
|
+
|
|
27
|
+
it('should reject IDs with wrong prefix', () => {
|
|
28
|
+
const shapeValidator = idValidator<MockShapeId>('shape')
|
|
29
|
+
|
|
30
|
+
expect(() => shapeValidator.validate('page:abc123')).toThrow(
|
|
31
|
+
'shape ID must start with "shape:"'
|
|
32
|
+
)
|
|
33
|
+
expect(() => shapeValidator.validate('asset:xyz789')).toThrow(
|
|
34
|
+
'shape ID must start with "shape:"'
|
|
35
|
+
)
|
|
36
|
+
expect(() => shapeValidator.validate('abc123')).toThrow('shape ID must start with "shape:"')
|
|
37
|
+
expect(() => shapeValidator.validate('')).toThrow('shape ID must start with "shape:"')
|
|
38
|
+
})
|
|
39
|
+
|
|
40
|
+
it('should work with different prefixes independently', () => {
|
|
41
|
+
const shapeValidator = idValidator<MockShapeId>('shape')
|
|
42
|
+
const pageValidator = idValidator<MockPageId>('page')
|
|
43
|
+
|
|
44
|
+
expect(shapeValidator.isValid('shape:abc123')).toBe(true)
|
|
45
|
+
expect(shapeValidator.isValid('page:abc123')).toBe(false)
|
|
46
|
+
|
|
47
|
+
expect(pageValidator.isValid('shape:abc123')).toBe(false)
|
|
48
|
+
expect(pageValidator.isValid('page:abc123')).toBe(true)
|
|
49
|
+
})
|
|
50
|
+
})
|
package/src/misc/id-validator.ts
CHANGED
|
@@ -1,7 +1,26 @@
|
|
|
1
1
|
import type { RecordId, UnknownRecord } from '@tldraw/store'
|
|
2
2
|
import { T } from '@tldraw/validate'
|
|
3
3
|
|
|
4
|
-
/**
|
|
4
|
+
/**
|
|
5
|
+
* Creates a validator for typed record IDs that ensures they follow the correct
|
|
6
|
+
* format with the specified prefix. Record IDs in tldraw follow the pattern
|
|
7
|
+
* "prefix:identifier" where the prefix indicates the record type.
|
|
8
|
+
*
|
|
9
|
+
* @param prefix - The required prefix for the ID (e.g., 'shape', 'page', 'asset')
|
|
10
|
+
* @returns A validator that checks the ID format and returns the typed ID
|
|
11
|
+
* @public
|
|
12
|
+
* @example
|
|
13
|
+
* ```ts
|
|
14
|
+
* const shapeIdValidator = idValidator<TLShapeId>('shape')
|
|
15
|
+
* const validId = shapeIdValidator.validate('shape:abc123') // Returns 'shape:abc123' as TLShapeId
|
|
16
|
+
*
|
|
17
|
+
* const pageIdValidator = idValidator<TLPageId>('page')
|
|
18
|
+
* const pageId = pageIdValidator.validate('page:main') // Returns 'page:main' as TLPageId
|
|
19
|
+
*
|
|
20
|
+
* // This would throw an error:
|
|
21
|
+
* // shapeIdValidator.validate('page:abc123') // Error: shape ID must start with "shape:"
|
|
22
|
+
* ```
|
|
23
|
+
*/
|
|
5
24
|
export function idValidator<Id extends RecordId<UnknownRecord>>(
|
|
6
25
|
prefix: Id['__type__']['typeName']
|
|
7
26
|
): T.Validator<Id> {
|