UNPKG

@tldraw/tlschema

Version:

tldraw infinite canvas SDK (schema).

1,602 lines (1,545 loc) • 200 kB
import { BaseRecord } from '@tldraw/store'; import { Expand } from '@tldraw/utils'; import { IndexKey } from '@tldraw/utils'; import { JsonObject } from '@tldraw/utils'; import { LegacyMigrations } from '@tldraw/store'; import { MakeUndefinedOptional } from '@tldraw/utils'; import { MigrationId } from '@tldraw/store'; import { MigrationSequence } from '@tldraw/store'; import { RecordId } from '@tldraw/store'; import { RecordScope } from '@tldraw/store'; import { RecordType } from '@tldraw/store'; import { SerializedStore } from '@tldraw/store'; import { Signal } from '@tldraw/state'; import { StandaloneDependsOn } from '@tldraw/store'; import { Store } from '@tldraw/store'; import { StoreSchema } from '@tldraw/store'; import { StoreSnapshot } from '@tldraw/store'; import { StoreValidator } from '@tldraw/store'; import { T } from '@tldraw/validate'; import { UnknownRecord } from '@tldraw/store'; /** * Migration sequence for arrow binding properties. * Handles schema evolution over time by defining how to migrate data between versions. * * The sequence includes: * - **AddSnap (v1)**: Adds the `snap` property with default value 'none' * * @example * ```ts * import { arrowBindingMigrations } from '@tldraw/tlschema' * * // Apply migrations when loading older data * const migratedBinding = arrowBindingMigrations.migrate(oldBinding) * ``` * * @public */ export declare const arrowBindingMigrations: TLPropsMigrations; /** * Validation schema for arrow binding properties. * Defines the runtime validation rules for each property in TLArrowBindingProps. * * @example * ```ts * import { arrowBindingProps } from '@tldraw/tlschema' * * // Use in custom shape schema * const customSchema = createTLSchema({ * bindings: { * arrow: { * props: arrowBindingProps, * migrations: arrowBindingMigrations * } * } * }) * ``` * * @public */ export declare const arrowBindingProps: RecordProps<TLArrowBinding>; /** * Version identifiers for arrow binding property migrations. * Each version represents a schema change that requires data migration. * * @example * ```ts * // Check if migration is needed * if (bindingVersion < arrowBindingVersions.AddSnap) { * // Apply AddSnap migration * } * ``` * * @public */ export declare const arrowBindingVersions: { AddSnap: `com.tldraw.binding.arrow/${number}`; }; /** * Style property for the arrowhead at the end of an arrow. * * Defines the visual style of the arrowhead at the end of the arrow path. * Defaults to 'arrow' style, giving arrows their characteristic pointed appearance. * * @example * ```ts * // Arrow with different start and end arrowheads * const doubleArrow: TLArrowShape = { * // ... other properties * props: { * arrowheadStart: 'triangle', * arrowheadEnd: 'diamond', * // ... other props * } * } * ``` * * @public */ export declare const ArrowShapeArrowheadEndStyle: EnumStyleProp<"arrow" | "bar" | "diamond" | "dot" | "inverted" | "none" | "pipe" | "square" | "triangle">; /** * Style property for the arrowhead at the start of an arrow. * * Defines the visual style of the arrowhead at the beginning of the arrow path. * Can be one of several predefined styles or none for no arrowhead. * * @example * ```ts * // Arrow with no start arrowhead but triangle end arrowhead * const arrow: TLArrowShape = { * // ... other properties * props: { * arrowheadStart: 'none', * arrowheadEnd: 'triangle', * // ... other props * } * } * ``` * * @public */ export declare const ArrowShapeArrowheadStartStyle: EnumStyleProp<"arrow" | "bar" | "diamond" | "dot" | "inverted" | "none" | "pipe" | "square" | "triangle">; /** * Style property for arrow shape kind, determining how the arrow is drawn. * * Arrows can be drawn as arcs (curved) or elbows (angled with straight segments). * This affects the visual appearance and behavior of arrow shapes. * * @example * ```ts * // Create an arrow with arc style (curved) * const arcArrow: TLArrowShape = { * // ... other properties * props: { * kind: 'arc', * // ... other props * } * } * * // Create an arrow with elbow style (angled) * const elbowArrow: TLArrowShape = { * // ... other properties * props: { * kind: 'elbow', * // ... other props * } * } * ``` * * @public */ export declare const ArrowShapeKindStyle: EnumStyleProp<"arc" | "elbow">; /** * Complete migration sequence for arrow shapes. * * Defines all the migrations needed to transform arrow shape data from older * versions to the current version. Each migration handles a specific schema change, * ensuring backward compatibility and smooth data evolution. * * @public */ export declare const arrowShapeMigrations: MigrationSequence; /** * Validation configuration for arrow shape properties. * * Defines the validators for each property of an arrow shape, ensuring that * arrow shape data is valid and conforms to the expected types and constraints. * * @example * ```ts * // The validators ensure proper typing and validation * const validator = T.object(arrowShapeProps) * const validArrowProps = validator.validate({ * kind: 'arc', * start: { x: 0, y: 0 }, * end: { x: 100, y: 50 }, * // ... other required properties * }) * ``` * * @public */ export declare const arrowShapeProps: RecordProps<TLArrowShape>; /** * Migration version identifiers for arrow shape properties. * * These track the evolution of the arrow shape schema over time, with each * version representing a specific change to the arrow shape structure or properties. * * @example * ```ts * // Used internally for migration system * if (version < arrowShapeVersions.AddLabelColor) { * // Apply label color migration * } * ``` * * @public */ export declare const arrowShapeVersions: { readonly AddElbow: "com.tldraw.shape.arrow/6"; readonly AddIsPrecise: "com.tldraw.shape.arrow/2"; readonly AddLabelColor: "com.tldraw.shape.arrow/1"; readonly AddLabelPosition: "com.tldraw.shape.arrow/3"; readonly AddRichText: "com.tldraw.shape.arrow/7"; readonly AddRichTextAttrs: "com.tldraw.shape.arrow/8"; readonly AddScale: "com.tldraw.shape.arrow/5"; readonly ExtractBindings: "com.tldraw.shape.arrow/4"; }; /** * A validator for asset record type IDs. This validator ensures that asset IDs * follow the correct format and type structure required by tldraw's asset system. * Asset IDs are prefixed with 'asset:' followed by a unique identifier. * * @example * ```ts * import { assetIdValidator } from '@tldraw/tlschema' * * // Valid asset ID * const validId = 'asset:abc123' * console.log(assetIdValidator.isValid(validId)) // true * * // Invalid asset ID * const invalidId = 'shape:abc123' * console.log(assetIdValidator.isValid(invalidId)) // false * ``` * * @public */ export declare const assetIdValidator: T.Validator<TLAssetId>; /** * Migration sequence for evolving asset record structure over time. * Handles converting asset records from older schema versions to current format. * * @example * ```ts * // Migration is applied automatically when loading old documents * const migratedStore = migrator.migrateStoreSnapshot({ * schema: oldSchema, * store: oldStoreSnapshot, * }) * ``` * * @public */ export declare const assetMigrations: MigrationSequence; /** * Record type definition for default TLAsset records with document scope and default metadata. * * @public */ export declare const AssetRecordType: RecordType<TLAsset<"bookmark" | "image" | "video">, "props" | "type">; /** * Utilities for encoding and decoding points using base64 and Float16 encoding. * Provides functions for converting between VecModel arrays and compact base64 strings, * as well as individual point encoding/decoding operations. * * @public */ export declare class b64Vecs { /* Excluded from this release type: _legacyEncodePoint */ /* Excluded from this release type: _legacyEncodePoints */ /* Excluded from this release type: _legacyDecodePoints */ /** * Encode an array of VecModels using delta encoding for improved precision. * The first point is stored as Float32 (high precision for absolute position), * subsequent points are stored as Float16 deltas from the previous point. * This provides full precision for the starting position and excellent precision * for deltas between consecutive points (which are typically small values). * * Format: * - First point: 3 Float32 values = 12 bytes = 16 base64 chars * - Delta points: 3 Float16 values each = 6 bytes = 8 base64 chars each * * @param points - An array of VecModel objects to encode * @returns A base64-encoded string containing delta-encoded points * @public */ static encodePoints(points: VecModel[]): string; /** * Decode a delta-encoded base64 string back to an array of absolute VecModels. * The first point is stored as Float32 (high precision), subsequent points are * Float16 deltas that are accumulated to reconstruct absolute positions. * * @param base64 - The base64-encoded string containing delta-encoded point data * @returns An array of VecModel objects with absolute coordinates * @public */ static decodePoints(base64: string): VecModel[]; /** * Get the first point from a delta-encoded base64 string. * The first point is stored as Float32 for full precision. * * @param b64Points - The delta-encoded base64 string * @returns The first point as a VecModel, or null if the string is too short * @public */ static decodeFirstPoint(b64Points: string): null | VecModel; /** * Get the last point from a delta-encoded base64 string. * Requires decoding all points to accumulate deltas. * * @param b64Points - The delta-encoded base64 string * @returns The last point as a VecModel, or null if the string is too short * @public */ static decodeLastPoint(b64Points: string): null | VecModel; } /** * Validator for binding IDs. Ensures that binding identifiers follow the correct * format and type constraints required by the tldraw schema system. * * Used internally by the schema validation system to verify binding IDs when * records are created or modified. All binding IDs must be prefixed with 'binding:'. * * @example * ```ts * import { bindingIdValidator } from '@tldraw/tlschema' * * // Validate a binding ID * const isValid = bindingIdValidator.isValid('binding:abc123') // true * const isInvalid = bindingIdValidator.isValid('shape:abc123') // false * * // Use in custom validation schema * const customBindingValidator = T.object({ * id: bindingIdValidator, * // ... other properties * }) * ``` * * @public */ export declare const bindingIdValidator: T.Validator<TLBindingId>; /** * Migration sequence for bookmark assets. Handles the evolution of bookmark asset * data structure over time, ensuring backward and forward compatibility. * * The migration sequence includes: * 1. **MakeUrlsValid** (v1): Validates and cleans up src URLs, setting invalid URLs to empty string * 2. **AddFavicon** (v2): Adds the favicon property and validates it, setting invalid favicons to empty string * * @public */ export declare const bookmarkAssetMigrations: MigrationSequence; /** @public */ export declare const bookmarkAssetProps: { description: T.Validator<string>; favicon: T.Validator<string>; image: T.Validator<string>; src: T.Validator<null | string>; title: T.Validator<string>; }; /** * Migration sequence for bookmark shape properties across different schema versions. * Handles backwards compatibility when bookmark shape structure changes. * * @public */ export declare const bookmarkShapeMigrations: TLPropsMigrations; /** * Validation schema for bookmark shape properties. * * @public * @example * ```ts * // Validates bookmark shape properties * const isValid = bookmarkShapeProps.url.isValid('https://example.com') * ``` */ export declare const bookmarkShapeProps: RecordProps<TLBookmarkShape>; /** * A serializable model for 2D boxes. * * @public */ export declare interface BoxModel { x: number; y: number; w: number; h: number; } /** * Validator for BoxModel objects that ensures they have numeric x, y coordinates * for position and w, h values for width and height. Used throughout the schema * to validate bounding box and rectangular area data structures. * * @public * @example * ```ts * const box = { x: 10, y: 20, w: 100, h: 50 } * const isValid = boxModelValidator.check(box) // true * * const invalidBox = { x: 10, y: 20, w: -5, h: 50 } * const isValidNegative = boxModelValidator.check(invalidBox) // true (validator allows negative values) * ``` */ export declare const boxModelValidator: T.ObjectValidator<BoxModel>; /** * Record type definition for TLCamera with validation and default properties. * Configures cameras as session-scoped records that don't persist across sessions. * * @example * ```ts * // Create a new camera record with defaults * const cameraRecord = CameraRecordType.create({ * id: 'camera:main' * // x: 0, y: 0, z: 1, meta: {} are applied as defaults * }) * * // Create with custom position and zoom * const customCamera = CameraRecordType.create({ * id: 'camera:user1', * x: -100, * y: -50, * z: 1.5, * meta: { userId: 'user123' } * }) * * // Store the camera * store.put([cameraRecord]) * ``` * * @public */ export declare const CameraRecordType: RecordType<TLCamera, never>; /** * A validator for canvas UI color types. * * This validator ensures that color values are one of the valid canvas UI * color types defined in {@link TL_CANVAS_UI_COLOR_TYPES}. It provides * runtime type checking for canvas UI color properties. * * @example * ```ts * import { canvasUiColorTypeValidator } from '@tldraw/tlschema' * * // Validate a color value * try { * const validColor = canvasUiColorTypeValidator.validate('accent') * console.log('Valid color:', validColor) * } catch (error) { * console.error('Invalid color:', error.message) * } * ``` * * @public */ export declare const canvasUiColorTypeValidator: T.Validator<"accent" | "black" | "laser" | "muted-1" | "selection-fill" | "selection-stroke" | "white">; /** * Compress legacy draw shape segments by converting VecModel[] points to delta-encoded base64 format. * This function is useful for converting old draw shape data to the new compressed format. * Uses delta encoding for improved Float16 precision. * * @public */ export declare function compressLegacySegments(segments: { points: VecModel[]; type: 'free' | 'straight'; }[]): TLDrawShapeSegment[]; /** * Creates properly formatted migration IDs for asset properties. * * @example * ```ts * const assetPropsVersions = createAssetPropsMigrationIds('file', { * AddFoo: 1, * RenameBar: 2, * }) * // => { AddFoo: 'com.tldraw.asset.file/1', RenameBar: 'com.tldraw.asset.file/2' } * ``` * * @public */ export declare function createAssetPropsMigrationIds<S extends string, T extends Record<string, number>>(assetType: S, ids: T): { [k in keyof T]: `com.tldraw.asset.${S}/${T[k]}`; }; /** * Creates a migration sequence for asset properties. * * @example * ```ts * const migrations = createAssetPropsMigrationSequence({ * sequence: [ * { id: 'com.myapp.asset.custom/1', up: (props) => { props.newField = '' } }, * ], * }) * ``` * * @public */ export declare function createAssetPropsMigrationSequence(migrations: TLPropsMigrations): TLPropsMigrations; /* Excluded from this release type: createAssetRecordType */ /** * Creates a validator for a specific asset record type. This factory function generates * a complete validator that validates the entire asset record structure including the * base properties (id, typeName, type, meta) and the type-specific props. * * @param type - The asset type identifier (e.g., 'image', 'video', 'bookmark') * @param props - A validator or per-key validator record for the asset's type-specific properties * @param meta - An optional per-key validator record for the asset's meta properties * @returns A complete validator for the asset record type * * @example * ```ts * import { createAssetValidator, TLBaseAsset } from '@tldraw/tlschema' * import { T } from '@tldraw/validate' * * // Define a custom asset type * type TLCustomAsset = TLBaseAsset<'custom', { * url: string * title: string * description?: string * }> * * // Create validator using a per-key record (recommended) * const customAssetValidator = createAssetValidator('custom', { * url: T.string, * title: T.string, * description: T.string.optional() * }) * * // Or using a T.object validator * const customAssetValidator2 = createAssetValidator('custom', T.object({ * url: T.string, * title: T.string, * description: T.string.optional() * })) * ``` * * @public */ export declare function createAssetValidator<Type extends string, Props extends JsonObject, Meta extends JsonObject = JsonObject>(type: Type, props?: { [K in keyof Props]: T.Validatable<Props[K]>; } | T.Validator<Props>, meta?: { [K in keyof Meta]: T.Validatable<Meta[K]>; }): T.ObjectValidator<Expand< { [P in "id" | "meta" | "typeName" | (undefined extends Props ? never : "props") | (undefined extends Type ? never : "type")]: TLBaseAsset<Type, Props>[P]; } & { [P in (undefined extends Props ? "props" : never) | (undefined extends Type ? "type" : never)]?: TLBaseAsset<Type, Props>[P] | undefined; }>>; /** * Creates a new TLBindingId with proper formatting. * Generates a unique ID if none is provided, or formats a provided ID correctly. * * @param id - Optional custom ID suffix. If not provided, a unique ID is generated * @returns A properly formatted binding ID * * @example * ```ts * // Create with auto-generated ID * const bindingId1 = createBindingId() // 'binding:abc123' * * // Create with custom ID * const bindingId2 = createBindingId('myCustomBinding') // 'binding:myCustomBinding' * * // Use in binding creation * const binding: TLBinding = { * id: createBindingId(), * type: 'arrow', * fromId: 'shape:arrow1', * toId: 'shape:rectangle1', * // ... other properties * } * ``` * * @public */ export declare function createBindingId(id?: string): TLBindingId; /** * Creates properly formatted migration IDs for binding property migrations. * Follows the convention: 'com.tldraw.binding.\{bindingType\}/\{version\}' * * @param bindingType - The type of binding these migrations apply to * @param ids - Object mapping migration names to version numbers * @returns Object with formatted migration IDs * * @example * ```ts * // Create migration IDs for custom binding * const myBindingVersions = createBindingPropsMigrationIds('myCustomBinding', { * AddNewProperty: 1, * UpdateProperty: 2 * }) * * // Result: * // { * // AddNewProperty: 'com.tldraw.binding.myCustomBinding/1', * // UpdateProperty: 'com.tldraw.binding.myCustomBinding/2' * // } * ``` * * @public */ export declare function createBindingPropsMigrationIds<S extends string, T extends Record<string, number>>(bindingType: S, ids: T): { [k in keyof T]: `com.tldraw.binding.${S}/${T[k]}`; }; /** * Creates a migration sequence for binding properties. * This is a pass-through function that validates and returns the provided migrations. * * @param migrations - The migration sequence for binding properties * @returns The validated migration sequence * * @example * ```ts * // Define migrations for custom binding properties * const myBindingMigrations = createBindingPropsMigrationSequence({ * sequence: [ * { * id: 'com.myapp.binding.custom/1.0.0', * up: (props) => ({ ...props, newProperty: 'default' }), * down: ({ newProperty, ...props }) => props * } * ] * }) * ``` * * @public */ export declare function createBindingPropsMigrationSequence(migrations: TLPropsMigrations): TLPropsMigrations; /** * Creates a runtime validator for a specific binding type. This factory function * generates a complete validation schema for custom bindings that extends TLBaseBinding. * * The validator ensures all binding records conform to the expected structure with * proper type safety and runtime validation. It validates the base binding properties * (id, type, fromId, toId) along with custom props and meta fields. * * @param type - The string literal type identifier for this binding (e.g., 'arrow', 'custom') * @param props - Optional validation schema for binding-specific properties * @param meta - Optional validation schema for metadata fields * * @returns A validator object that can validate complete binding records * * @example * ```ts * import { createBindingValidator } from '@tldraw/tlschema' * import { T } from '@tldraw/validate' * * // Create validator for a custom binding type * const myBindingValidator = createBindingValidator( * 'myBinding', * { * strength: T.number, * color: T.string, * enabled: T.boolean * }, * { * createdAt: T.number, * author: T.string * } * ) * * // Validate a binding instance * const bindingData = { * id: 'binding:123', * typeName: 'binding', * type: 'myBinding', * fromId: 'shape:abc', * toId: 'shape:def', * props: { * strength: 0.8, * color: 'red', * enabled: true * }, * meta: { * createdAt: Date.now(), * author: 'user123' * } * } * * const isValid = myBindingValidator.isValid(bindingData) // true * ``` * * @example * ```ts * // Simple binding without custom props or meta * const simpleBindingValidator = createBindingValidator('simple') * * // This will use JsonValue validation for props and meta * const binding = { * id: 'binding:456', * typeName: 'binding', * type: 'simple', * fromId: 'shape:start', * toId: 'shape:end', * props: {}, // Any JSON value allowed * meta: {} // Any JSON value allowed * } * ``` * * @public */ export declare function createBindingValidator<Type extends string, Props extends JsonObject, Meta extends JsonObject>(type: Type, props?: { [K in keyof Props]: T.Validatable<Props[K]>; }, meta?: { [K in keyof Meta]: T.Validatable<Meta[K]>; }): T.ObjectValidator<Expand< { [P in "fromId" | "id" | "meta" | "toId" | "typeName" | (undefined extends Props ? never : "props") | (undefined extends Type ? never : "type")]: TLBaseBinding<Type, Props>[P]; } & { [P in (undefined extends Props ? "props" : never) | (undefined extends Type ? "type" : never)]?: TLBaseBinding<Type, Props>[P] | undefined; }>>; /** * Create a cached {@link TLUserStore.resolve} implementation. * * Wraps a reactive lookup function so that each `userId` gets a single * stable {@link @tldraw/state#Signal | Signal} that is reused across calls. * The `resolveFn` is evaluated inside a `computed`, so any `.get()` calls * it makes are automatically tracked. * * @param resolveFn - A function that resolves a raw user-ID string to a * {@link TLUser} or `null`. Called reactively inside a `computed`. * @returns A function suitable for use as `TLUserStore.resolve`. * * @example * ```ts * const users: TLUserStore = { * currentUser: currentUserSignal, * resolve: createCachedUserResolve( * (userId) => usersAtom.get()[createUserId(userId)] ?? null * ), * } * ``` * * @public */ export declare function createCachedUserResolve(resolveFn: (userId: string) => null | TLUser): (userId: string) => Signal<null | TLUser>; /** * Creates a unique ID for a custom record type. * * @param typeName - The type name of the custom record * @param id - Optional custom ID suffix. If not provided, a unique ID will be generated * @returns A properly formatted record ID * * @example * ```ts * // Create with auto-generated ID * const commentId = createCustomRecordId('comment') // 'comment:abc123' * * // Create with custom ID * const customId = createCustomRecordId('comment', 'my-comment') // 'comment:my-comment' * ``` * * @public */ export declare function createCustomRecordId<T extends string>(typeName: T, id?: string): RecordId<UnknownRecord> & `${T}:${string}`; /** * Creates properly formatted migration IDs for custom record migrations. * * Generates standardized migration IDs following the convention: * `com.tldraw.{recordType}/{version}` * * @param recordType - The type name of the custom record * @param ids - Record mapping migration names to version numbers * @returns Record with the same keys but formatted migration ID values * * @example * ```ts * const commentVersions = createCustomRecordMigrationIds('comment', { * AddAuthorId: 1, * AddCreatedAt: 2, * RefactorReactions: 3 * }) * // Result: { * // AddAuthorId: 'com.tldraw.comment/1', * // AddCreatedAt: 'com.tldraw.comment/2', * // RefactorReactions: 'com.tldraw.comment/3' * // } * ``` * * @public */ export declare function createCustomRecordMigrationIds<const S extends string, const T extends Record<string, number>>(recordType: S, ids: T): { [k in keyof T]: `com.tldraw.${S}/${T[k]}`; }; /** * Creates a migration sequence for custom record types. * * This is a pass-through function that maintains the same structure as the input. * It's used for consistency and to provide a clear API for defining custom record migrations. * * @param migrations - The migration sequence to create * @returns The same migration sequence (pass-through) * * @example * ```ts * const commentMigrations = createCustomRecordMigrationSequence({ * sequence: [ * { * id: 'com.myapp.comment/1', * up: (record) => ({ ...record, authorId: record.authorId ?? 'unknown' }), * down: ({ authorId, ...record }) => record * } * ] * }) * ``` * * @public */ export declare function createCustomRecordMigrationSequence(migrations: TLPropsMigrations): TLPropsMigrations; /** * Creates a derivation that represents the current presence state of the current user. * * This function returns a derivation factory that, when given a store, creates a computed signal * containing the user's current presence state. The presence state includes information like cursor * position, selected shapes, camera position, and user metadata that gets synchronized in * multiplayer scenarios. * * @param $user - A reactive signal containing the user information, or `null` when anonymous * @param opts - Optional configuration for instance ID and presence derivation * @returns A function that takes a store and returns a computed signal of the user's presence state * * @example * ```ts * import { createPresenceStateDerivation } from '@tldraw/tlschema' * import { atom } from '@tldraw/state' * * const userSignal = atom('user', { id: 'user-123', name: 'Alice', color: '#ff0000', meta: {} }) * const presenceDerivation = createPresenceStateDerivation(userSignal) * * // Use with a store to get reactive presence state * const presenceState = presenceDerivation(store) * console.log(presenceState.get()) // Current user presence or null * ``` * * @public */ export declare function createPresenceStateDerivation($user: Signal<null | TLUser>, opts?: CreatePresenceStateDerivationOpts): (store: TLStore) => Signal<null | TLInstancePresence, unknown>; /** @public */ export declare interface CreatePresenceStateDerivationOpts { /** Custom instance ID. If not provided, one is generated from the store ID. */ instanceId?: TLInstancePresence['id']; /** * Override how presence state is built from the store and current user. * Defaults to {@link getDefaultUserPresence}. */ getUserPresence?(store: TLStore, user: TLUser): null | TLPresenceStateInfo; } /** * Creates a new shape ID. * * @param id - Optional custom ID suffix. If not provided, a unique ID will be generated * @returns A new shape ID with the "shape:" prefix * * @example * ```ts * // Create a shape with auto-generated ID * const shapeId = createShapeId() // "shape:abc123" * * // Create a shape with custom ID * const customShapeId = createShapeId('my-rectangle') // "shape:my-rectangle" * * // Use in shape creation * const newShape: TLGeoShape = { * id: createShapeId(), * type: 'geo', * x: 100, * y: 200, * // ... other properties * } * ``` * * @public */ export declare function createShapeId(id?: string): TLShapeId; /** * Creates properly formatted migration IDs for shape properties. * * Generates standardized migration IDs following the convention: * `com.tldraw.shape.{shapeType}/{version}` * * @param shapeType - The type of shape these migrations apply to * @param ids - Record mapping migration names to version numbers * @returns Record with the same keys but formatted migration ID values * * @example * ```ts * const myShapeVersions = createShapePropsMigrationIds('custom', { * AddColor: 1, * AddSize: 2, * RefactorProps: 3 * }) * // Result: { * // AddColor: 'com.tldraw.shape.custom/1', * // AddSize: 'com.tldraw.shape.custom/2', * // RefactorProps: 'com.tldraw.shape.custom/3' * // } * ``` * * @public */ export declare function createShapePropsMigrationIds<const S extends string, const T extends Record<string, number>>(shapeType: S, ids: T): { [k in keyof T]: `com.tldraw.shape.${S}/${T[k]}`; }; /** * Creates a migration sequence for shape properties. * * This is a pass-through function that maintains the same structure as the input. * It's used for consistency and to provide a clear API for defining shape property migrations. * * @param migrations - The migration sequence to create * @returns The same migration sequence (pass-through) * * @example * ```ts * const myShapeMigrations = createShapePropsMigrationSequence({ * sequence: [ * { * id: 'com.myapp.shape.custom/1.0.0', * up: (props) => ({ ...props, newProperty: 'default' }), * down: ({ newProperty, ...props }) => props * } * ] * }) * ``` * * @public */ export declare function createShapePropsMigrationSequence(migrations: TLPropsMigrations): TLPropsMigrations; /** * Creates a validator for a specific shape type. * * This function generates a complete validator that can validate shape records * of the specified type, including both the base shape properties and any * custom properties and metadata specific to that shape type. * * @param type - The string literal type for this shape (e.g., 'geo', 'arrow') * @param props - Optional validator configuration for shape-specific properties * @param meta - Optional validator configuration for shape-specific metadata * @returns A validator that can validate complete shape records of the specified type * * @example * ```ts * // Create a validator for a custom shape type * const customShapeValidator = createShapeValidator('custom', { * width: T.number, * height: T.number, * color: T.string * }) * * // Use the validator to validate shape data * const shapeData = { * id: 'shape:abc123', * typeName: 'shape', * type: 'custom', * x: 100, * y: 200, * // ... other base properties * props: { * width: 150, * height: 100, * color: 'red' * } * } * * const validatedShape = customShapeValidator.validate(shapeData) * ``` * * @public */ export declare function createShapeValidator<Type extends string, Props extends JsonObject, Meta extends JsonObject>(type: Type, props?: { [K in keyof Props]: T.Validatable<Props[K]>; }, meta?: { [K in keyof Meta]: T.Validatable<Meta[K]>; }): T.ObjectValidator<Expand< { [P in "id" | "index" | "isLocked" | "meta" | "opacity" | "parentId" | "rotation" | "typeName" | "x" | "y" | (undefined extends Props ? never : "props") | (undefined extends Type ? never : "type")]: TLBaseShape<Type, Props>[P]; } & { [P in (undefined extends Props ? "props" : never) | (undefined extends Type ? "type" : never)]?: TLBaseShape<Type, Props>[P] | undefined; }>>; /** * Creates a complete TLSchema for use with tldraw stores. This schema defines the structure, * validation, and migration sequences for all record types in a tldraw application. * * The schema includes all core record types (pages, cameras, instances, etc.) plus the * shape, binding, asset, and custom record types you specify. Style properties are * automatically collected from all shapes to ensure consistency across the application. * * @param options - Configuration options for the schema * - shapes - Shape schema configurations. Defaults to defaultShapeSchemas if not provided * - bindings - Binding schema configurations. Defaults to defaultBindingSchemas if not provided * - assets - Asset schema configurations. Defaults to defaultAssetSchemas if not provided * - user - Custom user record configuration with meta validators and migrations * - records - Custom record type configurations. These are additional record types beyond * the built-in shapes, bindings, assets, etc. * - migrations - Additional migration sequences to include in the schema * @returns A complete TLSchema ready for use with Store creation * * @public * @example * ```ts * import { * createTLSchema, * defaultShapeSchemas, * defaultBindingSchemas, * defaultAssetSchemas, * } from '@tldraw/tlschema' * import { Store } from '@tldraw/store' * * // Create schema with all default shapes, bindings, and assets * const schema = createTLSchema() * * // Create schema with custom shapes added * const customSchema = createTLSchema({ * shapes: { * ...defaultShapeSchemas, * myCustomShape: { * props: myCustomShapeProps, * migrations: myCustomShapeMigrations, * }, * }, * bindings: defaultBindingSchemas, * assets: defaultAssetSchemas, * }) * * // Create schema with custom user metadata * const schemaWithCustomUser = createTLSchema({ * user: { * meta: { * isAdmin: T.boolean, * department: T.string, * }, * }, * }) * * // Create schema with custom record types * const schemaWithCustomRecords = createTLSchema({ * records: { * comment: { * scope: 'document', * validator: T.object({ * id: T.string, * typeName: T.literal('comment'), * text: T.string, * shapeId: T.string, * }), * }, * }, * }) * * // Use the schema with a store * const store = new Store({ * schema: customSchema, * props: { * defaultName: 'My Drawing', * }, * }) * ``` */ export declare function createTLSchema({ shapes, bindings, assets, user, records, migrations }?: { assets?: Record<string, SchemaPropsInfo>; bindings?: Record<string, SchemaPropsInfo>; migrations?: readonly MigrationSequence[]; records?: Record<string, CustomRecordInfo>; shapes?: Record<string, SchemaPropsInfo>; user?: UserSchemaInfo; }): TLSchema; /** @public */ export declare function createUserId(id: string): TLUserId; /** * Creates a user record type with optional custom meta validation. * * When `meta` validators are provided, the user record's `meta` field will * validate those specific fields (when present) while still allowing * arbitrary additional JSON properties. Custom meta fields are treated as * optional so that user records created without them remain valid. * * @param config - Optional configuration for custom meta validators * @returns A configured user record type * * @example * ```ts * import { createUserRecordType } from '@tldraw/tlschema' * import { T } from '@tldraw/validate' * * const CustomUserRecordType = createUserRecordType({ * meta: { * isAdmin: T.boolean, * department: T.string, * }, * }) * ``` * * @public */ export declare function createUserRecordType(config?: { meta?: Record<string, T.Validatable<any>>; }): RecordType<TLUser, never>; /** * Configuration for a custom record type in the schema. * * Custom record types allow you to add entirely new data types to the tldraw store * that don't fit into the existing shape, binding, or asset categories. This is useful * for storing domain-specific data like comments, annotations, or application state * that needs to participate in persistence and synchronization. * * @example * ```ts * const commentRecordConfig: CustomRecordInfo = { * scope: 'document', * validator: T.object({ * id: T.string, * typeName: T.literal('comment'), * text: T.string, * shapeId: T.string, * authorId: T.string, * createdAt: T.number, * }), * migrations: createRecordMigrationSequence({ * sequenceId: 'com.myapp.comment', * recordType: 'comment', * sequence: [], * }), * } * ``` * * @public */ export declare interface CustomRecordInfo { /** * The scope determines how records of this type are persisted and synchronized: * - **document**: Persisted and synced across all clients * - **session**: Local to current session, not synced * - **presence**: Ephemeral presence data, may be synced but not persisted */ scope: RecordScope; /** * Validator for the complete record structure. * * Should validate the entire record including `id` and `typeName` fields. * Use validators like T.object, T.string, etc. */ validator: T.Validatable<any>; /** * Optional migration sequence for handling schema evolution over time. * * Can be a full MigrationSequence or a simplified TLPropsMigrations format. * If not provided, an empty migration sequence will be created automatically. */ migrations?: MigrationSequence | TLPropsMigrations; /** * Optional factory function that returns default property values for new records. * * Called when creating new records to provide initial values for any properties * not explicitly provided during creation. */ createDefaultProperties?: () => Record<string, unknown>; } /** * Default asset schema configurations for all built-in tldraw asset types. * * @public * @example * ```ts * import { createTLSchema, defaultAssetSchemas } from '@tldraw/tlschema' * * const schema = createTLSchema({ * assets: defaultAssetSchemas, * }) * ``` */ export declare const defaultAssetSchemas: { bookmark: { migrations: MigrationSequence; props: { description: T.Validator<string>; favicon: T.Validator<string>; image: T.Validator<string>; src: T.Validator<null | string>; title: T.Validator<string>; }; }; image: { migrations: MigrationSequence; props: { fileSize: T.Validator<number | undefined>; h: T.Validator<number>; isAnimated: T.Validator<boolean>; mimeType: T.Validator<null | string>; name: T.Validator<string>; pixelRatio: T.Validator<number | undefined>; src: T.Validator<null | string>; w: T.Validator<number>; }; }; video: { migrations: MigrationSequence; props: { fileSize: T.Validator<number | undefined>; h: T.Validator<number>; isAnimated: T.Validator<boolean>; mimeType: T.Validator<null | string>; name: T.Validator<string>; src: T.Validator<null | string>; w: T.Validator<number>; }; }; }; /** * Default binding schema configurations for all built-in tldraw binding types. * Bindings represent relationships between shapes, such as arrows connected to shapes. * * Currently includes: * - arrow: Bindings that connect arrow shapes to other shapes at specific anchor points * * @public * @example * ```ts * import { createTLSchema, defaultBindingSchemas } from '@tldraw/tlschema' * * // Use default bindings * const schema = createTLSchema({ * bindings: defaultBindingSchemas, * }) * * // Add custom binding alongside defaults * const customSchema = createTLSchema({ * bindings: { * ...defaultBindingSchemas, * myCustomBinding: { * props: myCustomBindingProps, * migrations: myCustomBindingMigrations, * }, * }, * }) * ``` */ export declare const defaultBindingSchemas: { arrow: { migrations: TLPropsMigrations; props: RecordProps<TLArrowBinding>; }; }; /** * @public */ export declare const DefaultColorStyle: EnumStyleProp<TLDefaultColorStyle>; /** * Default dash style property used by tldraw shapes for line styling. * Controls how shape outlines and lines are rendered with different dash patterns. * * Available values: * - `draw` - Hand-drawn, sketchy line style * - `solid` - Continuous solid line * - `dashed` - Evenly spaced dashes * - `dotted` - Evenly spaced dots * * @example * ```ts * import { DefaultDashStyle } from '@tldraw/tlschema' * * // Use in shape props definition * interface MyShapeProps { * dash: typeof DefaultDashStyle * // other props... * } * * // Create a shape with dashed outline * const shape = { * // ... other properties * props: { * dash: 'dashed' as const, * // ... other props * } * } * ``` * * @public */ export declare const DefaultDashStyle: EnumStyleProp<"dashed" | "dotted" | "draw" | "none" | "solid">; /** * Default fill style property used by tldraw shapes for interior styling. * Controls how the inside of shapes are filled or left empty. * * Available values: * - `none` - No fill, shape interior is transparent * - `semi` - Semi-transparent fill using the shape's color * - `solid` - Solid fill using the shape's color * - `pattern` - Crosshatch pattern fill using the shape's color * - `fill` - Alternative solid fill variant * * @example * ```ts * import { DefaultFillStyle } from '@tldraw/tlschema' * * // Use in shape props definition * interface MyShapeProps { * fill: typeof DefaultFillStyle * // other props... * } * * // Create a shape with solid fill * const shape = { * // ... other properties * props: { * fill: 'solid' as const, * // ... other props * } * } * ``` * * @public */ export declare const DefaultFillStyle: EnumStyleProp<"fill" | "lined-fill" | "none" | "pattern" | "semi" | "solid">; /** * Mapping of font style names to their corresponding CSS font-family declarations. * These are the actual CSS font families used when rendering text with each font style. * * @example * ```ts * import { DefaultFontFamilies, TLDefaultFontStyle } from '@tldraw/tlschema' * * // Get CSS font family for a font style * const fontStyle: TLDefaultFontStyle = 'mono' * const cssFamily = DefaultFontFamilies[fontStyle] // "'tldraw_mono', monospace" * * // Apply to DOM element * element.style.fontFamily = DefaultFontFamilies.sans * ``` * * @public */ export declare const DefaultFontFamilies: { draw: string; mono: string; sans: string; serif: string; }; /** * Default font style property used by tldraw shapes for text styling. * Controls which typeface is used for text content within shapes. * * Available values: * - `draw` - Hand-drawn, sketchy font style * - `sans` - Clean sans-serif font * - `serif` - Traditional serif font * - `mono` - Monospace font for code-like text * * @example * ```ts * import { DefaultFontStyle } from '@tldraw/tlschema' * * // Use in shape props definition * interface MyTextShapeProps { * font: typeof DefaultFontStyle * // other props... * } * * // Create a text shape with monospace font * const textShape = { * // ... other properties * props: { * font: 'mono' as const, * // ... other props * } * } * ``` * * @public */ export declare const DefaultFontStyle: EnumStyleProp<"draw" | "mono" | "sans" | "serif">; /** * Default horizontal alignment style property used by tldraw shapes for text positioning. * Controls how text content is horizontally aligned within shape boundaries. * * Available values: * - `start` - Align text to the start (left in LTR, right in RTL) * - `middle` - Center text horizontally * - `end` - Align text to the end (right in LTR, left in RTL) * - `start-legacy` - Legacy start alignment (deprecated) * - `end-legacy` - Legacy end alignment (deprecated) * - `middle-legacy` - Legacy middle alignment (deprecated) * * @example * ```ts * import { DefaultHorizontalAlignStyle } from '@tldraw/tlschema' * * // Use in shape props definition * interface MyTextShapeProps { * align: typeof DefaultHorizontalAlignStyle * // other props... * } * * // Create a shape with center-aligned text * const textShape = { * // ... other properties * props: { * align: 'middle' as const, * // ... other props * } * } * ``` * * @public */ export declare const DefaultHorizontalAlignStyle: EnumStyleProp<"end-legacy" | "end" | "middle-legacy" | "middle" | "start-legacy" | "start">; /** * Default shape schema configurations for all built-in tldraw shape types. * Each shape type includes its validation props and migration sequences. * * This object contains schema information for: * - arrow: Directional lines that can bind to other shapes * - bookmark: Website bookmark cards with preview information * - draw: Freehand drawing paths created with drawing tools * - embed: Embedded content from external services (YouTube, Figma, etc.) * - frame: Container shapes for organizing content * - geo: Geometric shapes (rectangles, ellipses, triangles, etc.) * - group: Logical groupings of multiple shapes * - highlight: Highlighting strokes from the highlighter tool * - image: Raster image shapes referencing image assets * - line: Multi-point lines and splines * - note: Sticky note shapes with text content * - text: Rich text shapes with formatting support * - video: Video shapes referencing video assets * * @public * @example * ```ts * import { createTLSchema, defaultShapeSchemas } from '@tldraw/tlschema' * * // Use all default shapes * const schema = createTLSchema({ * shapes: defaultShapeSchemas, * }) * * // Use only specific default shapes * const minimalSchema = createTLSchema({ * shapes: { * geo: defaultShapeSchemas.geo, * text: defaultShapeSchemas.text, * }, * }) * ``` */ export declare const defaultShapeSchemas: { arrow: { migrations: MigrationSequence; props: RecordProps<TLArrowShape>; }; bookmark: { migrations: TLPropsMigrations; props: RecordProps<TLBookmarkShape>; }; draw: { migrations: TLPropsMigrations; props: RecordProps<TLDrawShape>; }; embed: { migrations: TLPropsMigrations; props: RecordProps<TLEmbedShape>; }; frame: { migrations: TLPropsMigrations; props: RecordProps<TLFrameShape>; }; geo: { migrations: TLPropsMigrations; props: RecordProps<TLGeoShape>; }; group: { migrations: TLPropsMigrations; props: RecordProps<TLGroupShape>; }; highlight: { migrations: TLPropsMigrations; props: RecordProps<TLHighlightShape>; }; image: { migrations: TLPropsMigrations; props: RecordProps<TLImageShape>; }; line: { migrations: TLPropsMigrations; props: RecordProps<TLLineShape>; }; note: { migrations: TLPropsMigrations; props: RecordProps<TLNoteShape>; }; text: { migrations: TLPropsMigrations; props: RecordProps<TLTextShape>; }; video: { migrations: TLPropsMigrations; props: RecordProps<TLVideoShape>; }; }; /** * Default size style property used by tldraw shapes for scaling visual elements. * Controls the relative size of shape elements like stroke width, text size, and other proportional features. * * Available values: * - `s` - Small size * - `m` - Medium size (default) * - `l` - Large size * - `xl` - Extra large size * * @example * ```ts * import { DefaultSizeStyle } from '@tldraw/tlschema' * * // Use in shape props definition * interface MyShapeProps { * size: typeof DefaultSizeStyle * // other props... * } * * // Create a shape with large size * const shape = { * // ... other properties * props: { * size: 'l' as const, * // ... other props * } * } * ``` * * @public */ export declare const DefaultSizeStyle: EnumStyleProp<"l" | "m" | "s" | "xl">; /** * Default text alignment style property used by tldraw text shapes. * Controls how text content is aligned within text-based shapes like text boxes and notes. * * Available values: * - `start` - Align text to the start (left in LTR, right in RTL) * - `middle` - Center text horizontally * - `end` - Align text to the end (right in LTR, left in RTL) * * @example * ```ts * import { DefaultTextAlignStyle } from '@tldraw/tlschema' * * // Use in text shape props definition * interface MyTextShapeProps { * textAlign: typeof DefaultTextAlignStyle * // other props... * } * * // Create a text shape with center alignment * const textShape = { * // ... other properties * props: { * textAlign: 'middle' as const, * // ... other props * } * } * ``` * * @public */ export declare const DefaultTextAlignStyle: EnumStyleProp<"end" | "middle" | "start">; /** * Default vertical alignment style property used by tldraw shapes for text positioning. * Controls how text content is vertically aligned within shape boundaries. * * Available values: * - `start` - Align text to the top * - `middl