@tldraw/tlschema 4.1.0-next.542f014c3fac → 4.1.0-next.74327a60f18a

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.
Files changed (212) hide show
  1. package/dist-cjs/TLStore.js +3 -10
  2. package/dist-cjs/TLStore.js.map +2 -2
  3. package/dist-cjs/assets/TLBaseAsset.js.map +2 -2
  4. package/dist-cjs/assets/TLBookmarkAsset.js.map +2 -2
  5. package/dist-cjs/assets/TLImageAsset.js.map +2 -2
  6. package/dist-cjs/assets/TLVideoAsset.js.map +2 -2
  7. package/dist-cjs/bindings/TLArrowBinding.js.map +2 -2
  8. package/dist-cjs/bindings/TLBaseBinding.js.map +2 -2
  9. package/dist-cjs/createPresenceStateDerivation.js.map +2 -2
  10. package/dist-cjs/createTLSchema.js.map +2 -2
  11. package/dist-cjs/index.d.ts +4416 -223
  12. package/dist-cjs/index.js +1 -1
  13. package/dist-cjs/index.js.map +2 -2
  14. package/dist-cjs/misc/TLColor.js.map +2 -2
  15. package/dist-cjs/misc/TLCursor.js.map +2 -2
  16. package/dist-cjs/misc/TLHandle.js.map +2 -2
  17. package/dist-cjs/misc/TLOpacity.js.map +2 -2
  18. package/dist-cjs/misc/TLRichText.js.map +2 -2
  19. package/dist-cjs/misc/TLScribble.js.map +2 -2
  20. package/dist-cjs/misc/geometry-types.js.map +2 -2
  21. package/dist-cjs/misc/id-validator.js.map +2 -2
  22. package/dist-cjs/records/TLAsset.js.map +2 -2
  23. package/dist-cjs/records/TLBinding.js.map +2 -2
  24. package/dist-cjs/records/TLCamera.js.map +2 -2
  25. package/dist-cjs/records/TLDocument.js.map +2 -2
  26. package/dist-cjs/records/TLInstance.js.map +2 -2
  27. package/dist-cjs/records/TLPage.js.map +2 -2
  28. package/dist-cjs/records/TLPageState.js.map +2 -2
  29. package/dist-cjs/records/TLPointer.js.map +2 -2
  30. package/dist-cjs/records/TLPresence.js.map +2 -2
  31. package/dist-cjs/records/TLRecord.js.map +1 -1
  32. package/dist-cjs/records/TLShape.js.map +2 -2
  33. package/dist-cjs/recordsWithProps.js.map +2 -2
  34. package/dist-cjs/shapes/ShapeWithCrop.js.map +1 -1
  35. package/dist-cjs/shapes/TLArrowShape.js.map +2 -2
  36. package/dist-cjs/shapes/TLBaseShape.js.map +2 -2
  37. package/dist-cjs/shapes/TLBookmarkShape.js.map +2 -2
  38. package/dist-cjs/shapes/TLDrawShape.js.map +2 -2
  39. package/dist-cjs/shapes/TLEmbedShape.js.map +2 -2
  40. package/dist-cjs/shapes/TLFrameShape.js.map +2 -2
  41. package/dist-cjs/shapes/TLGeoShape.js.map +2 -2
  42. package/dist-cjs/shapes/TLGroupShape.js.map +2 -2
  43. package/dist-cjs/shapes/TLHighlightShape.js.map +2 -2
  44. package/dist-cjs/shapes/TLImageShape.js.map +2 -2
  45. package/dist-cjs/shapes/TLLineShape.js.map +2 -2
  46. package/dist-cjs/shapes/TLNoteShape.js.map +2 -2
  47. package/dist-cjs/shapes/TLTextShape.js.map +2 -2
  48. package/dist-cjs/shapes/TLVideoShape.js.map +2 -2
  49. package/dist-cjs/store-migrations.js.map +2 -2
  50. package/dist-cjs/styles/TLColorStyle.js.map +2 -2
  51. package/dist-cjs/styles/TLDashStyle.js.map +2 -2
  52. package/dist-cjs/styles/TLFillStyle.js.map +2 -2
  53. package/dist-cjs/styles/TLFontStyle.js.map +2 -2
  54. package/dist-cjs/styles/TLHorizontalAlignStyle.js.map +2 -2
  55. package/dist-cjs/styles/TLSizeStyle.js.map +2 -2
  56. package/dist-cjs/styles/TLTextAlignStyle.js.map +2 -2
  57. package/dist-cjs/styles/TLVerticalAlignStyle.js.map +2 -2
  58. package/dist-cjs/translations/translations.js +1 -1
  59. package/dist-cjs/translations/translations.js.map +2 -2
  60. package/dist-cjs/util-types.js.map +1 -1
  61. package/dist-esm/TLStore.mjs +3 -10
  62. package/dist-esm/TLStore.mjs.map +2 -2
  63. package/dist-esm/assets/TLBaseAsset.mjs.map +2 -2
  64. package/dist-esm/assets/TLBookmarkAsset.mjs.map +2 -2
  65. package/dist-esm/assets/TLImageAsset.mjs.map +2 -2
  66. package/dist-esm/assets/TLVideoAsset.mjs.map +2 -2
  67. package/dist-esm/bindings/TLArrowBinding.mjs.map +2 -2
  68. package/dist-esm/bindings/TLBaseBinding.mjs.map +2 -2
  69. package/dist-esm/createPresenceStateDerivation.mjs.map +2 -2
  70. package/dist-esm/createTLSchema.mjs.map +2 -2
  71. package/dist-esm/index.d.mts +4416 -223
  72. package/dist-esm/index.mjs +1 -1
  73. package/dist-esm/index.mjs.map +2 -2
  74. package/dist-esm/misc/TLColor.mjs.map +2 -2
  75. package/dist-esm/misc/TLCursor.mjs.map +2 -2
  76. package/dist-esm/misc/TLHandle.mjs.map +2 -2
  77. package/dist-esm/misc/TLOpacity.mjs.map +2 -2
  78. package/dist-esm/misc/TLRichText.mjs.map +2 -2
  79. package/dist-esm/misc/TLScribble.mjs.map +2 -2
  80. package/dist-esm/misc/geometry-types.mjs.map +2 -2
  81. package/dist-esm/misc/id-validator.mjs.map +2 -2
  82. package/dist-esm/records/TLAsset.mjs.map +2 -2
  83. package/dist-esm/records/TLBinding.mjs.map +2 -2
  84. package/dist-esm/records/TLCamera.mjs.map +2 -2
  85. package/dist-esm/records/TLDocument.mjs.map +2 -2
  86. package/dist-esm/records/TLInstance.mjs.map +2 -2
  87. package/dist-esm/records/TLPage.mjs.map +2 -2
  88. package/dist-esm/records/TLPageState.mjs.map +2 -2
  89. package/dist-esm/records/TLPointer.mjs.map +2 -2
  90. package/dist-esm/records/TLPresence.mjs.map +2 -2
  91. package/dist-esm/records/TLShape.mjs.map +2 -2
  92. package/dist-esm/recordsWithProps.mjs.map +2 -2
  93. package/dist-esm/shapes/TLArrowShape.mjs.map +2 -2
  94. package/dist-esm/shapes/TLBaseShape.mjs.map +2 -2
  95. package/dist-esm/shapes/TLBookmarkShape.mjs.map +2 -2
  96. package/dist-esm/shapes/TLDrawShape.mjs.map +2 -2
  97. package/dist-esm/shapes/TLEmbedShape.mjs.map +2 -2
  98. package/dist-esm/shapes/TLFrameShape.mjs.map +2 -2
  99. package/dist-esm/shapes/TLGeoShape.mjs.map +2 -2
  100. package/dist-esm/shapes/TLGroupShape.mjs.map +2 -2
  101. package/dist-esm/shapes/TLHighlightShape.mjs.map +2 -2
  102. package/dist-esm/shapes/TLImageShape.mjs.map +2 -2
  103. package/dist-esm/shapes/TLLineShape.mjs.map +2 -2
  104. package/dist-esm/shapes/TLNoteShape.mjs.map +2 -2
  105. package/dist-esm/shapes/TLTextShape.mjs.map +2 -2
  106. package/dist-esm/shapes/TLVideoShape.mjs.map +2 -2
  107. package/dist-esm/store-migrations.mjs.map +2 -2
  108. package/dist-esm/styles/TLColorStyle.mjs.map +2 -2
  109. package/dist-esm/styles/TLDashStyle.mjs.map +2 -2
  110. package/dist-esm/styles/TLFillStyle.mjs.map +2 -2
  111. package/dist-esm/styles/TLFontStyle.mjs.map +2 -2
  112. package/dist-esm/styles/TLHorizontalAlignStyle.mjs.map +2 -2
  113. package/dist-esm/styles/TLSizeStyle.mjs.map +2 -2
  114. package/dist-esm/styles/TLTextAlignStyle.mjs.map +2 -2
  115. package/dist-esm/styles/TLVerticalAlignStyle.mjs.map +2 -2
  116. package/dist-esm/translations/translations.mjs +1 -1
  117. package/dist-esm/translations/translations.mjs.map +2 -2
  118. package/package.json +5 -5
  119. package/src/TLStore.test.ts +644 -0
  120. package/src/TLStore.ts +205 -20
  121. package/src/assets/TLBaseAsset.ts +90 -7
  122. package/src/assets/TLBookmarkAsset.test.ts +96 -0
  123. package/src/assets/TLBookmarkAsset.ts +52 -2
  124. package/src/assets/TLImageAsset.test.ts +213 -0
  125. package/src/assets/TLImageAsset.ts +60 -2
  126. package/src/assets/TLVideoAsset.test.ts +105 -0
  127. package/src/assets/TLVideoAsset.ts +93 -4
  128. package/src/bindings/TLArrowBinding.test.ts +55 -0
  129. package/src/bindings/TLArrowBinding.ts +132 -10
  130. package/src/bindings/TLBaseBinding.ts +140 -3
  131. package/src/createPresenceStateDerivation.test.ts +158 -0
  132. package/src/createPresenceStateDerivation.ts +71 -2
  133. package/src/createTLSchema.test.ts +181 -0
  134. package/src/createTLSchema.ts +164 -7
  135. package/src/index.ts +32 -0
  136. package/src/misc/TLColor.ts +50 -6
  137. package/src/misc/TLCursor.ts +110 -8
  138. package/src/misc/TLHandle.ts +86 -6
  139. package/src/misc/TLOpacity.ts +51 -2
  140. package/src/misc/TLRichText.ts +56 -3
  141. package/src/misc/TLScribble.ts +105 -5
  142. package/src/misc/geometry-types.ts +30 -2
  143. package/src/misc/id-validator.test.ts +50 -0
  144. package/src/misc/id-validator.ts +20 -1
  145. package/src/records/TLAsset.test.ts +234 -0
  146. package/src/records/TLAsset.ts +165 -8
  147. package/src/records/TLBinding.test.ts +22 -0
  148. package/src/records/TLBinding.ts +277 -11
  149. package/src/records/TLCamera.test.ts +19 -0
  150. package/src/records/TLCamera.ts +118 -7
  151. package/src/records/TLDocument.test.ts +35 -0
  152. package/src/records/TLDocument.ts +148 -8
  153. package/src/records/TLInstance.test.ts +201 -0
  154. package/src/records/TLInstance.ts +117 -9
  155. package/src/records/TLPage.test.ts +110 -0
  156. package/src/records/TLPage.ts +106 -8
  157. package/src/records/TLPageState.test.ts +228 -0
  158. package/src/records/TLPageState.ts +88 -7
  159. package/src/records/TLPointer.test.ts +63 -0
  160. package/src/records/TLPointer.ts +105 -7
  161. package/src/records/TLPresence.test.ts +190 -0
  162. package/src/records/TLPresence.ts +99 -5
  163. package/src/records/TLRecord.test.ts +70 -0
  164. package/src/records/TLRecord.ts +43 -1
  165. package/src/records/TLShape.test.ts +232 -0
  166. package/src/records/TLShape.ts +289 -12
  167. package/src/recordsWithProps.test.ts +188 -0
  168. package/src/recordsWithProps.ts +131 -2
  169. package/src/shapes/ShapeWithCrop.test.ts +18 -0
  170. package/src/shapes/ShapeWithCrop.ts +64 -2
  171. package/src/shapes/TLArrowShape.test.ts +505 -0
  172. package/src/shapes/TLArrowShape.ts +188 -10
  173. package/src/shapes/TLBaseShape.test.ts +142 -0
  174. package/src/shapes/TLBaseShape.ts +103 -4
  175. package/src/shapes/TLBookmarkShape.test.ts +122 -0
  176. package/src/shapes/TLBookmarkShape.ts +58 -4
  177. package/src/shapes/TLDrawShape.test.ts +177 -0
  178. package/src/shapes/TLDrawShape.ts +97 -6
  179. package/src/shapes/TLEmbedShape.test.ts +286 -0
  180. package/src/shapes/TLEmbedShape.ts +57 -4
  181. package/src/shapes/TLFrameShape.test.ts +71 -0
  182. package/src/shapes/TLFrameShape.ts +59 -4
  183. package/src/shapes/TLGeoShape.test.ts +247 -0
  184. package/src/shapes/TLGeoShape.ts +103 -7
  185. package/src/shapes/TLGroupShape.test.ts +59 -0
  186. package/src/shapes/TLGroupShape.ts +52 -4
  187. package/src/shapes/TLHighlightShape.test.ts +325 -0
  188. package/src/shapes/TLHighlightShape.ts +79 -4
  189. package/src/shapes/TLImageShape.test.ts +534 -0
  190. package/src/shapes/TLImageShape.ts +105 -5
  191. package/src/shapes/TLLineShape.test.ts +269 -0
  192. package/src/shapes/TLLineShape.ts +128 -8
  193. package/src/shapes/TLNoteShape.test.ts +1568 -0
  194. package/src/shapes/TLNoteShape.ts +97 -4
  195. package/src/shapes/TLTextShape.test.ts +407 -0
  196. package/src/shapes/TLTextShape.ts +94 -4
  197. package/src/shapes/TLVideoShape.test.ts +112 -0
  198. package/src/shapes/TLVideoShape.ts +99 -4
  199. package/src/store-migrations.test.ts +88 -0
  200. package/src/store-migrations.ts +47 -1
  201. package/src/styles/TLColorStyle.test.ts +439 -0
  202. package/src/styles/TLColorStyle.ts +228 -10
  203. package/src/styles/TLDashStyle.ts +54 -2
  204. package/src/styles/TLFillStyle.ts +54 -2
  205. package/src/styles/TLFontStyle.ts +72 -3
  206. package/src/styles/TLHorizontalAlignStyle.ts +55 -2
  207. package/src/styles/TLSizeStyle.ts +54 -2
  208. package/src/styles/TLTextAlignStyle.ts +52 -2
  209. package/src/styles/TLVerticalAlignStyle.ts +52 -2
  210. package/src/translations/translations.test.ts +378 -35
  211. package/src/translations/translations.ts +157 -10
  212. package/src/util-types.ts +51 -1
