@tldraw/tlschema 4.6.0-next.5a871ec02ff3 → 4.6.0-next.d15997ff5a4b
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/createPresenceStateDerivation.js.map +2 -2
- package/dist-cjs/createTLSchema.js +1 -1
- package/dist-cjs/createTLSchema.js.map +2 -2
- package/dist-cjs/index.js +1 -1
- package/dist-cjs/misc/TLScribble.js +1 -1
- package/dist-cjs/misc/TLScribble.js.map +2 -2
- package/dist-cjs/records/TLCustomRecord.js.map +1 -1
- package/dist-cjs/records/TLPageState.js.map +2 -2
- package/dist-cjs/recordsWithProps.js.map +1 -1
- package/dist-cjs/shapes/TLArrowShape.js +1 -1
- package/dist-cjs/shapes/TLArrowShape.js.map +2 -2
- package/dist-cjs/shapes/TLBaseShape.js +1 -1
- package/dist-cjs/shapes/TLBaseShape.js.map +2 -2
- package/dist-esm/createPresenceStateDerivation.mjs.map +2 -2
- package/dist-esm/createTLSchema.mjs +1 -1
- package/dist-esm/createTLSchema.mjs.map +2 -2
- package/dist-esm/index.mjs +1 -1
- package/dist-esm/misc/TLScribble.mjs +1 -1
- package/dist-esm/misc/TLScribble.mjs.map +2 -2
- package/dist-esm/records/TLCustomRecord.mjs.map +1 -1
- package/dist-esm/records/TLPageState.mjs.map +2 -2
- package/dist-esm/recordsWithProps.mjs.map +1 -1
- package/dist-esm/shapes/TLArrowShape.mjs +1 -1
- package/dist-esm/shapes/TLArrowShape.mjs.map +2 -2
- package/dist-esm/shapes/TLBaseShape.mjs +1 -1
- package/dist-esm/shapes/TLBaseShape.mjs.map +2 -2
- package/package.json +7 -7
- package/src/createPresenceStateDerivation.ts +1 -1
- package/src/createTLSchema.ts +1 -1
- package/src/misc/TLScribble.ts +1 -1
- package/src/records/TLCustomRecord.ts +1 -1
- package/src/records/TLPageState.ts +4 -2
- package/src/recordsWithProps.ts +1 -1
- package/src/shapes/TLArrowShape.ts +1 -1
- package/src/shapes/TLBaseShape.ts +1 -1
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../src/createPresenceStateDerivation.ts"],
|
|
4
|
-
"sourcesContent": ["import { Signal, computed } from '@tldraw/state'\nimport {
|
|
5
|
-
"mappings": ";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,mBAAiC;
|
|
4
|
+
"sourcesContent": ["import { Signal, computed } from '@tldraw/state'\nimport { CameraRecordType } from './records/TLCamera'\nimport { TLINSTANCE_ID } from './records/TLInstance'\nimport { InstancePageStateRecordType } from './records/TLPageState'\nimport { TLPOINTER_ID } from './records/TLPointer'\nimport { InstancePresenceRecordType, TLInstancePresence } from './records/TLPresence'\nimport { TLStore } from './TLStore'\n\n/**\n * The information about a user which is used for multiplayer features.\n * @public\n */\nexport interface TLPresenceUserInfo {\n\t/**\n\t * id - A unique identifier for the user. This should be the same across all devices and sessions.\n\t */\n\tid: string\n\t/**\n\t * The user's display name.\n\t */\n\tname?: string | null\n\t/**\n\t * The user's color. If not given, a random color will be assigned.\n\t */\n\tcolor?: string | null\n}\n\n/**\n * Creates a derivation that represents the current presence state of the current user.\n *\n * This function returns a derivation factory that, when given a store, creates a computed signal\n * containing the user's current presence state. The presence state includes information like cursor\n * position, selected shapes, camera position, and user metadata that gets synchronized in\n * multiplayer scenarios.\n *\n * @param $user - A reactive signal containing the user information\n * @param instanceId - Optional custom instance ID. If not provided, one will be generated based on the store ID\n * @returns A function that takes a store and returns a computed signal of the user's presence state\n *\n * @example\n * ```ts\n * import { createPresenceStateDerivation } from '@tldraw/tlschema'\n * import { atom } from '@tldraw/state'\n *\n * const userSignal = atom('user', { id: 'user-123', name: 'Alice', color: '#ff0000' })\n * const presenceDerivation = createPresenceStateDerivation(userSignal)\n *\n * // Use with a store to get reactive presence state\n * const presenceState = presenceDerivation(store)\n * console.log(presenceState.get()) // Current user presence or null\n * ```\n *\n * @public\n */\nexport function createPresenceStateDerivation(\n\t$user: Signal<TLPresenceUserInfo>,\n\tinstanceId?: TLInstancePresence['id']\n) {\n\treturn (store: TLStore): Signal<TLInstancePresence | null> => {\n\t\treturn computed('instancePresence', () => {\n\t\t\tconst user = $user.get()\n\t\t\tif (!user) return null\n\n\t\t\tconst state = getDefaultUserPresence(store, user)\n\t\t\tif (!state) return null\n\n\t\t\treturn InstancePresenceRecordType.create({\n\t\t\t\t...state,\n\t\t\t\tid: instanceId ?? InstancePresenceRecordType.createId(store.id),\n\t\t\t})\n\t\t})\n\t}\n}\n\n/**\n * The shape of data used to create a presence record.\n *\n * This type represents all the properties needed to construct a TLInstancePresence record.\n * It includes user information, cursor state, camera position, selected shapes, and other\n * presence-related data that gets synchronized across multiplayer clients.\n *\n * @public\n */\nexport type TLPresenceStateInfo = Parameters<(typeof InstancePresenceRecordType)['create']>[0]\n\n/**\n * Creates default presence state information for a user based on the current store state.\n *\n * This function extracts the current state from various store records (instance, page state,\n * camera, pointer) and combines them with user information to create a complete presence\n * state object. This is commonly used as a starting point for custom presence implementations.\n *\n * @param store - The tldraw store containing the current editor state\n * @param user - The user information to include in the presence state\n * @returns The default presence state info, or null if required store records are missing\n *\n * @example\n * ```ts\n * import { getDefaultUserPresence } from '@tldraw/tlschema'\n *\n * const user = { id: 'user-123', name: 'Alice', color: '#ff0000' }\n * const presenceInfo = getDefaultUserPresence(store, user)\n *\n * if (presenceInfo) {\n * console.log('Current cursor:', presenceInfo.cursor)\n * console.log('Selected shapes:', presenceInfo.selectedShapeIds)\n * console.log('Camera position:', presenceInfo.camera)\n * }\n * ```\n *\n * @example\n * ```ts\n * // Common pattern: customize default presence\n * const customPresence = {\n * ...getDefaultUserPresence(store, user),\n * // Remove camera for privacy\n * camera: undefined,\n * // Add custom metadata\n * customField: 'my-data'\n * }\n * ```\n *\n * @public\n */\nexport function getDefaultUserPresence(store: TLStore, user: TLPresenceUserInfo) {\n\tconst instance = store.get(TLINSTANCE_ID)\n\tconst pageState = store.get(InstancePageStateRecordType.createId(instance?.currentPageId))\n\tconst camera = store.get(CameraRecordType.createId(instance?.currentPageId))\n\tconst pointer = store.get(TLPOINTER_ID)\n\tif (!pageState || !instance || !camera || !pointer) {\n\t\treturn null\n\t}\n\n\treturn {\n\t\tselectedShapeIds: pageState.selectedShapeIds,\n\t\tbrush: instance.brush,\n\t\tscribbles: instance.scribbles,\n\t\tuserId: user.id,\n\t\tuserName: user.name ?? '',\n\t\tfollowingUserId: instance.followingUserId,\n\t\tcamera: {\n\t\t\tx: camera.x,\n\t\t\ty: camera.y,\n\t\t\tz: camera.z,\n\t\t},\n\t\tcolor: user.color ?? '#FF0000',\n\t\tcurrentPageId: instance.currentPageId,\n\t\tcursor: {\n\t\t\tx: pointer.x,\n\t\t\ty: pointer.y,\n\t\t\trotation: instance.cursor.rotation,\n\t\t\ttype: instance.cursor.type,\n\t\t},\n\t\tlastActivityTimestamp: pointer.lastActivityTimestamp,\n\t\tscreenBounds: instance.screenBounds,\n\t\tchatMessage: instance.chatMessage,\n\t\tmeta: {},\n\t} satisfies TLPresenceStateInfo\n}\n"],
|
|
5
|
+
"mappings": ";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,mBAAiC;AACjC,sBAAiC;AACjC,wBAA8B;AAC9B,yBAA4C;AAC5C,uBAA6B;AAC7B,wBAA+D;AAiDxD,SAAS,8BACf,OACA,YACC;AACD,SAAO,CAAC,UAAsD;AAC7D,eAAO,uBAAS,oBAAoB,MAAM;AACzC,YAAM,OAAO,MAAM,IAAI;AACvB,UAAI,CAAC,KAAM,QAAO;AAElB,YAAM,QAAQ,uBAAuB,OAAO,IAAI;AAChD,UAAI,CAAC,MAAO,QAAO;AAEnB,aAAO,6CAA2B,OAAO;AAAA,QACxC,GAAG;AAAA,QACH,IAAI,cAAc,6CAA2B,SAAS,MAAM,EAAE;AAAA,MAC/D,CAAC;AAAA,IACF,CAAC;AAAA,EACF;AACD;AAoDO,SAAS,uBAAuB,OAAgB,MAA0B;AAChF,QAAM,WAAW,MAAM,IAAI,+BAAa;AACxC,QAAM,YAAY,MAAM,IAAI,+CAA4B,SAAS,UAAU,aAAa,CAAC;AACzF,QAAM,SAAS,MAAM,IAAI,iCAAiB,SAAS,UAAU,aAAa,CAAC;AAC3E,QAAM,UAAU,MAAM,IAAI,6BAAY;AACtC,MAAI,CAAC,aAAa,CAAC,YAAY,CAAC,UAAU,CAAC,SAAS;AACnD,WAAO;AAAA,EACR;AAEA,SAAO;AAAA,IACN,kBAAkB,UAAU;AAAA,IAC5B,OAAO,SAAS;AAAA,IAChB,WAAW,SAAS;AAAA,IACpB,QAAQ,KAAK;AAAA,IACb,UAAU,KAAK,QAAQ;AAAA,IACvB,iBAAiB,SAAS;AAAA,IAC1B,QAAQ;AAAA,MACP,GAAG,OAAO;AAAA,MACV,GAAG,OAAO;AAAA,MACV,GAAG,OAAO;AAAA,IACX;AAAA,IACA,OAAO,KAAK,SAAS;AAAA,IACrB,eAAe,SAAS;AAAA,IACxB,QAAQ;AAAA,MACP,GAAG,QAAQ;AAAA,MACX,GAAG,QAAQ;AAAA,MACX,UAAU,SAAS,OAAO;AAAA,MAC1B,MAAM,SAAS,OAAO;AAAA,IACvB;AAAA,IACA,uBAAuB,QAAQ;AAAA,IAC/B,cAAc,SAAS;AAAA,IACvB,aAAa,SAAS;AAAA,IACtB,MAAM,CAAC;AAAA,EACR;AACD;",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -25,7 +25,6 @@ __export(createTLSchema_exports, {
|
|
|
25
25
|
module.exports = __toCommonJS(createTLSchema_exports);
|
|
26
26
|
var import_store = require("@tldraw/store");
|
|
27
27
|
var import_utils = require("@tldraw/utils");
|
|
28
|
-
var import_TLStore = require("./TLStore");
|
|
29
28
|
var import_TLBookmarkAsset = require("./assets/TLBookmarkAsset");
|
|
30
29
|
var import_TLImageAsset = require("./assets/TLImageAsset");
|
|
31
30
|
var import_TLVideoAsset = require("./assets/TLVideoAsset");
|
|
@@ -56,6 +55,7 @@ var import_TLNoteShape = require("./shapes/TLNoteShape");
|
|
|
56
55
|
var import_TLTextShape = require("./shapes/TLTextShape");
|
|
57
56
|
var import_TLVideoShape = require("./shapes/TLVideoShape");
|
|
58
57
|
var import_store_migrations = require("./store-migrations");
|
|
58
|
+
var import_TLStore = require("./TLStore");
|
|
59
59
|
const defaultShapeSchemas = {
|
|
60
60
|
arrow: { migrations: import_TLArrowShape.arrowShapeMigrations, props: import_TLArrowShape.arrowShapeProps },
|
|
61
61
|
bookmark: { migrations: import_TLBookmarkShape.bookmarkShapeMigrations, props: import_TLBookmarkShape.bookmarkShapeProps },
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../src/createTLSchema.ts"],
|
|
4
|
-
"sourcesContent": ["import { LegacyMigrations, MigrationSequence, StoreSchema, StoreValidator } from '@tldraw/store'\nimport { objectMapValues } from '@tldraw/utils'\nimport { TLStoreProps, createIntegrityChecker, onValidationFailure } from './TLStore'\nimport { bookmarkAssetMigrations } from './assets/TLBookmarkAsset'\nimport { imageAssetMigrations } from './assets/TLImageAsset'\nimport { videoAssetMigrations } from './assets/TLVideoAsset'\nimport { arrowBindingMigrations, arrowBindingProps } from './bindings/TLArrowBinding'\nimport { AssetRecordType, assetMigrations } from './records/TLAsset'\nimport { TLBinding, TLDefaultBinding, createBindingRecordType } from './records/TLBinding'\nimport { CameraRecordType, cameraMigrations } from './records/TLCamera'\nimport {\n\tCustomRecordInfo,\n\tcreateCustomRecordType,\n\tprocessCustomRecordMigrations,\n} from './records/TLCustomRecord'\nimport { DocumentRecordType, documentMigrations } from './records/TLDocument'\nimport { createInstanceRecordType, instanceMigrations } from './records/TLInstance'\nimport { PageRecordType, pageMigrations } from './records/TLPage'\nimport { InstancePageStateRecordType, instancePageStateMigrations } from './records/TLPageState'\nimport { PointerRecordType, pointerMigrations } from './records/TLPointer'\nimport { InstancePresenceRecordType, instancePresenceMigrations } from './records/TLPresence'\nimport { TLRecord } from './records/TLRecord'\nimport {\n\tTLDefaultShape,\n\tTLShape,\n\tcreateShapeRecordType,\n\tgetShapePropKeysByStyle,\n\trootShapeMigrations,\n} from './records/TLShape'\nimport { RecordProps, TLPropsMigrations, processPropsMigrations } from './recordsWithProps'\nimport { arrowShapeMigrations, arrowShapeProps } from './shapes/TLArrowShape'\nimport { TLBaseShape } from './shapes/TLBaseShape'\nimport { bookmarkShapeMigrations, bookmarkShapeProps } from './shapes/TLBookmarkShape'\nimport { drawShapeMigrations, drawShapeProps } from './shapes/TLDrawShape'\nimport { embedShapeMigrations, embedShapeProps } from './shapes/TLEmbedShape'\nimport { frameShapeMigrations, frameShapeProps } from './shapes/TLFrameShape'\nimport { geoShapeMigrations, geoShapeProps } from './shapes/TLGeoShape'\nimport { groupShapeMigrations, groupShapeProps } from './shapes/TLGroupShape'\nimport { highlightShapeMigrations, highlightShapeProps } from './shapes/TLHighlightShape'\nimport { imageShapeMigrations, imageShapeProps } from './shapes/TLImageShape'\nimport { lineShapeMigrations, lineShapeProps } from './shapes/TLLineShape'\nimport { noteShapeMigrations, noteShapeProps } from './shapes/TLNoteShape'\nimport { textShapeMigrations, textShapeProps } from './shapes/TLTextShape'\nimport { videoShapeMigrations, videoShapeProps } from './shapes/TLVideoShape'\nimport { storeMigrations } from './store-migrations'\nimport { StyleProp } from './styles/StyleProp'\n\n/**\n * Configuration information for a schema type (shape or binding), including its properties,\n * metadata, and migration sequences for data evolution over time.\n *\n * @public\n * @example\n * ```ts\n * import { arrowShapeMigrations, arrowShapeProps } from './shapes/TLArrowShape'\n *\n * const myShapeSchema: SchemaPropsInfo = {\n * migrations: arrowShapeMigrations,\n * props: arrowShapeProps,\n * meta: {\n * customField: T.string,\n * },\n * }\n * ```\n */\nexport interface SchemaPropsInfo {\n\t/**\n\t * Migration sequences for handling data evolution over time. Can be legacy migrations,\n\t * props-specific migrations, or general migration sequences.\n\t */\n\tmigrations?: LegacyMigrations | TLPropsMigrations | MigrationSequence\n\n\t/**\n\t * Validation schema for the shape or binding properties. Maps property names to their validators.\n\t */\n\tprops?: Record<string, StoreValidator<any>>\n\n\t/**\n\t * Validation schema for metadata fields. Maps metadata field names to their validators.\n\t */\n\tmeta?: Record<string, StoreValidator<any>>\n}\n\n/**\n * The complete schema definition for a tldraw store, encompassing all record types,\n * validation rules, and migration sequences. This schema defines the structure of\n * the persistent data model used by tldraw.\n *\n * @public\n * @example\n * ```ts\n * import { createTLSchema, defaultShapeSchemas } from '@tldraw/tlschema'\n * import { Store } from '@tldraw/store'\n *\n * const schema: TLSchema = createTLSchema({\n * shapes: defaultShapeSchemas,\n * })\n *\n * const store = new Store({ schema })\n * ```\n */\nexport type TLSchema = StoreSchema<TLRecord, TLStoreProps>\n\n/**\n * Default shape schema configurations for all built-in tldraw shape types.\n * Each shape type includes its validation props and migration sequences.\n *\n * This object contains schema information for:\n * - arrow: Directional lines that can bind to other shapes\n * - bookmark: Website bookmark cards with preview information\n * - draw: Freehand drawing paths created with drawing tools\n * - embed: Embedded content from external services (YouTube, Figma, etc.)\n * - frame: Container shapes for organizing content\n * - geo: Geometric shapes (rectangles, ellipses, triangles, etc.)\n * - group: Logical groupings of multiple shapes\n * - highlight: Highlighting strokes from the highlighter tool\n * - image: Raster image shapes referencing image assets\n * - line: Multi-point lines and splines\n * - note: Sticky note shapes with text content\n * - text: Rich text shapes with formatting support\n * - video: Video shapes referencing video assets\n *\n * @public\n * @example\n * ```ts\n * import { createTLSchema, defaultShapeSchemas } from '@tldraw/tlschema'\n *\n * // Use all default shapes\n * const schema = createTLSchema({\n * shapes: defaultShapeSchemas,\n * })\n *\n * // Use only specific default shapes\n * const minimalSchema = createTLSchema({\n * shapes: {\n * geo: defaultShapeSchemas.geo,\n * text: defaultShapeSchemas.text,\n * },\n * })\n * ```\n */\nexport const defaultShapeSchemas = {\n\tarrow: { migrations: arrowShapeMigrations, props: arrowShapeProps },\n\tbookmark: { migrations: bookmarkShapeMigrations, props: bookmarkShapeProps },\n\tdraw: { migrations: drawShapeMigrations, props: drawShapeProps },\n\tembed: { migrations: embedShapeMigrations, props: embedShapeProps },\n\tframe: { migrations: frameShapeMigrations, props: frameShapeProps },\n\tgeo: { migrations: geoShapeMigrations, props: geoShapeProps },\n\tgroup: { migrations: groupShapeMigrations, props: groupShapeProps },\n\thighlight: { migrations: highlightShapeMigrations, props: highlightShapeProps },\n\timage: { migrations: imageShapeMigrations, props: imageShapeProps },\n\tline: { migrations: lineShapeMigrations, props: lineShapeProps },\n\tnote: { migrations: noteShapeMigrations, props: noteShapeProps },\n\ttext: { migrations: textShapeMigrations, props: textShapeProps },\n\tvideo: { migrations: videoShapeMigrations, props: videoShapeProps },\n} satisfies {\n\t[T in TLDefaultShape['type']]: {\n\t\tmigrations: SchemaPropsInfo['migrations']\n\t\tprops: RecordProps<TLBaseShape<T, Extract<TLDefaultShape, { type: T }>['props']>>\n\t}\n}\n\n/**\n * Default binding schema configurations for all built-in tldraw binding types.\n * Bindings represent relationships between shapes, such as arrows connected to shapes.\n *\n * Currently includes:\n * - arrow: Bindings that connect arrow shapes to other shapes at specific anchor points\n *\n * @public\n * @example\n * ```ts\n * import { createTLSchema, defaultBindingSchemas } from '@tldraw/tlschema'\n *\n * // Use default bindings\n * const schema = createTLSchema({\n * bindings: defaultBindingSchemas,\n * })\n *\n * // Add custom binding alongside defaults\n * const customSchema = createTLSchema({\n * bindings: {\n * ...defaultBindingSchemas,\n * myCustomBinding: {\n * props: myCustomBindingProps,\n * migrations: myCustomBindingMigrations,\n * },\n * },\n * })\n * ```\n */\nexport const defaultBindingSchemas = {\n\tarrow: { migrations: arrowBindingMigrations, props: arrowBindingProps },\n} satisfies { [T in TLDefaultBinding['type']]: SchemaPropsInfo }\n\n/**\n * Creates a complete TLSchema for use with tldraw stores. This schema defines the structure,\n * validation, and migration sequences for all record types in a tldraw application.\n *\n * The schema includes all core record types (pages, cameras, instances, etc.) plus the\n * shape, binding, and custom record types you specify. Style properties are automatically\n * collected from all shapes to ensure consistency across the application.\n *\n * @param options - Configuration options for the schema\n * - shapes - Shape schema configurations. Defaults to defaultShapeSchemas if not provided\n * - bindings - Binding schema configurations. Defaults to defaultBindingSchemas if not provided\n * - records - Custom record type configurations. These are additional record types beyond\n * the built-in shapes, bindings, assets, etc.\n * - migrations - Additional migration sequences to include in the schema\n * @returns A complete TLSchema ready for use with Store creation\n *\n * @public\n * @example\n * ```ts\n * import { createTLSchema, defaultShapeSchemas, defaultBindingSchemas } from '@tldraw/tlschema'\n * import { Store } from '@tldraw/store'\n *\n * // Create schema with all default shapes and bindings\n * const schema = createTLSchema()\n *\n * // Create schema with custom shapes added\n * const customSchema = createTLSchema({\n * shapes: {\n * ...defaultShapeSchemas,\n * myCustomShape: {\n * props: myCustomShapeProps,\n * migrations: myCustomShapeMigrations,\n * },\n * },\n * })\n *\n * // Create schema with custom record types\n * const schemaWithCustomRecords = createTLSchema({\n * records: {\n * comment: {\n * scope: 'document',\n * validator: T.object({\n * id: T.string,\n * typeName: T.literal('comment'),\n * text: T.string,\n * shapeId: T.string,\n * }),\n * },\n * },\n * })\n *\n * // Use the schema with a store\n * const store = new Store({\n * schema: customSchema,\n * props: {\n * defaultName: 'My Drawing',\n * },\n * })\n * ```\n */\nexport function createTLSchema({\n\tshapes = defaultShapeSchemas,\n\tbindings = defaultBindingSchemas,\n\trecords = {},\n\tmigrations,\n}: {\n\tshapes?: Record<string, SchemaPropsInfo>\n\tbindings?: Record<string, SchemaPropsInfo>\n\trecords?: Record<string, CustomRecordInfo>\n\tmigrations?: readonly MigrationSequence[]\n} = {}): TLSchema {\n\tconst stylesById = new Map<string, StyleProp<unknown>>()\n\tfor (const shape of objectMapValues(shapes)) {\n\t\tfor (const style of getShapePropKeysByStyle(shape.props ?? {}).keys()) {\n\t\t\tif (stylesById.has(style.id) && stylesById.get(style.id) !== style) {\n\t\t\t\tthrow new Error(`Multiple StyleProp instances with the same id: ${style.id}`)\n\t\t\t}\n\t\t\tstylesById.set(style.id, style)\n\t\t}\n\t}\n\n\tconst ShapeRecordType = createShapeRecordType(shapes)\n\tconst BindingRecordType = createBindingRecordType(bindings)\n\tconst InstanceRecordType = createInstanceRecordType(stylesById)\n\n\t// Create RecordTypes for custom records\n\tconst builtInTypeNames = new Set([\n\t\t'asset',\n\t\t'binding',\n\t\t'camera',\n\t\t'document',\n\t\t'instance',\n\t\t'instance_page_state',\n\t\t'page',\n\t\t'instance_presence',\n\t\t'pointer',\n\t\t'shape',\n\t\t'store',\n\t])\n\tconst customRecordTypes: Record<string, { createId: any }> = {}\n\tfor (const [typeName, config] of Object.entries(records)) {\n\t\tif (builtInTypeNames.has(typeName)) {\n\t\t\tthrow new Error(\n\t\t\t\t`Custom record type name '${typeName}' conflicts with tldraw's built-in record type of that name. Choose a different name instead.`\n\t\t\t)\n\t\t}\n\t\tcustomRecordTypes[typeName] = createCustomRecordType(typeName, config)\n\t}\n\n\treturn StoreSchema.create(\n\t\t{\n\t\t\tasset: AssetRecordType,\n\t\t\tbinding: BindingRecordType,\n\t\t\tcamera: CameraRecordType,\n\t\t\tdocument: DocumentRecordType,\n\t\t\tinstance: InstanceRecordType,\n\t\t\tinstance_page_state: InstancePageStateRecordType,\n\t\t\tpage: PageRecordType,\n\t\t\tinstance_presence: InstancePresenceRecordType,\n\t\t\tpointer: PointerRecordType,\n\t\t\tshape: ShapeRecordType,\n\t\t\t...customRecordTypes,\n\t\t},\n\t\t{\n\t\t\tmigrations: [\n\t\t\t\tstoreMigrations,\n\t\t\t\tassetMigrations,\n\t\t\t\tcameraMigrations,\n\t\t\t\tdocumentMigrations,\n\t\t\t\tinstanceMigrations,\n\t\t\t\tinstancePageStateMigrations,\n\t\t\t\tpageMigrations,\n\t\t\t\tinstancePresenceMigrations,\n\t\t\t\tpointerMigrations,\n\t\t\t\trootShapeMigrations,\n\n\t\t\t\tbookmarkAssetMigrations,\n\t\t\t\timageAssetMigrations,\n\t\t\t\tvideoAssetMigrations,\n\n\t\t\t\t...processPropsMigrations<TLShape>('shape', shapes),\n\t\t\t\t...processPropsMigrations<TLBinding>('binding', bindings),\n\t\t\t\t...processCustomRecordMigrations(records),\n\n\t\t\t\t...(migrations ?? []),\n\t\t\t],\n\t\t\tonValidationFailure,\n\t\t\tcreateIntegrityChecker,\n\t\t}\n\t)\n}\n"],
|
|
5
|
-
"mappings": ";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,mBAAiF;AACjF,mBAAgC;AAChC,
|
|
4
|
+
"sourcesContent": ["import { LegacyMigrations, MigrationSequence, StoreSchema, StoreValidator } from '@tldraw/store'\nimport { objectMapValues } from '@tldraw/utils'\nimport { bookmarkAssetMigrations } from './assets/TLBookmarkAsset'\nimport { imageAssetMigrations } from './assets/TLImageAsset'\nimport { videoAssetMigrations } from './assets/TLVideoAsset'\nimport { arrowBindingMigrations, arrowBindingProps } from './bindings/TLArrowBinding'\nimport { AssetRecordType, assetMigrations } from './records/TLAsset'\nimport { TLBinding, TLDefaultBinding, createBindingRecordType } from './records/TLBinding'\nimport { CameraRecordType, cameraMigrations } from './records/TLCamera'\nimport {\n\tCustomRecordInfo,\n\tcreateCustomRecordType,\n\tprocessCustomRecordMigrations,\n} from './records/TLCustomRecord'\nimport { DocumentRecordType, documentMigrations } from './records/TLDocument'\nimport { createInstanceRecordType, instanceMigrations } from './records/TLInstance'\nimport { PageRecordType, pageMigrations } from './records/TLPage'\nimport { InstancePageStateRecordType, instancePageStateMigrations } from './records/TLPageState'\nimport { PointerRecordType, pointerMigrations } from './records/TLPointer'\nimport { InstancePresenceRecordType, instancePresenceMigrations } from './records/TLPresence'\nimport { TLRecord } from './records/TLRecord'\nimport {\n\tTLDefaultShape,\n\tTLShape,\n\tcreateShapeRecordType,\n\tgetShapePropKeysByStyle,\n\trootShapeMigrations,\n} from './records/TLShape'\nimport { RecordProps, TLPropsMigrations, processPropsMigrations } from './recordsWithProps'\nimport { arrowShapeMigrations, arrowShapeProps } from './shapes/TLArrowShape'\nimport { TLBaseShape } from './shapes/TLBaseShape'\nimport { bookmarkShapeMigrations, bookmarkShapeProps } from './shapes/TLBookmarkShape'\nimport { drawShapeMigrations, drawShapeProps } from './shapes/TLDrawShape'\nimport { embedShapeMigrations, embedShapeProps } from './shapes/TLEmbedShape'\nimport { frameShapeMigrations, frameShapeProps } from './shapes/TLFrameShape'\nimport { geoShapeMigrations, geoShapeProps } from './shapes/TLGeoShape'\nimport { groupShapeMigrations, groupShapeProps } from './shapes/TLGroupShape'\nimport { highlightShapeMigrations, highlightShapeProps } from './shapes/TLHighlightShape'\nimport { imageShapeMigrations, imageShapeProps } from './shapes/TLImageShape'\nimport { lineShapeMigrations, lineShapeProps } from './shapes/TLLineShape'\nimport { noteShapeMigrations, noteShapeProps } from './shapes/TLNoteShape'\nimport { textShapeMigrations, textShapeProps } from './shapes/TLTextShape'\nimport { videoShapeMigrations, videoShapeProps } from './shapes/TLVideoShape'\nimport { storeMigrations } from './store-migrations'\nimport { StyleProp } from './styles/StyleProp'\nimport { TLStoreProps, createIntegrityChecker, onValidationFailure } from './TLStore'\n\n/**\n * Configuration information for a schema type (shape or binding), including its properties,\n * metadata, and migration sequences for data evolution over time.\n *\n * @public\n * @example\n * ```ts\n * import { arrowShapeMigrations, arrowShapeProps } from './shapes/TLArrowShape'\n *\n * const myShapeSchema: SchemaPropsInfo = {\n * migrations: arrowShapeMigrations,\n * props: arrowShapeProps,\n * meta: {\n * customField: T.string,\n * },\n * }\n * ```\n */\nexport interface SchemaPropsInfo {\n\t/**\n\t * Migration sequences for handling data evolution over time. Can be legacy migrations,\n\t * props-specific migrations, or general migration sequences.\n\t */\n\tmigrations?: LegacyMigrations | TLPropsMigrations | MigrationSequence\n\n\t/**\n\t * Validation schema for the shape or binding properties. Maps property names to their validators.\n\t */\n\tprops?: Record<string, StoreValidator<any>>\n\n\t/**\n\t * Validation schema for metadata fields. Maps metadata field names to their validators.\n\t */\n\tmeta?: Record<string, StoreValidator<any>>\n}\n\n/**\n * The complete schema definition for a tldraw store, encompassing all record types,\n * validation rules, and migration sequences. This schema defines the structure of\n * the persistent data model used by tldraw.\n *\n * @public\n * @example\n * ```ts\n * import { createTLSchema, defaultShapeSchemas } from '@tldraw/tlschema'\n * import { Store } from '@tldraw/store'\n *\n * const schema: TLSchema = createTLSchema({\n * shapes: defaultShapeSchemas,\n * })\n *\n * const store = new Store({ schema })\n * ```\n */\nexport type TLSchema = StoreSchema<TLRecord, TLStoreProps>\n\n/**\n * Default shape schema configurations for all built-in tldraw shape types.\n * Each shape type includes its validation props and migration sequences.\n *\n * This object contains schema information for:\n * - arrow: Directional lines that can bind to other shapes\n * - bookmark: Website bookmark cards with preview information\n * - draw: Freehand drawing paths created with drawing tools\n * - embed: Embedded content from external services (YouTube, Figma, etc.)\n * - frame: Container shapes for organizing content\n * - geo: Geometric shapes (rectangles, ellipses, triangles, etc.)\n * - group: Logical groupings of multiple shapes\n * - highlight: Highlighting strokes from the highlighter tool\n * - image: Raster image shapes referencing image assets\n * - line: Multi-point lines and splines\n * - note: Sticky note shapes with text content\n * - text: Rich text shapes with formatting support\n * - video: Video shapes referencing video assets\n *\n * @public\n * @example\n * ```ts\n * import { createTLSchema, defaultShapeSchemas } from '@tldraw/tlschema'\n *\n * // Use all default shapes\n * const schema = createTLSchema({\n * shapes: defaultShapeSchemas,\n * })\n *\n * // Use only specific default shapes\n * const minimalSchema = createTLSchema({\n * shapes: {\n * geo: defaultShapeSchemas.geo,\n * text: defaultShapeSchemas.text,\n * },\n * })\n * ```\n */\nexport const defaultShapeSchemas = {\n\tarrow: { migrations: arrowShapeMigrations, props: arrowShapeProps },\n\tbookmark: { migrations: bookmarkShapeMigrations, props: bookmarkShapeProps },\n\tdraw: { migrations: drawShapeMigrations, props: drawShapeProps },\n\tembed: { migrations: embedShapeMigrations, props: embedShapeProps },\n\tframe: { migrations: frameShapeMigrations, props: frameShapeProps },\n\tgeo: { migrations: geoShapeMigrations, props: geoShapeProps },\n\tgroup: { migrations: groupShapeMigrations, props: groupShapeProps },\n\thighlight: { migrations: highlightShapeMigrations, props: highlightShapeProps },\n\timage: { migrations: imageShapeMigrations, props: imageShapeProps },\n\tline: { migrations: lineShapeMigrations, props: lineShapeProps },\n\tnote: { migrations: noteShapeMigrations, props: noteShapeProps },\n\ttext: { migrations: textShapeMigrations, props: textShapeProps },\n\tvideo: { migrations: videoShapeMigrations, props: videoShapeProps },\n} satisfies {\n\t[T in TLDefaultShape['type']]: {\n\t\tmigrations: SchemaPropsInfo['migrations']\n\t\tprops: RecordProps<TLBaseShape<T, Extract<TLDefaultShape, { type: T }>['props']>>\n\t}\n}\n\n/**\n * Default binding schema configurations for all built-in tldraw binding types.\n * Bindings represent relationships between shapes, such as arrows connected to shapes.\n *\n * Currently includes:\n * - arrow: Bindings that connect arrow shapes to other shapes at specific anchor points\n *\n * @public\n * @example\n * ```ts\n * import { createTLSchema, defaultBindingSchemas } from '@tldraw/tlschema'\n *\n * // Use default bindings\n * const schema = createTLSchema({\n * bindings: defaultBindingSchemas,\n * })\n *\n * // Add custom binding alongside defaults\n * const customSchema = createTLSchema({\n * bindings: {\n * ...defaultBindingSchemas,\n * myCustomBinding: {\n * props: myCustomBindingProps,\n * migrations: myCustomBindingMigrations,\n * },\n * },\n * })\n * ```\n */\nexport const defaultBindingSchemas = {\n\tarrow: { migrations: arrowBindingMigrations, props: arrowBindingProps },\n} satisfies { [T in TLDefaultBinding['type']]: SchemaPropsInfo }\n\n/**\n * Creates a complete TLSchema for use with tldraw stores. This schema defines the structure,\n * validation, and migration sequences for all record types in a tldraw application.\n *\n * The schema includes all core record types (pages, cameras, instances, etc.) plus the\n * shape, binding, and custom record types you specify. Style properties are automatically\n * collected from all shapes to ensure consistency across the application.\n *\n * @param options - Configuration options for the schema\n * - shapes - Shape schema configurations. Defaults to defaultShapeSchemas if not provided\n * - bindings - Binding schema configurations. Defaults to defaultBindingSchemas if not provided\n * - records - Custom record type configurations. These are additional record types beyond\n * the built-in shapes, bindings, assets, etc.\n * - migrations - Additional migration sequences to include in the schema\n * @returns A complete TLSchema ready for use with Store creation\n *\n * @public\n * @example\n * ```ts\n * import { createTLSchema, defaultShapeSchemas, defaultBindingSchemas } from '@tldraw/tlschema'\n * import { Store } from '@tldraw/store'\n *\n * // Create schema with all default shapes and bindings\n * const schema = createTLSchema()\n *\n * // Create schema with custom shapes added\n * const customSchema = createTLSchema({\n * shapes: {\n * ...defaultShapeSchemas,\n * myCustomShape: {\n * props: myCustomShapeProps,\n * migrations: myCustomShapeMigrations,\n * },\n * },\n * })\n *\n * // Create schema with custom record types\n * const schemaWithCustomRecords = createTLSchema({\n * records: {\n * comment: {\n * scope: 'document',\n * validator: T.object({\n * id: T.string,\n * typeName: T.literal('comment'),\n * text: T.string,\n * shapeId: T.string,\n * }),\n * },\n * },\n * })\n *\n * // Use the schema with a store\n * const store = new Store({\n * schema: customSchema,\n * props: {\n * defaultName: 'My Drawing',\n * },\n * })\n * ```\n */\nexport function createTLSchema({\n\tshapes = defaultShapeSchemas,\n\tbindings = defaultBindingSchemas,\n\trecords = {},\n\tmigrations,\n}: {\n\tshapes?: Record<string, SchemaPropsInfo>\n\tbindings?: Record<string, SchemaPropsInfo>\n\trecords?: Record<string, CustomRecordInfo>\n\tmigrations?: readonly MigrationSequence[]\n} = {}): TLSchema {\n\tconst stylesById = new Map<string, StyleProp<unknown>>()\n\tfor (const shape of objectMapValues(shapes)) {\n\t\tfor (const style of getShapePropKeysByStyle(shape.props ?? {}).keys()) {\n\t\t\tif (stylesById.has(style.id) && stylesById.get(style.id) !== style) {\n\t\t\t\tthrow new Error(`Multiple StyleProp instances with the same id: ${style.id}`)\n\t\t\t}\n\t\t\tstylesById.set(style.id, style)\n\t\t}\n\t}\n\n\tconst ShapeRecordType = createShapeRecordType(shapes)\n\tconst BindingRecordType = createBindingRecordType(bindings)\n\tconst InstanceRecordType = createInstanceRecordType(stylesById)\n\n\t// Create RecordTypes for custom records\n\tconst builtInTypeNames = new Set([\n\t\t'asset',\n\t\t'binding',\n\t\t'camera',\n\t\t'document',\n\t\t'instance',\n\t\t'instance_page_state',\n\t\t'page',\n\t\t'instance_presence',\n\t\t'pointer',\n\t\t'shape',\n\t\t'store',\n\t])\n\tconst customRecordTypes: Record<string, { createId: any }> = {}\n\tfor (const [typeName, config] of Object.entries(records)) {\n\t\tif (builtInTypeNames.has(typeName)) {\n\t\t\tthrow new Error(\n\t\t\t\t`Custom record type name '${typeName}' conflicts with tldraw's built-in record type of that name. Choose a different name instead.`\n\t\t\t)\n\t\t}\n\t\tcustomRecordTypes[typeName] = createCustomRecordType(typeName, config)\n\t}\n\n\treturn StoreSchema.create(\n\t\t{\n\t\t\tasset: AssetRecordType,\n\t\t\tbinding: BindingRecordType,\n\t\t\tcamera: CameraRecordType,\n\t\t\tdocument: DocumentRecordType,\n\t\t\tinstance: InstanceRecordType,\n\t\t\tinstance_page_state: InstancePageStateRecordType,\n\t\t\tpage: PageRecordType,\n\t\t\tinstance_presence: InstancePresenceRecordType,\n\t\t\tpointer: PointerRecordType,\n\t\t\tshape: ShapeRecordType,\n\t\t\t...customRecordTypes,\n\t\t},\n\t\t{\n\t\t\tmigrations: [\n\t\t\t\tstoreMigrations,\n\t\t\t\tassetMigrations,\n\t\t\t\tcameraMigrations,\n\t\t\t\tdocumentMigrations,\n\t\t\t\tinstanceMigrations,\n\t\t\t\tinstancePageStateMigrations,\n\t\t\t\tpageMigrations,\n\t\t\t\tinstancePresenceMigrations,\n\t\t\t\tpointerMigrations,\n\t\t\t\trootShapeMigrations,\n\n\t\t\t\tbookmarkAssetMigrations,\n\t\t\t\timageAssetMigrations,\n\t\t\t\tvideoAssetMigrations,\n\n\t\t\t\t...processPropsMigrations<TLShape>('shape', shapes),\n\t\t\t\t...processPropsMigrations<TLBinding>('binding', bindings),\n\t\t\t\t...processCustomRecordMigrations(records),\n\n\t\t\t\t...(migrations ?? []),\n\t\t\t],\n\t\t\tonValidationFailure,\n\t\t\tcreateIntegrityChecker,\n\t\t}\n\t)\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
package/dist-cjs/index.js
CHANGED
|
@@ -187,7 +187,7 @@ var import_translations = require("./translations/translations");
|
|
|
187
187
|
var import_b64Vecs = require("./misc/b64Vecs");
|
|
188
188
|
(0, import_utils.registerTldrawLibraryVersion)(
|
|
189
189
|
"@tldraw/tlschema",
|
|
190
|
-
"4.6.0-next.
|
|
190
|
+
"4.6.0-next.d15997ff5a4b",
|
|
191
191
|
"cjs"
|
|
192
192
|
);
|
|
193
193
|
//# sourceMappingURL=index.js.map
|
|
@@ -23,8 +23,8 @@ __export(TLScribble_exports, {
|
|
|
23
23
|
});
|
|
24
24
|
module.exports = __toCommonJS(TLScribble_exports);
|
|
25
25
|
var import_validate = require("@tldraw/validate");
|
|
26
|
-
var import_TLColor = require("./TLColor");
|
|
27
26
|
var import_geometry_types = require("./geometry-types");
|
|
27
|
+
var import_TLColor = require("./TLColor");
|
|
28
28
|
const TL_SCRIBBLE_STATES = /* @__PURE__ */ new Set([
|
|
29
29
|
"starting",
|
|
30
30
|
"paused",
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../src/misc/TLScribble.ts"],
|
|
4
|
-
"sourcesContent": ["import { T } from '@tldraw/validate'\nimport { SetValue } from '../util-types'\nimport {
|
|
5
|
-
"mappings": ";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,sBAAkB;AAElB,
|
|
4
|
+
"sourcesContent": ["import { T } from '@tldraw/validate'\nimport { SetValue } from '../util-types'\nimport { VecModel, vecModelValidator } from './geometry-types'\nimport { TLCanvasUiColor, canvasUiColorTypeValidator } from './TLColor'\n\n/**\n * All available scribble states used by the tldraw drawing system.\n *\n * Scribble states represent the different phases of a drawing stroke:\n *\n * - `starting`: The scribble is being initiated\n * - `paused`: The scribble is temporarily paused\n * - `active`: The scribble is actively being drawn\n * - `complete`: The scribble is done being drawn but not yet fading\n * - `stopping`: The scribble is being finished\n *\n * These states help manage the drawing lifecycle and apply appropriate\n * visual effects during different phases of the stroke.\n *\n * @example\n * ```ts\n * // Check if a scribble state is valid\n * if (TL_SCRIBBLE_STATES.has('active')) {\n * console.log('Valid scribble state')\n * }\n *\n * // Get all available scribble states\n * const allStates = Array.from(TL_SCRIBBLE_STATES)\n * ```\n *\n * @public\n */\nexport const TL_SCRIBBLE_STATES = new Set([\n\t'starting',\n\t'paused',\n\t'active',\n\t'complete',\n\t'stopping',\n] as const)\n\n/**\n * A scribble object representing a drawing stroke in tldraw.\n *\n * Scribbles are temporary drawing strokes that appear during freehand drawing\n * operations. They provide visual feedback as the user draws and can be styled\n * with various properties like size, color, and effects.\n *\n * @example\n * ```ts\n * // A basic scribble stroke\n * const scribble: TLScribble = {\n * id: 'scribble-123',\n * points: [\n * { x: 0, y: 0, z: 0.5 },\n * { x: 10, y: 5, z: 0.7 },\n * { x: 20, y: 10, z: 0.6 }\n * ],\n * size: 4,\n * color: 'black',\n * opacity: 0.8,\n * state: 'active',\n * delay: 0,\n * shrink: 0.1,\n * taper: true\n * }\n *\n * // A laser pointer scribble\n * const laserScribble: TLScribble = {\n * id: 'laser-pointer',\n * points: [{ x: 50, y: 50, z: 1.0 }],\n * size: 8,\n * color: 'laser',\n * opacity: 1.0,\n * state: 'active',\n * delay: 100,\n * shrink: 0,\n * taper: false\n * }\n * ```\n *\n * @public\n */\nexport interface TLScribble {\n\t/** Unique identifier for the scribble */\n\tid: string\n\t/** Array of points that make up the scribble path */\n\tpoints: VecModel[]\n\t/** The brush size/width of the scribble stroke */\n\tsize: number\n\t/** The color of the scribble using canvas UI color types */\n\tcolor: TLCanvasUiColor\n\t/** The opacity of the scribble (0-1) */\n\topacity: number\n\t/** The current state of the scribble drawing */\n\tstate: SetValue<typeof TL_SCRIBBLE_STATES>\n\t/** Time delay in milliseconds for animation effects */\n\tdelay: number\n\t/** Amount the stroke should shrink over time (0-1) */\n\tshrink: number\n\t/** Whether the stroke should taper at the ends */\n\ttaper: boolean\n}\n\n/**\n * A validator for TLScribble objects.\n *\n * This validator ensures that scribble objects have all required properties\n * with valid types and values. It validates the points array, size constraints,\n * color types, and state values according to the scribble system requirements.\n *\n * @example\n * ```ts\n * import { scribbleValidator } from '@tldraw/tlschema'\n *\n * // Validate a scribble object\n * try {\n * const validScribble = scribbleValidator.validate({\n * id: 'scribble-1',\n * points: [{ x: 0, y: 0, z: 1 }, { x: 10, y: 10, z: 1 }],\n * size: 3,\n * color: 'black',\n * opacity: 0.8,\n * state: 'active',\n * delay: 0,\n * shrink: 0.05,\n * taper: true\n * })\n * console.log('Valid scribble:', validScribble)\n * } catch (error) {\n * console.error('Invalid scribble:', error.message)\n * }\n * ```\n *\n * @public\n */\nexport const scribbleValidator: T.ObjectValidator<TLScribble> = T.object({\n\tid: T.string,\n\tpoints: T.arrayOf(vecModelValidator),\n\tsize: T.positiveNumber,\n\tcolor: canvasUiColorTypeValidator,\n\topacity: T.number,\n\tstate: T.setEnum(TL_SCRIBBLE_STATES),\n\tdelay: T.number,\n\tshrink: T.number,\n\ttaper: T.boolean,\n})\n"],
|
|
5
|
+
"mappings": ";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,sBAAkB;AAElB,4BAA4C;AAC5C,qBAA4D;AA6BrD,MAAM,qBAAqB,oBAAI,IAAI;AAAA,EACzC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACD,CAAU;AAiGH,MAAM,oBAAmD,kBAAE,OAAO;AAAA,EACxE,IAAI,kBAAE;AAAA,EACN,QAAQ,kBAAE,QAAQ,uCAAiB;AAAA,EACnC,MAAM,kBAAE;AAAA,EACR,OAAO;AAAA,EACP,SAAS,kBAAE;AAAA,EACX,OAAO,kBAAE,QAAQ,kBAAkB;AAAA,EACnC,OAAO,kBAAE;AAAA,EACT,QAAQ,kBAAE;AAAA,EACV,OAAO,kBAAE;AACV,CAAC;",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../src/records/TLCustomRecord.ts"],
|
|
4
|
-
"sourcesContent": ["import {\n\tMigrationSequence,\n\tRecordId,\n\tRecordScope,\n\tUnknownRecord,\n\tcreateMigrationSequence,\n\tcreateRecordType,\n} from '@tldraw/store'\nimport { assert, mapObjectMapValues, uniqueId } from '@tldraw/utils'\nimport { T } from '@tldraw/validate'\nimport { TLPropsMigrations } from '../recordsWithProps'\n\n/**\n * Configuration for a custom record type in the schema.\n *\n * Custom record types allow you to add entirely new data types to the tldraw store\n * that don't fit into the existing shape, binding, or asset categories. This is useful\n * for storing domain-specific data like comments, annotations, or application state\n * that needs to participate in persistence and synchronization.\n *\n * @example\n * ```ts\n * const commentRecordConfig: CustomRecordInfo = {\n * scope: 'document',\n * validator: T.object({\n * id: T.string,\n * typeName: T.literal('comment'),\n * text: T.string,\n * shapeId: T.string,\n * authorId: T.string,\n * createdAt: T.number,\n * }),\n * migrations: createRecordMigrationSequence({\n * sequenceId: 'com.myapp.comment',\n * recordType: 'comment',\n * sequence: [],\n * }),\n * }\n * ```\n *\n * @public\n */\nexport interface CustomRecordInfo {\n\t/**\n\t * The scope determines how records of this type are persisted and synchronized:\n\t * - **document**: Persisted and synced across all clients\n\t * - **session**: Local to current session, not synced\n\t * - **presence**: Ephemeral presence data, may be synced but not persisted\n\t */\n\tscope: RecordScope\n\n\t/**\n\t * Validator for the complete record structure.\n\t *\n\t * Should validate the entire record including `id` and `typeName` fields.\n\t * Use validators like T.object, T.string, etc.\n\t */\n\tvalidator: T.Validatable<any>\n\n\t/**\n\t * Optional migration sequence for handling schema evolution over time.\n\t *\n\t * Can be a full MigrationSequence or a simplified TLPropsMigrations format.\n\t * If not provided, an empty migration sequence will be created automatically.\n\t */\n\tmigrations?: MigrationSequence | TLPropsMigrations\n\n\t/**\n\t * Optional factory function that returns default property values for new records.\n\t *\n\t * Called when creating new records to provide initial values for any properties\n\t * not explicitly provided during creation.\n\t */\n\t// eslint-disable-next-line
|
|
4
|
+
"sourcesContent": ["import {\n\tMigrationSequence,\n\tRecordId,\n\tRecordScope,\n\tUnknownRecord,\n\tcreateMigrationSequence,\n\tcreateRecordType,\n} from '@tldraw/store'\nimport { assert, mapObjectMapValues, uniqueId } from '@tldraw/utils'\nimport { T } from '@tldraw/validate'\nimport { TLPropsMigrations } from '../recordsWithProps'\n\n/**\n * Configuration for a custom record type in the schema.\n *\n * Custom record types allow you to add entirely new data types to the tldraw store\n * that don't fit into the existing shape, binding, or asset categories. This is useful\n * for storing domain-specific data like comments, annotations, or application state\n * that needs to participate in persistence and synchronization.\n *\n * @example\n * ```ts\n * const commentRecordConfig: CustomRecordInfo = {\n * scope: 'document',\n * validator: T.object({\n * id: T.string,\n * typeName: T.literal('comment'),\n * text: T.string,\n * shapeId: T.string,\n * authorId: T.string,\n * createdAt: T.number,\n * }),\n * migrations: createRecordMigrationSequence({\n * sequenceId: 'com.myapp.comment',\n * recordType: 'comment',\n * sequence: [],\n * }),\n * }\n * ```\n *\n * @public\n */\nexport interface CustomRecordInfo {\n\t/**\n\t * The scope determines how records of this type are persisted and synchronized:\n\t * - **document**: Persisted and synced across all clients\n\t * - **session**: Local to current session, not synced\n\t * - **presence**: Ephemeral presence data, may be synced but not persisted\n\t */\n\tscope: RecordScope\n\n\t/**\n\t * Validator for the complete record structure.\n\t *\n\t * Should validate the entire record including `id` and `typeName` fields.\n\t * Use validators like T.object, T.string, etc.\n\t */\n\tvalidator: T.Validatable<any>\n\n\t/**\n\t * Optional migration sequence for handling schema evolution over time.\n\t *\n\t * Can be a full MigrationSequence or a simplified TLPropsMigrations format.\n\t * If not provided, an empty migration sequence will be created automatically.\n\t */\n\tmigrations?: MigrationSequence | TLPropsMigrations\n\n\t/**\n\t * Optional factory function that returns default property values for new records.\n\t *\n\t * Called when creating new records to provide initial values for any properties\n\t * not explicitly provided during creation.\n\t */\n\t// eslint-disable-next-line tldraw/method-signature-style\n\tcreateDefaultProperties?: () => Record<string, unknown>\n}\n\n/**\n * Creates a RecordType for a custom record based on its configuration.\n *\n * @param typeName - The unique type name for this record type\n * @param config - Configuration for the custom record type\n * @returns A RecordType instance that can be used to create and manage records\n *\n * @internal\n */\nexport function createCustomRecordType(typeName: string, config: CustomRecordInfo) {\n\treturn createRecordType<UnknownRecord>(typeName, {\n\t\tscope: config.scope,\n\t\tvalidator: config.validator,\n\t}).withDefaultProperties(config.createDefaultProperties ?? (() => ({})))\n}\n\n/**\n * Processes migrations for custom record types.\n *\n * Converts the migration configuration from CustomRecordInfo into proper\n * MigrationSequence objects that can be used by the store system.\n *\n * @param records - Record of type names to their configuration\n * @returns Array of migration sequences for the custom record types\n *\n * @internal\n */\nexport function processCustomRecordMigrations(\n\trecords: Record<string, CustomRecordInfo>\n): MigrationSequence[] {\n\tconst result: MigrationSequence[] = []\n\n\tfor (const [typeName, config] of Object.entries(records)) {\n\t\tconst sequenceId = `com.tldraw.${typeName}`\n\t\tconst { migrations } = config\n\n\t\tif (!migrations) {\n\t\t\t// Provide empty migration sequence to allow for future migrations\n\t\t\tresult.push(\n\t\t\t\tcreateMigrationSequence({\n\t\t\t\t\tsequenceId,\n\t\t\t\t\tretroactive: true,\n\t\t\t\t\tsequence: [],\n\t\t\t\t})\n\t\t\t)\n\t\t} else if ('sequenceId' in migrations) {\n\t\t\t// Full MigrationSequence provided\n\t\t\tassert(\n\t\t\t\tsequenceId === migrations.sequenceId,\n\t\t\t\t`sequenceId mismatch for ${typeName} custom record migrations. Expected '${sequenceId}', got '${migrations.sequenceId}'`\n\t\t\t)\n\t\t\tresult.push(migrations)\n\t\t} else if ('sequence' in migrations) {\n\t\t\t// TLPropsMigrations format - convert to full MigrationSequence\n\t\t\tresult.push(\n\t\t\t\tcreateMigrationSequence({\n\t\t\t\t\tsequenceId,\n\t\t\t\t\tretroactive: true,\n\t\t\t\t\tsequence: migrations.sequence.map((m) => {\n\t\t\t\t\t\tif (!('id' in m)) return m\n\t\t\t\t\t\treturn {\n\t\t\t\t\t\t\tid: m.id,\n\t\t\t\t\t\t\tdependsOn: m.dependsOn,\n\t\t\t\t\t\t\tscope: 'record' as const,\n\t\t\t\t\t\t\tfilter: (r: UnknownRecord) => r.typeName === typeName,\n\t\t\t\t\t\t\tup: (record: any) => {\n\t\t\t\t\t\t\t\tconst result = m.up(record)\n\t\t\t\t\t\t\t\tif (result) return result\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tdown:\n\t\t\t\t\t\t\t\ttypeof m.down === 'function'\n\t\t\t\t\t\t\t\t\t? (record: any) => {\n\t\t\t\t\t\t\t\t\t\t\tconst result = (m.down as (r: any) => any)(record)\n\t\t\t\t\t\t\t\t\t\t\tif (result) return result\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t: undefined,\n\t\t\t\t\t\t}\n\t\t\t\t\t}),\n\t\t\t\t})\n\t\t\t)\n\t\t}\n\t}\n\n\treturn result\n}\n\n/**\n * Creates properly formatted migration IDs for custom record migrations.\n *\n * Generates standardized migration IDs following the convention:\n * `com.tldraw.{recordType}/{version}`\n *\n * @param recordType - The type name of the custom record\n * @param ids - Record mapping migration names to version numbers\n * @returns Record with the same keys but formatted migration ID values\n *\n * @example\n * ```ts\n * const commentVersions = createCustomRecordMigrationIds('comment', {\n * AddAuthorId: 1,\n * AddCreatedAt: 2,\n * RefactorReactions: 3\n * })\n * // Result: {\n * // AddAuthorId: 'com.tldraw.comment/1',\n * // AddCreatedAt: 'com.tldraw.comment/2',\n * // RefactorReactions: 'com.tldraw.comment/3'\n * // }\n * ```\n *\n * @public\n */\nexport function createCustomRecordMigrationIds<\n\tconst S extends string,\n\tconst T extends Record<string, number>,\n>(recordType: S, ids: T): { [k in keyof T]: `com.tldraw.${S}/${T[k]}` } {\n\treturn mapObjectMapValues(ids, (_k, v) => `com.tldraw.${recordType}/${v}`) as any\n}\n\n/**\n * Creates a migration sequence for custom record types.\n *\n * This is a pass-through function that maintains the same structure as the input.\n * It's used for consistency and to provide a clear API for defining custom record migrations.\n *\n * @param migrations - The migration sequence to create\n * @returns The same migration sequence (pass-through)\n *\n * @example\n * ```ts\n * const commentMigrations = createCustomRecordMigrationSequence({\n * sequence: [\n * {\n * id: 'com.myapp.comment/1',\n * up: (record) => ({ ...record, authorId: record.authorId ?? 'unknown' }),\n * down: ({ authorId, ...record }) => record\n * }\n * ]\n * })\n * ```\n *\n * @public\n */\nexport function createCustomRecordMigrationSequence(\n\tmigrations: TLPropsMigrations\n): TLPropsMigrations {\n\treturn migrations\n}\n\n/**\n * Creates a unique ID for a custom record type.\n *\n * @param typeName - The type name of the custom record\n * @param id - Optional custom ID suffix. If not provided, a unique ID will be generated\n * @returns A properly formatted record ID\n *\n * @example\n * ```ts\n * // Create with auto-generated ID\n * const commentId = createCustomRecordId('comment') // 'comment:abc123'\n *\n * // Create with custom ID\n * const customId = createCustomRecordId('comment', 'my-comment') // 'comment:my-comment'\n * ```\n *\n * @public\n */\nexport function createCustomRecordId<T extends string>(\n\ttypeName: T,\n\tid?: string\n): RecordId<UnknownRecord> & `${T}:${string}` {\n\treturn `${typeName}:${id ?? uniqueId()}` as RecordId<UnknownRecord> & `${T}:${string}`\n}\n\n/**\n * Type guard to check if a string is a valid ID for a specific custom record type.\n *\n * @param typeName - The type name to check against\n * @param id - The string to check\n * @returns True if the string is a valid ID for the specified record type\n *\n * @example\n * ```ts\n * const id = 'comment:abc123'\n * if (isCustomRecordId('comment', id)) {\n * // id is now typed as a comment record ID\n * const comment = store.get(id)\n * }\n * ```\n *\n * @public\n */\nexport function isCustomRecordId(typeName: string, id?: string): boolean {\n\tif (!id) return false\n\treturn id.startsWith(`${typeName}:`)\n}\n\n/**\n * Type guard to check if a record is of a specific custom type.\n *\n * @param typeName - The type name to check against\n * @param record - The record to check\n * @returns True if the record is of the specified type\n *\n * @example\n * ```ts\n * function handleRecord(record: TLRecord) {\n * if (isCustomRecord('comment', record)) {\n * // Handle comment record\n * console.log(`Comment: ${record.text}`)\n * }\n * }\n * ```\n *\n * @public\n */\nexport function isCustomRecord(typeName: string, record?: UnknownRecord): boolean {\n\tif (!record) return false\n\treturn record.typeName === typeName\n}\n"],
|
|
5
5
|
"mappings": ";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,mBAOO;AACP,mBAAqD;AA8E9C,SAAS,uBAAuB,UAAkB,QAA0B;AAClF,aAAO,+BAAgC,UAAU;AAAA,IAChD,OAAO,OAAO;AAAA,IACd,WAAW,OAAO;AAAA,EACnB,CAAC,EAAE,sBAAsB,OAAO,4BAA4B,OAAO,CAAC,GAAG;AACxE;AAaO,SAAS,8BACf,SACsB;AACtB,QAAM,SAA8B,CAAC;AAErC,aAAW,CAAC,UAAU,MAAM,KAAK,OAAO,QAAQ,OAAO,GAAG;AACzD,UAAM,aAAa,cAAc,QAAQ;AACzC,UAAM,EAAE,WAAW,IAAI;AAEvB,QAAI,CAAC,YAAY;AAEhB,aAAO;AAAA,YACN,sCAAwB;AAAA,UACvB;AAAA,UACA,aAAa;AAAA,UACb,UAAU,CAAC;AAAA,QACZ,CAAC;AAAA,MACF;AAAA,IACD,WAAW,gBAAgB,YAAY;AAEtC;AAAA,QACC,eAAe,WAAW;AAAA,QAC1B,2BAA2B,QAAQ,wCAAwC,UAAU,WAAW,WAAW,UAAU;AAAA,MACtH;AACA,aAAO,KAAK,UAAU;AAAA,IACvB,WAAW,cAAc,YAAY;AAEpC,aAAO;AAAA,YACN,sCAAwB;AAAA,UACvB;AAAA,UACA,aAAa;AAAA,UACb,UAAU,WAAW,SAAS,IAAI,CAAC,MAAM;AACxC,gBAAI,EAAE,QAAQ,GAAI,QAAO;AACzB,mBAAO;AAAA,cACN,IAAI,EAAE;AAAA,cACN,WAAW,EAAE;AAAA,cACb,OAAO;AAAA,cACP,QAAQ,CAAC,MAAqB,EAAE,aAAa;AAAA,cAC7C,IAAI,CAAC,WAAgB;AACpB,sBAAMA,UAAS,EAAE,GAAG,MAAM;AAC1B,oBAAIA,QAAQ,QAAOA;AAAA,cACpB;AAAA,cACA,MACC,OAAO,EAAE,SAAS,aACf,CAAC,WAAgB;AACjB,sBAAMA,UAAU,EAAE,KAAyB,MAAM;AACjD,oBAAIA,QAAQ,QAAOA;AAAA,cACpB,IACC;AAAA,YACL;AAAA,UACD,CAAC;AAAA,QACF,CAAC;AAAA,MACF;AAAA,IACD;AAAA,EACD;AAEA,SAAO;AACR;AA4BO,SAAS,+BAGd,YAAe,KAAuD;AACvE,aAAO,iCAAmB,KAAK,CAAC,IAAI,MAAM,cAAc,UAAU,IAAI,CAAC,EAAE;AAC1E;AA0BO,SAAS,oCACf,YACoB;AACpB,SAAO;AACR;AAoBO,SAAS,qBACf,UACA,IAC6C;AAC7C,SAAO,GAAG,QAAQ,IAAI,UAAM,uBAAS,CAAC;AACvC;AAoBO,SAAS,iBAAiB,UAAkB,IAAsB;AACxE,MAAI,CAAC,GAAI,QAAO;AAChB,SAAO,GAAG,WAAW,GAAG,QAAQ,GAAG;AACpC;AAqBO,SAAS,eAAe,UAAkB,QAAiC;AACjF,MAAI,CAAC,OAAQ,QAAO;AACpB,SAAO,OAAO,aAAa;AAC5B;",
|
|
6
6
|
"names": ["result"]
|
|
7
7
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../src/records/TLPageState.ts"],
|
|
4
|
-
"sourcesContent": ["import {\n\tBaseRecord,\n\tcreateMigrationIds,\n\tcreateRecordMigrationSequence,\n\tcreateRecordType,\n\tRecordId,\n} from '@tldraw/store'\nimport { JsonObject } from '@tldraw/utils'\nimport { T } from '@tldraw/validate'\nimport { idValidator } from '../misc/id-validator'\nimport { shapeIdValidator } from '../shapes/TLBaseShape'\nimport { pageIdValidator, TLPage } from './TLPage'\nimport { TLShapeId } from './TLShape'\n\n/**\n * State that is unique to a particular page within a particular browser tab.\n * This record tracks all page-specific interaction state including selected shapes,\n * editing state, hover state, and other transient UI state that is tied to\n * both a specific page and a specific browser session.\n *\n * Each combination of page and browser tab has its own TLInstancePageState record.\n *\n * @example\n * ```ts\n * const pageState: TLInstancePageState = {\n * id: 'instance_page_state:page1',\n * typeName: 'instance_page_state',\n * pageId: 'page:page1',\n * selectedShapeIds: ['shape:rect1', 'shape:circle2'],\n * hoveredShapeId: 'shape:text3',\n * editingShapeId: null,\n * focusedGroupId: null\n * }\n * ```\n *\n * @public\n */\nexport interface TLInstancePageState
|
|
5
|
-
"mappings": ";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,mBAMO;AAEP,sBAAkB;AAClB,0BAA4B;AAC5B,yBAAiC;AACjC,oBAAwC;
|
|
4
|
+
"sourcesContent": ["import {\n\tBaseRecord,\n\tcreateMigrationIds,\n\tcreateRecordMigrationSequence,\n\tcreateRecordType,\n\tRecordId,\n} from '@tldraw/store'\nimport { JsonObject } from '@tldraw/utils'\nimport { T } from '@tldraw/validate'\nimport { idValidator } from '../misc/id-validator'\nimport { shapeIdValidator } from '../shapes/TLBaseShape'\nimport { pageIdValidator, TLPage } from './TLPage'\nimport { TLShapeId } from './TLShape'\n\n/**\n * State that is unique to a particular page within a particular browser tab.\n * This record tracks all page-specific interaction state including selected shapes,\n * editing state, hover state, and other transient UI state that is tied to\n * both a specific page and a specific browser session.\n *\n * Each combination of page and browser tab has its own TLInstancePageState record.\n *\n * @example\n * ```ts\n * const pageState: TLInstancePageState = {\n * id: 'instance_page_state:page1',\n * typeName: 'instance_page_state',\n * pageId: 'page:page1',\n * selectedShapeIds: ['shape:rect1', 'shape:circle2'],\n * hoveredShapeId: 'shape:text3',\n * editingShapeId: null,\n * focusedGroupId: null\n * }\n * ```\n *\n * @public\n */\nexport interface TLInstancePageState extends BaseRecord<\n\t'instance_page_state',\n\tTLInstancePageStateId\n> {\n\tpageId: RecordId<TLPage>\n\tselectedShapeIds: TLShapeId[]\n\thintingShapeIds: TLShapeId[]\n\terasingShapeIds: TLShapeId[]\n\thoveredShapeId: TLShapeId | null\n\teditingShapeId: TLShapeId | null\n\tcroppingShapeId: TLShapeId | null\n\tfocusedGroupId: TLShapeId | null\n\tmeta: JsonObject\n}\n\n/**\n * Runtime validator for TLInstancePageState records. Validates the structure\n * and types of all instance page state properties to ensure data integrity.\n *\n * @example\n * ```ts\n * const pageState = {\n * id: 'instance_page_state:page1',\n * typeName: 'instance_page_state',\n * pageId: 'page:page1',\n * selectedShapeIds: ['shape:rect1'],\n * // ... other properties\n * }\n * const isValid = instancePageStateValidator.isValid(pageState) // true\n * ```\n *\n * @public\n */\nexport const instancePageStateValidator: T.Validator<TLInstancePageState> = T.model(\n\t'instance_page_state',\n\tT.object({\n\t\ttypeName: T.literal('instance_page_state'),\n\t\tid: idValidator<TLInstancePageStateId>('instance_page_state'),\n\t\tpageId: pageIdValidator,\n\t\tselectedShapeIds: T.arrayOf(shapeIdValidator),\n\t\thintingShapeIds: T.arrayOf(shapeIdValidator),\n\t\terasingShapeIds: T.arrayOf(shapeIdValidator),\n\t\thoveredShapeId: shapeIdValidator.nullable(),\n\t\teditingShapeId: shapeIdValidator.nullable(),\n\t\tcroppingShapeId: shapeIdValidator.nullable(),\n\t\tfocusedGroupId: shapeIdValidator.nullable(),\n\t\tmeta: T.jsonValue as T.ObjectValidator<JsonObject>,\n\t})\n)\n\n/**\n * Migration version identifiers for TLInstancePageState records. Each version\n * represents a schema change that requires data transformation when loading\n * older documents.\n *\n * @public\n */\nexport const instancePageStateVersions = createMigrationIds('com.tldraw.instance_page_state', {\n\tAddCroppingId: 1,\n\tRemoveInstanceIdAndCameraId: 2,\n\tAddMeta: 3,\n\tRenameProperties: 4,\n\tRenamePropertiesAgain: 5,\n} as const)\n\n/**\n * Migration sequence for TLInstancePageState records. Defines how to transform\n * instance page state records between different schema versions, ensuring data\n * compatibility when loading documents created with different versions.\n *\n * @example\n * ```ts\n * // Migrations are applied automatically when loading documents\n * const migrated = instancePageStateMigrations.migrate(oldState, targetVersion)\n * ```\n *\n * @public\n */\nexport const instancePageStateMigrations = createRecordMigrationSequence({\n\tsequenceId: 'com.tldraw.instance_page_state',\n\trecordType: 'instance_page_state',\n\tsequence: [\n\t\t{\n\t\t\tid: instancePageStateVersions.AddCroppingId,\n\t\t\tup(instance: any) {\n\t\t\t\tinstance.croppingShapeId = null\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tid: instancePageStateVersions.RemoveInstanceIdAndCameraId,\n\t\t\tup(instance: any) {\n\t\t\t\tdelete instance.instanceId\n\t\t\t\tdelete instance.cameraId\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tid: instancePageStateVersions.AddMeta,\n\t\t\tup: (record: any) => {\n\t\t\t\trecord.meta = {}\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tid: instancePageStateVersions.RenameProperties,\n\t\t\t// this migration is cursed: it was written wrong and doesn't do anything.\n\t\t\t// rather than replace it, I've added another migration below that fixes it.\n\t\t\tup: (_record) => {\n\t\t\t\t// noop\n\t\t\t},\n\t\t\tdown: (_record) => {\n\t\t\t\t// noop\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tid: instancePageStateVersions.RenamePropertiesAgain,\n\t\t\tup: (record: any) => {\n\t\t\t\trecord.selectedShapeIds = record.selectedIds\n\t\t\t\tdelete record.selectedIds\n\t\t\t\trecord.hintingShapeIds = record.hintingIds\n\t\t\t\tdelete record.hintingIds\n\t\t\t\trecord.erasingShapeIds = record.erasingIds\n\t\t\t\tdelete record.erasingIds\n\t\t\t\trecord.hoveredShapeId = record.hoveredId\n\t\t\t\tdelete record.hoveredId\n\t\t\t\trecord.editingShapeId = record.editingId\n\t\t\t\tdelete record.editingId\n\t\t\t\trecord.croppingShapeId = record.croppingShapeId ?? record.croppingId ?? null\n\t\t\t\tdelete record.croppingId\n\t\t\t\trecord.focusedGroupId = record.focusLayerId\n\t\t\t\tdelete record.focusLayerId\n\t\t\t},\n\t\t\tdown: (record: any) => {\n\t\t\t\trecord.selectedIds = record.selectedShapeIds\n\t\t\t\tdelete record.selectedShapeIds\n\t\t\t\trecord.hintingIds = record.hintingShapeIds\n\t\t\t\tdelete record.hintingShapeIds\n\t\t\t\trecord.erasingIds = record.erasingShapeIds\n\t\t\t\tdelete record.erasingShapeIds\n\t\t\t\trecord.hoveredId = record.hoveredShapeId\n\t\t\t\tdelete record.hoveredShapeId\n\t\t\t\trecord.editingId = record.editingShapeId\n\t\t\t\tdelete record.editingShapeId\n\t\t\t\trecord.croppingId = record.croppingShapeId\n\t\t\t\tdelete record.croppingShapeId\n\t\t\t\trecord.focusLayerId = record.focusedGroupId\n\t\t\t\tdelete record.focusedGroupId\n\t\t\t},\n\t\t},\n\t],\n})\n\n/**\n * The RecordType definition for TLInstancePageState records. Defines validation,\n * scope, and default properties for instance page state records.\n *\n * Instance page states are scoped to the session level, meaning they are\n * specific to a browser tab and don't persist across sessions or sync\n * in collaborative environments.\n *\n * @example\n * ```ts\n * const pageState = InstancePageStateRecordType.create({\n * id: 'instance_page_state:page1',\n * pageId: 'page:page1',\n * selectedShapeIds: ['shape:rect1']\n * })\n * ```\n *\n * @public\n */\nexport const InstancePageStateRecordType = createRecordType<TLInstancePageState>(\n\t'instance_page_state',\n\t{\n\t\tvalidator: instancePageStateValidator,\n\t\tscope: 'session',\n\t\tephemeralKeys: {\n\t\t\tpageId: false,\n\t\t\tselectedShapeIds: false,\n\t\t\teditingShapeId: false,\n\t\t\tcroppingShapeId: false,\n\t\t\tmeta: false,\n\n\t\t\thintingShapeIds: true,\n\t\t\terasingShapeIds: true,\n\t\t\thoveredShapeId: true,\n\t\t\tfocusedGroupId: true,\n\t\t},\n\t}\n).withDefaultProperties(\n\t(): Omit<TLInstancePageState, 'id' | 'typeName' | 'pageId'> => ({\n\t\teditingShapeId: null,\n\t\tcroppingShapeId: null,\n\t\tselectedShapeIds: [],\n\t\thoveredShapeId: null,\n\t\terasingShapeIds: [],\n\t\thintingShapeIds: [],\n\t\tfocusedGroupId: null,\n\t\tmeta: {},\n\t})\n)\n\n/**\n * A unique identifier for TLInstancePageState records.\n *\n * Instance page state IDs follow the format 'instance_page_state:' followed\n * by a unique identifier, typically related to the page ID.\n *\n * @example\n * ```ts\n * const stateId: TLInstancePageStateId = 'instance_page_state:page1'\n * ```\n *\n * @public\n */\nexport type TLInstancePageStateId = RecordId<TLInstancePageState>\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../src/recordsWithProps.ts"],
|
|
4
|
-
"sourcesContent": ["import {\n\tMigration,\n\tMigrationId,\n\tMigrationSequence,\n\tRecordType,\n\tStandaloneDependsOn,\n\tUnknownRecord,\n\tcreateMigrationSequence,\n} from '@tldraw/store'\nimport { MakeUndefinedOptional, assert } from '@tldraw/utils'\nimport { T } from '@tldraw/validate'\nimport { SchemaPropsInfo } from './createTLSchema'\n\n/**\n * Maps a record's property types to their corresponding validators.\n *\n * This utility type takes a record type with a `props` object and creates\n * a mapping where each property key maps to a validator for that property's type.\n * This is used to define validation schemas for record properties.\n *\n * @example\n * ```ts\n * interface MyShape extends TLBaseShape<'custom', { width: number; color: string }> {}\n *\n * // Define validators for the shape properties\n * const myShapeProps: RecordProps<MyShape> = {\n * width: T.number,\n * color: T.string\n * }\n * ```\n *\n * @public\n */\nexport type RecordProps<R extends UnknownRecord & { props: object }> = {\n\t[K in keyof R['props']]: T.Validatable<R['props'][K]>\n}\n\n/**\n * Extracts the TypeScript types from a record properties configuration.\n *\n * Takes a configuration object where values are validators and returns the\n * corresponding TypeScript types, with undefined values made optional.\n *\n * @example\n * ```ts\n * const shapePropsConfig = {\n * width: T.number,\n * height: T.number,\n * color: T.optional(T.string)\n * }\n *\n * type ShapeProps = RecordPropsType<typeof shapePropsConfig>\n * // Result: { width: number; height: number; color?: string }\n * ```\n *\n * @public\n */\nexport type RecordPropsType<Config extends Record<string, T.Validatable<any>>> =\n\tMakeUndefinedOptional<{\n\t\t[K in keyof Config]: T.TypeOf<Config[K]>\n\t}>\n\n/**\n * A migration definition for shape or record properties.\n *\n * Defines how to transform record properties when migrating between schema versions.\n * Each migration has an `up` function to upgrade data and an optional `down` function\n * to downgrade data if needed.\n *\n * @example\n * ```ts\n * const addColorMigration: TLPropsMigration = {\n * id: 'com.myapp.shape.custom/1.0.0',\n * up: (props) => {\n * // Add a default color property\n * return { ...props, color: 'black' }\n * },\n * down: (props) => {\n * // Remove the color property\n * const { color, ...rest } = props\n * return rest\n * }\n * }\n * ```\n *\n * @public\n */\nexport interface TLPropsMigration {\n\treadonly id: MigrationId\n\treadonly dependsOn?: MigrationId[]\n\t// eslint-disable-next-line
|
|
4
|
+
"sourcesContent": ["import {\n\tMigration,\n\tMigrationId,\n\tMigrationSequence,\n\tRecordType,\n\tStandaloneDependsOn,\n\tUnknownRecord,\n\tcreateMigrationSequence,\n} from '@tldraw/store'\nimport { MakeUndefinedOptional, assert } from '@tldraw/utils'\nimport { T } from '@tldraw/validate'\nimport { SchemaPropsInfo } from './createTLSchema'\n\n/**\n * Maps a record's property types to their corresponding validators.\n *\n * This utility type takes a record type with a `props` object and creates\n * a mapping where each property key maps to a validator for that property's type.\n * This is used to define validation schemas for record properties.\n *\n * @example\n * ```ts\n * interface MyShape extends TLBaseShape<'custom', { width: number; color: string }> {}\n *\n * // Define validators for the shape properties\n * const myShapeProps: RecordProps<MyShape> = {\n * width: T.number,\n * color: T.string\n * }\n * ```\n *\n * @public\n */\nexport type RecordProps<R extends UnknownRecord & { props: object }> = {\n\t[K in keyof R['props']]: T.Validatable<R['props'][K]>\n}\n\n/**\n * Extracts the TypeScript types from a record properties configuration.\n *\n * Takes a configuration object where values are validators and returns the\n * corresponding TypeScript types, with undefined values made optional.\n *\n * @example\n * ```ts\n * const shapePropsConfig = {\n * width: T.number,\n * height: T.number,\n * color: T.optional(T.string)\n * }\n *\n * type ShapeProps = RecordPropsType<typeof shapePropsConfig>\n * // Result: { width: number; height: number; color?: string }\n * ```\n *\n * @public\n */\nexport type RecordPropsType<Config extends Record<string, T.Validatable<any>>> =\n\tMakeUndefinedOptional<{\n\t\t[K in keyof Config]: T.TypeOf<Config[K]>\n\t}>\n\n/**\n * A migration definition for shape or record properties.\n *\n * Defines how to transform record properties when migrating between schema versions.\n * Each migration has an `up` function to upgrade data and an optional `down` function\n * to downgrade data if needed.\n *\n * @example\n * ```ts\n * const addColorMigration: TLPropsMigration = {\n * id: 'com.myapp.shape.custom/1.0.0',\n * up: (props) => {\n * // Add a default color property\n * return { ...props, color: 'black' }\n * },\n * down: (props) => {\n * // Remove the color property\n * const { color, ...rest } = props\n * return rest\n * }\n * }\n * ```\n *\n * @public\n */\nexport interface TLPropsMigration {\n\treadonly id: MigrationId\n\treadonly dependsOn?: MigrationId[]\n\t// eslint-disable-next-line tldraw/method-signature-style\n\treadonly up: (props: any) => any\n\t/**\n\t * If a down migration was deployed more than a couple of months ago it should be safe to retire it.\n\t * We only really need them to smooth over the transition between versions, and some folks do keep\n\t * browser tabs open for months without refreshing, but at a certain point that kind of behavior is\n\t * on them. Plus anyway recently chrome has started to actually kill tabs that are open for too long\n\t * rather than just suspending them, so if other browsers follow suit maybe it's less of a concern.\n\t *\n\t * @public\n\t */\n\treadonly down?: 'none' | 'retired' | ((props: any) => any)\n}\n\n/**\n * A sequence of property migrations for a record type.\n *\n * Contains an ordered array of migrations that should be applied to transform\n * record properties from one version to another. Migrations can include both\n * property-specific migrations and standalone dependency declarations.\n *\n * @example\n * ```ts\n * const myShapeMigrations: TLPropsMigrations = {\n * sequence: [\n * {\n * id: 'com.myapp.shape.custom/1.0.0',\n * up: (props) => ({ ...props, version: 1 })\n * },\n * {\n * id: 'com.myapp.shape.custom/2.0.0',\n * up: (props) => ({ ...props, newFeature: true })\n * }\n * ]\n * }\n * ```\n *\n * @public\n */\nexport interface TLPropsMigrations {\n\treadonly sequence: Array<StandaloneDependsOn | TLPropsMigration>\n}\n\n/**\n * Processes property migrations for all record types in a schema.\n *\n * Takes a collection of record configurations and converts their migrations\n * into proper migration sequences that can be used by the store system.\n * Handles different migration formats including legacy migrations.\n *\n * @param typeName - The base type name for the records (e.g., 'shape', 'binding')\n * @param records - Record of type names to their schema configuration\n * @returns Array of processed migration sequences\n *\n * @example\n * ```ts\n * const shapeRecords = {\n * geo: { props: geoProps, migrations: geoMigrations },\n * arrow: { props: arrowProps, migrations: arrowMigrations }\n * }\n *\n * const sequences = processPropsMigrations('shape', shapeRecords)\n * ```\n *\n * @internal\n */\nexport function processPropsMigrations<R extends UnknownRecord & { type: string; props: object }>(\n\ttypeName: R['typeName'],\n\trecords: Record<string, SchemaPropsInfo>\n) {\n\tconst result: MigrationSequence[] = []\n\n\tfor (const [subType, { migrations }] of Object.entries(records)) {\n\t\tconst sequenceId = `com.tldraw.${typeName}.${subType}`\n\t\tif (!migrations) {\n\t\t\t// provide empty migrations sequence to allow for future migrations\n\t\t\tresult.push(\n\t\t\t\tcreateMigrationSequence({\n\t\t\t\t\tsequenceId,\n\t\t\t\t\tretroactive: true,\n\t\t\t\t\tsequence: [],\n\t\t\t\t})\n\t\t\t)\n\t\t} else if ('sequenceId' in migrations) {\n\t\t\tassert(\n\t\t\t\tsequenceId === migrations.sequenceId,\n\t\t\t\t`sequenceId mismatch for ${subType} ${RecordType} migrations. Expected '${sequenceId}', got '${migrations.sequenceId}'`\n\t\t\t)\n\t\t\tresult.push(migrations)\n\t\t} else if ('sequence' in migrations) {\n\t\t\tresult.push(\n\t\t\t\tcreateMigrationSequence({\n\t\t\t\t\tsequenceId,\n\t\t\t\t\tretroactive: true,\n\t\t\t\t\tsequence: migrations.sequence.map((m) =>\n\t\t\t\t\t\t'id' in m ? createPropsMigration(typeName, subType, m) : m\n\t\t\t\t\t),\n\t\t\t\t})\n\t\t\t)\n\t\t} else {\n\t\t\t// legacy migrations, will be removed in the future\n\t\t\tresult.push(\n\t\t\t\tcreateMigrationSequence({\n\t\t\t\t\tsequenceId,\n\t\t\t\t\tretroactive: true,\n\t\t\t\t\tsequence: Object.keys(migrations.migrators)\n\t\t\t\t\t\t.map((k) => Number(k))\n\t\t\t\t\t\t.sort((a: number, b: number) => a - b)\n\t\t\t\t\t\t.map(\n\t\t\t\t\t\t\t(version): Migration => ({\n\t\t\t\t\t\t\t\tid: `${sequenceId}/${version}`,\n\t\t\t\t\t\t\t\tscope: 'record',\n\t\t\t\t\t\t\t\tfilter: (r) => r.typeName === typeName && (r as R).type === subType,\n\t\t\t\t\t\t\t\tup: (record: any) => {\n\t\t\t\t\t\t\t\t\tconst result = migrations.migrators[version].up(record)\n\t\t\t\t\t\t\t\t\tif (result) {\n\t\t\t\t\t\t\t\t\t\treturn result\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\tdown: (record: any) => {\n\t\t\t\t\t\t\t\t\tconst result = migrations.migrators[version].down(record)\n\t\t\t\t\t\t\t\t\tif (result) {\n\t\t\t\t\t\t\t\t\t\treturn result\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t})\n\t\t\t\t\t\t),\n\t\t\t\t})\n\t\t\t)\n\t\t}\n\t}\n\n\treturn result\n}\n\n/**\n * Creates a store migration from a props migration definition.\n *\n * Converts a high-level property migration into a low-level store migration\n * that can be applied to records. The resulting migration will only affect\n * records of the specified type and subtype.\n *\n * @param typeName - The base type name (e.g., 'shape', 'binding')\n * @param subType - The specific subtype (e.g., 'geo', 'arrow')\n * @param m - The property migration definition\n * @returns A store migration that applies the property transformation\n *\n * @example\n * ```ts\n * const propsMigration: TLPropsMigration = {\n * id: 'com.myapp.shape.custom/1.0.0',\n * up: (props) => ({ ...props, color: 'blue' })\n * }\n *\n * const storeMigration = createPropsMigration('shape', 'custom', propsMigration)\n * ```\n *\n * @internal\n */\nexport function createPropsMigration<R extends UnknownRecord & { type: string; props: object }>(\n\ttypeName: R['typeName'],\n\tsubType: R['type'],\n\tm: TLPropsMigration\n): Migration {\n\treturn {\n\t\tid: m.id,\n\t\tdependsOn: m.dependsOn,\n\t\tscope: 'record',\n\t\tfilter: (r) => r.typeName === typeName && (r as R).type === subType,\n\t\tup: (record: any) => {\n\t\t\tconst result = m.up(record.props)\n\t\t\tif (result) {\n\t\t\t\trecord.props = result\n\t\t\t}\n\t\t},\n\t\tdown:\n\t\t\ttypeof m.down === 'function'\n\t\t\t\t? (record: any) => {\n\t\t\t\t\t\tconst result = (m.down as (props: any) => any)(record.props)\n\t\t\t\t\t\tif (result) {\n\t\t\t\t\t\t\trecord.props = result\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t: undefined,\n\t}\n}\n"],
|
|
5
5
|
"mappings": ";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,mBAQO;AACP,mBAA8C;AAmJvC,SAAS,uBACf,UACA,SACC;AACD,QAAM,SAA8B,CAAC;AAErC,aAAW,CAAC,SAAS,EAAE,WAAW,CAAC,KAAK,OAAO,QAAQ,OAAO,GAAG;AAChE,UAAM,aAAa,cAAc,QAAQ,IAAI,OAAO;AACpD,QAAI,CAAC,YAAY;AAEhB,aAAO;AAAA,YACN,sCAAwB;AAAA,UACvB;AAAA,UACA,aAAa;AAAA,UACb,UAAU,CAAC;AAAA,QACZ,CAAC;AAAA,MACF;AAAA,IACD,WAAW,gBAAgB,YAAY;AACtC;AAAA,QACC,eAAe,WAAW;AAAA,QAC1B,2BAA2B,OAAO,IAAI,uBAAU,0BAA0B,UAAU,WAAW,WAAW,UAAU;AAAA,MACrH;AACA,aAAO,KAAK,UAAU;AAAA,IACvB,WAAW,cAAc,YAAY;AACpC,aAAO;AAAA,YACN,sCAAwB;AAAA,UACvB;AAAA,UACA,aAAa;AAAA,UACb,UAAU,WAAW,SAAS;AAAA,YAAI,CAAC,MAClC,QAAQ,IAAI,qBAAqB,UAAU,SAAS,CAAC,IAAI;AAAA,UAC1D;AAAA,QACD,CAAC;AAAA,MACF;AAAA,IACD,OAAO;AAEN,aAAO;AAAA,YACN,sCAAwB;AAAA,UACvB;AAAA,UACA,aAAa;AAAA,UACb,UAAU,OAAO,KAAK,WAAW,SAAS,EACxC,IAAI,CAAC,MAAM,OAAO,CAAC,CAAC,EACpB,KAAK,CAAC,GAAW,MAAc,IAAI,CAAC,EACpC;AAAA,YACA,CAAC,aAAwB;AAAA,cACxB,IAAI,GAAG,UAAU,IAAI,OAAO;AAAA,cAC5B,OAAO;AAAA,cACP,QAAQ,CAAC,MAAM,EAAE,aAAa,YAAa,EAAQ,SAAS;AAAA,cAC5D,IAAI,CAAC,WAAgB;AACpB,sBAAMA,UAAS,WAAW,UAAU,OAAO,EAAE,GAAG,MAAM;AACtD,oBAAIA,SAAQ;AACX,yBAAOA;AAAA,gBACR;AAAA,cACD;AAAA,cACA,MAAM,CAAC,WAAgB;AACtB,sBAAMA,UAAS,WAAW,UAAU,OAAO,EAAE,KAAK,MAAM;AACxD,oBAAIA,SAAQ;AACX,yBAAOA;AAAA,gBACR;AAAA,cACD;AAAA,YACD;AAAA,UACD;AAAA,QACF,CAAC;AAAA,MACF;AAAA,IACD;AAAA,EACD;AAEA,SAAO;AACR;AA0BO,SAAS,qBACf,UACA,SACA,GACY;AACZ,SAAO;AAAA,IACN,IAAI,EAAE;AAAA,IACN,WAAW,EAAE;AAAA,IACb,OAAO;AAAA,IACP,QAAQ,CAAC,MAAM,EAAE,aAAa,YAAa,EAAQ,SAAS;AAAA,IAC5D,IAAI,CAAC,WAAgB;AACpB,YAAM,SAAS,EAAE,GAAG,OAAO,KAAK;AAChC,UAAI,QAAQ;AACX,eAAO,QAAQ;AAAA,MAChB;AAAA,IACD;AAAA,IACA,MACC,OAAO,EAAE,SAAS,aACf,CAAC,WAAgB;AACjB,YAAM,SAAU,EAAE,KAA6B,OAAO,KAAK;AAC3D,UAAI,QAAQ;AACX,eAAO,QAAQ;AAAA,MAChB;AAAA,IACD,IACC;AAAA,EACL;AACD;",
|
|
6
6
|
"names": ["result"]
|
|
7
7
|
}
|
|
@@ -29,8 +29,8 @@ module.exports = __toCommonJS(TLArrowShape_exports);
|
|
|
29
29
|
var import_store = require("@tldraw/store");
|
|
30
30
|
var import_utils = require("@tldraw/utils");
|
|
31
31
|
var import_validate = require("@tldraw/validate");
|
|
32
|
-
var import_TLRichText = require("../misc/TLRichText");
|
|
33
32
|
var import_geometry_types = require("../misc/geometry-types");
|
|
33
|
+
var import_TLRichText = require("../misc/TLRichText");
|
|
34
34
|
var import_TLBinding = require("../records/TLBinding");
|
|
35
35
|
var import_TLShape = require("../records/TLShape");
|
|
36
36
|
var import_recordsWithProps = require("../recordsWithProps");
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../src/shapes/TLArrowShape.ts"],
|
|
4
|
-
"sourcesContent": ["import { createMigrationSequence } from '@tldraw/store'\nimport { structuredClone } from '@tldraw/utils'\nimport { T } from '@tldraw/validate'\nimport { TLRichText, richTextValidator, toRichText } from '../misc/TLRichText'\nimport { VecModel, vecModelValidator } from '../misc/geometry-types'\nimport { createBindingId } from '../records/TLBinding'\nimport { TLShape, TLShapeId, createShapePropsMigrationIds } from '../records/TLShape'\nimport { RecordProps, TLPropsMigration, createPropsMigration } from '../recordsWithProps'\nimport { StyleProp } from '../styles/StyleProp'\nimport {\n\tDefaultColorStyle,\n\tDefaultLabelColorStyle,\n\tTLDefaultColorStyle,\n} from '../styles/TLColorStyle'\nimport { DefaultDashStyle, TLDefaultDashStyle } from '../styles/TLDashStyle'\nimport { DefaultFillStyle, TLDefaultFillStyle } from '../styles/TLFillStyle'\nimport { DefaultFontStyle, TLDefaultFontStyle } from '../styles/TLFontStyle'\nimport { DefaultSizeStyle, TLDefaultSizeStyle } from '../styles/TLSizeStyle'\nimport { TLBaseShape } from './TLBaseShape'\n\nconst arrowKinds = ['arc', 'elbow'] as const\n/**\n * Style property for arrow shape kind, determining how the arrow is drawn.\n *\n * Arrows can be drawn as arcs (curved) or elbows (angled with straight segments).\n * This affects the visual appearance and behavior of arrow shapes.\n *\n * @example\n * ```ts\n * // Create an arrow with arc style (curved)\n * const arcArrow: TLArrowShape = {\n * // ... other properties\n * props: {\n * kind: 'arc',\n * // ... other props\n * }\n * }\n *\n * // Create an arrow with elbow style (angled)\n * const elbowArrow: TLArrowShape = {\n * // ... other properties\n * props: {\n * kind: 'elbow',\n * // ... other props\n * }\n * }\n * ```\n *\n * @public\n */\nexport const ArrowShapeKindStyle = StyleProp.defineEnum('tldraw:arrowKind', {\n\tdefaultValue: 'arc',\n\tvalues: arrowKinds,\n})\n\n/**\n * The type representing arrow shape kinds.\n *\n * @public\n */\nexport type TLArrowShapeKind = T.TypeOf<typeof ArrowShapeKindStyle>\n\nconst arrowheadTypes = [\n\t'arrow',\n\t'triangle',\n\t'square',\n\t'dot',\n\t'pipe',\n\t'diamond',\n\t'inverted',\n\t'bar',\n\t'none',\n] as const\n\n/**\n * Style property for the arrowhead at the start of an arrow.\n *\n * Defines the visual style of the arrowhead at the beginning of the arrow path.\n * Can be one of several predefined styles or none for no arrowhead.\n *\n * @example\n * ```ts\n * // Arrow with no start arrowhead but triangle end arrowhead\n * const arrow: TLArrowShape = {\n * // ... other properties\n * props: {\n * arrowheadStart: 'none',\n * arrowheadEnd: 'triangle',\n * // ... other props\n * }\n * }\n * ```\n *\n * @public\n */\nexport const ArrowShapeArrowheadStartStyle = StyleProp.defineEnum('tldraw:arrowheadStart', {\n\tdefaultValue: 'none',\n\tvalues: arrowheadTypes,\n})\n\n/**\n * Style property for the arrowhead at the end of an arrow.\n *\n * Defines the visual style of the arrowhead at the end of the arrow path.\n * Defaults to 'arrow' style, giving arrows their characteristic pointed appearance.\n *\n * @example\n * ```ts\n * // Arrow with different start and end arrowheads\n * const doubleArrow: TLArrowShape = {\n * // ... other properties\n * props: {\n * arrowheadStart: 'triangle',\n * arrowheadEnd: 'diamond',\n * // ... other props\n * }\n * }\n * ```\n *\n * @public\n */\nexport const ArrowShapeArrowheadEndStyle = StyleProp.defineEnum('tldraw:arrowheadEnd', {\n\tdefaultValue: 'arrow',\n\tvalues: arrowheadTypes,\n})\n\n/**\n * The type representing arrowhead styles for both start and end of arrows.\n *\n * @public\n */\nexport type TLArrowShapeArrowheadStyle = T.TypeOf<typeof ArrowShapeArrowheadStartStyle>\n\n/**\n * Properties specific to arrow shapes.\n *\n * Defines all the configurable aspects of an arrow shape, including visual styling,\n * geometry, text labeling, and positioning. Arrows can connect two points and\n * optionally display text labels.\n *\n * @example\n * ```ts\n * const arrowProps: TLArrowShapeProps = {\n * kind: 'arc',\n * labelColor: 'black',\n * color: 'blue',\n * fill: 'none',\n * dash: 'solid',\n * size: 'm',\n * arrowheadStart: 'none',\n * arrowheadEnd: 'arrow',\n * font: 'draw',\n * start: { x: 0, y: 0 },\n * end: { x: 100, y: 100 },\n * bend: 0.2,\n * richText: toRichText('Label'),\n * labelPosition: 0.5,\n * scale: 1,\n * elbowMidPoint: 0.5\n * }\n * ```\n *\n * @public\n */\nexport interface TLArrowShapeProps {\n\tkind: TLArrowShapeKind\n\tlabelColor: TLDefaultColorStyle\n\tcolor: TLDefaultColorStyle\n\tfill: TLDefaultFillStyle\n\tdash: TLDefaultDashStyle\n\tsize: TLDefaultSizeStyle\n\tarrowheadStart: TLArrowShapeArrowheadStyle\n\tarrowheadEnd: TLArrowShapeArrowheadStyle\n\tfont: TLDefaultFontStyle\n\tstart: VecModel\n\tend: VecModel\n\tbend: number\n\trichText: TLRichText\n\tlabelPosition: number\n\tscale: number\n\telbowMidPoint: number\n}\n\n/**\n * A complete arrow shape record.\n *\n * Combines the base shape interface with arrow-specific properties to create\n * a full arrow shape that can be stored and manipulated in the editor.\n *\n * @example\n * ```ts\n * const arrowShape: TLArrowShape = {\n * id: 'shape:arrow123',\n * typeName: 'shape',\n * type: 'arrow',\n * x: 100,\n * y: 200,\n * rotation: 0,\n * index: 'a1',\n * parentId: 'page:main',\n * isLocked: false,\n * opacity: 1,\n * props: {\n * kind: 'arc',\n * start: { x: 0, y: 0 },\n * end: { x: 150, y: 100 },\n * // ... other props\n * },\n * meta: {}\n * }\n * ```\n *\n * @public\n */\nexport type TLArrowShape = TLBaseShape<'arrow', TLArrowShapeProps>\n\n/**\n * Validation configuration for arrow shape properties.\n *\n * Defines the validators for each property of an arrow shape, ensuring that\n * arrow shape data is valid and conforms to the expected types and constraints.\n *\n * @example\n * ```ts\n * // The validators ensure proper typing and validation\n * const validator = T.object(arrowShapeProps)\n * const validArrowProps = validator.validate({\n * kind: 'arc',\n * start: { x: 0, y: 0 },\n * end: { x: 100, y: 50 },\n * // ... other required properties\n * })\n * ```\n *\n * @public\n */\nexport const arrowShapeProps: RecordProps<TLArrowShape> = {\n\tkind: ArrowShapeKindStyle,\n\tlabelColor: DefaultLabelColorStyle,\n\tcolor: DefaultColorStyle,\n\tfill: DefaultFillStyle,\n\tdash: DefaultDashStyle,\n\tsize: DefaultSizeStyle,\n\tarrowheadStart: ArrowShapeArrowheadStartStyle,\n\tarrowheadEnd: ArrowShapeArrowheadEndStyle,\n\tfont: DefaultFontStyle,\n\tstart: vecModelValidator,\n\tend: vecModelValidator,\n\tbend: T.number,\n\trichText: richTextValidator,\n\tlabelPosition: T.number,\n\tscale: T.nonZeroNumber,\n\telbowMidPoint: T.number,\n}\n\n/**\n * Migration version identifiers for arrow shape properties.\n *\n * These track the evolution of the arrow shape schema over time, with each\n * version representing a specific change to the arrow shape structure or properties.\n *\n * @example\n * ```ts\n * // Used internally for migration system\n * if (version < arrowShapeVersions.AddLabelColor) {\n * // Apply label color migration\n * }\n * ```\n *\n * @public\n */\nexport const arrowShapeVersions = createShapePropsMigrationIds('arrow', {\n\tAddLabelColor: 1,\n\tAddIsPrecise: 2,\n\tAddLabelPosition: 3,\n\tExtractBindings: 4,\n\tAddScale: 5,\n\tAddElbow: 6,\n\tAddRichText: 7,\n\tAddRichTextAttrs: 8,\n})\n\nfunction propsMigration(migration: TLPropsMigration) {\n\treturn createPropsMigration<TLArrowShape>('shape', 'arrow', migration)\n}\n\n/**\n * Complete migration sequence for arrow shapes.\n *\n * Defines all the migrations needed to transform arrow shape data from older\n * versions to the current version. Each migration handles a specific schema change,\n * ensuring backward compatibility and smooth data evolution.\n *\n * @public\n */\nexport const arrowShapeMigrations = createMigrationSequence({\n\tsequenceId: 'com.tldraw.shape.arrow',\n\tretroactive: false,\n\tsequence: [\n\t\tpropsMigration({\n\t\t\tid: arrowShapeVersions.AddLabelColor,\n\t\t\tup: (props) => {\n\t\t\t\tprops.labelColor = 'black'\n\t\t\t},\n\t\t\tdown: 'retired',\n\t\t}),\n\n\t\tpropsMigration({\n\t\t\tid: arrowShapeVersions.AddIsPrecise,\n\t\t\tup: ({ start, end }) => {\n\t\t\t\tif (start.type === 'binding') {\n\t\t\t\t\tstart.isPrecise = !(start.normalizedAnchor.x === 0.5 && start.normalizedAnchor.y === 0.5)\n\t\t\t\t}\n\t\t\t\tif (end.type === 'binding') {\n\t\t\t\t\tend.isPrecise = !(end.normalizedAnchor.x === 0.5 && end.normalizedAnchor.y === 0.5)\n\t\t\t\t}\n\t\t\t},\n\t\t\tdown: ({ start, end }) => {\n\t\t\t\tif (start.type === 'binding') {\n\t\t\t\t\tif (!start.isPrecise) {\n\t\t\t\t\t\tstart.normalizedAnchor = { x: 0.5, y: 0.5 }\n\t\t\t\t\t}\n\t\t\t\t\tdelete start.isPrecise\n\t\t\t\t}\n\t\t\t\tif (end.type === 'binding') {\n\t\t\t\t\tif (!end.isPrecise) {\n\t\t\t\t\t\tend.normalizedAnchor = { x: 0.5, y: 0.5 }\n\t\t\t\t\t}\n\t\t\t\t\tdelete end.isPrecise\n\t\t\t\t}\n\t\t\t},\n\t\t}),\n\n\t\tpropsMigration({\n\t\t\tid: arrowShapeVersions.AddLabelPosition,\n\t\t\tup: (props) => {\n\t\t\t\tprops.labelPosition = 0.5\n\t\t\t},\n\t\t\tdown: (props) => {\n\t\t\t\tdelete props.labelPosition\n\t\t\t},\n\t\t}),\n\n\t\t{\n\t\t\tid: arrowShapeVersions.ExtractBindings,\n\t\t\tscope: 'storage',\n\t\t\tup: (storage) => {\n\t\t\t\ttype OldArrowTerminal =\n\t\t\t\t\t| {\n\t\t\t\t\t\t\ttype: 'point'\n\t\t\t\t\t\t\tx: number\n\t\t\t\t\t\t\ty: number\n\t\t\t\t\t }\n\t\t\t\t\t| {\n\t\t\t\t\t\t\ttype: 'binding'\n\t\t\t\t\t\t\tboundShapeId: TLShapeId\n\t\t\t\t\t\t\tnormalizedAnchor: VecModel\n\t\t\t\t\t\t\tisExact: boolean\n\t\t\t\t\t\t\tisPrecise: boolean\n\t\t\t\t\t }\n\t\t\t\t\t// new type:\n\t\t\t\t\t| { type?: undefined; x: number; y: number }\n\n\t\t\t\ttype OldArrow = TLBaseShape<'arrow', { start: OldArrowTerminal; end: OldArrowTerminal }>\n\n\t\t\t\t// Collect all updates during iteration, then apply them after.\n\t\t\t\t// This avoids issues with live iterators (e.g., SQLite) where updating\n\t\t\t\t// records during iteration can cause them to be visited multiple times.\n\t\t\t\tconst updates: [string, unknown][] = []\n\n\t\t\t\tfor (const record of storage.values()) {\n\t\t\t\t\tif (record.typeName !== 'shape' || (record as TLShape).type !== 'arrow') continue\n\t\t\t\t\tconst arrow = record as OldArrow\n\t\t\t\t\tconst newArrow = structuredClone(arrow)\n\t\t\t\t\tconst { start, end } = arrow.props\n\t\t\t\t\tif (start.type === 'binding') {\n\t\t\t\t\t\tconst id = createBindingId()\n\t\t\t\t\t\tconst binding = {\n\t\t\t\t\t\t\ttypeName: 'binding',\n\t\t\t\t\t\t\tid,\n\t\t\t\t\t\t\ttype: 'arrow',\n\t\t\t\t\t\t\tfromId: arrow.id,\n\t\t\t\t\t\t\ttoId: start.boundShapeId,\n\t\t\t\t\t\t\tmeta: {},\n\t\t\t\t\t\t\tprops: {\n\t\t\t\t\t\t\t\tterminal: 'start',\n\t\t\t\t\t\t\t\tnormalizedAnchor: start.normalizedAnchor,\n\t\t\t\t\t\t\t\tisExact: start.isExact,\n\t\t\t\t\t\t\t\tisPrecise: start.isPrecise,\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tupdates.push([id, binding])\n\t\t\t\t\t\tnewArrow.props.start = { x: 0, y: 0 }\n\t\t\t\t\t} else {\n\t\t\t\t\t\tdelete newArrow.props.start.type\n\t\t\t\t\t}\n\t\t\t\t\tif (end.type === 'binding') {\n\t\t\t\t\t\tconst id = createBindingId()\n\t\t\t\t\t\tconst binding = {\n\t\t\t\t\t\t\ttypeName: 'binding',\n\t\t\t\t\t\t\tid,\n\t\t\t\t\t\t\ttype: 'arrow',\n\t\t\t\t\t\t\tfromId: arrow.id,\n\t\t\t\t\t\t\ttoId: end.boundShapeId,\n\t\t\t\t\t\t\tmeta: {},\n\t\t\t\t\t\t\tprops: {\n\t\t\t\t\t\t\t\tterminal: 'end',\n\t\t\t\t\t\t\t\tnormalizedAnchor: end.normalizedAnchor,\n\t\t\t\t\t\t\t\tisExact: end.isExact,\n\t\t\t\t\t\t\t\tisPrecise: end.isPrecise,\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tupdates.push([id, binding])\n\t\t\t\t\t\tnewArrow.props.end = { x: 0, y: 0 }\n\t\t\t\t\t} else {\n\t\t\t\t\t\tdelete newArrow.props.end.type\n\t\t\t\t\t}\n\t\t\t\t\tupdates.push([arrow.id, newArrow])\n\t\t\t\t}\n\n\t\t\t\tfor (const [id, record] of updates) {\n\t\t\t\t\tstorage.set(id, record as any)\n\t\t\t\t}\n\t\t\t},\n\t\t},\n\t\tpropsMigration({\n\t\t\tid: arrowShapeVersions.AddScale,\n\t\t\tup: (props) => {\n\t\t\t\tprops.scale = 1\n\t\t\t},\n\t\t\tdown: (props) => {\n\t\t\t\tdelete props.scale\n\t\t\t},\n\t\t}),\n\t\tpropsMigration({\n\t\t\tid: arrowShapeVersions.AddElbow,\n\t\t\tup: (props) => {\n\t\t\t\tprops.kind = 'arc'\n\t\t\t\tprops.elbowMidPoint = 0.5\n\t\t\t},\n\t\t\tdown: (props) => {\n\t\t\t\tdelete props.kind\n\t\t\t\tdelete props.elbowMidPoint\n\t\t\t},\n\t\t}),\n\t\tpropsMigration({\n\t\t\tid: arrowShapeVersions.AddRichText,\n\t\t\tup: (props) => {\n\t\t\t\tprops.richText = toRichText(props.text)\n\t\t\t\tdelete props.text\n\t\t\t},\n\t\t\t// N.B. Explicitly no down state so that we force clients to update.\n\t\t\t// down: (props) => {\n\t\t\t// \tdelete props.richText\n\t\t\t// },\n\t\t}),\n\t\tpropsMigration({\n\t\t\tid: arrowShapeVersions.AddRichTextAttrs,\n\t\t\tup: (_props) => {\n\t\t\t\t// noop - attrs is optional so old records are valid\n\t\t\t},\n\t\t\tdown: (props) => {\n\t\t\t\t// Remove attrs from richText when migrating down\n\t\t\t\tif (props.richText && 'attrs' in props.richText) {\n\t\t\t\t\tdelete props.richText.attrs\n\t\t\t\t}\n\t\t\t},\n\t\t}),\n\t],\n})\n"],
|
|
5
|
-
"mappings": ";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,mBAAwC;AACxC,mBAAgC;AAChC,sBAAkB;AAClB,wBAA0D;AAC1D,
|
|
4
|
+
"sourcesContent": ["import { createMigrationSequence } from '@tldraw/store'\nimport { structuredClone } from '@tldraw/utils'\nimport { T } from '@tldraw/validate'\nimport { VecModel, vecModelValidator } from '../misc/geometry-types'\nimport { TLRichText, richTextValidator, toRichText } from '../misc/TLRichText'\nimport { createBindingId } from '../records/TLBinding'\nimport { TLShape, TLShapeId, createShapePropsMigrationIds } from '../records/TLShape'\nimport { RecordProps, TLPropsMigration, createPropsMigration } from '../recordsWithProps'\nimport { StyleProp } from '../styles/StyleProp'\nimport {\n\tDefaultColorStyle,\n\tDefaultLabelColorStyle,\n\tTLDefaultColorStyle,\n} from '../styles/TLColorStyle'\nimport { DefaultDashStyle, TLDefaultDashStyle } from '../styles/TLDashStyle'\nimport { DefaultFillStyle, TLDefaultFillStyle } from '../styles/TLFillStyle'\nimport { DefaultFontStyle, TLDefaultFontStyle } from '../styles/TLFontStyle'\nimport { DefaultSizeStyle, TLDefaultSizeStyle } from '../styles/TLSizeStyle'\nimport { TLBaseShape } from './TLBaseShape'\n\nconst arrowKinds = ['arc', 'elbow'] as const\n/**\n * Style property for arrow shape kind, determining how the arrow is drawn.\n *\n * Arrows can be drawn as arcs (curved) or elbows (angled with straight segments).\n * This affects the visual appearance and behavior of arrow shapes.\n *\n * @example\n * ```ts\n * // Create an arrow with arc style (curved)\n * const arcArrow: TLArrowShape = {\n * // ... other properties\n * props: {\n * kind: 'arc',\n * // ... other props\n * }\n * }\n *\n * // Create an arrow with elbow style (angled)\n * const elbowArrow: TLArrowShape = {\n * // ... other properties\n * props: {\n * kind: 'elbow',\n * // ... other props\n * }\n * }\n * ```\n *\n * @public\n */\nexport const ArrowShapeKindStyle = StyleProp.defineEnum('tldraw:arrowKind', {\n\tdefaultValue: 'arc',\n\tvalues: arrowKinds,\n})\n\n/**\n * The type representing arrow shape kinds.\n *\n * @public\n */\nexport type TLArrowShapeKind = T.TypeOf<typeof ArrowShapeKindStyle>\n\nconst arrowheadTypes = [\n\t'arrow',\n\t'triangle',\n\t'square',\n\t'dot',\n\t'pipe',\n\t'diamond',\n\t'inverted',\n\t'bar',\n\t'none',\n] as const\n\n/**\n * Style property for the arrowhead at the start of an arrow.\n *\n * Defines the visual style of the arrowhead at the beginning of the arrow path.\n * Can be one of several predefined styles or none for no arrowhead.\n *\n * @example\n * ```ts\n * // Arrow with no start arrowhead but triangle end arrowhead\n * const arrow: TLArrowShape = {\n * // ... other properties\n * props: {\n * arrowheadStart: 'none',\n * arrowheadEnd: 'triangle',\n * // ... other props\n * }\n * }\n * ```\n *\n * @public\n */\nexport const ArrowShapeArrowheadStartStyle = StyleProp.defineEnum('tldraw:arrowheadStart', {\n\tdefaultValue: 'none',\n\tvalues: arrowheadTypes,\n})\n\n/**\n * Style property for the arrowhead at the end of an arrow.\n *\n * Defines the visual style of the arrowhead at the end of the arrow path.\n * Defaults to 'arrow' style, giving arrows their characteristic pointed appearance.\n *\n * @example\n * ```ts\n * // Arrow with different start and end arrowheads\n * const doubleArrow: TLArrowShape = {\n * // ... other properties\n * props: {\n * arrowheadStart: 'triangle',\n * arrowheadEnd: 'diamond',\n * // ... other props\n * }\n * }\n * ```\n *\n * @public\n */\nexport const ArrowShapeArrowheadEndStyle = StyleProp.defineEnum('tldraw:arrowheadEnd', {\n\tdefaultValue: 'arrow',\n\tvalues: arrowheadTypes,\n})\n\n/**\n * The type representing arrowhead styles for both start and end of arrows.\n *\n * @public\n */\nexport type TLArrowShapeArrowheadStyle = T.TypeOf<typeof ArrowShapeArrowheadStartStyle>\n\n/**\n * Properties specific to arrow shapes.\n *\n * Defines all the configurable aspects of an arrow shape, including visual styling,\n * geometry, text labeling, and positioning. Arrows can connect two points and\n * optionally display text labels.\n *\n * @example\n * ```ts\n * const arrowProps: TLArrowShapeProps = {\n * kind: 'arc',\n * labelColor: 'black',\n * color: 'blue',\n * fill: 'none',\n * dash: 'solid',\n * size: 'm',\n * arrowheadStart: 'none',\n * arrowheadEnd: 'arrow',\n * font: 'draw',\n * start: { x: 0, y: 0 },\n * end: { x: 100, y: 100 },\n * bend: 0.2,\n * richText: toRichText('Label'),\n * labelPosition: 0.5,\n * scale: 1,\n * elbowMidPoint: 0.5\n * }\n * ```\n *\n * @public\n */\nexport interface TLArrowShapeProps {\n\tkind: TLArrowShapeKind\n\tlabelColor: TLDefaultColorStyle\n\tcolor: TLDefaultColorStyle\n\tfill: TLDefaultFillStyle\n\tdash: TLDefaultDashStyle\n\tsize: TLDefaultSizeStyle\n\tarrowheadStart: TLArrowShapeArrowheadStyle\n\tarrowheadEnd: TLArrowShapeArrowheadStyle\n\tfont: TLDefaultFontStyle\n\tstart: VecModel\n\tend: VecModel\n\tbend: number\n\trichText: TLRichText\n\tlabelPosition: number\n\tscale: number\n\telbowMidPoint: number\n}\n\n/**\n * A complete arrow shape record.\n *\n * Combines the base shape interface with arrow-specific properties to create\n * a full arrow shape that can be stored and manipulated in the editor.\n *\n * @example\n * ```ts\n * const arrowShape: TLArrowShape = {\n * id: 'shape:arrow123',\n * typeName: 'shape',\n * type: 'arrow',\n * x: 100,\n * y: 200,\n * rotation: 0,\n * index: 'a1',\n * parentId: 'page:main',\n * isLocked: false,\n * opacity: 1,\n * props: {\n * kind: 'arc',\n * start: { x: 0, y: 0 },\n * end: { x: 150, y: 100 },\n * // ... other props\n * },\n * meta: {}\n * }\n * ```\n *\n * @public\n */\nexport type TLArrowShape = TLBaseShape<'arrow', TLArrowShapeProps>\n\n/**\n * Validation configuration for arrow shape properties.\n *\n * Defines the validators for each property of an arrow shape, ensuring that\n * arrow shape data is valid and conforms to the expected types and constraints.\n *\n * @example\n * ```ts\n * // The validators ensure proper typing and validation\n * const validator = T.object(arrowShapeProps)\n * const validArrowProps = validator.validate({\n * kind: 'arc',\n * start: { x: 0, y: 0 },\n * end: { x: 100, y: 50 },\n * // ... other required properties\n * })\n * ```\n *\n * @public\n */\nexport const arrowShapeProps: RecordProps<TLArrowShape> = {\n\tkind: ArrowShapeKindStyle,\n\tlabelColor: DefaultLabelColorStyle,\n\tcolor: DefaultColorStyle,\n\tfill: DefaultFillStyle,\n\tdash: DefaultDashStyle,\n\tsize: DefaultSizeStyle,\n\tarrowheadStart: ArrowShapeArrowheadStartStyle,\n\tarrowheadEnd: ArrowShapeArrowheadEndStyle,\n\tfont: DefaultFontStyle,\n\tstart: vecModelValidator,\n\tend: vecModelValidator,\n\tbend: T.number,\n\trichText: richTextValidator,\n\tlabelPosition: T.number,\n\tscale: T.nonZeroNumber,\n\telbowMidPoint: T.number,\n}\n\n/**\n * Migration version identifiers for arrow shape properties.\n *\n * These track the evolution of the arrow shape schema over time, with each\n * version representing a specific change to the arrow shape structure or properties.\n *\n * @example\n * ```ts\n * // Used internally for migration system\n * if (version < arrowShapeVersions.AddLabelColor) {\n * // Apply label color migration\n * }\n * ```\n *\n * @public\n */\nexport const arrowShapeVersions = createShapePropsMigrationIds('arrow', {\n\tAddLabelColor: 1,\n\tAddIsPrecise: 2,\n\tAddLabelPosition: 3,\n\tExtractBindings: 4,\n\tAddScale: 5,\n\tAddElbow: 6,\n\tAddRichText: 7,\n\tAddRichTextAttrs: 8,\n})\n\nfunction propsMigration(migration: TLPropsMigration) {\n\treturn createPropsMigration<TLArrowShape>('shape', 'arrow', migration)\n}\n\n/**\n * Complete migration sequence for arrow shapes.\n *\n * Defines all the migrations needed to transform arrow shape data from older\n * versions to the current version. Each migration handles a specific schema change,\n * ensuring backward compatibility and smooth data evolution.\n *\n * @public\n */\nexport const arrowShapeMigrations = createMigrationSequence({\n\tsequenceId: 'com.tldraw.shape.arrow',\n\tretroactive: false,\n\tsequence: [\n\t\tpropsMigration({\n\t\t\tid: arrowShapeVersions.AddLabelColor,\n\t\t\tup: (props) => {\n\t\t\t\tprops.labelColor = 'black'\n\t\t\t},\n\t\t\tdown: 'retired',\n\t\t}),\n\n\t\tpropsMigration({\n\t\t\tid: arrowShapeVersions.AddIsPrecise,\n\t\t\tup: ({ start, end }) => {\n\t\t\t\tif (start.type === 'binding') {\n\t\t\t\t\tstart.isPrecise = !(start.normalizedAnchor.x === 0.5 && start.normalizedAnchor.y === 0.5)\n\t\t\t\t}\n\t\t\t\tif (end.type === 'binding') {\n\t\t\t\t\tend.isPrecise = !(end.normalizedAnchor.x === 0.5 && end.normalizedAnchor.y === 0.5)\n\t\t\t\t}\n\t\t\t},\n\t\t\tdown: ({ start, end }) => {\n\t\t\t\tif (start.type === 'binding') {\n\t\t\t\t\tif (!start.isPrecise) {\n\t\t\t\t\t\tstart.normalizedAnchor = { x: 0.5, y: 0.5 }\n\t\t\t\t\t}\n\t\t\t\t\tdelete start.isPrecise\n\t\t\t\t}\n\t\t\t\tif (end.type === 'binding') {\n\t\t\t\t\tif (!end.isPrecise) {\n\t\t\t\t\t\tend.normalizedAnchor = { x: 0.5, y: 0.5 }\n\t\t\t\t\t}\n\t\t\t\t\tdelete end.isPrecise\n\t\t\t\t}\n\t\t\t},\n\t\t}),\n\n\t\tpropsMigration({\n\t\t\tid: arrowShapeVersions.AddLabelPosition,\n\t\t\tup: (props) => {\n\t\t\t\tprops.labelPosition = 0.5\n\t\t\t},\n\t\t\tdown: (props) => {\n\t\t\t\tdelete props.labelPosition\n\t\t\t},\n\t\t}),\n\n\t\t{\n\t\t\tid: arrowShapeVersions.ExtractBindings,\n\t\t\tscope: 'storage',\n\t\t\tup: (storage) => {\n\t\t\t\ttype OldArrowTerminal =\n\t\t\t\t\t| {\n\t\t\t\t\t\t\ttype: 'point'\n\t\t\t\t\t\t\tx: number\n\t\t\t\t\t\t\ty: number\n\t\t\t\t\t }\n\t\t\t\t\t| {\n\t\t\t\t\t\t\ttype: 'binding'\n\t\t\t\t\t\t\tboundShapeId: TLShapeId\n\t\t\t\t\t\t\tnormalizedAnchor: VecModel\n\t\t\t\t\t\t\tisExact: boolean\n\t\t\t\t\t\t\tisPrecise: boolean\n\t\t\t\t\t }\n\t\t\t\t\t// new type:\n\t\t\t\t\t| { type?: undefined; x: number; y: number }\n\n\t\t\t\ttype OldArrow = TLBaseShape<'arrow', { start: OldArrowTerminal; end: OldArrowTerminal }>\n\n\t\t\t\t// Collect all updates during iteration, then apply them after.\n\t\t\t\t// This avoids issues with live iterators (e.g., SQLite) where updating\n\t\t\t\t// records during iteration can cause them to be visited multiple times.\n\t\t\t\tconst updates: [string, unknown][] = []\n\n\t\t\t\tfor (const record of storage.values()) {\n\t\t\t\t\tif (record.typeName !== 'shape' || (record as TLShape).type !== 'arrow') continue\n\t\t\t\t\tconst arrow = record as OldArrow\n\t\t\t\t\tconst newArrow = structuredClone(arrow)\n\t\t\t\t\tconst { start, end } = arrow.props\n\t\t\t\t\tif (start.type === 'binding') {\n\t\t\t\t\t\tconst id = createBindingId()\n\t\t\t\t\t\tconst binding = {\n\t\t\t\t\t\t\ttypeName: 'binding',\n\t\t\t\t\t\t\tid,\n\t\t\t\t\t\t\ttype: 'arrow',\n\t\t\t\t\t\t\tfromId: arrow.id,\n\t\t\t\t\t\t\ttoId: start.boundShapeId,\n\t\t\t\t\t\t\tmeta: {},\n\t\t\t\t\t\t\tprops: {\n\t\t\t\t\t\t\t\tterminal: 'start',\n\t\t\t\t\t\t\t\tnormalizedAnchor: start.normalizedAnchor,\n\t\t\t\t\t\t\t\tisExact: start.isExact,\n\t\t\t\t\t\t\t\tisPrecise: start.isPrecise,\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tupdates.push([id, binding])\n\t\t\t\t\t\tnewArrow.props.start = { x: 0, y: 0 }\n\t\t\t\t\t} else {\n\t\t\t\t\t\tdelete newArrow.props.start.type\n\t\t\t\t\t}\n\t\t\t\t\tif (end.type === 'binding') {\n\t\t\t\t\t\tconst id = createBindingId()\n\t\t\t\t\t\tconst binding = {\n\t\t\t\t\t\t\ttypeName: 'binding',\n\t\t\t\t\t\t\tid,\n\t\t\t\t\t\t\ttype: 'arrow',\n\t\t\t\t\t\t\tfromId: arrow.id,\n\t\t\t\t\t\t\ttoId: end.boundShapeId,\n\t\t\t\t\t\t\tmeta: {},\n\t\t\t\t\t\t\tprops: {\n\t\t\t\t\t\t\t\tterminal: 'end',\n\t\t\t\t\t\t\t\tnormalizedAnchor: end.normalizedAnchor,\n\t\t\t\t\t\t\t\tisExact: end.isExact,\n\t\t\t\t\t\t\t\tisPrecise: end.isPrecise,\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tupdates.push([id, binding])\n\t\t\t\t\t\tnewArrow.props.end = { x: 0, y: 0 }\n\t\t\t\t\t} else {\n\t\t\t\t\t\tdelete newArrow.props.end.type\n\t\t\t\t\t}\n\t\t\t\t\tupdates.push([arrow.id, newArrow])\n\t\t\t\t}\n\n\t\t\t\tfor (const [id, record] of updates) {\n\t\t\t\t\tstorage.set(id, record as any)\n\t\t\t\t}\n\t\t\t},\n\t\t},\n\t\tpropsMigration({\n\t\t\tid: arrowShapeVersions.AddScale,\n\t\t\tup: (props) => {\n\t\t\t\tprops.scale = 1\n\t\t\t},\n\t\t\tdown: (props) => {\n\t\t\t\tdelete props.scale\n\t\t\t},\n\t\t}),\n\t\tpropsMigration({\n\t\t\tid: arrowShapeVersions.AddElbow,\n\t\t\tup: (props) => {\n\t\t\t\tprops.kind = 'arc'\n\t\t\t\tprops.elbowMidPoint = 0.5\n\t\t\t},\n\t\t\tdown: (props) => {\n\t\t\t\tdelete props.kind\n\t\t\t\tdelete props.elbowMidPoint\n\t\t\t},\n\t\t}),\n\t\tpropsMigration({\n\t\t\tid: arrowShapeVersions.AddRichText,\n\t\t\tup: (props) => {\n\t\t\t\tprops.richText = toRichText(props.text)\n\t\t\t\tdelete props.text\n\t\t\t},\n\t\t\t// N.B. Explicitly no down state so that we force clients to update.\n\t\t\t// down: (props) => {\n\t\t\t// \tdelete props.richText\n\t\t\t// },\n\t\t}),\n\t\tpropsMigration({\n\t\t\tid: arrowShapeVersions.AddRichTextAttrs,\n\t\t\tup: (_props) => {\n\t\t\t\t// noop - attrs is optional so old records are valid\n\t\t\t},\n\t\t\tdown: (props) => {\n\t\t\t\t// Remove attrs from richText when migrating down\n\t\t\t\tif (props.richText && 'attrs' in props.richText) {\n\t\t\t\t\tdelete props.richText.attrs\n\t\t\t\t}\n\t\t\t},\n\t\t}),\n\t],\n})\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -24,8 +24,8 @@ __export(TLBaseShape_exports, {
|
|
|
24
24
|
});
|
|
25
25
|
module.exports = __toCommonJS(TLBaseShape_exports);
|
|
26
26
|
var import_validate = require("@tldraw/validate");
|
|
27
|
-
var import_TLOpacity = require("../misc/TLOpacity");
|
|
28
27
|
var import_id_validator = require("../misc/id-validator");
|
|
28
|
+
var import_TLOpacity = require("../misc/TLOpacity");
|
|
29
29
|
const parentIdValidator = import_validate.T.string.refine((id) => {
|
|
30
30
|
if (!id.startsWith("page:") && !id.startsWith("shape:")) {
|
|
31
31
|
throw new Error('Parent ID must start with "page:" or "shape:"');
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../src/shapes/TLBaseShape.ts"],
|
|
4
|
-
"sourcesContent": ["import { IndexKey, JsonObject } from '@tldraw/utils'\nimport { T } from '@tldraw/validate'\nimport {
|
|
5
|
-
"mappings": ";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA,sBAAkB;AAClB,
|
|
4
|
+
"sourcesContent": ["import { IndexKey, JsonObject } from '@tldraw/utils'\nimport { T } from '@tldraw/validate'\nimport { idValidator } from '../misc/id-validator'\nimport { TLOpacityType, opacityValidator } from '../misc/TLOpacity'\nimport { TLParentId, TLShapeId } from '../records/TLShape'\n\n/**\n * Base interface for all shapes in tldraw.\n *\n * This interface defines the common properties that all shapes share, regardless of their\n * specific type. Every default shape extends this base with additional type-specific properties.\n *\n * Custom shapes should be defined by augmenting the TLGlobalShapePropsMap type and getting the shape type from the TLShape type.\n *\n * @example\n * ```ts\n * // Define a default shape type\n * interface TLArrowShape extends TLBaseShape<'arrow', {\n * kind: TLArrowShapeKind\n * labelColor: TLDefaultColorStyle\n * color: TLDefaultColorStyle\n * fill: TLDefaultFillStyle\n * dash: TLDefaultDashStyle\n * size: TLDefaultSizeStyle\n * arrowheadStart: TLArrowShapeArrowheadStyle\n * arrowheadEnd: TLArrowShapeArrowheadStyle\n * font: TLDefaultFontStyle\n * start: VecModel\n * end: VecModel\n * bend: number\n * richText: TLRichText\n * labelPosition: number\n * scale: number\n * elbowMidPoint: number\n * }> {}\n *\n * // Create a shape instance\n * const arrowShape: TLArrowShape = {\n * id: 'shape:abc123',\n * typeName: 'shape',\n * type: 'arrow',\n * x: 100,\n * y: 200,\n * rotation: 0,\n * index: 'a1',\n * parentId: 'page:main',\n * isLocked: false,\n * opacity: 1,\n * props: {\n * kind: 'arc',\n * start: { x: 0, y: 0 },\n * end: { x: 100, y: 100 },\n * // ... other props\n * },\n * meta: {}\n * }\n * ```\n *\n * @public\n */\nexport interface TLBaseShape<Type extends string, Props extends object> {\n\t// using real `extends BaseRecord<'shape', TLShapeId>` introduces a circularity in the types\n\t// and for that reason those \"base members\" have to be declared manually here\n\treadonly id: TLShapeId\n\treadonly typeName: 'shape'\n\n\ttype: Type\n\tx: number\n\ty: number\n\trotation: number\n\tindex: IndexKey\n\tparentId: TLParentId\n\tisLocked: boolean\n\topacity: TLOpacityType\n\tprops: Props\n\tmeta: JsonObject\n}\n\n/**\n * Validator for parent IDs, ensuring they follow the correct format.\n *\n * Parent IDs must start with either \"page:\" (for shapes directly on a page)\n * or \"shape:\" (for shapes inside other shapes like frames or groups).\n *\n * @example\n * ```ts\n * // Valid parent IDs\n * const pageParent = parentIdValidator.validate('page:main') // \u2713\n * const shapeParent = parentIdValidator.validate('shape:frame1') // \u2713\n *\n * // Invalid parent ID (throws error)\n * const invalid = parentIdValidator.validate('invalid:123') // \u2717\n * ```\n *\n * @public\n */\nexport const parentIdValidator = T.string.refine((id) => {\n\tif (!id.startsWith('page:') && !id.startsWith('shape:')) {\n\t\tthrow new Error('Parent ID must start with \"page:\" or \"shape:\"')\n\t}\n\treturn id as TLParentId\n})\n\n/**\n * Validator for shape IDs, ensuring they follow the \"shape:\" format.\n *\n * @example\n * ```ts\n * const validId = shapeIdValidator.validate('shape:abc123') // \u2713\n * const invalidId = shapeIdValidator.validate('page:abc123') // \u2717 throws error\n * ```\n *\n * @public\n */\nexport const shapeIdValidator = idValidator<TLShapeId>('shape')\n\n/**\n * Creates a validator for a specific shape type.\n *\n * This function generates a complete validator that can validate shape records\n * of the specified type, including both the base shape properties and any\n * custom properties and metadata specific to that shape type.\n *\n * @param type - The string literal type for this shape (e.g., 'geo', 'arrow')\n * @param props - Optional validator configuration for shape-specific properties\n * @param meta - Optional validator configuration for shape-specific metadata\n * @returns A validator that can validate complete shape records of the specified type\n *\n * @example\n * ```ts\n * // Create a validator for a custom shape type\n * const customShapeValidator = createShapeValidator('custom', {\n * width: T.number,\n * height: T.number,\n * color: T.string\n * })\n *\n * // Use the validator to validate shape data\n * const shapeData = {\n * id: 'shape:abc123',\n * typeName: 'shape',\n * type: 'custom',\n * x: 100,\n * y: 200,\n * // ... other base properties\n * props: {\n * width: 150,\n * height: 100,\n * color: 'red'\n * }\n * }\n *\n * const validatedShape = customShapeValidator.validate(shapeData)\n * ```\n *\n * @public\n */\nexport function createShapeValidator<\n\tType extends string,\n\tProps extends JsonObject,\n\tMeta extends JsonObject,\n>(\n\ttype: Type,\n\tprops?: { [K in keyof Props]: T.Validatable<Props[K]> },\n\tmeta?: { [K in keyof Meta]: T.Validatable<Meta[K]> }\n) {\n\treturn T.object<TLBaseShape<Type, Props>>({\n\t\tid: shapeIdValidator,\n\t\ttypeName: T.literal('shape'),\n\t\tx: T.number,\n\t\ty: T.number,\n\t\trotation: T.number,\n\t\tindex: T.indexKey,\n\t\tparentId: parentIdValidator,\n\t\ttype: T.literal(type),\n\t\tisLocked: T.boolean,\n\t\topacity: opacityValidator,\n\t\tprops: props ? T.object(props) : (T.jsonValue as any),\n\t\tmeta: meta ? T.object(meta) : (T.jsonValue as any),\n\t})\n}\n"],
|
|
5
|
+
"mappings": ";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA,sBAAkB;AAClB,0BAA4B;AAC5B,uBAAgD;AA6FzC,MAAM,oBAAoB,kBAAE,OAAO,OAAO,CAAC,OAAO;AACxD,MAAI,CAAC,GAAG,WAAW,OAAO,KAAK,CAAC,GAAG,WAAW,QAAQ,GAAG;AACxD,UAAM,IAAI,MAAM,+CAA+C;AAAA,EAChE;AACA,SAAO;AACR,CAAC;AAaM,MAAM,uBAAmB,iCAAuB,OAAO;AA2CvD,SAAS,qBAKf,MACA,OACA,MACC;AACD,SAAO,kBAAE,OAAiC;AAAA,IACzC,IAAI;AAAA,IACJ,UAAU,kBAAE,QAAQ,OAAO;AAAA,IAC3B,GAAG,kBAAE;AAAA,IACL,GAAG,kBAAE;AAAA,IACL,UAAU,kBAAE;AAAA,IACZ,OAAO,kBAAE;AAAA,IACT,UAAU;AAAA,IACV,MAAM,kBAAE,QAAQ,IAAI;AAAA,IACpB,UAAU,kBAAE;AAAA,IACZ,SAAS;AAAA,IACT,OAAO,QAAQ,kBAAE,OAAO,KAAK,IAAK,kBAAE;AAAA,IACpC,MAAM,OAAO,kBAAE,OAAO,IAAI,IAAK,kBAAE;AAAA,EAClC,CAAC;AACF;",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../src/createPresenceStateDerivation.ts"],
|
|
4
|
-
"sourcesContent": ["import { Signal, computed } from '@tldraw/state'\nimport {
|
|
5
|
-
"mappings": "AAAA,SAAiB,gBAAgB;
|
|
4
|
+
"sourcesContent": ["import { Signal, computed } from '@tldraw/state'\nimport { CameraRecordType } from './records/TLCamera'\nimport { TLINSTANCE_ID } from './records/TLInstance'\nimport { InstancePageStateRecordType } from './records/TLPageState'\nimport { TLPOINTER_ID } from './records/TLPointer'\nimport { InstancePresenceRecordType, TLInstancePresence } from './records/TLPresence'\nimport { TLStore } from './TLStore'\n\n/**\n * The information about a user which is used for multiplayer features.\n * @public\n */\nexport interface TLPresenceUserInfo {\n\t/**\n\t * id - A unique identifier for the user. This should be the same across all devices and sessions.\n\t */\n\tid: string\n\t/**\n\t * The user's display name.\n\t */\n\tname?: string | null\n\t/**\n\t * The user's color. If not given, a random color will be assigned.\n\t */\n\tcolor?: string | null\n}\n\n/**\n * Creates a derivation that represents the current presence state of the current user.\n *\n * This function returns a derivation factory that, when given a store, creates a computed signal\n * containing the user's current presence state. The presence state includes information like cursor\n * position, selected shapes, camera position, and user metadata that gets synchronized in\n * multiplayer scenarios.\n *\n * @param $user - A reactive signal containing the user information\n * @param instanceId - Optional custom instance ID. If not provided, one will be generated based on the store ID\n * @returns A function that takes a store and returns a computed signal of the user's presence state\n *\n * @example\n * ```ts\n * import { createPresenceStateDerivation } from '@tldraw/tlschema'\n * import { atom } from '@tldraw/state'\n *\n * const userSignal = atom('user', { id: 'user-123', name: 'Alice', color: '#ff0000' })\n * const presenceDerivation = createPresenceStateDerivation(userSignal)\n *\n * // Use with a store to get reactive presence state\n * const presenceState = presenceDerivation(store)\n * console.log(presenceState.get()) // Current user presence or null\n * ```\n *\n * @public\n */\nexport function createPresenceStateDerivation(\n\t$user: Signal<TLPresenceUserInfo>,\n\tinstanceId?: TLInstancePresence['id']\n) {\n\treturn (store: TLStore): Signal<TLInstancePresence | null> => {\n\t\treturn computed('instancePresence', () => {\n\t\t\tconst user = $user.get()\n\t\t\tif (!user) return null\n\n\t\t\tconst state = getDefaultUserPresence(store, user)\n\t\t\tif (!state) return null\n\n\t\t\treturn InstancePresenceRecordType.create({\n\t\t\t\t...state,\n\t\t\t\tid: instanceId ?? InstancePresenceRecordType.createId(store.id),\n\t\t\t})\n\t\t})\n\t}\n}\n\n/**\n * The shape of data used to create a presence record.\n *\n * This type represents all the properties needed to construct a TLInstancePresence record.\n * It includes user information, cursor state, camera position, selected shapes, and other\n * presence-related data that gets synchronized across multiplayer clients.\n *\n * @public\n */\nexport type TLPresenceStateInfo = Parameters<(typeof InstancePresenceRecordType)['create']>[0]\n\n/**\n * Creates default presence state information for a user based on the current store state.\n *\n * This function extracts the current state from various store records (instance, page state,\n * camera, pointer) and combines them with user information to create a complete presence\n * state object. This is commonly used as a starting point for custom presence implementations.\n *\n * @param store - The tldraw store containing the current editor state\n * @param user - The user information to include in the presence state\n * @returns The default presence state info, or null if required store records are missing\n *\n * @example\n * ```ts\n * import { getDefaultUserPresence } from '@tldraw/tlschema'\n *\n * const user = { id: 'user-123', name: 'Alice', color: '#ff0000' }\n * const presenceInfo = getDefaultUserPresence(store, user)\n *\n * if (presenceInfo) {\n * console.log('Current cursor:', presenceInfo.cursor)\n * console.log('Selected shapes:', presenceInfo.selectedShapeIds)\n * console.log('Camera position:', presenceInfo.camera)\n * }\n * ```\n *\n * @example\n * ```ts\n * // Common pattern: customize default presence\n * const customPresence = {\n * ...getDefaultUserPresence(store, user),\n * // Remove camera for privacy\n * camera: undefined,\n * // Add custom metadata\n * customField: 'my-data'\n * }\n * ```\n *\n * @public\n */\nexport function getDefaultUserPresence(store: TLStore, user: TLPresenceUserInfo) {\n\tconst instance = store.get(TLINSTANCE_ID)\n\tconst pageState = store.get(InstancePageStateRecordType.createId(instance?.currentPageId))\n\tconst camera = store.get(CameraRecordType.createId(instance?.currentPageId))\n\tconst pointer = store.get(TLPOINTER_ID)\n\tif (!pageState || !instance || !camera || !pointer) {\n\t\treturn null\n\t}\n\n\treturn {\n\t\tselectedShapeIds: pageState.selectedShapeIds,\n\t\tbrush: instance.brush,\n\t\tscribbles: instance.scribbles,\n\t\tuserId: user.id,\n\t\tuserName: user.name ?? '',\n\t\tfollowingUserId: instance.followingUserId,\n\t\tcamera: {\n\t\t\tx: camera.x,\n\t\t\ty: camera.y,\n\t\t\tz: camera.z,\n\t\t},\n\t\tcolor: user.color ?? '#FF0000',\n\t\tcurrentPageId: instance.currentPageId,\n\t\tcursor: {\n\t\t\tx: pointer.x,\n\t\t\ty: pointer.y,\n\t\t\trotation: instance.cursor.rotation,\n\t\t\ttype: instance.cursor.type,\n\t\t},\n\t\tlastActivityTimestamp: pointer.lastActivityTimestamp,\n\t\tscreenBounds: instance.screenBounds,\n\t\tchatMessage: instance.chatMessage,\n\t\tmeta: {},\n\t} satisfies TLPresenceStateInfo\n}\n"],
|
|
5
|
+
"mappings": "AAAA,SAAiB,gBAAgB;AACjC,SAAS,wBAAwB;AACjC,SAAS,qBAAqB;AAC9B,SAAS,mCAAmC;AAC5C,SAAS,oBAAoB;AAC7B,SAAS,kCAAsD;AAiDxD,SAAS,8BACf,OACA,YACC;AACD,SAAO,CAAC,UAAsD;AAC7D,WAAO,SAAS,oBAAoB,MAAM;AACzC,YAAM,OAAO,MAAM,IAAI;AACvB,UAAI,CAAC,KAAM,QAAO;AAElB,YAAM,QAAQ,uBAAuB,OAAO,IAAI;AAChD,UAAI,CAAC,MAAO,QAAO;AAEnB,aAAO,2BAA2B,OAAO;AAAA,QACxC,GAAG;AAAA,QACH,IAAI,cAAc,2BAA2B,SAAS,MAAM,EAAE;AAAA,MAC/D,CAAC;AAAA,IACF,CAAC;AAAA,EACF;AACD;AAoDO,SAAS,uBAAuB,OAAgB,MAA0B;AAChF,QAAM,WAAW,MAAM,IAAI,aAAa;AACxC,QAAM,YAAY,MAAM,IAAI,4BAA4B,SAAS,UAAU,aAAa,CAAC;AACzF,QAAM,SAAS,MAAM,IAAI,iBAAiB,SAAS,UAAU,aAAa,CAAC;AAC3E,QAAM,UAAU,MAAM,IAAI,YAAY;AACtC,MAAI,CAAC,aAAa,CAAC,YAAY,CAAC,UAAU,CAAC,SAAS;AACnD,WAAO;AAAA,EACR;AAEA,SAAO;AAAA,IACN,kBAAkB,UAAU;AAAA,IAC5B,OAAO,SAAS;AAAA,IAChB,WAAW,SAAS;AAAA,IACpB,QAAQ,KAAK;AAAA,IACb,UAAU,KAAK,QAAQ;AAAA,IACvB,iBAAiB,SAAS;AAAA,IAC1B,QAAQ;AAAA,MACP,GAAG,OAAO;AAAA,MACV,GAAG,OAAO;AAAA,MACV,GAAG,OAAO;AAAA,IACX;AAAA,IACA,OAAO,KAAK,SAAS;AAAA,IACrB,eAAe,SAAS;AAAA,IACxB,QAAQ;AAAA,MACP,GAAG,QAAQ;AAAA,MACX,GAAG,QAAQ;AAAA,MACX,UAAU,SAAS,OAAO;AAAA,MAC1B,MAAM,SAAS,OAAO;AAAA,IACvB;AAAA,IACA,uBAAuB,QAAQ;AAAA,IAC/B,cAAc,SAAS;AAAA,IACvB,aAAa,SAAS;AAAA,IACtB,MAAM,CAAC;AAAA,EACR;AACD;",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import { StoreSchema } from "@tldraw/store";
|
|
2
2
|
import { objectMapValues } from "@tldraw/utils";
|
|
3
|
-
import { createIntegrityChecker, onValidationFailure } from "./TLStore.mjs";
|
|
4
3
|
import { bookmarkAssetMigrations } from "./assets/TLBookmarkAsset.mjs";
|
|
5
4
|
import { imageAssetMigrations } from "./assets/TLImageAsset.mjs";
|
|
6
5
|
import { videoAssetMigrations } from "./assets/TLVideoAsset.mjs";
|
|
@@ -38,6 +37,7 @@ import { noteShapeMigrations, noteShapeProps } from "./shapes/TLNoteShape.mjs";
|
|
|
38
37
|
import { textShapeMigrations, textShapeProps } from "./shapes/TLTextShape.mjs";
|
|
39
38
|
import { videoShapeMigrations, videoShapeProps } from "./shapes/TLVideoShape.mjs";
|
|
40
39
|
import { storeMigrations } from "./store-migrations.mjs";
|
|
40
|
+
import { createIntegrityChecker, onValidationFailure } from "./TLStore.mjs";
|
|
41
41
|
const defaultShapeSchemas = {
|
|
42
42
|
arrow: { migrations: arrowShapeMigrations, props: arrowShapeProps },
|
|
43
43
|
bookmark: { migrations: bookmarkShapeMigrations, props: bookmarkShapeProps },
|