tldraw 5.6.0 → 5.7.0-next.433c23fa9ce6

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 (170) hide show
  1. package/DOCS.md +28 -23
  2. package/RELEASE_NOTES.md +1 -35
  3. package/dist-cjs/index.d.ts +17 -5
  4. package/dist-cjs/index.js +1 -1
  5. package/dist-cjs/lib/shapes/arrow/ArrowShapeUtil.js +3 -0
  6. package/dist-cjs/lib/shapes/arrow/ArrowShapeUtil.js.map +2 -2
  7. package/dist-cjs/lib/shapes/draw/DrawShapeUtil.js +3 -0
  8. package/dist-cjs/lib/shapes/draw/DrawShapeUtil.js.map +2 -2
  9. package/dist-cjs/lib/shapes/geo/GeoShapeUtil.js +3 -0
  10. package/dist-cjs/lib/shapes/geo/GeoShapeUtil.js.map +2 -2
  11. package/dist-cjs/lib/shapes/highlight/HighlightShapeUtil.js +3 -0
  12. package/dist-cjs/lib/shapes/highlight/HighlightShapeUtil.js.map +2 -2
  13. package/dist-cjs/lib/shapes/image/ImageShapeUtil.js +3 -0
  14. package/dist-cjs/lib/shapes/image/ImageShapeUtil.js.map +2 -2
  15. package/dist-cjs/lib/shapes/line/LineShapeUtil.js +3 -0
  16. package/dist-cjs/lib/shapes/line/LineShapeUtil.js.map +2 -2
  17. package/dist-cjs/lib/tools/SelectTool/childStates/Crop/children/Idle.js +2 -9
  18. package/dist-cjs/lib/tools/SelectTool/childStates/Crop/children/Idle.js.map +2 -2
  19. package/dist-cjs/lib/tools/SelectTool/childStates/Crop/children/PointingCrop.js +6 -13
  20. package/dist-cjs/lib/tools/SelectTool/childStates/Crop/children/PointingCrop.js.map +2 -2
  21. package/dist-cjs/lib/tools/SelectTool/childStates/Crop/children/PointingCropHandle.js +5 -12
  22. package/dist-cjs/lib/tools/SelectTool/childStates/Crop/children/PointingCropHandle.js.map +2 -2
  23. package/dist-cjs/lib/tools/SelectTool/childStates/Idle.js +1 -2
  24. package/dist-cjs/lib/tools/SelectTool/childStates/Idle.js.map +2 -2
  25. package/dist-cjs/lib/tools/SelectTool/childStates/PointingCanvas.js +2 -3
  26. package/dist-cjs/lib/tools/SelectTool/childStates/PointingCanvas.js.map +2 -2
  27. package/dist-cjs/lib/tools/SelectTool/childStates/PointingHandle.js +4 -16
  28. package/dist-cjs/lib/tools/SelectTool/childStates/PointingHandle.js.map +2 -2
  29. package/dist-cjs/lib/tools/SelectTool/childStates/PointingResizeHandle.js +5 -14
  30. package/dist-cjs/lib/tools/SelectTool/childStates/PointingResizeHandle.js.map +2 -2
  31. package/dist-cjs/lib/tools/SelectTool/childStates/PointingRotateHandle.js +5 -12
  32. package/dist-cjs/lib/tools/SelectTool/childStates/PointingRotateHandle.js.map +2 -2
  33. package/dist-cjs/lib/tools/SelectTool/childStates/PointingSelection.js +2 -3
  34. package/dist-cjs/lib/tools/SelectTool/childStates/PointingSelection.js.map +2 -2
  35. package/dist-cjs/lib/tools/SelectTool/childStates/PointingShape.js +1 -3
  36. package/dist-cjs/lib/tools/SelectTool/childStates/PointingShape.js.map +2 -2
  37. package/dist-cjs/lib/tools/SelectTool/selectHelpers.js +48 -0
  38. package/dist-cjs/lib/tools/SelectTool/selectHelpers.js.map +2 -2
  39. package/dist-cjs/lib/ui/components/ColorSchemeMenu.js +2 -2
  40. package/dist-cjs/lib/ui/components/ColorSchemeMenu.js.map +2 -2
  41. package/dist-cjs/lib/ui/components/InputModeMenu.js +2 -2
  42. package/dist-cjs/lib/ui/components/InputModeMenu.js.map +2 -2
  43. package/dist-cjs/lib/ui/components/KeyboardShortcutsDialog/DefaultKeyboardShortcutsDialogContent.js +3 -2
  44. package/dist-cjs/lib/ui/components/KeyboardShortcutsDialog/DefaultKeyboardShortcutsDialogContent.js.map +2 -2
  45. package/dist-cjs/lib/ui/components/LanguageMenu.js +2 -2
  46. package/dist-cjs/lib/ui/components/LanguageMenu.js.map +2 -2
  47. package/dist-cjs/lib/ui/components/menu-items.js +2 -2
  48. package/dist-cjs/lib/ui/components/menu-items.js.map +2 -2
  49. package/dist-cjs/lib/ui/components/primitives/menus/TldrawUiMenuContext.js +2 -1
  50. package/dist-cjs/lib/ui/components/primitives/menus/TldrawUiMenuContext.js.map +2 -2
  51. package/dist-cjs/lib/ui/context/action-predicates.js +14 -5
  52. package/dist-cjs/lib/ui/context/action-predicates.js.map +2 -2
  53. package/dist-cjs/lib/ui/context/action-state.js +81 -0
  54. package/dist-cjs/lib/ui/context/action-state.js.map +7 -0
  55. package/dist-cjs/lib/ui/context/actions.js +105 -161
  56. package/dist-cjs/lib/ui/context/actions.js.map +2 -2
  57. package/dist-cjs/lib/ui/hooks/useActionState.js +3 -44
  58. package/dist-cjs/lib/ui/hooks/useActionState.js.map +2 -2
  59. package/dist-cjs/lib/ui/hooks/useKeyboardShortcuts.js +1 -0
  60. package/dist-cjs/lib/ui/hooks/useKeyboardShortcuts.js.map +2 -2
  61. package/dist-cjs/lib/ui/overrides.js.map +2 -2
  62. package/dist-cjs/lib/ui/version.js +3 -3
  63. package/dist-cjs/lib/ui/version.js.map +1 -1
  64. package/dist-cjs/lib/utils/frames/frames.js +1 -1
  65. package/dist-cjs/lib/utils/frames/frames.js.map +2 -2
  66. package/dist-esm/index.d.mts +17 -5
  67. package/dist-esm/index.mjs +1 -1
  68. package/dist-esm/lib/shapes/arrow/ArrowShapeUtil.mjs +3 -0
  69. package/dist-esm/lib/shapes/arrow/ArrowShapeUtil.mjs.map +2 -2
  70. package/dist-esm/lib/shapes/draw/DrawShapeUtil.mjs +3 -0
  71. package/dist-esm/lib/shapes/draw/DrawShapeUtil.mjs.map +2 -2
  72. package/dist-esm/lib/shapes/geo/GeoShapeUtil.mjs +3 -0
  73. package/dist-esm/lib/shapes/geo/GeoShapeUtil.mjs.map +2 -2
  74. package/dist-esm/lib/shapes/highlight/HighlightShapeUtil.mjs +3 -0
  75. package/dist-esm/lib/shapes/highlight/HighlightShapeUtil.mjs.map +2 -2
  76. package/dist-esm/lib/shapes/image/ImageShapeUtil.mjs +3 -0
  77. package/dist-esm/lib/shapes/image/ImageShapeUtil.mjs.map +2 -2
  78. package/dist-esm/lib/shapes/line/LineShapeUtil.mjs +3 -0
  79. package/dist-esm/lib/shapes/line/LineShapeUtil.mjs.map +2 -2
  80. package/dist-esm/lib/tools/SelectTool/childStates/Crop/children/Idle.mjs +2 -9
  81. package/dist-esm/lib/tools/SelectTool/childStates/Crop/children/Idle.mjs.map +2 -2
  82. package/dist-esm/lib/tools/SelectTool/childStates/Crop/children/PointingCrop.mjs +6 -13
  83. package/dist-esm/lib/tools/SelectTool/childStates/Crop/children/PointingCrop.mjs.map +2 -2
  84. package/dist-esm/lib/tools/SelectTool/childStates/Crop/children/PointingCropHandle.mjs +5 -12
  85. package/dist-esm/lib/tools/SelectTool/childStates/Crop/children/PointingCropHandle.mjs.map +2 -2
  86. package/dist-esm/lib/tools/SelectTool/childStates/Idle.mjs +2 -2
  87. package/dist-esm/lib/tools/SelectTool/childStates/Idle.mjs.map +2 -2
  88. package/dist-esm/lib/tools/SelectTool/childStates/PointingCanvas.mjs +2 -3
  89. package/dist-esm/lib/tools/SelectTool/childStates/PointingCanvas.mjs.map +2 -2
  90. package/dist-esm/lib/tools/SelectTool/childStates/PointingHandle.mjs +5 -17
  91. package/dist-esm/lib/tools/SelectTool/childStates/PointingHandle.mjs.map +2 -2
  92. package/dist-esm/lib/tools/SelectTool/childStates/PointingResizeHandle.mjs +5 -14
  93. package/dist-esm/lib/tools/SelectTool/childStates/PointingResizeHandle.mjs.map +2 -2
  94. package/dist-esm/lib/tools/SelectTool/childStates/PointingRotateHandle.mjs +5 -12
  95. package/dist-esm/lib/tools/SelectTool/childStates/PointingRotateHandle.mjs.map +2 -2
  96. package/dist-esm/lib/tools/SelectTool/childStates/PointingSelection.mjs +2 -3
  97. package/dist-esm/lib/tools/SelectTool/childStates/PointingSelection.mjs.map +2 -2
  98. package/dist-esm/lib/tools/SelectTool/childStates/PointingShape.mjs +2 -4
  99. package/dist-esm/lib/tools/SelectTool/childStates/PointingShape.mjs.map +2 -2
  100. package/dist-esm/lib/tools/SelectTool/selectHelpers.mjs +48 -0
  101. package/dist-esm/lib/tools/SelectTool/selectHelpers.mjs.map +2 -2
  102. package/dist-esm/lib/ui/components/ColorSchemeMenu.mjs +2 -2
  103. package/dist-esm/lib/ui/components/ColorSchemeMenu.mjs.map +2 -2
  104. package/dist-esm/lib/ui/components/InputModeMenu.mjs +2 -2
  105. package/dist-esm/lib/ui/components/InputModeMenu.mjs.map +2 -2
  106. package/dist-esm/lib/ui/components/KeyboardShortcutsDialog/DefaultKeyboardShortcutsDialogContent.mjs +3 -2
  107. package/dist-esm/lib/ui/components/KeyboardShortcutsDialog/DefaultKeyboardShortcutsDialogContent.mjs.map +2 -2
  108. package/dist-esm/lib/ui/components/LanguageMenu.mjs +2 -2
  109. package/dist-esm/lib/ui/components/LanguageMenu.mjs.map +2 -2
  110. package/dist-esm/lib/ui/components/menu-items.mjs +2 -2
  111. package/dist-esm/lib/ui/components/menu-items.mjs.map +2 -2
  112. package/dist-esm/lib/ui/components/primitives/menus/TldrawUiMenuContext.mjs +3 -2
  113. package/dist-esm/lib/ui/components/primitives/menus/TldrawUiMenuContext.mjs.map +2 -2
  114. package/dist-esm/lib/ui/context/action-predicates.mjs +14 -5
  115. package/dist-esm/lib/ui/context/action-predicates.mjs.map +2 -2
  116. package/dist-esm/lib/ui/context/action-state.mjs +61 -0
  117. package/dist-esm/lib/ui/context/action-state.mjs.map +7 -0
  118. package/dist-esm/lib/ui/context/actions.mjs +107 -162
  119. package/dist-esm/lib/ui/context/actions.mjs.map +2 -2
  120. package/dist-esm/lib/ui/hooks/useActionState.mjs +1 -42
  121. package/dist-esm/lib/ui/hooks/useActionState.mjs.map +2 -2
  122. package/dist-esm/lib/ui/hooks/useKeyboardShortcuts.mjs +1 -0
  123. package/dist-esm/lib/ui/hooks/useKeyboardShortcuts.mjs.map +2 -2
  124. package/dist-esm/lib/ui/overrides.mjs.map +2 -2
  125. package/dist-esm/lib/ui/version.mjs +3 -3
  126. package/dist-esm/lib/ui/version.mjs.map +1 -1
  127. package/dist-esm/lib/utils/frames/frames.mjs +1 -1
  128. package/dist-esm/lib/utils/frames/frames.mjs.map +2 -2
  129. package/package.json +6 -6
  130. package/src/lib/shapes/arrow/ArrowShapeUtil.tsx +4 -0
  131. package/src/lib/shapes/draw/DrawShapeUtil.tsx +4 -0
  132. package/src/lib/shapes/geo/GeoShapeUtil.tsx +4 -0
  133. package/src/lib/shapes/highlight/HighlightShapeUtil.tsx +4 -0
  134. package/src/lib/shapes/image/ImageShapeUtil.tsx +4 -0
  135. package/src/lib/shapes/line/LineShapeUtil.tsx +4 -0
  136. package/src/lib/tools/SelectTool/childStates/Crop/children/Idle.ts +5 -10
  137. package/src/lib/tools/SelectTool/childStates/Crop/children/PointingCrop.ts +6 -19
  138. package/src/lib/tools/SelectTool/childStates/Crop/children/PointingCropHandle.ts +5 -18
  139. package/src/lib/tools/SelectTool/childStates/Idle.ts +2 -4
  140. package/src/lib/tools/SelectTool/childStates/PointingCanvas.ts +2 -8
  141. package/src/lib/tools/SelectTool/childStates/PointingHandle.ts +5 -23
  142. package/src/lib/tools/SelectTool/childStates/PointingResizeHandle.ts +5 -20
  143. package/src/lib/tools/SelectTool/childStates/PointingRotateHandle.ts +5 -18
  144. package/src/lib/tools/SelectTool/childStates/PointingSelection.ts +2 -8
  145. package/src/lib/tools/SelectTool/childStates/PointingShape.ts +2 -9
  146. package/src/lib/tools/SelectTool/selectHelpers.ts +75 -0
  147. package/src/lib/ui/components/ColorSchemeMenu.tsx +2 -2
  148. package/src/lib/ui/components/InputModeMenu.tsx +2 -2
  149. package/src/lib/ui/components/KeyboardShortcutsDialog/DefaultKeyboardShortcutsDialogContent.tsx +3 -2
  150. package/src/lib/ui/components/LanguageMenu.tsx +2 -2
  151. package/src/lib/ui/components/menu-items.tsx +2 -2
  152. package/src/lib/ui/components/primitives/menus/TldrawUiMenuContext.tsx +4 -2
  153. package/src/lib/ui/context/action-predicates.ts +26 -7
  154. package/src/lib/ui/context/action-state.ts +93 -0
  155. package/src/lib/ui/context/actions.tsx +142 -235
  156. package/src/lib/ui/hooks/useActionState.ts +2 -64
  157. package/src/lib/ui/hooks/useKeyboardShortcuts.ts +4 -1
  158. package/src/lib/ui/overrides.ts +4 -0
  159. package/src/lib/ui/version.ts +3 -3
  160. package/src/lib/utils/frames/frames.ts +1 -1
  161. package/src/test/SelectTool.test.ts +0 -60
  162. package/src/test/cropping.test.ts +41 -66
  163. package/src/test/deferredDoubleClick.test.ts +231 -0
  164. package/src/test/frames.test.ts +19 -0
  165. package/src/test/ui/FrameSelectionMenuItem.test.tsx +11 -2
  166. package/src/test/ui/actionGate.test.tsx +197 -0
  167. package/src/test/ui/actionGating.test.tsx +102 -1
  168. package/src/test/ui/actionPredicates.test.ts +24 -0
  169. package/src/test/ui/keyboardShortcuts.test.tsx +350 -26
  170. package/src/test/ui/menuActionItem.test.tsx +37 -0
