@tldraw/editor 3.10.3 → 3.11.0-canary.03a8f07c67a3
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/CHANGELOG.md +2 -23
- package/dist-cjs/index.d.ts +24 -10
- package/dist-cjs/index.js +1 -1
- package/dist-cjs/index.js.map +2 -2
- package/dist-cjs/lib/components/default-components/DefaultShapeIndicator.js +4 -4
- package/dist-cjs/lib/components/default-components/DefaultShapeIndicator.js.map +2 -2
- package/dist-cjs/lib/components/default-components/DefaultShapeIndicators.js +34 -26
- package/dist-cjs/lib/components/default-components/DefaultShapeIndicators.js.map +2 -2
- package/dist-cjs/lib/config/TLUserPreferences.js +1 -1
- package/dist-cjs/lib/config/TLUserPreferences.js.map +1 -1
- package/dist-cjs/lib/config/createTLStore.js +2 -1
- package/dist-cjs/lib/config/createTLStore.js.map +2 -2
- package/dist-cjs/lib/constants.js +1 -1
- package/dist-cjs/lib/constants.js.map +2 -2
- package/dist-cjs/lib/editor/Editor.js +18 -10
- package/dist-cjs/lib/editor/Editor.js.map +2 -2
- package/dist-cjs/lib/editor/managers/FocusManager.js +15 -0
- package/dist-cjs/lib/editor/managers/FocusManager.js.map +2 -2
- package/dist-cjs/lib/editor/managers/UserPreferencesManager.js +1 -1
- package/dist-cjs/lib/editor/managers/UserPreferencesManager.js.map +2 -2
- package/dist-cjs/lib/exports/exportToSvg.js.map +1 -1
- package/dist-cjs/lib/exports/getSvgJsx.js +1 -1
- package/dist-cjs/lib/exports/getSvgJsx.js.map +2 -2
- package/dist-cjs/lib/hooks/useLocalStore.js +3 -0
- package/dist-cjs/lib/hooks/useLocalStore.js.map +2 -2
- package/dist-cjs/lib/license/Watermark.js +7 -1
- package/dist-cjs/lib/license/Watermark.js.map +2 -2
- package/dist-cjs/lib/options.js +2 -1
- package/dist-cjs/lib/options.js.map +2 -2
- package/dist-cjs/lib/utils/sync/LocalIndexedDb.js +8 -0
- package/dist-cjs/lib/utils/sync/LocalIndexedDb.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 +24 -10
- package/dist-esm/index.mjs +4 -2
- package/dist-esm/index.mjs.map +2 -2
- package/dist-esm/lib/components/default-components/DefaultShapeIndicator.mjs +4 -4
- package/dist-esm/lib/components/default-components/DefaultShapeIndicator.mjs.map +2 -2
- package/dist-esm/lib/components/default-components/DefaultShapeIndicators.mjs +34 -26
- package/dist-esm/lib/components/default-components/DefaultShapeIndicators.mjs.map +2 -2
- package/dist-esm/lib/config/TLUserPreferences.mjs +1 -1
- package/dist-esm/lib/config/TLUserPreferences.mjs.map +1 -1
- package/dist-esm/lib/config/createTLStore.mjs +2 -1
- package/dist-esm/lib/config/createTLStore.mjs.map +2 -2
- package/dist-esm/lib/constants.mjs +1 -1
- package/dist-esm/lib/constants.mjs.map +2 -2
- package/dist-esm/lib/editor/Editor.mjs +18 -10
- package/dist-esm/lib/editor/Editor.mjs.map +2 -2
- package/dist-esm/lib/editor/managers/FocusManager.mjs +15 -0
- package/dist-esm/lib/editor/managers/FocusManager.mjs.map +2 -2
- package/dist-esm/lib/editor/managers/UserPreferencesManager.mjs +1 -1
- package/dist-esm/lib/editor/managers/UserPreferencesManager.mjs.map +2 -2
- package/dist-esm/lib/exports/exportToSvg.mjs.map +1 -1
- package/dist-esm/lib/exports/getSvgJsx.mjs +1 -1
- package/dist-esm/lib/exports/getSvgJsx.mjs.map +2 -2
- package/dist-esm/lib/hooks/useLocalStore.mjs +3 -0
- package/dist-esm/lib/hooks/useLocalStore.mjs.map +2 -2
- package/dist-esm/lib/license/Watermark.mjs +7 -1
- package/dist-esm/lib/license/Watermark.mjs.map +2 -2
- package/dist-esm/lib/options.mjs +2 -1
- package/dist-esm/lib/options.mjs.map +2 -2
- package/dist-esm/lib/utils/sync/LocalIndexedDb.mjs +8 -0
- package/dist-esm/lib/utils/sync/LocalIndexedDb.mjs.map +2 -2
- package/dist-esm/version.mjs +3 -3
- package/dist-esm/version.mjs.map +1 -1
- package/editor.css +1 -1
- package/package.json +10 -7
- package/src/index.ts +4 -1
- package/src/lib/components/default-components/DefaultShapeIndicator.tsx +4 -4
- package/src/lib/components/default-components/DefaultShapeIndicators.tsx +52 -31
- package/src/lib/config/TLUserPreferences.ts +1 -1
- package/src/lib/config/createTLStore.ts +1 -0
- package/src/lib/constants.ts +1 -1
- package/src/lib/editor/Editor.ts +21 -12
- package/src/lib/editor/managers/FocusManager.ts +18 -0
- package/src/lib/editor/managers/UserPreferencesManager.ts +1 -1
- package/src/lib/exports/exportToSvg.tsx +1 -1
- package/src/lib/exports/getSvgJsx.tsx +1 -1
- package/src/lib/hooks/useLocalStore.ts +3 -0
- package/src/lib/license/Watermark.tsx +7 -1
- package/src/lib/options.ts +6 -0
- package/src/lib/utils/sync/LocalIndexedDb.ts +9 -0
- package/src/version.ts +3 -3
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tldraw/editor",
|
|
3
3
|
"description": "A tiny little drawing app (editor).",
|
|
4
|
-
"version": "3.
|
|
4
|
+
"version": "3.11.0-canary.03a8f07c67a3",
|
|
5
5
|
"author": {
|
|
6
6
|
"name": "tldraw Inc.",
|
|
7
7
|
"email": "hello@tldraw.com"
|
|
@@ -48,12 +48,12 @@
|
|
|
48
48
|
"@tiptap/core": "^2.9.1",
|
|
49
49
|
"@tiptap/pm": "^2.9.1",
|
|
50
50
|
"@tiptap/react": "^2.9.1",
|
|
51
|
-
"@tldraw/state": "3.
|
|
52
|
-
"@tldraw/state-react": "3.
|
|
53
|
-
"@tldraw/store": "3.
|
|
54
|
-
"@tldraw/tlschema": "3.
|
|
55
|
-
"@tldraw/utils": "3.
|
|
56
|
-
"@tldraw/validate": "3.
|
|
51
|
+
"@tldraw/state": "3.11.0-canary.03a8f07c67a3",
|
|
52
|
+
"@tldraw/state-react": "3.11.0-canary.03a8f07c67a3",
|
|
53
|
+
"@tldraw/store": "3.11.0-canary.03a8f07c67a3",
|
|
54
|
+
"@tldraw/tlschema": "3.11.0-canary.03a8f07c67a3",
|
|
55
|
+
"@tldraw/utils": "3.11.0-canary.03a8f07c67a3",
|
|
56
|
+
"@tldraw/validate": "3.11.0-canary.03a8f07c67a3",
|
|
57
57
|
"@types/core-js": "^2.5.8",
|
|
58
58
|
"@use-gesture/react": "^10.3.1",
|
|
59
59
|
"classnames": "^2.5.1",
|
|
@@ -72,12 +72,15 @@
|
|
|
72
72
|
"@testing-library/jest-dom": "^5.17.0",
|
|
73
73
|
"@testing-library/react": "^15.0.7",
|
|
74
74
|
"@types/benchmark": "^2.1.5",
|
|
75
|
+
"@types/react": "^18.3.18",
|
|
75
76
|
"@types/wicg-file-system-access": "^2020.9.8",
|
|
76
77
|
"benchmark": "^2.1.4",
|
|
77
78
|
"fake-indexeddb": "^4.0.2",
|
|
78
79
|
"jest-canvas-mock": "^2.5.2",
|
|
79
80
|
"jest-environment-jsdom": "^29.7.0",
|
|
80
81
|
"lazyrepo": "0.0.0-alpha.27",
|
|
82
|
+
"react": "^18.3.1",
|
|
83
|
+
"react-dom": "^18.3.1",
|
|
81
84
|
"resize-observer-polyfill": "^1.5.1"
|
|
82
85
|
},
|
|
83
86
|
"jest": {
|
package/src/index.ts
CHANGED
|
@@ -109,7 +109,10 @@ export {
|
|
|
109
109
|
type TLShapeIndicatorProps,
|
|
110
110
|
} from './lib/components/default-components/DefaultShapeIndicator'
|
|
111
111
|
export { type TLShapeIndicatorErrorFallbackComponent } from './lib/components/default-components/DefaultShapeIndicatorErrorFallback'
|
|
112
|
-
export {
|
|
112
|
+
export {
|
|
113
|
+
DefaultShapeIndicators,
|
|
114
|
+
type TLShapeIndicatorsProps,
|
|
115
|
+
} from './lib/components/default-components/DefaultShapeIndicators'
|
|
113
116
|
export {
|
|
114
117
|
DefaultSnapIndicator,
|
|
115
118
|
type TLSnapIndicatorProps,
|
|
@@ -9,15 +9,15 @@ import { useEditorComponents } from '../../hooks/useEditorComponents'
|
|
|
9
9
|
import { OptionalErrorBoundary } from '../ErrorBoundary'
|
|
10
10
|
|
|
11
11
|
// need an extra layer of indirection here to allow hooks to be used inside the indicator render
|
|
12
|
-
const EvenInnererIndicator = ({ shape, util }: { shape: TLShape; util: ShapeUtil<any> }) => {
|
|
12
|
+
const EvenInnererIndicator = memo(({ shape, util }: { shape: TLShape; util: ShapeUtil<any> }) => {
|
|
13
13
|
return useStateTracking('Indicator: ' + shape.type, () =>
|
|
14
14
|
// always fetch the latest shape from the store even if the props/meta have not changed, to avoid
|
|
15
15
|
// calling the render method with stale data.
|
|
16
16
|
util.indicator(util.editor.store.unsafeGetWithoutCapture(shape.id) as TLShape)
|
|
17
17
|
)
|
|
18
|
-
}
|
|
18
|
+
})
|
|
19
19
|
|
|
20
|
-
const InnerIndicator = ({ editor, id }: { editor: Editor; id: TLShapeId }) => {
|
|
20
|
+
const InnerIndicator = memo(({ editor, id }: { editor: Editor; id: TLShapeId }) => {
|
|
21
21
|
const shape = useValue('shape for indicator', () => editor.store.get(id), [editor, id])
|
|
22
22
|
|
|
23
23
|
const { ShapeIndicatorErrorFallback } = useEditorComponents()
|
|
@@ -34,7 +34,7 @@ const InnerIndicator = ({ editor, id }: { editor: Editor; id: TLShapeId }) => {
|
|
|
34
34
|
<EvenInnererIndicator key={shape.id} shape={shape} util={editor.getShapeUtil(shape)} />
|
|
35
35
|
</OptionalErrorBoundary>
|
|
36
36
|
)
|
|
37
|
-
}
|
|
37
|
+
})
|
|
38
38
|
|
|
39
39
|
/** @public */
|
|
40
40
|
export interface TLShapeIndicatorProps {
|
|
@@ -4,10 +4,24 @@ import { memo, useRef } from 'react'
|
|
|
4
4
|
import { useEditor } from '../../hooks/useEditor'
|
|
5
5
|
import { useEditorComponents } from '../../hooks/useEditorComponents'
|
|
6
6
|
|
|
7
|
+
/** @public */
|
|
8
|
+
export interface TLShapeIndicatorsProps {
|
|
9
|
+
/** Whether to hide all of the indicators */
|
|
10
|
+
hideAll?: boolean
|
|
11
|
+
/** Whether to show all of the indicators */
|
|
12
|
+
showAll?: boolean
|
|
13
|
+
}
|
|
14
|
+
|
|
7
15
|
/** @public @react */
|
|
8
|
-
export const DefaultShapeIndicators = memo(function DefaultShapeIndicators(
|
|
16
|
+
export const DefaultShapeIndicators = memo(function DefaultShapeIndicators({
|
|
17
|
+
hideAll,
|
|
18
|
+
showAll,
|
|
19
|
+
}: TLShapeIndicatorsProps) {
|
|
9
20
|
const editor = useEditor()
|
|
10
21
|
|
|
22
|
+
if (hideAll && showAll)
|
|
23
|
+
throw Error('You cannot set both hideAll and showAll props to true, cmon now')
|
|
24
|
+
|
|
11
25
|
const rPreviousSelectedShapeIds = useRef<Set<TLShapeId>>(new Set())
|
|
12
26
|
|
|
13
27
|
const idsToDisplay = useValue(
|
|
@@ -16,34 +30,38 @@ export const DefaultShapeIndicators = memo(function DefaultShapeIndicators() {
|
|
|
16
30
|
const prev = rPreviousSelectedShapeIds.current
|
|
17
31
|
const next = new Set<TLShapeId>()
|
|
18
32
|
|
|
19
|
-
|
|
20
|
-
// We only show indicators when in the following states...
|
|
21
|
-
editor.isInAny(
|
|
22
|
-
'select.idle',
|
|
23
|
-
'select.brushing',
|
|
24
|
-
'select.scribble_brushing',
|
|
25
|
-
'select.editing_shape',
|
|
26
|
-
'select.pointing_shape',
|
|
27
|
-
'select.pointing_selection',
|
|
28
|
-
'select.pointing_handle'
|
|
29
|
-
) &&
|
|
30
|
-
// ...but we hide indicators when we've just changed a style (so that the user can see the change)
|
|
31
|
-
!editor.getInstanceState().isChangingStyle
|
|
32
|
-
) {
|
|
33
|
-
// We always want to show indicators for the selected shapes, if any
|
|
34
|
-
const selected = editor.getSelectedShapeIds()
|
|
35
|
-
for (const id of selected) {
|
|
36
|
-
next.add(id)
|
|
37
|
-
}
|
|
33
|
+
const instanceState = editor.getInstanceState()
|
|
38
34
|
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
35
|
+
const isChangingStyle = instanceState.isChangingStyle
|
|
36
|
+
|
|
37
|
+
// todo: this is tldraw specific and is duplicated at the tldraw layer. What should we do here instead?
|
|
38
|
+
|
|
39
|
+
const isIdleOrEditing = editor.isInAny('select.idle', 'select.editing_shape')
|
|
40
|
+
|
|
41
|
+
const isInSelectState = editor.isInAny(
|
|
42
|
+
'select.brushing',
|
|
43
|
+
'select.scribble_brushing',
|
|
44
|
+
'select.pointing_shape',
|
|
45
|
+
'select.pointing_selection',
|
|
46
|
+
'select.pointing_handle'
|
|
47
|
+
)
|
|
48
|
+
|
|
49
|
+
// We hide all indicators if we're changing style or in certain interactions
|
|
50
|
+
// todo: move this to some kind of Tool.hideIndicators property
|
|
51
|
+
if (isChangingStyle || !(isIdleOrEditing || isInSelectState)) {
|
|
52
|
+
rPreviousSelectedShapeIds.current = next
|
|
53
|
+
return next
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
// We always want to show indicators for the selected shapes, if any
|
|
57
|
+
for (const id of editor.getSelectedShapeIds()) {
|
|
58
|
+
next.add(id)
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
// If we're idle or editing a shape, we want to also show an indicator for the hovered shape, if any
|
|
62
|
+
if (isIdleOrEditing && instanceState.isHoveringCanvas && !instanceState.isCoarsePointer) {
|
|
63
|
+
const hovered = editor.getHoveredShapeId()
|
|
64
|
+
if (hovered) next.add(hovered)
|
|
47
65
|
}
|
|
48
66
|
|
|
49
67
|
// Ok, has anything changed?
|
|
@@ -54,7 +72,7 @@ export const DefaultShapeIndicators = memo(function DefaultShapeIndicators() {
|
|
|
54
72
|
return next
|
|
55
73
|
}
|
|
56
74
|
|
|
57
|
-
//
|
|
75
|
+
// Set difference check
|
|
58
76
|
for (const id of next) {
|
|
59
77
|
if (!prev.has(id)) {
|
|
60
78
|
rPreviousSelectedShapeIds.current = next
|
|
@@ -62,7 +80,6 @@ export const DefaultShapeIndicators = memo(function DefaultShapeIndicators() {
|
|
|
62
80
|
}
|
|
63
81
|
}
|
|
64
82
|
|
|
65
|
-
// If nothing has changed, then return the previous value
|
|
66
83
|
return prev
|
|
67
84
|
},
|
|
68
85
|
[editor]
|
|
@@ -75,6 +92,10 @@ export const DefaultShapeIndicators = memo(function DefaultShapeIndicators() {
|
|
|
75
92
|
if (!ShapeIndicator) return null
|
|
76
93
|
|
|
77
94
|
return renderingShapes.map(({ id }) => (
|
|
78
|
-
<ShapeIndicator
|
|
95
|
+
<ShapeIndicator
|
|
96
|
+
key={id + '_indicator'}
|
|
97
|
+
shapeId={id}
|
|
98
|
+
hidden={!showAll && (hideAll || !idsToDisplay.has(id))}
|
|
99
|
+
/>
|
|
79
100
|
))
|
|
80
101
|
})
|
package/src/lib/constants.ts
CHANGED
package/src/lib/editor/Editor.ts
CHANGED
|
@@ -4218,7 +4218,13 @@ export class Editor extends EventEmitter<TLEventMap> {
|
|
|
4218
4218
|
: (assets as TLAsset[]).map((a) => a.id)
|
|
4219
4219
|
if (ids.length <= 0) return this
|
|
4220
4220
|
|
|
4221
|
-
this.run(
|
|
4221
|
+
this.run(
|
|
4222
|
+
() => {
|
|
4223
|
+
this.store.props.assets.remove?.(ids)
|
|
4224
|
+
this.store.remove(ids)
|
|
4225
|
+
},
|
|
4226
|
+
{ history: 'ignore' }
|
|
4227
|
+
)
|
|
4222
4228
|
return this
|
|
4223
4229
|
}
|
|
4224
4230
|
|
|
@@ -5610,7 +5616,7 @@ export class Editor extends EventEmitter<TLEventMap> {
|
|
|
5610
5616
|
* Create bindings from a list of partial bindings. You can omit the ID and most props of a
|
|
5611
5617
|
* binding, but the `type`, `toId`, and `fromId` must all be provided.
|
|
5612
5618
|
*/
|
|
5613
|
-
createBindings(partials: TLBindingCreate[]) {
|
|
5619
|
+
createBindings<B extends TLBinding = TLBinding>(partials: TLBindingCreate<B>[]) {
|
|
5614
5620
|
const bindings: TLBinding[] = []
|
|
5615
5621
|
for (const partial of partials) {
|
|
5616
5622
|
const fromShape = this.getShape(partial.fromId)
|
|
@@ -6328,21 +6334,22 @@ export class Editor extends EventEmitter<TLEventMap> {
|
|
|
6328
6334
|
*
|
|
6329
6335
|
* @example
|
|
6330
6336
|
* ```ts
|
|
6331
|
-
* editor.stackShapes([box1, box2], 'horizontal'
|
|
6332
|
-
* editor.stackShapes(editor.getSelectedShapeIds(), 'horizontal'
|
|
6337
|
+
* editor.stackShapes([box1, box2], 'horizontal')
|
|
6338
|
+
* editor.stackShapes(editor.getSelectedShapeIds(), 'horizontal')
|
|
6333
6339
|
* ```
|
|
6334
6340
|
*
|
|
6335
6341
|
* @param shapes - The shapes (or shape ids) to stack.
|
|
6336
6342
|
* @param operation - Whether to stack horizontally or vertically.
|
|
6337
|
-
* @param gap - The gap to leave between shapes.
|
|
6343
|
+
* @param gap - The gap to leave between shapes. By default, uses the editor's `adjacentShapeMargin` option.
|
|
6338
6344
|
*
|
|
6339
6345
|
* @public
|
|
6340
6346
|
*/
|
|
6341
6347
|
stackShapes(
|
|
6342
6348
|
shapes: TLShapeId[] | TLShape[],
|
|
6343
6349
|
operation: 'horizontal' | 'vertical',
|
|
6344
|
-
gap
|
|
6350
|
+
gap?: number
|
|
6345
6351
|
): this {
|
|
6352
|
+
const _gap = gap ?? this.options.adjacentShapeMargin
|
|
6346
6353
|
const ids =
|
|
6347
6354
|
typeof shapes[0] === 'string'
|
|
6348
6355
|
? (shapes as TLShapeId[])
|
|
@@ -6400,7 +6407,7 @@ export class Editor extends EventEmitter<TLEventMap> {
|
|
|
6400
6407
|
}
|
|
6401
6408
|
|
|
6402
6409
|
const len = shapeClustersToStack.length
|
|
6403
|
-
if ((
|
|
6410
|
+
if ((_gap === 0 && len < 3) || len < 2) return this
|
|
6404
6411
|
|
|
6405
6412
|
let val: 'x' | 'y'
|
|
6406
6413
|
let min: 'minX' | 'minY'
|
|
@@ -6421,7 +6428,7 @@ export class Editor extends EventEmitter<TLEventMap> {
|
|
|
6421
6428
|
|
|
6422
6429
|
let shapeGap: number = 0
|
|
6423
6430
|
|
|
6424
|
-
if (
|
|
6431
|
+
if (_gap === 0) {
|
|
6425
6432
|
// note: this is not used in the current tldraw.com; there we use a specified stack
|
|
6426
6433
|
|
|
6427
6434
|
const gaps: Record<number, number> = {}
|
|
@@ -6461,7 +6468,7 @@ export class Editor extends EventEmitter<TLEventMap> {
|
|
|
6461
6468
|
}
|
|
6462
6469
|
} else {
|
|
6463
6470
|
// If a gap was provided, then use that instead.
|
|
6464
|
-
shapeGap =
|
|
6471
|
+
shapeGap = _gap
|
|
6465
6472
|
}
|
|
6466
6473
|
|
|
6467
6474
|
const changes: TLShapePartial[] = []
|
|
@@ -6500,17 +6507,19 @@ export class Editor extends EventEmitter<TLEventMap> {
|
|
|
6500
6507
|
*
|
|
6501
6508
|
* @example
|
|
6502
6509
|
* ```ts
|
|
6503
|
-
* editor.packShapes([box1, box2]
|
|
6510
|
+
* editor.packShapes([box1, box2])
|
|
6504
6511
|
* editor.packShapes(editor.getSelectedShapeIds(), 32)
|
|
6505
6512
|
* ```
|
|
6506
6513
|
*
|
|
6507
6514
|
*
|
|
6508
6515
|
* @param shapes - The shapes (or shape ids) to pack.
|
|
6509
|
-
* @param gap - The padding to apply to the packed shapes. Defaults to
|
|
6516
|
+
* @param gap - The padding to apply to the packed shapes. Defaults to the editor's `adjacentShapeMargin` option.
|
|
6510
6517
|
*/
|
|
6511
|
-
packShapes(shapes: TLShapeId[] | TLShape[],
|
|
6518
|
+
packShapes(shapes: TLShapeId[] | TLShape[], _gap?: number): this {
|
|
6512
6519
|
if (this.getIsReadonly()) return this
|
|
6513
6520
|
|
|
6521
|
+
const gap = _gap ?? this.options.adjacentShapeMargin
|
|
6522
|
+
|
|
6514
6523
|
const ids =
|
|
6515
6524
|
typeof shapes[0] === 'string'
|
|
6516
6525
|
? (shapes as TLShapeId[])
|
|
@@ -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() {
|
|
@@ -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.
|
|
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
|
}
|
|
@@ -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
|
})
|
package/src/lib/options.ts
CHANGED
|
@@ -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
|
|
@@ -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.
|
|
4
|
+
export const version = '3.11.0-canary.03a8f07c67a3'
|
|
5
5
|
export const publishDates = {
|
|
6
6
|
major: '2024-09-13T14:36:29.063Z',
|
|
7
|
-
minor: '2025-03-
|
|
8
|
-
patch: '2025-03-
|
|
7
|
+
minor: '2025-03-19T13:45:12.707Z',
|
|
8
|
+
patch: '2025-03-19T13:45:12.707Z',
|
|
9
9
|
}
|