@tldraw/tlschema 4.2.0-next.f100cedfc45b → 4.3.0-canary.03ae87dcc44b

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.
Files changed (47) hide show
  1. package/dist-cjs/bindings/TLBaseBinding.js.map +2 -2
  2. package/dist-cjs/createTLSchema.js.map +2 -2
  3. package/dist-cjs/index.d.ts +194 -38
  4. package/dist-cjs/index.js +2 -1
  5. package/dist-cjs/index.js.map +2 -2
  6. package/dist-cjs/misc/TLHandle.js.map +1 -1
  7. package/dist-cjs/records/TLAsset.js.map +1 -1
  8. package/dist-cjs/records/TLBinding.js.map +2 -2
  9. package/dist-cjs/records/TLShape.js.map +2 -2
  10. package/dist-cjs/shapes/ShapeWithCrop.js.map +1 -1
  11. package/dist-cjs/shapes/TLBaseShape.js.map +2 -2
  12. package/dist-cjs/store-migrations.js +1 -1
  13. package/dist-cjs/store-migrations.js.map +2 -2
  14. package/dist-cjs/styles/TLColorStyle.js +26 -0
  15. package/dist-cjs/styles/TLColorStyle.js.map +2 -2
  16. package/dist-cjs/styles/TLFillStyle.js +1 -1
  17. package/dist-cjs/styles/TLFillStyle.js.map +2 -2
  18. package/dist-esm/bindings/TLBaseBinding.mjs.map +2 -2
  19. package/dist-esm/createTLSchema.mjs.map +2 -2
  20. package/dist-esm/index.d.mts +194 -38
  21. package/dist-esm/index.mjs +3 -1
  22. package/dist-esm/index.mjs.map +2 -2
  23. package/dist-esm/misc/TLHandle.mjs.map +1 -1
  24. package/dist-esm/records/TLAsset.mjs.map +1 -1
  25. package/dist-esm/records/TLBinding.mjs.map +2 -2
  26. package/dist-esm/records/TLShape.mjs.map +2 -2
  27. package/dist-esm/shapes/TLBaseShape.mjs.map +2 -2
  28. package/dist-esm/store-migrations.mjs +1 -1
  29. package/dist-esm/store-migrations.mjs.map +2 -2
  30. package/dist-esm/styles/TLColorStyle.mjs +26 -0
  31. package/dist-esm/styles/TLColorStyle.mjs.map +2 -2
  32. package/dist-esm/styles/TLFillStyle.mjs +1 -1
  33. package/dist-esm/styles/TLFillStyle.mjs.map +2 -2
  34. package/package.json +5 -5
  35. package/src/bindings/TLBaseBinding.ts +25 -14
  36. package/src/createTLSchema.ts +8 -2
  37. package/src/index.ts +7 -0
  38. package/src/misc/TLHandle.ts +2 -0
  39. package/src/records/TLAsset.ts +2 -2
  40. package/src/records/TLBinding.ts +65 -23
  41. package/src/records/TLRecord.test.ts +17 -5
  42. package/src/records/TLShape.ts +100 -5
  43. package/src/shapes/ShapeWithCrop.ts +2 -2
  44. package/src/shapes/TLBaseShape.ts +34 -10
  45. package/src/store-migrations.ts +2 -1
  46. package/src/styles/TLColorStyle.ts +27 -0
  47. package/src/styles/TLFillStyle.ts +1 -1
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../src/misc/TLHandle.ts"],
4
- "sourcesContent": ["import { IndexKey } from '@tldraw/utils'\nimport { SetValue } from '../util-types'\n\n/**\n * All available handle types used by shapes in the tldraw editor.\n *\n * Handles are interactive control points on shapes that allow users to\n * modify the shape's geometry. Different handle types serve different purposes:\n *\n * - `vertex`: A control point that defines a vertex of the shape\n * - `virtual`: A handle that exists between vertices for adding new points\n * - `create`: A handle for creating new geometry (like extending a line)\n * - `clone`: A handle for duplicating or cloning shape elements\n *\n * @example\n * ```ts\n * // Check if a handle type is valid\n * if (TL_HANDLE_TYPES.has('vertex')) {\n * console.log('Valid handle type')\n * }\n *\n * // Get all available handle types\n * const allHandleTypes = Array.from(TL_HANDLE_TYPES)\n * ```\n *\n * @public\n */\nexport const TL_HANDLE_TYPES = new Set(['vertex', 'virtual', 'create', 'clone'] as const)\n\n/**\n * A union type representing all available handle types.\n *\n * Handle types determine how a handle behaves when interacted with and\n * what kind of shape modification it enables.\n *\n * @example\n * ```ts\n * const vertexHandle: TLHandleType = 'vertex'\n * const virtualHandle: TLHandleType = 'virtual'\n * const createHandle: TLHandleType = 'create'\n * const cloneHandle: TLHandleType = 'clone'\n * ```\n *\n * @public\n */\nexport type TLHandleType = SetValue<typeof TL_HANDLE_TYPES>\n\n/**\n * A handle object representing an interactive control point on a shape.\n *\n * Handles allow users to manipulate shape geometry by dragging control points.\n * Each handle has a position, type, and various properties that control its\n * behavior during interactions.\n *\n * @example\n * ```ts\n * // A vertex handle for a line endpoint\n * const lineEndHandle: TLHandle = {\n * id: 'end',\n * label: 'End point',\n * type: 'vertex',\n * canSnap: true,\n * index: 'a1',\n * x: 100,\n * y: 50\n * }\n *\n * // A virtual handle for adding new points\n * const virtualHandle: TLHandle = {\n * id: 'virtual-1',\n * type: 'virtual',\n * canSnap: false,\n * index: 'a1V',\n * x: 75,\n * y: 25\n * }\n *\n * // A create handle for extending geometry\n * const createHandle: TLHandle = {\n * id: 'create',\n * type: 'create',\n * canSnap: true,\n * index: 'a2',\n * x: 200,\n * y: 100\n * }\n * ```\n *\n * @public\n */\nexport interface TLHandle {\n\t/** A unique identifier for the handle within the shape */\n\tid: string\n\t/** Optional human-readable label for the handle */\n\t// TODO(mime): this needs to be required.\n\tlabel?: string\n\t/** The type of handle, determining its behavior and interaction mode */\n\ttype: TLHandleType\n\t/**\n\t * @deprecated Use `snapType` instead. Whether this handle should snap to other geometry during interactions.\n\t */\n\tcanSnap?: boolean\n\t/** The type of snap to use for this handle */\n\tsnapType?: 'point' | 'align'\n\t/** The fractional index used for ordering handles */\n\tindex: IndexKey\n\t/** The x-coordinate of the handle in the shape's local coordinate system */\n\tx: number\n\t/** The y-coordinate of the handle in the shape's local coordinate system */\n\ty: number\n}\n"],
4
+ "sourcesContent": ["import { IndexKey } from '@tldraw/utils'\nimport { SetValue } from '../util-types'\n\n/**\n * All available handle types used by shapes in the tldraw editor.\n *\n * Handles are interactive control points on shapes that allow users to\n * modify the shape's geometry. Different handle types serve different purposes:\n *\n * - `vertex`: A control point that defines a vertex of the shape\n * - `virtual`: A handle that exists between vertices for adding new points\n * - `create`: A handle for creating new geometry (like extending a line)\n * - `clone`: A handle for duplicating or cloning shape elements\n *\n * @example\n * ```ts\n * // Check if a handle type is valid\n * if (TL_HANDLE_TYPES.has('vertex')) {\n * console.log('Valid handle type')\n * }\n *\n * // Get all available handle types\n * const allHandleTypes = Array.from(TL_HANDLE_TYPES)\n * ```\n *\n * @public\n */\nexport const TL_HANDLE_TYPES = new Set(['vertex', 'virtual', 'create', 'clone'] as const)\n\n/**\n * A union type representing all available handle types.\n *\n * Handle types determine how a handle behaves when interacted with and\n * what kind of shape modification it enables.\n *\n * @example\n * ```ts\n * const vertexHandle: TLHandleType = 'vertex'\n * const virtualHandle: TLHandleType = 'virtual'\n * const createHandle: TLHandleType = 'create'\n * const cloneHandle: TLHandleType = 'clone'\n * ```\n *\n * @public\n */\nexport type TLHandleType = SetValue<typeof TL_HANDLE_TYPES>\n\n/**\n * A handle object representing an interactive control point on a shape.\n *\n * Handles allow users to manipulate shape geometry by dragging control points.\n * Each handle has a position, type, and various properties that control its\n * behavior during interactions.\n *\n * @example\n * ```ts\n * // A vertex handle for a line endpoint\n * const lineEndHandle: TLHandle = {\n * id: 'end',\n * label: 'End point',\n * type: 'vertex',\n * canSnap: true,\n * index: 'a1',\n * x: 100,\n * y: 50\n * }\n *\n * // A virtual handle for adding new points\n * const virtualHandle: TLHandle = {\n * id: 'virtual-1',\n * type: 'virtual',\n * canSnap: false,\n * index: 'a1V',\n * x: 75,\n * y: 25\n * }\n *\n * // A create handle for extending geometry\n * const createHandle: TLHandle = {\n * id: 'create',\n * type: 'create',\n * canSnap: true,\n * index: 'a2',\n * x: 200,\n * y: 100\n * }\n * ```\n *\n * @public\n */\nexport interface TLHandle {\n\t/** A unique identifier for the handle within the shape */\n\tid: string\n\t/** Optional human-readable label for the handle */\n\t// TODO(mime): this needs to be required.\n\tlabel?: string\n\t/** The type of handle, determining its behavior and interaction mode */\n\ttype: TLHandleType\n\t/**\n\t * @deprecated Use `snapType` instead. Whether this handle should snap to other geometry during interactions.\n\t */\n\tcanSnap?: boolean\n\t/** The type of snap to use for this handle */\n\tsnapType?: 'point' | 'align'\n\t/** The ID of the handle to use as reference point for shift-modifier angle snapping */\n\tsnapReferenceHandleId?: string\n\t/** The fractional index used for ordering handles */\n\tindex: IndexKey\n\t/** The x-coordinate of the handle in the shape's local coordinate system */\n\tx: number\n\t/** The y-coordinate of the handle in the shape's local coordinate system */\n\ty: number\n}\n"],
5
5
  "mappings": ";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AA2BO,MAAM,kBAAkB,oBAAI,IAAI,CAAC,UAAU,WAAW,UAAU,OAAO,CAAU;",
6
6
  "names": []
