tldraw 4.1.0-canary.e4499a57ef5b → 4.1.0-next.0df13eab91e1

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 (75) hide show
  1. package/dist-cjs/index.js +1 -1
  2. package/dist-cjs/lib/canvas/TldrawCropHandles.js +1 -1
  3. package/dist-cjs/lib/canvas/TldrawScribble.js +1 -1
  4. package/dist-cjs/lib/canvas/TldrawSelectionForeground.js +1 -1
  5. package/dist-cjs/lib/defaultExternalContentHandlers.js +1 -1
  6. package/dist-cjs/lib/defaultExternalContentHandlers.js.map +2 -2
  7. package/dist-cjs/lib/shapes/arrow/curved-arrow.js +8 -2
  8. package/dist-cjs/lib/shapes/arrow/curved-arrow.js.map +2 -2
  9. package/dist-cjs/lib/shapes/arrow/straight-arrow.js +4 -1
  10. package/dist-cjs/lib/shapes/arrow/straight-arrow.js.map +2 -2
  11. package/dist-cjs/lib/shapes/bookmark/BookmarkShapeUtil.js +1 -1
  12. package/dist-cjs/lib/shapes/frame/FrameShapeUtil.js +1 -1
  13. package/dist-cjs/lib/shapes/image/ImageShapeUtil.js +1 -1
  14. package/dist-cjs/lib/shapes/shared/HyperlinkButton.js +1 -1
  15. package/dist-cjs/lib/shapes/shared/PlainTextLabel.js +1 -1
  16. package/dist-cjs/lib/shapes/shared/RichTextLabel.js +2 -2
  17. package/dist-cjs/lib/shapes/shared/RichTextLabel.js.map +2 -2
  18. package/dist-cjs/lib/shapes/shared/ShapeFill.js +1 -1
  19. package/dist-cjs/lib/shapes/text/PlainTextArea.js +1 -1
  20. package/dist-cjs/lib/shapes/text/RichTextArea.js +1 -1
  21. package/dist-cjs/lib/shapes/video/VideoShapeUtil.js +1 -1
  22. package/dist-cjs/lib/ui/TldrawUi.js +2 -2
  23. package/dist-cjs/lib/ui/components/DebugMenu/DefaultDebugMenuContent.js +1 -1
  24. package/dist-cjs/lib/ui/components/KeyboardShortcutsDialog/DefaultKeyboardShortcutsDialog.js +1 -1
  25. package/dist-cjs/lib/ui/components/Minimap/DefaultMinimap.js +1 -1
  26. package/dist-cjs/lib/ui/components/OfflineIndicator/OfflineIndicator.js +1 -1
  27. package/dist-cjs/lib/ui/components/SharePanel/UserPresenceColorPicker.js +1 -1
  28. package/dist-cjs/lib/ui/components/StylePanel/DefaultStylePanel.js +1 -1
  29. package/dist-cjs/lib/ui/components/StylePanel/DefaultStylePanelContent.js +1 -1
  30. package/dist-cjs/lib/ui/components/StylePanel/StylePanelDoubleDropdownPicker.js +1 -1
  31. package/dist-cjs/lib/ui/components/StylePanel/StylePanelDropdownPicker.js +1 -1
  32. package/dist-cjs/lib/ui/components/Toolbar/DefaultToolbar.js +1 -1
  33. package/dist-cjs/lib/ui/components/Toolbar/OverflowingToolbar.js +1 -1
  34. package/dist-cjs/lib/ui/components/Toolbar/ToggleToolLockedButton.js +1 -1
  35. package/dist-cjs/lib/ui/components/primitives/Button/TldrawUiButton.js +2 -2
  36. package/dist-cjs/lib/ui/components/primitives/TldrawUiContextualToolbar.js +1 -1
  37. package/dist-cjs/lib/ui/components/primitives/TldrawUiDialog.js +1 -1
  38. package/dist-cjs/lib/ui/components/primitives/TldrawUiDropdownMenu.js +1 -1
  39. package/dist-cjs/lib/ui/components/primitives/TldrawUiIcon.js +1 -1
  40. package/dist-cjs/lib/ui/components/primitives/TldrawUiInput.js +2 -2
  41. package/dist-cjs/lib/ui/components/primitives/TldrawUiPopover.js +2 -2
  42. package/dist-cjs/lib/ui/components/primitives/TldrawUiSlider.js +1 -1
  43. package/dist-cjs/lib/ui/components/primitives/TldrawUiToolbar.js +2 -2
  44. package/dist-cjs/lib/ui/components/primitives/TldrawUiTooltip.js +1 -1
  45. package/dist-cjs/lib/ui/components/primitives/layout.js +1 -1
  46. package/dist-cjs/lib/ui/components/primitives/menus/TldrawUiMenuGroup.js +1 -1
  47. package/dist-cjs/lib/ui/context/actions.js +1 -1
  48. package/dist-cjs/lib/ui/context/breakpoints.js +1 -1
  49. package/dist-cjs/lib/ui/context/events.js +1 -1
  50. package/dist-cjs/lib/ui/hooks/useClipboardEvents.js +1 -1
  51. package/dist-cjs/lib/ui/hooks/useKeyboardShortcuts.js +1 -1
  52. package/dist-cjs/lib/ui/hooks/useLocalStorageState.js +1 -1
  53. package/dist-cjs/lib/ui/hooks/useTools.js +1 -1
  54. package/dist-cjs/lib/ui/hooks/useTranslation/useTranslation.js +1 -1
  55. package/dist-cjs/lib/ui/version.js +3 -3
  56. package/dist-cjs/lib/ui/version.js.map +1 -1
  57. package/dist-cjs/lib/utils/text/richText.js +4 -4
  58. package/dist-esm/index.mjs +1 -1
  59. package/dist-esm/lib/defaultExternalContentHandlers.mjs +1 -1
  60. package/dist-esm/lib/defaultExternalContentHandlers.mjs.map +2 -2
  61. package/dist-esm/lib/shapes/arrow/curved-arrow.mjs +8 -2
  62. package/dist-esm/lib/shapes/arrow/curved-arrow.mjs.map +2 -2
  63. package/dist-esm/lib/shapes/arrow/straight-arrow.mjs +4 -1
  64. package/dist-esm/lib/shapes/arrow/straight-arrow.mjs.map +2 -2
  65. package/dist-esm/lib/shapes/shared/RichTextLabel.mjs +1 -1
  66. package/dist-esm/lib/shapes/shared/RichTextLabel.mjs.map +2 -2
  67. package/dist-esm/lib/ui/version.mjs +3 -3
  68. package/dist-esm/lib/ui/version.mjs.map +1 -1
  69. package/package.json +11 -11
  70. package/src/lib/defaultExternalContentHandlers.ts +1 -1
  71. package/src/lib/shapes/arrow/ArrowShapeUtil.test.ts +211 -1
  72. package/src/lib/shapes/arrow/curved-arrow.ts +8 -2
  73. package/src/lib/shapes/arrow/straight-arrow.ts +5 -1
  74. package/src/lib/shapes/shared/RichTextLabel.tsx +1 -1
  75. package/src/lib/ui/version.ts +3 -3
