tldraw 4.3.0-next.7810f2131b3c → 4.3.0-next.7f179bd04d6c
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist-cjs/index.d.ts +14 -5
- package/dist-cjs/index.js +1 -1
- package/dist-cjs/lib/bindings/arrow/ArrowBindingUtil.js.map +2 -2
- package/dist-cjs/lib/canvas/TldrawSelectionForeground.js.map +2 -2
- package/dist-cjs/lib/defaultExternalContentHandlers.js.map +2 -2
- package/dist-cjs/lib/shapes/arrow/ArrowShapeUtil.js.map +2 -2
- package/dist-cjs/lib/shapes/arrow/arrowLabel.js.map +2 -2
- package/dist-cjs/lib/shapes/arrow/arrowTargetState.js.map +2 -2
- package/dist-cjs/lib/shapes/arrow/elbow/elbowArrowSnapLines.js.map +2 -2
- package/dist-cjs/lib/shapes/arrow/shared.js.map +2 -2
- package/dist-cjs/lib/shapes/arrow/toolStates/Pointing.js.map +2 -2
- package/dist-cjs/lib/shapes/bookmark/bookmarks.js.map +2 -2
- package/dist-cjs/lib/shapes/draw/toolStates/Drawing.js.map +2 -2
- package/dist-cjs/lib/shapes/embed/EmbedShapeUtil.js.map +2 -2
- package/dist-cjs/lib/shapes/frame/FrameShapeTool.js.map +1 -1
- package/dist-cjs/lib/shapes/geo/toolStates/Pointing.js.map +2 -2
- package/dist-cjs/lib/shapes/line/toolStates/Pointing.js.map +2 -2
- package/dist-cjs/lib/shapes/note/noteHelpers.js.map +2 -2
- package/dist-cjs/lib/shapes/shared/PlainTextLabel.js.map +2 -2
- package/dist-cjs/lib/shapes/shared/RichTextLabel.js.map +2 -2
- package/dist-cjs/lib/shapes/shared/crop.js +1 -0
- package/dist-cjs/lib/shapes/shared/crop.js.map +2 -2
- package/dist-cjs/lib/shapes/shared/useEditablePlainText.js.map +2 -2
- package/dist-cjs/lib/shapes/shared/useEditableRichText.js.map +2 -2
- package/dist-cjs/lib/shapes/text/toolStates/Pointing.js.map +2 -2
- package/dist-cjs/lib/tools/EraserTool/childStates/Erasing.js.map +2 -2
- package/dist-cjs/lib/tools/EraserTool/childStates/Pointing.js.map +2 -2
- package/dist-cjs/lib/tools/SelectTool/DragAndDropManager.js +1 -4
- package/dist-cjs/lib/tools/SelectTool/DragAndDropManager.js.map +2 -2
- package/dist-cjs/lib/tools/SelectTool/childStates/Brushing.js.map +2 -2
- package/dist-cjs/lib/tools/SelectTool/childStates/Crop/children/Idle.js.map +2 -2
- package/dist-cjs/lib/tools/SelectTool/childStates/DraggingHandle.js +1 -1
- package/dist-cjs/lib/tools/SelectTool/childStates/DraggingHandle.js.map +2 -2
- package/dist-cjs/lib/tools/SelectTool/childStates/EditingShape.js.map +2 -2
- package/dist-cjs/lib/tools/SelectTool/childStates/Idle.js.map +2 -2
- package/dist-cjs/lib/tools/SelectTool/childStates/PointingArrowLabel.js.map +2 -2
- package/dist-cjs/lib/tools/SelectTool/childStates/PointingHandle.js.map +2 -2
- package/dist-cjs/lib/tools/SelectTool/childStates/PointingSelection.js.map +2 -2
- package/dist-cjs/lib/tools/SelectTool/childStates/Resizing.js.map +2 -2
- package/dist-cjs/lib/tools/SelectTool/childStates/ScribbleBrushing.js.map +2 -2
- package/dist-cjs/lib/tools/SelectTool/childStates/Translating.js.map +2 -2
- package/dist-cjs/lib/ui/components/EditLinkDialog.js +11 -1
- package/dist-cjs/lib/ui/components/EditLinkDialog.js.map +2 -2
- package/dist-cjs/lib/ui/components/Toolbar/AltTextEditor.js.map +2 -2
- package/dist-cjs/lib/ui/components/menu-items.js.map +2 -2
- package/dist-cjs/lib/ui/context/actions.js +1 -2
- package/dist-cjs/lib/ui/context/actions.js.map +2 -2
- package/dist-cjs/lib/ui/hooks/menu-hooks.js.map +2 -2
- package/dist-cjs/lib/ui/hooks/useFlatten.js.map +2 -2
- package/dist-cjs/lib/ui/hooks/useTools.js.map +2 -2
- package/dist-cjs/lib/ui/version.js +3 -3
- package/dist-cjs/lib/ui/version.js.map +1 -1
- package/dist-cjs/lib/utils/excalidraw/putExcalidrawContent.js +8 -0
- package/dist-cjs/lib/utils/excalidraw/putExcalidrawContent.js.map +2 -2
- package/dist-cjs/lib/utils/export/exportAs.js.map +2 -2
- package/dist-cjs/lib/utils/frames/frames.js.map +2 -2
- package/dist-cjs/lib/utils/tldr/buildFromV1Document.js.map +2 -2
- package/dist-esm/index.d.mts +14 -5
- package/dist-esm/index.mjs +1 -1
- package/dist-esm/lib/bindings/arrow/ArrowBindingUtil.mjs.map +2 -2
- package/dist-esm/lib/canvas/TldrawSelectionForeground.mjs.map +2 -2
- package/dist-esm/lib/defaultExternalContentHandlers.mjs.map +2 -2
- package/dist-esm/lib/shapes/arrow/ArrowShapeUtil.mjs.map +2 -2
- package/dist-esm/lib/shapes/arrow/arrowLabel.mjs.map +2 -2
- package/dist-esm/lib/shapes/arrow/arrowTargetState.mjs.map +2 -2
- package/dist-esm/lib/shapes/arrow/elbow/elbowArrowSnapLines.mjs.map +2 -2
- package/dist-esm/lib/shapes/arrow/shared.mjs.map +2 -2
- package/dist-esm/lib/shapes/arrow/toolStates/Pointing.mjs.map +2 -2
- package/dist-esm/lib/shapes/bookmark/bookmarks.mjs.map +2 -2
- package/dist-esm/lib/shapes/draw/toolStates/Drawing.mjs.map +2 -2
- package/dist-esm/lib/shapes/embed/EmbedShapeUtil.mjs.map +2 -2
- package/dist-esm/lib/shapes/frame/FrameShapeTool.mjs.map +1 -1
- package/dist-esm/lib/shapes/geo/toolStates/Pointing.mjs.map +2 -2
- package/dist-esm/lib/shapes/line/toolStates/Pointing.mjs.map +2 -2
- package/dist-esm/lib/shapes/note/noteHelpers.mjs.map +2 -2
- package/dist-esm/lib/shapes/shared/PlainTextLabel.mjs.map +2 -2
- package/dist-esm/lib/shapes/shared/RichTextLabel.mjs.map +2 -2
- package/dist-esm/lib/shapes/shared/crop.mjs +1 -0
- package/dist-esm/lib/shapes/shared/crop.mjs.map +2 -2
- package/dist-esm/lib/shapes/shared/useEditablePlainText.mjs.map +2 -2
- package/dist-esm/lib/shapes/shared/useEditableRichText.mjs.map +2 -2
- package/dist-esm/lib/shapes/text/toolStates/Pointing.mjs.map +2 -2
- package/dist-esm/lib/tools/EraserTool/childStates/Erasing.mjs.map +2 -2
- package/dist-esm/lib/tools/EraserTool/childStates/Pointing.mjs +1 -4
- package/dist-esm/lib/tools/EraserTool/childStates/Pointing.mjs.map +2 -2
- package/dist-esm/lib/tools/SelectTool/DragAndDropManager.mjs +1 -4
- package/dist-esm/lib/tools/SelectTool/DragAndDropManager.mjs.map +2 -2
- package/dist-esm/lib/tools/SelectTool/childStates/Brushing.mjs.map +2 -2
- package/dist-esm/lib/tools/SelectTool/childStates/Crop/children/Idle.mjs.map +2 -2
- package/dist-esm/lib/tools/SelectTool/childStates/DraggingHandle.mjs +1 -1
- package/dist-esm/lib/tools/SelectTool/childStates/DraggingHandle.mjs.map +2 -2
- package/dist-esm/lib/tools/SelectTool/childStates/EditingShape.mjs.map +2 -2
- package/dist-esm/lib/tools/SelectTool/childStates/Idle.mjs.map +2 -2
- package/dist-esm/lib/tools/SelectTool/childStates/PointingArrowLabel.mjs.map +2 -2
- package/dist-esm/lib/tools/SelectTool/childStates/PointingHandle.mjs +1 -4
- package/dist-esm/lib/tools/SelectTool/childStates/PointingHandle.mjs.map +2 -2
- package/dist-esm/lib/tools/SelectTool/childStates/PointingSelection.mjs.map +2 -2
- package/dist-esm/lib/tools/SelectTool/childStates/Resizing.mjs.map +2 -2
- package/dist-esm/lib/tools/SelectTool/childStates/ScribbleBrushing.mjs.map +2 -2
- package/dist-esm/lib/tools/SelectTool/childStates/Translating.mjs.map +2 -2
- package/dist-esm/lib/ui/components/EditLinkDialog.mjs +11 -1
- package/dist-esm/lib/ui/components/EditLinkDialog.mjs.map +2 -2
- package/dist-esm/lib/ui/components/Toolbar/AltTextEditor.mjs.map +2 -2
- package/dist-esm/lib/ui/components/menu-items.mjs +1 -4
- package/dist-esm/lib/ui/components/menu-items.mjs.map +2 -2
- package/dist-esm/lib/ui/context/actions.mjs +1 -2
- package/dist-esm/lib/ui/context/actions.mjs.map +2 -2
- package/dist-esm/lib/ui/hooks/menu-hooks.mjs +1 -4
- package/dist-esm/lib/ui/hooks/menu-hooks.mjs.map +2 -2
- package/dist-esm/lib/ui/hooks/useFlatten.mjs.map +2 -2
- package/dist-esm/lib/ui/hooks/useTools.mjs.map +2 -2
- package/dist-esm/lib/ui/version.mjs +3 -3
- package/dist-esm/lib/ui/version.mjs.map +1 -1
- package/dist-esm/lib/utils/excalidraw/putExcalidrawContent.mjs +8 -0
- package/dist-esm/lib/utils/excalidraw/putExcalidrawContent.mjs.map +2 -2
- package/dist-esm/lib/utils/export/exportAs.mjs +1 -3
- package/dist-esm/lib/utils/export/exportAs.mjs.map +2 -2
- package/dist-esm/lib/utils/frames/frames.mjs.map +2 -2
- package/dist-esm/lib/utils/tldr/buildFromV1Document.mjs.map +2 -2
- package/package.json +10 -10
- package/src/lib/bindings/arrow/ArrowBindingUtil.ts +1 -1
- package/src/lib/canvas/TldrawSelectionForeground.tsx +4 -9
- package/src/lib/defaultExternalContentHandlers.ts +3 -4
- package/src/lib/shapes/arrow/ArrowShapeUtil.test.ts +2 -2
- package/src/lib/shapes/arrow/ArrowShapeUtil.tsx +1 -1
- package/src/lib/shapes/arrow/arrowLabel.ts +1 -1
- package/src/lib/shapes/arrow/arrowTargetState.ts +1 -1
- package/src/lib/shapes/arrow/elbow/elbowArrowSnapLines.tsx +3 -3
- package/src/lib/shapes/arrow/shared.ts +4 -4
- package/src/lib/shapes/arrow/toolStates/Pointing.tsx +1 -1
- package/src/lib/shapes/bookmark/bookmarks.ts +3 -3
- package/src/lib/shapes/draw/toolStates/Drawing.ts +4 -4
- package/src/lib/shapes/embed/EmbedShapeUtil.tsx +1 -1
- package/src/lib/shapes/frame/FrameShapeTool.ts +1 -1
- package/src/lib/shapes/geo/GeoShapeUtil.test.tsx +10 -2
- package/src/lib/shapes/geo/toolStates/Pointing.ts +3 -3
- package/src/lib/shapes/line/LineShapeTool.test.ts +6 -6
- package/src/lib/shapes/line/LineShapeUtil.test.tsx +5 -5
- package/src/lib/shapes/line/toolStates/Pointing.ts +1 -1
- package/src/lib/shapes/note/NoteShapeTool.test.ts +2 -1
- package/src/lib/shapes/note/noteHelpers.ts +2 -2
- package/src/lib/shapes/shared/PlainTextLabel.tsx +2 -1
- package/src/lib/shapes/shared/RichTextLabel.tsx +2 -1
- package/src/lib/shapes/shared/crop.ts +1 -0
- package/src/lib/shapes/shared/useEditablePlainText.ts +7 -3
- package/src/lib/shapes/shared/useEditableRichText.ts +7 -3
- package/src/lib/shapes/text/TextShapeTool.test.ts +4 -4
- package/src/lib/shapes/text/toolStates/Pointing.ts +1 -1
- package/src/lib/tools/EraserTool/childStates/Erasing.ts +3 -5
- package/src/lib/tools/EraserTool/childStates/Pointing.ts +3 -16
- package/src/lib/tools/SelectTool/DragAndDropManager.ts +2 -4
- package/src/lib/tools/SelectTool/childStates/Brushing.ts +2 -6
- package/src/lib/tools/SelectTool/childStates/Crop/children/Idle.ts +2 -3
- package/src/lib/tools/SelectTool/childStates/DraggingHandle.tsx +4 -7
- package/src/lib/tools/SelectTool/childStates/EditingShape.ts +2 -4
- package/src/lib/tools/SelectTool/childStates/Idle.ts +6 -10
- package/src/lib/tools/SelectTool/childStates/PointingArrowLabel.ts +1 -1
- package/src/lib/tools/SelectTool/childStates/PointingHandle.ts +4 -12
- package/src/lib/tools/SelectTool/childStates/PointingSelection.ts +2 -2
- package/src/lib/tools/SelectTool/childStates/Resizing.ts +2 -4
- package/src/lib/tools/SelectTool/childStates/ScribbleBrushing.ts +2 -4
- package/src/lib/tools/SelectTool/childStates/Translating.ts +1 -3
- package/src/lib/ui/components/EditLinkDialog.tsx +16 -6
- package/src/lib/ui/components/Toolbar/AltTextEditor.tsx +2 -2
- package/src/lib/ui/components/menu-items.tsx +6 -14
- package/src/lib/ui/context/actions.tsx +9 -13
- package/src/lib/ui/hooks/menu-hooks.ts +9 -19
- package/src/lib/ui/hooks/useFlatten.ts +1 -2
- package/src/lib/ui/hooks/useTools.tsx +1 -2
- package/src/lib/ui/version.ts +3 -3
- package/src/lib/utils/excalidraw/putExcalidrawContent.ts +8 -0
- package/src/lib/utils/export/exportAs.ts +2 -9
- package/src/lib/utils/frames/frames.ts +1 -1
- package/src/lib/utils/tldr/buildFromV1Document.ts +12 -17
- package/src/test/Editor.test.tsx +38 -12
- package/src/test/SelectTool.test.ts +11 -19
- package/src/test/TestEditor.ts +1 -4
- package/src/test/TldrawEditor.test.tsx +21 -18
- package/src/test/bindings.test.tsx +29 -25
- package/src/test/bindingsIndex.test.tsx +4 -4
- package/src/test/commands/createShape.test.ts +64 -0
- package/src/test/commands/createShapes.test.ts +15 -1
- package/src/test/commands/getSvgString.test.ts +2 -2
- package/src/test/commands/isShapeOfType.test.ts +44 -0
- package/src/test/commands/putContent.test.ts +1 -0
- package/src/test/commands/updateShape.test.ts +67 -0
- package/src/test/commands/updateShapes.test.ts +21 -5
- package/src/test/custom-clipping.test.ts +36 -35
- package/src/test/customSnapping.test.tsx +77 -62
- package/src/test/duplicate.test.ts +1 -1
- package/src/test/frames.test.ts +2 -2
- package/src/test/getCulledShapes.test.tsx +11 -3
- package/src/test/getShapeAtPoint.test.ts +2 -2
- package/src/test/groups.test.tsx +6 -3
- package/src/test/resizing.test.ts +9 -13
- package/src/test/selection-omnibus.test.ts +11 -11
- package/src/test/shapeutils.test.ts +1 -1
- package/src/test/styles2.test.tsx +1 -1
- package/src/test/styles3.test.ts +5 -5
- package/src/test/test-jsx.tsx +69 -57
- package/src/test/text.test.ts +15 -17
- package/src/test/translating.test.ts +6 -8
|
@@ -3876,10 +3876,8 @@ it('uses the cross cursor when create resizing', () => {
|
|
|
3876
3876
|
describe('Resizing text from the right edge', () => {
|
|
3877
3877
|
it('Resizes text from the right edge', () => {
|
|
3878
3878
|
const id = createShapeId()
|
|
3879
|
-
editor.createShapes
|
|
3880
|
-
editor.updateShapes
|
|
3881
|
-
{ id, type: 'text', props: { richText: toRichText('Hello World') } },
|
|
3882
|
-
]) // auto size
|
|
3879
|
+
editor.createShapes([{ id, type: 'text', props: { richText: toRichText('H') } }])
|
|
3880
|
+
editor.updateShapes([{ id, type: 'text', props: { richText: toRichText('Hello World') } }]) // auto size
|
|
3883
3881
|
|
|
3884
3882
|
editor.select(id)
|
|
3885
3883
|
|
|
@@ -3905,10 +3903,8 @@ describe('Resizing text from the right edge', () => {
|
|
|
3905
3903
|
editor.updateInstanceState({ isCoarsePointer: true })
|
|
3906
3904
|
|
|
3907
3905
|
const id = createShapeId()
|
|
3908
|
-
editor.createShapes
|
|
3909
|
-
editor.updateShapes
|
|
3910
|
-
{ id, type: 'text', props: { richText: toRichText('Hello World') } },
|
|
3911
|
-
]) // auto size
|
|
3906
|
+
editor.createShapes([{ id, type: 'text', props: { richText: toRichText('H') } }])
|
|
3907
|
+
editor.updateShapes([{ id, type: 'text', props: { richText: toRichText('Hello World') } }]) // auto size
|
|
3912
3908
|
|
|
3913
3909
|
editor.select(id)
|
|
3914
3910
|
|
|
@@ -3954,7 +3950,7 @@ describe('When resizing near the edges of the screen', () => {
|
|
|
3954
3950
|
|
|
3955
3951
|
describe('resizing text with autosize true', () => {
|
|
3956
3952
|
it('resizes text from the right side', () => {
|
|
3957
|
-
editor.createShape
|
|
3953
|
+
editor.createShape({
|
|
3958
3954
|
type: 'text',
|
|
3959
3955
|
x: 0,
|
|
3960
3956
|
y: 0,
|
|
@@ -3980,7 +3976,7 @@ describe('resizing text with autosize true', () => {
|
|
|
3980
3976
|
})
|
|
3981
3977
|
|
|
3982
3978
|
it('resizes text from the right side when alt key is pressed', () => {
|
|
3983
|
-
editor.createShape
|
|
3979
|
+
editor.createShape({
|
|
3984
3980
|
type: 'text',
|
|
3985
3981
|
x: 0,
|
|
3986
3982
|
y: 0,
|
|
@@ -4007,7 +4003,7 @@ describe('resizing text with autosize true', () => {
|
|
|
4007
4003
|
})
|
|
4008
4004
|
|
|
4009
4005
|
it('resizes text from the left side', () => {
|
|
4010
|
-
editor.createShape
|
|
4006
|
+
editor.createShape({
|
|
4011
4007
|
type: 'text',
|
|
4012
4008
|
x: 0,
|
|
4013
4009
|
y: 0,
|
|
@@ -4033,7 +4029,7 @@ describe('resizing text with autosize true', () => {
|
|
|
4033
4029
|
})
|
|
4034
4030
|
|
|
4035
4031
|
it('resizes text from the left side when alt is pressed', () => {
|
|
4036
|
-
editor.createShape
|
|
4032
|
+
editor.createShape({
|
|
4037
4033
|
type: 'text',
|
|
4038
4034
|
x: 0,
|
|
4039
4035
|
y: 0,
|
|
@@ -4062,7 +4058,7 @@ describe('resizing text with autosize true', () => {
|
|
|
4062
4058
|
|
|
4063
4059
|
describe('cancelling a resize operation', () => {
|
|
4064
4060
|
it('undoes any changes since the start of the resize operation', () => {
|
|
4065
|
-
editor.createShape
|
|
4061
|
+
editor.createShape({
|
|
4066
4062
|
type: 'geo',
|
|
4067
4063
|
x: 0,
|
|
4068
4064
|
y: 0,
|
|
@@ -76,7 +76,7 @@ describe('Hovering shapes', () => {
|
|
|
76
76
|
editor.pointerMove(50, 50)
|
|
77
77
|
expect(editor.getHoveredShapeId()).toBe(null)
|
|
78
78
|
|
|
79
|
-
editor.updateShape
|
|
79
|
+
editor.updateShape({
|
|
80
80
|
id: ids.box1,
|
|
81
81
|
type: 'geo',
|
|
82
82
|
props: { richText: toRichText('hello') },
|
|
@@ -88,7 +88,7 @@ describe('Hovering shapes', () => {
|
|
|
88
88
|
})
|
|
89
89
|
|
|
90
90
|
it('selects a shape with a full label on pointer down', () => {
|
|
91
|
-
editor.updateShape
|
|
91
|
+
editor.updateShape({
|
|
92
92
|
id: ids.box1,
|
|
93
93
|
type: 'geo',
|
|
94
94
|
props: { richText: toRichText('hello') },
|
|
@@ -462,7 +462,7 @@ describe('when shape is hollow', () => {
|
|
|
462
462
|
describe('when shape is a frame', () => {
|
|
463
463
|
let frame1: TLFrameShape
|
|
464
464
|
beforeEach(() => {
|
|
465
|
-
editor.createShape
|
|
465
|
+
editor.createShape({ id: ids.frame1, type: 'frame', props: { w: 100, h: 100 } })
|
|
466
466
|
frame1 = editor.getShape<TLFrameShape>(ids.frame1)!
|
|
467
467
|
})
|
|
468
468
|
|
|
@@ -517,8 +517,8 @@ describe('when shape is a frame', () => {
|
|
|
517
517
|
describe('When a shape is behind a frame', () => {
|
|
518
518
|
beforeEach(() => {
|
|
519
519
|
editor.selectAll().deleteShapes(editor.getSelectedShapeIds())
|
|
520
|
-
editor.createShape
|
|
521
|
-
editor.createShape
|
|
520
|
+
editor.createShape({ id: ids.box1, type: 'geo', x: 25, y: 25 })
|
|
521
|
+
editor.createShape({ id: ids.frame1, type: 'frame', props: { w: 100, h: 100 } })
|
|
522
522
|
})
|
|
523
523
|
|
|
524
524
|
it('does not select the shape when clicked inside', () => {
|
|
@@ -548,8 +548,8 @@ describe('when shape is inside of a frame', () => {
|
|
|
548
548
|
let frame1: TLFrameShape
|
|
549
549
|
let box1: TLGeoShape
|
|
550
550
|
beforeEach(() => {
|
|
551
|
-
editor.createShape
|
|
552
|
-
editor.createShape
|
|
551
|
+
editor.createShape({ id: ids.frame1, type: 'frame', props: { w: 100, h: 100 } })
|
|
552
|
+
editor.createShape({
|
|
553
553
|
id: ids.box1,
|
|
554
554
|
parentId: ids.frame1,
|
|
555
555
|
type: 'geo',
|
|
@@ -703,15 +703,15 @@ describe('when a frame has multiple children', () => {
|
|
|
703
703
|
let box2: TLGeoShape
|
|
704
704
|
beforeEach(() => {
|
|
705
705
|
editor
|
|
706
|
-
.createShape
|
|
707
|
-
.createShape
|
|
706
|
+
.createShape({ id: ids.frame1, type: 'frame', props: { w: 100, h: 100 } })
|
|
707
|
+
.createShape({
|
|
708
708
|
id: ids.box1,
|
|
709
709
|
parentId: ids.frame1,
|
|
710
710
|
type: 'geo',
|
|
711
711
|
x: 25,
|
|
712
712
|
y: 25,
|
|
713
713
|
})
|
|
714
|
-
.createShape
|
|
714
|
+
.createShape({
|
|
715
715
|
id: ids.box2,
|
|
716
716
|
parentId: ids.frame1,
|
|
717
717
|
type: 'geo',
|
|
@@ -849,7 +849,7 @@ describe('When shapes are overlapping', () => {
|
|
|
849
849
|
let box4: TLGeoShape
|
|
850
850
|
let box5: TLGeoShape
|
|
851
851
|
beforeEach(() => {
|
|
852
|
-
editor.createShapes
|
|
852
|
+
editor.createShapes([
|
|
853
853
|
{
|
|
854
854
|
id: ids.box1,
|
|
855
855
|
type: 'geo',
|
|
@@ -470,7 +470,7 @@ describe('When interacting with a shape...', () => {
|
|
|
470
470
|
})
|
|
471
471
|
|
|
472
472
|
it('Fires handle dragging cancel events', () => {
|
|
473
|
-
const util = editor.getShapeUtil
|
|
473
|
+
const util = editor.getShapeUtil('line')
|
|
474
474
|
|
|
475
475
|
const calls: string[] = []
|
|
476
476
|
|
package/src/test/styles3.test.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { createShapeId, toRichText } from '@tldraw/editor'
|
|
2
2
|
import { TestEditor } from './TestEditor'
|
|
3
3
|
|
|
4
4
|
let editor: TestEditor
|
|
@@ -14,7 +14,7 @@ afterEach(() => {
|
|
|
14
14
|
it("When changing the style of a geo shape, if the text label is empty, don't measure it", () => {
|
|
15
15
|
const id = createShapeId()
|
|
16
16
|
|
|
17
|
-
editor.createShapes
|
|
17
|
+
editor.createShapes([
|
|
18
18
|
{
|
|
19
19
|
id,
|
|
20
20
|
type: 'geo',
|
|
@@ -29,7 +29,7 @@ it("When changing the style of a geo shape, if the text label is empty, don't me
|
|
|
29
29
|
|
|
30
30
|
const boundsBefore = editor.getShapeGeometry(id).bounds
|
|
31
31
|
|
|
32
|
-
editor.updateShapes
|
|
32
|
+
editor.updateShapes([
|
|
33
33
|
{
|
|
34
34
|
id,
|
|
35
35
|
type: 'geo',
|
|
@@ -43,7 +43,7 @@ it("When changing the style of a geo shape, if the text label is empty, don't me
|
|
|
43
43
|
it('When changing the style of a geo shape, if the text label has text, measure it and possibly update the size', () => {
|
|
44
44
|
const id = createShapeId()
|
|
45
45
|
|
|
46
|
-
editor.createShapes
|
|
46
|
+
editor.createShapes([
|
|
47
47
|
{
|
|
48
48
|
id,
|
|
49
49
|
type: 'geo',
|
|
@@ -58,7 +58,7 @@ it('When changing the style of a geo shape, if the text label has text, measure
|
|
|
58
58
|
|
|
59
59
|
const boundsBefore = editor.getShapeGeometry(id).bounds!
|
|
60
60
|
|
|
61
|
-
editor.updateShapes
|
|
61
|
+
editor.updateShapes([
|
|
62
62
|
{
|
|
63
63
|
id,
|
|
64
64
|
type: 'geo',
|
package/src/test/test-jsx.tsx
CHANGED
|
@@ -5,8 +5,7 @@ import {
|
|
|
5
5
|
TLBinding,
|
|
6
6
|
TLBindingCreate,
|
|
7
7
|
TLBindingId,
|
|
8
|
-
|
|
9
|
-
TLDefaultShape,
|
|
8
|
+
TLShape,
|
|
10
9
|
TLShapeId,
|
|
11
10
|
TLShapePartial,
|
|
12
11
|
ZERO_INDEX_KEY,
|
|
@@ -23,6 +22,7 @@ import React, { Fragment } from 'react'
|
|
|
23
22
|
const shapeTypeSymbol = Symbol('shapeJsx')
|
|
24
23
|
const assetTypeSymbol = Symbol('assetJsx')
|
|
25
24
|
const bindingTypeSymbol = Symbol('bindingJsx')
|
|
25
|
+
|
|
26
26
|
interface CommonShapeProps {
|
|
27
27
|
x?: number
|
|
28
28
|
y?: number
|
|
@@ -34,7 +34,6 @@ interface CommonShapeProps {
|
|
|
34
34
|
opacity?: number
|
|
35
35
|
}
|
|
36
36
|
|
|
37
|
-
type ShapeByType<Type extends TLDefaultShape['type']> = Extract<TLDefaultShape, { type: Type }>
|
|
38
37
|
type FormatShapeProps<Props extends object> = {
|
|
39
38
|
[K in keyof Props]?: Props[K] extends TLAssetId
|
|
40
39
|
? TLAssetId | React.JSX.Element
|
|
@@ -42,24 +41,39 @@ type FormatShapeProps<Props extends object> = {
|
|
|
42
41
|
? TLAssetId | React.JSX.Element | null
|
|
43
42
|
: Props[K]
|
|
44
43
|
}
|
|
45
|
-
type PropsForShape<Type extends
|
|
46
|
-
|
|
47
|
-
: CommonShapeProps & Record<string, unknown>
|
|
44
|
+
type PropsForShape<Type extends TLShape['type']> = CommonShapeProps &
|
|
45
|
+
FormatShapeProps<TLShape<Type>['props']>
|
|
48
46
|
|
|
49
47
|
type AssetByType<Type extends TLAsset['type']> = Extract<TLAsset, { type: Type }>
|
|
50
48
|
type PropsForAsset<Type extends string> = Type extends TLAsset['type']
|
|
51
49
|
? Partial<AssetByType<Type>['props']>
|
|
52
50
|
: Record<string, unknown>
|
|
53
51
|
|
|
54
|
-
interface
|
|
52
|
+
interface BindingReactConnections {
|
|
55
53
|
from?: string | TLShapeId
|
|
56
54
|
to: string | TLShapeId
|
|
57
55
|
}
|
|
58
56
|
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
57
|
+
interface CommonBindingReactProps extends BindingReactConnections {
|
|
58
|
+
ref?: string
|
|
59
|
+
id?: TLBindingId
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
type ReactPropsForBinding<Type extends TLBinding['type']> = CommonBindingReactProps &
|
|
63
|
+
Partial<TLBinding<Type>['props']>
|
|
64
|
+
|
|
65
|
+
type BindingToCreate = TLBinding extends infer E
|
|
66
|
+
? E extends TLBinding
|
|
67
|
+
? {
|
|
68
|
+
type: E['type']
|
|
69
|
+
props: Partial<TLBinding<E['type']>['props']>
|
|
70
|
+
id: TLBindingId | undefined
|
|
71
|
+
parentId: TLShapeId | undefined
|
|
72
|
+
ref: string | undefined
|
|
73
|
+
connections: BindingReactConnections
|
|
74
|
+
}
|
|
75
|
+
: never
|
|
76
|
+
: never
|
|
63
77
|
|
|
64
78
|
const createElement = (
|
|
65
79
|
type: typeof shapeTypeSymbol | typeof assetTypeSymbol | typeof bindingTypeSymbol,
|
|
@@ -90,10 +104,9 @@ const tlBinding = new Proxy(
|
|
|
90
104
|
return createElement(bindingTypeSymbol, key as string)
|
|
91
105
|
},
|
|
92
106
|
}
|
|
93
|
-
) as {
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
>
|
|
107
|
+
) as {
|
|
108
|
+
[K in TLBinding['type']]: (props: ReactPropsForBinding<K>) => null
|
|
109
|
+
}
|
|
97
110
|
|
|
98
111
|
/**
|
|
99
112
|
* TL - jsx helpers for creating tldraw shapes in test cases
|
|
@@ -112,8 +125,8 @@ export const TL = new Proxy(
|
|
|
112
125
|
},
|
|
113
126
|
}
|
|
114
127
|
) as { asset: typeof tlAsset; binding: typeof tlBinding } & {
|
|
115
|
-
[K in
|
|
116
|
-
}
|
|
128
|
+
[K in TLShape['type']]: (props: PropsForShape<K>) => null
|
|
129
|
+
}
|
|
117
130
|
|
|
118
131
|
export function shapesFromJsx(shapes: React.JSX.Element | Array<React.JSX.Element>, idPrefix = '') {
|
|
119
132
|
const ids = { bindings: {} } as Record<string, TLShapeId> & {
|
|
@@ -122,12 +135,7 @@ export function shapesFromJsx(shapes: React.JSX.Element | Array<React.JSX.Elemen
|
|
|
122
135
|
const currentPageShapes: Array<TLShapePartial> = []
|
|
123
136
|
const assets: Array<TLAsset> = []
|
|
124
137
|
|
|
125
|
-
const bindingsToCreate: Array<
|
|
126
|
-
type: string
|
|
127
|
-
props: Record<string, unknown>
|
|
128
|
-
parentId: TLShapeId | undefined
|
|
129
|
-
ref: string | undefined
|
|
130
|
-
}> = []
|
|
138
|
+
const bindingsToCreate: Array<BindingToCreate> = []
|
|
131
139
|
|
|
132
140
|
function addChildren(
|
|
133
141
|
children: React.JSX.Element | Array<React.JSX.Element>,
|
|
@@ -152,10 +160,21 @@ export function shapesFromJsx(shapes: React.JSX.Element | Array<React.JSX.Elemen
|
|
|
152
160
|
}
|
|
153
161
|
|
|
154
162
|
if (el.type[bindingTypeSymbol]) {
|
|
155
|
-
const bindingType = (el.type as any)[bindingTypeSymbol] as
|
|
156
|
-
const
|
|
157
|
-
|
|
158
|
-
|
|
163
|
+
const bindingType = (el.type as any)[bindingTypeSymbol] as TLBinding['type']
|
|
164
|
+
const { id, from, to, ref, ...props } = el.props
|
|
165
|
+
const bindingRef: unknown = (el as any).ref || ref
|
|
166
|
+
assert(
|
|
167
|
+
bindingRef === undefined || typeof bindingRef === 'string',
|
|
168
|
+
'ref must be string or undefined'
|
|
169
|
+
)
|
|
170
|
+
bindingsToCreate.push({
|
|
171
|
+
type: bindingType,
|
|
172
|
+
props,
|
|
173
|
+
id,
|
|
174
|
+
parentId,
|
|
175
|
+
ref: bindingRef,
|
|
176
|
+
connections: { from, to },
|
|
177
|
+
})
|
|
159
178
|
} else {
|
|
160
179
|
const shapeType = (el.type as any)[shapeTypeSymbol] as string
|
|
161
180
|
if (!shapeType) {
|
|
@@ -239,55 +258,48 @@ export function shapesFromJsx(shapes: React.JSX.Element | Array<React.JSX.Elemen
|
|
|
239
258
|
addChildren(shapes)
|
|
240
259
|
|
|
241
260
|
const bindings: TLBindingCreate[] = []
|
|
242
|
-
for (const binding of bindingsToCreate) {
|
|
261
|
+
for (const { id, parentId, ref, connections, ...binding } of bindingsToCreate) {
|
|
243
262
|
let fromId: TLShapeId, toId: TLShapeId
|
|
244
|
-
if (
|
|
245
|
-
assert(typeof
|
|
246
|
-
if (isShapeId(
|
|
247
|
-
fromId =
|
|
263
|
+
if (connections.from) {
|
|
264
|
+
assert(typeof connections.from === 'string', 'from must be a ref string or a shape id')
|
|
265
|
+
if (isShapeId(connections.from)) {
|
|
266
|
+
fromId = connections.from
|
|
248
267
|
} else {
|
|
249
|
-
assert(ids[
|
|
250
|
-
fromId = ids[
|
|
268
|
+
assert(ids[connections.from], `Ref not found: ${connections.from}`)
|
|
269
|
+
fromId = ids[connections.from]
|
|
251
270
|
}
|
|
252
|
-
} else if (
|
|
253
|
-
fromId =
|
|
271
|
+
} else if (parentId) {
|
|
272
|
+
fromId = parentId
|
|
254
273
|
} else {
|
|
255
274
|
throw new Error('from must be specified, or binding must be a child of a shape')
|
|
256
275
|
}
|
|
257
276
|
|
|
258
|
-
assert(
|
|
259
|
-
assert(typeof
|
|
260
|
-
if (isShapeId(
|
|
261
|
-
toId =
|
|
277
|
+
assert(connections.to, 'to must be specified')
|
|
278
|
+
assert(typeof connections.to === 'string', 'to must be a ref string or a shape id')
|
|
279
|
+
if (isShapeId(connections.to)) {
|
|
280
|
+
toId = connections.to
|
|
262
281
|
} else {
|
|
263
|
-
assert(ids[
|
|
264
|
-
toId = ids[
|
|
282
|
+
assert(ids[connections.to], `Ref not found: ${connections.to}`)
|
|
283
|
+
toId = ids[connections.to]
|
|
265
284
|
}
|
|
266
285
|
|
|
267
|
-
let bindingId
|
|
268
|
-
if (
|
|
269
|
-
assert(typeof
|
|
270
|
-
assert(!ids.bindings[
|
|
271
|
-
assert(!bindingId, `Cannot use both ref and id on binding: ${
|
|
272
|
-
bindingId = createBindingId(`${idPrefix}${
|
|
273
|
-
ids.bindings[
|
|
286
|
+
let bindingId = id
|
|
287
|
+
if (ref) {
|
|
288
|
+
assert(typeof ref === 'string', 'binding ref must be string')
|
|
289
|
+
assert(!ids.bindings[ref], `Duplicate ref: ${ref}`)
|
|
290
|
+
assert(!bindingId, `Cannot use both ref and id on binding: ${ref}`)
|
|
291
|
+
bindingId = createBindingId(`${idPrefix}${ref}`)
|
|
292
|
+
ids.bindings[ref] = bindingId
|
|
274
293
|
}
|
|
275
294
|
if (!bindingId) {
|
|
276
295
|
bindingId = createBindingId()
|
|
277
296
|
}
|
|
278
297
|
|
|
279
|
-
const props = { ...binding.props }
|
|
280
|
-
delete props.ref
|
|
281
|
-
delete props.id
|
|
282
|
-
delete props.from
|
|
283
|
-
delete props.to
|
|
284
|
-
|
|
285
298
|
bindings.push({
|
|
299
|
+
...binding,
|
|
286
300
|
id: bindingId,
|
|
287
|
-
type: binding.type,
|
|
288
301
|
fromId,
|
|
289
302
|
toId,
|
|
290
|
-
props,
|
|
291
303
|
})
|
|
292
304
|
}
|
|
293
305
|
|
package/src/test/text.test.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { createShapeId, toRichText } from '@tldraw/editor'
|
|
2
2
|
import { TestEditor } from './TestEditor'
|
|
3
3
|
|
|
4
4
|
let editor: TestEditor
|
|
@@ -13,7 +13,7 @@ afterEach(() => {
|
|
|
13
13
|
describe('When editing text', () => {
|
|
14
14
|
it('preserves the top center when center aligned', () => {
|
|
15
15
|
const id = createShapeId()
|
|
16
|
-
editor.createShapes
|
|
16
|
+
editor.createShapes([
|
|
17
17
|
{
|
|
18
18
|
id,
|
|
19
19
|
type: 'text',
|
|
@@ -27,7 +27,7 @@ describe('When editing text', () => {
|
|
|
27
27
|
},
|
|
28
28
|
])
|
|
29
29
|
const boundsA = editor.getShapePageBounds(id)
|
|
30
|
-
editor.updateShapes
|
|
30
|
+
editor.updateShapes([
|
|
31
31
|
{
|
|
32
32
|
id,
|
|
33
33
|
type: 'text',
|
|
@@ -47,7 +47,7 @@ describe('When editing text', () => {
|
|
|
47
47
|
|
|
48
48
|
it('preserved the right center when center aligned and rotated 90deg', () => {
|
|
49
49
|
const id = createShapeId()
|
|
50
|
-
editor.createShapes
|
|
50
|
+
editor.createShapes([
|
|
51
51
|
{
|
|
52
52
|
id,
|
|
53
53
|
type: 'text',
|
|
@@ -63,9 +63,7 @@ describe('When editing text', () => {
|
|
|
63
63
|
])
|
|
64
64
|
|
|
65
65
|
const boundsA = editor.getShapePageBounds(id)!
|
|
66
|
-
editor.updateShapes
|
|
67
|
-
{ id, type: 'text', props: { richText: toRichText('Hello, world!') } },
|
|
68
|
-
])
|
|
66
|
+
editor.updateShapes([{ id, type: 'text', props: { richText: toRichText('Hello, world!') } }])
|
|
69
67
|
const boundsB = editor.getShapePageBounds(id)!
|
|
70
68
|
expect(boundsA.x).toBeCloseTo(boundsB.x)
|
|
71
69
|
expect(boundsA.y).not.toBeCloseTo(boundsB.y)
|
|
@@ -75,7 +73,7 @@ describe('When editing text', () => {
|
|
|
75
73
|
|
|
76
74
|
it('preserves the top left corner when start aligned', () => {
|
|
77
75
|
const id = createShapeId()
|
|
78
|
-
editor.createShapes
|
|
76
|
+
editor.createShapes([
|
|
79
77
|
{
|
|
80
78
|
id,
|
|
81
79
|
type: 'text',
|
|
@@ -89,7 +87,7 @@ describe('When editing text', () => {
|
|
|
89
87
|
},
|
|
90
88
|
])
|
|
91
89
|
const boundsA = editor.getShapePageBounds(id)
|
|
92
|
-
editor.updateShapes
|
|
90
|
+
editor.updateShapes([
|
|
93
91
|
{
|
|
94
92
|
id,
|
|
95
93
|
type: 'text',
|
|
@@ -109,7 +107,7 @@ describe('When editing text', () => {
|
|
|
109
107
|
|
|
110
108
|
it('preserves the top right edge when end aligned', () => {
|
|
111
109
|
const id = createShapeId()
|
|
112
|
-
editor.createShapes
|
|
110
|
+
editor.createShapes([
|
|
113
111
|
{
|
|
114
112
|
id,
|
|
115
113
|
type: 'text',
|
|
@@ -123,7 +121,7 @@ describe('When editing text', () => {
|
|
|
123
121
|
},
|
|
124
122
|
])
|
|
125
123
|
const boundsA = editor.getShapePageBounds(id)
|
|
126
|
-
editor.updateShapes
|
|
124
|
+
editor.updateShapes([
|
|
127
125
|
{
|
|
128
126
|
id,
|
|
129
127
|
type: 'text',
|
|
@@ -145,7 +143,7 @@ describe('When editing text', () => {
|
|
|
145
143
|
describe('When changing text size', () => {
|
|
146
144
|
it('preserves the center when center aligned', () => {
|
|
147
145
|
const id = createShapeId()
|
|
148
|
-
editor.createShapes
|
|
146
|
+
editor.createShapes([
|
|
149
147
|
{
|
|
150
148
|
id,
|
|
151
149
|
type: 'text',
|
|
@@ -160,7 +158,7 @@ describe('When changing text size', () => {
|
|
|
160
158
|
},
|
|
161
159
|
])
|
|
162
160
|
const boundsA = editor.getShapePageBounds(id)
|
|
163
|
-
editor.updateShapes
|
|
161
|
+
editor.updateShapes([
|
|
164
162
|
{
|
|
165
163
|
id,
|
|
166
164
|
type: 'text',
|
|
@@ -180,7 +178,7 @@ describe('When changing text size', () => {
|
|
|
180
178
|
|
|
181
179
|
it('preserves the center left point when start aligned', () => {
|
|
182
180
|
const id = createShapeId()
|
|
183
|
-
editor.createShapes
|
|
181
|
+
editor.createShapes([
|
|
184
182
|
{
|
|
185
183
|
id,
|
|
186
184
|
type: 'text',
|
|
@@ -195,7 +193,7 @@ describe('When changing text size', () => {
|
|
|
195
193
|
},
|
|
196
194
|
])
|
|
197
195
|
const boundsA = editor.getShapePageBounds(id)
|
|
198
|
-
editor.updateShapes
|
|
196
|
+
editor.updateShapes([
|
|
199
197
|
{
|
|
200
198
|
id,
|
|
201
199
|
type: 'text',
|
|
@@ -215,7 +213,7 @@ describe('When changing text size', () => {
|
|
|
215
213
|
|
|
216
214
|
it('preserves the top right edge when end aligned', () => {
|
|
217
215
|
const id = createShapeId()
|
|
218
|
-
editor.createShapes
|
|
216
|
+
editor.createShapes([
|
|
219
217
|
{
|
|
220
218
|
id,
|
|
221
219
|
type: 'text',
|
|
@@ -230,7 +228,7 @@ describe('When changing text size', () => {
|
|
|
230
228
|
},
|
|
231
229
|
])
|
|
232
230
|
const boundsA = editor.getShapePageBounds(id)
|
|
233
|
-
editor.updateShapes
|
|
231
|
+
editor.updateShapes([
|
|
234
232
|
{
|
|
235
233
|
id,
|
|
236
234
|
type: 'text',
|
|
@@ -1749,9 +1749,7 @@ describe('translating a shape with a bound shape', () => {
|
|
|
1749
1749
|
|
|
1750
1750
|
const newArrow = editor
|
|
1751
1751
|
.getCurrentPageShapes()
|
|
1752
|
-
.find(
|
|
1753
|
-
(s) => editor.isShapeOfType<TLArrowShape>(s, 'arrow') && s.id !== arrow1
|
|
1754
|
-
)! as TLArrowShape
|
|
1752
|
+
.find((s) => editor.isShapeOfType(s, 'arrow') && s.id !== arrow1)! as TLArrowShape
|
|
1755
1753
|
expect(getArrowBindings(editor, newArrow)).toMatchObject({
|
|
1756
1754
|
start: { type: 'arrow' },
|
|
1757
1755
|
end: undefined,
|
|
@@ -2061,7 +2059,7 @@ describe('Note shape grid helper positions / pits', () => {
|
|
|
2061
2059
|
editor
|
|
2062
2060
|
.createShape({ type: 'note' })
|
|
2063
2061
|
.createShape({ type: 'note', x: 500, y: 500 })
|
|
2064
|
-
.updateShape({ ...editor.getLastCreatedShape(), props: { growY: 100 } })
|
|
2062
|
+
.updateShape({ ...editor.getLastCreatedShape<TLNoteShape>(), props: { growY: 100 } })
|
|
2065
2063
|
.pointerMove(600, 600)
|
|
2066
2064
|
// start translating
|
|
2067
2065
|
.pointerDown()
|
|
@@ -2080,7 +2078,7 @@ describe('Note shape grid helper positions / pits', () => {
|
|
|
2080
2078
|
it('Snaps correctly to the bottom when the not-translating shape has growY', () => {
|
|
2081
2079
|
editor
|
|
2082
2080
|
.createShape({ type: 'note' })
|
|
2083
|
-
.updateShape({ ...editor.getLastCreatedShape(), props: { growY: 100 } })
|
|
2081
|
+
.updateShape({ ...editor.getLastCreatedShape<TLNoteShape>(), props: { growY: 100 } })
|
|
2084
2082
|
.createShape({ type: 'note', x: 500, y: 500 })
|
|
2085
2083
|
.pointerMove(600, 600)
|
|
2086
2084
|
// start translating
|
|
@@ -2183,7 +2181,7 @@ describe('Note shape grid helper positions / pits', () => {
|
|
|
2183
2181
|
|
|
2184
2182
|
describe('cancelling a translate operation', () => {
|
|
2185
2183
|
it('undoes any changes since the start of the translate operation', () => {
|
|
2186
|
-
editor.createShape
|
|
2184
|
+
editor.createShape({
|
|
2187
2185
|
type: 'geo',
|
|
2188
2186
|
x: 0,
|
|
2189
2187
|
y: 0,
|
|
@@ -2220,7 +2218,7 @@ describe('cancelling a translate operation', () => {
|
|
|
2220
2218
|
const shapeId = createShapeId()
|
|
2221
2219
|
|
|
2222
2220
|
editor
|
|
2223
|
-
.createShape
|
|
2221
|
+
.createShape({
|
|
2224
2222
|
id: shapeId,
|
|
2225
2223
|
type: 'geo',
|
|
2226
2224
|
x: 0,
|
|
@@ -2268,7 +2266,7 @@ describe('cancelling a translate operation', () => {
|
|
|
2268
2266
|
const shapeId = createShapeId()
|
|
2269
2267
|
|
|
2270
2268
|
editor
|
|
2271
|
-
.createShape
|
|
2269
|
+
.createShape({
|
|
2272
2270
|
id: shapeId,
|
|
2273
2271
|
type: 'geo',
|
|
2274
2272
|
x: 0,
|