@@ -2,30 +2,110 @@ import { IndexKey } from '@tldraw/utils'
2
2
  import { SetValue } from '../util-types'
3
3
 
4
4
  /**
5
- * The handle types used by tldraw's default shapes.
5
+ * All available handle types used by shapes in the tldraw editor.
6
6
  *
7
- * @public */
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 for the handle types used by tldraw's default shapes.
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
- * @public */
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 base interface for a shape's handles.
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
  }
@@ -1,9 +1,58 @@
1
1
  import { T } from '@tldraw/validate'
2
2
 
3
- /** @public */
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
- /** @public */
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')
@@ -1,12 +1,65 @@
1
1
  import { T } from '@tldraw/validate'
2
2
 
3
- /** @public */
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
- /** @public */
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
- /** @public */
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) => {
@@ -4,28 +4,128 @@ import { TLCanvasUiColor, canvasUiColorTypeValidator } from './TLColor'
4
4
  import { VecModel, vecModelValidator } from './geometry-types'
5
5
 
6
6
  /**
7
- * The scribble states used by tldraw.
7
+ * All available scribble states used by the tldraw drawing system.
8
8
  *
9
- * @public */
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 type for the scribble used by tldraw.
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
- * @public */
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
- /** @public */
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
- /** @public */
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
- /** @public */
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
+ })
@@ -1,7 +1,26 @@
1
1
  import type { RecordId, UnknownRecord } from '@tldraw/store'
2
2
  import { T } from '@tldraw/validate'
3
3
 
4
- /** @public */
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> {