123 lines
2.9 KiB
TypeScript
123 lines
2.9 KiB
TypeScript
|
import { defineMigrations } from '@tldraw/tlstore'
|
||
|
import { T } from '@tldraw/tlvalidate'
|
||
|
import { Vec2dModel } from '../geometry-types'
|
||
|
import { TLColorType, TLDashType, TLFillType, TLOpacityType, TLSizeType } from '../style-types'
|
||
|
import { SetValue } from '../util-types'
|
||
|
import {
|
||
|
colorValidator,
|
||
|
dashValidator,
|
||
|
fillValidator,
|
||
|
opacityValidator,
|
||
|
sizeValidator,
|
||
|
} from '../validation'
|
||
|
import { TLBaseShape, createShapeValidator } from './shape-validation'
|
||
|
|
||
|
/** @public */
|
||
|
export const TL_DRAW_SHAPE_SEGMENT_TYPE = new Set(['free', 'straight'] as const)
|
||
|
|
||
|
/** @public */
|
||
|
export type TLDrawShapeSegment = {
|
||
|
type: SetValue<typeof TL_DRAW_SHAPE_SEGMENT_TYPE>
|
||
|
points: Vec2dModel[]
|
||
|
}
|
||
|
|
||
|
/** @public */
|
||
|
export type TLDrawShapeProps = {
|
||
|
color: TLColorType
|
||
|
fill: TLFillType
|
||
|
dash: TLDashType
|
||
|
size: TLSizeType
|
||
|
opacity: TLOpacityType
|
||
|
segments: TLDrawShapeSegment[]
|
||
|
isComplete: boolean
|
||
|
isClosed: boolean
|
||
|
isPen: boolean
|
||
|
}
|
||
|
|
||
|
/** @public */
|
||
|
export type TLDrawShape = TLBaseShape<'draw', TLDrawShapeProps>
|
||
|
|
||
|
// --- VALIDATION ---
|
||
|
/** @public */
|
||
|
export const drawShapeTypeValidator: T.Validator<TLDrawShape> = createShapeValidator(
|
||
|
'draw',
|
||
|
T.object({
|
||
|
color: colorValidator,
|
||
|
fill: fillValidator,
|
||
|
dash: dashValidator,
|
||
|
size: sizeValidator,
|
||
|
opacity: opacityValidator,
|
||
|
segments: T.arrayOf(
|
||
|
T.object({
|
||
|
type: T.setEnum(TL_DRAW_SHAPE_SEGMENT_TYPE),
|
||
|
points: T.arrayOf(T.point),
|
||
|
})
|
||
|
),
|
||
|
isComplete: T.boolean,
|
||
|
isClosed: T.boolean,
|
||
|
isPen: T.boolean,
|
||
|
})
|
||
|
)
|
||
|
|
||
|
// --- MIGRATIONS ---
|
||
|
// STEP 1: Add a new version number here, give it a meaningful name.
|
||
|
// It should be 1 higher than the current version
|
||
|
const Versions = {
|
||
|
Initial: 0,
|
||
|
AddInPen: 1,
|
||
|
} as const
|
||
|
|
||
|
/** @public */
|
||
|
export const drawShapeMigrations = defineMigrations({
|
||
|
// STEP 2: Update the current version to point to your latest version
|
||
|
firstVersion: Versions.Initial,
|
||
|
currentVersion: Versions.AddInPen,
|
||
|
migrators: {
|
||
|
// STEP 3: Add an up+down migration for the new version here
|
||
|
[Versions.AddInPen]: {
|
||
|
up: (shape) => {
|
||
|
// Rather than checking to see whether the shape is a pen at runtime,
|
||
|
// from now on we're going to use the type of device reported to us
|
||
|
// as well as the pressure data received; but for existing shapes we
|
||
|
// need to check the pressure data to see if it's a pen or not.
|
||
|
|
||
|
const { points } = shape.props.segments[0]
|
||
|
|
||
|
if (points.length === 0) {
|
||
|
return {
|
||
|
...shape,
|
||
|
props: {
|
||
|
...shape.props,
|
||
|
isPen: false,
|
||
|
},
|
||
|
}
|
||
|
}
|
||
|
|
||
|
let isPen = !(points[0].z === 0 || points[0].z === 0.5)
|
||
|
|
||
|
if (points[1]) {
|
||
|
// Double check if we have a second point (we probably should)
|
||
|
isPen = isPen && !(points[1].z === 0 || points[1].z === 0.5)
|
||
|
}
|
||
|
|
||
|
return {
|
||
|
...shape,
|
||
|
props: {
|
||
|
...shape.props,
|
||
|
isPen,
|
||
|
},
|
||
|
}
|
||
|
},
|
||
|
down: (shape) => {
|
||
|
const { isPen: _isPen, ...propsWithOutIsPen } = shape.props
|
||
|
return {
|
||
|
...shape,
|
||
|
props: {
|
||
|
...propsWithOutIsPen,
|
||
|
},
|
||
|
}
|
||
|
},
|
||
|
},
|
||
|
},
|
||
|
})
|