7
7
  }
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../src/records/TLAsset.ts"],
4
- "sourcesContent": ["import {\n\tcreateMigrationIds,\n\tcreateRecordMigrationSequence,\n\tcreateRecordType,\n\tRecordId,\n} from '@tldraw/store'\nimport { T } from '@tldraw/validate'\nimport { TLBaseAsset } from '../assets/TLBaseAsset'\nimport { bookmarkAssetValidator, TLBookmarkAsset } from '../assets/TLBookmarkAsset'\nimport { imageAssetValidator, TLImageAsset } from '../assets/TLImageAsset'\nimport { TLVideoAsset, videoAssetValidator } from '../assets/TLVideoAsset'\nimport { TLShape } from './TLShape'\n\n/**\n * Union type representing all possible asset types in tldraw.\n * Assets represent external resources like images, videos, or bookmarks that can be referenced by shapes.\n *\n * @example\n * ```ts\n * const imageAsset: TLAsset = {\n * id: 'asset:image123',\n * typeName: 'asset',\n * type: 'image',\n * props: {\n * src: 'https://example.com/image.jpg',\n * w: 800,\n * h: 600,\n * mimeType: 'image/jpeg',\n * isAnimated: false\n * },\n * meta: {}\n * }\n * ```\n *\n * @public\n */\nexport type TLAsset = TLImageAsset | TLVideoAsset | TLBookmarkAsset\n\n/**\n * Validator for TLAsset records that ensures runtime type safety.\n * Uses a discriminated union based on the 'type' field to validate different asset types.\n *\n * @example\n * ```ts\n * // Validation happens automatically when assets are stored\n * try {\n * const validatedAsset = assetValidator.validate(assetData)\n * store.put([validatedAsset])\n * } catch (error) {\n * console.error('Asset validation failed:', error.message)\n * }\n * ```\n *\n * @public\n */\nexport const assetValidator: T.Validator<TLAsset> = T.model(\n\t'asset',\n\tT.union('type', {\n\t\timage: imageAssetValidator,\n\t\tvideo: videoAssetValidator,\n\t\tbookmark: bookmarkAssetValidator,\n\t})\n)\n\n/**\n * Migration version identifiers for asset record schema evolution.\n * Each version represents a breaking change that requires data migration.\n *\n * @example\n * ```ts\n * // Check if a migration is needed\n * const needsMigration = currentVersion < assetVersions.AddMeta\n * ```\n *\n * @public\n */\nexport const assetVersions = createMigrationIds('com.tldraw.asset', {\n\tAddMeta: 1,\n} as const)\n\n/**\n * Migration sequence for evolving asset record structure over time.\n * Handles converting asset records from older schema versions to current format.\n *\n * @example\n * ```ts\n * // Migration is applied automatically when loading old documents\n * const migratedStore = migrator.migrateStoreSnapshot({\n * schema: oldSchema,\n * store: oldStoreSnapshot\n * })\n * ```\n *\n * @public\n */\nexport const assetMigrations = createRecordMigrationSequence({\n\tsequenceId: 'com.tldraw.asset',\n\trecordType: 'asset',\n\tsequence: [\n\t\t{\n\t\t\tid: assetVersions.AddMeta,\n\t\t\tup: (record) => {\n\t\t\t\t;(record as any).meta = {}\n\t\t\t},\n\t\t},\n\t],\n})\n\n/**\n * Partial type for TLAsset allowing optional properties except id and type.\n * Useful for creating or updating assets where not all properties need to be specified.\n *\n * @example\n * ```ts\n * // Create a partial asset for updating\n * const partialAsset: TLAssetPartial<TLImageAsset> = {\n * id: 'asset:image123',\n * type: 'image',\n * props: {\n * w: 800 // Only updating width\n * }\n * }\n *\n * // Use in asset updates\n * editor.updateAssets([partialAsset])\n * ```\n *\n * @public\n */\nexport type TLAssetPartial<T extends TLAsset = TLAsset> = T extends T\n\t? {\n\t\t\tid: TLAssetId\n\t\t\ttype: T['type']\n\t\t\tprops?: Partial<T['props']>\n\t\t\tmeta?: Partial<T['meta']>\n\t\t} & Partial<Omit<T, 'type' | 'id' | 'props' | 'meta'>>\n\t: never\n\n/**\n * Record type definition for TLAsset with validation and default properties.\n * Configures assets as document-scoped records that persist across sessions.\n *\n * @example\n * ```ts\n * // Create a new asset record\n * const assetRecord = AssetRecordType.create({\n * id: 'asset:image123',\n * type: 'image',\n * props: {\n * src: 'https://example.com/image.jpg',\n * w: 800,\n * h: 600,\n * mimeType: 'image/jpeg',\n * isAnimated: false\n * }\n * })\n *\n * // Store the asset\n * store.put([assetRecord])\n * ```\n *\n * @public\n */\nexport const AssetRecordType = createRecordType<TLAsset>('asset', {\n\tvalidator: assetValidator,\n\tscope: 'document',\n}).withDefaultProperties(() => ({\n\tmeta: {},\n}))\n\n/**\n * Branded string type for asset record identifiers.\n * Prevents mixing asset IDs with other types of record IDs at compile time.\n *\n * @example\n * ```ts\n * import { createAssetId } from '@tldraw/tlschema'\n *\n * // Create a new asset ID\n * const assetId: TLAssetId = createAssetId()\n *\n * // Use in asset records\n * const asset: TLAsset = {\n * id: assetId,\n * // ... other properties\n * }\n *\n * // Reference in shapes\n * const imageShape: TLImageShape = {\n * props: {\n * assetId: assetId,\n * // ... other properties\n * }\n * }\n * ```\n *\n * @public\n */\nexport type TLAssetId = RecordId<TLBaseAsset<any, any>>\n\n/**\n * Union type of all shapes that reference assets through an assetId property.\n * Includes image shapes, video shapes, and any other shapes that depend on external assets.\n *\n * @example\n * ```ts\n * // Function that works with any asset-based shape\n * function handleAssetShape(shape: TLAssetShape) {\n * const assetId = shape.props.assetId\n * if (assetId) {\n * const asset = editor.getAsset(assetId)\n * // Handle the asset...\n * }\n * }\n *\n * // Use with image or video shapes\n * const imageShape: TLImageShape = { props: { assetId: 'asset:img1' } }\n * const videoShape: TLVideoShape = { props: { assetId: 'asset:vid1' } }\n * handleAssetShape(imageShape) // Works\n * handleAssetShape(videoShape) // Works\n * ```\n *\n * @public\n */\nexport type TLAssetShape = Extract<TLShape, { props: { assetId: TLAssetId } }>\n"],
4
+ "sourcesContent": ["import {\n\tcreateMigrationIds,\n\tcreateRecordMigrationSequence,\n\tcreateRecordType,\n\tRecordId,\n} from '@tldraw/store'\nimport { T } from '@tldraw/validate'\nimport { TLBaseAsset } from '../assets/TLBaseAsset'\nimport { bookmarkAssetValidator, TLBookmarkAsset } from '../assets/TLBookmarkAsset'\nimport { imageAssetValidator, TLImageAsset } from '../assets/TLImageAsset'\nimport { TLVideoAsset, videoAssetValidator } from '../assets/TLVideoAsset'\nimport { ExtractShapeByProps } from './TLShape'\n\n/**\n * Union type representing all possible asset types in tldraw.\n * Assets represent external resources like images, videos, or bookmarks that can be referenced by shapes.\n *\n * @example\n * ```ts\n * const imageAsset: TLAsset = {\n * id: 'asset:image123',\n * typeName: 'asset',\n * type: 'image',\n * props: {\n * src: 'https://example.com/image.jpg',\n * w: 800,\n * h: 600,\n * mimeType: 'image/jpeg',\n * isAnimated: false\n * },\n * meta: {}\n * }\n * ```\n *\n * @public\n */\nexport type TLAsset = TLImageAsset | TLVideoAsset | TLBookmarkAsset\n\n/**\n * Validator for TLAsset records that ensures runtime type safety.\n * Uses a discriminated union based on the 'type' field to validate different asset types.\n *\n * @example\n * ```ts\n * // Validation happens automatically when assets are stored\n * try {\n * const validatedAsset = assetValidator.validate(assetData)\n * store.put([validatedAsset])\n * } catch (error) {\n * console.error('Asset validation failed:', error.message)\n * }\n * ```\n *\n * @public\n */\nexport const assetValidator: T.Validator<TLAsset> = T.model(\n\t'asset',\n\tT.union('type', {\n\t\timage: imageAssetValidator,\n\t\tvideo: videoAssetValidator,\n\t\tbookmark: bookmarkAssetValidator,\n\t})\n)\n\n/**\n * Migration version identifiers for asset record schema evolution.\n * Each version represents a breaking change that requires data migration.\n *\n * @example\n * ```ts\n * // Check if a migration is needed\n * const needsMigration = currentVersion < assetVersions.AddMeta\n * ```\n *\n * @public\n */\nexport const assetVersions = createMigrationIds('com.tldraw.asset', {\n\tAddMeta: 1,\n} as const)\n\n/**\n * Migration sequence for evolving asset record structure over time.\n * Handles converting asset records from older schema versions to current format.\n *\n * @example\n * ```ts\n * // Migration is applied automatically when loading old documents\n * const migratedStore = migrator.migrateStoreSnapshot({\n * schema: oldSchema,\n * store: oldStoreSnapshot\n * })\n * ```\n *\n * @public\n */\nexport const assetMigrations = createRecordMigrationSequence({\n\tsequenceId: 'com.tldraw.asset',\n\trecordType: 'asset',\n\tsequence: [\n\t\t{\n\t\t\tid: assetVersions.AddMeta,\n\t\t\tup: (record) => {\n\t\t\t\t;(record as any).meta = {}\n\t\t\t},\n\t\t},\n\t],\n})\n\n/**\n * Partial type for TLAsset allowing optional properties except id and type.\n * Useful for creating or updating assets where not all properties need to be specified.\n *\n * @example\n * ```ts\n * // Create a partial asset for updating\n * const partialAsset: TLAssetPartial<TLImageAsset> = {\n * id: 'asset:image123',\n * type: 'image',\n * props: {\n * w: 800 // Only updating width\n * }\n * }\n *\n * // Use in asset updates\n * editor.updateAssets([partialAsset])\n * ```\n *\n * @public\n */\nexport type TLAssetPartial<T extends TLAsset = TLAsset> = T extends T\n\t? {\n\t\t\tid: TLAssetId\n\t\t\ttype: T['type']\n\t\t\tprops?: Partial<T['props']>\n\t\t\tmeta?: Partial<T['meta']>\n\t\t} & Partial<Omit<T, 'type' | 'id' | 'props' | 'meta'>>\n\t: never\n\n/**\n * Record type definition for TLAsset with validation and default properties.\n * Configures assets as document-scoped records that persist across sessions.\n *\n * @example\n * ```ts\n * // Create a new asset record\n * const assetRecord = AssetRecordType.create({\n * id: 'asset:image123',\n * type: 'image',\n * props: {\n * src: 'https://example.com/image.jpg',\n * w: 800,\n * h: 600,\n * mimeType: 'image/jpeg',\n * isAnimated: false\n * }\n * })\n *\n * // Store the asset\n * store.put([assetRecord])\n * ```\n *\n * @public\n */\nexport const AssetRecordType = createRecordType<TLAsset>('asset', {\n\tvalidator: assetValidator,\n\tscope: 'document',\n}).withDefaultProperties(() => ({\n\tmeta: {},\n}))\n\n/**\n * Branded string type for asset record identifiers.\n * Prevents mixing asset IDs with other types of record IDs at compile time.\n *\n * @example\n * ```ts\n * import { createAssetId } from '@tldraw/tlschema'\n *\n * // Create a new asset ID\n * const assetId: TLAssetId = createAssetId()\n *\n * // Use in asset records\n * const asset: TLAsset = {\n * id: assetId,\n * // ... other properties\n * }\n *\n * // Reference in shapes\n * const imageShape: TLImageShape = {\n * props: {\n * assetId: assetId,\n * // ... other properties\n * }\n * }\n * ```\n *\n * @public\n */\nexport type TLAssetId = RecordId<TLBaseAsset<any, any>>\n\n/**\n * Union type of all shapes that reference assets through an assetId property.\n * Includes image shapes, video shapes, and any other shapes that depend on external assets.\n *\n * @example\n * ```ts\n * // Function that works with any asset-based shape\n * function handleAssetShape(shape: TLAssetShape) {\n * const assetId = shape.props.assetId\n * if (assetId) {\n * const asset = editor.getAsset(assetId)\n * // Handle the asset...\n * }\n * }\n *\n * // Use with image or video shapes\n * const imageShape: TLImageShape = { props: { assetId: 'asset:img1' } }\n * const videoShape: TLVideoShape = { props: { assetId: 'asset:vid1' } }\n * handleAssetShape(imageShape) // Works\n * handleAssetShape(videoShape) // Works\n * ```\n *\n * @public\n */\nexport type TLAssetShape = ExtractShapeByProps<{ assetId: TLAssetId }>\n"],
5
5
  "mappings": ";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,mBAKO;AACP,sBAAkB;AAElB,6BAAwD;AACxD,0BAAkD;AAClD,0BAAkD;AA6C3C,MAAM,iBAAuC,kBAAE;AAAA,EACrD;AAAA,EACA,kBAAE,MAAM,QAAQ;AAAA,IACf,OAAO;AAAA,IACP,OAAO;AAAA,IACP,UAAU;AAAA,EACX,CAAC;AACF;AAcO,MAAM,oBAAgB,iCAAmB,oBAAoB;AAAA,EACnE,SAAS;AACV,CAAU;AAiBH,MAAM,sBAAkB,4CAA8B;AAAA,EAC5D,YAAY;AAAA,EACZ,YAAY;AAAA,EACZ,UAAU;AAAA,IACT;AAAA,MACC,IAAI,cAAc;AAAA,MAClB,IAAI,CAAC,WAAW;AACf;AAAC,QAAC,OAAe,OAAO,CAAC;AAAA,MAC1B;AAAA,IACD;AAAA,EACD;AACD,CAAC;AAyDM,MAAM,sBAAkB,+BAA0B,SAAS;AAAA,EACjE,WAAW;AAAA,EACX,OAAO;AACR,CAAC,EAAE,sBAAsB,OAAO;AAAA,EAC/B,MAAM,CAAC;AACR,EAAE;",
6
6
  "names": []
