UNPKG

@tldraw/tlschema

Version:

tldraw infinite canvas SDK (schema).

127 lines (118 loc) 3.73 kB
import { T } from '@tldraw/validate' /** * A `StyleProp` is a property of a shape that follows some special rules. * * 1. The same value can be set on lots of shapes at the same time. * * 2. The last used value is automatically saved and applied to new shapes. * * For example, {@link DefaultColorStyle} is a style prop used by tldraw's default shapes to set * their color. If you try selecting several shapes on tldraw.com and changing their color, you'll * see that the color is applied to all of them. Then, if you draw a new shape, it'll have the same * color as the one you just set. * * You can use styles in your own shapes by either defining your own (see {@link StyleProp.define} * and {@link StyleProp.defineEnum}) or using tldraw's default ones, like {@link DefaultColorStyle}. * When you define a shape, pass a `props` object describing all of your shape's properties, using * `StyleProp`s for the ones you want to be styles. See the * {@link https://github.com/tldraw/tldraw/tree/main/apps/examples | custom styles example} * for more. * * @public */ export class StyleProp<Type> implements T.Validatable<Type> { /** * Define a new {@link StyleProp}. * * @param uniqueId - Each StyleProp must have a unique ID. We recommend you prefix this with * your app/library name. * @param options - * - `defaultValue`: The default value for this style prop. * * - `type`: Optionally, describe what type of data you expect for this style prop. * * @example * ```ts * import {T} from '@tldraw/validate' * import {StyleProp} from '@tldraw/tlschema' * * const MyLineWidthProp = StyleProp.define('myApp:lineWidth', { * defaultValue: 1, * type: T.number, * }) * ``` * @public */ static define<Type>( uniqueId: string, options: { defaultValue: Type; type?: T.Validatable<Type> } ) { const { defaultValue, type = T.any } = options return new StyleProp<Type>(uniqueId, defaultValue, type) } /** * Define a new {@link StyleProp} as a list of possible values. * * @param uniqueId - Each StyleProp must have a unique ID. We recommend you prefix this with * your app/library name. * @param options - * - `defaultValue`: The default value for this style prop. * * - `values`: An array of possible values of this style prop. * * @example * ```ts * import {StyleProp} from '@tldraw/tlschema' * * const MySizeProp = StyleProp.defineEnum('myApp:size', { * defaultValue: 'medium', * values: ['small', 'medium', 'large'], * }) * ``` */ static defineEnum<const Values extends readonly unknown[]>( uniqueId: string, options: { defaultValue: Values[number]; values: Values } ) { const { defaultValue, values } = options return new EnumStyleProp<Values[number]>(uniqueId, defaultValue, values) } /** @internal */ protected constructor( readonly id: string, public defaultValue: Type, readonly type: T.Validatable<Type> ) {} setDefaultValue(value: Type) { this.defaultValue = value } validate(value: unknown) { return this.type.validate(value) } validateUsingKnownGoodVersion(prevValue: Type, newValue: unknown) { if (this.type.validateUsingKnownGoodVersion) { return this.type.validateUsingKnownGoodVersion(prevValue, newValue) } else { return this.validate(newValue) } } } /** * See {@link StyleProp} & {@link StyleProp.defineEnum} * * @public */ export class EnumStyleProp<T> extends StyleProp<T> { /** @internal */ constructor( id: string, defaultValue: T, readonly values: readonly T[] ) { super(id, defaultValue, T.literalEnum(...values)) } } /** * @public */ export type StylePropValue<T extends StyleProp<any>> = T extends StyleProp<infer U> ? U : never