package/DOCS.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # tldraw Documentation
2
2
 
3
- Version: `5.6.0`
3
+ Version: `5.7.0-next.433c23fa9ce6`
4
4
 
5
5
  This file is generated during package publishing from the tldraw docs content for this exact package version.
6
6
 
@@ -4482,19 +4482,19 @@ Keyboard shortcuts are bound automatically. The `useKeyboardShortcuts` hook pars
4482
4482
 
4483
4483
  The `TLUiActionItem` interface defines what an action contains:
4484
4484
 
4485
- | Property | Description |
4486
- | ---------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------- |
4487
- | `id` | Unique identifier for the action (e.g., `'duplicate'`, `'zoom-in'`) |
4488
- | `label` | Translation key for display text. Can be a string or an object mapping contexts to different keys (see [Context-sensitive labels](#context-sensitive-labels)) |
4489
- | `icon` | Icon name from tldraw's icon set, or a custom React element |
4490
- | `kbd` | Keyboard shortcut string. Use commas to bind several combinations, e.g. `'cmd+g,ctrl+g'` (see [Keyboard shortcuts](#keyboard-shortcuts)) |
4491
- | `readonlyOk` | When `true`, the action works in readonly mode. Defaults to `false` |
4492
- | `checkbox` | When `true`, renders as a toggle with a checkmark indicator in menus |
4493
- | `isRequiredA11yAction` | When `true`, the keyboard shortcut works even when shortcuts are normally disabled (e.g., while editing a shape). Used for accessibility actions |
4494
- | `isAvailable` | Optional `(editor) => boolean`. When it returns `false`, menus hide the action (see [Enabling and checking actions](#enabling-and-checking-actions)) |
4495
- | `isEnabled` | Optional `(editor) => boolean`. When it returns `false`, menus disable or hide the action |
4496
- | `isChecked` | Optional `(editor) => boolean`. For checkbox actions, whether the item shows as checked |
4497
- | `onSelect` | Handler called when the action is triggered. Receives a `TLUiEventSource` indicating the trigger origin (`'kbd'`, `'menu'`, `'toolbar'`, etc.) |
4485
+ | Property | Description |
4486
+ | ---------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
4487
+ | `id` | Unique identifier for the action (e.g., `'duplicate'`, `'zoom-in'`) |
4488
+ | `label` | Translation key for display text. Can be a string or an object mapping contexts to different keys (see [Context-sensitive labels](#context-sensitive-labels)) |
4489
+ | `icon` | Icon name from tldraw's icon set, or a custom React element |
4490
+ | `kbd` | Keyboard shortcut string. Use commas to bind several combinations, e.g. `'cmd+g,ctrl+g'` (see [Keyboard shortcuts](#keyboard-shortcuts)) |
4491
+ | `readonlyOk` | When `true`, the action runs in readonly mode; otherwise it doesn't run, however it's triggered. Defaults to `false` |
4492
+ | `checkbox` | When `true`, renders as a toggle with a checkmark indicator in menus |
4493
+ | `isRequiredA11yAction` | When `true`, the keyboard shortcut works even when shortcuts are normally disabled (e.g., while editing a shape). Used for accessibility actions |
4494
+ | `isAvailable` | Optional `(editor) => boolean`. When it returns `false`, menus hide the action, and the action doesn't run (see [Enabling and checking actions](#enabling-and-checking-actions)) |
4495
+ | `isEnabled` | Optional `(editor) => boolean`. When it returns `false`, menus disable or hide the action, and the action doesn't run |
4496
+ | `isChecked` | Optional `(editor) => boolean`. For checkbox actions, whether the item shows as checked |
4497
+ | `onSelect` | Handler called when the action is triggered. Receives a `TLUiEventSource` indicating the trigger origin (`'kbd'`, `'menu'`, `'toolbar'`, etc.) |
4498
4498
 
4499
4499
  #### Accessing actions
4500
4500
 
@@ -4523,13 +4523,14 @@ The default actions cover most editing operations you'd expect in a canvas appli
4523
4523
  | Category | Action ids |
4524
4524
  | ----------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
4525
4525
  | Editing | `undo`, `redo`, `duplicate`, `delete`, `copy`, `cut`, `paste` |
4526
- | Grouping | `group`, `ungroup` |
4526
+ | Grouping | `group`, `ungroup`, `toggle-group` |
4527
+ | Frames | `frame-selection`, `remove-frame`, `toggle-frame`, `fit-frame-to-content` |
4527
4528
  | Arrangement | `bring-to-front`, `bring-forward`, `send-backward`, `send-to-back`, `align-left`, `align-center-horizontal`, `align-right`, `distribute-horizontal`, `distribute-vertical` |
4528
4529
  | Export | `export-as-svg`, `export-as-png`, `copy-as-svg`, `copy-as-png` |
4529
4530
  | Zoom | `zoom-in`, `zoom-out`, `zoom-to-100`, `zoom-to-fit`, `zoom-to-selection`, `select-zoom-tool` |
4530
4531
  | Preferences | `toggle-dark-mode`, `toggle-snap-mode`, `toggle-grid`, `toggle-focus-mode` |
4531
4532
 
4532
- The full list is in the [default actions source](https://github.com/tldraw/tldraw/blob/main/packages/tldraw/src/lib/ui/context/actions.tsx). Most actions guard themselves inside their handlers. For example, `group` and the arrangement actions do nothing unless shapes are selected and the select tool is active.
4533
+ The full list is in the [default actions source](https://github.com/tldraw/tldraw/blob/main/packages/tldraw/src/lib/ui/context/actions.tsx). An action doesn't run when its `isAvailable` or `isEnabled` returns false, or when the editor is readonly and it isn't `readonlyOk`, including when you call `onSelect` on an action from `useActions()`. For example, `group` does nothing unless two or more unlocked shapes are selected in the select tool.
4533
4534
 
4534
4535
  #### Overriding actions
4535
4536
 
@@ -4555,7 +4556,9 @@ function App() {
4555
4556
  }
4556
4557
  ```
4557
4558
 
4558
- The `copy`, `cut`, and `paste` shortcuts are handled by native clipboard events rather than the `kbd` system, so changing their `kbd` has no effect.
4559
+ The `copy`, `cut`, and `paste` shortcuts are handled by native clipboard events rather than the `kbd` system, so changing their `kbd` or `isEnabled` has no effect on them.
4560
+
4561
+ Cmd+G and Cmd+Alt+G belong to `toggle-group` and `toggle-frame`, which run `group` or `ungroup`, and `frame-selection` or `remove-frame`, depending on the selection. To change or remove those shortcuts, override the toggle actions, not `group` or `frame-selection`.
4559
4562
 
4560
4563
  ##### Modifying behavior
4561
4564
 
@@ -4581,7 +4584,7 @@ You can call the original handler before or after your custom logic, or replace
4581
4584
 
4582
4585
  ##### Adding custom actions
4583
4586
 
4584
- Add new actions by inserting them into the actions record:
4587
+ Add new actions by inserting them into the actions record. The `actions` map passed to `overrides` isn't gated yet, so calling a built-in's `onSelect` on it from inside a custom action skips the readonly check, `isAvailable` and `isEnabled`. Before you call it, check `editor.getIsReadonly()` (unless it's `readonlyOk`) and whichever of `isAvailable` and `isEnabled` it defines. Actions you get from `useActions()` in component code are gated.
4585
4588
 
4586
4589
  ```typescript
4587
4590
  const overrides: TLUiOverrides = {
@@ -4720,7 +4723,7 @@ actions['make-red'] = {
4720
4723
  }
4721
4724
  ```
4722
4725
 
4723
- Keyboard shortcuts ignore `isAvailable` and `isEnabled`, so `onSelect` should still check its own preconditions.
4726
+ Menus, keyboard shortcuts and `onSelect` calls on actions from `useActions()` all respect `isEnabled`, so `onSelect` doesn't need to check it again. The gate comes from the action as `overrides` returned it, so changing `isEnabled` on a copy of an action from `useActions()` doesn't change when it runs; override it instead. The exception is the copy, cut and paste shortcuts: they come from native clipboard events, which don't check the action's `isEnabled`.
4724
4727
 
4725
4728
  When you change a built-in action, spread the original so it keeps its `isAvailable`, `isEnabled` and `isChecked`:
4726
4729
 
@@ -4728,7 +4731,7 @@ When you change a built-in action, spread the original so it keeps its `isAvaila
4728
4731
  actions['group'] = { ...actions['group'], onSelect: myGroup }
4729
4732
  ```
4730
4733
 
4731
- Replacing an action with a new object drops them: menus show it as always enabled, and a checkbox item for it always shows as unchecked.
4734
+ Replacing an action with a new object drops them, along with `readonlyOk`: menus show it as always enabled, a checkbox item for it always shows as unchecked, shortcuts and `onSelect` calls run it whatever the selection, and if the built-in was `readonlyOk`, it stops running while the editor is readonly.
4732
4735
 
4733
4736
  Use `isAvailable` instead when the action doesn't exist in the current context at all, rather than being blocked right now. Every menu item hides an unavailable action, whatever `whenDisabled` says; only the keyboard shortcuts dialog still lists it. The built-in paste (without clipboard read access), copy as PNG (without clipboard write access), copy as JSON (outside debug mode), cursor chat (on touch), exit pen mode, stop following, and back to content work this way.
4734
4737
 
@@ -10947,7 +10950,7 @@ editor.createShape({
10947
10950
 
10948
10951
  #### Creating frames
10949
10952
 
10950
- You can create a frame programmatically with `Editor#createShape`, or interactively with the frame tool. The frame tool ships in the default toolbar; users can also press `F` to switch to it. The **Frame selection** action (`Cmd/Ctrl+Alt+G`) wraps the current selection in a new frame.
10953
+ You can create a frame programmatically with `Editor#createShape`, or interactively with the frame tool. The frame tool ships in the default toolbar; users can also press `F` to switch to it. The **Frame selection** action wraps the current selection in a new frame. `Cmd/Ctrl+Alt+G` runs the `toggle-frame` action: it frames the selection, or removes the frame if only frames are selected. Override `toggle-frame` to rebind it.
10951
10954
 
10952
10955
  When the user drags a frame around existing shapes, the frame tool reparents any sibling shapes that fall fully inside the frame's bounds. Locked shapes are skipped. This is what makes "draw a frame around the things I want to group" work as a single gesture.
10953
10956
 
@@ -11030,7 +11033,7 @@ import { removeFrame } from 'tldraw'
11030
11033
  removeFrame(editor, [frameId])
11031
11034
  ```
11032
11035
 
11033
- The **Remove frame** and **Fit frame to content** actions in the main menu and the context menu's Edit submenu call these helpers when a frame is selected. **Frame selection** (`Cmd/Ctrl+Alt+G`) also removes frames when every selected shape is a frame.
11036
+ The **Remove frame** and **Fit frame to content** actions in the main menu and the context menu's Edit submenu call these helpers when a frame is selected. **Remove frame** (`remove-frame`) has its own shortcut, `Cmd/Ctrl+Alt+Shift+G`.
11034
11037
 
11035
11038
  #### Exporting frames
11036
11039
 
@@ -11934,7 +11937,7 @@ editor.groupShapes([shapeId1, shapeId2], {
11934
11937
  })
11935
11938
  ```
11936
11939
 
11937
- Grouping requires at least two shapes. The method does nothing if you pass fewer, and it skips [locked shapes](https://tldraw.dev/sdk-features/locked-shapes). Users can also group shapes with Ctrl+G (Cmd+G on Mac); when the only selected shape is a group, the same shortcut ungroups it.
11940
+ Grouping requires at least two shapes. The method does nothing if you pass fewer, and it skips [locked shapes](https://tldraw.dev/sdk-features/locked-shapes). Users can also group shapes with Ctrl+G (Cmd+G on Mac). Pressing the shortcut again with the resulting group selected ungroups it. The shortcut belongs to the `toggle-group` action, so override that action to rebind it.
11938
11941
 
11939
11942
  The new group is positioned at the top-left of the combined bounds of all grouped shapes. It takes the z-index of the topmost grouped shape, so it sits where that shape was in its parent's layer stack.
11940
11943
 
@@ -16976,6 +16979,8 @@ editor.flipShapes([box1, box2], 'vertical')
16976
16979
 
16977
16980
  When flipping groups, the editor includes all children of the group so the whole hierarchy flips together. Shapes can opt out of flipping by returning `false` from `ShapeUtil#canBeLaidOut`; arrows do this when the shape they're bound to isn't part of the flip.
16978
16981
 
16982
+ The default UI only offers flip for a single selected shape when `ShapeUtil#canFlip` returns `true`, meaning flipping changes the shape itself by mirroring it or toggling its stored flip. `Editor#flipShapes` doesn't check it. It defaults to `false`; the built-in group, image, arrow, line, draw, highlight and geo shapes return `true`. Override it in your shape util if your shape changes when flipped. Shapes that return `false` still move with the rest of a multi-shape flip.
16983
+
16979
16984
  ##### Rotation
16980
16985
 
16981
16986
  `Editor#rotateShapesBy` rotates shapes by a delta in radians around a common center point. The editor calculates the center of all the shapes' rotated bounds, then rotates each shape around that point and around its own origin: shapes orbit the selection center while also rotating individually. Pass `{ center }` to rotate around a different point.
package/RELEASE_NOTES.md CHANGED
@@ -1,43 +1,9 @@
1
1
  # Releases
2
2
 
3
- Version: `5.6.0`
3
+ Version: `5.7.0-next.433c23fa9ce6`
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.6.0
8
-
9
- So far this release adds a `ThrottledFunction` type to `@tldraw/utils`, thins the hinted shape outline, and fixes bugs in resizing, page duplication, local persistence, the store, and sync.
10
-
11
- ### API changes
12
-
13
- - Add a `ThrottledFunction<T>` type to `@tldraw/utils` for annotating the result of `throttle`. `throttle` now returns this type, with the same runtime behavior. ([#10927](https://github.com/tldraw/tldraw/pull/10927))
14
- - Add `isAvailable(editor)`, `isEnabled(editor)` and `isChecked(editor)` to actions. Menu items built with `TldrawUiMenuActionItem` and `TldrawUiMenuActionCheckboxItem` read them: an unavailable action is hidden, a disabled one is greyed out or hidden depending on `whenDisabled: 'hide' | 'disable'`. `useSomeActionsEnabled` returns whether any of the given actions is available and enabled, so a submenu can hide when none of its items can run. If you replace a built-in action with a new object instead of spreading it, it loses its gating, and a toggle's checkbox always shows as unchecked. ([#11038](https://github.com/tldraw/tldraw/pull/11038))
15
- - `TldrawUiMenuActionItem` now disables itself when its action's `isEnabled` returns false, so custom menus that render built-in actions grey them out when they can't run. The public menu item wrappers, such as `GroupMenuItem`, `FrameSelectionMenuItem` and `ArrangeMenuSubmenu`, now also hide outside the select tool, where their actions do nothing. ([#11038](https://github.com/tldraw/tldraw/pull/11038))
16
-
17
- ### Improvements
18
-
19
- - Menus no longer offer actions that would do nothing: grouping locked shapes, flipping a locked shape, unlocking when nothing is locked, exporting all shapes on an empty page, moving to a new page at the page limit, and grouping an arrow away from a shape it's bound to. The main menu hides Paste, instead of disabling it, in browsers that can't read the clipboard. ([#11038](https://github.com/tldraw/tldraw/pull/11038))
20
- - Draw the hinted outline around shapes, such as a frame you're dragging a shape into, at 2px instead of 2.5px. ([#10952](https://github.com/tldraw/tldraw/pull/10952))
21
- - Speed up `store.query.index()` and `store.query.ids()` updates by no longer allocating for each change. ([#10228](https://github.com/tldraw/tldraw/pull/10228))
22
-
23
- ### Bug fixes
24
-
25
- - Fix the edge scrolling preference showing as off when edge scrolling is on at a speed other than 1, such as 0.5 or 2. ([#11038](https://github.com/tldraw/tldraw/pull/11038))
26
- - Fix three resize issues: flipping a rotated selection gave its children the wrong rotation, shapes not aligned with the selection received `onResizeStart` and `onResizeEnd` more than once, and `resizeBox` slid the fixed edge when a shape hit its `maxWidth` or `maxHeight`. ([#10351](https://github.com/tldraw/tldraw/pull/10351))
27
- - Fix duplicating a page moving its shapes when they were off screen, and starting the new page with the current page's camera instead of the duplicated page's. ([#10465](https://github.com/tldraw/tldraw/pull/10465))
28
- - Fix the arrow tool's precise mode carrying over when you move to a different target shape. ([#10244](https://github.com/tldraw/tldraw/pull/10244))
29
- - Fix holding Cmd/Ctrl+Shift+Arrow switching from selecting a parent or child to selecting the adjacent shape once the key starts repeating. ([#10184](https://github.com/tldraw/tldraw/pull/10184))
30
- - Fix `editor.setCursor` throwing for the rotate and resize cursor types, and hex cursor colors breaking SVG cursors. ([#10350](https://github.com/tldraw/tldraw/pull/10350))
31
- - Fix edits being lost when an editor remounts with the same `persistenceKey` while the previous one is still saving. ([#10752](https://github.com/tldraw/tldraw/pull/10752))
32
- - Fix store changes made in the last frame before a listener is removed never reaching that listener. ([#10802](https://github.com/tldraw/tldraw/pull/10802))
33
- - Fix a reaction that writes to the store re-running on every unrelated store change. ([#10236](https://github.com/tldraw/tldraw/pull/10236))
34
- - Fix undo restoring an in-between state after a single `put` updated the same record twice. ([#10203](https://github.com/tldraw/tldraw/pull/10203))
35
- - Fix `migrateStoreSnapshot` throwing on a malformed persisted schema instead of returning a migration error. ([#10220](https://github.com/tldraw/tldraw/pull/10220))
36
- - Fix migrations rerunning on records when a persisted schema's sequence version isn't a number. ([#10917](https://github.com/tldraw/tldraw/pull/10917))
37
- - Fix a resumed sync session on a hibernating host skipping the version checks made on first connect, so after a server redeploy a client could be sent changes its schema couldn't handle. It's now rejected with `SERVER_TOO_OLD` or `CLIENT_TOO_OLD`, as on connect. ([#10122](https://github.com/tldraw/tldraw/pull/10122))
38
- - Fix a record field set to `undefined` getting the sync session kicked with `INVALID_RECORD`, and ignore `__proto__` keys in incoming changes. ([#10118](https://github.com/tldraw/tldraw/pull/10118))
39
- - Fix older sync clients (protocol version 7) silently falling out of sync when the server sent them text-append changes they don't support. ([#10095](https://github.com/tldraw/tldraw/pull/10095))
40
-
41
7
  ## v5.5.0
42
8
 
43
9
  [View on GitHub](https://github.com/tldraw/tldraw/releases/tag/v5.5.0)
@@ -432,6 +432,7 @@ export declare class ArrowShapeUtil extends ShapeUtil<TLArrowShape> {
432
432
  } & Partial<Omit<TLArrowShape, "id" | "meta" | "props" | "type">>) | undefined;
433
433
  onTranslate(initialShape: TLArrowShape, shape: TLArrowShape): void;
434
434
  private readonly _resizeInitialBindings;
435
+ canFlip(): boolean;
435
436
  onResize(shape: TLArrowShape, info: TLResizeInfo<TLArrowShape>): {
436
437
  props: {
437
438
  bend: number;
@@ -1685,6 +1686,7 @@ export declare class DrawShapeUtil extends ShapeUtil<TLDrawShape> {
1685
1686
  getIndicatorPath(shape: TLDrawShape): Path2D;
1686
1687
  toSvg(shape: TLDrawShape, ctx: SvgExportContext): JSX.Element;
1687
1688
  getCanvasSvgDefs(): TLShapeUtilCanvasSvgDef[];
1689
+ canFlip(): boolean;
1688
1690
  onResize(shape: TLDrawShape, info: TLResizeInfo<TLDrawShape>): {
1689
1691
  props: {
1690
1692
  scaleX: number;
@@ -2304,6 +2306,7 @@ export declare class GeoShapeUtil extends BaseBoxShapeUtil<TLGeoShape> {
2304
2306
  getIndicatorPath(shape: TLGeoShape): Path2D | undefined;
2305
2307
  toSvg(shape: TLGeoShape, ctx: SvgExportContext): JSX.Element;
2306
2308
  getCanvasSvgDefs(): TLShapeUtilCanvasSvgDef[];
2309
+ canFlip(): boolean;
2307
2310
  onResize(shape: TLGeoShape, { handle, newPoint, scaleX, scaleY, initialShape }: TLResizeInfo<TLGeoShape>): {
2308
2311
  props: {
2309
2312
  flipX: boolean;
@@ -2779,6 +2782,7 @@ export declare class HighlightShapeUtil extends ShapeUtil<TLHighlightShape> {
2779
2782
  getIndicatorPath(shape: TLHighlightShape): Path2D;
2780
2783
  toSvg(shape: TLHighlightShape, ctx: SvgExportContext): JSX.Element;
2781
2784
  toBackgroundSvg(shape: TLHighlightShape, ctx: SvgExportContext): JSX.Element;
2785
+ canFlip(): boolean;
2782
2786
  onResize(shape: TLHighlightShape, info: TLResizeInfo<TLHighlightShape>): {
2783
2787
  props: {
2784
2788
  scaleX: number;
@@ -2844,6 +2848,7 @@ export declare class ImageShapeUtil extends BaseBoxShapeUtil<TLImageShape> {
2844
2848
  createShapeForAsset(asset: TLAsset, position: VecModel): null | TLShapePartial;
2845
2849
  getGeometry(shape: TLImageShape): Geometry2d;
2846
2850
  getAriaDescriptor(shape: TLImageShape): string;
2851
+ canFlip(): boolean;
2847
2852
  onResize(shape: TLImageShape, info: TLResizeInfo<TLImageShape>): TLImageShape;
2848
2853
  component(shape: TLImageShape): JSX.Element;
2849
2854
  getIndicatorPath(shape: TLImageShape): Path2D | undefined;
@@ -2923,6 +2928,7 @@ export declare class LineShapeUtil extends ShapeUtil<TLLineShape> {
2923
2928
  getDefaultProps(): TLLineShape['props'];
2924
2929
  getGeometry(shape: TLLineShape): PathBuilderGeometry2d;
2925
2930
  getHandles(shape: TLLineShape): TLHandle[];
2931
+ canFlip(): boolean;
2926
2932
  onResize(shape: TLLineShape, info: TLResizeInfo<TLLineShape>): {
2927
2933
  props: {
2928
2934
  points: {
@@ -4932,19 +4938,21 @@ export declare interface TLUiActionItem<TransationKey extends string = string, I
4932
4938
  label?: {
4933
4939
  [key: string]: TransationKey;
4934
4940
  } | TransationKey;
4941
+ /** When `true`, the action runs while the editor is readonly. Defaults to `false`. */
4935
4942
  readonlyOk?: boolean;
4936
4943
  checkbox?: boolean;
4937
4944
  isRequiredA11yAction?: boolean;
4938
4945
  /**
4939
4946
  * Whether the action exists in the current context at all, e.g. clipboard support or debug
4940
- * mode. Menus hide the item when it returns false (the keyboard shortcuts dialog still lists
4941
- * it); keyboard shortcuts ignore it. Must be pure and read only editor state.
4947
+ * mode. When false, menus hide the item (the keyboard shortcuts dialog still lists it) and the
4948
+ * action doesn't run from a menu, a shortcut or `useActions()`. Must be pure and read only
4949
+ * editor state.
4942
4950
  */
4943
4951
  isAvailable?(editor: Editor): boolean;
4944
4952
  /**
4945
- * Whether the action can run now. Menus disable or hide the item when it returns false;
4946
- * keyboard shortcuts ignore it. Must be pure and read only editor state: menus re-run it when
4947
- * that state changes, so anything else it reads goes stale.
4953
+ * Whether the action can run now. When false, menus disable or hide the item and the action
4954
+ * doesn't run from a menu, a shortcut or `useActions()`. Must be pure and read only editor
4955
+ * state: menus re-run it when that state changes, so anything else it reads goes stale.
4948
4956
  */
4949
4957
  isEnabled?(editor: Editor): boolean;
4950
4958
  /** For checkbox actions: whether the item shows as checked. Must be pure and read only editor state. */
@@ -5635,6 +5643,10 @@ export declare type TLUiOverrideHelpers = ReturnType<typeof useDefaultHelpers>;
5635
5643
 
5636
5644
  /** @public */
5637
5645
  export declare interface TLUiOverrides {
5646
+ /**
5647
+ * The `actions` passed in aren't gated yet: calling one's `onSelect` here skips the readonly
5648
+ * check, `isAvailable` and `isEnabled`.
5649
+ */
5638
5650
  actions?(editor: Editor, actions: TLUiActionsContextType, helpers: TLUiOverrideHelpers): TLUiActionsContextType;
5639
5651
  tools?(editor: Editor, tools: TLUiToolsContextType, helpers: TLUiOverrideHelpers): TLUiToolsContextType;
5640
5652
  translations?: TLUiTranslationProviderProps['overrides'];
package/dist-cjs/index.js CHANGED
@@ -671,7 +671,7 @@ var import_buildFromV1Document = require("./lib/utils/tldr/buildFromV1Document")
671
671
  var import_file = require("./lib/utils/tldr/file");
672
672
  (0, import_editor.registerTldrawLibraryVersion)(
673
673
  "tldraw",
674
- "5.6.0",
674
+ "5.7.0-next.433c23fa9ce6",
675
675
  "cjs"
676
676
  );
677
677
  //# sourceMappingURL=index.js.map
@@ -512,6 +512,9 @@ class ArrowShapeUtil extends import_editor.ShapeUtil {
512
512
  }
513
513
  }
514
514
  _resizeInitialBindings = new import_editor.WeakCache();
515
+ canFlip() {
516
+ return true;
517
+ }
515
518
  onResize(shape, info) {
516
519
  const { scaleX, scaleY } = info;
517
520
  const bindings = this._resizeInitialBindings.get(