7
7
  }
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../src/records/TLBinding.ts"],
4
- "sourcesContent": ["import {\n\tRecordId,\n\tUnknownRecord,\n\tcreateMigrationIds,\n\tcreateRecordMigrationSequence,\n\tcreateRecordType,\n} from '@tldraw/store'\nimport { Expand, mapObjectMapValues, uniqueId } from '@tldraw/utils'\nimport { T } from '@tldraw/validate'\nimport { TLArrowBinding } from '../bindings/TLArrowBinding'\nimport { TLBaseBinding, createBindingValidator } from '../bindings/TLBaseBinding'\nimport { SchemaPropsInfo } from '../createTLSchema'\nimport { TLPropsMigrations } from '../recordsWithProps'\n\n/**\n * The default set of bindings that are available in the editor.\n * Currently includes only arrow bindings, but can be extended with custom bindings.\n *\n * @example\n * ```ts\n * // Arrow binding connects an arrow to shapes\n * const arrowBinding: TLDefaultBinding = {\n * id: 'binding:arrow1',\n * typeName: 'binding',\n * type: 'arrow',\n * fromId: 'shape:arrow1',\n * toId: 'shape:rectangle1',\n * props: {\n * terminal: 'end',\n * normalizedAnchor: { x: 0.5, y: 0.5 },\n * isExact: false,\n * isPrecise: true\n * }\n * }\n * ```\n *\n * @public\n */\nexport type TLDefaultBinding = TLArrowBinding\n\n/**\n * A type for a binding that is available in the editor but whose type is\n * unknown\u2014either one of the editor's default bindings or else a custom binding.\n * Used internally for type-safe handling of bindings with unknown structure.\n *\n * @example\n * ```ts\n * // Function that works with any binding type\n * function processBinding(binding: TLUnknownBinding) {\n * console.log(`Processing ${binding.type} binding from ${binding.fromId} to ${binding.toId}`)\n * // Handle binding properties generically\n * }\n * ```\n *\n * @public\n */\nexport type TLUnknownBinding = TLBaseBinding<string, object>\n\n/**\n * The set of all bindings that are available in the editor, including unknown bindings.\n * Bindings represent relationships between shapes, such as arrows connecting to other shapes.\n *\n * @example\n * ```ts\n * // Check binding type and handle accordingly\n * function handleBinding(binding: TLBinding) {\n * switch (binding.type) {\n * case 'arrow':\n * // Handle arrow binding\n * break\n * default:\n * // Handle unknown custom binding\n * break\n * }\n * }\n * ```\n *\n * @public\n */\nexport type TLBinding = TLDefaultBinding | TLUnknownBinding\n\n/**\n * Type for updating existing bindings with partial properties.\n * Only the id and type are required, all other properties are optional.\n *\n * @example\n * ```ts\n * // Update arrow binding properties\n * const bindingUpdate: TLBindingUpdate<TLArrowBinding> = {\n * id: 'binding:arrow1',\n * type: 'arrow',\n * props: {\n * normalizedAnchor: { x: 0.7, y: 0.3 } // Only update anchor position\n * }\n * }\n *\n * editor.updateBindings([bindingUpdate])\n * ```\n *\n * @public\n */\nexport type TLBindingUpdate<T extends TLBinding = TLBinding> = Expand<{\n\tid: TLBindingId\n\ttype: T['type']\n\ttypeName?: T['typeName']\n\tfromId?: T['fromId']\n\ttoId?: T['toId']\n\tprops?: Partial<T['props']>\n\tmeta?: Partial<T['meta']>\n}>\n\n/**\n * Type for creating new bindings with required fromId and toId.\n * The id is optional and will be generated if not provided.\n *\n * @example\n * ```ts\n * // Create a new arrow binding\n * const newBinding: TLBindingCreate<TLArrowBinding> = {\n * type: 'arrow',\n * fromId: 'shape:arrow1',\n * toId: 'shape:rectangle1',\n * props: {\n * terminal: 'end',\n * normalizedAnchor: { x: 0.5, y: 0.5 },\n * isExact: false,\n * isPrecise: true\n * }\n * }\n *\n * editor.createBindings([newBinding])\n * ```\n *\n * @public\n */\nexport type TLBindingCreate<T extends TLBinding = TLBinding> = Expand<{\n\tid?: TLBindingId\n\ttype: T['type']\n\ttypeName?: T['typeName']\n\tfromId: T['fromId']\n\ttoId: T['toId']\n\tprops?: Partial<T['props']>\n\tmeta?: Partial<T['meta']>\n}>\n\n/**\n * Branded string type for binding record identifiers.\n * Prevents mixing binding IDs with other types of record IDs at compile time.\n *\n * @example\n * ```ts\n * import { createBindingId } from '@tldraw/tlschema'\n *\n * // Create a new binding ID\n * const bindingId: TLBindingId = createBindingId()\n *\n * // Use in binding records\n * const binding: TLBinding = {\n * id: bindingId,\n * type: 'arrow',\n * fromId: 'shape:arrow1',\n * toId: 'shape:rectangle1',\n * // ... other properties\n * }\n * ```\n *\n * @public\n */\nexport type TLBindingId = RecordId<TLUnknownBinding>\n\n/**\n * Migration version identifiers for the root binding record schema.\n * Currently empty as no migrations have been applied to the base binding structure.\n *\n * @example\n * ```ts\n * // Future migrations would be defined here\n * const rootBindingVersions = createMigrationIds('com.tldraw.binding', {\n * AddNewProperty: 1,\n * } as const)\n * ```\n *\n * @public\n */\nexport const rootBindingVersions = createMigrationIds('com.tldraw.binding', {} as const)\n\n/**\n * Migration sequence for the root binding record structure.\n * Currently empty as the binding schema has not required any migrations yet.\n *\n * @example\n * ```ts\n * // Migrations would be automatically applied when loading old documents\n * const migratedStore = migrator.migrateStoreSnapshot({\n * schema: oldSchema,\n * store: oldStoreSnapshot\n * })\n * ```\n *\n * @public\n */\nexport const rootBindingMigrations = createRecordMigrationSequence({\n\tsequenceId: 'com.tldraw.binding',\n\trecordType: 'binding',\n\tsequence: [],\n})\n\n/**\n * Type guard to check if a record is a TLBinding.\n * Useful for filtering or type narrowing when working with mixed record types.\n *\n * @param record - The record to check\n * @returns True if the record is a binding, false otherwise\n *\n * @example\n * ```ts\n * // Filter bindings from mixed records\n * const allRecords = store.allRecords()\n * const bindings = allRecords.filter(isBinding)\n *\n * // Type guard usage\n * function processRecord(record: UnknownRecord) {\n * if (isBinding(record)) {\n * // record is now typed as TLBinding\n * console.log(`Binding from ${record.fromId} to ${record.toId}`)\n * }\n * }\n * ```\n *\n * @public\n */\nexport function isBinding(record?: UnknownRecord): record is TLBinding {\n\tif (!record) return false\n\treturn record.typeName === 'binding'\n}\n\n/**\n * Type guard to check if a string is a valid TLBindingId.\n * Validates that the ID follows the correct format for binding identifiers.\n *\n * @param id - The string to check\n * @returns True if the string is a valid binding ID, false otherwise\n *\n * @example\n * ```ts\n * // Validate binding IDs\n * const maybeBindingId = 'binding:abc123'\n * if (isBindingId(maybeBindingId)) {\n * // maybeBindingId is now typed as TLBindingId\n * const binding = store.get(maybeBindingId)\n * }\n *\n * // Filter binding IDs from mixed ID array\n * const mixedIds = ['shape:1', 'binding:2', 'page:3']\n * const bindingIds = mixedIds.filter(isBindingId)\n * ```\n *\n * @public\n */\nexport function isBindingId(id?: string): id is TLBindingId {\n\tif (!id) return false\n\treturn id.startsWith('binding:')\n}\n\n/**\n * Creates a new TLBindingId with proper formatting.\n * Generates a unique ID if none is provided, or formats a provided ID correctly.\n *\n * @param id - Optional custom ID suffix. If not provided, a unique ID is generated\n * @returns A properly formatted binding ID\n *\n * @example\n * ```ts\n * // Create with auto-generated ID\n * const bindingId1 = createBindingId() // 'binding:abc123'\n *\n * // Create with custom ID\n * const bindingId2 = createBindingId('myCustomBinding') // 'binding:myCustomBinding'\n *\n * // Use in binding creation\n * const binding: TLBinding = {\n * id: createBindingId(),\n * type: 'arrow',\n * fromId: 'shape:arrow1',\n * toId: 'shape:rectangle1',\n * // ... other properties\n * }\n * ```\n *\n * @public\n */\nexport function createBindingId(id?: string): TLBindingId {\n\treturn `binding:${id ?? uniqueId()}` as TLBindingId\n}\n\n/**\n * Creates a migration sequence for binding properties.\n * This is a pass-through function that validates and returns the provided migrations.\n *\n * @param migrations - The migration sequence for binding properties\n * @returns The validated migration sequence\n *\n * @example\n * ```ts\n * // Define migrations for custom binding properties\n * const myBindingMigrations = createBindingPropsMigrationSequence({\n * sequence: [\n * {\n * id: 'com.myapp.binding.custom/1.0.0',\n * up: (props) => ({ ...props, newProperty: 'default' }),\n * down: ({ newProperty, ...props }) => props\n * }\n * ]\n * })\n * ```\n *\n * @public\n */\nexport function createBindingPropsMigrationSequence(\n\tmigrations: TLPropsMigrations\n): TLPropsMigrations {\n\treturn migrations\n}\n\n/**\n * Creates properly formatted migration IDs for binding property migrations.\n * Follows the convention: 'com.tldraw.binding.\\{bindingType\\}/\\{version\\}'\n *\n * @param bindingType - The type of binding these migrations apply to\n * @param ids - Object mapping migration names to version numbers\n * @returns Object with formatted migration IDs\n *\n * @example\n * ```ts\n * // Create migration IDs for custom binding\n * const myBindingVersions = createBindingPropsMigrationIds('myCustomBinding', {\n * AddNewProperty: 1,\n * UpdateProperty: 2\n * })\n *\n * // Result:\n * // {\n * // AddNewProperty: 'com.tldraw.binding.myCustomBinding/1',\n * // UpdateProperty: 'com.tldraw.binding.myCustomBinding/2'\n * // }\n * ```\n *\n * @public\n */\nexport function createBindingPropsMigrationIds<S extends string, T extends Record<string, number>>(\n\tbindingType: S,\n\tids: T\n): { [k in keyof T]: `com.tldraw.binding.${S}/${T[k]}` } {\n\treturn mapObjectMapValues(ids, (_k, v) => `com.tldraw.binding.${bindingType}/${v}`) as any\n}\n\n/**\n * Creates a record type for TLBinding with validation based on the provided binding schemas.\n * This function is used internally to configure the binding record type in the schema.\n *\n * @param bindings - Record mapping binding type names to their schema information\n * @returns A configured record type for bindings with validation\n *\n * @example\n * ```ts\n * // Used internally when creating schemas\n * const bindingRecordType = createBindingRecordType({\n * arrow: {\n * props: arrowBindingProps,\n * meta: arrowBindingMeta\n * }\n * })\n * ```\n *\n * @internal\n */\nexport function createBindingRecordType(bindings: Record<string, SchemaPropsInfo>) {\n\treturn createRecordType<TLBinding>('binding', {\n\t\tscope: 'document',\n\t\tvalidator: T.model(\n\t\t\t'binding',\n\t\t\tT.union(\n\t\t\t\t'type',\n\t\t\t\tmapObjectMapValues(bindings, (type, { props, meta }) =>\n\t\t\t\t\tcreateBindingValidator(type, props, meta)\n\t\t\t\t)\n\t\t\t)\n\t\t),\n\t}).withDefaultProperties(() => ({\n\t\tmeta: {},\n\t}))\n}\n"],
5
- "mappings": ";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,mBAMO;AACP,mBAAqD;AACrD,sBAAkB;AAElB,2BAAsD;AA8K/C,MAAM,0BAAsB,iCAAmB,sBAAsB,CAAC,CAAU;AAiBhF,MAAM,4BAAwB,4CAA8B;AAAA,EAClE,YAAY;AAAA,EACZ,YAAY;AAAA,EACZ,UAAU,CAAC;AACZ,CAAC;AA0BM,SAAS,UAAU,QAA6C;AACtE,MAAI,CAAC,OAAQ,QAAO;AACpB,SAAO,OAAO,aAAa;AAC5B;AAyBO,SAAS,YAAY,IAAgC;AAC3D,MAAI,CAAC,GAAI,QAAO;AAChB,SAAO,GAAG,WAAW,UAAU;AAChC;AA6BO,SAAS,gBAAgB,IAA0B;AACzD,SAAO,WAAW,UAAM,uBAAS,CAAC;AACnC;AAyBO,SAAS,oCACf,YACoB;AACpB,SAAO;AACR;AA2BO,SAAS,+BACf,aACA,KACwD;AACxD,aAAO,iCAAmB,KAAK,CAAC,IAAI,MAAM,sBAAsB,WAAW,IAAI,CAAC,EAAE;AACnF;AAsBO,SAAS,wBAAwB,UAA2C;AAClF,aAAO,+BAA4B,WAAW;AAAA,IAC7C,OAAO;AAAA,IACP,WAAW,kBAAE;AAAA,MACZ;AAAA,MACA,kBAAE;AAAA,QACD;AAAA,YACA;AAAA,UAAmB;AAAA,UAAU,CAAC,MAAM,EAAE,OAAO,KAAK,UACjD,6CAAuB,MAAM,OAAO,IAAI;AAAA,QACzC;AAAA,MACD;AAAA,IACD;AAAA,EACD,CAAC,EAAE,sBAAsB,OAAO;AAAA,IAC/B,MAAM,CAAC;AAAA,EACR,EAAE;AACH;",
4
+ "sourcesContent": ["import {\n\tRecordId,\n\tUnknownRecord,\n\tcreateMigrationIds,\n\tcreateRecordMigrationSequence,\n\tcreateRecordType,\n} from '@tldraw/store'\nimport { mapObjectMapValues, uniqueId } from '@tldraw/utils'\nimport { T } from '@tldraw/validate'\nimport { TLArrowBinding } from '../bindings/TLArrowBinding'\nimport { TLBaseBinding, createBindingValidator } from '../bindings/TLBaseBinding'\nimport { SchemaPropsInfo } from '../createTLSchema'\nimport { TLPropsMigrations } from '../recordsWithProps'\n\n/**\n * The default set of bindings that are available in the editor.\n * Currently includes only arrow bindings, but can be extended with custom bindings.\n *\n * @example\n * ```ts\n * // Arrow binding connects an arrow to shapes\n * const arrowBinding: TLDefaultBinding = {\n * id: 'binding:arrow1',\n * typeName: 'binding',\n * type: 'arrow',\n * fromId: 'shape:arrow1',\n * toId: 'shape:rectangle1',\n * props: {\n * terminal: 'end',\n * normalizedAnchor: { x: 0.5, y: 0.5 },\n * isExact: false,\n * isPrecise: true\n * }\n * }\n * ```\n *\n * @public\n */\nexport type TLDefaultBinding = TLArrowBinding\n\n/**\n * A type for a binding that is available in the editor but whose type is\n * unknown\u2014either one of the editor's default bindings or else a custom binding.\n * Used internally for type-safe handling of bindings with unknown structure.\n *\n * @example\n * ```ts\n * // Function that works with any binding type\n * function processBinding(binding: TLUnknownBinding) {\n * console.log(`Processing ${binding.type} binding from ${binding.fromId} to ${binding.toId}`)\n * // Handle binding properties generically\n * }\n * ```\n *\n * @public\n */\nexport type TLUnknownBinding = TLBaseBinding<string, object>\n\n/** @public */\n// eslint-disable-next-line @typescript-eslint/no-empty-object-type\nexport interface TLGlobalBindingPropsMap {}\n\n/** @public */\n// prettier-ignore\nexport type TLIndexedBindings = {\n\t// We iterate over a union of augmented keys and default binding types.\n\t// This allows us to include (or conditionally exclude or override) the default bindings in one go.\n\t//\n\t// In the `as` clause we are filtering out disabled bindings.\n\t[K in keyof TLGlobalBindingPropsMap | TLDefaultBinding['type'] as K extends TLDefaultBinding['type']\n\t\t? K extends keyof TLGlobalBindingPropsMap\n\t\t\t? // if it extends a nullish value the user has disabled this binding type so we filter it out with never\n\t\t\t\tTLGlobalBindingPropsMap[K] extends null | undefined\n\t\t\t\t? never\n\t\t\t\t: K\n\t\t\t: K\n\t\t: K]: K extends TLDefaultBinding['type']\n\t\t\t? // if it's a default binding type we need to check if it's been overridden\n\t\t\t\tK extends keyof TLGlobalBindingPropsMap\n\t\t\t\t? // if it has been overriden then use the custom binding definition\n\t\t\t\t\tTLBaseBinding<K, TLGlobalBindingPropsMap[K]>\n\t\t\t\t: // if it has not been overriden then reuse existing type aliases for better type display\n\t\t\t\t\tExtract<TLDefaultBinding, { type: K }>\n\t\t\t: // use the custom binding definition\n\t\t\t\tTLBaseBinding<K, TLGlobalBindingPropsMap[K & keyof TLGlobalBindingPropsMap]>\n}\n\n/**\n * The set of all bindings that are available in the editor.\n * Bindings represent relationships between shapes, such as arrows connecting to other shapes.\n *\n * You can use this type without a type argument to work with any binding, or pass\n * a specific binding type string (e.g., `'arrow'`) to narrow down to that specific binding type.\n *\n * @example\n * ```ts\n * // Check binding type and handle accordingly\n * function handleBinding(binding: TLBinding) {\n * switch (binding.type) {\n * case 'arrow':\n * // Handle arrow binding\n * break\n * default:\n * // Handle unknown custom binding\n * break\n * }\n * }\n *\n * // Narrow to a specific binding type by passing the type as a generic argument\n * function getArrowSourceId(binding: TLBinding<'arrow'>) {\n * return binding.fromId // TypeScript knows this is a TLArrowBinding\n * }\n * ```\n *\n * @public\n */\nexport type TLBinding<K extends keyof TLIndexedBindings = keyof TLIndexedBindings> =\n\tTLIndexedBindings[K]\n\n/**\n * Type for updating existing bindings with partial properties.\n * Only the id and type are required, all other properties are optional.\n *\n * @example\n * ```ts\n * // Update arrow binding properties\n * const bindingUpdate: TLBindingUpdate<TLArrowBinding> = {\n * id: 'binding:arrow1',\n * type: 'arrow',\n * props: {\n * normalizedAnchor: { x: 0.7, y: 0.3 } // Only update anchor position\n * }\n * }\n *\n * editor.updateBindings([bindingUpdate])\n * ```\n *\n * @public\n */\nexport type TLBindingUpdate<T extends TLBinding = TLBinding> = T extends T\n\t? {\n\t\t\tid: TLBindingId\n\t\t\ttype: T['type']\n\t\t\ttypeName?: T['typeName']\n\t\t\tfromId?: T['fromId']\n\t\t\ttoId?: T['toId']\n\t\t\tprops?: Partial<T['props']>\n\t\t\tmeta?: Partial<T['meta']>\n\t\t}\n\t: never\n\n/**\n * Type for creating new bindings with required fromId and toId.\n * The id is optional and will be generated if not provided.\n *\n * @example\n * ```ts\n * // Create a new arrow binding\n * const newBinding: TLBindingCreate<TLArrowBinding> = {\n * type: 'arrow',\n * fromId: 'shape:arrow1',\n * toId: 'shape:rectangle1',\n * props: {\n * terminal: 'end',\n * normalizedAnchor: { x: 0.5, y: 0.5 },\n * isExact: false,\n * isPrecise: true\n * }\n * }\n *\n * editor.createBindings([newBinding])\n * ```\n *\n * @public\n */\nexport type TLBindingCreate<T extends TLBinding = TLBinding> = T extends T\n\t? {\n\t\t\tid?: TLBindingId\n\t\t\ttype: T['type']\n\t\t\ttypeName?: T['typeName']\n\t\t\tfromId: T['fromId']\n\t\t\ttoId: T['toId']\n\t\t\tprops?: Partial<T['props']>\n\t\t\tmeta?: Partial<T['meta']>\n\t\t}\n\t: never\n\n/**\n * Branded string type for binding record identifiers.\n * Prevents mixing binding IDs with other types of record IDs at compile time.\n *\n * @example\n * ```ts\n * import { createBindingId } from '@tldraw/tlschema'\n *\n * // Create a new binding ID\n * const bindingId: TLBindingId = createBindingId()\n *\n * // Use in binding records\n * const binding: TLBinding = {\n * id: bindingId,\n * type: 'arrow',\n * fromId: 'shape:arrow1',\n * toId: 'shape:rectangle1',\n * // ... other properties\n * }\n * ```\n *\n * @public\n */\nexport type TLBindingId = RecordId<TLBinding>\n\n/**\n * Migration version identifiers for the root binding record schema.\n * Currently empty as no migrations have been applied to the base binding structure.\n *\n * @example\n * ```ts\n * // Future migrations would be defined here\n * const rootBindingVersions = createMigrationIds('com.tldraw.binding', {\n * AddNewProperty: 1,\n * } as const)\n * ```\n *\n * @public\n */\nexport const rootBindingVersions = createMigrationIds('com.tldraw.binding', {} as const)\n\n/**\n * Migration sequence for the root binding record structure.\n * Currently empty as the binding schema has not required any migrations yet.\n *\n * @example\n * ```ts\n * // Migrations would be automatically applied when loading old documents\n * const migratedStore = migrator.migrateStoreSnapshot({\n * schema: oldSchema,\n * store: oldStoreSnapshot\n * })\n * ```\n *\n * @public\n */\nexport const rootBindingMigrations = createRecordMigrationSequence({\n\tsequenceId: 'com.tldraw.binding',\n\trecordType: 'binding',\n\tsequence: [],\n})\n\n/**\n * Type guard to check if a record is a TLBinding.\n * Useful for filtering or type narrowing when working with mixed record types.\n *\n * @param record - The record to check\n * @returns True if the record is a binding, false otherwise\n *\n * @example\n * ```ts\n * // Filter bindings from mixed records\n * const allRecords = store.allRecords()\n * const bindings = allRecords.filter(isBinding)\n *\n * // Type guard usage\n * function processRecord(record: UnknownRecord) {\n * if (isBinding(record)) {\n * // record is now typed as TLBinding\n * console.log(`Binding from ${record.fromId} to ${record.toId}`)\n * }\n * }\n * ```\n *\n * @public\n */\nexport function isBinding(record?: UnknownRecord): record is TLBinding {\n\tif (!record) return false\n\treturn record.typeName === 'binding'\n}\n\n/**\n * Type guard to check if a string is a valid TLBindingId.\n * Validates that the ID follows the correct format for binding identifiers.\n *\n * @param id - The string to check\n * @returns True if the string is a valid binding ID, false otherwise\n *\n * @example\n * ```ts\n * // Validate binding IDs\n * const maybeBindingId = 'binding:abc123'\n * if (isBindingId(maybeBindingId)) {\n * // maybeBindingId is now typed as TLBindingId\n * const binding = store.get(maybeBindingId)\n * }\n *\n * // Filter binding IDs from mixed ID array\n * const mixedIds = ['shape:1', 'binding:2', 'page:3']\n * const bindingIds = mixedIds.filter(isBindingId)\n * ```\n *\n * @public\n */\nexport function isBindingId(id?: string): id is TLBindingId {\n\tif (!id) return false\n\treturn id.startsWith('binding:')\n}\n\n/**\n * Creates a new TLBindingId with proper formatting.\n * Generates a unique ID if none is provided, or formats a provided ID correctly.\n *\n * @param id - Optional custom ID suffix. If not provided, a unique ID is generated\n * @returns A properly formatted binding ID\n *\n * @example\n * ```ts\n * // Create with auto-generated ID\n * const bindingId1 = createBindingId() // 'binding:abc123'\n *\n * // Create with custom ID\n * const bindingId2 = createBindingId('myCustomBinding') // 'binding:myCustomBinding'\n *\n * // Use in binding creation\n * const binding: TLBinding = {\n * id: createBindingId(),\n * type: 'arrow',\n * fromId: 'shape:arrow1',\n * toId: 'shape:rectangle1',\n * // ... other properties\n * }\n * ```\n *\n * @public\n */\nexport function createBindingId(id?: string): TLBindingId {\n\treturn `binding:${id ?? uniqueId()}` as TLBindingId\n}\n\n/**\n * Creates a migration sequence for binding properties.\n * This is a pass-through function that validates and returns the provided migrations.\n *\n * @param migrations - The migration sequence for binding properties\n * @returns The validated migration sequence\n *\n * @example\n * ```ts\n * // Define migrations for custom binding properties\n * const myBindingMigrations = createBindingPropsMigrationSequence({\n * sequence: [\n * {\n * id: 'com.myapp.binding.custom/1.0.0',\n * up: (props) => ({ ...props, newProperty: 'default' }),\n * down: ({ newProperty, ...props }) => props\n * }\n * ]\n * })\n * ```\n *\n * @public\n */\nexport function createBindingPropsMigrationSequence(\n\tmigrations: TLPropsMigrations\n): TLPropsMigrations {\n\treturn migrations\n}\n\n/**\n * Creates properly formatted migration IDs for binding property migrations.\n * Follows the convention: 'com.tldraw.binding.\\{bindingType\\}/\\{version\\}'\n *\n * @param bindingType - The type of binding these migrations apply to\n * @param ids - Object mapping migration names to version numbers\n * @returns Object with formatted migration IDs\n *\n * @example\n * ```ts\n * // Create migration IDs for custom binding\n * const myBindingVersions = createBindingPropsMigrationIds('myCustomBinding', {\n * AddNewProperty: 1,\n * UpdateProperty: 2\n * })\n *\n * // Result:\n * // {\n * // AddNewProperty: 'com.tldraw.binding.myCustomBinding/1',\n * // UpdateProperty: 'com.tldraw.binding.myCustomBinding/2'\n * // }\n * ```\n *\n * @public\n */\nexport function createBindingPropsMigrationIds<S extends string, T extends Record<string, number>>(\n\tbindingType: S,\n\tids: T\n): { [k in keyof T]: `com.tldraw.binding.${S}/${T[k]}` } {\n\treturn mapObjectMapValues(ids, (_k, v) => `com.tldraw.binding.${bindingType}/${v}`) as any\n}\n\n/**\n * Creates a record type for TLBinding with validation based on the provided binding schemas.\n * This function is used internally to configure the binding record type in the schema.\n *\n * @param bindings - Record mapping binding type names to their schema information\n * @returns A configured record type for bindings with validation\n *\n * @example\n * ```ts\n * // Used internally when creating schemas\n * const bindingRecordType = createBindingRecordType({\n * arrow: {\n * props: arrowBindingProps,\n * meta: arrowBindingMeta\n * }\n * })\n * ```\n *\n * @internal\n */\nexport function createBindingRecordType(bindings: Record<string, SchemaPropsInfo>) {\n\treturn createRecordType('binding', {\n\t\tscope: 'document',\n\t\tvalidator: T.model(\n\t\t\t'binding',\n\t\t\tT.union(\n\t\t\t\t'type',\n\t\t\t\tmapObjectMapValues(bindings, (type, { props, meta }) =>\n\t\t\t\t\tcreateBindingValidator(type, props, meta)\n\t\t\t\t)\n\t\t\t)\n\t\t),\n\t}).withDefaultProperties(() => ({\n\t\tmeta: {},\n\t}))\n}\n"],
5
+ "mappings": ";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,mBAMO;AACP,mBAA6C;AAC7C,sBAAkB;AAElB,2BAAsD;AAwN/C,MAAM,0BAAsB,iCAAmB,sBAAsB,CAAC,CAAU;AAiBhF,MAAM,4BAAwB,4CAA8B;AAAA,EAClE,YAAY;AAAA,EACZ,YAAY;AAAA,EACZ,UAAU,CAAC;AACZ,CAAC;AA0BM,SAAS,UAAU,QAA6C;AACtE,MAAI,CAAC,OAAQ,QAAO;AACpB,SAAO,OAAO,aAAa;AAC5B;AAyBO,SAAS,YAAY,IAAgC;AAC3D,MAAI,CAAC,GAAI,QAAO;AAChB,SAAO,GAAG,WAAW,UAAU;AAChC;AA6BO,SAAS,gBAAgB,IAA0B;AACzD,SAAO,WAAW,UAAM,uBAAS,CAAC;AACnC;AAyBO,SAAS,oCACf,YACoB;AACpB,SAAO;AACR;AA2BO,SAAS,+BACf,aACA,KACwD;AACxD,aAAO,iCAAmB,KAAK,CAAC,IAAI,MAAM,sBAAsB,WAAW,IAAI,CAAC,EAAE;AACnF;AAsBO,SAAS,wBAAwB,UAA2C;AAClF,aAAO,+BAAiB,WAAW;AAAA,IAClC,OAAO;AAAA,IACP,WAAW,kBAAE;AAAA,MACZ;AAAA,MACA,kBAAE;AAAA,QACD;AAAA,YACA;AAAA,UAAmB;AAAA,UAAU,CAAC,MAAM,EAAE,OAAO,KAAK,UACjD,6CAAuB,MAAM,OAAO,IAAI;AAAA,QACzC;AAAA,MACD;AAAA,IACD;AAAA,EACD,CAAC,EAAE,sBAAsB,OAAO;AAAA,IAC/B,MAAM,CAAC;AAAA,EACR,EAAE;AACH;",
6
6
  "names": []
