tldraw 5.3.1 → 5.3.2

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/DOCS.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # tldraw Documentation
2
2
 
3
- Version: `5.3.1`
3
+ Version: `5.3.2`
4
4
 
5
5
  This file is generated during package publishing from the tldraw docs content for this exact package version.
6
6
 
package/RELEASE_NOTES.md CHANGED
@@ -1,23 +1,27 @@
1
1
  # Releases
2
2
 
3
- Version: `5.3.1`
3
+ Version: `5.3.2`
4
4
 
5
5
  This file is generated during package publishing from the tldraw release notes content for this exact package version.
6
6
 
7
- ## v5.3.1
7
+ ## v5.3.2
8
8
 
9
- This release adds a `center` operation to `Editor.alignShapes`, `iterateGraphemes` to `@tldraw/utils`, and two new reactive methods on `AtomMap`. It also deprecates `useViewportHeight` and fixes a batch of crashes and interaction bugs across dialogs, sync reconnection, undo, and keyboard shortcut tooltips.
9
+ This release adds a `center` operation to `Editor.alignShapes`, `iterateGraphemes` to `@tldraw/utils`, and two new reactive methods on `AtomMap`. It also deprecates `useViewportHeight`, speeds up the signals and store layers, and fixes a batch of crashes and interaction bugs across dialogs, sync reconnection, undo, and keyboard shortcut tooltips.
10
10
 
11
11
  ### API changes
12
12
 
13
13
  - 🔜 **`useViewportHeight()`** is deprecated. Read `window.visualViewport` directly instead. The hook returns only the visible viewport's bottom edge, and keeping a panel clear of the software keyboard generally needs the whole visible rectangle. ([#9826](https://github.com/tldraw/tldraw/pull/9826))
