@tldraw/tlschema 4.1.0-canary.8ac9e489017b → 4.1.0-canary.95d46c96eb30
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 +4412 -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.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 +4412 -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.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 +82 -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 -4
- 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/records/TLBinding.ts
CHANGED
|
@@ -14,25 +14,91 @@ import { TLPropsMigrations } from '../recordsWithProps'
|
|
|
14
14
|
|
|
15
15
|
/**
|
|
16
16
|
* The default set of bindings that are available in the editor.
|
|
17
|
+
* Currently includes only arrow bindings, but can be extended with custom bindings.
|
|
17
18
|
*
|
|
18
|
-
* @
|
|
19
|
+
* @example
|
|
20
|
+
* ```ts
|
|
21
|
+
* // Arrow binding connects an arrow to shapes
|
|
22
|
+
* const arrowBinding: TLDefaultBinding = {
|
|
23
|
+
* id: 'binding:arrow1',
|
|
24
|
+
* typeName: 'binding',
|
|
25
|
+
* type: 'arrow',
|
|
26
|
+
* fromId: 'shape:arrow1',
|
|
27
|
+
* toId: 'shape:rectangle1',
|
|
28
|
+
* props: {
|
|
29
|
+
* terminal: 'end',
|
|
30
|
+
* normalizedAnchor: { x: 0.5, y: 0.5 },
|
|
31
|
+
* isExact: false,
|
|
32
|
+
* isPrecise: true
|
|
33
|
+
* }
|
|
34
|
+
* }
|
|
35
|
+
* ```
|
|
36
|
+
*
|
|
37
|
+
* @public
|
|
38
|
+
*/
|
|
19
39
|
export type TLDefaultBinding = TLArrowBinding
|
|
20
40
|
|
|
21
41
|
/**
|
|
22
42
|
* A type for a binding that is available in the editor but whose type is
|
|
23
43
|
* unknown—either one of the editor's default bindings or else a custom binding.
|
|
44
|
+
* Used internally for type-safe handling of bindings with unknown structure.
|
|
24
45
|
*
|
|
25
|
-
* @
|
|
46
|
+
* @example
|
|
47
|
+
* ```ts
|
|
48
|
+
* // Function that works with any binding type
|
|
49
|
+
* function processBinding(binding: TLUnknownBinding) {
|
|
50
|
+
* console.log(`Processing ${binding.type} binding from ${binding.fromId} to ${binding.toId}`)
|
|
51
|
+
* // Handle binding properties generically
|
|
52
|
+
* }
|
|
53
|
+
* ```
|
|
54
|
+
*
|
|
55
|
+
* @public
|
|
56
|
+
*/
|
|
26
57
|
export type TLUnknownBinding = TLBaseBinding<string, object>
|
|
27
58
|
|
|
28
59
|
/**
|
|
29
60
|
* The set of all bindings that are available in the editor, including unknown bindings.
|
|
61
|
+
* Bindings represent relationships between shapes, such as arrows connecting to other shapes.
|
|
62
|
+
*
|
|
63
|
+
* @example
|
|
64
|
+
* ```ts
|
|
65
|
+
* // Check binding type and handle accordingly
|
|
66
|
+
* function handleBinding(binding: TLBinding) {
|
|
67
|
+
* switch (binding.type) {
|
|
68
|
+
* case 'arrow':
|
|
69
|
+
* // Handle arrow binding
|
|
70
|
+
* break
|
|
71
|
+
* default:
|
|
72
|
+
* // Handle unknown custom binding
|
|
73
|
+
* break
|
|
74
|
+
* }
|
|
75
|
+
* }
|
|
76
|
+
* ```
|
|
30
77
|
*
|
|
31
78
|
* @public
|
|
32
79
|
*/
|
|
33
80
|
export type TLBinding = TLDefaultBinding | TLUnknownBinding
|
|
34
81
|
|
|
35
|
-
/**
|
|
82
|
+
/**
|
|
83
|
+
* Type for updating existing bindings with partial properties.
|
|
84
|
+
* Only the id and type are required, all other properties are optional.
|
|
85
|
+
*
|
|
86
|
+
* @example
|
|
87
|
+
* ```ts
|
|
88
|
+
* // Update arrow binding properties
|
|
89
|
+
* const bindingUpdate: TLBindingUpdate<TLArrowBinding> = {
|
|
90
|
+
* id: 'binding:arrow1',
|
|
91
|
+
* type: 'arrow',
|
|
92
|
+
* props: {
|
|
93
|
+
* normalizedAnchor: { x: 0.7, y: 0.3 } // Only update anchor position
|
|
94
|
+
* }
|
|
95
|
+
* }
|
|
96
|
+
*
|
|
97
|
+
* editor.updateBindings([bindingUpdate])
|
|
98
|
+
* ```
|
|
99
|
+
*
|
|
100
|
+
* @public
|
|
101
|
+
*/
|
|
36
102
|
export type TLBindingUpdate<T extends TLBinding = TLBinding> = Expand<{
|
|
37
103
|
id: TLBindingId
|
|
38
104
|
type: T['type']
|
|
@@ -43,7 +109,30 @@ export type TLBindingUpdate<T extends TLBinding = TLBinding> = Expand<{
|
|
|
43
109
|
meta?: Partial<T['meta']>
|
|
44
110
|
}>
|
|
45
111
|
|
|
46
|
-
/**
|
|
112
|
+
/**
|
|
113
|
+
* Type for creating new bindings with required fromId and toId.
|
|
114
|
+
* The id is optional and will be generated if not provided.
|
|
115
|
+
*
|
|
116
|
+
* @example
|
|
117
|
+
* ```ts
|
|
118
|
+
* // Create a new arrow binding
|
|
119
|
+
* const newBinding: TLBindingCreate<TLArrowBinding> = {
|
|
120
|
+
* type: 'arrow',
|
|
121
|
+
* fromId: 'shape:arrow1',
|
|
122
|
+
* toId: 'shape:rectangle1',
|
|
123
|
+
* props: {
|
|
124
|
+
* terminal: 'end',
|
|
125
|
+
* normalizedAnchor: { x: 0.5, y: 0.5 },
|
|
126
|
+
* isExact: false,
|
|
127
|
+
* isPrecise: true
|
|
128
|
+
* }
|
|
129
|
+
* }
|
|
130
|
+
*
|
|
131
|
+
* editor.createBindings([newBinding])
|
|
132
|
+
* ```
|
|
133
|
+
*
|
|
134
|
+
* @public
|
|
135
|
+
*/
|
|
47
136
|
export type TLBindingCreate<T extends TLBinding = TLBinding> = Expand<{
|
|
48
137
|
id?: TLBindingId
|
|
49
138
|
type: T['type']
|
|
@@ -55,40 +144,176 @@ export type TLBindingCreate<T extends TLBinding = TLBinding> = Expand<{
|
|
|
55
144
|
}>
|
|
56
145
|
|
|
57
146
|
/**
|
|
58
|
-
*
|
|
147
|
+
* Branded string type for binding record identifiers.
|
|
148
|
+
* Prevents mixing binding IDs with other types of record IDs at compile time.
|
|
149
|
+
*
|
|
150
|
+
* @example
|
|
151
|
+
* ```ts
|
|
152
|
+
* import { createBindingId } from '@tldraw/tlschema'
|
|
153
|
+
*
|
|
154
|
+
* // Create a new binding ID
|
|
155
|
+
* const bindingId: TLBindingId = createBindingId()
|
|
156
|
+
*
|
|
157
|
+
* // Use in binding records
|
|
158
|
+
* const binding: TLBinding = {
|
|
159
|
+
* id: bindingId,
|
|
160
|
+
* type: 'arrow',
|
|
161
|
+
* fromId: 'shape:arrow1',
|
|
162
|
+
* toId: 'shape:rectangle1',
|
|
163
|
+
* // ... other properties
|
|
164
|
+
* }
|
|
165
|
+
* ```
|
|
59
166
|
*
|
|
60
167
|
* @public
|
|
61
168
|
*/
|
|
62
169
|
export type TLBindingId = RecordId<TLUnknownBinding>
|
|
63
170
|
|
|
64
|
-
/**
|
|
171
|
+
/**
|
|
172
|
+
* Migration version identifiers for the root binding record schema.
|
|
173
|
+
* Currently empty as no migrations have been applied to the base binding structure.
|
|
174
|
+
*
|
|
175
|
+
* @example
|
|
176
|
+
* ```ts
|
|
177
|
+
* // Future migrations would be defined here
|
|
178
|
+
* const rootBindingVersions = createMigrationIds('com.tldraw.binding', {
|
|
179
|
+
* AddNewProperty: 1,
|
|
180
|
+
* } as const)
|
|
181
|
+
* ```
|
|
182
|
+
*
|
|
183
|
+
* @public
|
|
184
|
+
*/
|
|
65
185
|
export const rootBindingVersions = createMigrationIds('com.tldraw.binding', {} as const)
|
|
66
186
|
|
|
67
|
-
/**
|
|
187
|
+
/**
|
|
188
|
+
* Migration sequence for the root binding record structure.
|
|
189
|
+
* Currently empty as the binding schema has not required any migrations yet.
|
|
190
|
+
*
|
|
191
|
+
* @example
|
|
192
|
+
* ```ts
|
|
193
|
+
* // Migrations would be automatically applied when loading old documents
|
|
194
|
+
* const migratedStore = migrator.migrateStoreSnapshot({
|
|
195
|
+
* schema: oldSchema,
|
|
196
|
+
* store: oldStoreSnapshot
|
|
197
|
+
* })
|
|
198
|
+
* ```
|
|
199
|
+
*
|
|
200
|
+
* @public
|
|
201
|
+
*/
|
|
68
202
|
export const rootBindingMigrations = createRecordMigrationSequence({
|
|
69
203
|
sequenceId: 'com.tldraw.binding',
|
|
70
204
|
recordType: 'binding',
|
|
71
205
|
sequence: [],
|
|
72
206
|
})
|
|
73
207
|
|
|
74
|
-
/**
|
|
208
|
+
/**
|
|
209
|
+
* Type guard to check if a record is a TLBinding.
|
|
210
|
+
* Useful for filtering or type narrowing when working with mixed record types.
|
|
211
|
+
*
|
|
212
|
+
* @param record - The record to check
|
|
213
|
+
* @returns True if the record is a binding, false otherwise
|
|
214
|
+
*
|
|
215
|
+
* @example
|
|
216
|
+
* ```ts
|
|
217
|
+
* // Filter bindings from mixed records
|
|
218
|
+
* const allRecords = store.allRecords()
|
|
219
|
+
* const bindings = allRecords.filter(isBinding)
|
|
220
|
+
*
|
|
221
|
+
* // Type guard usage
|
|
222
|
+
* function processRecord(record: UnknownRecord) {
|
|
223
|
+
* if (isBinding(record)) {
|
|
224
|
+
* // record is now typed as TLBinding
|
|
225
|
+
* console.log(`Binding from ${record.fromId} to ${record.toId}`)
|
|
226
|
+
* }
|
|
227
|
+
* }
|
|
228
|
+
* ```
|
|
229
|
+
*
|
|
230
|
+
* @public
|
|
231
|
+
*/
|
|
75
232
|
export function isBinding(record?: UnknownRecord): record is TLBinding {
|
|
76
233
|
if (!record) return false
|
|
77
234
|
return record.typeName === 'binding'
|
|
78
235
|
}
|
|
79
236
|
|
|
80
|
-
/**
|
|
237
|
+
/**
|
|
238
|
+
* Type guard to check if a string is a valid TLBindingId.
|
|
239
|
+
* Validates that the ID follows the correct format for binding identifiers.
|
|
240
|
+
*
|
|
241
|
+
* @param id - The string to check
|
|
242
|
+
* @returns True if the string is a valid binding ID, false otherwise
|
|
243
|
+
*
|
|
244
|
+
* @example
|
|
245
|
+
* ```ts
|
|
246
|
+
* // Validate binding IDs
|
|
247
|
+
* const maybeBindingId = 'binding:abc123'
|
|
248
|
+
* if (isBindingId(maybeBindingId)) {
|
|
249
|
+
* // maybeBindingId is now typed as TLBindingId
|
|
250
|
+
* const binding = store.get(maybeBindingId)
|
|
251
|
+
* }
|
|
252
|
+
*
|
|
253
|
+
* // Filter binding IDs from mixed ID array
|
|
254
|
+
* const mixedIds = ['shape:1', 'binding:2', 'page:3']
|
|
255
|
+
* const bindingIds = mixedIds.filter(isBindingId)
|
|
256
|
+
* ```
|
|
257
|
+
*
|
|
258
|
+
* @public
|
|
259
|
+
*/
|
|
81
260
|
export function isBindingId(id?: string): id is TLBindingId {
|
|
82
261
|
if (!id) return false
|
|
83
262
|
return id.startsWith('binding:')
|
|
84
263
|
}
|
|
85
264
|
|
|
86
|
-
/**
|
|
265
|
+
/**
|
|
266
|
+
* Creates a new TLBindingId with proper formatting.
|
|
267
|
+
* Generates a unique ID if none is provided, or formats a provided ID correctly.
|
|
268
|
+
*
|
|
269
|
+
* @param id - Optional custom ID suffix. If not provided, a unique ID is generated
|
|
270
|
+
* @returns A properly formatted binding ID
|
|
271
|
+
*
|
|
272
|
+
* @example
|
|
273
|
+
* ```ts
|
|
274
|
+
* // Create with auto-generated ID
|
|
275
|
+
* const bindingId1 = createBindingId() // 'binding:abc123'
|
|
276
|
+
*
|
|
277
|
+
* // Create with custom ID
|
|
278
|
+
* const bindingId2 = createBindingId('myCustomBinding') // 'binding:myCustomBinding'
|
|
279
|
+
*
|
|
280
|
+
* // Use in binding creation
|
|
281
|
+
* const binding: TLBinding = {
|
|
282
|
+
* id: createBindingId(),
|
|
283
|
+
* type: 'arrow',
|
|
284
|
+
* fromId: 'shape:arrow1',
|
|
285
|
+
* toId: 'shape:rectangle1',
|
|
286
|
+
* // ... other properties
|
|
287
|
+
* }
|
|
288
|
+
* ```
|
|
289
|
+
*
|
|
290
|
+
* @public
|
|
291
|
+
*/
|
|
87
292
|
export function createBindingId(id?: string): TLBindingId {
|
|
88
293
|
return `binding:${id ?? uniqueId()}` as TLBindingId
|
|
89
294
|
}
|
|
90
295
|
|
|
91
296
|
/**
|
|
297
|
+
* Creates a migration sequence for binding properties.
|
|
298
|
+
* This is a pass-through function that validates and returns the provided migrations.
|
|
299
|
+
*
|
|
300
|
+
* @param migrations - The migration sequence for binding properties
|
|
301
|
+
* @returns The validated migration sequence
|
|
302
|
+
*
|
|
303
|
+
* @example
|
|
304
|
+
* ```ts
|
|
305
|
+
* // Define migrations for custom binding properties
|
|
306
|
+
* const myBindingMigrations = createBindingPropsMigrationSequence({
|
|
307
|
+
* sequence: [
|
|
308
|
+
* {
|
|
309
|
+
* id: 'com.myapp.binding.custom/1.0.0',
|
|
310
|
+
* up: (props) => ({ ...props, newProperty: 'default' }),
|
|
311
|
+
* down: ({ newProperty, ...props }) => props
|
|
312
|
+
* }
|
|
313
|
+
* ]
|
|
314
|
+
* })
|
|
315
|
+
* ```
|
|
316
|
+
*
|
|
92
317
|
* @public
|
|
93
318
|
*/
|
|
94
319
|
export function createBindingPropsMigrationSequence(
|
|
@@ -98,6 +323,28 @@ export function createBindingPropsMigrationSequence(
|
|
|
98
323
|
}
|
|
99
324
|
|
|
100
325
|
/**
|
|
326
|
+
* Creates properly formatted migration IDs for binding property migrations.
|
|
327
|
+
* Follows the convention: 'com.tldraw.binding.\{bindingType\}/\{version\}'
|
|
328
|
+
*
|
|
329
|
+
* @param bindingType - The type of binding these migrations apply to
|
|
330
|
+
* @param ids - Object mapping migration names to version numbers
|
|
331
|
+
* @returns Object with formatted migration IDs
|
|
332
|
+
*
|
|
333
|
+
* @example
|
|
334
|
+
* ```ts
|
|
335
|
+
* // Create migration IDs for custom binding
|
|
336
|
+
* const myBindingVersions = createBindingPropsMigrationIds('myCustomBinding', {
|
|
337
|
+
* AddNewProperty: 1,
|
|
338
|
+
* UpdateProperty: 2
|
|
339
|
+
* })
|
|
340
|
+
*
|
|
341
|
+
* // Result:
|
|
342
|
+
* // {
|
|
343
|
+
* // AddNewProperty: 'com.tldraw.binding.myCustomBinding/1',
|
|
344
|
+
* // UpdateProperty: 'com.tldraw.binding.myCustomBinding/2'
|
|
345
|
+
* // }
|
|
346
|
+
* ```
|
|
347
|
+
*
|
|
101
348
|
* @public
|
|
102
349
|
*/
|
|
103
350
|
export function createBindingPropsMigrationIds<S extends string, T extends Record<string, number>>(
|
|
@@ -107,7 +354,26 @@ export function createBindingPropsMigrationIds<S extends string, T extends Recor
|
|
|
107
354
|
return mapObjectMapValues(ids, (_k, v) => `com.tldraw.binding.${bindingType}/${v}`) as any
|
|
108
355
|
}
|
|
109
356
|
|
|
110
|
-
/**
|
|
357
|
+
/**
|
|
358
|
+
* Creates a record type for TLBinding with validation based on the provided binding schemas.
|
|
359
|
+
* This function is used internally to configure the binding record type in the schema.
|
|
360
|
+
*
|
|
361
|
+
* @param bindings - Record mapping binding type names to their schema information
|
|
362
|
+
* @returns A configured record type for bindings with validation
|
|
363
|
+
*
|
|
364
|
+
* @example
|
|
365
|
+
* ```ts
|
|
366
|
+
* // Used internally when creating schemas
|
|
367
|
+
* const bindingRecordType = createBindingRecordType({
|
|
368
|
+
* arrow: {
|
|
369
|
+
* props: arrowBindingProps,
|
|
370
|
+
* meta: arrowBindingMeta
|
|
371
|
+
* }
|
|
372
|
+
* })
|
|
373
|
+
* ```
|
|
374
|
+
*
|
|
375
|
+
* @internal
|
|
376
|
+
*/
|
|
111
377
|
export function createBindingRecordType(bindings: Record<string, SchemaPropsInfo>) {
|
|
112
378
|
return createRecordType<TLBinding>('binding', {
|
|
113
379
|
scope: 'document',
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { describe, expect, it } from 'vitest'
|
|
2
|
+
import { cameraMigrations, cameraVersions } from './TLCamera'
|
|
3
|
+
|
|
4
|
+
describe('cameraMigrations', () => {
|
|
5
|
+
it('should apply AddMeta migration correctly', () => {
|
|
6
|
+
const addMetaMigration = cameraMigrations.sequence.find((m) => m.id === cameraVersions.AddMeta)!
|
|
7
|
+
|
|
8
|
+
const oldRecord: any = {
|
|
9
|
+
typeName: 'camera',
|
|
10
|
+
id: 'camera:test',
|
|
11
|
+
x: 100,
|
|
12
|
+
y: 200,
|
|
13
|
+
z: 0.5,
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
addMetaMigration.up(oldRecord)
|
|
17
|
+
expect(oldRecord.meta).toEqual({})
|
|
18
|
+
})
|
|
19
|
+
})
|
package/src/records/TLCamera.ts
CHANGED
|
@@ -10,24 +10,84 @@ import { T } from '@tldraw/validate'
|
|
|
10
10
|
import { idValidator } from '../misc/id-validator'
|
|
11
11
|
|
|
12
12
|
/**
|
|
13
|
-
* A camera record.
|
|
13
|
+
* A camera record representing the viewport's position and zoom level.
|
|
14
|
+
* The camera defines what portion of the infinite canvas is visible to the user.
|
|
15
|
+
*
|
|
16
|
+
* @example
|
|
17
|
+
* ```ts
|
|
18
|
+
* const camera: TLCamera = {
|
|
19
|
+
* id: 'camera:user1',
|
|
20
|
+
* typeName: 'camera',
|
|
21
|
+
* x: 100, // Camera x position (negative values pan right)
|
|
22
|
+
* y: 50, // Camera y position (negative values pan down)
|
|
23
|
+
* z: 0.5, // Zoom level (1 = 100%, 0.5 = 50%, 2 = 200%)
|
|
24
|
+
* meta: {
|
|
25
|
+
* userId: 'user123',
|
|
26
|
+
* lastUpdated: Date.now()
|
|
27
|
+
* }
|
|
28
|
+
* }
|
|
29
|
+
*
|
|
30
|
+
* // Set camera position and zoom
|
|
31
|
+
* editor.setCamera({ x: -200, y: -100, z: 1.5 })
|
|
32
|
+
* ```
|
|
14
33
|
*
|
|
15
34
|
* @public
|
|
16
35
|
*/
|
|
17
36
|
export interface TLCamera extends BaseRecord<'camera', TLCameraId> {
|
|
37
|
+
/** Camera x position. Negative values move the viewport right */
|
|
18
38
|
x: number
|
|
39
|
+
/** Camera y position. Negative values move the viewport down */
|
|
19
40
|
y: number
|
|
41
|
+
/** Zoom level. 1 = 100%, 0.5 = 50% zoom, 2 = 200% zoom */
|
|
20
42
|
z: number
|
|
43
|
+
/** User-defined metadata for the camera */
|
|
21
44
|
meta: JsonObject
|
|
22
45
|
}
|
|
23
46
|
|
|
24
47
|
/**
|
|
25
|
-
*
|
|
48
|
+
* Branded string type for camera record identifiers.
|
|
49
|
+
* Prevents mixing camera IDs with other types of record IDs at compile time.
|
|
50
|
+
*
|
|
51
|
+
* @example
|
|
52
|
+
* ```ts
|
|
53
|
+
* import { CameraRecordType } from '@tldraw/tlschema'
|
|
54
|
+
*
|
|
55
|
+
* // Create a camera ID (typically one per user/session)
|
|
56
|
+
* const cameraId: TLCameraId = CameraRecordType.createId()
|
|
26
57
|
*
|
|
27
|
-
*
|
|
58
|
+
* // Use in camera records
|
|
59
|
+
* const camera: TLCamera = {
|
|
60
|
+
* id: cameraId,
|
|
61
|
+
* typeName: 'camera',
|
|
62
|
+
* x: 0, y: 0, z: 1,
|
|
63
|
+
* meta: {}
|
|
64
|
+
* }
|
|
65
|
+
*
|
|
66
|
+
* // Get camera from store
|
|
67
|
+
* const currentCamera = store.get(cameraId)
|
|
68
|
+
* ```
|
|
69
|
+
*
|
|
70
|
+
* @public
|
|
71
|
+
*/
|
|
28
72
|
export type TLCameraId = RecordId<TLCamera>
|
|
29
73
|
|
|
30
|
-
/**
|
|
74
|
+
/**
|
|
75
|
+
* Validator for TLCamera records that ensures runtime type safety.
|
|
76
|
+
* Validates camera position coordinates and zoom level.
|
|
77
|
+
*
|
|
78
|
+
* @example
|
|
79
|
+
* ```ts
|
|
80
|
+
* // Validation happens automatically when cameras are stored
|
|
81
|
+
* try {
|
|
82
|
+
* const validatedCamera = cameraValidator.validate(cameraData)
|
|
83
|
+
* store.put([validatedCamera])
|
|
84
|
+
* } catch (error) {
|
|
85
|
+
* console.error('Camera validation failed:', error.message)
|
|
86
|
+
* }
|
|
87
|
+
* ```
|
|
88
|
+
*
|
|
89
|
+
* @public
|
|
90
|
+
*/
|
|
31
91
|
export const cameraValidator: T.Validator<TLCamera> = T.model(
|
|
32
92
|
'camera',
|
|
33
93
|
T.object({
|
|
@@ -40,12 +100,37 @@ export const cameraValidator: T.Validator<TLCamera> = T.model(
|
|
|
40
100
|
})
|
|
41
101
|
)
|
|
42
102
|
|
|
43
|
-
/**
|
|
103
|
+
/**
|
|
104
|
+
* Migration version identifiers for camera record schema evolution.
|
|
105
|
+
* Each version represents a breaking change that requires data migration.
|
|
106
|
+
*
|
|
107
|
+
* @example
|
|
108
|
+
* ```ts
|
|
109
|
+
* // Check if a camera needs migration
|
|
110
|
+
* const needsMigration = currentVersion < cameraVersions.AddMeta
|
|
111
|
+
* ```
|
|
112
|
+
*
|
|
113
|
+
* @public
|
|
114
|
+
*/
|
|
44
115
|
export const cameraVersions = createMigrationIds('com.tldraw.camera', {
|
|
45
116
|
AddMeta: 1,
|
|
46
117
|
})
|
|
47
118
|
|
|
48
|
-
/**
|
|
119
|
+
/**
|
|
120
|
+
* Migration sequence for evolving camera record structure over time.
|
|
121
|
+
* Handles converting camera records from older schema versions to current format.
|
|
122
|
+
*
|
|
123
|
+
* @example
|
|
124
|
+
* ```ts
|
|
125
|
+
* // Migration is applied automatically when loading old documents
|
|
126
|
+
* const migratedStore = migrator.migrateStoreSnapshot({
|
|
127
|
+
* schema: oldSchema,
|
|
128
|
+
* store: oldStoreSnapshot
|
|
129
|
+
* })
|
|
130
|
+
* ```
|
|
131
|
+
*
|
|
132
|
+
* @public
|
|
133
|
+
*/
|
|
49
134
|
export const cameraMigrations = createRecordMigrationSequence({
|
|
50
135
|
sequenceId: 'com.tldraw.camera',
|
|
51
136
|
recordType: 'camera',
|
|
@@ -59,7 +144,33 @@ export const cameraMigrations = createRecordMigrationSequence({
|
|
|
59
144
|
],
|
|
60
145
|
})
|
|
61
146
|
|
|
62
|
-
/**
|
|
147
|
+
/**
|
|
148
|
+
* Record type definition for TLCamera with validation and default properties.
|
|
149
|
+
* Configures cameras as session-scoped records that don't persist across sessions.
|
|
150
|
+
*
|
|
151
|
+
* @example
|
|
152
|
+
* ```ts
|
|
153
|
+
* // Create a new camera record with defaults
|
|
154
|
+
* const cameraRecord = CameraRecordType.create({
|
|
155
|
+
* id: 'camera:main'
|
|
156
|
+
* // x: 0, y: 0, z: 1, meta: {} are applied as defaults
|
|
157
|
+
* })
|
|
158
|
+
*
|
|
159
|
+
* // Create with custom position and zoom
|
|
160
|
+
* const customCamera = CameraRecordType.create({
|
|
161
|
+
* id: 'camera:user1',
|
|
162
|
+
* x: -100,
|
|
163
|
+
* y: -50,
|
|
164
|
+
* z: 1.5,
|
|
165
|
+
* meta: { userId: 'user123' }
|
|
166
|
+
* })
|
|
167
|
+
*
|
|
168
|
+
* // Store the camera
|
|
169
|
+
* store.put([cameraRecord])
|
|
170
|
+
* ```
|
|
171
|
+
*
|
|
172
|
+
* @public
|
|
173
|
+
*/
|
|
63
174
|
export const CameraRecordType = createRecordType<TLCamera>('camera', {
|
|
64
175
|
validator: cameraValidator,
|
|
65
176
|
scope: 'session',
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { describe, expect, it } from 'vitest'
|
|
2
|
+
import { documentMigrations, documentVersions, TLDOCUMENT_ID } from './TLDocument'
|
|
3
|
+
|
|
4
|
+
describe('documentMigrations', () => {
|
|
5
|
+
it('should apply AddName migration correctly', () => {
|
|
6
|
+
const addNameMigration = documentMigrations.sequence.find(
|
|
7
|
+
(m) => m.id === documentVersions.AddName
|
|
8
|
+
)!
|
|
9
|
+
|
|
10
|
+
const oldRecord: any = {
|
|
11
|
+
typeName: 'document',
|
|
12
|
+
id: TLDOCUMENT_ID,
|
|
13
|
+
gridSize: 10,
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
addNameMigration.up(oldRecord)
|
|
17
|
+
expect(oldRecord.name).toBe('')
|
|
18
|
+
})
|
|
19
|
+
|
|
20
|
+
it('should apply AddMeta migration correctly', () => {
|
|
21
|
+
const addMetaMigration = documentMigrations.sequence.find(
|
|
22
|
+
(m) => m.id === documentVersions.AddMeta
|
|
23
|
+
)!
|
|
24
|
+
|
|
25
|
+
const oldRecord: any = {
|
|
26
|
+
typeName: 'document',
|
|
27
|
+
id: TLDOCUMENT_ID,
|
|
28
|
+
gridSize: 10,
|
|
29
|
+
name: 'Test',
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
addMetaMigration.up(oldRecord)
|
|
33
|
+
expect(oldRecord.meta).toEqual({})
|
|
34
|
+
})
|
|
35
|
+
})
|