@tldraw/tlschema 4.2.2 → 4.2.3

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 (117) 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 +71 -242
  4. package/dist-cjs/index.js +1 -4
  5. package/dist-cjs/index.js.map +2 -2
  6. package/dist-cjs/misc/TLOpacity.js +5 -1
  7. package/dist-cjs/misc/TLOpacity.js.map +2 -2
  8. package/dist-cjs/misc/TLRichText.js +1 -5
  9. package/dist-cjs/misc/TLRichText.js.map +2 -2
  10. package/dist-cjs/records/TLAsset.js.map +1 -1
  11. package/dist-cjs/records/TLBinding.js.map +2 -2
  12. package/dist-cjs/records/TLShape.js.map +2 -2
  13. package/dist-cjs/shapes/ShapeWithCrop.js.map +1 -1
  14. package/dist-cjs/shapes/TLArrowShape.js +13 -26
  15. package/dist-cjs/shapes/TLArrowShape.js.map +2 -2
  16. package/dist-cjs/shapes/TLBaseShape.js.map +2 -2
  17. package/dist-cjs/shapes/TLDrawShape.js +4 -37
  18. package/dist-cjs/shapes/TLDrawShape.js.map +2 -2
  19. package/dist-cjs/shapes/TLEmbedShape.js +0 -17
  20. package/dist-cjs/shapes/TLEmbedShape.js.map +2 -2
  21. package/dist-cjs/shapes/TLGeoShape.js +1 -12
  22. package/dist-cjs/shapes/TLGeoShape.js.map +2 -2
  23. package/dist-cjs/shapes/TLHighlightShape.js +2 -29
  24. package/dist-cjs/shapes/TLHighlightShape.js.map +2 -2
  25. package/dist-cjs/shapes/TLNoteShape.js +1 -12
  26. package/dist-cjs/shapes/TLNoteShape.js.map +2 -2
  27. package/dist-cjs/shapes/TLTextShape.js +1 -12
  28. package/dist-cjs/shapes/TLTextShape.js.map +2 -2
  29. package/dist-cjs/store-migrations.js +15 -15
  30. package/dist-cjs/store-migrations.js.map +2 -2
  31. package/dist-esm/bindings/TLBaseBinding.mjs.map +2 -2
  32. package/dist-esm/createTLSchema.mjs.map +2 -2
  33. package/dist-esm/index.d.mts +71 -242
  34. package/dist-esm/index.mjs +1 -5
  35. package/dist-esm/index.mjs.map +2 -2
  36. package/dist-esm/misc/TLOpacity.mjs +5 -1
  37. package/dist-esm/misc/TLOpacity.mjs.map +2 -2
  38. package/dist-esm/misc/TLRichText.mjs +1 -5
  39. package/dist-esm/misc/TLRichText.mjs.map +2 -2
  40. package/dist-esm/records/TLAsset.mjs.map +1 -1
  41. package/dist-esm/records/TLBinding.mjs.map +2 -2
  42. package/dist-esm/records/TLShape.mjs.map +2 -2
  43. package/dist-esm/shapes/TLArrowShape.mjs +13 -26
  44. package/dist-esm/shapes/TLArrowShape.mjs.map +2 -2
  45. package/dist-esm/shapes/TLBaseShape.mjs.map +2 -2
  46. package/dist-esm/shapes/TLDrawShape.mjs +4 -37
  47. package/dist-esm/shapes/TLDrawShape.mjs.map +2 -2
  48. package/dist-esm/shapes/TLEmbedShape.mjs +0 -17
  49. package/dist-esm/shapes/TLEmbedShape.mjs.map +2 -2
  50. package/dist-esm/shapes/TLGeoShape.mjs +1 -12
  51. package/dist-esm/shapes/TLGeoShape.mjs.map +2 -2
  52. package/dist-esm/shapes/TLHighlightShape.mjs +2 -29
  53. package/dist-esm/shapes/TLHighlightShape.mjs.map +2 -2
  54. package/dist-esm/shapes/TLNoteShape.mjs +1 -12
  55. package/dist-esm/shapes/TLNoteShape.mjs.map +2 -2
  56. package/dist-esm/shapes/TLTextShape.mjs +1 -12
  57. package/dist-esm/shapes/TLTextShape.mjs.map +2 -2
  58. package/dist-esm/store-migrations.mjs +15 -15
  59. package/dist-esm/store-migrations.mjs.map +2 -2
  60. package/package.json +8 -8
  61. package/src/__tests__/migrationTestUtils.ts +3 -9
  62. package/src/assets/TLBookmarkAsset.test.ts +96 -0
  63. package/src/assets/TLImageAsset.test.ts +213 -0
  64. package/src/assets/TLVideoAsset.test.ts +105 -0
  65. package/src/bindings/TLArrowBinding.test.ts +55 -0
  66. package/src/bindings/TLBaseBinding.ts +14 -25
  67. package/src/createTLSchema.ts +2 -8
  68. package/src/index.ts +0 -9
  69. package/src/migrations.test.ts +1 -149
  70. package/src/misc/TLOpacity.ts +5 -1
  71. package/src/misc/TLRichText.ts +1 -6
  72. package/src/misc/id-validator.test.ts +50 -0
  73. package/src/records/TLAsset.test.ts +234 -0
  74. package/src/records/TLAsset.ts +2 -2
  75. package/src/records/TLBinding.test.ts +22 -0
  76. package/src/records/TLBinding.ts +23 -65
  77. package/src/records/TLCamera.test.ts +19 -0
  78. package/src/records/TLDocument.test.ts +35 -0
  79. package/src/records/TLInstance.test.ts +201 -0
  80. package/src/records/TLPage.test.ts +110 -0
  81. package/src/records/TLPageState.test.ts +228 -0
  82. package/src/records/TLPointer.test.ts +63 -0
  83. package/src/records/TLPresence.test.ts +190 -0
  84. package/src/records/TLRecord.test.ts +70 -0
  85. package/src/records/TLShape.test.ts +232 -0
  86. package/src/records/TLShape.ts +5 -100
  87. package/src/shapes/ShapeWithCrop.test.ts +18 -0
  88. package/src/shapes/ShapeWithCrop.ts +2 -2
  89. package/src/shapes/TLArrowShape.test.ts +505 -0
  90. package/src/shapes/TLArrowShape.ts +14 -28
  91. package/src/shapes/TLBaseShape.test.ts +142 -0
  92. package/src/shapes/TLBaseShape.ts +10 -34
  93. package/src/shapes/TLBookmarkShape.test.ts +122 -0
  94. package/src/shapes/TLDrawShape.test.ts +177 -0
  95. package/src/shapes/TLDrawShape.ts +12 -59
  96. package/src/shapes/TLEmbedShape.test.ts +286 -0
  97. package/src/shapes/TLEmbedShape.ts +0 -17
  98. package/src/shapes/TLFrameShape.test.ts +71 -0
  99. package/src/shapes/TLGeoShape.test.ts +247 -0
  100. package/src/shapes/TLGeoShape.ts +1 -14
  101. package/src/shapes/TLGroupShape.test.ts +59 -0
  102. package/src/shapes/TLHighlightShape.test.ts +325 -0
  103. package/src/shapes/TLHighlightShape.ts +0 -37
  104. package/src/shapes/TLImageShape.test.ts +534 -0
  105. package/src/shapes/TLLineShape.test.ts +269 -0
  106. package/src/shapes/TLNoteShape.test.ts +1568 -0
  107. package/src/shapes/TLNoteShape.ts +1 -15
  108. package/src/shapes/TLTextShape.test.ts +407 -0
  109. package/src/shapes/TLTextShape.ts +2 -16
  110. package/src/shapes/TLVideoShape.test.ts +112 -0
  111. package/src/store-migrations.ts +16 -17
  112. package/src/styles/TLColorStyle.test.ts +439 -0
  113. package/dist-cjs/misc/b64Vecs.js +0 -224
  114. package/dist-cjs/misc/b64Vecs.js.map +0 -7
  115. package/dist-esm/misc/b64Vecs.mjs +0 -204
  116. package/dist-esm/misc/b64Vecs.mjs.map +0 -7
  117. package/src/misc/b64Vecs.ts +0 -308
