@tldraw/editor 3.11.0-canary.f529c521e249 → 3.12.0-canary.10d4563919ca

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 (103) hide show
  1. package/CHANGELOG.md +93 -2
  2. package/dist-cjs/index.d.ts +23 -9
  3. package/dist-cjs/index.js +1 -1
  4. package/dist-cjs/index.js.map +2 -2
  5. package/dist-cjs/lib/components/Shape.js +2 -2
  6. package/dist-cjs/lib/components/Shape.js.map +2 -2
  7. package/dist-cjs/lib/components/default-components/DefaultShapeIndicator.js +4 -4
  8. package/dist-cjs/lib/components/default-components/DefaultShapeIndicator.js.map +2 -2
  9. package/dist-cjs/lib/components/default-components/DefaultShapeIndicators.js +34 -26
  10. package/dist-cjs/lib/components/default-components/DefaultShapeIndicators.js.map +2 -2
  11. package/dist-cjs/lib/config/TLUserPreferences.js +1 -1
  12. package/dist-cjs/lib/config/TLUserPreferences.js.map +1 -1
  13. package/dist-cjs/lib/config/createTLStore.js +2 -1
  14. package/dist-cjs/lib/config/createTLStore.js.map +2 -2
  15. package/dist-cjs/lib/constants.js +1 -1
  16. package/dist-cjs/lib/constants.js.map +2 -2
  17. package/dist-cjs/lib/editor/Editor.js +27 -16
  18. package/dist-cjs/lib/editor/Editor.js.map +2 -2
  19. package/dist-cjs/lib/editor/managers/FocusManager.js +15 -0
  20. package/dist-cjs/lib/editor/managers/FocusManager.js.map +2 -2
  21. package/dist-cjs/lib/editor/managers/UserPreferencesManager.js +1 -1
  22. package/dist-cjs/lib/editor/managers/UserPreferencesManager.js.map +2 -2
  23. package/dist-cjs/lib/exports/StyleEmbedder.js +16 -1
  24. package/dist-cjs/lib/exports/StyleEmbedder.js.map +2 -2
  25. package/dist-cjs/lib/exports/exportToSvg.js.map +1 -1
  26. package/dist-cjs/lib/exports/getSvgJsx.js +1 -1
  27. package/dist-cjs/lib/exports/getSvgJsx.js.map +2 -2
  28. package/dist-cjs/lib/exports/parseCss.js +27 -2
  29. package/dist-cjs/lib/exports/parseCss.js.map +2 -2
  30. package/dist-cjs/lib/hooks/useLocalStore.js +3 -0
  31. package/dist-cjs/lib/hooks/useLocalStore.js.map +2 -2
  32. package/dist-cjs/lib/license/Watermark.js +7 -1
  33. package/dist-cjs/lib/license/Watermark.js.map +2 -2
  34. package/dist-cjs/lib/options.js +2 -1
  35. package/dist-cjs/lib/options.js.map +2 -2
  36. package/dist-cjs/lib/primitives/geometry/Group2d.js +1 -1
  37. package/dist-cjs/lib/primitives/geometry/Group2d.js.map +2 -2
  38. package/dist-cjs/lib/utils/sync/LocalIndexedDb.js +8 -0
  39. package/dist-cjs/lib/utils/sync/LocalIndexedDb.js.map +2 -2
  40. package/dist-cjs/version.js +3 -3
  41. package/dist-cjs/version.js.map +1 -1
  42. package/dist-esm/index.d.mts +23 -9
  43. package/dist-esm/index.mjs +4 -2
  44. package/dist-esm/index.mjs.map +2 -2
  45. package/dist-esm/lib/components/Shape.mjs +2 -2
  46. package/dist-esm/lib/components/Shape.mjs.map +2 -2
  47. package/dist-esm/lib/components/default-components/DefaultShapeIndicator.mjs +4 -4
  48. package/dist-esm/lib/components/default-components/DefaultShapeIndicator.mjs.map +2 -2
  49. package/dist-esm/lib/components/default-components/DefaultShapeIndicators.mjs +34 -26
  50. package/dist-esm/lib/components/default-components/DefaultShapeIndicators.mjs.map +2 -2
  51. package/dist-esm/lib/config/TLUserPreferences.mjs +1 -1
  52. package/dist-esm/lib/config/TLUserPreferences.mjs.map +1 -1
  53. package/dist-esm/lib/config/createTLStore.mjs +2 -1
  54. package/dist-esm/lib/config/createTLStore.mjs.map +2 -2
  55. package/dist-esm/lib/constants.mjs +1 -1
  56. package/dist-esm/lib/constants.mjs.map +2 -2
  57. package/dist-esm/lib/editor/Editor.mjs +27 -16
  58. package/dist-esm/lib/editor/Editor.mjs.map +2 -2
  59. package/dist-esm/lib/editor/managers/FocusManager.mjs +15 -0
  60. package/dist-esm/lib/editor/managers/FocusManager.mjs.map +2 -2
  61. package/dist-esm/lib/editor/managers/UserPreferencesManager.mjs +1 -1
  62. package/dist-esm/lib/editor/managers/UserPreferencesManager.mjs.map +2 -2
  63. package/dist-esm/lib/exports/StyleEmbedder.mjs +22 -2
  64. package/dist-esm/lib/exports/StyleEmbedder.mjs.map +2 -2
  65. package/dist-esm/lib/exports/exportToSvg.mjs.map +1 -1
  66. package/dist-esm/lib/exports/getSvgJsx.mjs +1 -1
  67. package/dist-esm/lib/exports/getSvgJsx.mjs.map +2 -2
  68. package/dist-esm/lib/exports/parseCss.mjs +27 -2
  69. package/dist-esm/lib/exports/parseCss.mjs.map +2 -2
  70. package/dist-esm/lib/hooks/useLocalStore.mjs +3 -0
  71. package/dist-esm/lib/hooks/useLocalStore.mjs.map +2 -2
  72. package/dist-esm/lib/license/Watermark.mjs +7 -1
  73. package/dist-esm/lib/license/Watermark.mjs.map +2 -2
  74. package/dist-esm/lib/options.mjs +2 -1
  75. package/dist-esm/lib/options.mjs.map +2 -2
  76. package/dist-esm/lib/primitives/geometry/Group2d.mjs +1 -1
  77. package/dist-esm/lib/primitives/geometry/Group2d.mjs.map +2 -2
  78. package/dist-esm/lib/utils/sync/LocalIndexedDb.mjs +8 -0
  79. package/dist-esm/lib/utils/sync/LocalIndexedDb.mjs.map +2 -2
  80. package/dist-esm/version.mjs +3 -3
  81. package/dist-esm/version.mjs.map +1 -1
  82. package/editor.css +28 -12
  83. package/package.json +10 -7
  84. package/src/index.ts +4 -1
  85. package/src/lib/components/Shape.tsx +2 -2
  86. package/src/lib/components/default-components/DefaultShapeIndicator.tsx +4 -4
  87. package/src/lib/components/default-components/DefaultShapeIndicators.tsx +52 -31
  88. package/src/lib/config/TLUserPreferences.ts +1 -1
  89. package/src/lib/config/createTLStore.ts +1 -0
  90. package/src/lib/constants.ts +1 -1
  91. package/src/lib/editor/Editor.ts +32 -19
  92. package/src/lib/editor/managers/FocusManager.ts +18 -0
  93. package/src/lib/editor/managers/UserPreferencesManager.ts +1 -1
  94. package/src/lib/exports/StyleEmbedder.ts +23 -4
  95. package/src/lib/exports/exportToSvg.tsx +1 -1
  96. package/src/lib/exports/getSvgJsx.tsx +1 -1
  97. package/src/lib/exports/parseCss.ts +36 -2
  98. package/src/lib/hooks/useLocalStore.ts +3 -0
  99. package/src/lib/license/Watermark.tsx +7 -1
  100. package/src/lib/options.ts +6 -0
  101. package/src/lib/primitives/geometry/Group2d.ts +1 -1
  102. package/src/lib/utils/sync/LocalIndexedDb.ts +9 -0
  103. package/src/version.ts +3 -3