7
7
  }
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../src/records/TLShape.ts"],
4
- "sourcesContent": ["import {\n\tRecordId,\n\tUnknownRecord,\n\tcreateMigrationIds,\n\tcreateRecordMigrationSequence,\n\tcreateRecordType,\n} from '@tldraw/store'\nimport { mapObjectMapValues, uniqueId } from '@tldraw/utils'\nimport { T } from '@tldraw/validate'\nimport { SchemaPropsInfo } from '../createTLSchema'\nimport { TLPropsMigrations } from '../recordsWithProps'\nimport { TLArrowShape } from '../shapes/TLArrowShape'\nimport { TLBaseShape, createShapeValidator } from '../shapes/TLBaseShape'\nimport { TLBookmarkShape } from '../shapes/TLBookmarkShape'\nimport { TLDrawShape } from '../shapes/TLDrawShape'\nimport { TLEmbedShape } from '../shapes/TLEmbedShape'\nimport { TLFrameShape } from '../shapes/TLFrameShape'\nimport { TLGeoShape } from '../shapes/TLGeoShape'\nimport { TLGroupShape } from '../shapes/TLGroupShape'\nimport { TLHighlightShape } from '../shapes/TLHighlightShape'\nimport { TLImageShape } from '../shapes/TLImageShape'\nimport { TLLineShape } from '../shapes/TLLineShape'\nimport { TLNoteShape } from '../shapes/TLNoteShape'\nimport { TLTextShape } from '../shapes/TLTextShape'\nimport { TLVideoShape } from '../shapes/TLVideoShape'\nimport { StyleProp } from '../styles/StyleProp'\nimport { TLPageId } from './TLPage'\n\n/**\n * The default set of shapes that are available in the editor.\n *\n * This union type represents all the built-in shape types supported by tldraw,\n * including arrows, bookmarks, drawings, embeds, frames, geometry shapes,\n * groups, images, lines, notes, text, videos, and highlights.\n *\n * @example\n * ```ts\n * // Check if a shape is a default shape type\n * function isDefaultShape(shape: TLShape): shape is TLDefaultShape {\n * const defaultTypes = ['arrow', 'bookmark', 'draw', 'embed', 'frame', 'geo', 'group', 'image', 'line', 'note', 'text', 'video', 'highlight']\n * return defaultTypes.includes(shape.type)\n * }\n * ```\n *\n * @public\n */\nexport type TLDefaultShape =\n\t| TLArrowShape\n\t| TLBookmarkShape\n\t| TLDrawShape\n\t| TLEmbedShape\n\t| TLFrameShape\n\t| TLGeoShape\n\t| TLGroupShape\n\t| TLImageShape\n\t| TLLineShape\n\t| TLNoteShape\n\t| TLTextShape\n\t| TLVideoShape\n\t| TLHighlightShape\n\n/**\n * A type for a shape that is available in the editor but whose type is\n * unknown\u2014either one of the editor's default shapes or else a custom shape.\n *\n * This is useful when working with shapes generically without knowing their specific type.\n * The shape type is a string and props are a generic object.\n *\n * @example\n * ```ts\n * // Handle any shape regardless of its specific type\n * function processUnknownShape(shape: TLUnknownShape) {\n * console.log(`Processing shape of type: ${shape.type}`)\n * console.log(`Position: (${shape.x}, ${shape.y})`)\n * }\n * ```\n *\n * @public\n */\nexport type TLUnknownShape = TLBaseShape<string, object>\n\n/**\n * The set of all shapes that are available in the editor, including unknown shapes.\n *\n * This is the primary shape type used throughout tldraw. It includes both the\n * built-in default shapes and any custom shapes that might be added.\n *\n * @example\n * ```ts\n * // Work with any shape in the editor\n * function moveShape(shape: TLShape, deltaX: number, deltaY: number): TLShape {\n * return {\n * ...shape,\n * x: shape.x + deltaX,\n * y: shape.y + deltaY\n * }\n * }\n * ```\n *\n * @public\n */\nexport type TLShape = TLDefaultShape | TLUnknownShape\n\n/**\n * A partial version of a shape, useful for updates and patches.\n *\n * This type represents a shape where all properties except `id` and `type` are optional.\n * It's commonly used when updating existing shapes or creating shape patches.\n *\n * @example\n * ```ts\n * // Update a shape's position\n * const shapeUpdate: TLShapePartial = {\n * id: 'shape:123',\n * type: 'geo',\n * x: 100,\n * y: 200\n * }\n *\n * // Update shape properties\n * const propsUpdate: TLShapePartial<TLGeoShape> = {\n * id: 'shape:123',\n * type: 'geo',\n * props: {\n * w: 150,\n * h: 100\n * }\n * }\n * ```\n *\n * @public\n */\nexport type TLShapePartial<T extends TLShape = TLShape> = T extends T\n\t? {\n\t\t\tid: TLShapeId\n\t\t\ttype: T['type']\n\t\t\tprops?: Partial<T['props']>\n\t\t\tmeta?: Partial<T['meta']>\n\t\t} & Partial<Omit<T, 'type' | 'id' | 'props' | 'meta'>>\n\t: never\n\n/**\n * A unique identifier for a shape record.\n *\n * Shape IDs are branded strings that start with \"shape:\" followed by a unique identifier.\n * This type-safe approach prevents mixing up different types of record IDs.\n *\n * @example\n * ```ts\n * const shapeId: TLShapeId = createShapeId() // \"shape:abc123\"\n * const customId: TLShapeId = createShapeId('my-custom-id') // \"shape:my-custom-id\"\n * ```\n *\n * @public\n */\nexport type TLShapeId = RecordId<TLUnknownShape>\n\n/**\n * The ID of a shape's parent, which can be either a page or another shape.\n *\n * Shapes can be parented to pages (for top-level shapes) or to other shapes\n * (for shapes inside frames or groups).\n *\n * @example\n * ```ts\n * // Shape parented to a page\n * const pageParentId: TLParentId = 'page:main'\n *\n * // Shape parented to another shape (e.g., inside a frame)\n * const shapeParentId: TLParentId = 'shape:frame123'\n * ```\n *\n * @public\n */\nexport type TLParentId = TLPageId | TLShapeId\n\n/**\n * Migration version IDs for the root shape schema.\n *\n * These track the evolution of the base shape structure over time, ensuring\n * that shapes created in older versions can be migrated to newer formats.\n *\n * @example\n * ```ts\n * // Check if a migration needs to be applied\n * if (shapeVersion < rootShapeVersions.AddIsLocked) {\n * // Apply isLocked migration\n * }\n * ```\n *\n * @public\n */\nexport const rootShapeVersions = createMigrationIds('com.tldraw.shape', {\n\tAddIsLocked: 1,\n\tHoistOpacity: 2,\n\tAddMeta: 3,\n\tAddWhite: 4,\n} as const)\n\n/**\n * Migration sequence for the root shape record type.\n *\n * This sequence defines how shape records should be transformed when migrating\n * between different schema versions. Each migration handles a specific version\n * upgrade, ensuring data compatibility across tldraw versions.\n *\n * @public\n */\nexport const rootShapeMigrations = createRecordMigrationSequence({\n\tsequenceId: 'com.tldraw.shape',\n\trecordType: 'shape',\n\tsequence: [\n\t\t{\n\t\t\tid: rootShapeVersions.AddIsLocked,\n\t\t\tup: (record: any) => {\n\t\t\t\trecord.isLocked = false\n\t\t\t},\n\t\t\tdown: (record: any) => {\n\t\t\t\tdelete record.isLocked\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tid: rootShapeVersions.HoistOpacity,\n\t\t\tup: (record: any) => {\n\t\t\t\trecord.opacity = Number(record.props.opacity ?? '1')\n\t\t\t\tdelete record.props.opacity\n\t\t\t},\n\t\t\tdown: (record: any) => {\n\t\t\t\tconst opacity = record.opacity\n\t\t\t\tdelete record.opacity\n\t\t\t\trecord.props.opacity =\n\t\t\t\t\topacity < 0.175\n\t\t\t\t\t\t? '0.1'\n\t\t\t\t\t\t: opacity < 0.375\n\t\t\t\t\t\t\t? '0.25'\n\t\t\t\t\t\t\t: opacity < 0.625\n\t\t\t\t\t\t\t\t? '0.5'\n\t\t\t\t\t\t\t\t: opacity < 0.875\n\t\t\t\t\t\t\t\t\t? '0.75'\n\t\t\t\t\t\t\t\t\t: '1'\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tid: rootShapeVersions.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: rootShapeVersions.AddWhite,\n\t\t\tup: (_record) => {\n\t\t\t\t// noop\n\t\t\t},\n\t\t\tdown: (record: any) => {\n\t\t\t\tif (record.props.color === 'white') {\n\t\t\t\t\trecord.props.color = 'black'\n\t\t\t\t}\n\t\t\t},\n\t\t},\n\t],\n})\n\n/**\n * Type guard to check if a record is a shape.\n *\n * @param record - The record to check\n * @returns True if the record is a shape, false otherwise\n *\n * @example\n * ```ts\n * const record = store.get('shape:abc123')\n * if (isShape(record)) {\n * console.log(`Shape type: ${record.type}`)\n * console.log(`Position: (${record.x}, ${record.y})`)\n * }\n * ```\n *\n * @public\n */\nexport function isShape(record?: UnknownRecord): record is TLShape {\n\tif (!record) return false\n\treturn record.typeName === 'shape'\n}\n\n/**\n * Type guard to check if a string is a valid shape ID.\n *\n * @param id - The string to check\n * @returns True if the string is a valid shape ID, false otherwise\n *\n * @example\n * ```ts\n * const id = 'shape:abc123'\n * if (isShapeId(id)) {\n * const shape = store.get(id) // TypeScript knows id is TLShapeId\n * }\n *\n * // Check user input\n * function selectShape(id: string) {\n * if (isShapeId(id)) {\n * editor.selectShape(id)\n * } else {\n * console.error('Invalid shape ID format')\n * }\n * }\n * ```\n *\n * @public\n */\nexport function isShapeId(id?: string): id is TLShapeId {\n\tif (!id) return false\n\treturn id.startsWith('shape:')\n}\n\n/**\n * Creates a new shape ID.\n *\n * @param id - Optional custom ID suffix. If not provided, a unique ID will be generated\n * @returns A new shape ID with the \"shape:\" prefix\n *\n * @example\n * ```ts\n * // Create a shape with auto-generated ID\n * const shapeId = createShapeId() // \"shape:abc123\"\n *\n * // Create a shape with custom ID\n * const customShapeId = createShapeId('my-rectangle') // \"shape:my-rectangle\"\n *\n * // Use in shape creation\n * const newShape: TLGeoShape = {\n * id: createShapeId(),\n * type: 'geo',\n * x: 100,\n * y: 200,\n * // ... other properties\n * }\n * ```\n *\n * @public\n */\nexport function createShapeId(id?: string): TLShapeId {\n\treturn `shape:${id ?? uniqueId()}` as TLShapeId\n}\n\n/**\n * Extracts style properties from a shape's props definition and maps them to their property keys.\n *\n * This function analyzes shape property validators to identify which ones are style properties\n * and creates a mapping from StyleProp instances to their corresponding property keys.\n * It also validates that each style property is only used once per shape.\n *\n * @param props - Record of property validators for a shape type\n * @returns Map from StyleProp instances to their property keys\n * @throws Error if a style property is used more than once in the same shape\n *\n * @example\n * ```ts\n * const geoShapeProps = {\n * color: DefaultColorStyle,\n * fill: DefaultFillStyle,\n * width: T.number,\n * height: T.number\n * }\n *\n * const styleMap = getShapePropKeysByStyle(geoShapeProps)\n * // styleMap.get(DefaultColorStyle) === 'color'\n * // styleMap.get(DefaultFillStyle) === 'fill'\n * ```\n *\n * @internal\n */\nexport function getShapePropKeysByStyle(props: Record<string, T.Validatable<any>>) {\n\tconst propKeysByStyle = new Map<StyleProp<unknown>, string>()\n\tfor (const [key, prop] of Object.entries(props)) {\n\t\tif (prop instanceof StyleProp) {\n\t\t\tif (propKeysByStyle.has(prop)) {\n\t\t\t\tthrow new Error(\n\t\t\t\t\t`Duplicate style prop ${prop.id}. Each style prop can only be used once within a shape.`\n\t\t\t\t)\n\t\t\t}\n\t\t\tpropKeysByStyle.set(prop, key)\n\t\t}\n\t}\n\treturn propKeysByStyle\n}\n\n/**\n * Creates a migration sequence for shape properties.\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 shape property 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 myShapeMigrations = createShapePropsMigrationSequence({\n * sequence: [\n * {\n * id: 'com.myapp.shape.custom/1.0.0',\n * up: (props) => ({ ...props, newProperty: 'default' }),\n * down: ({ newProperty, ...props }) => props\n * }\n * ]\n * })\n * ```\n *\n * @public\n */\nexport function createShapePropsMigrationSequence(\n\tmigrations: TLPropsMigrations\n): TLPropsMigrations {\n\treturn migrations\n}\n\n/**\n * Creates properly formatted migration IDs for shape properties.\n *\n * Generates standardized migration IDs following the convention:\n * `com.tldraw.shape.{shapeType}/{version}`\n *\n * @param shapeType - The type of shape these migrations apply to\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 myShapeVersions = createShapePropsMigrationIds('custom', {\n * AddColor: 1,\n * AddSize: 2,\n * RefactorProps: 3\n * })\n * // Result: {\n * // AddColor: 'com.tldraw.shape.custom/1',\n * // AddSize: 'com.tldraw.shape.custom/2',\n * // RefactorProps: 'com.tldraw.shape.custom/3'\n * // }\n * ```\n *\n * @public\n */\nexport function createShapePropsMigrationIds<\n\tconst S extends string,\n\tconst T extends Record<string, number>,\n>(shapeType: S, ids: T): { [k in keyof T]: `com.tldraw.shape.${S}/${T[k]}` } {\n\treturn mapObjectMapValues(ids, (_k, v) => `com.tldraw.shape.${shapeType}/${v}`) as any\n}\n\n/**\n * Creates the record type definition for shapes.\n *\n * This function generates a complete record type for shapes that includes validation\n * for all registered shape types. It combines the base shape properties with\n * type-specific properties and creates a union validator that can handle any\n * registered shape type.\n *\n * @param shapes - Record of shape type names to their schema configuration\n * @returns A complete RecordType for shapes with proper validation and default properties\n *\n * @example\n * ```ts\n * const shapeRecordType = createShapeRecordType({\n * geo: { props: geoShapeProps, migrations: geoMigrations },\n * arrow: { props: arrowShapeProps, migrations: arrowMigrations }\n * })\n * ```\n *\n * @internal\n */\nexport function createShapeRecordType(shapes: Record<string, SchemaPropsInfo>) {\n\treturn createRecordType<TLShape>('shape', {\n\t\tscope: 'document',\n\t\tvalidator: T.model(\n\t\t\t'shape',\n\t\t\tT.union(\n\t\t\t\t'type',\n\t\t\t\tmapObjectMapValues(shapes, (type, { props, meta }) =>\n\t\t\t\t\tcreateShapeValidator(type, props, meta)\n\t\t\t\t)\n\t\t\t)\n\t\t),\n\t}).withDefaultProperties(() => ({\n\t\tx: 0,\n\t\ty: 0,\n\t\trotation: 0,\n\t\tisLocked: false,\n\t\topacity: 1,\n\t\tmeta: {},\n\t}))\n}\n"],
5
- "mappings": ";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,mBAMO;AACP,mBAA6C;AAC7C,sBAAkB;AAIlB,yBAAkD;AAalD,uBAA0B;AAuKnB,MAAM,wBAAoB,iCAAmB,oBAAoB;AAAA,EACvE,aAAa;AAAA,EACb,cAAc;AAAA,EACd,SAAS;AAAA,EACT,UAAU;AACX,CAAU;AAWH,MAAM,0BAAsB,4CAA8B;AAAA,EAChE,YAAY;AAAA,EACZ,YAAY;AAAA,EACZ,UAAU;AAAA,IACT;AAAA,MACC,IAAI,kBAAkB;AAAA,MACtB,IAAI,CAAC,WAAgB;AACpB,eAAO,WAAW;AAAA,MACnB;AAAA,MACA,MAAM,CAAC,WAAgB;AACtB,eAAO,OAAO;AAAA,MACf;AAAA,IACD;AAAA,IACA;AAAA,MACC,IAAI,kBAAkB;AAAA,MACtB,IAAI,CAAC,WAAgB;AACpB,eAAO,UAAU,OAAO,OAAO,MAAM,WAAW,GAAG;AACnD,eAAO,OAAO,MAAM;AAAA,MACrB;AAAA,MACA,MAAM,CAAC,WAAgB;AACtB,cAAM,UAAU,OAAO;AACvB,eAAO,OAAO;AACd,eAAO,MAAM,UACZ,UAAU,QACP,QACA,UAAU,QACT,SACA,UAAU,QACT,QACA,UAAU,QACT,SACA;AAAA,MACR;AAAA,IACD;AAAA,IACA;AAAA,MACC,IAAI,kBAAkB;AAAA,MACtB,IAAI,CAAC,WAAgB;AACpB,eAAO,OAAO,CAAC;AAAA,MAChB;AAAA,IACD;AAAA,IACA;AAAA,MACC,IAAI,kBAAkB;AAAA,MACtB,IAAI,CAAC,YAAY;AAAA,MAEjB;AAAA,MACA,MAAM,CAAC,WAAgB;AACtB,YAAI,OAAO,MAAM,UAAU,SAAS;AACnC,iBAAO,MAAM,QAAQ;AAAA,QACtB;AAAA,MACD;AAAA,IACD;AAAA,EACD;AACD,CAAC;AAmBM,SAAS,QAAQ,QAA2C;AAClE,MAAI,CAAC,OAAQ,QAAO;AACpB,SAAO,OAAO,aAAa;AAC5B;AA2BO,SAAS,UAAU,IAA8B;AACvD,MAAI,CAAC,GAAI,QAAO;AAChB,SAAO,GAAG,WAAW,QAAQ;AAC9B;AA4BO,SAAS,cAAc,IAAwB;AACrD,SAAO,SAAS,UAAM,uBAAS,CAAC;AACjC;AA6BO,SAAS,wBAAwB,OAA2C;AAClF,QAAM,kBAAkB,oBAAI,IAAgC;AAC5D,aAAW,CAAC,KAAK,IAAI,KAAK,OAAO,QAAQ,KAAK,GAAG;AAChD,QAAI,gBAAgB,4BAAW;AAC9B,UAAI,gBAAgB,IAAI,IAAI,GAAG;AAC9B,cAAM,IAAI;AAAA,UACT,wBAAwB,KAAK,EAAE;AAAA,QAChC;AAAA,MACD;AACA,sBAAgB,IAAI,MAAM,GAAG;AAAA,IAC9B;AAAA,EACD;AACA,SAAO;AACR;AA0BO,SAAS,kCACf,YACoB;AACpB,SAAO;AACR;AA4BO,SAAS,6BAGd,WAAc,KAA6D;AAC5E,aAAO,iCAAmB,KAAK,CAAC,IAAI,MAAM,oBAAoB,SAAS,IAAI,CAAC,EAAE;AAC/E;AAuBO,SAAS,sBAAsB,QAAyC;AAC9E,aAAO,+BAA0B,SAAS;AAAA,IACzC,OAAO;AAAA,IACP,WAAW,kBAAE;AAAA,MACZ;AAAA,MACA,kBAAE;AAAA,QACD;AAAA,YACA;AAAA,UAAmB;AAAA,UAAQ,CAAC,MAAM,EAAE,OAAO,KAAK,UAC/C,yCAAqB,MAAM,OAAO,IAAI;AAAA,QACvC;AAAA,MACD;AAAA,IACD;AAAA,EACD,CAAC,EAAE,sBAAsB,OAAO;AAAA,IAC/B,GAAG;AAAA,IACH,GAAG;AAAA,IACH,UAAU;AAAA,IACV,UAAU;AAAA,IACV,SAAS;AAAA,IACT,MAAM,CAAC;AAAA,EACR,EAAE;AACH;",
4
+ "sourcesContent": ["import {\n\tRecordId,\n\tUnknownRecord,\n\tcreateMigrationIds,\n\tcreateRecordMigrationSequence,\n\tcreateRecordType,\n} from '@tldraw/store'\nimport { mapObjectMapValues, uniqueId } from '@tldraw/utils'\nimport { T } from '@tldraw/validate'\nimport { SchemaPropsInfo } from '../createTLSchema'\nimport { TLPropsMigrations } from '../recordsWithProps'\nimport { TLArrowShape } from '../shapes/TLArrowShape'\nimport { TLBaseShape, createShapeValidator } from '../shapes/TLBaseShape'\nimport { TLBookmarkShape } from '../shapes/TLBookmarkShape'\nimport { TLDrawShape } from '../shapes/TLDrawShape'\nimport { TLEmbedShape } from '../shapes/TLEmbedShape'\nimport { TLFrameShape } from '../shapes/TLFrameShape'\nimport { TLGeoShape } from '../shapes/TLGeoShape'\nimport { TLGroupShape } from '../shapes/TLGroupShape'\nimport { TLHighlightShape } from '../shapes/TLHighlightShape'\nimport { TLImageShape } from '../shapes/TLImageShape'\nimport { TLLineShape } from '../shapes/TLLineShape'\nimport { TLNoteShape } from '../shapes/TLNoteShape'\nimport { TLTextShape } from '../shapes/TLTextShape'\nimport { TLVideoShape } from '../shapes/TLVideoShape'\nimport { StyleProp } from '../styles/StyleProp'\nimport { TLPageId } from './TLPage'\n\n/**\n * The default set of shapes that are available in the editor.\n *\n * This union type represents all the built-in shape types supported by tldraw,\n * including arrows, bookmarks, drawings, embeds, frames, geometry shapes,\n * groups, images, lines, notes, text, videos, and highlights.\n *\n * @example\n * ```ts\n * // Check if a shape is a default shape type\n * function isDefaultShape(shape: TLShape): shape is TLDefaultShape {\n * const defaultTypes = ['arrow', 'bookmark', 'draw', 'embed', 'frame', 'geo', 'group', 'image', 'line', 'note', 'text', 'video', 'highlight']\n * return defaultTypes.includes(shape.type)\n * }\n * ```\n *\n * @public\n */\nexport type TLDefaultShape =\n\t| TLArrowShape\n\t| TLBookmarkShape\n\t| TLDrawShape\n\t| TLEmbedShape\n\t| TLFrameShape\n\t| TLGeoShape\n\t| TLGroupShape\n\t| TLImageShape\n\t| TLLineShape\n\t| TLNoteShape\n\t| TLTextShape\n\t| TLVideoShape\n\t| TLHighlightShape\n\n/**\n * A type for a shape that is available in the editor but whose type is\n * unknown\u2014either one of the editor's default shapes or else a custom shape.\n *\n * This is useful when working with shapes generically without knowing their specific type.\n * The shape type is a string and props are a generic object.\n *\n * @example\n * ```ts\n * // Handle any shape regardless of its specific type\n * function processUnknownShape(shape: TLUnknownShape) {\n * console.log(`Processing shape of type: ${shape.type}`)\n * console.log(`Position: (${shape.x}, ${shape.y})`)\n * }\n * ```\n *\n * @public\n */\nexport type TLUnknownShape = TLBaseShape<string, object>\n\n/** @public */\n// eslint-disable-next-line @typescript-eslint/no-empty-object-type\nexport interface TLGlobalShapePropsMap {}\n\n/** @public */\n// prettier-ignore\nexport type TLIndexedShapes = {\n\t// We iterate over a union of augmented keys and default shape types.\n\t// This allows us to include (or conditionally exclude or override) the default shapes in one go.\n\t//\n\t// In the `as` clause we are filtering out disabled shapes.\n\t[K in keyof TLGlobalShapePropsMap | TLDefaultShape['type'] as K extends TLDefaultShape['type']\n\t\t? // core shapes are always available and cannot be overridden so we just include them\n\t\t\tK extends 'group'\n\t\t\t? K\n\t\t\t: K extends keyof TLGlobalShapePropsMap\n\t\t\t\t? // if it extends a nullish value the user has disabled this shape type so we filter it out with never\n\t\t\t\t\tTLGlobalShapePropsMap[K] extends null | undefined\n\t\t\t\t\t? never\n\t\t\t\t\t: K\n\t\t\t\t: K\n\t\t: K]: K extends 'group'\n\t\t? // core shapes are always available and cannot be overridden so we just include them\n\t\t\tExtract<TLDefaultShape, { type: K }>\n\t\t: K extends TLDefaultShape['type']\n\t\t\t? // if it's a default shape type we need to check if it's been overridden\n\t\t\t\tK extends keyof TLGlobalShapePropsMap\n\t\t\t\t? // if it has been overriden then use the custom shape definition\n\t\t\t\t\tTLBaseShape<K, TLGlobalShapePropsMap[K]>\n\t\t\t\t: // if it has not been overriden then reuse existing type aliases for better type display\n\t\t\t\t\tExtract<TLDefaultShape, { type: K }>\n\t\t\t: // use the custom shape definition\n\t\t\t\tTLBaseShape<K, TLGlobalShapePropsMap[K & keyof TLGlobalShapePropsMap]>\n}\n\n/**\n * The set of all shapes that are available in the editor.\n *\n * This is the primary shape type used throughout tldraw. It includes both the\n * built-in default shapes and any custom shapes that might be added.\n *\n * You can use this type without a type argument to work with any shape, or pass\n * a specific shape type string (e.g., `'geo'`, `'arrow'`, `'text'`) to narrow\n * down to that specific shape type.\n *\n * @example\n * ```ts\n * // Work with any shape in the editor\n * function moveShape(shape: TLShape, deltaX: number, deltaY: number): TLShape {\n * return {\n * ...shape,\n * x: shape.x + deltaX,\n * y: shape.y + deltaY\n * }\n * }\n *\n * // Narrow to a specific shape type by passing the type as a generic argument\n * function getArrowLabel(shape: TLShape<'arrow'>): string {\n * return shape.props.text // TypeScript knows this is a TLArrowShape\n * }\n * ```\n *\n * @public\n */\nexport type TLShape<K extends keyof TLIndexedShapes = keyof TLIndexedShapes> = TLIndexedShapes[K]\n\n/**\n * A partial version of a shape, useful for updates and patches.\n *\n * This type represents a shape where all properties except `id` and `type` are optional.\n * It's commonly used when updating existing shapes or creating shape patches.\n *\n * @example\n * ```ts\n * // Update a shape's position\n * const shapeUpdate: TLShapePartial = {\n * id: 'shape:123',\n * type: 'geo',\n * x: 100,\n * y: 200\n * }\n *\n * // Update shape properties\n * const propsUpdate: TLShapePartial<TLGeoShape> = {\n * id: 'shape:123',\n * type: 'geo',\n * props: {\n * w: 150,\n * h: 100\n * }\n * }\n * ```\n *\n * @public\n */\nexport type TLShapePartial<T extends TLShape = TLShape> = T extends T\n\t? {\n\t\t\tid: TLShapeId\n\t\t\ttype: T['type']\n\t\t\tprops?: Partial<T['props']>\n\t\t\tmeta?: Partial<T['meta']>\n\t\t} & Partial<Omit<T, 'type' | 'id' | 'props' | 'meta'>>\n\t: never\n\n/**\n * A partial version of a shape, useful for creating shapes.\n *\n * This type represents a shape where all properties except `type` are optional.\n * It's commonly used when creating shapes.\n *\n * @example\n * ```ts\n * // Create a shape\n * const shapeCreate: TLCreateShapePartial = {\n * type: 'geo',\n * x: 100,\n * y: 200\n * }\n *\n * // Create shape properties\n * const propsCreate: TLCreateShapePartial<TLGeoShape> = {\n * type: 'geo',\n * props: {\n * w: 150,\n * h: 100\n * }\n * }\n * ```\n *\n * @public\n */\nexport type TLCreateShapePartial<T extends TLShape = TLShape> = T extends T\n\t? {\n\t\t\ttype: T['type']\n\t\t\tprops?: Partial<T['props']>\n\t\t\tmeta?: Partial<T['meta']>\n\t\t} & Partial<Omit<T, 'type' | 'props' | 'meta'>>\n\t: never\n\n/**\n * Extract a shape type by its props.\n *\n * This utility type takes a props object type and returns the corresponding shape type\n * from the TLShape union whose props match the given type.\n *\n * @example\n * ```ts\n * type MyShape = ExtractShapeByProps<{ w: number; h: number }>\n * // MyShape is now the type of shape(s) that have props with w and h as numbers\n * ```\n *\n * @public\n */\nexport type ExtractShapeByProps<P> = Extract<TLShape, { props: P }>\n\n/**\n * A unique identifier for a shape record.\n *\n * Shape IDs are branded strings that start with \"shape:\" followed by a unique identifier.\n * This type-safe approach prevents mixing up different types of record IDs.\n *\n * @example\n * ```ts\n * const shapeId: TLShapeId = createShapeId() // \"shape:abc123\"\n * const customId: TLShapeId = createShapeId('my-custom-id') // \"shape:my-custom-id\"\n * ```\n *\n * @public\n */\nexport type TLShapeId = RecordId<TLShape>\n\n/**\n * The ID of a shape's parent, which can be either a page or another shape.\n *\n * Shapes can be parented to pages (for top-level shapes) or to other shapes\n * (for shapes inside frames or groups).\n *\n * @example\n * ```ts\n * // Shape parented to a page\n * const pageParentId: TLParentId = 'page:main'\n *\n * // Shape parented to another shape (e.g., inside a frame)\n * const shapeParentId: TLParentId = 'shape:frame123'\n * ```\n *\n * @public\n */\nexport type TLParentId = TLPageId | TLShapeId\n\n/**\n * Migration version IDs for the root shape schema.\n *\n * These track the evolution of the base shape structure over time, ensuring\n * that shapes created in older versions can be migrated to newer formats.\n *\n * @example\n * ```ts\n * // Check if a migration needs to be applied\n * if (shapeVersion < rootShapeVersions.AddIsLocked) {\n * // Apply isLocked migration\n * }\n * ```\n *\n * @public\n */\nexport const rootShapeVersions = createMigrationIds('com.tldraw.shape', {\n\tAddIsLocked: 1,\n\tHoistOpacity: 2,\n\tAddMeta: 3,\n\tAddWhite: 4,\n})\n\n/**\n * Migration sequence for the root shape record type.\n *\n * This sequence defines how shape records should be transformed when migrating\n * between different schema versions. Each migration handles a specific version\n * upgrade, ensuring data compatibility across tldraw versions.\n *\n * @public\n */\nexport const rootShapeMigrations = createRecordMigrationSequence({\n\tsequenceId: 'com.tldraw.shape',\n\trecordType: 'shape',\n\tsequence: [\n\t\t{\n\t\t\tid: rootShapeVersions.AddIsLocked,\n\t\t\tup: (record: any) => {\n\t\t\t\trecord.isLocked = false\n\t\t\t},\n\t\t\tdown: (record: any) => {\n\t\t\t\tdelete record.isLocked\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tid: rootShapeVersions.HoistOpacity,\n\t\t\tup: (record: any) => {\n\t\t\t\trecord.opacity = Number(record.props.opacity ?? '1')\n\t\t\t\tdelete record.props.opacity\n\t\t\t},\n\t\t\tdown: (record: any) => {\n\t\t\t\tconst opacity = record.opacity\n\t\t\t\tdelete record.opacity\n\t\t\t\trecord.props.opacity =\n\t\t\t\t\topacity < 0.175\n\t\t\t\t\t\t? '0.1'\n\t\t\t\t\t\t: opacity < 0.375\n\t\t\t\t\t\t\t? '0.25'\n\t\t\t\t\t\t\t: opacity < 0.625\n\t\t\t\t\t\t\t\t? '0.5'\n\t\t\t\t\t\t\t\t: opacity < 0.875\n\t\t\t\t\t\t\t\t\t? '0.75'\n\t\t\t\t\t\t\t\t\t: '1'\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tid: rootShapeVersions.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: rootShapeVersions.AddWhite,\n\t\t\tup: (_record) => {\n\t\t\t\t// noop\n\t\t\t},\n\t\t\tdown: (record: any) => {\n\t\t\t\tif (record.props.color === 'white') {\n\t\t\t\t\trecord.props.color = 'black'\n\t\t\t\t}\n\t\t\t},\n\t\t},\n\t],\n})\n\n/**\n * Type guard to check if a record is a shape.\n *\n * @param record - The record to check\n * @returns True if the record is a shape, false otherwise\n *\n * @example\n * ```ts\n * const record = store.get('shape:abc123')\n * if (isShape(record)) {\n * console.log(`Shape type: ${record.type}`)\n * console.log(`Position: (${record.x}, ${record.y})`)\n * }\n * ```\n *\n * @public\n */\nexport function isShape(record?: UnknownRecord): record is TLShape {\n\tif (!record) return false\n\treturn record.typeName === 'shape'\n}\n\n/**\n * Type guard to check if a string is a valid shape ID.\n *\n * @param id - The string to check\n * @returns True if the string is a valid shape ID, false otherwise\n *\n * @example\n * ```ts\n * const id = 'shape:abc123'\n * if (isShapeId(id)) {\n * const shape = store.get(id) // TypeScript knows id is TLShapeId\n * }\n *\n * // Check user input\n * function selectShape(id: string) {\n * if (isShapeId(id)) {\n * editor.selectShape(id)\n * } else {\n * console.error('Invalid shape ID format')\n * }\n * }\n * ```\n *\n * @public\n */\nexport function isShapeId(id?: string): id is TLShapeId {\n\tif (!id) return false\n\treturn id.startsWith('shape:')\n}\n\n/**\n * Creates a new shape ID.\n *\n * @param id - Optional custom ID suffix. If not provided, a unique ID will be generated\n * @returns A new shape ID with the \"shape:\" prefix\n *\n * @example\n * ```ts\n * // Create a shape with auto-generated ID\n * const shapeId = createShapeId() // \"shape:abc123\"\n *\n * // Create a shape with custom ID\n * const customShapeId = createShapeId('my-rectangle') // \"shape:my-rectangle\"\n *\n * // Use in shape creation\n * const newShape: TLGeoShape = {\n * id: createShapeId(),\n * type: 'geo',\n * x: 100,\n * y: 200,\n * // ... other properties\n * }\n * ```\n *\n * @public\n */\nexport function createShapeId(id?: string): TLShapeId {\n\treturn `shape:${id ?? uniqueId()}` as TLShapeId\n}\n\n/**\n * Extracts style properties from a shape's props definition and maps them to their property keys.\n *\n * This function analyzes shape property validators to identify which ones are style properties\n * and creates a mapping from StyleProp instances to their corresponding property keys.\n * It also validates that each style property is only used once per shape.\n *\n * @param props - Record of property validators for a shape type\n * @returns Map from StyleProp instances to their property keys\n * @throws Error if a style property is used more than once in the same shape\n *\n * @example\n * ```ts\n * const geoShapeProps = {\n * color: DefaultColorStyle,\n * fill: DefaultFillStyle,\n * width: T.number,\n * height: T.number\n * }\n *\n * const styleMap = getShapePropKeysByStyle(geoShapeProps)\n * // styleMap.get(DefaultColorStyle) === 'color'\n * // styleMap.get(DefaultFillStyle) === 'fill'\n * ```\n *\n * @internal\n */\nexport function getShapePropKeysByStyle(props: Record<string, T.Validatable<any>>) {\n\tconst propKeysByStyle = new Map<StyleProp<unknown>, string>()\n\tfor (const [key, prop] of Object.entries(props)) {\n\t\tif (prop instanceof StyleProp) {\n\t\t\tif (propKeysByStyle.has(prop)) {\n\t\t\t\tthrow new Error(\n\t\t\t\t\t`Duplicate style prop ${prop.id}. Each style prop can only be used once within a shape.`\n\t\t\t\t)\n\t\t\t}\n\t\t\tpropKeysByStyle.set(prop, key)\n\t\t}\n\t}\n\treturn propKeysByStyle\n}\n\n/**\n * Creates a migration sequence for shape properties.\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 shape property 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 myShapeMigrations = createShapePropsMigrationSequence({\n * sequence: [\n * {\n * id: 'com.myapp.shape.custom/1.0.0',\n * up: (props) => ({ ...props, newProperty: 'default' }),\n * down: ({ newProperty, ...props }) => props\n * }\n * ]\n * })\n * ```\n *\n * @public\n */\nexport function createShapePropsMigrationSequence(\n\tmigrations: TLPropsMigrations\n): TLPropsMigrations {\n\treturn migrations\n}\n\n/**\n * Creates properly formatted migration IDs for shape properties.\n *\n * Generates standardized migration IDs following the convention:\n * `com.tldraw.shape.{shapeType}/{version}`\n *\n * @param shapeType - The type of shape these migrations apply to\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 myShapeVersions = createShapePropsMigrationIds('custom', {\n * AddColor: 1,\n * AddSize: 2,\n * RefactorProps: 3\n * })\n * // Result: {\n * // AddColor: 'com.tldraw.shape.custom/1',\n * // AddSize: 'com.tldraw.shape.custom/2',\n * // RefactorProps: 'com.tldraw.shape.custom/3'\n * // }\n * ```\n *\n * @public\n */\nexport function createShapePropsMigrationIds<\n\tconst S extends string,\n\tconst T extends Record<string, number>,\n>(shapeType: S, ids: T): { [k in keyof T]: `com.tldraw.shape.${S}/${T[k]}` } {\n\treturn mapObjectMapValues(ids, (_k, v) => `com.tldraw.shape.${shapeType}/${v}`) as any\n}\n\n/**\n * Creates the record type definition for shapes.\n *\n * This function generates a complete record type for shapes that includes validation\n * for all registered shape types. It combines the base shape properties with\n * type-specific properties and creates a union validator that can handle any\n * registered shape type.\n *\n * @param shapes - Record of shape type names to their schema configuration\n * @returns A complete RecordType for shapes with proper validation and default properties\n *\n * @example\n * ```ts\n * const shapeRecordType = createShapeRecordType({\n * geo: { props: geoShapeProps, migrations: geoMigrations },\n * arrow: { props: arrowShapeProps, migrations: arrowMigrations }\n * })\n * ```\n *\n * @internal\n */\nexport function createShapeRecordType(shapes: Record<string, SchemaPropsInfo>) {\n\treturn createRecordType('shape', {\n\t\tscope: 'document',\n\t\tvalidator: T.model(\n\t\t\t'shape',\n\t\t\tT.union(\n\t\t\t\t'type',\n\t\t\t\tmapObjectMapValues(shapes, (type, { props, meta }) =>\n\t\t\t\t\tcreateShapeValidator(type, props, meta)\n\t\t\t\t)\n\t\t\t)\n\t\t),\n\t}).withDefaultProperties(() => ({\n\t\tx: 0,\n\t\ty: 0,\n\t\trotation: 0,\n\t\tisLocked: false,\n\t\topacity: 1,\n\t\tmeta: {},\n\t}))\n}\n"],
5
+ "mappings": ";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,mBAMO;AACP,mBAA6C;AAC7C,sBAAkB;AAIlB,yBAAkD;AAalD,uBAA0B;AAsQnB,MAAM,wBAAoB,iCAAmB,oBAAoB;AAAA,EACvE,aAAa;AAAA,EACb,cAAc;AAAA,EACd,SAAS;AAAA,EACT,UAAU;AACX,CAAC;AAWM,MAAM,0BAAsB,4CAA8B;AAAA,EAChE,YAAY;AAAA,EACZ,YAAY;AAAA,EACZ,UAAU;AAAA,IACT;AAAA,MACC,IAAI,kBAAkB;AAAA,MACtB,IAAI,CAAC,WAAgB;AACpB,eAAO,WAAW;AAAA,MACnB;AAAA,MACA,MAAM,CAAC,WAAgB;AACtB,eAAO,OAAO;AAAA,MACf;AAAA,IACD;AAAA,IACA;AAAA,MACC,IAAI,kBAAkB;AAAA,MACtB,IAAI,CAAC,WAAgB;AACpB,eAAO,UAAU,OAAO,OAAO,MAAM,WAAW,GAAG;AACnD,eAAO,OAAO,MAAM;AAAA,MACrB;AAAA,MACA,MAAM,CAAC,WAAgB;AACtB,cAAM,UAAU,OAAO;AACvB,eAAO,OAAO;AACd,eAAO,MAAM,UACZ,UAAU,QACP,QACA,UAAU,QACT,SACA,UAAU,QACT,QACA,UAAU,QACT,SACA;AAAA,MACR;AAAA,IACD;AAAA,IACA;AAAA,MACC,IAAI,kBAAkB;AAAA,MACtB,IAAI,CAAC,WAAgB;AACpB,eAAO,OAAO,CAAC;AAAA,MAChB;AAAA,IACD;AAAA,IACA;AAAA,MACC,IAAI,kBAAkB;AAAA,MACtB,IAAI,CAAC,YAAY;AAAA,MAEjB;AAAA,MACA,MAAM,CAAC,WAAgB;AACtB,YAAI,OAAO,MAAM,UAAU,SAAS;AACnC,iBAAO,MAAM,QAAQ;AAAA,QACtB;AAAA,MACD;AAAA,IACD;AAAA,EACD;AACD,CAAC;AAmBM,SAAS,QAAQ,QAA2C;AAClE,MAAI,CAAC,OAAQ,QAAO;AACpB,SAAO,OAAO,aAAa;AAC5B;AA2BO,SAAS,UAAU,IAA8B;AACvD,MAAI,CAAC,GAAI,QAAO;AAChB,SAAO,GAAG,WAAW,QAAQ;AAC9B;AA4BO,SAAS,cAAc,IAAwB;AACrD,SAAO,SAAS,UAAM,uBAAS,CAAC;AACjC;AA6BO,SAAS,wBAAwB,OAA2C;AAClF,QAAM,kBAAkB,oBAAI,IAAgC;AAC5D,aAAW,CAAC,KAAK,IAAI,KAAK,OAAO,QAAQ,KAAK,GAAG;AAChD,QAAI,gBAAgB,4BAAW;AAC9B,UAAI,gBAAgB,IAAI,IAAI,GAAG;AAC9B,cAAM,IAAI;AAAA,UACT,wBAAwB,KAAK,EAAE;AAAA,QAChC;AAAA,MACD;AACA,sBAAgB,IAAI,MAAM,GAAG;AAAA,IAC9B;AAAA,EACD;AACA,SAAO;AACR;AA0BO,SAAS,kCACf,YACoB;AACpB,SAAO;AACR;AA4BO,SAAS,6BAGd,WAAc,KAA6D;AAC5E,aAAO,iCAAmB,KAAK,CAAC,IAAI,MAAM,oBAAoB,SAAS,IAAI,CAAC,EAAE;AAC/E;AAuBO,SAAS,sBAAsB,QAAyC;AAC9E,aAAO,+BAAiB,SAAS;AAAA,IAChC,OAAO;AAAA,IACP,WAAW,kBAAE;AAAA,MACZ;AAAA,MACA,kBAAE;AAAA,QACD;AAAA,YACA;AAAA,UAAmB;AAAA,UAAQ,CAAC,MAAM,EAAE,OAAO,KAAK,UAC/C,yCAAqB,MAAM,OAAO,IAAI;AAAA,QACvC;AAAA,MACD;AAAA,IACD;AAAA,EACD,CAAC,EAAE,sBAAsB,OAAO;AAAA,IAC/B,GAAG;AAAA,IACH,GAAG;AAAA,IACH,UAAU;AAAA,IACV,UAAU;AAAA,IACV,SAAS;AAAA,IACT,MAAM,CAAC;AAAA,EACR,EAAE;AACH;",
6
6
  "names": []
