@tldraw/tlschema 5.2.0-next.ee0fa4d6244f → 5.2.1
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/DOCS.md +682 -0
- package/README.md +9 -1
- package/dist-cjs/index.d.ts +85 -11
- package/dist-cjs/index.js +3 -1
- package/dist-cjs/index.js.map +2 -2
- package/dist-cjs/misc/b64Vecs.js +175 -10
- package/dist-cjs/misc/b64Vecs.js.map +2 -2
- package/dist-cjs/records/TLInstance.js +3 -2
- package/dist-cjs/records/TLInstance.js.map +2 -2
- package/dist-cjs/records/TLPageState.js +5 -1
- package/dist-cjs/records/TLPageState.js.map +2 -2
- package/dist-cjs/records/TLPresence.js +3 -2
- package/dist-cjs/records/TLPresence.js.map +2 -2
- package/dist-cjs/shapes/TLDrawShape.js +16 -2
- package/dist-cjs/shapes/TLDrawShape.js.map +2 -2
- package/dist-cjs/shapes/TLHighlightShape.js +14 -1
- package/dist-cjs/shapes/TLHighlightShape.js.map +2 -2
- package/dist-cjs/shapes/TLNoteShape.js +14 -2
- package/dist-cjs/shapes/TLNoteShape.js.map +2 -2
- package/dist-esm/index.d.mts +85 -11
- package/dist-esm/index.mjs +4 -2
- package/dist-esm/index.mjs.map +2 -2
- package/dist-esm/misc/b64Vecs.mjs +175 -10
- package/dist-esm/misc/b64Vecs.mjs.map +2 -2
- package/dist-esm/records/TLInstance.mjs +3 -2
- package/dist-esm/records/TLInstance.mjs.map +2 -2
- package/dist-esm/records/TLPageState.mjs +5 -1
- package/dist-esm/records/TLPageState.mjs.map +2 -2
- package/dist-esm/records/TLPresence.mjs +3 -2
- package/dist-esm/records/TLPresence.mjs.map +2 -2
- package/dist-esm/shapes/TLDrawShape.mjs +17 -3
- package/dist-esm/shapes/TLDrawShape.mjs.map +2 -2
- package/dist-esm/shapes/TLHighlightShape.mjs +15 -2
- package/dist-esm/shapes/TLHighlightShape.mjs.map +2 -2
- package/dist-esm/shapes/TLNoteShape.mjs +14 -2
- package/dist-esm/shapes/TLNoteShape.mjs.map +2 -2
- package/package.json +11 -7
- package/src/index.ts +1 -1
- package/src/migrations.test.ts +136 -1
- package/src/misc/b64Vecs.test.ts +112 -0
- package/src/misc/b64Vecs.ts +230 -15
- package/src/records/TLInstance.ts +5 -4
- package/src/records/TLPageState.ts +5 -1
- package/src/records/TLPresence.ts +5 -4
- package/src/shapes/TLDrawShape.ts +30 -1
- package/src/shapes/TLHighlightShape.ts +19 -1
- package/src/shapes/TLNoteShape.ts +15 -3
|
@@ -13,6 +13,7 @@ import { cursorTypeValidator, TLCursor } from '../misc/TLCursor'
|
|
|
13
13
|
import { scribbleValidator, TLScribble } from '../misc/TLScribble'
|
|
14
14
|
import { TLPageId } from './TLPage'
|
|
15
15
|
import { TLShapeId } from './TLShape'
|
|
16
|
+
import { TLUserId, userIdValidator } from './TLUser'
|
|
16
17
|
|
|
17
18
|
/**
|
|
18
19
|
* Represents the presence state of a user in a collaborative tldraw session.
|
|
@@ -39,7 +40,7 @@ import { TLShapeId } from './TLShape'
|
|
|
39
40
|
* @public
|
|
40
41
|
*/
|
|
41
42
|
export interface TLInstancePresence extends BaseRecord<'instance_presence', TLInstancePresenceID> {
|
|
42
|
-
userId:
|
|
43
|
+
userId: TLUserId
|
|
43
44
|
userName: string
|
|
44
45
|
lastActivityTimestamp: number | null
|
|
45
46
|
color: string // can be any hex color
|
|
@@ -49,7 +50,7 @@ export interface TLInstancePresence extends BaseRecord<'instance_presence', TLIn
|
|
|
49
50
|
brush: BoxModel | null
|
|
50
51
|
scribbles: TLScribble[]
|
|
51
52
|
screenBounds: BoxModel | null
|
|
52
|
-
followingUserId:
|
|
53
|
+
followingUserId: TLUserId | null
|
|
53
54
|
cursor: {
|
|
54
55
|
x: number
|
|
55
56
|
y: number
|
|
@@ -101,10 +102,10 @@ export const instancePresenceValidator: T.Validator<TLInstancePresence> = T.mode
|
|
|
101
102
|
T.object({
|
|
102
103
|
typeName: T.literal('instance_presence'),
|
|
103
104
|
id: idValidator<TLInstancePresenceID>('instance_presence'),
|
|
104
|
-
userId:
|
|
105
|
+
userId: userIdValidator,
|
|
105
106
|
userName: T.string,
|
|
106
107
|
lastActivityTimestamp: T.number.nullable(),
|
|
107
|
-
followingUserId:
|
|
108
|
+
followingUserId: userIdValidator.nullable(),
|
|
108
109
|
cursor: T.object({
|
|
109
110
|
x: T.number,
|
|
110
111
|
y: T.number,
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { T } from '@tldraw/validate'
|
|
2
|
-
import { b64Vecs } from '../misc/b64Vecs'
|
|
2
|
+
import { DIM_2D, DIM_3D, b64Vecs } from '../misc/b64Vecs'
|
|
3
3
|
import { VecModel } from '../misc/geometry-types'
|
|
4
4
|
import { createShapePropsMigrationIds, createShapePropsMigrationSequence } from '../records/TLShape'
|
|
5
5
|
import { RecordProps } from '../recordsWithProps'
|
|
@@ -22,6 +22,12 @@ export interface TLDrawShapeSegment {
|
|
|
22
22
|
* First point stored as Float32 (12 bytes) for precision, subsequent points as Float16 deltas (6 bytes each).
|
|
23
23
|
*/
|
|
24
24
|
path: string
|
|
25
|
+
/**
|
|
26
|
+
* Encoding dimension of `path`. `2` means (x, y) only — the constant 0.5 pressure
|
|
27
|
+
* was omitted, for input from devices that don't report pressure. `3` or absent
|
|
28
|
+
* (the legacy default) means (x, y, z). Added in the `OmitNonPressureZ` migration.
|
|
29
|
+
*/
|
|
30
|
+
dim?: 2 | 3
|
|
25
31
|
}
|
|
26
32
|
|
|
27
33
|
/**
|
|
@@ -32,6 +38,7 @@ export interface TLDrawShapeSegment {
|
|
|
32
38
|
export const DrawShapeSegment: T.ObjectValidator<TLDrawShapeSegment> = T.object({
|
|
33
39
|
type: T.literalEnum('free', 'straight'),
|
|
34
40
|
path: T.string,
|
|
41
|
+
dim: T.literalEnum(DIM_2D, DIM_3D).optional(),
|
|
35
42
|
})
|
|
36
43
|
|
|
37
44
|
/**
|
|
@@ -138,6 +145,7 @@ const Versions = createShapePropsMigrationIds('draw', {
|
|
|
138
145
|
AddScale: 2,
|
|
139
146
|
Base64: 3,
|
|
140
147
|
LegacyPointsConversion: 4,
|
|
148
|
+
OmitNonPressureZ: 5,
|
|
141
149
|
})
|
|
142
150
|
|
|
143
151
|
/**
|
|
@@ -239,6 +247,27 @@ export const drawShapeMigrations = createShapePropsMigrationSequence({
|
|
|
239
247
|
// handled by the previous down migration
|
|
240
248
|
},
|
|
241
249
|
},
|
|
250
|
+
{
|
|
251
|
+
id: Versions.OmitNonPressureZ,
|
|
252
|
+
up: (_props) => {
|
|
253
|
+
// No-op. Pre-existing segments have no `dim` field, which is exactly how
|
|
254
|
+
// the new schema reads them (3D). The validator now accepts the optional
|
|
255
|
+
// `dim`, so newer 2D segments validate as well — nothing to rewrite here.
|
|
256
|
+
},
|
|
257
|
+
down: (props) => {
|
|
258
|
+
// Older clients only understand 3D paths and reject the unknown `dim` field.
|
|
259
|
+
// Strip `dim` from every segment that carries it; a 2D segment is also
|
|
260
|
+
// re-encoded back to 3D (decode supplies z = 0.5), while a `dim: 3` segment
|
|
261
|
+
// already has a 3D path so we just drop the field.
|
|
262
|
+
props.segments = props.segments.map((segment: any) => {
|
|
263
|
+
if (segment.dim === undefined) return segment
|
|
264
|
+
const { dim, ...rest } = segment
|
|
265
|
+
return dim === DIM_2D
|
|
266
|
+
? { ...rest, path: b64Vecs.encodePoints(b64Vecs.decodePoints(segment.path, DIM_2D)) }
|
|
267
|
+
: rest
|
|
268
|
+
})
|
|
269
|
+
},
|
|
270
|
+
},
|
|
242
271
|
],
|
|
243
272
|
})
|
|
244
273
|
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { T } from '@tldraw/validate'
|
|
2
|
-
import { b64Vecs } from '../misc/b64Vecs'
|
|
2
|
+
import { DIM_2D, b64Vecs } from '../misc/b64Vecs'
|
|
3
3
|
import { createShapePropsMigrationIds, createShapePropsMigrationSequence } from '../records/TLShape'
|
|
4
4
|
import { RecordProps } from '../recordsWithProps'
|
|
5
5
|
import { DefaultColorStyle, TLDefaultColorStyle } from '../styles/TLColorStyle'
|
|
@@ -105,6 +105,7 @@ const Versions = createShapePropsMigrationIds('highlight', {
|
|
|
105
105
|
AddScale: 1,
|
|
106
106
|
Base64: 2,
|
|
107
107
|
LegacyPointsConversion: 3,
|
|
108
|
+
OmitNonPressureZ: 4,
|
|
108
109
|
})
|
|
109
110
|
|
|
110
111
|
/**
|
|
@@ -182,5 +183,22 @@ export const highlightShapeMigrations = createShapePropsMigrationSequence({
|
|
|
182
183
|
// handled by the previous down migration
|
|
183
184
|
},
|
|
184
185
|
},
|
|
186
|
+
{
|
|
187
|
+
id: Versions.OmitNonPressureZ,
|
|
188
|
+
up: (_props) => {
|
|
189
|
+
// No-op — see the matching draw-shape migration. Absent `dim` reads as 3D.
|
|
190
|
+
},
|
|
191
|
+
down: (props) => {
|
|
192
|
+
// Strip `dim` from every segment that carries it (older clients reject the
|
|
193
|
+
// unknown field); 2D segments are re-encoded to 3D, dim: 3 just loses the field.
|
|
194
|
+
props.segments = props.segments.map((segment: any) => {
|
|
195
|
+
if (segment.dim === undefined) return segment
|
|
196
|
+
const { dim, ...rest } = segment
|
|
197
|
+
return dim === DIM_2D
|
|
198
|
+
? { ...rest, path: b64Vecs.encodePoints(b64Vecs.decodePoints(segment.path, DIM_2D)) }
|
|
199
|
+
: rest
|
|
200
|
+
})
|
|
201
|
+
},
|
|
202
|
+
},
|
|
185
203
|
],
|
|
186
204
|
})
|
|
@@ -64,8 +64,8 @@ export interface TLNoteShapeProps {
|
|
|
64
64
|
richText: TLRichText
|
|
65
65
|
/** Scale factor applied to the note shape for display */
|
|
66
66
|
scale: number
|
|
67
|
-
/** User ID of the person who
|
|
68
|
-
|
|
67
|
+
/** User ID of the person who last edited the note text */
|
|
68
|
+
textLastEditedBy: string | null
|
|
69
69
|
}
|
|
70
70
|
|
|
71
71
|
/**
|
|
@@ -132,7 +132,7 @@ export const noteShapeProps: RecordProps<TLNoteShape> = {
|
|
|
132
132
|
url: T.linkUrl,
|
|
133
133
|
richText: richTextValidator,
|
|
134
134
|
scale: T.nonZeroNumber,
|
|
135
|
-
|
|
135
|
+
textLastEditedBy: T.string.nullable(),
|
|
136
136
|
}
|
|
137
137
|
|
|
138
138
|
const Versions = createShapePropsMigrationIds('note', {
|
|
@@ -148,6 +148,7 @@ const Versions = createShapePropsMigrationIds('note', {
|
|
|
148
148
|
AddRichTextAttrs: 10,
|
|
149
149
|
AddFirstEditedBy: 11,
|
|
150
150
|
MakeFontSizeAdjustmentRatio: 12,
|
|
151
|
+
RenameFirstEditedByToLast: 13,
|
|
151
152
|
})
|
|
152
153
|
|
|
153
154
|
/**
|
|
@@ -292,5 +293,16 @@ export const noteShapeMigrations = createShapePropsMigrationSequence({
|
|
|
292
293
|
props.fontSizeAdjustment = 0
|
|
293
294
|
},
|
|
294
295
|
},
|
|
296
|
+
{
|
|
297
|
+
id: Versions.RenameFirstEditedByToLast,
|
|
298
|
+
up: (props) => {
|
|
299
|
+
props.textLastEditedBy = props.textFirstEditedBy ?? null
|
|
300
|
+
delete props.textFirstEditedBy
|
|
301
|
+
},
|
|
302
|
+
down: (props) => {
|
|
303
|
+
props.textFirstEditedBy = props.textLastEditedBy ?? null
|
|
304
|
+
delete props.textLastEditedBy
|
|
305
|
+
},
|
|
306
|
+
},
|
|
295
307
|
],
|
|
296
308
|
})
|