@@ -1,7 +1,7 @@
1
1
  import { HALF_PI, TLArrowShape, TLShapeId, createShapeId, toRichText } from '@tldraw/editor'
2
2
  import { vi } from 'vitest'
3
3
  import { TestEditor } from '../../../test/TestEditor'
4
- import { createOrUpdateArrowBinding, getArrowBindings } from './shared'
4
+ import { createOrUpdateArrowBinding, getArrowBindings, getArrowInfo } from './shared'
5
5
 
6
6
  let editor: TestEditor
7
7
 
@@ -620,3 +620,213 @@ describe('Arrow export bounds', () => {
620
620
  expect(arrow.props.richText).not.toBeNull()
621
621
  })
622
622
  })
623
+
624
+ describe('Arrow terminal positioning bug fix', () => {
625
+ const data = {
626
+ document: {
627
+ store: {
628
+ 'shape:1Hm61DGAsY0uqEO-kt75l': {
629
+ x: 637.2890625,
630
+ y: 383.9296875,
631
+ rotation: 0,
632
+ isLocked: false,
633
+ opacity: 1,
634
+ meta: {},
635
+ id: 'shape:1Hm61DGAsY0uqEO-kt75l',
636
+ type: 'geo',
637
+ props: {
638
+ w: 230.66796875,
639
+ h: 114.796875,
640
+ geo: 'rectangle',
641
+ dash: 'draw',
642
+ growY: 0,
643
+ url: '',
644
+ scale: 1,
645
+ color: 'black',
646
+ labelColor: 'black',
647
+ fill: 'none',
648
+ size: 'm',
649
+ font: 'draw',
650
+ align: 'middle',
651
+ verticalAlign: 'middle',
652
+ richText: {
653
+ type: 'doc',
654
+ content: [
655
+ {
656
+ type: 'paragraph',
657
+ },
658
+ ],
659
+ },
660
+ },
661
+ parentId: 'page:page',
662
+ index: 'a1',
663
+ typeName: 'shape',
664
+ },
665
+ 'binding:nekxhMCGaoEJO98DEqWgo': {
666
+ meta: {},
667
+ id: 'binding:nekxhMCGaoEJO98DEqWgo',
668
+ type: 'arrow',
669
+ fromId: 'shape:j0HKQihjBXqMqgVhfRhDS',
670
+ toId: 'shape:1Hm61DGAsY0uqEO-kt75l',
671
+ props: {
672
+ isPrecise: true,
673
+ isExact: false,
674
+ normalizedAnchor: {
675
+ x: 0.13182672605036325,
676
+ y: 0.8036953858717844,
677
+ },
678
+ snap: 'none',
679
+ terminal: 'start',
680
+ },
681
+ typeName: 'binding',
682
+ },
683
+ 'binding:kWamalL_QSq_kFPZDgp7Z': {
684
+ meta: {},
685
+ id: 'binding:kWamalL_QSq_kFPZDgp7Z',
686
+ type: 'arrow',
687
+ fromId: 'shape:j0HKQihjBXqMqgVhfRhDS',
688
+ toId: 'shape:1Hm61DGAsY0uqEO-kt75l',
689
+ props: {
690
+ isPrecise: true,
691
+ isExact: false,
692
+ normalizedAnchor: {
693
+ x: 0.7138744475114731,
694
+ y: 0.45797604464407243,
695
+ },
696
+ snap: 'none',
697
+ terminal: 'end',
698
+ },
699
+ typeName: 'binding',
700
+ },
701
+ 'shape:j0HKQihjBXqMqgVhfRhDS': {
702
+ x: 665.296875,
703
+ y: 477.59765625,
704
+ rotation: 0,
705
+ isLocked: false,
706
+ opacity: 1,
707
+ meta: {},
708
+ id: 'shape:j0HKQihjBXqMqgVhfRhDS',
709
+ type: 'arrow',
710
+ props: {
711
+ kind: 'arc',
712
+ elbowMidPoint: 0.5,
713
+ dash: 'draw',
714
+ size: 'm',
715
+ fill: 'none',
716
+ color: 'black',
717
+ labelColor: 'black',
718
+ bend: 0,
719
+ start: {
720
+ x: 0,
721
+ y: 0,
722
+ },
723
+ end: {
724
+ x: 2,
725
+ y: 0,
726
+ },
727
+ arrowheadStart: 'none',
728
+ arrowheadEnd: 'arrow',
729
+ richText: {
730
+ type: 'doc',
731
+ content: [
732
+ {
733
+ type: 'paragraph',
734
+ },
735
+ ],
736
+ },
737
+ labelPosition: 0.5,
738
+ font: 'draw',
739
+ scale: 1,
740
+ },
741
+ parentId: 'page:page',
742
+ index: 'a2lbpzZG',
743
+ typeName: 'shape',
744
+ },
745
+ 'page:page': {
746
+ meta: {},
747
+ id: 'page:page',
748
+ name: 'Page 1',
749
+ index: 'a1',
750
+ typeName: 'page',
751
+ },
752
+ 'document:document': {
753
+ gridSize: 10,
754
+ name: '',
755
+ meta: {},
756
+ id: 'document:document',
757
+ typeName: 'document',
758
+ },
759
+ },
760
+ schema: {
761
+ schemaVersion: 2,
762
+ sequences: {
763
+ 'com.tldraw.store': 5,
764
+ 'com.tldraw.asset': 1,
765
+ 'com.tldraw.camera': 1,
766
+ 'com.tldraw.document': 2,
767
+ 'com.tldraw.instance': 25,
768
+ 'com.tldraw.instance_page_state': 5,
769
+ 'com.tldraw.page': 1,
770
+ 'com.tldraw.instance_presence': 6,
771
+ 'com.tldraw.pointer': 1,
772
+ 'com.tldraw.shape': 4,
773
+ 'com.tldraw.asset.bookmark': 2,
774
+ 'com.tldraw.asset.image': 5,
775
+ 'com.tldraw.asset.video': 5,
776
+ 'com.tldraw.shape.group': 0,
777
+ 'com.tldraw.shape.text': 3,
778
+ 'com.tldraw.shape.bookmark': 2,
779
+ 'com.tldraw.shape.draw': 2,
780
+ 'com.tldraw.shape.geo': 10,
781
+ 'com.tldraw.shape.note': 9,
782
+ 'com.tldraw.shape.line': 5,
783
+ 'com.tldraw.shape.frame': 1,
784
+ 'com.tldraw.shape.arrow': 7,
785
+ 'com.tldraw.shape.highlight': 1,
786
+ 'com.tldraw.shape.embed': 4,
787
+ 'com.tldraw.shape.image': 5,
788
+ 'com.tldraw.shape.video': 4,
789
+ 'com.tldraw.binding.arrow': 1,
790
+ },
791
+ },
792
+ },
793
+ session: {
794
+ version: 0,
795
+ currentPageId: 'page:page',
796
+ exportBackground: true,
797
+ isFocusMode: false,
798
+ isDebugMode: false,
799
+ isToolLocked: false,
800
+ isGridMode: false,
801
+ pageStates: [
802
+ {
803
+ pageId: 'page:page',
804
+ camera: {
805
+ x: 0,
806
+ y: 0,
807
+ z: 1,
808
+ },
809
+ selectedShapeIds: ['shape:j0HKQihjBXqMqgVhfRhDS'],
810
+ focusedGroupId: null,
811
+ },
812
+ ],
813
+ },
814
+ }
815
+
816
+ it('should position straight arrow terminals on shape boundary, not text label boundary', () => {
817
+ // Create a geo shape with text label
818
+ editor.loadSnapshot(data as any)
819
+
820
+ const arrow = editor.getShape('shape:j0HKQihjBXqMqgVhfRhDS' as TLShapeId) as TLArrowShape
821
+ expect(arrow).toBeDefined()
822
+
823
+ expect(getArrowBindings(editor, arrow)).toMatchObject({
824
+ end: { props: { isPrecise: true } },
825
+ start: { props: { isPrecise: true } },
826
+ })
827
+
828
+ const info = getArrowInfo(editor, arrow)
829
+ expect(info?.start.handle).toEqual(info?.start.point)
830
+ expect(info?.end.handle).toEqual(info?.end.point)
831
+ })
832
+ })
@@ -154,7 +154,10 @@ export function getCurvedArrowInfo(
154
154
  }