@@ -5,7 +5,6 @@ const TLDRAW_APP_RE = /(^\/r\/[^/]+\/?$)/;
5
5
  const EMBED_DEFINITIONS = [
6
6
  {
7
7
  hostnames: ["beta.tldraw.com", "tldraw.com", "localhost:3000"],
8
- canEditWhileLocked: true,
9
8
  fromEmbedUrl: (url) => {
10
9
  const urlObj = safeParseUrl(url);
11
10
  if (urlObj && urlObj.pathname.match(TLDRAW_APP_RE)) {
@@ -16,7 +15,6 @@ const EMBED_DEFINITIONS = [
16
15
  },
17
16
  {
18
17
  hostnames: ["figma.com"],
19
- canEditWhileLocked: true,
20
18
  fromEmbedUrl: (url) => {
21
19
  const urlObj = safeParseUrl(url);
22
20
  if (urlObj && urlObj.pathname.match(/^\/embed\/?$/)) {
@@ -30,7 +28,6 @@ const EMBED_DEFINITIONS = [
30
28
  },
31
29
  {
32
30
  hostnames: ["google.*"],
33
- canEditWhileLocked: true,
34
31
  fromEmbedUrl: (url) => {
35
32
  const urlObj = safeParseUrl(url);
36
33
  if (!urlObj) return;
@@ -45,7 +42,6 @@ const EMBED_DEFINITIONS = [
45
42
  },
46
43
  {
47
44
  hostnames: ["val.town"],
48
- canEditWhileLocked: true,
49
45
  fromEmbedUrl: (url) => {
50
46
  const urlObj = safeParseUrl(url);
51
47
  const matches = urlObj && urlObj.pathname.match(/\/embed\/(.+)\/?/);
@@ -57,7 +53,6 @@ const EMBED_DEFINITIONS = [
57
53
  },
58
54
  {
59
55
  hostnames: ["codesandbox.io"],
60
- canEditWhileLocked: true,
61
56
  fromEmbedUrl: (url) => {
62
57
  const urlObj = safeParseUrl(url);
63
58
  const matches = urlObj && urlObj.pathname.match(/\/embed\/([^/]+)\/?/);
@@ -69,7 +64,6 @@ const EMBED_DEFINITIONS = [
69
64
  },
70
65
  {
71
66
  hostnames: ["codepen.io"],
72
- canEditWhileLocked: true,
73
67
  fromEmbedUrl: (url) => {
74
68
  const CODEPEN_EMBED_REGEXP = /https:\/\/codepen.io\/([^/]+)\/embed\/([^/]+)/;
75
69
  const matches = url.match(CODEPEN_EMBED_REGEXP);
@@ -82,7 +76,6 @@ const EMBED_DEFINITIONS = [
82
76
  },
83
77
  {
84
78
  hostnames: ["scratch.mit.edu"],
85
- canEditWhileLocked: true,
86
79
  fromEmbedUrl: (url) => {
87
80
  const SCRATCH_EMBED_REGEXP = /https:\/\/scratch.mit.edu\/projects\/embed\/([^/]+)/;
88
81
  const matches = url.match(SCRATCH_EMBED_REGEXP);
@@ -95,7 +88,6 @@ const EMBED_DEFINITIONS = [
95
88
  },
96
89
  {
97
90
  hostnames: ["*.youtube.com", "youtube.com", "youtu.be"],
98
- canEditWhileLocked: true,
99
91
  fromEmbedUrl: (url) => {
100
92
  const urlObj = safeParseUrl(url);
101
93
  if (!urlObj) return;
@@ -111,7 +103,6 @@ const EMBED_DEFINITIONS = [
111
103
  },
112
104
  {
113
105
  hostnames: ["calendar.google.*"],
114
- canEditWhileLocked: true,
115
106
  fromEmbedUrl: (url) => {
116
107
  const urlObj = safeParseUrl(url);
117
108
  const srcQs = urlObj?.searchParams.get("src");
@@ -129,7 +120,6 @@ const EMBED_DEFINITIONS = [
129
120
  },
130
121
  {
131
122
  hostnames: ["docs.google.*"],
132
- canEditWhileLocked: true,
133
123
  fromEmbedUrl: (url) => {
134
124
  const urlObj = safeParseUrl(url);
135
125
  if (urlObj?.pathname.match(/^\/presentation/) && urlObj?.pathname.match(/\/embed\/?$/)) {
@@ -145,7 +135,6 @@ const EMBED_DEFINITIONS = [
145
135
  },
146
136
  {
147
137
  hostnames: ["gist.github.com"],
148
- canEditWhileLocked: true,
149
138
  fromEmbedUrl: (url) => {
150
139
  const urlObj = safeParseUrl(url);
151
140
  if (urlObj && urlObj.pathname.match(/\/([^/]+)\/([^/]+)/)) {
@@ -157,7 +146,6 @@ const EMBED_DEFINITIONS = [
157
146
  },
158
147
  {
159
148
  hostnames: ["replit.com"],
160
- canEditWhileLocked: true,
161
149
  fromEmbedUrl: (url) => {
162
150
  const urlObj = safeParseUrl(url);
163
151
  if (urlObj && urlObj.pathname.match(/\/@([^/]+)\/([^/]+)/) && urlObj.searchParams.has("embed")) {
@@ -169,7 +157,6 @@ const EMBED_DEFINITIONS = [
169
157
  },
170
158
  {
171
159
  hostnames: ["felt.com"],
172
- canEditWhileLocked: true,
173
160
  fromEmbedUrl: (url) => {
174
161
  const urlObj = safeParseUrl(url);
175
162
  if (urlObj && urlObj.pathname.match(/^\/embed\/map\//)) {
@@ -181,7 +168,6 @@ const EMBED_DEFINITIONS = [
181
168
  },
182
169
  {
183
170
  hostnames: ["open.spotify.com"],
184
- canEditWhileLocked: true,
185
171
  fromEmbedUrl: (url) => {
186
172
  const urlObj = safeParseUrl(url);
187
173
  if (urlObj && urlObj.pathname.match(/^\/embed\/(artist|album)\//)) {
@@ -192,7 +178,6 @@ const EMBED_DEFINITIONS = [
192
178
  },
193
179
  {
194
180
  hostnames: ["vimeo.com", "player.vimeo.com"],
195
- canEditWhileLocked: true,
196
181
  fromEmbedUrl: (url) => {
197
182
  const urlObj = safeParseUrl(url);
198
183
  if (urlObj && urlObj.hostname === "player.vimeo.com") {
@@ -206,7 +191,6 @@ const EMBED_DEFINITIONS = [
206
191
  },
207
192
  {
208
193
  hostnames: ["observablehq.com"],
209
- canEditWhileLocked: true,
210
194
  fromEmbedUrl: (url) => {
211
195
  const urlObj = safeParseUrl(url);
212
196
  if (urlObj && urlObj.pathname.match(/^\/embed\/@([^/]+)\/([^/]+)\/?$/)) {
@@ -220,7 +204,6 @@ const EMBED_DEFINITIONS = [
220
204
  },
221
205
  {
222
206
  hostnames: ["desmos.com"],
223
- canEditWhileLocked: true,
224
207
  fromEmbedUrl: (url) => {
225
208
  const urlObj = safeParseUrl(url);
226
209
  if (urlObj && urlObj.hostname === "www.desmos.com" && urlObj.pathname.match(/^\/calculator\/([^/]+)\/?$/) && urlObj.search === "?embed" && urlObj.hash === "") {
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../src/shapes/TLEmbedShape.ts"],
4
- "sourcesContent": ["import { safeParseUrl } from '@tldraw/utils'\nimport { T } from '@tldraw/validate'\nimport { createShapePropsMigrationIds, createShapePropsMigrationSequence } from '../records/TLShape'\nimport { RecordProps } from '../recordsWithProps'\nimport { TLBaseShape } from './TLBaseShape'\n\n// Only allow multiplayer embeds. If we add additional routes later for example '/help' this won't match\nconst TLDRAW_APP_RE = /(^\\/r\\/[^/]+\\/?$)/\n\nconst EMBED_DEFINITIONS = [\n\t{\n\t\thostnames: ['beta.tldraw.com', 'tldraw.com', 'localhost:3000'],\n\t\tcanEditWhileLocked: true,\n\t\tfromEmbedUrl: (url: string) => {\n\t\t\tconst urlObj = safeParseUrl(url)\n\t\t\tif (urlObj && urlObj.pathname.match(TLDRAW_APP_RE)) {\n\t\t\t\treturn url\n\t\t\t}\n\t\t\treturn\n\t\t},\n\t},\n\t{\n\t\thostnames: ['figma.com'],\n\t\tcanEditWhileLocked: true,\n\t\tfromEmbedUrl: (url: string) => {\n\t\t\tconst urlObj = safeParseUrl(url)\n\t\t\tif (urlObj && urlObj.pathname.match(/^\\/embed\\/?$/)) {\n\t\t\t\tconst outUrl = urlObj.searchParams.get('url')\n\t\t\t\tif (outUrl) {\n\t\t\t\t\treturn outUrl\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn\n\t\t},\n\t},\n\t{\n\t\thostnames: ['google.*'],\n\t\tcanEditWhileLocked: true,\n\t\tfromEmbedUrl: (url: string) => {\n\t\t\tconst urlObj = safeParseUrl(url)\n\t\t\tif (!urlObj) return\n\n\t\t\tconst matches = urlObj.pathname.match(/^\\/maps\\/embed\\/v1\\/view\\/?$/)\n\t\t\tif (matches && urlObj.searchParams.has('center') && urlObj.searchParams.get('zoom')) {\n\t\t\t\tconst zoom = urlObj.searchParams.get('zoom')\n\t\t\t\tconst [lat, lon] = urlObj.searchParams.get('center')!.split(',')\n\t\t\t\treturn `https://www.google.com/maps/@${lat},${lon},${zoom}z`\n\t\t\t}\n\t\t\treturn\n\t\t},\n\t},\n\t{\n\t\thostnames: ['val.town'],\n\t\tcanEditWhileLocked: true,\n\t\tfromEmbedUrl: (url: string) => {\n\t\t\tconst urlObj = safeParseUrl(url)\n\t\t\t// e.g. extract \"steveruizok/mathFact\" from https://www.val.town/v/steveruizok/mathFact\n\t\t\tconst matches = urlObj && urlObj.pathname.match(/\\/embed\\/(.+)\\/?/)\n\t\t\tif (matches) {\n\t\t\t\treturn `https://www.val.town/v/${matches[1]}`\n\t\t\t}\n\t\t\treturn\n\t\t},\n\t},\n\t{\n\t\thostnames: ['codesandbox.io'],\n\t\tcanEditWhileLocked: true,\n\t\tfromEmbedUrl: (url: string) => {\n\t\t\tconst urlObj = safeParseUrl(url)\n\t\t\tconst matches = urlObj && urlObj.pathname.match(/\\/embed\\/([^/]+)\\/?/)\n\t\t\tif (matches) {\n\t\t\t\treturn `https://codesandbox.io/s/${matches[1]}`\n\t\t\t}\n\t\t\treturn\n\t\t},\n\t},\n\t{\n\t\thostnames: ['codepen.io'],\n\t\tcanEditWhileLocked: true,\n\t\tfromEmbedUrl: (url: string) => {\n\t\t\tconst CODEPEN_EMBED_REGEXP = /https:\\/\\/codepen.io\\/([^/]+)\\/embed\\/([^/]+)/\n\t\t\tconst matches = url.match(CODEPEN_EMBED_REGEXP)\n\t\t\tif (matches) {\n\t\t\t\tconst [_, user, id] = matches\n\t\t\t\treturn `https://codepen.io/${user}/pen/${id}`\n\t\t\t}\n\t\t\treturn\n\t\t},\n\t},\n\t{\n\t\thostnames: ['scratch.mit.edu'],\n\t\tcanEditWhileLocked: true,\n\t\tfromEmbedUrl: (url: string) => {\n\t\t\tconst SCRATCH_EMBED_REGEXP = /https:\\/\\/scratch.mit.edu\\/projects\\/embed\\/([^/]+)/\n\t\t\tconst matches = url.match(SCRATCH_EMBED_REGEXP)\n\t\t\tif (matches) {\n\t\t\t\tconst [_, id] = matches\n\t\t\t\treturn `https://scratch.mit.edu/projects/${id}`\n\t\t\t}\n\t\t\treturn\n\t\t},\n\t},\n\t{\n\t\thostnames: ['*.youtube.com', 'youtube.com', 'youtu.be'],\n\t\tcanEditWhileLocked: true,\n\t\tfromEmbedUrl: (url: string) => {\n\t\t\tconst urlObj = safeParseUrl(url)\n\t\t\tif (!urlObj) return\n\n\t\t\tconst hostname = urlObj.hostname.replace(/^www./, '')\n\t\t\tif (hostname === 'youtube.com') {\n\t\t\t\tconst matches = urlObj.pathname.match(/^\\/embed\\/([^/]+)\\/?/)\n\t\t\t\tif (matches) {\n\t\t\t\t\treturn `https://www.youtube.com/watch?v=${matches[1]}`\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn\n\t\t},\n\t},\n\t{\n\t\thostnames: ['calendar.google.*'],\n\t\tcanEditWhileLocked: true,\n\t\tfromEmbedUrl: (url: string) => {\n\t\t\tconst urlObj = safeParseUrl(url)\n\t\t\tconst srcQs = urlObj?.searchParams.get('src')\n\n\t\t\tif (urlObj?.pathname.match(/\\/calendar\\/embed/) && srcQs) {\n\t\t\t\turlObj.pathname = '/calendar/u/0'\n\t\t\t\tconst keys = Array.from(urlObj.searchParams.keys())\n\t\t\t\tfor (const key of keys) {\n\t\t\t\t\turlObj.searchParams.delete(key)\n\t\t\t\t}\n\t\t\t\turlObj.searchParams.set('cid', srcQs)\n\t\t\t\treturn urlObj.href\n\t\t\t}\n\t\t\treturn\n\t\t},\n\t},\n\t{\n\t\thostnames: ['docs.google.*'],\n\t\tcanEditWhileLocked: true,\n\t\tfromEmbedUrl: (url: string) => {\n\t\t\tconst urlObj = safeParseUrl(url)\n\n\t\t\tif (urlObj?.pathname.match(/^\\/presentation/) && urlObj?.pathname.match(/\\/embed\\/?$/)) {\n\t\t\t\turlObj.pathname = urlObj.pathname.replace(/\\/embed$/, '/pub')\n\t\t\t\tconst keys = Array.from(urlObj.searchParams.keys())\n\t\t\t\tfor (const key of keys) {\n\t\t\t\t\turlObj.searchParams.delete(key)\n\t\t\t\t}\n\t\t\t\treturn urlObj.href\n\t\t\t}\n\t\t\treturn\n\t\t},\n\t},\n\t{\n\t\thostnames: ['gist.github.com'],\n\t\tcanEditWhileLocked: true,\n\t\tfromEmbedUrl: (url: string) => {\n\t\t\tconst urlObj = safeParseUrl(url)\n\t\t\tif (urlObj && urlObj.pathname.match(/\\/([^/]+)\\/([^/]+)/)) {\n\t\t\t\tif (!url.split('/').pop()) return\n\t\t\t\treturn url\n\t\t\t}\n\t\t\treturn\n\t\t},\n\t},\n\t{\n\t\thostnames: ['replit.com'],\n\t\tcanEditWhileLocked: true,\n\t\tfromEmbedUrl: (url: string) => {\n\t\t\tconst urlObj = safeParseUrl(url)\n\t\t\tif (\n\t\t\t\turlObj &&\n\t\t\t\turlObj.pathname.match(/\\/@([^/]+)\\/([^/]+)/) &&\n\t\t\t\turlObj.searchParams.has('embed')\n\t\t\t) {\n\t\t\t\turlObj.searchParams.delete('embed')\n\t\t\t\treturn urlObj.href\n\t\t\t}\n\t\t\treturn\n\t\t},\n\t},\n\t{\n\t\thostnames: ['felt.com'],\n\t\tcanEditWhileLocked: true,\n\t\tfromEmbedUrl: (url: string) => {\n\t\t\tconst urlObj = safeParseUrl(url)\n\t\t\tif (urlObj && urlObj.pathname.match(/^\\/embed\\/map\\//)) {\n\t\t\t\turlObj.pathname = urlObj.pathname.replace(/^\\/embed/, '')\n\t\t\t\treturn urlObj.href\n\t\t\t}\n\t\t\treturn\n\t\t},\n\t},\n\t{\n\t\thostnames: ['open.spotify.com'],\n\t\tcanEditWhileLocked: true,\n\t\tfromEmbedUrl: (url: string) => {\n\t\t\tconst urlObj = safeParseUrl(url)\n\t\t\tif (urlObj && urlObj.pathname.match(/^\\/embed\\/(artist|album)\\//)) {\n\t\t\t\treturn urlObj.origin + urlObj.pathname.replace(/^\\/embed/, '')\n\t\t\t}\n\t\t\treturn\n\t\t},\n\t},\n\t{\n\t\thostnames: ['vimeo.com', 'player.vimeo.com'],\n\t\tcanEditWhileLocked: true,\n\t\tfromEmbedUrl: (url: string) => {\n\t\t\tconst urlObj = safeParseUrl(url)\n\t\t\tif (urlObj && urlObj.hostname === 'player.vimeo.com') {\n\t\t\t\tconst matches = urlObj.pathname.match(/^\\/video\\/([^/]+)\\/?$/)\n\t\t\t\tif (matches) {\n\t\t\t\t\treturn 'https://vimeo.com/' + matches[1]\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn\n\t\t},\n\t},\n\t{\n\t\thostnames: ['observablehq.com'],\n\t\tcanEditWhileLocked: true,\n\t\tfromEmbedUrl: (url: string) => {\n\t\t\tconst urlObj = safeParseUrl(url)\n\t\t\tif (urlObj && urlObj.pathname.match(/^\\/embed\\/@([^/]+)\\/([^/]+)\\/?$/)) {\n\t\t\t\treturn `${urlObj.origin}${urlObj.pathname.replace('/embed', '')}#cell-*`\n\t\t\t}\n\t\t\tif (urlObj && urlObj.pathname.match(/^\\/embed\\/([^/]+)\\/?$/)) {\n\t\t\t\treturn `${urlObj.origin}${urlObj.pathname.replace('/embed', '/d')}#cell-*`\n\t\t\t}\n\n\t\t\treturn\n\t\t},\n\t},\n\t{\n\t\thostnames: ['desmos.com'],\n\t\tcanEditWhileLocked: true,\n\t\tfromEmbedUrl: (url: string) => {\n\t\t\tconst urlObj = safeParseUrl(url)\n\t\t\tif (\n\t\t\t\turlObj &&\n\t\t\t\turlObj.hostname === 'www.desmos.com' &&\n\t\t\t\turlObj.pathname.match(/^\\/calculator\\/([^/]+)\\/?$/) &&\n\t\t\t\turlObj.search === '?embed' &&\n\t\t\t\turlObj.hash === ''\n\t\t\t) {\n\t\t\t\treturn url.replace('?embed', '')\n\t\t\t}\n\t\t\treturn\n\t\t},\n\t},\n]\n\n/**\n * Properties for the embed shape, which displays embedded content from external services.\n *\n * @public\n */\nexport interface TLEmbedShapeProps {\n\t/** Width of the embed shape in pixels */\n\tw: number\n\t/** Height of the embed shape in pixels */\n\th: number\n\t/** URL of the content to embed (supports YouTube, Figma, CodePen, etc.) */\n\turl: string\n}\n\n/**\n * An embed shape displays external content like YouTube videos, Figma designs, CodePen demos,\n * and other embeddable content within the tldraw canvas.\n *\n * @public\n * @example\n * ```ts\n * const embedShape: TLEmbedShape = {\n * id: createShapeId(),\n * typeName: 'shape',\n * type: 'embed',\n * x: 200,\n * y: 200,\n * rotation: 0,\n * index: 'a1',\n * parentId: 'page:page1',\n * isLocked: false,\n * opacity: 1,\n * props: {\n * w: 560,\n * h: 315,\n * url: 'https://www.youtube.com/watch?v=dQw4w9WgXcQ'\n * },\n * meta: {}\n * }\n * ```\n */\nexport type TLEmbedShape = TLBaseShape<'embed', TLEmbedShapeProps>\n\n/**\n * Validation schema for embed shape properties.\n *\n * @public\n * @example\n * ```ts\n * // Validate embed shape properties\n * const isValidUrl = embedShapeProps.url.isValid('https://youtube.com/watch?v=abc123')\n * const isValidSize = embedShapeProps.w.isValid(560)\n * ```\n */\nexport const embedShapeProps: RecordProps<TLEmbedShape> = {\n\tw: T.nonZeroNumber,\n\th: T.nonZeroNumber,\n\turl: T.string,\n}\n\nconst Versions = createShapePropsMigrationIds('embed', {\n\tGenOriginalUrlInEmbed: 1,\n\tRemoveDoesResize: 2,\n\tRemoveTmpOldUrl: 3,\n\tRemovePermissionOverrides: 4,\n})\n\n/**\n * Version identifiers for embed shape migrations.\n *\n * @public\n */\nexport { Versions as embedShapeVersions }\n\n/**\n * Migration sequence for embed shape properties across different schema versions.\n * Handles URL transformations and removal of deprecated properties.\n *\n * @public\n */\nexport const embedShapeMigrations = createShapePropsMigrationSequence({\n\tsequence: [\n\t\t{\n\t\t\tid: Versions.GenOriginalUrlInEmbed,\n\t\t\t// add tmpOldUrl property\n\t\t\tup: (props) => {\n\t\t\t\ttry {\n\t\t\t\t\tconst url = props.url\n\t\t\t\t\tconst host = new URL(url).host.replace('www.', '')\n\t\t\t\t\tlet originalUrl\n\t\t\t\t\tfor (const localEmbedDef of EMBED_DEFINITIONS) {\n\t\t\t\t\t\tif (localEmbedDef.hostnames.includes(host)) {\n\t\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\t\toriginalUrl = localEmbedDef.fromEmbedUrl(url)\n\t\t\t\t\t\t\t} catch (err) {\n\t\t\t\t\t\t\t\tconsole.warn(err)\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\tprops.tmpOldUrl = props.url\n\t\t\t\t\tprops.url = originalUrl ?? ''\n\t\t\t\t} catch {\n\t\t\t\t\tprops.url = ''\n\t\t\t\t\tprops.tmpOldUrl = props.url\n\t\t\t\t}\n\t\t\t},\n\t\t\tdown: 'retired',\n\t\t},\n\t\t{\n\t\t\tid: Versions.RemoveDoesResize,\n\t\t\tup: (props) => {\n\t\t\t\tdelete props.doesResize\n\t\t\t},\n\t\t\tdown: 'retired',\n\t\t},\n\t\t{\n\t\t\tid: Versions.RemoveTmpOldUrl,\n\t\t\tup: (props) => {\n\t\t\t\tdelete props.tmpOldUrl\n\t\t\t},\n\t\t\tdown: 'retired',\n\t\t},\n\t\t{\n\t\t\tid: Versions.RemovePermissionOverrides,\n\t\t\tup: (props) => {\n\t\t\t\tdelete props.overridePermissions\n\t\t\t},\n\t\t\tdown: 'retired',\n\t\t},\n\t],\n})\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["import { safeParseUrl } from '@tldraw/utils'\nimport { T } from '@tldraw/validate'\nimport { createShapePropsMigrationIds, createShapePropsMigrationSequence } from '../records/TLShape'\nimport { RecordProps } from '../recordsWithProps'\nimport { TLBaseShape } from './TLBaseShape'\n\n// Only allow multiplayer embeds. If we add additional routes later for example '/help' this won't match\nconst TLDRAW_APP_RE = /(^\\/r\\/[^/]+\\/?$)/\n\nconst EMBED_DEFINITIONS = [\n\t{\n\t\thostnames: ['beta.tldraw.com', 'tldraw.com', 'localhost:3000'],\n\t\tfromEmbedUrl: (url: string) => {\n\t\t\tconst urlObj = safeParseUrl(url)\n\t\t\tif (urlObj && urlObj.pathname.match(TLDRAW_APP_RE)) {\n\t\t\t\treturn url\n\t\t\t}\n\t\t\treturn\n\t\t},\n\t},\n\t{\n\t\thostnames: ['figma.com'],\n\t\tfromEmbedUrl: (url: string) => {\n\t\t\tconst urlObj = safeParseUrl(url)\n\t\t\tif (urlObj && urlObj.pathname.match(/^\\/embed\\/?$/)) {\n\t\t\t\tconst outUrl = urlObj.searchParams.get('url')\n\t\t\t\tif (outUrl) {\n\t\t\t\t\treturn outUrl\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn\n\t\t},\n\t},\n\t{\n\t\thostnames: ['google.*'],\n\t\tfromEmbedUrl: (url: string) => {\n\t\t\tconst urlObj = safeParseUrl(url)\n\t\t\tif (!urlObj) return\n\n\t\t\tconst matches = urlObj.pathname.match(/^\\/maps\\/embed\\/v1\\/view\\/?$/)\n\t\t\tif (matches && urlObj.searchParams.has('center') && urlObj.searchParams.get('zoom')) {\n\t\t\t\tconst zoom = urlObj.searchParams.get('zoom')\n\t\t\t\tconst [lat, lon] = urlObj.searchParams.get('center')!.split(',')\n\t\t\t\treturn `https://www.google.com/maps/@${lat},${lon},${zoom}z`\n\t\t\t}\n\t\t\treturn\n\t\t},\n\t},\n\t{\n\t\thostnames: ['val.town'],\n\t\tfromEmbedUrl: (url: string) => {\n\t\t\tconst urlObj = safeParseUrl(url)\n\t\t\t// e.g. extract \"steveruizok/mathFact\" from https://www.val.town/v/steveruizok/mathFact\n\t\t\tconst matches = urlObj && urlObj.pathname.match(/\\/embed\\/(.+)\\/?/)\n\t\t\tif (matches) {\n\t\t\t\treturn `https://www.val.town/v/${matches[1]}`\n\t\t\t}\n\t\t\treturn\n\t\t},\n\t},\n\t{\n\t\thostnames: ['codesandbox.io'],\n\t\tfromEmbedUrl: (url: string) => {\n\t\t\tconst urlObj = safeParseUrl(url)\n\t\t\tconst matches = urlObj && urlObj.pathname.match(/\\/embed\\/([^/]+)\\/?/)\n\t\t\tif (matches) {\n\t\t\t\treturn `https://codesandbox.io/s/${matches[1]}`\n\t\t\t}\n\t\t\treturn\n\t\t},\n\t},\n\t{\n\t\thostnames: ['codepen.io'],\n\t\tfromEmbedUrl: (url: string) => {\n\t\t\tconst CODEPEN_EMBED_REGEXP = /https:\\/\\/codepen.io\\/([^/]+)\\/embed\\/([^/]+)/\n\t\t\tconst matches = url.match(CODEPEN_EMBED_REGEXP)\n\t\t\tif (matches) {\n\t\t\t\tconst [_, user, id] = matches\n\t\t\t\treturn `https://codepen.io/${user}/pen/${id}`\n\t\t\t}\n\t\t\treturn\n\t\t},\n\t},\n\t{\n\t\thostnames: ['scratch.mit.edu'],\n\t\tfromEmbedUrl: (url: string) => {\n\t\t\tconst SCRATCH_EMBED_REGEXP = /https:\\/\\/scratch.mit.edu\\/projects\\/embed\\/([^/]+)/\n\t\t\tconst matches = url.match(SCRATCH_EMBED_REGEXP)\n\t\t\tif (matches) {\n\t\t\t\tconst [_, id] = matches\n\t\t\t\treturn `https://scratch.mit.edu/projects/${id}`\n\t\t\t}\n\t\t\treturn\n\t\t},\n\t},\n\t{\n\t\thostnames: ['*.youtube.com', 'youtube.com', 'youtu.be'],\n\t\tfromEmbedUrl: (url: string) => {\n\t\t\tconst urlObj = safeParseUrl(url)\n\t\t\tif (!urlObj) return\n\n\t\t\tconst hostname = urlObj.hostname.replace(/^www./, '')\n\t\t\tif (hostname === 'youtube.com') {\n\t\t\t\tconst matches = urlObj.pathname.match(/^\\/embed\\/([^/]+)\\/?/)\n\t\t\t\tif (matches) {\n\t\t\t\t\treturn `https://www.youtube.com/watch?v=${matches[1]}`\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn\n\t\t},\n\t},\n\t{\n\t\thostnames: ['calendar.google.*'],\n\t\tfromEmbedUrl: (url: string) => {\n\t\t\tconst urlObj = safeParseUrl(url)\n\t\t\tconst srcQs = urlObj?.searchParams.get('src')\n\n\t\t\tif (urlObj?.pathname.match(/\\/calendar\\/embed/) && srcQs) {\n\t\t\t\turlObj.pathname = '/calendar/u/0'\n\t\t\t\tconst keys = Array.from(urlObj.searchParams.keys())\n\t\t\t\tfor (const key of keys) {\n\t\t\t\t\turlObj.searchParams.delete(key)\n\t\t\t\t}\n\t\t\t\turlObj.searchParams.set('cid', srcQs)\n\t\t\t\treturn urlObj.href\n\t\t\t}\n\t\t\treturn\n\t\t},\n\t},\n\t{\n\t\thostnames: ['docs.google.*'],\n\t\tfromEmbedUrl: (url: string) => {\n\t\t\tconst urlObj = safeParseUrl(url)\n\n\t\t\tif (urlObj?.pathname.match(/^\\/presentation/) && urlObj?.pathname.match(/\\/embed\\/?$/)) {\n\t\t\t\turlObj.pathname = urlObj.pathname.replace(/\\/embed$/, '/pub')\n\t\t\t\tconst keys = Array.from(urlObj.searchParams.keys())\n\t\t\t\tfor (const key of keys) {\n\t\t\t\t\turlObj.searchParams.delete(key)\n\t\t\t\t}\n\t\t\t\treturn urlObj.href\n\t\t\t}\n\t\t\treturn\n\t\t},\n\t},\n\t{\n\t\thostnames: ['gist.github.com'],\n\t\tfromEmbedUrl: (url: string) => {\n\t\t\tconst urlObj = safeParseUrl(url)\n\t\t\tif (urlObj && urlObj.pathname.match(/\\/([^/]+)\\/([^/]+)/)) {\n\t\t\t\tif (!url.split('/').pop()) return\n\t\t\t\treturn url\n\t\t\t}\n\t\t\treturn\n\t\t},\n\t},\n\t{\n\t\thostnames: ['replit.com'],\n\t\tfromEmbedUrl: (url: string) => {\n\t\t\tconst urlObj = safeParseUrl(url)\n\t\t\tif (\n\t\t\t\turlObj &&\n\t\t\t\turlObj.pathname.match(/\\/@([^/]+)\\/([^/]+)/) &&\n\t\t\t\turlObj.searchParams.has('embed')\n\t\t\t) {\n\t\t\t\turlObj.searchParams.delete('embed')\n\t\t\t\treturn urlObj.href\n\t\t\t}\n\t\t\treturn\n\t\t},\n\t},\n\t{\n\t\thostnames: ['felt.com'],\n\t\tfromEmbedUrl: (url: string) => {\n\t\t\tconst urlObj = safeParseUrl(url)\n\t\t\tif (urlObj && urlObj.pathname.match(/^\\/embed\\/map\\//)) {\n\t\t\t\turlObj.pathname = urlObj.pathname.replace(/^\\/embed/, '')\n\t\t\t\treturn urlObj.href\n\t\t\t}\n\t\t\treturn\n\t\t},\n\t},\n\t{\n\t\thostnames: ['open.spotify.com'],\n\t\tfromEmbedUrl: (url: string) => {\n\t\t\tconst urlObj = safeParseUrl(url)\n\t\t\tif (urlObj && urlObj.pathname.match(/^\\/embed\\/(artist|album)\\//)) {\n\t\t\t\treturn urlObj.origin + urlObj.pathname.replace(/^\\/embed/, '')\n\t\t\t}\n\t\t\treturn\n\t\t},\n\t},\n\t{\n\t\thostnames: ['vimeo.com', 'player.vimeo.com'],\n\t\tfromEmbedUrl: (url: string) => {\n\t\t\tconst urlObj = safeParseUrl(url)\n\t\t\tif (urlObj && urlObj.hostname === 'player.vimeo.com') {\n\t\t\t\tconst matches = urlObj.pathname.match(/^\\/video\\/([^/]+)\\/?$/)\n\t\t\t\tif (matches) {\n\t\t\t\t\treturn 'https://vimeo.com/' + matches[1]\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn\n\t\t},\n\t},\n\t{\n\t\thostnames: ['observablehq.com'],\n\t\tfromEmbedUrl: (url: string) => {\n\t\t\tconst urlObj = safeParseUrl(url)\n\t\t\tif (urlObj && urlObj.pathname.match(/^\\/embed\\/@([^/]+)\\/([^/]+)\\/?$/)) {\n\t\t\t\treturn `${urlObj.origin}${urlObj.pathname.replace('/embed', '')}#cell-*`\n\t\t\t}\n\t\t\tif (urlObj && urlObj.pathname.match(/^\\/embed\\/([^/]+)\\/?$/)) {\n\t\t\t\treturn `${urlObj.origin}${urlObj.pathname.replace('/embed', '/d')}#cell-*`\n\t\t\t}\n\n\t\t\treturn\n\t\t},\n\t},\n\t{\n\t\thostnames: ['desmos.com'],\n\t\tfromEmbedUrl: (url: string) => {\n\t\t\tconst urlObj = safeParseUrl(url)\n\t\t\tif (\n\t\t\t\turlObj &&\n\t\t\t\turlObj.hostname === 'www.desmos.com' &&\n\t\t\t\turlObj.pathname.match(/^\\/calculator\\/([^/]+)\\/?$/) &&\n\t\t\t\turlObj.search === '?embed' &&\n\t\t\t\turlObj.hash === ''\n\t\t\t) {\n\t\t\t\treturn url.replace('?embed', '')\n\t\t\t}\n\t\t\treturn\n\t\t},\n\t},\n]\n\n/**\n * Properties for the embed shape, which displays embedded content from external services.\n *\n * @public\n */\nexport interface TLEmbedShapeProps {\n\t/** Width of the embed shape in pixels */\n\tw: number\n\t/** Height of the embed shape in pixels */\n\th: number\n\t/** URL of the content to embed (supports YouTube, Figma, CodePen, etc.) */\n\turl: string\n}\n\n/**\n * An embed shape displays external content like YouTube videos, Figma designs, CodePen demos,\n * and other embeddable content within the tldraw canvas.\n *\n * @public\n * @example\n * ```ts\n * const embedShape: TLEmbedShape = {\n * id: createShapeId(),\n * typeName: 'shape',\n * type: 'embed',\n * x: 200,\n * y: 200,\n * rotation: 0,\n * index: 'a1',\n * parentId: 'page:page1',\n * isLocked: false,\n * opacity: 1,\n * props: {\n * w: 560,\n * h: 315,\n * url: 'https://www.youtube.com/watch?v=dQw4w9WgXcQ'\n * },\n * meta: {}\n * }\n * ```\n */\nexport type TLEmbedShape = TLBaseShape<'embed', TLEmbedShapeProps>\n\n/**\n * Validation schema for embed shape properties.\n *\n * @public\n * @example\n * ```ts\n * // Validate embed shape properties\n * const isValidUrl = embedShapeProps.url.isValid('https://youtube.com/watch?v=abc123')\n * const isValidSize = embedShapeProps.w.isValid(560)\n * ```\n */\nexport const embedShapeProps: RecordProps<TLEmbedShape> = {\n\tw: T.nonZeroNumber,\n\th: T.nonZeroNumber,\n\turl: T.string,\n}\n\nconst Versions = createShapePropsMigrationIds('embed', {\n\tGenOriginalUrlInEmbed: 1,\n\tRemoveDoesResize: 2,\n\tRemoveTmpOldUrl: 3,\n\tRemovePermissionOverrides: 4,\n})\n\n/**\n * Version identifiers for embed shape migrations.\n *\n * @public\n */\nexport { Versions as embedShapeVersions }\n\n/**\n * Migration sequence for embed shape properties across different schema versions.\n * Handles URL transformations and removal of deprecated properties.\n *\n * @public\n */\nexport const embedShapeMigrations = createShapePropsMigrationSequence({\n\tsequence: [\n\t\t{\n\t\t\tid: Versions.GenOriginalUrlInEmbed,\n\t\t\t// add tmpOldUrl property\n\t\t\tup: (props) => {\n\t\t\t\ttry {\n\t\t\t\t\tconst url = props.url\n\t\t\t\t\tconst host = new URL(url).host.replace('www.', '')\n\t\t\t\t\tlet originalUrl\n\t\t\t\t\tfor (const localEmbedDef of EMBED_DEFINITIONS) {\n\t\t\t\t\t\tif (localEmbedDef.hostnames.includes(host)) {\n\t\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\t\toriginalUrl = localEmbedDef.fromEmbedUrl(url)\n\t\t\t\t\t\t\t} catch (err) {\n\t\t\t\t\t\t\t\tconsole.warn(err)\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\tprops.tmpOldUrl = props.url\n\t\t\t\t\tprops.url = originalUrl ?? ''\n\t\t\t\t} catch {\n\t\t\t\t\tprops.url = ''\n\t\t\t\t\tprops.tmpOldUrl = props.url\n\t\t\t\t}\n\t\t\t},\n\t\t\tdown: 'retired',\n\t\t},\n\t\t{\n\t\t\tid: Versions.RemoveDoesResize,\n\t\t\tup: (props) => {\n\t\t\t\tdelete props.doesResize\n\t\t\t},\n\t\t\tdown: 'retired',\n\t\t},\n\t\t{\n\t\t\tid: Versions.RemoveTmpOldUrl,\n\t\t\tup: (props) => {\n\t\t\t\tdelete props.tmpOldUrl\n\t\t\t},\n\t\t\tdown: 'retired',\n\t\t},\n\t\t{\n\t\t\tid: Versions.RemovePermissionOverrides,\n\t\t\tup: (props) => {\n\t\t\t\tdelete props.overridePermissions\n\t\t\t},\n\t\t\tdown: 'retired',\n\t\t},\n\t],\n})\n"],
5
+ "mappings": "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",
6
6
  "names": []
7
7
  }
@@ -69,8 +69,7 @@ const geoShapeVersions = createShapePropsMigrationIds("geo", {
69
69
  AddCloud: 7,
70
70
  MakeUrlsValid: 8,
71
71
  AddScale: 9,
72
- AddRichText: 10,
73
- AddRichTextAttrs: 11
72
+ AddRichText: 10
74
73
  });
75
74
  const geoShapeMigrations = createShapePropsMigrationSequence({
76
75
  sequence: [
@@ -164,16 +163,6 @@ const geoShapeMigrations = createShapePropsMigrationSequence({
164
163
  // down: (props) => {
165
164
  // delete props.richText
166
165
  // },
167
- },
168
- {
169
- id: geoShapeVersions.AddRichTextAttrs,
170
- up: (_props) => {
171
- },
172
- down: (props) => {
173
- if (props.richText && "attrs" in props.richText) {
174
- delete props.richText.attrs;
175
- }
176
- }
177
166
  }
178
167
  ]
179
168
  });
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../src/shapes/TLGeoShape.ts"],
4
- "sourcesContent": ["import { T } from '@tldraw/validate'\nimport { TLRichText, richTextValidator, toRichText } from '../misc/TLRichText'\nimport { createShapePropsMigrationIds, createShapePropsMigrationSequence } from '../records/TLShape'\nimport { RecordProps } from '../recordsWithProps'\nimport { StyleProp } from '../styles/StyleProp'\nimport {\n\tDefaultColorStyle,\n\tDefaultLabelColorStyle,\n\tTLDefaultColorStyle,\n} from '../styles/TLColorStyle'\nimport { DefaultDashStyle, TLDefaultDashStyle } from '../styles/TLDashStyle'\nimport { DefaultFillStyle, TLDefaultFillStyle } from '../styles/TLFillStyle'\nimport { DefaultFontStyle, TLDefaultFontStyle } from '../styles/TLFontStyle'\nimport {\n\tDefaultHorizontalAlignStyle,\n\tTLDefaultHorizontalAlignStyle,\n} from '../styles/TLHorizontalAlignStyle'\nimport { DefaultSizeStyle, TLDefaultSizeStyle } from '../styles/TLSizeStyle'\nimport {\n\tDefaultVerticalAlignStyle,\n\tTLDefaultVerticalAlignStyle,\n} from '../styles/TLVerticalAlignStyle'\nimport { TLBaseShape } from './TLBaseShape'\n\n/**\n * Style property defining the geometric shape type for geo shapes.\n * Provides a variety of built-in geometric forms including basic shapes,\n * polygons, arrows, and special shapes.\n *\n * @public\n * @example\n * ```ts\n * // Use in shape props\n * const props = {\n * geo: 'rectangle', // or 'ellipse', 'triangle', etc.\n * // other properties...\n * }\n * ```\n */\nexport const GeoShapeGeoStyle = StyleProp.defineEnum('tldraw:geo', {\n\tdefaultValue: 'rectangle',\n\tvalues: [\n\t\t'cloud',\n\t\t'rectangle',\n\t\t'ellipse',\n\t\t'triangle',\n\t\t'diamond',\n\t\t'pentagon',\n\t\t'hexagon',\n\t\t'octagon',\n\t\t'star',\n\t\t'rhombus',\n\t\t'rhombus-2',\n\t\t'oval',\n\t\t'trapezoid',\n\t\t'arrow-right',\n\t\t'arrow-left',\n\t\t'arrow-up',\n\t\t'arrow-down',\n\t\t'x-box',\n\t\t'check-box',\n\t\t'heart',\n\t],\n})\n\n/**\n * Type representing valid geometric shape styles for geo shapes.\n *\n * @public\n */\nexport type TLGeoShapeGeoStyle = T.TypeOf<typeof GeoShapeGeoStyle>\n\n/**\n * Properties for the geo shape, which renders various geometric forms with styling and text.\n *\n * @public\n */\nexport interface TLGeoShapeProps {\n\t/** Geometric shape type (rectangle, ellipse, triangle, etc.) */\n\tgeo: TLGeoShapeGeoStyle\n\t/** Dash pattern style for the shape outline */\n\tdash: TLDefaultDashStyle\n\t/** URL link associated with the shape */\n\turl: string\n\t/** Width of the shape in pixels */\n\tw: number\n\t/** Height of the shape in pixels */\n\th: number\n\t/** Additional vertical growth for text content */\n\tgrowY: number\n\t/** Scale factor applied to the shape */\n\tscale: number\n\n\t/** Color style for text label */\n\tlabelColor: TLDefaultColorStyle\n\t/** Color style for the shape outline */\n\tcolor: TLDefaultColorStyle\n\t/** Fill style for the shape interior */\n\tfill: TLDefaultFillStyle\n\t/** Size/thickness style for outline and text */\n\tsize: TLDefaultSizeStyle\n\t/** Font style for text content */\n\tfont: TLDefaultFontStyle\n\t/** Horizontal alignment for text content */\n\talign: TLDefaultHorizontalAlignStyle\n\t/** Vertical alignment for text content */\n\tverticalAlign: TLDefaultVerticalAlignStyle\n\t/** Rich text content displayed within the shape */\n\trichText: TLRichText\n}\n\n/**\n * A geo shape represents geometric forms like rectangles, ellipses, triangles, and other\n * predefined shapes. Geo shapes support styling, text content, and can act as containers.\n *\n * @public\n * @example\n * ```ts\n * const geoShape: TLGeoShape = {\n * id: createShapeId(),\n * typeName: 'shape',\n * type: 'geo',\n * x: 100,\n * y: 100,\n * rotation: 0,\n * index: 'a1',\n * parentId: 'page:page1',\n * isLocked: false,\n * opacity: 1,\n * props: {\n * geo: 'rectangle',\n * w: 200,\n * h: 100,\n * color: 'black',\n * fill: 'solid',\n * dash: 'solid',\n * size: 'm',\n * font: 'draw',\n * align: 'middle',\n * verticalAlign: 'middle',\n * richText: toRichText('Hello World'),\n * labelColor: 'black',\n * url: '',\n * growY: 0,\n * scale: 1\n * },\n * meta: {}\n * }\n * ```\n */\nexport type TLGeoShape = TLBaseShape<'geo', TLGeoShapeProps>\n\n/**\n * Validation schema for geo shape properties.\n *\n * @public\n * @example\n * ```ts\n * // Validate geo shape properties\n * const isValidGeo = geoShapeProps.geo.isValid('rectangle')\n * const isValidSize = geoShapeProps.w.isValid(100)\n * const isValidText = geoShapeProps.richText.isValid(toRichText('Hello'))\n * ```\n */\nexport const geoShapeProps: RecordProps<TLGeoShape> = {\n\tgeo: GeoShapeGeoStyle,\n\tdash: DefaultDashStyle,\n\turl: T.linkUrl,\n\tw: T.nonZeroNumber,\n\th: T.nonZeroNumber,\n\tgrowY: T.positiveNumber,\n\tscale: T.nonZeroNumber,\n\n\t// Text properties\n\tlabelColor: DefaultLabelColorStyle,\n\tcolor: DefaultColorStyle,\n\tfill: DefaultFillStyle,\n\tsize: DefaultSizeStyle,\n\tfont: DefaultFontStyle,\n\talign: DefaultHorizontalAlignStyle,\n\tverticalAlign: DefaultVerticalAlignStyle,\n\trichText: richTextValidator,\n}\n\nconst geoShapeVersions = createShapePropsMigrationIds('geo', {\n\tAddUrlProp: 1,\n\tAddLabelColor: 2,\n\tRemoveJustify: 3,\n\tAddCheckBox: 4,\n\tAddVerticalAlign: 5,\n\tMigrateLegacyAlign: 6,\n\tAddCloud: 7,\n\tMakeUrlsValid: 8,\n\tAddScale: 9,\n\tAddRichText: 10,\n\tAddRichTextAttrs: 11,\n})\n\n/**\n * Version identifiers for geo shape migrations.\n *\n * @public\n */\nexport { geoShapeVersions as geoShapeVersions }\n\n/**\n * Migration sequence for geo shape properties across different schema versions.\n * Handles evolution of geo shapes including URL support, label colors, alignment changes,\n * the transition from plain text to rich text, and support for attrs property on richText.\n *\n * @public\n */\nexport const geoShapeMigrations = createShapePropsMigrationSequence({\n\tsequence: [\n\t\t{\n\t\t\tid: geoShapeVersions.AddUrlProp,\n\t\t\tup: (props) => {\n\t\t\t\tprops.url = ''\n\t\t\t},\n\t\t\tdown: 'retired',\n\t\t},\n\t\t{\n\t\t\tid: geoShapeVersions.AddLabelColor,\n\t\t\tup: (props) => {\n\t\t\t\tprops.labelColor = 'black'\n\t\t\t},\n\t\t\tdown: 'retired',\n\t\t},\n\t\t{\n\t\t\tid: geoShapeVersions.RemoveJustify,\n\t\t\tup: (props) => {\n\t\t\t\tif (props.align === 'justify') {\n\t\t\t\t\tprops.align = 'start'\n\t\t\t\t}\n\t\t\t},\n\t\t\tdown: 'retired',\n\t\t},\n\t\t{\n\t\t\tid: geoShapeVersions.AddCheckBox,\n\t\t\tup: (_props) => {\n\t\t\t\t// noop\n\t\t\t},\n\t\t\tdown: 'retired',\n\t\t},\n\t\t{\n\t\t\tid: geoShapeVersions.AddVerticalAlign,\n\t\t\tup: (props) => {\n\t\t\t\tprops.verticalAlign = 'middle'\n\t\t\t},\n\t\t\tdown: 'retired',\n\t\t},\n\t\t{\n\t\t\tid: geoShapeVersions.MigrateLegacyAlign,\n\t\t\tup: (props) => {\n\t\t\t\tlet newAlign: TLDefaultHorizontalAlignStyle\n\t\t\t\tswitch (props.align) {\n\t\t\t\t\tcase 'start':\n\t\t\t\t\t\tnewAlign = 'start-legacy'\n\t\t\t\t\t\tbreak\n\t\t\t\t\tcase 'end':\n\t\t\t\t\t\tnewAlign = 'end-legacy'\n\t\t\t\t\t\tbreak\n\t\t\t\t\tdefault:\n\t\t\t\t\t\tnewAlign = 'middle-legacy'\n\t\t\t\t\t\tbreak\n\t\t\t\t}\n\t\t\t\tprops.align = newAlign\n\t\t\t},\n\t\t\tdown: 'retired',\n\t\t},\n\t\t{\n\t\t\tid: geoShapeVersions.AddCloud,\n\t\t\tup: (_props) => {\n\t\t\t\t// noop\n\t\t\t},\n\t\t\tdown: 'retired',\n\t\t},\n\t\t{\n\t\t\tid: geoShapeVersions.MakeUrlsValid,\n\t\t\tup: (props) => {\n\t\t\t\tif (!T.linkUrl.isValid(props.url)) {\n\t\t\t\t\tprops.url = ''\n\t\t\t\t}\n\t\t\t},\n\t\t\tdown: (_props) => {\n\t\t\t\t// noop\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tid: geoShapeVersions.AddScale,\n\t\t\tup: (props) => {\n\t\t\t\tprops.scale = 1\n\t\t\t},\n\t\t\tdown: (props) => {\n\t\t\t\tdelete props.scale\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tid: geoShapeVersions.AddRichText,\n\t\t\tup: (props) => {\n\t\t\t\tprops.richText = toRichText(props.text)\n\t\t\t\tdelete props.text\n\t\t\t},\n\t\t\t// N.B. Explicitly no down state so that we force clients to update.\n\t\t\t// down: (props) => {\n\t\t\t// \tdelete props.richText\n\t\t\t// },\n\t\t},\n\t\t{\n\t\t\tid: geoShapeVersions.AddRichTextAttrs,\n\t\t\tup: (_props) => {\n\t\t\t\t// noop - attrs is optional so old records are valid\n\t\t\t},\n\t\t\tdown: (props) => {\n\t\t\t\t// Remove attrs from richText when migrating down\n\t\t\t\tif (props.richText && 'attrs' in props.richText) {\n\t\t\t\t\tdelete props.richText.attrs\n\t\t\t\t}\n\t\t\t},\n\t\t},\n\t],\n})\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["import { T } from '@tldraw/validate'\nimport { TLRichText, richTextValidator, toRichText } from '../misc/TLRichText'\nimport { createShapePropsMigrationIds, createShapePropsMigrationSequence } from '../records/TLShape'\nimport { RecordProps } from '../recordsWithProps'\nimport { StyleProp } from '../styles/StyleProp'\nimport {\n\tDefaultColorStyle,\n\tDefaultLabelColorStyle,\n\tTLDefaultColorStyle,\n} from '../styles/TLColorStyle'\nimport { DefaultDashStyle, TLDefaultDashStyle } from '../styles/TLDashStyle'\nimport { DefaultFillStyle, TLDefaultFillStyle } from '../styles/TLFillStyle'\nimport { DefaultFontStyle, TLDefaultFontStyle } from '../styles/TLFontStyle'\nimport {\n\tDefaultHorizontalAlignStyle,\n\tTLDefaultHorizontalAlignStyle,\n} from '../styles/TLHorizontalAlignStyle'\nimport { DefaultSizeStyle, TLDefaultSizeStyle } from '../styles/TLSizeStyle'\nimport {\n\tDefaultVerticalAlignStyle,\n\tTLDefaultVerticalAlignStyle,\n} from '../styles/TLVerticalAlignStyle'\nimport { TLBaseShape } from './TLBaseShape'\n\n/**\n * Style property defining the geometric shape type for geo shapes.\n * Provides a variety of built-in geometric forms including basic shapes,\n * polygons, arrows, and special shapes.\n *\n * @public\n * @example\n * ```ts\n * // Use in shape props\n * const props = {\n * geo: 'rectangle', // or 'ellipse', 'triangle', etc.\n * // other properties...\n * }\n * ```\n */\nexport const GeoShapeGeoStyle = StyleProp.defineEnum('tldraw:geo', {\n\tdefaultValue: 'rectangle',\n\tvalues: [\n\t\t'cloud',\n\t\t'rectangle',\n\t\t'ellipse',\n\t\t'triangle',\n\t\t'diamond',\n\t\t'pentagon',\n\t\t'hexagon',\n\t\t'octagon',\n\t\t'star',\n\t\t'rhombus',\n\t\t'rhombus-2',\n\t\t'oval',\n\t\t'trapezoid',\n\t\t'arrow-right',\n\t\t'arrow-left',\n\t\t'arrow-up',\n\t\t'arrow-down',\n\t\t'x-box',\n\t\t'check-box',\n\t\t'heart',\n\t],\n})\n\n/**\n * Type representing valid geometric shape styles for geo shapes.\n *\n * @public\n */\nexport type TLGeoShapeGeoStyle = T.TypeOf<typeof GeoShapeGeoStyle>\n\n/**\n * Properties for the geo shape, which renders various geometric forms with styling and text.\n *\n * @public\n */\nexport interface TLGeoShapeProps {\n\t/** Geometric shape type (rectangle, ellipse, triangle, etc.) */\n\tgeo: TLGeoShapeGeoStyle\n\t/** Dash pattern style for the shape outline */\n\tdash: TLDefaultDashStyle\n\t/** URL link associated with the shape */\n\turl: string\n\t/** Width of the shape in pixels */\n\tw: number\n\t/** Height of the shape in pixels */\n\th: number\n\t/** Additional vertical growth for text content */\n\tgrowY: number\n\t/** Scale factor applied to the shape */\n\tscale: number\n\n\t/** Color style for text label */\n\tlabelColor: TLDefaultColorStyle\n\t/** Color style for the shape outline */\n\tcolor: TLDefaultColorStyle\n\t/** Fill style for the shape interior */\n\tfill: TLDefaultFillStyle\n\t/** Size/thickness style for outline and text */\n\tsize: TLDefaultSizeStyle\n\t/** Font style for text content */\n\tfont: TLDefaultFontStyle\n\t/** Horizontal alignment for text content */\n\talign: TLDefaultHorizontalAlignStyle\n\t/** Vertical alignment for text content */\n\tverticalAlign: TLDefaultVerticalAlignStyle\n\t/** Rich text content displayed within the shape */\n\trichText: TLRichText\n}\n\n/**\n * A geo shape represents geometric forms like rectangles, ellipses, triangles, and other\n * predefined shapes. Geo shapes support styling, text content, and can act as containers.\n *\n * @public\n * @example\n * ```ts\n * const geoShape: TLGeoShape = {\n * id: createShapeId(),\n * typeName: 'shape',\n * type: 'geo',\n * x: 100,\n * y: 100,\n * rotation: 0,\n * index: 'a1',\n * parentId: 'page:page1',\n * isLocked: false,\n * opacity: 1,\n * props: {\n * geo: 'rectangle',\n * w: 200,\n * h: 100,\n * color: 'black',\n * fill: 'solid',\n * dash: 'solid',\n * size: 'm',\n * font: 'draw',\n * align: 'middle',\n * verticalAlign: 'middle',\n * richText: toRichText('Hello World'),\n * labelColor: 'black',\n * url: '',\n * growY: 0,\n * scale: 1\n * },\n * meta: {}\n * }\n * ```\n */\nexport type TLGeoShape = TLBaseShape<'geo', TLGeoShapeProps>\n\n/**\n * Validation schema for geo shape properties.\n *\n * @public\n * @example\n * ```ts\n * // Validate geo shape properties\n * const isValidGeo = geoShapeProps.geo.isValid('rectangle')\n * const isValidSize = geoShapeProps.w.isValid(100)\n * const isValidText = geoShapeProps.richText.isValid(toRichText('Hello'))\n * ```\n */\nexport const geoShapeProps: RecordProps<TLGeoShape> = {\n\tgeo: GeoShapeGeoStyle,\n\tdash: DefaultDashStyle,\n\turl: T.linkUrl,\n\tw: T.nonZeroNumber,\n\th: T.nonZeroNumber,\n\tgrowY: T.positiveNumber,\n\tscale: T.nonZeroNumber,\n\n\t// Text properties\n\tlabelColor: DefaultLabelColorStyle,\n\tcolor: DefaultColorStyle,\n\tfill: DefaultFillStyle,\n\tsize: DefaultSizeStyle,\n\tfont: DefaultFontStyle,\n\talign: DefaultHorizontalAlignStyle,\n\tverticalAlign: DefaultVerticalAlignStyle,\n\trichText: richTextValidator,\n}\n\nconst geoShapeVersions = createShapePropsMigrationIds('geo', {\n\tAddUrlProp: 1,\n\tAddLabelColor: 2,\n\tRemoveJustify: 3,\n\tAddCheckBox: 4,\n\tAddVerticalAlign: 5,\n\tMigrateLegacyAlign: 6,\n\tAddCloud: 7,\n\tMakeUrlsValid: 8,\n\tAddScale: 9,\n\tAddRichText: 10,\n})\n\n/**\n * Version identifiers for geo shape migrations.\n *\n * @public\n */\nexport { geoShapeVersions as geoShapeVersions }\n\n/**\n * Migration sequence for geo shape properties across different schema versions.\n * Handles evolution of geo shapes including URL support, label colors, alignment changes,\n * and the transition from plain text to rich text.\n *\n * @public\n */\nexport const geoShapeMigrations = createShapePropsMigrationSequence({\n\tsequence: [\n\t\t{\n\t\t\tid: geoShapeVersions.AddUrlProp,\n\t\t\tup: (props) => {\n\t\t\t\tprops.url = ''\n\t\t\t},\n\t\t\tdown: 'retired',\n\t\t},\n\t\t{\n\t\t\tid: geoShapeVersions.AddLabelColor,\n\t\t\tup: (props) => {\n\t\t\t\tprops.labelColor = 'black'\n\t\t\t},\n\t\t\tdown: 'retired',\n\t\t},\n\t\t{\n\t\t\tid: geoShapeVersions.RemoveJustify,\n\t\t\tup: (props) => {\n\t\t\t\tif (props.align === 'justify') {\n\t\t\t\t\tprops.align = 'start'\n\t\t\t\t}\n\t\t\t},\n\t\t\tdown: 'retired',\n\t\t},\n\t\t{\n\t\t\tid: geoShapeVersions.AddCheckBox,\n\t\t\tup: (_props) => {\n\t\t\t\t// noop\n\t\t\t},\n\t\t\tdown: 'retired',\n\t\t},\n\t\t{\n\t\t\tid: geoShapeVersions.AddVerticalAlign,\n\t\t\tup: (props) => {\n\t\t\t\tprops.verticalAlign = 'middle'\n\t\t\t},\n\t\t\tdown: 'retired',\n\t\t},\n\t\t{\n\t\t\tid: geoShapeVersions.MigrateLegacyAlign,\n\t\t\tup: (props) => {\n\t\t\t\tlet newAlign: TLDefaultHorizontalAlignStyle\n\t\t\t\tswitch (props.align) {\n\t\t\t\t\tcase 'start':\n\t\t\t\t\t\tnewAlign = 'start-legacy'\n\t\t\t\t\t\tbreak\n\t\t\t\t\tcase 'end':\n\t\t\t\t\t\tnewAlign = 'end-legacy'\n\t\t\t\t\t\tbreak\n\t\t\t\t\tdefault:\n\t\t\t\t\t\tnewAlign = 'middle-legacy'\n\t\t\t\t\t\tbreak\n\t\t\t\t}\n\t\t\t\tprops.align = newAlign\n\t\t\t},\n\t\t\tdown: 'retired',\n\t\t},\n\t\t{\n\t\t\tid: geoShapeVersions.AddCloud,\n\t\t\tup: (_props) => {\n\t\t\t\t// noop\n\t\t\t},\n\t\t\tdown: 'retired',\n\t\t},\n\t\t{\n\t\t\tid: geoShapeVersions.MakeUrlsValid,\n\t\t\tup: (props) => {\n\t\t\t\tif (!T.linkUrl.isValid(props.url)) {\n\t\t\t\t\tprops.url = ''\n\t\t\t\t}\n\t\t\t},\n\t\t\tdown: (_props) => {\n\t\t\t\t// noop\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tid: geoShapeVersions.AddScale,\n\t\t\tup: (props) => {\n\t\t\t\tprops.scale = 1\n\t\t\t},\n\t\t\tdown: (props) => {\n\t\t\t\tdelete props.scale\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tid: geoShapeVersions.AddRichText,\n\t\t\tup: (props) => {\n\t\t\t\tprops.richText = toRichText(props.text)\n\t\t\t\tdelete props.text\n\t\t\t},\n\t\t\t// N.B. Explicitly no down state so that we force clients to update.\n\t\t\t// down: (props) => {\n\t\t\t// \tdelete props.richText\n\t\t\t// },\n\t\t},\n\t],\n})\n"],
5
+ "mappings": "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",
6
6
  "names": []
7
7
  }
@@ -1,5 +1,4 @@
1
1
  import { T } from "@tldraw/validate";
2
- import { b64Vecs } from "../misc/b64Vecs.mjs";
3
2
  import { createShapePropsMigrationIds, createShapePropsMigrationSequence } from "../records/TLShape.mjs";
4
3
  import { DefaultColorStyle } from "../styles/TLColorStyle.mjs";
5
4
  import { DefaultSizeStyle } from "../styles/TLSizeStyle.mjs";
@@ -10,13 +9,10 @@ const highlightShapeProps = {
10
9
  segments: T.arrayOf(DrawShapeSegment),
11
10
  isComplete: T.boolean,
12
11
  isPen: T.boolean,
13
- scale: T.nonZeroNumber,
14
- scaleX: T.nonZeroFiniteNumber,
15
- scaleY: T.nonZeroFiniteNumber
12
+ scale: T.nonZeroNumber
16
13
  };
17
14
  const Versions = createShapePropsMigrationIds("highlight", {
18
- AddScale: 1,
19
- Base64: 2
15
+ AddScale: 1
20
16
  });
21
17
  const highlightShapeMigrations = createShapePropsMigrationSequence({
22
18
  sequence: [
@@ -28,29 +24,6 @@ const highlightShapeMigrations = createShapePropsMigrationSequence({
28
24
  down: (props) => {
29
25
  delete props.scale;
30
26
  }
31
- },
32
- {
33
- id: Versions.Base64,
34
- up: (props) => {
35
- props.segments = props.segments.map((segment) => {
36
- return {
37
- ...segment,
38
- // Only encode if points is an array (not already base64 string)
39
- points: typeof segment.points === "string" ? segment.points : b64Vecs.encodePoints(segment.points)
40
- };
41
- });
42
- props.scaleX = props.scaleX ?? 1;
43
- props.scaleY = props.scaleY ?? 1;
44
- },
45
- down: (props) => {
46
- props.segments = props.segments.map((segment) => ({
47
- ...segment,
48
- // Only decode if points is a string (not already VecModel[])
49
- points: Array.isArray(segment.points) ? segment.points : b64Vecs.decodePoints(segment.points)
50
- }));
51
- delete props.scaleX;
52
- delete props.scaleY;
53
- }
54
27
  }
55
28
  ]
56
29
  });
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../src/shapes/TLHighlightShape.ts"],
4
- "sourcesContent": ["import { T } from '@tldraw/validate'\nimport { b64Vecs } from '../misc/b64Vecs'\nimport { createShapePropsMigrationIds, createShapePropsMigrationSequence } from '../records/TLShape'\nimport { RecordProps } from '../recordsWithProps'\nimport { DefaultColorStyle, TLDefaultColorStyle } from '../styles/TLColorStyle'\nimport { DefaultSizeStyle, TLDefaultSizeStyle } from '../styles/TLSizeStyle'\nimport { TLBaseShape } from './TLBaseShape'\nimport { DrawShapeSegment, TLDrawShapeSegment } from './TLDrawShape'\n\n/**\n * Properties for a highlight shape. Highlight shapes represent highlighting strokes made with\n * a highlighting tool, typically used to emphasize or mark up content.\n *\n * @public\n * @example\n * ```ts\n * const highlightProps: TLHighlightShapeProps = {\n * color: 'yellow',\n * size: 'm',\n * segments: [{ type: 'straight', points: [{ x: 0, y: 0, z: 0.5 }] }],\n * isComplete: true,\n * isPen: false,\n * scale: 1\n * }\n * ```\n */\nexport interface TLHighlightShapeProps {\n\t/** The color style of the highlight stroke */\n\tcolor: TLDefaultColorStyle\n\t/** The size style determining the thickness of the highlight stroke */\n\tsize: TLDefaultSizeStyle\n\t/** Array of segments that make up the highlight stroke path */\n\tsegments: TLDrawShapeSegment[]\n\t/** Whether the highlight stroke has been completed by the user */\n\tisComplete: boolean\n\t/** Whether the highlight was drawn with a pen/stylus (affects rendering style) */\n\tisPen: boolean\n\t/** Scale factor applied to the highlight shape for display */\n\tscale: number\n\t/** Horizontal scale factor for lazy resize */\n\tscaleX: number\n\t/** Vertical scale factor for lazy resize */\n\tscaleY: number\n}\n\n/**\n * A highlight shape representing a highlighting stroke drawn by the user. Highlight shapes\n * are typically semi-transparent and used for marking up or emphasizing content on the canvas.\n *\n * @public\n * @example\n * ```ts\n * const highlightShape: TLHighlightShape = {\n * id: 'shape:highlight1',\n * type: 'highlight',\n * x: 100,\n * y: 50,\n * rotation: 0,\n * index: 'a1',\n * parentId: 'page:main',\n * isLocked: false,\n * opacity: 0.7,\n * props: {\n * color: 'yellow',\n * size: 'l',\n * segments: [],\n * isComplete: false,\n * isPen: false,\n * scale: 1\n * },\n * meta: {},\n * typeName: 'shape'\n * }\n * ```\n */\nexport type TLHighlightShape = TLBaseShape<'highlight', TLHighlightShapeProps>\n\n/**\n * Validation schema for highlight shape properties. Defines the runtime validation rules\n * for all properties of highlight shapes.\n *\n * @public\n * @example\n * ```ts\n * import { highlightShapeProps } from '@tldraw/tlschema'\n *\n * // Used internally by the validation system\n * const validator = T.object(highlightShapeProps)\n * const validatedProps = validator.validate(someHighlightProps)\n * ```\n */\n/** @public */\nexport const highlightShapeProps: RecordProps<TLHighlightShape> = {\n\tcolor: DefaultColorStyle,\n\tsize: DefaultSizeStyle,\n\tsegments: T.arrayOf(DrawShapeSegment),\n\tisComplete: T.boolean,\n\tisPen: T.boolean,\n\tscale: T.nonZeroNumber,\n\tscaleX: T.nonZeroFiniteNumber,\n\tscaleY: T.nonZeroFiniteNumber,\n}\n\nconst Versions = createShapePropsMigrationIds('highlight', {\n\tAddScale: 1,\n\tBase64: 2,\n})\n\n/**\n * Version identifiers for highlight shape migrations. These version numbers track\n * schema changes over time to enable proper data migration.\n *\n * @public\n */\nexport { Versions as highlightShapeVersions }\n\n/**\n * Migration sequence for highlight shapes. Handles schema evolution over time by defining\n * how to upgrade and downgrade highlight shape data between different versions.\n *\n * @public\n */\nexport const highlightShapeMigrations = createShapePropsMigrationSequence({\n\tsequence: [\n\t\t{\n\t\t\tid: Versions.AddScale,\n\t\t\tup: (props) => {\n\t\t\t\tprops.scale = 1\n\t\t\t},\n\t\t\tdown: (props) => {\n\t\t\t\tdelete props.scale\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tid: Versions.Base64,\n\t\t\tup: (props) => {\n\t\t\t\tprops.segments = props.segments.map((segment: any) => {\n\t\t\t\t\treturn {\n\t\t\t\t\t\t...segment,\n\t\t\t\t\t\t// Only encode if points is an array (not already base64 string)\n\t\t\t\t\t\tpoints:\n\t\t\t\t\t\t\ttypeof segment.points === 'string'\n\t\t\t\t\t\t\t\t? segment.points\n\t\t\t\t\t\t\t\t: b64Vecs.encodePoints(segment.points),\n\t\t\t\t\t}\n\t\t\t\t})\n\t\t\t\tprops.scaleX = props.scaleX ?? 1\n\t\t\t\tprops.scaleY = props.scaleY ?? 1\n\t\t\t},\n\t\t\tdown: (props) => {\n\t\t\t\tprops.segments = props.segments.map((segment: any) => ({\n\t\t\t\t\t...segment,\n\t\t\t\t\t// Only decode if points is a string (not already VecModel[])\n\t\t\t\t\tpoints: Array.isArray(segment.points)\n\t\t\t\t\t\t? segment.points\n\t\t\t\t\t\t: b64Vecs.decodePoints(segment.points),\n\t\t\t\t}))\n\t\t\t\tdelete props.scaleX\n\t\t\t\tdelete props.scaleY\n\t\t\t},\n\t\t},\n\t],\n})\n"],
5
- "mappings": "AAAA,SAAS,SAAS;AAClB,SAAS,eAAe;AACxB,SAAS,8BAA8B,yCAAyC;AAEhF,SAAS,yBAA8C;AACvD,SAAS,wBAA4C;AAErD,SAAS,wBAA4C;AAqF9C,MAAM,sBAAqD;AAAA,EACjE,OAAO;AAAA,EACP,MAAM;AAAA,EACN,UAAU,EAAE,QAAQ,gBAAgB;AAAA,EACpC,YAAY,EAAE;AAAA,EACd,OAAO,EAAE;AAAA,EACT,OAAO,EAAE;AAAA,EACT,QAAQ,EAAE;AAAA,EACV,QAAQ,EAAE;AACX;AAEA,MAAM,WAAW,6BAA6B,aAAa;AAAA,EAC1D,UAAU;AAAA,EACV,QAAQ;AACT,CAAC;AAgBM,MAAM,2BAA2B,kCAAkC;AAAA,EACzE,UAAU;AAAA,IACT;AAAA,MACC,IAAI,SAAS;AAAA,MACb,IAAI,CAAC,UAAU;AACd,cAAM,QAAQ;AAAA,MACf;AAAA,MACA,MAAM,CAAC,UAAU;AAChB,eAAO,MAAM;AAAA,MACd;AAAA,IACD;AAAA,IACA;AAAA,MACC,IAAI,SAAS;AAAA,MACb,IAAI,CAAC,UAAU;AACd,cAAM,WAAW,MAAM,SAAS,IAAI,CAAC,YAAiB;AACrD,iBAAO;AAAA,YACN,GAAG;AAAA;AAAA,YAEH,QACC,OAAO,QAAQ,WAAW,WACvB,QAAQ,SACR,QAAQ,aAAa,QAAQ,MAAM;AAAA,UACxC;AAAA,QACD,CAAC;AACD,cAAM,SAAS,MAAM,UAAU;AAC/B,cAAM,SAAS,MAAM,UAAU;AAAA,MAChC;AAAA,MACA,MAAM,CAAC,UAAU;AAChB,cAAM,WAAW,MAAM,SAAS,IAAI,CAAC,aAAkB;AAAA,UACtD,GAAG;AAAA;AAAA,UAEH,QAAQ,MAAM,QAAQ,QAAQ,MAAM,IACjC,QAAQ,SACR,QAAQ,aAAa,QAAQ,MAAM;AAAA,QACvC,EAAE;AACF,eAAO,MAAM;AACb,eAAO,MAAM;AAAA,MACd;AAAA,IACD;AAAA,EACD;AACD,CAAC;",
4
+ "sourcesContent": ["import { T } from '@tldraw/validate'\nimport { createShapePropsMigrationIds, createShapePropsMigrationSequence } from '../records/TLShape'\nimport { RecordProps } from '../recordsWithProps'\nimport { DefaultColorStyle, TLDefaultColorStyle } from '../styles/TLColorStyle'\nimport { DefaultSizeStyle, TLDefaultSizeStyle } from '../styles/TLSizeStyle'\nimport { TLBaseShape } from './TLBaseShape'\nimport { DrawShapeSegment, TLDrawShapeSegment } from './TLDrawShape'\n\n/**\n * Properties for a highlight shape. Highlight shapes represent highlighting strokes made with\n * a highlighting tool, typically used to emphasize or mark up content.\n *\n * @public\n * @example\n * ```ts\n * const highlightProps: TLHighlightShapeProps = {\n * color: 'yellow',\n * size: 'm',\n * segments: [{ type: 'straight', points: [{ x: 0, y: 0, z: 0.5 }] }],\n * isComplete: true,\n * isPen: false,\n * scale: 1\n * }\n * ```\n */\nexport interface TLHighlightShapeProps {\n\t/** The color style of the highlight stroke */\n\tcolor: TLDefaultColorStyle\n\t/** The size style determining the thickness of the highlight stroke */\n\tsize: TLDefaultSizeStyle\n\t/** Array of segments that make up the highlight stroke path */\n\tsegments: TLDrawShapeSegment[]\n\t/** Whether the highlight stroke has been completed by the user */\n\tisComplete: boolean\n\t/** Whether the highlight was drawn with a pen/stylus (affects rendering style) */\n\tisPen: boolean\n\t/** Scale factor applied to the highlight shape for display */\n\tscale: number\n}\n\n/**\n * A highlight shape representing a highlighting stroke drawn by the user. Highlight shapes\n * are typically semi-transparent and used for marking up or emphasizing content on the canvas.\n *\n * @public\n * @example\n * ```ts\n * const highlightShape: TLHighlightShape = {\n * id: 'shape:highlight1',\n * type: 'highlight',\n * x: 100,\n * y: 50,\n * rotation: 0,\n * index: 'a1',\n * parentId: 'page:main',\n * isLocked: false,\n * opacity: 0.7,\n * props: {\n * color: 'yellow',\n * size: 'l',\n * segments: [],\n * isComplete: false,\n * isPen: false,\n * scale: 1\n * },\n * meta: {},\n * typeName: 'shape'\n * }\n * ```\n */\nexport type TLHighlightShape = TLBaseShape<'highlight', TLHighlightShapeProps>\n\n/**\n * Validation schema for highlight shape properties. Defines the runtime validation rules\n * for all properties of highlight shapes.\n *\n * @public\n * @example\n * ```ts\n * import { highlightShapeProps } from '@tldraw/tlschema'\n *\n * // Used internally by the validation system\n * const validator = T.object(highlightShapeProps)\n * const validatedProps = validator.validate(someHighlightProps)\n * ```\n */\nexport const highlightShapeProps: RecordProps<TLHighlightShape> = {\n\tcolor: DefaultColorStyle,\n\tsize: DefaultSizeStyle,\n\tsegments: T.arrayOf(DrawShapeSegment),\n\tisComplete: T.boolean,\n\tisPen: T.boolean,\n\tscale: T.nonZeroNumber,\n}\n\nconst Versions = createShapePropsMigrationIds('highlight', {\n\tAddScale: 1,\n})\n\n/**\n * Version identifiers for highlight shape migrations. These version numbers track\n * schema changes over time to enable proper data migration.\n *\n * @public\n */\nexport { Versions as highlightShapeVersions }\n\n/**\n * Migration sequence for highlight shapes. Handles schema evolution over time by defining\n * how to upgrade and downgrade highlight shape data between different versions.\n *\n * @public\n */\nexport const highlightShapeMigrations = createShapePropsMigrationSequence({\n\tsequence: [\n\t\t{\n\t\t\tid: Versions.AddScale,\n\t\t\tup: (props) => {\n\t\t\t\tprops.scale = 1\n\t\t\t},\n\t\t\tdown: (props) => {\n\t\t\t\tdelete props.scale\n\t\t\t},\n\t\t},\n\t],\n})\n"],
5
+ "mappings": "AAAA,SAAS,SAAS;AAClB,SAAS,8BAA8B,yCAAyC;AAEhF,SAAS,yBAA8C;AACvD,SAAS,wBAA4C;AAErD,SAAS,wBAA4C;AAgF9C,MAAM,sBAAqD;AAAA,EACjE,OAAO;AAAA,EACP,MAAM;AAAA,EACN,UAAU,EAAE,QAAQ,gBAAgB;AAAA,EACpC,YAAY,EAAE;AAAA,EACd,OAAO,EAAE;AAAA,EACT,OAAO,EAAE;AACV;AAEA,MAAM,WAAW,6BAA6B,aAAa;AAAA,EAC1D,UAAU;AACX,CAAC;AAgBM,MAAM,2BAA2B,kCAAkC;AAAA,EACzE,UAAU;AAAA,IACT;AAAA,MACC,IAAI,SAAS;AAAA,MACb,IAAI,CAAC,UAAU;AACd,cAAM,QAAQ;AAAA,MACf;AAAA,MACA,MAAM,CAAC,UAAU;AAChB,eAAO,MAAM;AAAA,MACd;AAAA,IACD;AAAA,EACD;AACD,CAAC;",
6
6
  "names": []
7
7
  }
@@ -35,8 +35,7 @@ const Versions = createShapePropsMigrationIds("note", {
35
35
  AddFontSizeAdjustment: 6,
36
36
  AddScale: 7,
37
37
  AddLabelColor: 8,
38
- AddRichText: 9,
39
- AddRichTextAttrs: 10
38
+ AddRichText: 9
40
39
  });
41
40
  const noteShapeMigrations = createShapePropsMigrationSequence({
42
41
  sequence: [
@@ -127,16 +126,6 @@ const noteShapeMigrations = createShapePropsMigrationSequence({
127
126
  // down: (props) => {
128
127
  // delete props.richText
129
128
  // },
130
- },
131
- {
132
- id: Versions.AddRichTextAttrs,
133
- up: (_props) => {
134
- },
135
- down: (props) => {
136
- if (props.richText && "attrs" in props.richText) {
137
- delete props.richText.attrs;
138
- }
139
- }
140
129
  }
141
130
  ]
142
131
  });
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../src/shapes/TLNoteShape.ts"],
4
- "sourcesContent": ["import { T } from '@tldraw/validate'\nimport { TLRichText, richTextValidator, toRichText } from '../misc/TLRichText'\nimport { createShapePropsMigrationIds, createShapePropsMigrationSequence } from '../records/TLShape'\nimport { RecordProps } from '../recordsWithProps'\nimport {\n\tDefaultColorStyle,\n\tDefaultLabelColorStyle,\n\tTLDefaultColorStyle,\n} from '../styles/TLColorStyle'\nimport { DefaultFontStyle, TLDefaultFontStyle } from '../styles/TLFontStyle'\nimport {\n\tDefaultHorizontalAlignStyle,\n\tTLDefaultHorizontalAlignStyle,\n} from '../styles/TLHorizontalAlignStyle'\nimport { DefaultSizeStyle, TLDefaultSizeStyle } from '../styles/TLSizeStyle'\nimport {\n\tDefaultVerticalAlignStyle,\n\tTLDefaultVerticalAlignStyle,\n} from '../styles/TLVerticalAlignStyle'\nimport { TLBaseShape } from './TLBaseShape'\n\n/**\n * Properties for a note shape. Note shapes represent sticky notes or text annotations\n * with rich formatting capabilities and various styling options.\n *\n * @public\n * @example\n * ```ts\n * const noteProps: TLNoteShapeProps = {\n * color: 'yellow',\n * labelColor: 'black',\n * size: 'm',\n * font: 'draw',\n * fontSizeAdjustment: 0,\n * align: 'middle',\n * verticalAlign: 'middle',\n * growY: 0,\n * url: '',\n * richText: toRichText('Hello **world**!'),\n * scale: 1\n * }\n * ```\n */\nexport interface TLNoteShapeProps {\n\t/** Background color style of the note */\n\tcolor: TLDefaultColorStyle\n\t/** Text color style for the note content */\n\tlabelColor: TLDefaultColorStyle\n\t/** Size style determining the font size and note dimensions */\n\tsize: TLDefaultSizeStyle\n\t/** Font family style for the note text */\n\tfont: TLDefaultFontStyle\n\t/** Adjustment to the base font size (positive increases, negative decreases) */\n\tfontSizeAdjustment: number\n\t/** Horizontal alignment of text within the note */\n\talign: TLDefaultHorizontalAlignStyle\n\t/** Vertical alignment of text within the note */\n\tverticalAlign: TLDefaultVerticalAlignStyle\n\t/** Additional height growth for the note beyond its base size */\n\tgrowY: number\n\t/** Optional URL associated with the note for linking */\n\turl: string\n\t/** Rich text content with formatting like bold, italic, etc. */\n\trichText: TLRichText\n\t/** Scale factor applied to the note shape for display */\n\tscale: number\n}\n\n/**\n * A note shape representing a sticky note or text annotation on the canvas.\n * Note shapes support rich text formatting, various styling options, and can\n * be used for annotations, reminders, or general text content.\n *\n * @public\n * @example\n * ```ts\n * const noteShape: TLNoteShape = {\n * id: 'shape:note1',\n * type: 'note',\n * x: 100,\n * y: 100,\n * rotation: 0,\n * index: 'a1',\n * parentId: 'page:main',\n * isLocked: false,\n * opacity: 1,\n * props: {\n * color: 'light-blue',\n * labelColor: 'black',\n * size: 's',\n * font: 'sans',\n * fontSizeAdjustment: 2,\n * align: 'start',\n * verticalAlign: 'start',\n * growY: 50,\n * url: 'https://example.com',\n * richText: toRichText('Important **note**!'),\n * scale: 1\n * },\n * meta: {},\n * typeName: 'shape'\n * }\n * ```\n */\nexport type TLNoteShape = TLBaseShape<'note', TLNoteShapeProps>\n\n/**\n * Validation schema for note shape properties. Defines the runtime validation rules\n * for all properties of note shapes, ensuring data integrity and type safety.\n *\n * @public\n * @example\n * ```ts\n * import { noteShapeProps } from '@tldraw/tlschema'\n *\n * // Used internally by the validation system\n * const validator = T.object(noteShapeProps)\n * const validatedProps = validator.validate(someNoteProps)\n * ```\n */\nexport const noteShapeProps: RecordProps<TLNoteShape> = {\n\tcolor: DefaultColorStyle,\n\tlabelColor: DefaultLabelColorStyle,\n\tsize: DefaultSizeStyle,\n\tfont: DefaultFontStyle,\n\tfontSizeAdjustment: T.positiveNumber,\n\talign: DefaultHorizontalAlignStyle,\n\tverticalAlign: DefaultVerticalAlignStyle,\n\tgrowY: T.positiveNumber,\n\turl: T.linkUrl,\n\trichText: richTextValidator,\n\tscale: T.nonZeroNumber,\n}\n\nconst Versions = createShapePropsMigrationIds('note', {\n\tAddUrlProp: 1,\n\tRemoveJustify: 2,\n\tMigrateLegacyAlign: 3,\n\tAddVerticalAlign: 4,\n\tMakeUrlsValid: 5,\n\tAddFontSizeAdjustment: 6,\n\tAddScale: 7,\n\tAddLabelColor: 8,\n\tAddRichText: 9,\n\tAddRichTextAttrs: 10,\n})\n\n/**\n * Version identifiers for note shape migrations. These version numbers track\n * significant schema changes over time, enabling proper data migration between versions.\n *\n * @public\n */\nexport { Versions as noteShapeVersions }\n\n/**\n * Migration sequence for note shapes. Handles schema evolution over time by defining\n * how to upgrade and downgrade note shape data between different versions. Includes\n * migrations for URL properties, text alignment changes, vertical alignment addition,\n * font size adjustments, scaling support, label color, the transition from plain text to rich text,\n * and support for attrs property on richText.\n *\n * @public\n */\nexport const noteShapeMigrations = createShapePropsMigrationSequence({\n\tsequence: [\n\t\t{\n\t\t\tid: Versions.AddUrlProp,\n\t\t\tup: (props) => {\n\t\t\t\tprops.url = ''\n\t\t\t},\n\t\t\tdown: 'retired',\n\t\t},\n\t\t{\n\t\t\tid: Versions.RemoveJustify,\n\t\t\tup: (props) => {\n\t\t\t\tif (props.align === 'justify') {\n\t\t\t\t\tprops.align = 'start'\n\t\t\t\t}\n\t\t\t},\n\t\t\tdown: 'retired',\n\t\t},\n\t\t{\n\t\t\tid: Versions.MigrateLegacyAlign,\n\t\t\tup: (props) => {\n\t\t\t\tswitch (props.align) {\n\t\t\t\t\tcase 'start':\n\t\t\t\t\t\tprops.align = 'start-legacy'\n\t\t\t\t\t\treturn\n\t\t\t\t\tcase 'end':\n\t\t\t\t\t\tprops.align = 'end-legacy'\n\t\t\t\t\t\treturn\n\t\t\t\t\tdefault:\n\t\t\t\t\t\tprops.align = 'middle-legacy'\n\t\t\t\t\t\treturn\n\t\t\t\t}\n\t\t\t},\n\t\t\tdown: 'retired',\n\t\t},\n\t\t{\n\t\t\tid: Versions.AddVerticalAlign,\n\t\t\tup: (props) => {\n\t\t\t\tprops.verticalAlign = 'middle'\n\t\t\t},\n\t\t\tdown: 'retired',\n\t\t},\n\t\t{\n\t\t\tid: Versions.MakeUrlsValid,\n\t\t\tup: (props) => {\n\t\t\t\tif (!T.linkUrl.isValid(props.url)) {\n\t\t\t\t\tprops.url = ''\n\t\t\t\t}\n\t\t\t},\n\t\t\tdown: (_props) => {\n\t\t\t\t// noop\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tid: Versions.AddFontSizeAdjustment,\n\t\t\tup: (props) => {\n\t\t\t\tprops.fontSizeAdjustment = 0\n\t\t\t},\n\t\t\tdown: (props) => {\n\t\t\t\tdelete props.fontSizeAdjustment\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tid: Versions.AddScale,\n\t\t\tup: (props) => {\n\t\t\t\tprops.scale = 1\n\t\t\t},\n\t\t\tdown: (props) => {\n\t\t\t\tdelete props.scale\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tid: Versions.AddLabelColor,\n\t\t\tup: (props) => {\n\t\t\t\tprops.labelColor = 'black'\n\t\t\t},\n\t\t\tdown: (props) => {\n\t\t\t\tdelete props.labelColor\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tid: Versions.AddRichText,\n\t\t\tup: (props) => {\n\t\t\t\tprops.richText = toRichText(props.text)\n\t\t\t\tdelete props.text\n\t\t\t},\n\t\t\t// N.B. Explicitly no down state so that we force clients to update.\n\t\t\t// down: (props) => {\n\t\t\t// \tdelete props.richText\n\t\t\t// },\n\t\t},\n\t\t{\n\t\t\tid: Versions.AddRichTextAttrs,\n\t\t\tup: (_props) => {\n\t\t\t\t// noop - attrs is optional so old records are valid\n\t\t\t},\n\t\t\tdown: (props) => {\n\t\t\t\t// Remove attrs from richText when migrating down\n\t\t\t\tif (props.richText && 'attrs' in props.richText) {\n\t\t\t\t\tdelete props.richText.attrs\n\t\t\t\t}\n\t\t\t},\n\t\t},\n\t],\n})\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["import { T } from '@tldraw/validate'\nimport { TLRichText, richTextValidator, toRichText } from '../misc/TLRichText'\nimport { createShapePropsMigrationIds, createShapePropsMigrationSequence } from '../records/TLShape'\nimport { RecordProps } from '../recordsWithProps'\nimport {\n\tDefaultColorStyle,\n\tDefaultLabelColorStyle,\n\tTLDefaultColorStyle,\n} from '../styles/TLColorStyle'\nimport { DefaultFontStyle, TLDefaultFontStyle } from '../styles/TLFontStyle'\nimport {\n\tDefaultHorizontalAlignStyle,\n\tTLDefaultHorizontalAlignStyle,\n} from '../styles/TLHorizontalAlignStyle'\nimport { DefaultSizeStyle, TLDefaultSizeStyle } from '../styles/TLSizeStyle'\nimport {\n\tDefaultVerticalAlignStyle,\n\tTLDefaultVerticalAlignStyle,\n} from '../styles/TLVerticalAlignStyle'\nimport { TLBaseShape } from './TLBaseShape'\n\n/**\n * Properties for a note shape. Note shapes represent sticky notes or text annotations\n * with rich formatting capabilities and various styling options.\n *\n * @public\n * @example\n * ```ts\n * const noteProps: TLNoteShapeProps = {\n * color: 'yellow',\n * labelColor: 'black',\n * size: 'm',\n * font: 'draw',\n * fontSizeAdjustment: 0,\n * align: 'middle',\n * verticalAlign: 'middle',\n * growY: 0,\n * url: '',\n * richText: toRichText('Hello **world**!'),\n * scale: 1\n * }\n * ```\n */\nexport interface TLNoteShapeProps {\n\t/** Background color style of the note */\n\tcolor: TLDefaultColorStyle\n\t/** Text color style for the note content */\n\tlabelColor: TLDefaultColorStyle\n\t/** Size style determining the font size and note dimensions */\n\tsize: TLDefaultSizeStyle\n\t/** Font family style for the note text */\n\tfont: TLDefaultFontStyle\n\t/** Adjustment to the base font size (positive increases, negative decreases) */\n\tfontSizeAdjustment: number\n\t/** Horizontal alignment of text within the note */\n\talign: TLDefaultHorizontalAlignStyle\n\t/** Vertical alignment of text within the note */\n\tverticalAlign: TLDefaultVerticalAlignStyle\n\t/** Additional height growth for the note beyond its base size */\n\tgrowY: number\n\t/** Optional URL associated with the note for linking */\n\turl: string\n\t/** Rich text content with formatting like bold, italic, etc. */\n\trichText: TLRichText\n\t/** Scale factor applied to the note shape for display */\n\tscale: number\n}\n\n/**\n * A note shape representing a sticky note or text annotation on the canvas.\n * Note shapes support rich text formatting, various styling options, and can\n * be used for annotations, reminders, or general text content.\n *\n * @public\n * @example\n * ```ts\n * const noteShape: TLNoteShape = {\n * id: 'shape:note1',\n * type: 'note',\n * x: 100,\n * y: 100,\n * rotation: 0,\n * index: 'a1',\n * parentId: 'page:main',\n * isLocked: false,\n * opacity: 1,\n * props: {\n * color: 'light-blue',\n * labelColor: 'black',\n * size: 's',\n * font: 'sans',\n * fontSizeAdjustment: 2,\n * align: 'start',\n * verticalAlign: 'start',\n * growY: 50,\n * url: 'https://example.com',\n * richText: toRichText('Important **note**!'),\n * scale: 1\n * },\n * meta: {},\n * typeName: 'shape'\n * }\n * ```\n */\nexport type TLNoteShape = TLBaseShape<'note', TLNoteShapeProps>\n\n/**\n * Validation schema for note shape properties. Defines the runtime validation rules\n * for all properties of note shapes, ensuring data integrity and type safety.\n *\n * @public\n * @example\n * ```ts\n * import { noteShapeProps } from '@tldraw/tlschema'\n *\n * // Used internally by the validation system\n * const validator = T.object(noteShapeProps)\n * const validatedProps = validator.validate(someNoteProps)\n * ```\n */\nexport const noteShapeProps: RecordProps<TLNoteShape> = {\n\tcolor: DefaultColorStyle,\n\tlabelColor: DefaultLabelColorStyle,\n\tsize: DefaultSizeStyle,\n\tfont: DefaultFontStyle,\n\tfontSizeAdjustment: T.positiveNumber,\n\talign: DefaultHorizontalAlignStyle,\n\tverticalAlign: DefaultVerticalAlignStyle,\n\tgrowY: T.positiveNumber,\n\turl: T.linkUrl,\n\trichText: richTextValidator,\n\tscale: T.nonZeroNumber,\n}\n\nconst Versions = createShapePropsMigrationIds('note', {\n\tAddUrlProp: 1,\n\tRemoveJustify: 2,\n\tMigrateLegacyAlign: 3,\n\tAddVerticalAlign: 4,\n\tMakeUrlsValid: 5,\n\tAddFontSizeAdjustment: 6,\n\tAddScale: 7,\n\tAddLabelColor: 8,\n\tAddRichText: 9,\n})\n\n/**\n * Version identifiers for note shape migrations. These version numbers track\n * significant schema changes over time, enabling proper data migration between versions.\n *\n * @public\n */\nexport { Versions as noteShapeVersions }\n\n/**\n * Migration sequence for note shapes. Handles schema evolution over time by defining\n * how to upgrade and downgrade note shape data between different versions. Includes\n * migrations for URL properties, text alignment changes, vertical alignment addition,\n * font size adjustments, scaling support, label color, and the transition from plain text to rich text.\n *\n * @public\n */\nexport const noteShapeMigrations = createShapePropsMigrationSequence({\n\tsequence: [\n\t\t{\n\t\t\tid: Versions.AddUrlProp,\n\t\t\tup: (props) => {\n\t\t\t\tprops.url = ''\n\t\t\t},\n\t\t\tdown: 'retired',\n\t\t},\n\t\t{\n\t\t\tid: Versions.RemoveJustify,\n\t\t\tup: (props) => {\n\t\t\t\tif (props.align === 'justify') {\n\t\t\t\t\tprops.align = 'start'\n\t\t\t\t}\n\t\t\t},\n\t\t\tdown: 'retired',\n\t\t},\n\t\t{\n\t\t\tid: Versions.MigrateLegacyAlign,\n\t\t\tup: (props) => {\n\t\t\t\tswitch (props.align) {\n\t\t\t\t\tcase 'start':\n\t\t\t\t\t\tprops.align = 'start-legacy'\n\t\t\t\t\t\treturn\n\t\t\t\t\tcase 'end':\n\t\t\t\t\t\tprops.align = 'end-legacy'\n\t\t\t\t\t\treturn\n\t\t\t\t\tdefault:\n\t\t\t\t\t\tprops.align = 'middle-legacy'\n\t\t\t\t\t\treturn\n\t\t\t\t}\n\t\t\t},\n\t\t\tdown: 'retired',\n\t\t},\n\t\t{\n\t\t\tid: Versions.AddVerticalAlign,\n\t\t\tup: (props) => {\n\t\t\t\tprops.verticalAlign = 'middle'\n\t\t\t},\n\t\t\tdown: 'retired',\n\t\t},\n\t\t{\n\t\t\tid: Versions.MakeUrlsValid,\n\t\t\tup: (props) => {\n\t\t\t\tif (!T.linkUrl.isValid(props.url)) {\n\t\t\t\t\tprops.url = ''\n\t\t\t\t}\n\t\t\t},\n\t\t\tdown: (_props) => {\n\t\t\t\t// noop\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tid: Versions.AddFontSizeAdjustment,\n\t\t\tup: (props) => {\n\t\t\t\tprops.fontSizeAdjustment = 0\n\t\t\t},\n\t\t\tdown: (props) => {\n\t\t\t\tdelete props.fontSizeAdjustment\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tid: Versions.AddScale,\n\t\t\tup: (props) => {\n\t\t\t\tprops.scale = 1\n\t\t\t},\n\t\t\tdown: (props) => {\n\t\t\t\tdelete props.scale\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tid: Versions.AddLabelColor,\n\t\t\tup: (props) => {\n\t\t\t\tprops.labelColor = 'black'\n\t\t\t},\n\t\t\tdown: (props) => {\n\t\t\t\tdelete props.labelColor\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tid: Versions.AddRichText,\n\t\t\tup: (props) => {\n\t\t\t\tprops.richText = toRichText(props.text)\n\t\t\t\tdelete props.text\n\t\t\t},\n\t\t\t// N.B. Explicitly no down state so that we force clients to update.\n\t\t\t// down: (props) => {\n\t\t\t// \tdelete props.richText\n\t\t\t// },\n\t\t},\n\t],\n})\n"],
5
+ "mappings": "AAAA,SAAS,SAAS;AAClB,SAAqB,mBAAmB,kBAAkB;AAC1D,SAAS,8BAA8B,yCAAyC;AAEhF;AAAA,EACC;AAAA,EACA;AAAA,OAEM;AACP,SAAS,wBAA4C;AACrD;AAAA,EACC;AAAA,OAEM;AACP,SAAS,wBAA4C;AACrD;AAAA,EACC;AAAA,OAEM;AAsGA,MAAM,iBAA2C;AAAA,EACvD,OAAO;AAAA,EACP,YAAY;AAAA,EACZ,MAAM;AAAA,EACN,MAAM;AAAA,EACN,oBAAoB,EAAE;AAAA,EACtB,OAAO;AAAA,EACP,eAAe;AAAA,EACf,OAAO,EAAE;AAAA,EACT,KAAK,EAAE;AAAA,EACP,UAAU;AAAA,EACV,OAAO,EAAE;AACV;AAEA,MAAM,WAAW,6BAA6B,QAAQ;AAAA,EACrD,YAAY;AAAA,EACZ,eAAe;AAAA,EACf,oBAAoB;AAAA,EACpB,kBAAkB;AAAA,EAClB,eAAe;AAAA,EACf,uBAAuB;AAAA,EACvB,UAAU;AAAA,EACV,eAAe;AAAA,EACf,aAAa;AACd,CAAC;AAkBM,MAAM,sBAAsB,kCAAkC;AAAA,EACpE,UAAU;AAAA,IACT;AAAA,MACC,IAAI,SAAS;AAAA,MACb,IAAI,CAAC,UAAU;AACd,cAAM,MAAM;AAAA,MACb;AAAA,MACA,MAAM;AAAA,IACP;AAAA,IACA;AAAA,MACC,IAAI,SAAS;AAAA,MACb,IAAI,CAAC,UAAU;AACd,YAAI,MAAM,UAAU,WAAW;AAC9B,gBAAM,QAAQ;AAAA,QACf;AAAA,MACD;AAAA,MACA,MAAM;AAAA,IACP;AAAA,IACA;AAAA,MACC,IAAI,SAAS;AAAA,MACb,IAAI,CAAC,UAAU;AACd,gBAAQ,MAAM,OAAO;AAAA,UACpB,KAAK;AACJ,kBAAM,QAAQ;AACd;AAAA,UACD,KAAK;AACJ,kBAAM,QAAQ;AACd;AAAA,UACD;AACC,kBAAM,QAAQ;AACd;AAAA,QACF;AAAA,MACD;AAAA,MACA,MAAM;AAAA,IACP;AAAA,IACA;AAAA,MACC,IAAI,SAAS;AAAA,MACb,IAAI,CAAC,UAAU;AACd,cAAM,gBAAgB;AAAA,MACvB;AAAA,MACA,MAAM;AAAA,IACP;AAAA,IACA;AAAA,MACC,IAAI,SAAS;AAAA,MACb,IAAI,CAAC,UAAU;AACd,YAAI,CAAC,EAAE,QAAQ,QAAQ,MAAM,GAAG,GAAG;AAClC,gBAAM,MAAM;AAAA,QACb;AAAA,MACD;AAAA,MACA,MAAM,CAAC,WAAW;AAAA,MAElB;AAAA,IACD;AAAA,IACA;AAAA,MACC,IAAI,SAAS;AAAA,MACb,IAAI,CAAC,UAAU;AACd,cAAM,qBAAqB;AAAA,MAC5B;AAAA,MACA,MAAM,CAAC,UAAU;AAChB,eAAO,MAAM;AAAA,MACd;AAAA,IACD;AAAA,IACA;AAAA,MACC,IAAI,SAAS;AAAA,MACb,IAAI,CAAC,UAAU;AACd,cAAM,QAAQ;AAAA,MACf;AAAA,MACA,MAAM,CAAC,UAAU;AAChB,eAAO,MAAM;AAAA,MACd;AAAA,IACD;AAAA,IACA;AAAA,MACC,IAAI,SAAS;AAAA,MACb,IAAI,CAAC,UAAU;AACd,cAAM,aAAa;AAAA,MACpB;AAAA,MACA,MAAM,CAAC,UAAU;AAChB,eAAO,MAAM;AAAA,MACd;AAAA,IACD;AAAA,IACA;AAAA,MACC,IAAI,SAAS;AAAA,MACb,IAAI,CAAC,UAAU;AACd,cAAM,WAAW,WAAW,MAAM,IAAI;AACtC,eAAO,MAAM;AAAA,MACd;AAAA;AAAA;AAAA;AAAA;AAAA,IAKD;AAAA,EACD;AACD,CAAC;",
6
6
  "names": []
7
7
  }
@@ -18,8 +18,7 @@ const textShapeProps = {
18
18
  const Versions = createShapePropsMigrationIds("text", {
19
19
  RemoveJustify: 1,
20
20
  AddTextAlign: 2,
21
- AddRichText: 3,
22
- AddRichTextAttrs: 4
21
+ AddRichText: 3
23
22
  });
24
23
  const textShapeMigrations = createShapePropsMigrationSequence({
25
24
  sequence: [
@@ -53,16 +52,6 @@ const textShapeMigrations = createShapePropsMigrationSequence({
53
52
  // down: (props) => {
54
53
  // delete props.richText
55
54
  // },
56
- },
57
- {
58
- id: Versions.AddRichTextAttrs,
59
- up: (_props) => {
60
- },
61
- down: (props) => {
62
- if (props.richText && "attrs" in props.richText) {
63
- delete props.richText.attrs;
64
- }
65
- }
66
55
  }
67
56
  ]
68
57
  });
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../src/shapes/TLTextShape.ts"],
4
- "sourcesContent": ["import { T } from '@tldraw/validate'\nimport { TLRichText, richTextValidator, toRichText } from '../misc/TLRichText'\nimport { createShapePropsMigrationIds, createShapePropsMigrationSequence } from '../records/TLShape'\nimport { RecordProps } from '../recordsWithProps'\nimport { DefaultColorStyle, TLDefaultColorStyle } from '../styles/TLColorStyle'\nimport { DefaultFontStyle, TLDefaultFontStyle } from '../styles/TLFontStyle'\nimport { DefaultSizeStyle, TLDefaultSizeStyle } from '../styles/TLSizeStyle'\nimport { DefaultTextAlignStyle, TLDefaultTextAlignStyle } from '../styles/TLTextAlignStyle'\nimport { TLBaseShape } from './TLBaseShape'\n\n/**\n * Configuration interface defining properties for text shapes in tldraw.\n * Text shapes support rich formatting, styling, and automatic sizing.\n *\n * @public\n * @example\n * ```ts\n * const textProps: TLTextShapeProps = {\n * color: 'black',\n * size: 'm',\n * font: 'draw',\n * textAlign: 'start',\n * w: 200,\n * richText: toRichText('Hello **bold** text'),\n * scale: 1,\n * autoSize: true\n * }\n * ```\n */\nexport interface TLTextShapeProps {\n\tcolor: TLDefaultColorStyle\n\tsize: TLDefaultSizeStyle\n\tfont: TLDefaultFontStyle\n\ttextAlign: TLDefaultTextAlignStyle\n\tw: number\n\trichText: TLRichText\n\tscale: number\n\tautoSize: boolean\n}\n\n/**\n * A text shape that can display formatted text content with various styling options.\n * Text shapes support rich formatting, automatic sizing, and consistent styling through\n * the tldraw style system.\n *\n * @public\n * @example\n * ```ts\n * const textShape: TLTextShape = {\n * id: 'shape:text123',\n * typeName: 'shape',\n * type: 'text',\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 * color: 'black',\n * size: 'm',\n * font: 'draw',\n * textAlign: 'start',\n * w: 200,\n * richText: toRichText('Sample text'),\n * scale: 1,\n * autoSize: false\n * },\n * meta: {}\n * }\n * ```\n */\nexport type TLTextShape = TLBaseShape<'text', TLTextShapeProps>\n\n/**\n * Validation schema for text shape properties. This defines the runtime validation\n * rules that ensure text shape data integrity when records are stored or transmitted.\n *\n * @public\n * @example\n * ```ts\n * import { textShapeProps } from '@tldraw/tlschema'\n *\n * // Validate text shape properties\n * const isValid = textShapeProps.richText.isValid(myRichText)\n * if (isValid) {\n * // Properties are valid, safe to use\n * }\n * ```\n */\nexport const textShapeProps: RecordProps<TLTextShape> = {\n\tcolor: DefaultColorStyle,\n\tsize: DefaultSizeStyle,\n\tfont: DefaultFontStyle,\n\ttextAlign: DefaultTextAlignStyle,\n\tw: T.nonZeroNumber,\n\trichText: richTextValidator,\n\tscale: T.nonZeroNumber,\n\tautoSize: T.boolean,\n}\n\nconst Versions = createShapePropsMigrationIds('text', {\n\tRemoveJustify: 1,\n\tAddTextAlign: 2,\n\tAddRichText: 3,\n\tAddRichTextAttrs: 4,\n})\n\n/**\n * Version identifiers for text shape migrations. These constants track\n * the evolution of the text shape schema over time.\n *\n * @public\n * @example\n * ```ts\n * import { textShapeVersions } from '@tldraw/tlschema'\n *\n * // Check if shape data needs migration\n * if (shapeVersion < textShapeVersions.AddRichTextAttrs) {\n * // Apply rich text attrs migration\n * }\n * ```\n */\nexport { Versions as textShapeVersions }\n\n/**\n * Migration sequence for text shape schema evolution. This handles transforming\n * text shape data between different versions as the schema evolves over time.\n *\n * Key migrations include:\n * - RemoveJustify: Replaced 'justify' alignment with 'start'\n * - AddTextAlign: Migrated from 'align' to 'textAlign' property\n * - AddRichText: Converted plain text to rich text format\n * - AddRichTextAttrs: Added support for attrs property on richText\n *\n * @public\n */\nexport const textShapeMigrations = createShapePropsMigrationSequence({\n\tsequence: [\n\t\t{\n\t\t\tid: Versions.RemoveJustify,\n\t\t\tup: (props) => {\n\t\t\t\tif (props.align === 'justify') {\n\t\t\t\t\tprops.align = 'start'\n\t\t\t\t}\n\t\t\t},\n\t\t\tdown: 'retired',\n\t\t},\n\t\t{\n\t\t\tid: Versions.AddTextAlign,\n\t\t\tup: (props) => {\n\t\t\t\tprops.textAlign = props.align\n\t\t\t\tdelete props.align\n\t\t\t},\n\t\t\tdown: (props) => {\n\t\t\t\tprops.align = props.textAlign\n\t\t\t\tdelete props.textAlign\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tid: Versions.AddRichText,\n\t\t\tup: (props) => {\n\t\t\t\tprops.richText = toRichText(props.text)\n\t\t\t\tdelete props.text\n\t\t\t},\n\t\t\t// N.B. Explicitly no down state so that we force clients to update.\n\t\t\t// down: (props) => {\n\t\t\t// \tdelete props.richText\n\t\t\t// },\n\t\t},\n\t\t{\n\t\t\tid: Versions.AddRichTextAttrs,\n\t\t\tup: (_props) => {\n\t\t\t\t// noop - attrs is optional so old records are valid\n\t\t\t},\n\t\t\tdown: (props) => {\n\t\t\t\t// Remove attrs from richText when migrating down\n\t\t\t\tif (props.richText && 'attrs' in props.richText) {\n\t\t\t\t\tdelete props.richText.attrs\n\t\t\t\t}\n\t\t\t},\n\t\t},\n\t],\n})\n"],
5
- "mappings": "AAAA,SAAS,SAAS;AAClB,SAAqB,mBAAmB,kBAAkB;AAC1D,SAAS,8BAA8B,yCAAyC;AAEhF,SAAS,yBAA8C;AACvD,SAAS,wBAA4C;AACrD,SAAS,wBAA4C;AACrD,SAAS,6BAAsD;AAoFxD,MAAM,iBAA2C;AAAA,EACvD,OAAO;AAAA,EACP,MAAM;AAAA,EACN,MAAM;AAAA,EACN,WAAW;AAAA,EACX,GAAG,EAAE;AAAA,EACL,UAAU;AAAA,EACV,OAAO,EAAE;AAAA,EACT,UAAU,EAAE;AACb;AAEA,MAAM,WAAW,6BAA6B,QAAQ;AAAA,EACrD,eAAe;AAAA,EACf,cAAc;AAAA,EACd,aAAa;AAAA,EACb,kBAAkB;AACnB,CAAC;AA+BM,MAAM,sBAAsB,kCAAkC;AAAA,EACpE,UAAU;AAAA,IACT;AAAA,MACC,IAAI,SAAS;AAAA,MACb,IAAI,CAAC,UAAU;AACd,YAAI,MAAM,UAAU,WAAW;AAC9B,gBAAM,QAAQ;AAAA,QACf;AAAA,MACD;AAAA,MACA,MAAM;AAAA,IACP;AAAA,IACA;AAAA,MACC,IAAI,SAAS;AAAA,MACb,IAAI,CAAC,UAAU;AACd,cAAM,YAAY,MAAM;AACxB,eAAO,MAAM;AAAA,MACd;AAAA,MACA,MAAM,CAAC,UAAU;AAChB,cAAM,QAAQ,MAAM;AACpB,eAAO,MAAM;AAAA,MACd;AAAA,IACD;AAAA,IACA;AAAA,MACC,IAAI,SAAS;AAAA,MACb,IAAI,CAAC,UAAU;AACd,cAAM,WAAW,WAAW,MAAM,IAAI;AACtC,eAAO,MAAM;AAAA,MACd;AAAA;AAAA;AAAA;AAAA;AAAA,IAKD;AAAA,IACA;AAAA,MACC,IAAI,SAAS;AAAA,MACb,IAAI,CAAC,WAAW;AAAA,MAEhB;AAAA,MACA,MAAM,CAAC,UAAU;AAEhB,YAAI,MAAM,YAAY,WAAW,MAAM,UAAU;AAChD,iBAAO,MAAM,SAAS;AAAA,QACvB;AAAA,MACD;AAAA,IACD;AAAA,EACD;AACD,CAAC;",
4
+ "sourcesContent": ["import { T } from '@tldraw/validate'\nimport { TLRichText, richTextValidator, toRichText } from '../misc/TLRichText'\nimport { createShapePropsMigrationIds, createShapePropsMigrationSequence } from '../records/TLShape'\nimport { RecordProps } from '../recordsWithProps'\nimport { DefaultColorStyle, TLDefaultColorStyle } from '../styles/TLColorStyle'\nimport { DefaultFontStyle, TLDefaultFontStyle } from '../styles/TLFontStyle'\nimport { DefaultSizeStyle, TLDefaultSizeStyle } from '../styles/TLSizeStyle'\nimport { DefaultTextAlignStyle, TLDefaultTextAlignStyle } from '../styles/TLTextAlignStyle'\nimport { TLBaseShape } from './TLBaseShape'\n\n/**\n * Configuration interface defining properties for text shapes in tldraw.\n * Text shapes support rich formatting, styling, and automatic sizing.\n *\n * @public\n * @example\n * ```ts\n * const textProps: TLTextShapeProps = {\n * color: 'black',\n * size: 'm',\n * font: 'draw',\n * textAlign: 'start',\n * w: 200,\n * richText: toRichText('Hello **bold** text'),\n * scale: 1,\n * autoSize: true\n * }\n * ```\n */\nexport interface TLTextShapeProps {\n\tcolor: TLDefaultColorStyle\n\tsize: TLDefaultSizeStyle\n\tfont: TLDefaultFontStyle\n\ttextAlign: TLDefaultTextAlignStyle\n\tw: number\n\trichText: TLRichText\n\tscale: number\n\tautoSize: boolean\n}\n\n/**\n * A text shape that can display formatted text content with various styling options.\n * Text shapes support rich formatting, automatic sizing, and consistent styling through\n * the tldraw style system.\n *\n * @public\n * @example\n * ```ts\n * const textShape: TLTextShape = {\n * id: 'shape:text123',\n * typeName: 'shape',\n * type: 'text',\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 * color: 'black',\n * size: 'm',\n * font: 'draw',\n * textAlign: 'start',\n * w: 200,\n * richText: toRichText('Sample text'),\n * scale: 1,\n * autoSize: false\n * },\n * meta: {}\n * }\n * ```\n */\nexport type TLTextShape = TLBaseShape<'text', TLTextShapeProps>\n\n/**\n * Validation schema for text shape properties. This defines the runtime validation\n * rules that ensure text shape data integrity when records are stored or transmitted.\n *\n * @public\n * @example\n * ```ts\n * import { textShapeProps } from '@tldraw/tlschema'\n *\n * // Validate text shape properties\n * const isValid = textShapeProps.richText.isValid(myRichText)\n * if (isValid) {\n * // Properties are valid, safe to use\n * }\n * ```\n */\nexport const textShapeProps: RecordProps<TLTextShape> = {\n\tcolor: DefaultColorStyle,\n\tsize: DefaultSizeStyle,\n\tfont: DefaultFontStyle,\n\ttextAlign: DefaultTextAlignStyle,\n\tw: T.nonZeroNumber,\n\trichText: richTextValidator,\n\tscale: T.nonZeroNumber,\n\tautoSize: T.boolean,\n}\n\nconst Versions = createShapePropsMigrationIds('text', {\n\tRemoveJustify: 1,\n\tAddTextAlign: 2,\n\tAddRichText: 3,\n})\n\n/**\n * Version identifiers for text shape migrations. These constants track\n * the evolution of the text shape schema over time.\n *\n * @public\n * @example\n * ```ts\n * import { textShapeVersions } from '@tldraw/tlschema'\n *\n * // Check if shape data needs migration\n * if (shapeVersion < textShapeVersions.AddRichText) {\n * // Apply rich text migration\n * }\n * ```\n */\nexport { Versions as textShapeVersions }\n\n/**\n * Migration sequence for text shape schema evolution. This handles transforming\n * text shape data between different versions as the schema evolves over time.\n *\n * Key migrations include:\n * - RemoveJustify: Replaced 'justify' alignment with 'start'\n * - AddTextAlign: Migrated from 'align' to 'textAlign' property\n * - AddRichText: Converted plain text to rich text format\n *\n * @public\n */\nexport const textShapeMigrations = createShapePropsMigrationSequence({\n\tsequence: [\n\t\t{\n\t\t\tid: Versions.RemoveJustify,\n\t\t\tup: (props) => {\n\t\t\t\tif (props.align === 'justify') {\n\t\t\t\t\tprops.align = 'start'\n\t\t\t\t}\n\t\t\t},\n\t\t\tdown: 'retired',\n\t\t},\n\t\t{\n\t\t\tid: Versions.AddTextAlign,\n\t\t\tup: (props) => {\n\t\t\t\tprops.textAlign = props.align\n\t\t\t\tdelete props.align\n\t\t\t},\n\t\t\tdown: (props) => {\n\t\t\t\tprops.align = props.textAlign\n\t\t\t\tdelete props.textAlign\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tid: Versions.AddRichText,\n\t\t\tup: (props) => {\n\t\t\t\tprops.richText = toRichText(props.text)\n\t\t\t\tdelete props.text\n\t\t\t},\n\t\t\t// N.B. Explicitly no down state so that we force clients to update.\n\t\t\t// down: (props) => {\n\t\t\t// \tdelete props.richText\n\t\t\t// },\n\t\t},\n\t],\n})\n"],
5
+ "mappings": "AAAA,SAAS,SAAS;AAClB,SAAqB,mBAAmB,kBAAkB;AAC1D,SAAS,8BAA8B,yCAAyC;AAEhF,SAAS,yBAA8C;AACvD,SAAS,wBAA4C;AACrD,SAAS,wBAA4C;AACrD,SAAS,6BAAsD;AAoFxD,MAAM,iBAA2C;AAAA,EACvD,OAAO;AAAA,EACP,MAAM;AAAA,EACN,MAAM;AAAA,EACN,WAAW;AAAA,EACX,GAAG,EAAE;AAAA,EACL,UAAU;AAAA,EACV,OAAO,EAAE;AAAA,EACT,UAAU,EAAE;AACb;AAEA,MAAM,WAAW,6BAA6B,QAAQ;AAAA,EACrD,eAAe;AAAA,EACf,cAAc;AAAA,EACd,aAAa;AACd,CAAC;AA8BM,MAAM,sBAAsB,kCAAkC;AAAA,EACpE,UAAU;AAAA,IACT;AAAA,MACC,IAAI,SAAS;AAAA,MACb,IAAI,CAAC,UAAU;AACd,YAAI,MAAM,UAAU,WAAW;AAC9B,gBAAM,QAAQ;AAAA,QACf;AAAA,MACD;AAAA,MACA,MAAM;AAAA,IACP;AAAA,IACA;AAAA,MACC,IAAI,SAAS;AAAA,MACb,IAAI,CAAC,UAAU;AACd,cAAM,YAAY,MAAM;AACxB,eAAO,MAAM;AAAA,MACd;AAAA,MACA,MAAM,CAAC,UAAU;AAChB,cAAM,QAAQ,MAAM;AACpB,eAAO,MAAM;AAAA,MACd;AAAA,IACD;AAAA,IACA;AAAA,MACC,IAAI,SAAS;AAAA,MACb,IAAI,CAAC,UAAU;AACd,cAAM,WAAW,WAAW,MAAM,IAAI;AACtC,eAAO,MAAM;AAAA,MACd;AAAA;AAAA;AAAA;AAAA;AAAA,IAKD;AAAA,EACD;AACD,CAAC;",
6
6
  "names": []
7
7
  }
@@ -13,29 +13,29 @@ const storeMigrations = createMigrationSequence({
13
13
  sequence: [
14
14
  {
15
15
  id: Versions.RemoveCodeAndIconShapeTypes,
16
- scope: "storage",
17
- up: (storage) => {
18
- for (const [id, record] of storage.entries()) {
19
- if (record.typeName === "shape" && "type" in record && (record.type === "icon" || record.type === "code")) {
20
- storage.delete(id);
16
+ scope: "store",
17
+ up: (store) => {
18
+ for (const [id, record] of objectMapEntries(store)) {
19
+ if (record.typeName === "shape" && (record.type === "icon" || record.type === "code")) {
20
+ delete store[id];
21
21
  }
22
22
  }
23
23
  }
24
24
  },
25
25
  {
26
26
  id: Versions.AddInstancePresenceType,
27
- scope: "storage",
28
- up(_storage) {
27
+ scope: "store",
28
+ up(_store) {
29
29
  }
30
30
  },
31
31
  {
32
32
  // remove user and presence records and add pointer records
33
33
  id: Versions.RemoveTLUserAndPresenceAndAddPointer,
34
- scope: "storage",
35
- up: (storage) => {
36
- for (const [id, record] of storage.entries()) {
34
+ scope: "store",
35
+ up: (store) => {
36
+ for (const [id, record] of objectMapEntries(store)) {
37
37
  if (record.typeName.match(/^(user|user_presence)$/)) {
38
- storage.delete(id);
38
+ delete store[id];
39
39
  }
40
40
  }
41
41
  }
@@ -43,11 +43,11 @@ const storeMigrations = createMigrationSequence({
43
43
  {
44
44
  // remove user document records
45
45
  id: Versions.RemoveUserDocument,
46
- scope: "storage",
47
- up: (storage) => {
48
- for (const [id, record] of storage.entries()) {
46
+ scope: "store",
47
+ up: (store) => {
48
+ for (const [id, record] of objectMapEntries(store)) {
49
49
  if (record.typeName.match("user_document")) {
50
- storage.delete(id);
50
+ delete store[id];
51
51
  }
52
52
  }
53
53
  }