@tldraw/editor 3.14.0-canary.b477608fafb4 → 3.14.0-canary.b58d09b378a2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist-cjs/index.d.ts +68 -46
- package/dist-cjs/index.js +1 -3
- package/dist-cjs/index.js.map +2 -2
- package/dist-cjs/lib/config/TLSessionStateSnapshot.js +1 -12
- package/dist-cjs/lib/config/TLSessionStateSnapshot.js.map +3 -3
- package/dist-cjs/lib/editor/Editor.js +56 -21
- package/dist-cjs/lib/editor/Editor.js.map +2 -2
- package/dist-cjs/lib/editor/bindings/BindingUtil.js.map +2 -2
- package/dist-cjs/lib/editor/managers/FontManager/FontManager.js +1 -2
- package/dist-cjs/lib/editor/managers/FontManager/FontManager.js.map +2 -2
- package/dist-cjs/lib/editor/managers/TextManager/TextManager.js +73 -42
- package/dist-cjs/lib/editor/managers/TextManager/TextManager.js.map +2 -2
- package/dist-cjs/lib/editor/shapes/group/GroupShapeUtil.js +1 -1
- package/dist-cjs/lib/editor/shapes/group/GroupShapeUtil.js.map +1 -1
- package/dist-cjs/lib/editor/tools/StateNode.js +3 -3
- package/dist-cjs/lib/editor/tools/StateNode.js.map +2 -2
- package/dist-cjs/lib/editor/types/external-content.js.map +1 -1
- package/dist-cjs/lib/hooks/useCanvasEvents.js +1 -2
- package/dist-cjs/lib/hooks/useCanvasEvents.js.map +2 -2
- package/dist-cjs/lib/primitives/Box.js +0 -6
- package/dist-cjs/lib/primitives/Box.js.map +2 -2
- package/dist-cjs/lib/utils/areShapesContentEqual.js +1 -1
- package/dist-cjs/lib/utils/areShapesContentEqual.js.map +2 -2
- package/dist-cjs/lib/utils/richText.js +7 -2
- package/dist-cjs/lib/utils/richText.js.map +2 -2
- package/dist-cjs/version.js +3 -3
- package/dist-cjs/version.js.map +1 -1
- package/dist-esm/index.d.mts +68 -46
- package/dist-esm/index.mjs +1 -3
- package/dist-esm/index.mjs.map +2 -2
- package/dist-esm/lib/config/TLSessionStateSnapshot.mjs +1 -1
- package/dist-esm/lib/config/TLSessionStateSnapshot.mjs.map +2 -2
- package/dist-esm/lib/editor/Editor.mjs +56 -21
- package/dist-esm/lib/editor/Editor.mjs.map +2 -2
- package/dist-esm/lib/editor/bindings/BindingUtil.mjs.map +2 -2
- package/dist-esm/lib/editor/managers/FontManager/FontManager.mjs +1 -2
- package/dist-esm/lib/editor/managers/FontManager/FontManager.mjs.map +2 -2
- package/dist-esm/lib/editor/managers/TextManager/TextManager.mjs +73 -42
- package/dist-esm/lib/editor/managers/TextManager/TextManager.mjs.map +2 -2
- package/dist-esm/lib/editor/shapes/group/GroupShapeUtil.mjs +1 -1
- package/dist-esm/lib/editor/shapes/group/GroupShapeUtil.mjs.map +1 -1
- package/dist-esm/lib/editor/tools/StateNode.mjs +3 -3
- package/dist-esm/lib/editor/tools/StateNode.mjs.map +2 -2
- package/dist-esm/lib/hooks/useCanvasEvents.mjs +1 -2
- package/dist-esm/lib/hooks/useCanvasEvents.mjs.map +2 -2
- package/dist-esm/lib/primitives/Box.mjs +0 -6
- package/dist-esm/lib/primitives/Box.mjs.map +2 -2
- package/dist-esm/lib/utils/areShapesContentEqual.mjs +1 -1
- package/dist-esm/lib/utils/areShapesContentEqual.mjs.map +2 -2
- package/dist-esm/lib/utils/richText.mjs +8 -3
- package/dist-esm/lib/utils/richText.mjs.map +2 -2
- package/dist-esm/version.mjs +3 -3
- package/dist-esm/version.mjs.map +1 -1
- package/editor.css +433 -482
- package/package.json +8 -9
- package/src/index.ts +2 -1
- package/src/lib/config/TLSessionStateSnapshot.ts +1 -1
- package/src/lib/editor/Editor.test.ts +252 -3
- package/src/lib/editor/Editor.ts +55 -18
- package/src/lib/editor/bindings/BindingUtil.ts +6 -0
- package/src/lib/editor/managers/FontManager/FontManager.ts +1 -2
- package/src/lib/editor/managers/TextManager/TextManager.test.ts +1 -5
- package/src/lib/editor/managers/TextManager/TextManager.ts +117 -86
- package/src/lib/editor/shapes/group/GroupShapeUtil.tsx +1 -1
- package/src/lib/editor/tools/StateNode.ts +3 -3
- package/src/lib/editor/types/external-content.ts +11 -2
- package/src/lib/hooks/useCanvasEvents.ts +0 -1
- package/src/lib/primitives/Box.ts +0 -8
- package/src/lib/utils/areShapesContentEqual.ts +1 -2
- package/src/lib/utils/richText.ts +9 -3
- package/src/version.ts +3 -3
|
@@ -20,6 +20,27 @@ const textAlignmentsForLtr = {
|
|
|
20
20
|
'end-legacy': 'right',
|
|
21
21
|
}
|
|
22
22
|
|
|
23
|
+
/** @public */
|
|
24
|
+
export interface TLMeasureTextOpts {
|
|
25
|
+
fontStyle: string
|
|
26
|
+
fontWeight: string
|
|
27
|
+
fontFamily: string
|
|
28
|
+
fontSize: number
|
|
29
|
+
lineHeight: number
|
|
30
|
+
/**
|
|
31
|
+
* When maxWidth is a number, the text will be wrapped to that maxWidth. When maxWidth
|
|
32
|
+
* is null, the text will be measured without wrapping, but explicit line breaks and
|
|
33
|
+
* space are preserved.
|
|
34
|
+
*/
|
|
35
|
+
maxWidth: null | number
|
|
36
|
+
minWidth?: null | number
|
|
37
|
+
// todo: make this a number so that it is consistent with other TLMeasureTextSpanOpts
|
|
38
|
+
padding: string
|
|
39
|
+
otherStyles?: Record<string, string>
|
|
40
|
+
disableOverflowWrapBreaking?: boolean
|
|
41
|
+
measureScrollWidth?: boolean
|
|
42
|
+
}
|
|
43
|
+
|
|
23
44
|
/** @public */
|
|
24
45
|
export interface TLMeasureTextSpanOpts {
|
|
25
46
|
overflow: 'wrap' | 'truncate-ellipsis' | 'truncate-clip'
|
|
@@ -33,96 +54,99 @@ export interface TLMeasureTextSpanOpts {
|
|
|
33
54
|
lineHeight: number
|
|
34
55
|
textAlign: TLDefaultHorizontalAlignStyle
|
|
35
56
|
otherStyles?: Record<string, string>
|
|
57
|
+
measureScrollWidth?: boolean
|
|
36
58
|
}
|
|
37
59
|
|
|
38
60
|
const spaceCharacterRegex = /\s/
|
|
39
61
|
|
|
40
62
|
/** @public */
|
|
41
63
|
export class TextManager {
|
|
42
|
-
private
|
|
64
|
+
private elm: HTMLDivElement
|
|
65
|
+
private defaultStyles: Record<string, string | null>
|
|
43
66
|
|
|
44
67
|
constructor(public editor: Editor) {
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
68
|
+
const elm = document.createElement('div')
|
|
69
|
+
elm.classList.add('tl-text')
|
|
70
|
+
elm.classList.add('tl-text-measure')
|
|
71
|
+
elm.setAttribute('dir', 'auto')
|
|
72
|
+
elm.tabIndex = -1
|
|
73
|
+
this.editor.getContainer().appendChild(elm)
|
|
74
|
+
|
|
75
|
+
// we need to save the default styles so that we can restore them when we're done
|
|
76
|
+
// these must be the css names, not the js names for the styles
|
|
77
|
+
this.defaultStyles = {
|
|
78
|
+
'overflow-wrap': 'break-word',
|
|
79
|
+
'word-break': 'auto',
|
|
80
|
+
width: null,
|
|
81
|
+
height: null,
|
|
82
|
+
'max-width': null,
|
|
83
|
+
'min-width': null,
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
this.elm = elm
|
|
49
87
|
}
|
|
50
88
|
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
/**
|
|
60
|
-
* When maxWidth is a number, the text will be wrapped to that maxWidth. When maxWidth
|
|
61
|
-
* is null, the text will be measured without wrapping, but explicit line breaks and
|
|
62
|
-
* space are preserved.
|
|
63
|
-
*/
|
|
64
|
-
maxWidth: null | number
|
|
65
|
-
minWidth?: null | number
|
|
66
|
-
padding: string
|
|
67
|
-
disableOverflowWrapBreaking?: boolean
|
|
89
|
+
dispose() {
|
|
90
|
+
return this.elm.remove()
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
private resetElmStyles() {
|
|
94
|
+
const { elm, defaultStyles } = this
|
|
95
|
+
for (const key in defaultStyles) {
|
|
96
|
+
elm.style.setProperty(key, defaultStyles[key])
|
|
68
97
|
}
|
|
69
|
-
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
measureText(textToMeasure: string, opts: TLMeasureTextOpts): BoxModel & { scrollWidth: number } {
|
|
70
101
|
const div = document.createElement('div')
|
|
71
102
|
div.textContent = normalizeTextForDom(textToMeasure)
|
|
72
103
|
return this.measureHtml(div.innerHTML, opts)
|
|
73
104
|
}
|
|
74
105
|
|
|
75
|
-
measureHtml(
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
* is null, the text will be measured without wrapping, but explicit line breaks and
|
|
86
|
-
* space are preserved.
|
|
87
|
-
*/
|
|
88
|
-
maxWidth: null | number
|
|
89
|
-
minWidth?: null | number
|
|
90
|
-
otherStyles?: Record<string, string>
|
|
91
|
-
padding: string
|
|
92
|
-
disableOverflowWrapBreaking?: boolean
|
|
106
|
+
measureHtml(html: string, opts: TLMeasureTextOpts): BoxModel & { scrollWidth: number } {
|
|
107
|
+
const { elm } = this
|
|
108
|
+
|
|
109
|
+
if (opts.otherStyles) {
|
|
110
|
+
for (const key in opts.otherStyles) {
|
|
111
|
+
if (!this.defaultStyles[key]) {
|
|
112
|
+
// we need to save the original style so that we can restore it when we're done
|
|
113
|
+
this.defaultStyles[key] = elm.style.getPropertyValue(key)
|
|
114
|
+
}
|
|
115
|
+
}
|
|
93
116
|
}
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
+
|
|
118
|
+
elm.innerHTML = html
|
|
119
|
+
|
|
120
|
+
// Apply the default styles to the element (for all styles here or that were ever seen in opts.otherStyles)
|
|
121
|
+
this.resetElmStyles()
|
|
122
|
+
|
|
123
|
+
elm.style.setProperty('font-family', opts.fontFamily)
|
|
124
|
+
elm.style.setProperty('font-style', opts.fontStyle)
|
|
125
|
+
elm.style.setProperty('font-weight', opts.fontWeight)
|
|
126
|
+
elm.style.setProperty('font-size', opts.fontSize + 'px')
|
|
127
|
+
elm.style.setProperty('line-height', opts.lineHeight * opts.fontSize + 'px')
|
|
128
|
+
elm.style.setProperty('padding', opts.padding)
|
|
129
|
+
|
|
130
|
+
if (opts.maxWidth) {
|
|
131
|
+
elm.style.setProperty('max-width', opts.maxWidth + 'px')
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
if (opts.minWidth) {
|
|
135
|
+
elm.style.setProperty('min-width', opts.minWidth + 'px')
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
if (opts.disableOverflowWrapBreaking) {
|
|
139
|
+
elm.style.setProperty('overflow-wrap', 'normal')
|
|
140
|
+
}
|
|
141
|
+
|
|
117
142
|
if (opts.otherStyles) {
|
|
118
143
|
for (const [key, value] of Object.entries(opts.otherStyles)) {
|
|
119
|
-
|
|
144
|
+
elm.style.setProperty(key, value)
|
|
120
145
|
}
|
|
121
146
|
}
|
|
122
147
|
|
|
123
|
-
const scrollWidth =
|
|
124
|
-
const rect =
|
|
125
|
-
wrapperElm.remove()
|
|
148
|
+
const scrollWidth = opts.measureScrollWidth ? elm.scrollWidth : 0
|
|
149
|
+
const rect = elm.getBoundingClientRect()
|
|
126
150
|
|
|
127
151
|
return {
|
|
128
152
|
x: 0,
|
|
@@ -247,27 +271,29 @@ export class TextManager {
|
|
|
247
271
|
): { text: string; box: BoxModel }[] {
|
|
248
272
|
if (textToMeasure === '') return []
|
|
249
273
|
|
|
250
|
-
const elm = this
|
|
251
|
-
|
|
274
|
+
const { elm } = this
|
|
275
|
+
|
|
276
|
+
if (opts.otherStyles) {
|
|
277
|
+
for (const key in opts.otherStyles) {
|
|
278
|
+
if (!this.defaultStyles[key]) {
|
|
279
|
+
// we need to save the original style so that we can restore it when we're done
|
|
280
|
+
this.defaultStyles[key] = elm.style.getPropertyValue(key)
|
|
281
|
+
}
|
|
282
|
+
}
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
this.resetElmStyles()
|
|
286
|
+
|
|
287
|
+
elm.style.setProperty('font-family', opts.fontFamily)
|
|
288
|
+
elm.style.setProperty('font-style', opts.fontStyle)
|
|
289
|
+
elm.style.setProperty('font-weight', opts.fontWeight)
|
|
290
|
+
elm.style.setProperty('font-size', opts.fontSize + 'px')
|
|
291
|
+
elm.style.setProperty('line-height', opts.lineHeight * opts.fontSize + 'px')
|
|
252
292
|
|
|
253
293
|
const elementWidth = Math.ceil(opts.width - opts.padding * 2)
|
|
254
|
-
elm.setAttribute('dir', 'auto')
|
|
255
|
-
// N.B. This property, while discouraged ("intended for Document Type Definition (DTD) designers")
|
|
256
|
-
// is necessary for ensuring correct mixed RTL/LTR behavior when exporting SVGs.
|
|
257
|
-
elm.style.setProperty('unicode-bidi', 'plaintext')
|
|
258
294
|
elm.style.setProperty('width', `${elementWidth}px`)
|
|
259
295
|
elm.style.setProperty('height', 'min-content')
|
|
260
|
-
elm.style.setProperty('font-size', `${opts.fontSize}px`)
|
|
261
|
-
elm.style.setProperty('font-family', opts.fontFamily)
|
|
262
|
-
elm.style.setProperty('font-weight', opts.fontWeight)
|
|
263
|
-
elm.style.setProperty('line-height', `${opts.lineHeight * opts.fontSize}px`)
|
|
264
296
|
elm.style.setProperty('text-align', textAlignmentsForLtr[opts.textAlign])
|
|
265
|
-
elm.style.setProperty('font-style', opts.fontStyle)
|
|
266
|
-
if (opts.otherStyles) {
|
|
267
|
-
for (const [key, value] of Object.entries(opts.otherStyles)) {
|
|
268
|
-
elm.style.setProperty(key, value)
|
|
269
|
-
}
|
|
270
|
-
}
|
|
271
297
|
|
|
272
298
|
const shouldTruncateToFirstLine =
|
|
273
299
|
opts.overflow === 'truncate-ellipsis' || opts.overflow === 'truncate-clip'
|
|
@@ -277,6 +303,12 @@ export class TextManager {
|
|
|
277
303
|
elm.style.setProperty('word-break', 'break-all')
|
|
278
304
|
}
|
|
279
305
|
|
|
306
|
+
if (opts.otherStyles) {
|
|
307
|
+
for (const [key, value] of Object.entries(opts.otherStyles)) {
|
|
308
|
+
elm.style.setProperty(key, value)
|
|
309
|
+
}
|
|
310
|
+
}
|
|
311
|
+
|
|
280
312
|
const normalizedText = normalizeTextForDom(textToMeasure)
|
|
281
313
|
|
|
282
314
|
// Render the text into the measurement element:
|
|
@@ -313,11 +345,10 @@ export class TextManager {
|
|
|
313
345
|
h: lastSpan.box.h,
|
|
314
346
|
},
|
|
315
347
|
})
|
|
348
|
+
|
|
316
349
|
return truncatedSpans
|
|
317
350
|
}
|
|
318
351
|
|
|
319
|
-
elm.remove()
|
|
320
|
-
|
|
321
352
|
return spans
|
|
322
353
|
}
|
|
323
354
|
}
|
|
@@ -206,15 +206,15 @@ export abstract class StateNode implements Partial<TLEventHandlers> {
|
|
|
206
206
|
}
|
|
207
207
|
|
|
208
208
|
// todo: move this logic into transition
|
|
209
|
-
exit(info: any,
|
|
209
|
+
exit(info: any, to: string) {
|
|
210
210
|
if (debugFlags.measurePerformance.get() && this.performanceTracker.isStarted()) {
|
|
211
211
|
this.performanceTracker.stop()
|
|
212
212
|
}
|
|
213
213
|
this._isActive.set(false)
|
|
214
|
-
this.onExit?.(info,
|
|
214
|
+
this.onExit?.(info, to)
|
|
215
215
|
|
|
216
216
|
if (!this.getIsActive()) {
|
|
217
|
-
this.getCurrent()?.exit(info,
|
|
217
|
+
this.getCurrent()?.exit(info, to)
|
|
218
218
|
}
|
|
219
219
|
}
|
|
220
220
|
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { TLAssetId } from '@tldraw/tlschema'
|
|
1
|
+
import { TLAssetId, TLShapeId } from '@tldraw/tlschema'
|
|
2
2
|
import { VecLike } from '../../primitives/Vec'
|
|
3
3
|
import { TLContent } from './clipboard-types'
|
|
4
4
|
|
|
@@ -52,7 +52,15 @@ export interface TLTextExternalContent extends TLBaseExternalContent {
|
|
|
52
52
|
export interface TLFilesExternalContent extends TLBaseExternalContent {
|
|
53
53
|
type: 'files'
|
|
54
54
|
files: File[]
|
|
55
|
-
ignoreParent
|
|
55
|
+
ignoreParent?: boolean
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
/** @public */
|
|
59
|
+
export interface TLFileReplaceExternalContent extends TLBaseExternalContent {
|
|
60
|
+
type: 'file-replace'
|
|
61
|
+
file: File
|
|
62
|
+
shapeId: TLShapeId
|
|
63
|
+
isImage: boolean
|
|
56
64
|
}
|
|
57
65
|
|
|
58
66
|
/** @public */
|
|
@@ -90,6 +98,7 @@ export interface TLExcalidrawExternalContent extends TLBaseExternalContent {
|
|
|
90
98
|
export type TLExternalContent<EmbedDefinition> =
|
|
91
99
|
| TLTextExternalContent
|
|
92
100
|
| TLFilesExternalContent
|
|
101
|
+
| TLFileReplaceExternalContent
|
|
93
102
|
| TLUrlExternalContent
|
|
94
103
|
| TLSvgTextExternalContent
|
|
95
104
|
| TLEmbedExternalContent<EmbedDefinition>
|
|
@@ -591,14 +591,6 @@ export class Box {
|
|
|
591
591
|
return b.x === a.x && b.y === a.y && b.w === a.w && b.h === a.h
|
|
592
592
|
}
|
|
593
593
|
|
|
594
|
-
prettyMuchEquals(other: Box | BoxModel) {
|
|
595
|
-
return this.clone().toFixed().equals(Box.From(other).toFixed())
|
|
596
|
-
}
|
|
597
|
-
|
|
598
|
-
static PrettyMuchEquals(a: Box | BoxModel, b: Box | BoxModel) {
|
|
599
|
-
return b.x === a.x && b.y === a.y && b.w === a.w && b.h === a.h
|
|
600
|
-
}
|
|
601
|
-
|
|
602
594
|
zeroFix() {
|
|
603
595
|
this.w = Math.max(1, this.w)
|
|
604
596
|
this.h = Math.max(1, this.h)
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { getSchema, JSONContent, Editor as TTEditor } from '@tiptap/core'
|
|
2
|
-
import { Node } from '@tiptap/pm/model'
|
|
2
|
+
import { Node, Schema } from '@tiptap/pm/model'
|
|
3
3
|
import { EditorProviderProps } from '@tiptap/react'
|
|
4
4
|
import { TLRichText } from '@tldraw/tlschema'
|
|
5
|
-
import { assert } from '@tldraw/utils'
|
|
5
|
+
import { assert, WeakCache } from '@tldraw/utils'
|
|
6
6
|
import { Editor } from '../editor/Editor'
|
|
7
7
|
import { TLFontFace } from '../editor/managers/FontManager/FontManager'
|
|
8
8
|
|
|
@@ -39,6 +39,11 @@ export type RichTextFontVisitor = (
|
|
|
39
39
|
addFont: (font: TLFontFace) => void
|
|
40
40
|
) => RichTextFontVisitorState
|
|
41
41
|
|
|
42
|
+
const schemaCache = new WeakCache<EditorProviderProps, Schema>()
|
|
43
|
+
export function getTipTapSchema(tipTapConfig: EditorProviderProps) {
|
|
44
|
+
return schemaCache.get(tipTapConfig, () => getSchema(tipTapConfig.extensions ?? []))
|
|
45
|
+
}
|
|
46
|
+
|
|
42
47
|
/** @public */
|
|
43
48
|
export function getFontsFromRichText(
|
|
44
49
|
editor: Editor,
|
|
@@ -49,7 +54,8 @@ export function getFontsFromRichText(
|
|
|
49
54
|
assert(tipTapConfig, 'textOptions.tipTapConfig must be set to use rich text')
|
|
50
55
|
assert(addFontsFromNode, 'textOptions.addFontsFromNode must be set to use rich text')
|
|
51
56
|
|
|
52
|
-
const schema =
|
|
57
|
+
const schema = getTipTapSchema(tipTapConfig)
|
|
58
|
+
|
|
53
59
|
const rootNode = Node.fromJSON(schema, richText as JSONContent)
|
|
54
60
|
|
|
55
61
|
const fonts = new Set<TLFontFace>()
|
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.14.0-canary.
|
|
4
|
+
export const version = '3.14.0-canary.b58d09b378a2'
|
|
5
5
|
export const publishDates = {
|
|
6
6
|
major: '2024-09-13T14:36:29.063Z',
|
|
7
|
-
minor: '2025-06-
|
|
8
|
-
patch: '2025-06-
|
|
7
|
+
minor: '2025-06-23T08:34:38.965Z',
|
|
8
|
+
patch: '2025-06-23T08:34:38.965Z',
|
|
9
9
|
}
|