14
14
  - Add `'center'` as an `Editor.alignShapes` operation. It applies the existing `'center-horizontal'` and `'center-vertical'` operations together, so shapes center on both axes in one command. ([#9074](https://github.com/tldraw/tldraw/pull/9074))
15
15
  - Add `getOrInsert(key, defaultValue)` and `getOrInsertComputed(key, callback)` to `AtomMap`, matching the `Map` methods added in newer JavaScript runtimes. Both are reactive, and the callback only runs when the key is absent. ([#9752](https://github.com/tldraw/tldraw/pull/9752))
16
+ - Add `isPage(record)` to `@tldraw/tlschema`, a type guard that narrows an unknown record to `TLPage`. ([#9774](https://github.com/tldraw/tldraw/pull/9774))
16
17
  - Add `iterateGraphemes(str)` to `@tldraw/utils`. It iterates a string's grapheme clusters, using `Intl.Segmenter` when it's available and falling back to code-point iteration when it isn't. ([#9896](https://github.com/tldraw/tldraw/pull/9896))
18
+ - Add `isPage(record)` to `@tldraw/tlschema`, a type guard for page records that matches the guards already exported for the other record types. ([#9774](https://github.com/tldraw/tldraw/pull/9774))
17
19
 
18
20
  ### Improvements
19
21
 
20
22
  - Reduce per-pointer-event allocations in `Group2d` and `Editor` hit-testing. ([#8600](https://github.com/tldraw/tldraw/pull/8600))
23
+ - Speed up signal reads in `@tldraw/state`. Capturing a parent used to scan the capturing signal's parent set twice, once to check for the parent and again to add it. ([#9690](https://github.com/tldraw/tldraw/pull/9690))
24
+ - Reduce the work and allocations in `@tldraw/store` history bookkeeping, so squashing record diffs and filtering query history no longer build intermediate copies on every tick. ([#9689](https://github.com/tldraw/tldraw/pull/9689), [#9869](https://github.com/tldraw/tldraw/pull/9869))
21
25
 
22
26
  ### Bug fixes
23
27
 
@@ -27,6 +31,7 @@ This release adds a `center` operation to `Editor.alignShapes`, `iterateGrapheme
27
31
  - Fix modifier keys (Shift, Alt, Ctrl, Cmd) briefly being treated as held at the start of a new click or drag right after being released, which could momentarily affect snapping and other modifier-dependent behavior. ([#9523](https://github.com/tldraw/tldraw/pull/9523))
28
32
  - Fix **Flatten to image** producing different groupings depending on selection order, and not merging clusters that were only connected through a bridging shape. ([#8661](https://github.com/tldraw/tldraw/pull/8661))
29
33
  - Fix pasted links showing a broken preview image when the linked page has no Open Graph image. ([#9909](https://github.com/tldraw/tldraw/pull/9909))
34
+ - Fix video shapes showing a floating spinner with no bounding box while their asset uploads or loads. They now show the same loading plate as image shapes. ([#9994](https://github.com/tldraw/tldraw/pull/9994))
30
35
  - Fix closing a stacked dialog by touch also closing the dialog beneath it. ([#10002](https://github.com/tldraw/tldraw/pull/10002))
31
36
  - Fix wheel event normalization passing through non-finite delta values. ([#9586](https://github.com/tldraw/tldraw/pull/9586))
32
37
  - Fix the counterclockwise rotation tooltip not showing its comma key. ([#9772](https://github.com/tldraw/tldraw/pull/9772))
@@ -34,6 +39,7 @@ This release adds a `center` operation to `Editor.alignShapes`, `iterateGrapheme
34
39
  - Fix the people menu's collaborator rows not lining up with your own row above them: the follow icon sat too close to the right edge, and collaborator names sat slightly left of your own. ([#9900](https://github.com/tldraw/tldraw/pull/9900))
35
40
  - Fix the comment thread popover briefly rendering with a doubled shadow the first time a thread is opened. ([#9886](https://github.com/tldraw/tldraw/pull/9886))
36
41
  - Fix background tabs repeatedly dropping and re-establishing their sync connection when the browser throttles timers. ([#9964](https://github.com/tldraw/tldraw/pull/9964))
42
+ - Fix video shapes showing a floating spinner with no bounding box while the video asset uploads or loads. They now show the same loading plate as image shapes. ([#9994](https://github.com/tldraw/tldraw/pull/9994))
37
43
 
38
44
  ## v5.3.0
39
45
 
@@ -125,6 +131,16 @@ See the [commenting docs](https://tldraw.dev/docs/commenting) for setup.
125
131
  - Fix a crash when a custom font failed to load after its editor had been disposed. ([#9494](https://github.com/tldraw/tldraw/pull/9494))
126
132
  - Fix license expiry being evaluated in local time, which could deactivate a license a calendar day early for users west of UTC; the expiry date is now treated as the last fully usable day in UTC. ([#9475](https://github.com/tldraw/tldraw/pull/9475))
127
133
 
134
+ ---
135
+
136
+ ### Patch releases
137
+
138
+ #### v5.3.1
139
+
140
+ - Fix touches in part of the canvas being ignored on iOS when the editor was inset from the edge of the page, such as beside a sidebar. ([#9989](https://github.com/tldraw/tldraw/pull/9989))
141
+
142
+ [View release on GitHub](https://github.com/tldraw/tldraw/releases/tag/v5.3.1)
143
+
128
144
  ## v5.2.0
129
145
 
130
146
  [View on GitHub](https://github.com/tldraw/tldraw/releases/tag/v5.2.0)
package/dist-cjs/index.js CHANGED
@@ -653,7 +653,7 @@ var import_buildFromV1Document = require("./lib/utils/tldr/buildFromV1Document")
653
653
  var import_file = require("./lib/utils/tldr/file");
654
654
  (0, import_editor.registerTldrawLibraryVersion)(
655
655
  "tldraw",
656
- "5.3.1",
656
+ "5.3.2",
657
657
  "cjs"
658
658
  );
659
659
  //# sourceMappingURL=index.js.map
@@ -23,6 +23,6 @@ __export(useCommentingEnabled_exports, {
23
23
  module.exports = __toCommonJS(useCommentingEnabled_exports);
24
24
  var import_editor = require("@tldraw/editor");
25
25
  function useCommentingEnabled() {
26
- return (0, import_editor.useLicenseFeatureFlag)((0, import_editor.useLicenseContext)(), "commenting");
26
+ return (0, import_editor.useLicenseFeatureFlag)((0, import_editor.useMaybeLicenseManager)(), "commenting");
27
27
  }
28
28
  //# sourceMappingURL=useCommentingEnabled.js.map
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../src/lib/ui/hooks/useCommentingEnabled.ts"],
4
- "sourcesContent": ["import { useLicenseContext, useLicenseFeatureFlag } from '@tldraw/editor'\n\n/**\n * Whether the commenting feature is licensed for this editor. The default comment quick action and\n * its keyboard shortcut are hidden/disabled unless this is true. Enabled in development; in\n * production it requires a license that includes the commenting feature (or the collaboration\n * umbrella that grants it). Reactive: re-reads when license validation resolves.\n *\n * @internal\n */\nexport function useCommentingEnabled(): boolean {\n\treturn useLicenseFeatureFlag(useLicenseContext(), 'commenting')\n}\n"],
5
- "mappings": ";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,oBAAyD;AAUlD,SAAS,uBAAgC;AAC/C,aAAO,yCAAsB,iCAAkB,GAAG,YAAY;AAC/D;",
4
+ "sourcesContent": ["import { useLicenseFeatureFlag, useMaybeLicenseManager } from '@tldraw/editor'\n\n/**\n * Whether the commenting feature is licensed for this editor. The default comment quick action and\n * its keyboard shortcut are hidden/disabled unless this is true. Enabled in development; in\n * production it requires a license that includes the commenting feature (or the collaboration\n * umbrella that grants it). Reactive: re-reads when license validation resolves. Works outside\n * `<Tldraw />` too: UI mounted via `EditorProvider` resolves the license through the editor, and\n * with no editor at all this is `false`.\n *\n * @internal\n */\nexport function useCommentingEnabled(): boolean {\n\treturn useLicenseFeatureFlag(useMaybeLicenseManager(), 'commenting')\n}\n"],
5
+ "mappings": ";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,oBAA8D;AAYvD,SAAS,uBAAgC;AAC/C,aAAO,yCAAsB,sCAAuB,GAAG,YAAY;AACpE;",
6
6
  "names": []
7
7
  }
@@ -22,10 +22,10 @@ __export(version_exports, {
22
22
  version: () => version
23
23
  });
24
24
  module.exports = __toCommonJS(version_exports);
25
- const version = "5.3.1";
25
+ const version = "5.3.2";
26
26
  const publishDates = {
27
27
  major: "2026-05-06T16:28:18.473Z",
28
28
  minor: "2026-08-05T11:39:54.978Z",
29
- patch: "2026-08-14T10:46:20.010Z"
29
+ patch: "2026-08-18T09:59:40.172Z"
30
30
  };
31
31
  //# sourceMappingURL=version.js.map
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../src/lib/ui/version.ts"],
4
- "sourcesContent": ["// This file is automatically generated by internal/scripts/refresh-assets.ts.\n// Do not edit manually. Or do, I'm a comment, not a cop.\n\nexport const version = '5.3.1'\nexport const publishDates = {\n\tmajor: '2026-05-06T16:28:18.473Z',\n\tminor: '2026-08-05T11:39:54.978Z',\n\tpatch: '2026-08-14T10:46:20.010Z',\n}\n"],
4
+ "sourcesContent": ["// This file is automatically generated by internal/scripts/refresh-assets.ts.\n// Do not edit manually. Or do, I'm a comment, not a cop.\n\nexport const version = '5.3.2'\nexport const publishDates = {\n\tmajor: '2026-05-06T16:28:18.473Z',\n\tminor: '2026-08-05T11:39:54.978Z',\n\tpatch: '2026-08-18T09:59:40.172Z',\n}\n"],
5
5
  "mappings": ";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAGO,MAAM,UAAU;AAChB,MAAM,eAAe;AAAA,EAC3B,OAAO;AAAA,EACP,OAAO;AAAA,EACP,OAAO;AACR;",
6
6
  "names": []
7
7
  }
@@ -637,7 +637,7 @@ import {
637
637
  } from "./lib/utils/tldr/file.mjs";
638
638
  registerTldrawLibraryVersion(
639
639
  "tldraw",
640
- "5.3.1",
640
+ "5.3.2",
641
641
  "esm"
642
642
  );
643
643
  export {
@@ -1,6 +1,6 @@
1
- import { useLicenseContext, useLicenseFeatureFlag } from "@tldraw/editor";
1
+ import { useLicenseFeatureFlag, useMaybeLicenseManager } from "@tldraw/editor";
2
2
  function useCommentingEnabled() {
3
- return useLicenseFeatureFlag(useLicenseContext(), "commenting");
3
+ return useLicenseFeatureFlag(useMaybeLicenseManager(), "commenting");
4
4
  }
5
5
  export {
6
6
  useCommentingEnabled
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../src/lib/ui/hooks/useCommentingEnabled.ts"],
4
- "sourcesContent": ["import { useLicenseContext, useLicenseFeatureFlag } from '@tldraw/editor'\n\n/**\n * Whether the commenting feature is licensed for this editor. The default comment quick action and\n * its keyboard shortcut are hidden/disabled unless this is true. Enabled in development; in\n * production it requires a license that includes the commenting feature (or the collaboration\n * umbrella that grants it). Reactive: re-reads when license validation resolves.\n *\n * @internal\n */\nexport function useCommentingEnabled(): boolean {\n\treturn useLicenseFeatureFlag(useLicenseContext(), 'commenting')\n}\n"],
5
- "mappings": "AAAA,SAAS,mBAAmB,6BAA6B;AAUlD,SAAS,uBAAgC;AAC/C,SAAO,sBAAsB,kBAAkB,GAAG,YAAY;AAC/D;",
4
+ "sourcesContent": ["import { useLicenseFeatureFlag, useMaybeLicenseManager } from '@tldraw/editor'\n\n/**\n * Whether the commenting feature is licensed for this editor. The default comment quick action and\n * its keyboard shortcut are hidden/disabled unless this is true. Enabled in development; in\n * production it requires a license that includes the commenting feature (or the collaboration\n * umbrella that grants it). Reactive: re-reads when license validation resolves. Works outside\n * `<Tldraw />` too: UI mounted via `EditorProvider` resolves the license through the editor, and\n * with no editor at all this is `false`.\n *\n * @internal\n */\nexport function useCommentingEnabled(): boolean {\n\treturn useLicenseFeatureFlag(useMaybeLicenseManager(), 'commenting')\n}\n"],
5
+ "mappings": "AAAA,SAAS,uBAAuB,8BAA8B;AAYvD,SAAS,uBAAgC;AAC/C,SAAO,sBAAsB,uBAAuB,GAAG,YAAY;AACpE;",
6
6
  "names": []
7
7
  }
@@ -1,8 +1,8 @@
1
- const version = "5.3.1";
1
+ const version = "5.3.2";
2
2
  const publishDates = {
3
3
  major: "2026-05-06T16:28:18.473Z",
4
4
  minor: "2026-08-05T11:39:54.978Z",
5
- patch: "2026-08-14T10:46:20.010Z"
5
+ patch: "2026-08-18T09:59:40.172Z"
6
6
  };
7
7
  export {
8
8
  publishDates,
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../src/lib/ui/version.ts"],
4
- "sourcesContent": ["// This file is automatically generated by internal/scripts/refresh-assets.ts.\n// Do not edit manually. Or do, I'm a comment, not a cop.\n\nexport const version = '5.3.1'\nexport const publishDates = {\n\tmajor: '2026-05-06T16:28:18.473Z',\n\tminor: '2026-08-05T11:39:54.978Z',\n\tpatch: '2026-08-14T10:46:20.010Z',\n}\n"],
4
+ "sourcesContent": ["// This file is automatically generated by internal/scripts/refresh-assets.ts.\n// Do not edit manually. Or do, I'm a comment, not a cop.\n\nexport const version = '5.3.2'\nexport const publishDates = {\n\tmajor: '2026-05-06T16:28:18.473Z',\n\tminor: '2026-08-05T11:39:54.978Z',\n\tpatch: '2026-08-18T09:59:40.172Z',\n}\n"],
5
5
  "mappings": "AAGO,MAAM,UAAU;AAChB,MAAM,eAAe;AAAA,EAC3B,OAAO;AAAA,EACP,OAAO;AAAA,EACP,OAAO;AACR;",
6
6
  "names": []
7
7
  }
package/package.json CHANGED
@@ -1,13 +1,19 @@
1
1
  {
2
2
  "name": "tldraw",
3
3
  "description": "A tiny little drawing editor.",
4
- "version": "5.3.1",
4
+ "version": "5.3.2",
5
5
  "author": {
6
6
  "name": "tldraw Inc.",
7
7
  "email": "hello@tldraw.com"
8
8
  },
9
9
  "homepage": "https://tldraw.dev",
10
10
  "license": "SEE LICENSE IN LICENSE.md",
11
+ "tldraw_product": {
12
+ "stableId": "tldraw:sdk-core",
13
+ "name": "SDK",
14
+ "type": "product",
15
+ "premium": false
16
+ },
11
17
  "repository": {
12
18
  "type": "git",
13
19
  "url": "https://github.com/tldraw/tldraw"
@@ -63,11 +69,11 @@
63
69
  "@tiptap/pm": "^3.12.1",
64
70
  "@tiptap/react": "^3.12.1",
65
71
  "@tiptap/starter-kit": "^3.12.1",
66
- "@tldraw/driver": "5.3.1",
67
- "@tldraw/editor": "5.3.1",
68
- "@tldraw/state": "5.3.1",
69
- "@tldraw/store": "5.3.1",
70
- "@tldraw/tlschema": "5.3.1",
72
+ "@tldraw/driver": "5.3.2",
73
+ "@tldraw/editor": "5.3.2",
74
+ "@tldraw/state": "5.3.2",
75
+ "@tldraw/store": "5.3.2",
76
+ "@tldraw/tlschema": "5.3.2",
71
77
  "classnames": "^2.5.1",
72
78
  "idb": "^7.1.1",
73
79
  "lz-string": "^1.5.0",
@@ -1,13 +1,15 @@
1
- import { useLicenseContext, useLicenseFeatureFlag } from '@tldraw/editor'
1
+ import { useLicenseFeatureFlag, useMaybeLicenseManager } from '@tldraw/editor'
2
2
 
3
3
  /**
4
4
  * Whether the commenting feature is licensed for this editor. The default comment quick action and
5
5
  * its keyboard shortcut are hidden/disabled unless this is true. Enabled in development; in
6
6
  * production it requires a license that includes the commenting feature (or the collaboration
7
- * umbrella that grants it). Reactive: re-reads when license validation resolves.
7
+ * umbrella that grants it). Reactive: re-reads when license validation resolves. Works outside
8
+ * `<Tldraw />` too: UI mounted via `EditorProvider` resolves the license through the editor, and
9
+ * with no editor at all this is `false`.
8
10
  *
9
11
  * @internal
10
12
  */
11
13
  export function useCommentingEnabled(): boolean {
12
- return useLicenseFeatureFlag(useLicenseContext(), 'commenting')
14
+ return useLicenseFeatureFlag(useMaybeLicenseManager(), 'commenting')
13
15
  }
@@ -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 = '5.3.1'
4
+ export const version = '5.3.2'
5
5
  export const publishDates = {
6
6
  major: '2026-05-06T16:28:18.473Z',
7
7
  minor: '2026-08-05T11:39:54.978Z',
8
- patch: '2026-08-14T10:46:20.010Z',
8
+ patch: '2026-08-18T09:59:40.172Z',
9
9
  }
@@ -0,0 +1,74 @@
1
+ import { render } from '@testing-library/react'
2
+ import { ContainerProvider, EditorProvider, useLicenseContext } from '@tldraw/editor'
3
+ import { vi } from 'vitest'
4
+ import { Tldraw } from '../lib/Tldraw'
5
+ import { DefaultToolbar } from '../lib/ui/components/Toolbar/DefaultToolbar'
6
+ import { TldrawUiContextProvider } from '../lib/ui/context/TldrawUiContextProvider'
7
+ import { useCommentingEnabled } from '../lib/ui/hooks/useCommentingEnabled'
8
+ import { renderTldrawComponentWithEditor } from './testutils/renderTldrawComponent'
9
+
10
+ // Default UI components can be mounted beside <Tldraw /> rather than inside it, wrapped in the
11
+ // providers the caller recreates (container, editor, ui context). The license provider is not
12
+ // among them — it only exists inside <TldrawEditor />.
13
+ describe('default UI mounted outside <Tldraw />', () => {
14
+ it('renders the default toolbar and resolves license feature flags through the editor', async () => {
15
+ const { editor } = await renderTldrawComponentWithEditor(
16
+ (onMount) => <Tldraw onMount={onMount} components={{ Toolbar: null }} />,
17
+ { waitForPatterns: true }
18
+ )
19
+
20
+ expect(editor.licenseManager).toBeDefined()
21
+
22
+ let commentingEnabled: boolean | undefined
23
+ function CommentingProbe() {
24
+ commentingEnabled = useCommentingEnabled()
25
+ return null
26
+ }
27
+
28
+ const result = render(
29
+ <ContainerProvider container={editor.getContainer()}>
30
+ <EditorProvider editor={editor}>
31
+ <TldrawUiContextProvider>
32
+ <DefaultToolbar />
33
+ <CommentingProbe />
34
+ </TldrawUiContextProvider>
35
+ </EditorProvider>
36
+ </ContainerProvider>
37
+ )
38
+
39
+ expect(await result.findByTestId('tools.select')).toBeTruthy()
40
+ // In tests the environment counts as development, where every feature is licensed — so a
41
+ // `true` here proves the flag resolved via the editor's license manager, not the
42
+ // fail-closed `false` of having no license manager at all.
43
+ expect(commentingEnabled).toBe(true)
44
+ })
45
+
46
+ it('license feature flags fail closed with no editor and no license context', () => {
47
+ let commentingEnabled: boolean | undefined
48
+ function CommentingProbe() {
49
+ commentingEnabled = useCommentingEnabled()
50
+ return null
51
+ }
52
+
53
+ render(<CommentingProbe />)
54
+
55
+ expect(commentingEnabled).toBe(false)
56
+ })
57
+
58
+ it('useLicenseContext throws when there is no license provider and no editor', () => {
59
+ function LicenseProbe() {
60
+ useLicenseContext()
61
+ return null
62
+ }
63
+
64
+ // silence React's error boundary logging for the expected throw
65
+ const consoleError = vi.spyOn(console, 'error').mockImplementation(() => {})
66
+ try {
67
+ expect(() => render(<LicenseProbe />)).toThrow(
68
+ 'useLicenseContext must be used inside of the <Tldraw /> or <TldrawEditor /> components'
69
+ )
70
+ } finally {
71
+ consoleError.mockRestore()
72
+ }
73
+ })
74
+ })