@@ -2102,12 +2102,6 @@ export class Editor extends EventEmitter<TLEventMap> {
2102
2102
  * @public
2103
2103
  */
2104
2104
  setRichTextEditor(textEditor: TiptapEditor | null) {
2105
- // If the new editor is different from the current one, destroy the current one
2106
- const current = this._currentRichTextEditor.__unsafe__getWithoutCapture()
2107
- if (current !== textEditor) {
2108
- current?.destroy()
2109
- }
2110
-
2111
2105
  this._currentRichTextEditor.set(textEditor)
2112
2106
  return this
2113
2107
  }
@@ -4218,7 +4212,13 @@ export class Editor extends EventEmitter<TLEventMap> {
4218
4212
  : (assets as TLAsset[]).map((a) => a.id)
4219
4213
  if (ids.length <= 0) return this
4220
4214
 
4221
- this.run(() => this.store.remove(ids), { history: 'ignore' })
4215
+ this.run(
4216
+ () => {
4217
+ this.store.props.assets.remove?.(ids)
4218
+ this.store.remove(ids)
4219
+ },
4220
+ { history: 'ignore' }
4221
+ )
4222
4222
  return this
4223
4223
  }
4224
4224
 
@@ -6328,21 +6328,22 @@ export class Editor extends EventEmitter<TLEventMap> {
6328
6328
  *
6329
6329
  * @example
6330
6330
  * ```ts
6331
- * editor.stackShapes([box1, box2], 'horizontal', 32)
6332
- * editor.stackShapes(editor.getSelectedShapeIds(), 'horizontal', 32)
6331
+ * editor.stackShapes([box1, box2], 'horizontal')
6332
+ * editor.stackShapes(editor.getSelectedShapeIds(), 'horizontal')
6333
6333
  * ```
6334
6334
  *
6335
6335
  * @param shapes - The shapes (or shape ids) to stack.
6336
6336
  * @param operation - Whether to stack horizontally or vertically.
6337
- * @param gap - The gap to leave between shapes.
6337
+ * @param gap - The gap to leave between shapes. By default, uses the editor's `adjacentShapeMargin` option.
6338
6338
  *
6339
6339
  * @public
6340
6340
  */
6341
6341
  stackShapes(
6342
6342
  shapes: TLShapeId[] | TLShape[],
6343
6343
  operation: 'horizontal' | 'vertical',
6344
- gap: number
6344
+ gap?: number
6345
6345
  ): this {
6346
+ const _gap = gap ?? this.options.adjacentShapeMargin
6346
6347
  const ids =
6347
6348
  typeof shapes[0] === 'string'
6348
6349
  ? (shapes as TLShapeId[])
@@ -6400,7 +6401,7 @@ export class Editor extends EventEmitter<TLEventMap> {
6400
6401
  }
6401
6402
 
6402
6403
  const len = shapeClustersToStack.length
6403
- if ((gap === 0 && len < 3) || len < 2) return this
6404
+ if ((_gap === 0 && len < 3) || len < 2) return this
6404
6405
 
6405
6406
  let val: 'x' | 'y'
6406
6407
  let min: 'minX' | 'minY'
@@ -6421,7 +6422,7 @@ export class Editor extends EventEmitter<TLEventMap> {
6421
6422
 
6422
6423
  let shapeGap: number = 0
6423
6424
 
6424
- if (gap === 0) {
6425
+ if (_gap === 0) {
6425
6426
  // note: this is not used in the current tldraw.com; there we use a specified stack
6426
6427
 
6427
6428
  const gaps: Record<number, number> = {}
@@ -6461,7 +6462,7 @@ export class Editor extends EventEmitter<TLEventMap> {
6461
6462
  }
6462
6463
  } else {
6463
6464
  // If a gap was provided, then use that instead.
6464
- shapeGap = gap
6465
+ shapeGap = _gap
6465
6466
  }
6466
6467
 
6467
6468
  const changes: TLShapePartial[] = []
@@ -6500,17 +6501,19 @@ export class Editor extends EventEmitter<TLEventMap> {
6500
6501
  *
6501
6502
  * @example
6502
6503
  * ```ts
6503
- * editor.packShapes([box1, box2], 32)
6504
+ * editor.packShapes([box1, box2])
6504
6505
  * editor.packShapes(editor.getSelectedShapeIds(), 32)
6505
6506
  * ```
6506
6507
  *
6507
6508
  *
6508
6509
  * @param shapes - The shapes (or shape ids) to pack.
6509
- * @param gap - The padding to apply to the packed shapes. Defaults to 16.
6510
+ * @param gap - The padding to apply to the packed shapes. Defaults to the editor's `adjacentShapeMargin` option.
6510
6511
  */
6511
- packShapes(shapes: TLShapeId[] | TLShape[], gap: number): this {
6512
+ packShapes(shapes: TLShapeId[] | TLShape[], _gap?: number): this {
6512
6513
  if (this.getIsReadonly()) return this
6513
6514
 
6515
+ const gap = _gap ?? this.options.adjacentShapeMargin
6516
+
6514
6517
  const ids =
6515
6518
  typeof shapes[0] === 'string'
6516
6519
  ? (shapes as TLShapeId[])
@@ -8136,8 +8139,18 @@ export class Editor extends EventEmitter<TLEventMap> {
8136
8139
  if (!currentTool) return styles
8137
8140
 
8138
8141
  if (currentTool.shapeType) {
8139
- for (const style of this.styleProps[currentTool.shapeType].keys()) {
8140
- styles.applyValue(style, this.getStyleForNextShape(style))
8142
+ if (
8143
+ currentTool.shapeType === 'frame' &&
8144
+ !(this.getShapeUtil('frame')!.options as any).showColors
8145
+ ) {
8146
+ for (const style of this.styleProps[currentTool.shapeType].keys()) {
8147
+ if (style.id === 'tldraw:color') continue
8148
+ styles.applyValue(style, this.getStyleForNextShape(style))
8149
+ }
8150
+ } else {
8151
+ for (const style of this.styleProps[currentTool.shapeType].keys()) {
8152
+ styles.applyValue(style, this.getStyleForNextShape(style))
8153
+ }
8141
8154
  }
8142
8155
  }
8143
8156
 
@@ -30,6 +30,9 @@ export class FocusManager {
30
30
  editor.updateInstanceState({ isFocused: !!autoFocus })
31
31
  }
32
32
  this.updateContainerClass()
33
+
34
+ document.body.addEventListener('keydown', this.handleKeyDown.bind(this))
35
+ document.body.addEventListener('mousedown', this.handleMouseDown.bind(this))
33
36
  }
34
37
 
35
38
  /**
@@ -50,6 +53,19 @@ export class FocusManager {
50
53
  } else {
51
54
  container.classList.remove('tl-container__focused')
52
55
  }
56
+ container.classList.add('tl-container__no-focus-ring')
57
+ }
58
+
59
+ private handleKeyDown(keyEvent: KeyboardEvent) {
60
+ const container = this.editor.getContainer()
61
+ if (keyEvent.key === 'Tab') {
62
+ container.classList.remove('tl-container__no-focus-ring')
63
+ }
64
+ }
65
+
66
+ private handleMouseDown() {
67
+ const container = this.editor.getContainer()
68
+ container.classList.add('tl-container__no-focus-ring')
53
69
  }
54
70
 
55
71
  focus() {
@@ -62,6 +78,8 @@ export class FocusManager {
62
78
  }
63
79
 
64
80
  dispose() {
81
+ document.body.removeEventListener('keydown', this.handleKeyDown.bind(this))
82
+ document.body.removeEventListener('mousedown', this.handleMouseDown.bind(this))
65
83
  this.disposeSideEffectListener?.()
66
84
  }
67
85
  }
@@ -80,7 +80,7 @@ export class UserPreferencesManager {
80
80
  }
81
81
 
82
82
  @computed getName() {
83
- return this.user.userPreferences.get().name ?? defaultUserPreferences.name
83
+ return this.user.userPreferences.get().name?.trim() ?? defaultUserPreferences.name
84
84
  }
85
85
 
86
86
  @computed getLocale() {
@@ -7,7 +7,12 @@ import {
7
7
  getRenderedChildren,
8
8
  } from './domUtils'
9
9
  import { resourceToDataUrl } from './fetchCache'
10
- import { isPropertyInherited, parseCssValueUrls, shouldIncludeCssProperty } from './parseCss'
10
+ import {
11
+ isPropertyCoveredByCurrentColor,
12
+ isPropertyInherited,
13
+ parseCssValueUrls,
14
+ shouldIncludeCssProperty,
15
+ } from './parseCss'
11
16
 
12
17
  type Styles = { [K in string]?: string }
13
18
  type ReadonlyStyles = { readonly [K in string]?: string }
@@ -53,9 +58,20 @@ export class StyleEmbedder {
53
58
  ? getDefaultStylesForTagName(element.tagName.toLowerCase())
54
59
  : NO_STYLES
55
60
 
56
- const parentStyles = shouldSkipInheritedParentStyles
57
- ? (this.styles.get(element.parentElement as Element)?.self ?? NO_STYLES)
58
- : NO_STYLES
61
+ const parentStyles = Object.assign({}, NO_STYLES) as Styles
62
+ if (shouldSkipInheritedParentStyles) {
63
+ let el = element.parentElement
64
+ // Keep going up the tree to find all the relevant styles
65
+ while (el) {
66
+ const currentStyles = this.styles.get(el)?.self
67
+ for (const style in currentStyles) {
68
+ if (!parentStyles[style]) {
69
+ parentStyles[style] = currentStyles[style]
70
+ }
71
+ }
72
+ el = el.parentElement
73
+ }
74
+ }
59
75
 
60
76
  const info: ElementStyleInfo = {
61
77
  self: styleFromElement(element, { defaultStyles, parentStyles }),
@@ -230,6 +246,8 @@ function styleFromComputedStyleMap(
230
246
 
231
247
  if (defaultStyles[property] === value) continue
232
248
  if (parentStyles[property] === value && isPropertyInherited(property)) continue
249
+ if (isPropertyCoveredByCurrentColor(style.get('color')?.toString() || '', property, value))
250
+ continue
233
251
 
234
252
  styles[property] = value
235
253
  }
@@ -249,6 +267,7 @@ function styleFromComputedStyle(
249
267
 
250
268
  if (defaultStyles[property] === value) continue
251
269
  if (parentStyles[property] === value && isPropertyInherited(property)) continue
270
+ if (isPropertyCoveredByCurrentColor(style.color, property, value)) continue
252
271
 
253
272
  styles[property] = value
254
273
  }
@@ -62,7 +62,7 @@ export async function exportToSvg(
62
62
  const svg = renderTarget.firstElementChild
63
63
  assert(svg instanceof SVGSVGElement, 'Expected an SVG element')
64
64
 
65
- // And apply any changes to <foreignObject> elements that we need to make. Whilst we're in
65
+ // And apply any changes to <foreignObject> elements that we need to make. while we're in
66
66
  // the document, these elements work exactly as we'd expect from other dom elements - they
67
67
  // can load external resources, and any stylesheets in the document apply to them as we
68
68
  // would expect them to. But when we pull the SVG into its own file or draw it to a canvas
@@ -354,7 +354,7 @@ function SvgExport({
354
354
  key: uniqueId(),
355
355
  getElement: async () => {
356
356
  const declaration = await editor.fonts.toEmbeddedCssDeclaration(font)
357
- return <style>{declaration}</style>
357
+ return <style nonce={editor.options.nonce}>{declaration}</style>
358
358
  },
359
359
  })
360
360
  }
@@ -111,11 +111,43 @@ export function parseCssValueUrls(value: string) {
111
111
  }))
112
112
  }
113
113
 
114
+ const currentColorProperties = new Set([
115
+ 'border-block-end-color',
116
+ 'border-block-start-color',
117
+ 'border-bottom-color',
118
+ 'border-inline-end-color',
119
+ 'border-inline-start-color',
120
+ 'border-left-color',
121
+ 'border-right-color',
122
+ 'border-top-color',
123
+ 'caret-color',
124
+ 'column-rule-color',
125
+ 'outline-color',
126
+ 'text-decoration',
127
+ 'text-decoration-color',
128
+ 'text-emphasis-color',
129
+ ])
130
+
131
+ export function isPropertyCoveredByCurrentColor(
132
+ currentColor: string,
133
+ property: string,
134
+ value: string
135
+ ) {
136
+ if (currentColorProperties.has(property)) {
137
+ return (
138
+ value === 'currentColor' ||
139
+ value === currentColor ||
140
+ (property === 'text-decoration' && value === `none solid ${currentColor}`)
141
+ )
142
+ }
143
+ }
144
+
114
145
  const inheritedProperties = new Set([
115
146
  'border-collapse',
116
147
  'border-spacing',
117
148
  'caption-side',
118
- 'color',
149
+ // N.B. We shouldn't inherit 'color' because there's some UA styling, e.g. `mark` elements
150
+ // 'color',
119
151
  'cursor',
120
152
  'direction',
121
153
  'empty-cells',
@@ -136,16 +168,18 @@ const inheritedProperties = new Set([
136
168
  'orphans',
137
169
  'overflow-wrap',
138
170
  'quotes',
171
+ 'stroke-linecap',
172
+ 'stroke-linejoin',
139
173
  'tab-size',
140
174
  'text-align',
141
175
  'text-align-last',
142
- 'text-decoration-color',
143
176
  'text-indent',
144
177
  'text-justify',
145
178
  'text-shadow',
146
179
  'text-transform',
147
180
  'visibility',
148
181
  'white-space',
182
+ 'white-space-collapse',
149
183
  'widows',
150
184
  'word-break',
151
185
  'word-spacing',
@@ -52,6 +52,9 @@ export function useLocalStore(
52
52
 
53
53
  return asset.props.src
54
54
  },
55
+ remove: async (assetIds) => {
56
+ await client.db.removeAssets(assetIds)
57
+ },
55
58
  ...rest.assets,
56
59
  }
57
60
 
@@ -85,6 +85,7 @@ const WatermarkInner = memo(function WatermarkInner({ src }: { src: string }) {
85
85
  })
86
86
 
87
87
  const LicenseStyles = memo(function LicenseStyles() {
88
+ const editor = useEditor()
88
89
  const className = LicenseManager.className
89
90
 
90
91
  const CSS = `/* ------------------- SEE LICENSE -------------------
@@ -156,8 +157,13 @@ To remove the watermark, please purchase a license at tldraw.dev.
156
157
  animation: delayed_link 0.2s forwards ease-in-out;
157
158
  animation-delay: 0.32s;
158
159
  }
160
+
161
+ .${className} > a:focus-visible {
162
+ opacity: 1;
163
+ }
159
164
  }
160
165
 
166
+
161
167
  @keyframes delayed_link {
162
168
  0% {
163
169
  cursor: inherit;
@@ -171,5 +177,5 @@ To remove the watermark, please purchase a license at tldraw.dev.
171
177
  }
172
178
  }`
173
179
 
174
- return <style>{CSS}</style>
180
+ return <style nonce={editor.options.nonce}>{CSS}</style>
175
181
  })
@@ -75,6 +75,11 @@ export interface TldrawOptions {
75
75
  * away and let the fonts load in in the background.
76
76
  */
77
77
  readonly maxFontsToLoadBeforeRender: number
78
+ /**
79
+ * If you have a CSP policy that blocks inline styles, you can use this prop to provide a
80
+ * nonce to use in the editor's styles.
81
+ */
82
+ readonly nonce: string | undefined
78
83
  }
79
84
 
80
85
  /** @public */
@@ -121,4 +126,5 @@ export const defaultTldrawOptions = {
121
126
  exportProvider: Fragment,
122
127
  enableToolbarKeyboardShortcuts: true,
123
128
  maxFontsToLoadBeforeRender: Infinity,
129
+ nonce: undefined,
124
130
  } as const satisfies TldrawOptions
@@ -102,6 +102,6 @@ export class Group2d extends Geometry2d {
102
102
  }
103
103
 
104
104
  getSvgPathData(): string {
105
- return this.children.map((c, i) => (c.isLabel ? '' : c.getSvgPathData(i === 0))).join(' ')
105
+ return this.children.map((c) => (c.isLabel ? '' : c.getSvgPathData(true))).join(' ')
106
106
  }
107
107
  }
@@ -303,6 +303,15 @@ export class LocalIndexedDb {
303
303
  await assetsStore.put(blob, assetId)
304
304
  })
305
305
  }
306
+
307
+ async removeAssets(assetId: string[]) {
308
+ await this.tx('readwrite', [Table.Assets], async (tx) => {
309
+ const assetsStore = tx.objectStore(Table.Assets)
310
+ for (const id of assetId) {
311
+ await assetsStore.delete(id)
312
+ }
313
+ })
314
+ }
306
315
  }
307
316
 
308
317
  /** @internal */
package/src/version.ts CHANGED
@@ -1,9 +1,9 @@
1
1
  // This file is automatically generated by internal/scripts/refresh-assets.ts.
2
2
  // Do not edit manually. Or do, I'm a comment, not a cop.
3
3
 
4
- export const version = '3.11.0-canary.f529c521e249'
4
+ export const version = '3.12.0-canary.10d4563919ca'
5
5
  export const publishDates = {
6
6
  major: '2024-09-13T14:36:29.063Z',
7
- minor: '2025-03-11T14:54:49.451Z',
8
- patch: '2025-03-11T14:54:49.451Z',
7
+ minor: '2025-03-24T14:17:27.684Z',
8
+ patch: '2025-03-24T14:17:27.684Z',
9
9
  }