7
7
  }
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../src/shapes/ShapeWithCrop.ts"],
4
- "sourcesContent": ["import { VecModel } from '../misc/geometry-types'\nimport { TLBaseShape } from './TLBaseShape'\n\n/**\n * Defines cropping parameters for shapes that support cropping.\n *\n * Specifies the visible area of an asset (like an image or video) within a shape.\n * The crop is defined by top-left and bottom-right coordinates in normalized space (0-1),\n * where (0,0) is the top-left of the original asset and (1,1) is the bottom-right.\n *\n * @example\n * ```ts\n * // Crop the center 50% of an image\n * const centerCrop: TLShapeCrop = {\n * topLeft: { x: 0.25, y: 0.25 },\n * bottomRight: { x: 0.75, y: 0.75 }\n * }\n *\n * // Crop for a circular image shape\n * const circleCrop: TLShapeCrop = {\n * topLeft: { x: 0, y: 0 },\n * bottomRight: { x: 1, y: 1 },\n * isCircle: true\n * }\n * ```\n *\n * @public\n */\nexport interface TLShapeCrop {\n\ttopLeft: VecModel\n\tbottomRight: VecModel\n\tisCircle?: boolean\n}\n\n/**\n * A shape type that supports cropping functionality.\n *\n * This type represents any shape that can display cropped content, typically media shapes\n * like images and videos. The shape has width, height, and optional crop parameters.\n * When crop is null, the entire asset is displayed.\n *\n * @example\n * ```ts\n * // An image shape with cropping\n * const croppedImageShape: ShapeWithCrop = {\n * id: 'shape:image1',\n * type: 'image',\n * x: 100,\n * y: 200,\n * // ... other base shape properties\n * props: {\n * w: 300,\n * h: 200,\n * crop: {\n * topLeft: { x: 0.1, y: 0.1 },\n * bottomRight: { x: 0.9, y: 0.9 }\n * }\n * }\n * }\n *\n * // A shape without cropping (shows full asset)\n * const fullImageShape: ShapeWithCrop = {\n * // ... shape properties\n * props: {\n * w: 400,\n * h: 300,\n * crop: null // Shows entire asset\n * }\n * }\n * ```\n *\n * @public\n */\nexport type ShapeWithCrop = TLBaseShape<string, { w: number; h: number; crop: TLShapeCrop | null }>\n"],
4
+ "sourcesContent": ["import { VecModel } from '../misc/geometry-types'\nimport { ExtractShapeByProps } from '../records/TLShape'\n\n/**\n * Defines cropping parameters for shapes that support cropping.\n *\n * Specifies the visible area of an asset (like an image or video) within a shape.\n * The crop is defined by top-left and bottom-right coordinates in normalized space (0-1),\n * where (0,0) is the top-left of the original asset and (1,1) is the bottom-right.\n *\n * @example\n * ```ts\n * // Crop the center 50% of an image\n * const centerCrop: TLShapeCrop = {\n * topLeft: { x: 0.25, y: 0.25 },\n * bottomRight: { x: 0.75, y: 0.75 }\n * }\n *\n * // Crop for a circular image shape\n * const circleCrop: TLShapeCrop = {\n * topLeft: { x: 0, y: 0 },\n * bottomRight: { x: 1, y: 1 },\n * isCircle: true\n * }\n * ```\n *\n * @public\n */\nexport interface TLShapeCrop {\n\ttopLeft: VecModel\n\tbottomRight: VecModel\n\tisCircle?: boolean\n}\n\n/**\n * A shape type that supports cropping functionality.\n *\n * This type represents any shape that can display cropped content, typically media shapes\n * like images and videos. The shape has width, height, and optional crop parameters.\n * When crop is null, the entire asset is displayed.\n *\n * @example\n * ```ts\n * // An image shape with cropping\n * const croppedImageShape: ShapeWithCrop = {\n * id: 'shape:image1',\n * type: 'image',\n * x: 100,\n * y: 200,\n * // ... other base shape properties\n * props: {\n * w: 300,\n * h: 200,\n * crop: {\n * topLeft: { x: 0.1, y: 0.1 },\n * bottomRight: { x: 0.9, y: 0.9 }\n * }\n * }\n * }\n *\n * // A shape without cropping (shows full asset)\n * const fullImageShape: ShapeWithCrop = {\n * // ... shape properties\n * props: {\n * w: 400,\n * h: 300,\n * crop: null // Shows entire asset\n * }\n * }\n * ```\n *\n * @public\n */\nexport type ShapeWithCrop = ExtractShapeByProps<{ w: number; h: number; crop: TLShapeCrop | null }>\n"],
5
5
  "mappings": ";;;;;;;;;;;;;;AAAA;AAAA;",