155
155
  if (!point) {
156
156
  if (isClosed) {
157
- const nearestPoint = startShapeInfo.geometry.nearestPoint(startInStartShapeLocalSpace)
157
+ const nearestPoint = startShapeInfo.geometry.nearestPoint(startInStartShapeLocalSpace, {
158
+ includeInternal: false,
159
+ includeLabels: false,
160
+ })
158
161
  if (Vec.DistMin(nearestPoint, startInStartShapeLocalSpace, 1)) {
159
162
  point = nearestPoint
160
163
  }
@@ -233,7 +236,10 @@ export function getCurvedArrowInfo(
233
236
  }
234
237
  if (!point) {
235
238
  if (isClosed) {
236
- const nearestPoint = endShapeInfo.geometry.nearestPoint(endInEndShapeLocalSpace)
239
+ const nearestPoint = endShapeInfo.geometry.nearestPoint(endInEndShapeLocalSpace, {
240
+ includeInternal: false,
241
+ includeLabels: false,
242
+ })
237
243
  if (Vec.DistMin(nearestPoint, endInEndShapeLocalSpace, 1)) {
238
244
  point = nearestPoint
239
245
  }
@@ -248,7 +248,11 @@ function updateArrowheadPointWithBoundShape(
248
248
  if (targetInt === undefined) {
249
249
  // No intersection? The arrowhead point will be at the arrow terminal.
250
250
  // if we _almost_ hit the target, just put the arrowhead at the target.
251
- targetInt = targetShapeInfo.geometry.nearestPoint(targetTo)
251
+ targetInt = targetShapeInfo.geometry.nearestPoint(targetTo, {
252
+ includeLabels: false,
253
+ includeInternal: false,
254
+ })
255
+
252
256
  if (!Vec.DistMin(targetInt, targetTo, 1)) {
253
257
  return
254
258
  }
@@ -109,7 +109,7 @@ export const RichTextLabel = React.memo(function RichTextLabel({
109
109
  // We don't get the mouseup event later because we preventDefault
110
110
  // so we have to do it manually.
111
111
  const handlePointerUp = (e: TLEventInfo) => {
112
- if (e.name !== 'pointer_up') return
112
+ if (e.name !== 'pointer_up' || !link) return
113
113
 
114
114
  if (!isDragging.current) {
115
115
  window.open(link, '_blank', 'noopener, noreferrer')
@@ -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 = '4.1.0-canary.e4499a57ef5b'
4
+ export const version = '4.1.0-next.0df13eab91e1'
5
5
  export const publishDates = {
6
6
  major: '2025-09-18T14:39:22.803Z',
7
- minor: '2025-09-19T11:41:15.460Z',
8
- patch: '2025-09-19T11:41:15.460Z',
7
+ minor: '2025-10-01T09:28:43.241Z',
8
+ patch: '2025-10-01T09:28:43.241Z',
9
9
  }