6
6
  "names": []
7
7
  }
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../src/shapes/TLBaseShape.ts"],
4
- "sourcesContent": ["import { BaseRecord } from '@tldraw/store'\nimport { IndexKey, JsonObject } from '@tldraw/utils'\nimport { T } from '@tldraw/validate'\nimport { TLOpacityType, opacityValidator } from '../misc/TLOpacity'\nimport { idValidator } from '../misc/id-validator'\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 shape extends this base with additional type-specific properties.\n *\n * @example\n * ```ts\n * // Define a custom shape type\n * interface MyCustomShape extends TLBaseShape<'custom', { size: number; color: string }> {}\n *\n * // Create a shape instance\n * const myShape: MyCustomShape = {\n * id: 'shape:abc123',\n * typeName: 'shape',\n * type: 'custom',\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 * size: 50,\n * color: 'blue'\n * },\n * meta: {}\n * }\n * ```\n *\n * @public\n */\nexport interface TLBaseShape<Type extends string, Props extends object>\n\textends BaseRecord<'shape', TLShapeId> {\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;AAEA,sBAAkB;AAClB,uBAAgD;AAChD,0BAA4B;AAoErB,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;",
4
+ "sourcesContent": ["import { IndexKey, JsonObject } from '@tldraw/utils'\nimport { T } from '@tldraw/validate'\nimport { TLOpacityType, opacityValidator } from '../misc/TLOpacity'\nimport { idValidator } from '../misc/id-validator'\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,uBAAgD;AAChD,0BAA4B;AA6FrB,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
  }
@@ -40,7 +40,7 @@ const storeMigrations = (0, import_store.createMigrationSequence)({
40
40
  scope: "store",
41
41
  up: (store) => {
42
42
  for (const [id, record] of (0, import_utils.objectMapEntries)(store)) {
43
- if (record.typeName === "shape" && (record.type === "icon" || record.type === "code")) {
43
+ if (record.typeName === "shape" && "type" in record && (record.type === "icon" || record.type === "code")) {
44
44
  delete store[id];
45
45
  }
46
46
  }
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../src/store-migrations.ts"],
4
- "sourcesContent": ["import { createMigrationIds, createMigrationSequence } from '@tldraw/store'\nimport { IndexKey, objectMapEntries } from '@tldraw/utils'\nimport { TLPage } from './records/TLPage'\nimport { TLShape } from './records/TLShape'\nimport { TLLineShape } from './shapes/TLLineShape'\n\n/**\n * Migration version constants for store-level schema changes.\n * Each version represents a breaking change that requires data transformation.\n *\n * @internal\n */\nconst Versions = createMigrationIds('com.tldraw.store', {\n\tRemoveCodeAndIconShapeTypes: 1,\n\tAddInstancePresenceType: 2,\n\tRemoveTLUserAndPresenceAndAddPointer: 3,\n\tRemoveUserDocument: 4,\n\tFixIndexKeys: 5,\n} as const)\n\n/**\n * Migration version identifiers for store-level migrations.\n * These versions track changes to the overall store structure and data model.\n *\n * @example\n * ```ts\n * import { storeVersions } from '@tldraw/tlschema'\n *\n * // Check if a specific migration version exists\n * const hasRemoveCodeShapes = storeVersions.RemoveCodeAndIconShapeTypes\n * ```\n *\n * @public\n */\nexport { Versions as storeVersions }\n\n/**\n * Store-level migration sequence that handles evolution of the tldraw data model.\n * These migrations run when the store schema version changes and ensure backward\n * compatibility by transforming old data structures to new formats.\n *\n * The migrations handle:\n * - Removal of deprecated shape types (code, icon)\n * - Addition of new record types (instance presence)\n * - Cleanup of obsolete user and presence data\n * - Removal of deprecated user document records\n *\n * @example\n * ```ts\n * import { storeMigrations } from '@tldraw/tlschema'\n * import { migrate } from '@tldraw/store'\n *\n * // Apply store migrations to old data\n * const migratedStore = migrate({\n * store: oldStoreData,\n * migrations: storeMigrations,\n * fromVersion: 0,\n * toVersion: storeMigrations.currentVersion\n * })\n * ```\n *\n * @public\n */\nexport const storeMigrations = createMigrationSequence({\n\tsequenceId: 'com.tldraw.store',\n\tretroactive: false,\n\tsequence: [\n\t\t{\n\t\t\tid: Versions.RemoveCodeAndIconShapeTypes,\n\t\t\tscope: 'store',\n\t\t\tup: (store) => {\n\t\t\t\tfor (const [id, record] of objectMapEntries(store)) {\n\t\t\t\t\tif (\n\t\t\t\t\t\trecord.typeName === 'shape' &&\n\t\t\t\t\t\t((record as TLShape).type === 'icon' || (record as TLShape).type === 'code')\n\t\t\t\t\t) {\n\t\t\t\t\t\tdelete store[id]\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tid: Versions.AddInstancePresenceType,\n\t\t\tscope: 'store',\n\t\t\tup(_store) {\n\t\t\t\t// noop\n\t\t\t\t// there used to be a down migration for this but we made down migrations optional\n\t\t\t\t// and we don't use them on store-level migrations so we can just remove it\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\t// remove user and presence records and add pointer records\n\t\t\tid: Versions.RemoveTLUserAndPresenceAndAddPointer,\n\t\t\tscope: 'store',\n\t\t\tup: (store) => {\n\t\t\t\tfor (const [id, record] of objectMapEntries(store)) {\n\t\t\t\t\tif (record.typeName.match(/^(user|user_presence)$/)) {\n\t\t\t\t\t\tdelete store[id]\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\t// remove user document records\n\t\t\tid: Versions.RemoveUserDocument,\n\t\t\tscope: 'store',\n\t\t\tup: (store) => {\n\t\t\t\tfor (const [id, record] of objectMapEntries(store)) {\n\t\t\t\t\tif (record.typeName.match('user_document')) {\n\t\t\t\t\t\tdelete store[id]\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tid: Versions.FixIndexKeys,\n\t\t\tscope: 'record',\n\t\t\tup: (record) => {\n\t\t\t\tif (['shape', 'page'].includes(record.typeName) && 'index' in record) {\n\t\t\t\t\tconst recordWithIndex = record as TLShape | TLPage\n\t\t\t\t\t// Our newer fractional indexed library (more correctly) validates that indices\n\t\t\t\t\t// do not end with 0. ('a0' being an exception)\n\t\t\t\t\tif (recordWithIndex.index.endsWith('0') && recordWithIndex.index !== 'a0') {\n\t\t\t\t\t\trecordWithIndex.index = (recordWithIndex.index.slice(0, -1) +\n\t\t\t\t\t\t\tgetNRandomBase62Digits(3)) as IndexKey\n\t\t\t\t\t}\n\t\t\t\t\t// Line shapes have 'points' that have indices as well.\n\t\t\t\t\tif (record.typeName === 'shape' && (recordWithIndex as TLShape).type === 'line') {\n\t\t\t\t\t\tconst lineShape = recordWithIndex as TLLineShape\n\t\t\t\t\t\tfor (const [_, point] of objectMapEntries(lineShape.props.points)) {\n\t\t\t\t\t\t\tif (point.index.endsWith('0') && point.index !== 'a0') {\n\t\t\t\t\t\t\t\tpoint.index = (point.index.slice(0, -1) + getNRandomBase62Digits(3)) as IndexKey\n\t\t\t\t\t\t\t}\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\tdown: () => {\n\t\t\t\t// noop\n\t\t\t\t// Enables tlsync to support older clients so as to not force people to refresh immediately after deploying.\n\t\t\t},\n\t\t},\n\t],\n})\n\nconst BASE_62_DIGITS_WITHOUT_ZERO = '123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz'\nconst getRandomBase62Digit = () => {\n\treturn BASE_62_DIGITS_WITHOUT_ZERO.charAt(\n\t\tMath.floor(Math.random() * BASE_62_DIGITS_WITHOUT_ZERO.length)\n\t)\n}\n\nconst getNRandomBase62Digits = (n: number) => {\n\treturn Array.from({ length: n }, getRandomBase62Digit).join('')\n}\n"],
5
- "mappings": ";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,mBAA4D;AAC5D,mBAA2C;AAW3C,MAAM,eAAW,iCAAmB,oBAAoB;AAAA,EACvD,6BAA6B;AAAA,EAC7B,yBAAyB;AAAA,EACzB,sCAAsC;AAAA,EACtC,oBAAoB;AAAA,EACpB,cAAc;AACf,CAAU;AA6CH,MAAM,sBAAkB,sCAAwB;AAAA,EACtD,YAAY;AAAA,EACZ,aAAa;AAAA,EACb,UAAU;AAAA,IACT;AAAA,MACC,IAAI,SAAS;AAAA,MACb,OAAO;AAAA,MACP,IAAI,CAAC,UAAU;AACd,mBAAW,CAAC,IAAI,MAAM,SAAK,+BAAiB,KAAK,GAAG;AACnD,cACC,OAAO,aAAa,YAClB,OAAmB,SAAS,UAAW,OAAmB,SAAS,SACpE;AACD,mBAAO,MAAM,EAAE;AAAA,UAChB;AAAA,QACD;AAAA,MACD;AAAA,IACD;AAAA,IACA;AAAA,MACC,IAAI,SAAS;AAAA,MACb,OAAO;AAAA,MACP,GAAG,QAAQ;AAAA,MAIX;AAAA,IACD;AAAA,IACA;AAAA;AAAA,MAEC,IAAI,SAAS;AAAA,MACb,OAAO;AAAA,MACP,IAAI,CAAC,UAAU;AACd,mBAAW,CAAC,IAAI,MAAM,SAAK,+BAAiB,KAAK,GAAG;AACnD,cAAI,OAAO,SAAS,MAAM,wBAAwB,GAAG;AACpD,mBAAO,MAAM,EAAE;AAAA,UAChB;AAAA,QACD;AAAA,MACD;AAAA,IACD;AAAA,IACA;AAAA;AAAA,MAEC,IAAI,SAAS;AAAA,MACb,OAAO;AAAA,MACP,IAAI,CAAC,UAAU;AACd,mBAAW,CAAC,IAAI,MAAM,SAAK,+BAAiB,KAAK,GAAG;AACnD,cAAI,OAAO,SAAS,MAAM,eAAe,GAAG;AAC3C,mBAAO,MAAM,EAAE;AAAA,UAChB;AAAA,QACD;AAAA,MACD;AAAA,IACD;AAAA,IACA;AAAA,MACC,IAAI,SAAS;AAAA,MACb,OAAO;AAAA,MACP,IAAI,CAAC,WAAW;AACf,YAAI,CAAC,SAAS,MAAM,EAAE,SAAS,OAAO,QAAQ,KAAK,WAAW,QAAQ;AACrE,gBAAM,kBAAkB;AAGxB,cAAI,gBAAgB,MAAM,SAAS,GAAG,KAAK,gBAAgB,UAAU,MAAM;AAC1E,4BAAgB,QAAS,gBAAgB,MAAM,MAAM,GAAG,EAAE,IACzD,uBAAuB,CAAC;AAAA,UAC1B;AAEA,cAAI,OAAO,aAAa,WAAY,gBAA4B,SAAS,QAAQ;AAChF,kBAAM,YAAY;AAClB,uBAAW,CAAC,GAAG,KAAK,SAAK,+BAAiB,UAAU,MAAM,MAAM,GAAG;AAClE,kBAAI,MAAM,MAAM,SAAS,GAAG,KAAK,MAAM,UAAU,MAAM;AACtD,sBAAM,QAAS,MAAM,MAAM,MAAM,GAAG,EAAE,IAAI,uBAAuB,CAAC;AAAA,cACnE;AAAA,YACD;AAAA,UACD;AAAA,QACD;AAAA,MACD;AAAA,MACA,MAAM,MAAM;AAAA,MAGZ;AAAA,IACD;AAAA,EACD;AACD,CAAC;AAED,MAAM,8BAA8B;AACpC,MAAM,uBAAuB,MAAM;AAClC,SAAO,4BAA4B;AAAA,IAClC,KAAK,MAAM,KAAK,OAAO,IAAI,4BAA4B,MAAM;AAAA,EAC9D;AACD;AAEA,MAAM,yBAAyB,CAAC,MAAc;AAC7C,SAAO,MAAM,KAAK,EAAE,QAAQ,EAAE,GAAG,oBAAoB,EAAE,KAAK,EAAE;AAC/D;",
4
+ "sourcesContent": ["import { createMigrationIds, createMigrationSequence } from '@tldraw/store'\nimport { IndexKey, objectMapEntries } from '@tldraw/utils'\nimport { TLPage } from './records/TLPage'\nimport { TLShape } from './records/TLShape'\nimport { TLLineShape } from './shapes/TLLineShape'\n\n/**\n * Migration version constants for store-level schema changes.\n * Each version represents a breaking change that requires data transformation.\n *\n * @internal\n */\nconst Versions = createMigrationIds('com.tldraw.store', {\n\tRemoveCodeAndIconShapeTypes: 1,\n\tAddInstancePresenceType: 2,\n\tRemoveTLUserAndPresenceAndAddPointer: 3,\n\tRemoveUserDocument: 4,\n\tFixIndexKeys: 5,\n} as const)\n\n/**\n * Migration version identifiers for store-level migrations.\n * These versions track changes to the overall store structure and data model.\n *\n * @example\n * ```ts\n * import { storeVersions } from '@tldraw/tlschema'\n *\n * // Check if a specific migration version exists\n * const hasRemoveCodeShapes = storeVersions.RemoveCodeAndIconShapeTypes\n * ```\n *\n * @public\n */\nexport { Versions as storeVersions }\n\n/**\n * Store-level migration sequence that handles evolution of the tldraw data model.\n * These migrations run when the store schema version changes and ensure backward\n * compatibility by transforming old data structures to new formats.\n *\n * The migrations handle:\n * - Removal of deprecated shape types (code, icon)\n * - Addition of new record types (instance presence)\n * - Cleanup of obsolete user and presence data\n * - Removal of deprecated user document records\n *\n * @example\n * ```ts\n * import { storeMigrations } from '@tldraw/tlschema'\n * import { migrate } from '@tldraw/store'\n *\n * // Apply store migrations to old data\n * const migratedStore = migrate({\n * store: oldStoreData,\n * migrations: storeMigrations,\n * fromVersion: 0,\n * toVersion: storeMigrations.currentVersion\n * })\n * ```\n *\n * @public\n */\nexport const storeMigrations = createMigrationSequence({\n\tsequenceId: 'com.tldraw.store',\n\tretroactive: false,\n\tsequence: [\n\t\t{\n\t\t\tid: Versions.RemoveCodeAndIconShapeTypes,\n\t\t\tscope: 'store',\n\t\t\tup: (store) => {\n\t\t\t\tfor (const [id, record] of objectMapEntries(store)) {\n\t\t\t\t\tif (\n\t\t\t\t\t\trecord.typeName === 'shape' &&\n\t\t\t\t\t\t'type' in record &&\n\t\t\t\t\t\t(record.type === 'icon' || record.type === 'code')\n\t\t\t\t\t) {\n\t\t\t\t\t\tdelete store[id]\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tid: Versions.AddInstancePresenceType,\n\t\t\tscope: 'store',\n\t\t\tup(_store) {\n\t\t\t\t// noop\n\t\t\t\t// there used to be a down migration for this but we made down migrations optional\n\t\t\t\t// and we don't use them on store-level migrations so we can just remove it\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\t// remove user and presence records and add pointer records\n\t\t\tid: Versions.RemoveTLUserAndPresenceAndAddPointer,\n\t\t\tscope: 'store',\n\t\t\tup: (store) => {\n\t\t\t\tfor (const [id, record] of objectMapEntries(store)) {\n\t\t\t\t\tif (record.typeName.match(/^(user|user_presence)$/)) {\n\t\t\t\t\t\tdelete store[id]\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\t// remove user document records\n\t\t\tid: Versions.RemoveUserDocument,\n\t\t\tscope: 'store',\n\t\t\tup: (store) => {\n\t\t\t\tfor (const [id, record] of objectMapEntries(store)) {\n\t\t\t\t\tif (record.typeName.match('user_document')) {\n\t\t\t\t\t\tdelete store[id]\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tid: Versions.FixIndexKeys,\n\t\t\tscope: 'record',\n\t\t\tup: (record) => {\n\t\t\t\tif (['shape', 'page'].includes(record.typeName) && 'index' in record) {\n\t\t\t\t\tconst recordWithIndex = record as TLShape | TLPage\n\t\t\t\t\t// Our newer fractional indexed library (more correctly) validates that indices\n\t\t\t\t\t// do not end with 0. ('a0' being an exception)\n\t\t\t\t\tif (recordWithIndex.index.endsWith('0') && recordWithIndex.index !== 'a0') {\n\t\t\t\t\t\trecordWithIndex.index = (recordWithIndex.index.slice(0, -1) +\n\t\t\t\t\t\t\tgetNRandomBase62Digits(3)) as IndexKey\n\t\t\t\t\t}\n\t\t\t\t\t// Line shapes have 'points' that have indices as well.\n\t\t\t\t\tif (record.typeName === 'shape' && (recordWithIndex as TLShape).type === 'line') {\n\t\t\t\t\t\tconst lineShape = recordWithIndex as TLLineShape\n\t\t\t\t\t\tfor (const [_, point] of objectMapEntries(lineShape.props.points)) {\n\t\t\t\t\t\t\tif (point.index.endsWith('0') && point.index !== 'a0') {\n\t\t\t\t\t\t\t\tpoint.index = (point.index.slice(0, -1) + getNRandomBase62Digits(3)) as IndexKey\n\t\t\t\t\t\t\t}\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\tdown: () => {\n\t\t\t\t// noop\n\t\t\t\t// Enables tlsync to support older clients so as to not force people to refresh immediately after deploying.\n\t\t\t},\n\t\t},\n\t],\n})\n\nconst BASE_62_DIGITS_WITHOUT_ZERO = '123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz'\nconst getRandomBase62Digit = () => {\n\treturn BASE_62_DIGITS_WITHOUT_ZERO.charAt(\n\t\tMath.floor(Math.random() * BASE_62_DIGITS_WITHOUT_ZERO.length)\n\t)\n}\n\nconst getNRandomBase62Digits = (n: number) => {\n\treturn Array.from({ length: n }, getRandomBase62Digit).join('')\n}\n"],
5
+ "mappings": ";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,mBAA4D;AAC5D,mBAA2C;AAW3C,MAAM,eAAW,iCAAmB,oBAAoB;AAAA,EACvD,6BAA6B;AAAA,EAC7B,yBAAyB;AAAA,EACzB,sCAAsC;AAAA,EACtC,oBAAoB;AAAA,EACpB,cAAc;AACf,CAAU;AA6CH,MAAM,sBAAkB,sCAAwB;AAAA,EACtD,YAAY;AAAA,EACZ,aAAa;AAAA,EACb,UAAU;AAAA,IACT;AAAA,MACC,IAAI,SAAS;AAAA,MACb,OAAO;AAAA,MACP,IAAI,CAAC,UAAU;AACd,mBAAW,CAAC,IAAI,MAAM,SAAK,+BAAiB,KAAK,GAAG;AACnD,cACC,OAAO,aAAa,WACpB,UAAU,WACT,OAAO,SAAS,UAAU,OAAO,SAAS,SAC1C;AACD,mBAAO,MAAM,EAAE;AAAA,UAChB;AAAA,QACD;AAAA,MACD;AAAA,IACD;AAAA,IACA;AAAA,MACC,IAAI,SAAS;AAAA,MACb,OAAO;AAAA,MACP,GAAG,QAAQ;AAAA,MAIX;AAAA,IACD;AAAA,IACA;AAAA;AAAA,MAEC,IAAI,SAAS;AAAA,MACb,OAAO;AAAA,MACP,IAAI,CAAC,UAAU;AACd,mBAAW,CAAC,IAAI,MAAM,SAAK,+BAAiB,KAAK,GAAG;AACnD,cAAI,OAAO,SAAS,MAAM,wBAAwB,GAAG;AACpD,mBAAO,MAAM,EAAE;AAAA,UAChB;AAAA,QACD;AAAA,MACD;AAAA,IACD;AAAA,IACA;AAAA;AAAA,MAEC,IAAI,SAAS;AAAA,MACb,OAAO;AAAA,MACP,IAAI,CAAC,UAAU;AACd,mBAAW,CAAC,IAAI,MAAM,SAAK,+BAAiB,KAAK,GAAG;AACnD,cAAI,OAAO,SAAS,MAAM,eAAe,GAAG;AAC3C,mBAAO,MAAM,EAAE;AAAA,UAChB;AAAA,QACD;AAAA,MACD;AAAA,IACD;AAAA,IACA;AAAA,MACC,IAAI,SAAS;AAAA,MACb,OAAO;AAAA,MACP,IAAI,CAAC,WAAW;AACf,YAAI,CAAC,SAAS,MAAM,EAAE,SAAS,OAAO,QAAQ,KAAK,WAAW,QAAQ;AACrE,gBAAM,kBAAkB;AAGxB,cAAI,gBAAgB,MAAM,SAAS,GAAG,KAAK,gBAAgB,UAAU,MAAM;AAC1E,4BAAgB,QAAS,gBAAgB,MAAM,MAAM,GAAG,EAAE,IACzD,uBAAuB,CAAC;AAAA,UAC1B;AAEA,cAAI,OAAO,aAAa,WAAY,gBAA4B,SAAS,QAAQ;AAChF,kBAAM,YAAY;AAClB,uBAAW,CAAC,GAAG,KAAK,SAAK,+BAAiB,UAAU,MAAM,MAAM,GAAG;AAClE,kBAAI,MAAM,MAAM,SAAS,GAAG,KAAK,MAAM,UAAU,MAAM;AACtD,sBAAM,QAAS,MAAM,MAAM,MAAM,GAAG,EAAE,IAAI,uBAAuB,CAAC;AAAA,cACnE;AAAA,YACD;AAAA,UACD;AAAA,QACD;AAAA,MACD;AAAA,MACA,MAAM,MAAM;AAAA,MAGZ;AAAA,IACD;AAAA,EACD;AACD,CAAC;AAED,MAAM,8BAA8B;AACpC,MAAM,uBAAuB,MAAM;AAClC,SAAO,4BAA4B;AAAA,IAClC,KAAK,MAAM,KAAK,OAAO,IAAI,4BAA4B,MAAM;AAAA,EAC9D;AACD;AAEA,MAAM,yBAAyB,CAAC,MAAc;AAC7C,SAAO,MAAM,KAAK,EAAE,QAAQ,EAAE,GAAG,oBAAoB,EAAE,KAAK,EAAE;AAC/D;",
6
6
  "names": []
7
7
  }
@@ -52,6 +52,7 @@ const DefaultColorThemePalette = {
52
52
  black: {
53
53
  solid: "#1d1d1d",
54
54
  fill: "#1d1d1d",
55
+ linedFill: "#363636",
55
56
  frameHeadingStroke: "#717171",
56
57
  frameHeadingFill: "#ffffff",
57
58
  frameStroke: "#717171",
@@ -67,6 +68,7 @@ const DefaultColorThemePalette = {
67
68
  blue: {
68
69
  solid: "#4465e9",
69
70
  fill: "#4465e9",
71
+ linedFill: "#6580ec",
70
72
  frameHeadingStroke: "#6681ec",
71
73
  frameHeadingFill: "#f9fafe",
72
74
  frameStroke: "#6681ec",
@@ -82,6 +84,7 @@ const DefaultColorThemePalette = {
82
84
  green: {
83
85
  solid: "#099268",
84
86
  fill: "#099268",
87
+ linedFill: "#0bad7c",
85
88
  frameHeadingStroke: "#37a684",
86
89
  frameHeadingFill: "#f8fcfa",
87
90
  frameStroke: "#37a684",
@@ -97,6 +100,7 @@ const DefaultColorThemePalette = {
97
100
  grey: {
98
101
  solid: "#9fa8b2",
99
102
  fill: "#9fa8b2",
103
+ linedFill: "#bbc1c9",
100
104
  frameHeadingStroke: "#aaaaab",
101
105
  frameHeadingFill: "#fbfcfc",
102
106
  frameStroke: "#aaaaab",
@@ -112,6 +116,7 @@ const DefaultColorThemePalette = {
112
116
  "light-blue": {
113
117
  solid: "#4ba1f1",
114
118
  fill: "#4ba1f1",
119
+ linedFill: "#7abaf5",
115
120
  frameHeadingStroke: "#6cb2f3",
116
121
  frameHeadingFill: "#f8fbfe",
117
122
  frameStroke: "#6cb2f3",
@@ -127,6 +132,7 @@ const DefaultColorThemePalette = {
127
132
  "light-green": {
128
133
  solid: "#4cb05e",
129
134
  fill: "#4cb05e",
135
+ linedFill: "#7ec88c",
130
136
  frameHeadingStroke: "#6dbe7c",
131
137
  frameHeadingFill: "#f8fcf9",
132
138
  frameStroke: "#6dbe7c",
@@ -142,6 +148,7 @@ const DefaultColorThemePalette = {
142
148
  "light-red": {
143
149
  solid: "#f87777",
144
150
  fill: "#f87777",
151
+ linedFill: "#f99a9a",
145
152
  frameHeadingStroke: "#f89090",
146
153
  frameHeadingFill: "#fffafa",
147
154
  frameStroke: "#f89090",
@@ -157,6 +164,7 @@ const DefaultColorThemePalette = {
157
164
  "light-violet": {
158
165
  solid: "#e085f4",
159
166
  fill: "#e085f4",
167
+ linedFill: "#e9abf7",
160
168
  frameHeadingStroke: "#e59bf5",
161
169
  frameHeadingFill: "#fefaff",
162
170
  frameStroke: "#e59bf5",
@@ -172,6 +180,7 @@ const DefaultColorThemePalette = {
172
180
  orange: {
173
181
  solid: "#e16919",
174
182
  fill: "#e16919",
183
+ linedFill: "#ea8643",
175
184
  frameHeadingStroke: "#e68544",
176
185
  frameHeadingFill: "#fef9f6",
177
186
  frameStroke: "#e68544",
@@ -187,6 +196,7 @@ const DefaultColorThemePalette = {
187
196
  red: {
188
197
  solid: "#e03131",
189
198
  fill: "#e03131",
199
+ linedFill: "#e75f5f",
190
200
  frameHeadingStroke: "#e55757",
191
201
  frameHeadingFill: "#fef7f7",
192
202
  frameStroke: "#e55757",
@@ -202,6 +212,7 @@ const DefaultColorThemePalette = {
202
212
  violet: {
203
213
  solid: "#ae3ec9",
204
214
  fill: "#ae3ec9",
215
+ linedFill: "#be68d4",
205
216
  frameHeadingStroke: "#bc62d3",
206
217
  frameHeadingFill: "#fcf7fd",
207
218
  frameStroke: "#bc62d3",
@@ -217,6 +228,7 @@ const DefaultColorThemePalette = {
217
228
  yellow: {
218
229
  solid: "#f1ac4b",
219
230
  fill: "#f1ac4b",
231
+ linedFill: "#f5c27a",
220
232
  frameHeadingStroke: "#f3bb6c",
221
233
  frameHeadingFill: "#fefcf8",
222
234
  frameStroke: "#f3bb6c",
@@ -232,6 +244,7 @@ const DefaultColorThemePalette = {
232
244
  white: {
233
245
  solid: "#FFFFFF",
234
246
  fill: "#FFFFFF",
247
+ linedFill: "#ffffff",
235
248
  semi: "#f5f5f5",
236
249
  pattern: "#f9f9f9",
237
250
  frameHeadingStroke: "#7d7d7d",
@@ -253,6 +266,7 @@ const DefaultColorThemePalette = {
253
266
  black: {
254
267
  solid: "#f2f2f2",
255
268
  fill: "#f2f2f2",
269
+ linedFill: "#ffffff",
256
270
  frameHeadingStroke: "#5c5c5c",
257
271
  frameHeadingFill: "#252525",
258
272
  frameStroke: "#5c5c5c",
@@ -269,6 +283,7 @@ const DefaultColorThemePalette = {
269
283
  solid: "#4f72fc",
270
284
  // 3c60f0
271
285
  fill: "#4f72fc",
286
+ linedFill: "#3c5cdd",
272
287
  frameHeadingStroke: "#384994",
273
288
  frameHeadingFill: "#1C2036",
274
289
  frameStroke: "#384994",
@@ -284,6 +299,7 @@ const DefaultColorThemePalette = {
284
299
  green: {
285
300
  solid: "#099268",
286
301
  fill: "#099268",
302
+ linedFill: "#087856",
287
303
  frameHeadingStroke: "#10513C",
288
304
  frameHeadingFill: "#14241f",
289
305
  frameStroke: "#10513C",
@@ -299,6 +315,7 @@ const DefaultColorThemePalette = {
299
315
  grey: {
300
316
  solid: "#9398b0",
301
317
  fill: "#9398b0",
318
+ linedFill: "#8388a5",
302
319
  frameHeadingStroke: "#42474D",
303
320
  frameHeadingFill: "#23262A",
304
321
  frameStroke: "#42474D",
@@ -314,6 +331,7 @@ const DefaultColorThemePalette = {
314
331
  "light-blue": {
315
332
  solid: "#4dabf7",
316
333
  fill: "#4dabf7",
334
+ linedFill: "#2793ec",
317
335
  frameHeadingStroke: "#075797",
318
336
  frameHeadingFill: "#142839",
319
337
  frameStroke: "#075797",
@@ -329,6 +347,7 @@ const DefaultColorThemePalette = {
329
347
  "light-green": {
330
348
  solid: "#40c057",
331
349
  fill: "#40c057",
350
+ linedFill: "#37a44b",
332
351
  frameHeadingStroke: "#1C5427",
333
352
  frameHeadingFill: "#18251A",
334
353
  frameStroke: "#1C5427",
@@ -344,6 +363,7 @@ const DefaultColorThemePalette = {
344
363
  "light-red": {
345
364
  solid: "#ff8787",
346
365
  fill: "#ff8787",
366
+ linedFill: "#ff6666",
347
367
  frameHeadingStroke: "#6f3232",
348
368
  // Darker and desaturated variant of solid
349
369
  frameHeadingFill: "#341818",
@@ -367,6 +387,7 @@ const DefaultColorThemePalette = {
367
387
  "light-violet": {
368
388
  solid: "#e599f7",
369
389
  fill: "#e599f7",
390
+ linedFill: "#dc71f4",
370
391
  frameHeadingStroke: "#6c367a",
371
392
  frameHeadingFill: "#2D2230",
372
393
  frameStroke: "#6c367a",
@@ -382,6 +403,7 @@ const DefaultColorThemePalette = {
382
403
  orange: {
383
404
  solid: "#f76707",
384
405
  fill: "#f76707",
406
+ linedFill: "#f54900",
385
407
  frameHeadingStroke: "#773a0e",
386
408
  // Darker, muted version of solid
387
409
  frameHeadingFill: "#2f1d13",
@@ -405,6 +427,7 @@ const DefaultColorThemePalette = {
405
427
  red: {
406
428
  solid: "#e03131",
407
429
  fill: "#e03131",
430
+ linedFill: "#c31d1d",
408
431
  frameHeadingStroke: "#701e1e",
409
432
  // Darker, muted variation of solid
410
433
  frameHeadingFill: "#301616",
@@ -428,6 +451,7 @@ const DefaultColorThemePalette = {
428
451
  violet: {
429
452
  solid: "#ae3ec9",
430
453
  fill: "#ae3ec9",
454
+ linedFill: "#8f2fa7",
431
455
  frameHeadingStroke: "#6d1583",
432
456
  // Darker, muted variation of solid
433
457
  frameHeadingFill: "#27152e",
@@ -451,6 +475,7 @@ const DefaultColorThemePalette = {
451
475
  yellow: {
452
476
  solid: "#ffc034",
453
477
  fill: "#ffc034",
478
+ linedFill: "#ffae00",
454
479
  frameHeadingStroke: "#684e12",
455
480
  // Darker, muted variant of solid
456
481
  frameHeadingFill: "#2a2113",
@@ -474,6 +499,7 @@ const DefaultColorThemePalette = {
474
499
  white: {
475
500
  solid: "#f3f3f3",
476
501
  fill: "#f3f3f3",
502
+ linedFill: "#f3f3f3",
477
503
  semi: "#f5f5f5",
478
504
  pattern: "#f9f9f9",
479
505
  frameHeadingStroke: "#ffffff",