tldraw 5.2.0-next.e2b8d10bf10e → 5.2.0
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 +20294 -0
- package/README.md +13 -1
- package/RELEASE_NOTES.md +2908 -0
- package/dist-cjs/index.d.ts +110 -23
- package/dist-cjs/index.js +3 -3
- package/dist-cjs/index.js.map +2 -2
- package/dist-cjs/lib/TldrawImage.js +0 -1
- package/dist-cjs/lib/TldrawImage.js.map +2 -2
- package/dist-cjs/lib/bindings/arrow/ArrowBindingUtil.js +2 -1
- package/dist-cjs/lib/bindings/arrow/ArrowBindingUtil.js.map +2 -2
- package/dist-cjs/lib/defaultEmbedDefinitions.js +3 -2
- package/dist-cjs/lib/defaultEmbedDefinitions.js.map +2 -2
- package/dist-cjs/lib/defaultOverlayUtils.js +11 -11
- package/dist-cjs/lib/defaultOverlayUtils.js.map +2 -2
- package/dist-cjs/lib/overlays/SelectionForegroundOverlayUtil.js +76 -64
- package/dist-cjs/lib/overlays/SelectionForegroundOverlayUtil.js.map +2 -2
- package/dist-cjs/lib/overlays/ShapeHandleOverlayUtil.js +1 -1
- package/dist-cjs/lib/overlays/ShapeHandleOverlayUtil.js.map +2 -2
- package/dist-cjs/lib/overlays/ShapeIndicatorOverlayUtil.js +107 -0
- package/dist-cjs/lib/overlays/ShapeIndicatorOverlayUtil.js.map +7 -0
- package/dist-cjs/lib/shapes/arrow/toolStates/Pointing.js +3 -0
- package/dist-cjs/lib/shapes/arrow/toolStates/Pointing.js.map +2 -2
- package/dist-cjs/lib/shapes/bookmark/BookmarkShapeUtil.js +12 -3
- package/dist-cjs/lib/shapes/bookmark/BookmarkShapeUtil.js.map +2 -2
- package/dist-cjs/lib/shapes/bookmark/bookmarks.js +54 -6
- package/dist-cjs/lib/shapes/bookmark/bookmarks.js.map +2 -2
- package/dist-cjs/lib/shapes/draw/DrawShapeUtil.js +2 -1
- package/dist-cjs/lib/shapes/draw/DrawShapeUtil.js.map +2 -2
- package/dist-cjs/lib/shapes/draw/getPath.js +1 -1
- package/dist-cjs/lib/shapes/draw/getPath.js.map +2 -2
- package/dist-cjs/lib/shapes/draw/toolStates/Drawing.js +45 -47
- package/dist-cjs/lib/shapes/draw/toolStates/Drawing.js.map +2 -2
- package/dist-cjs/lib/shapes/embed/EmbedShapeUtil.js +2 -1
- package/dist-cjs/lib/shapes/embed/EmbedShapeUtil.js.map +2 -2
- package/dist-cjs/lib/shapes/frame/FrameShapeTool.js +23 -18
- package/dist-cjs/lib/shapes/frame/FrameShapeTool.js.map +2 -2
- package/dist-cjs/lib/shapes/geo/GeoShapeUtil.js +1 -1
- package/dist-cjs/lib/shapes/geo/GeoShapeUtil.js.map +2 -2
- package/dist-cjs/lib/shapes/geo/toolStates/Pointing.js +3 -0
- package/dist-cjs/lib/shapes/geo/toolStates/Pointing.js.map +2 -2
- package/dist-cjs/lib/shapes/highlight/HighlightShapeUtil.js +11 -7
- package/dist-cjs/lib/shapes/highlight/HighlightShapeUtil.js.map +2 -2
- package/dist-cjs/lib/shapes/image/ImageShapeUtil.js +3 -11
- package/dist-cjs/lib/shapes/image/ImageShapeUtil.js.map +2 -2
- package/dist-cjs/lib/shapes/line/toolStates/Pointing.js +5 -1
- package/dist-cjs/lib/shapes/line/toolStates/Pointing.js.map +2 -2
- package/dist-cjs/lib/shapes/note/NoteShapeUtil.js +31 -41
- package/dist-cjs/lib/shapes/note/NoteShapeUtil.js.map +2 -2
- package/dist-cjs/lib/shapes/note/noteHelpers.js +1 -1
- package/dist-cjs/lib/shapes/note/noteHelpers.js.map +2 -2
- package/dist-cjs/lib/shapes/note/toolStates/Pointing.js +28 -6
- package/dist-cjs/lib/shapes/note/toolStates/Pointing.js.map +2 -2
- package/dist-cjs/lib/shapes/shared/PlainTextLabel.js +3 -2
- package/dist-cjs/lib/shapes/shared/PlainTextLabel.js.map +2 -2
- package/dist-cjs/lib/shapes/shared/RichTextLabel.js +3 -3
- package/dist-cjs/lib/shapes/shared/RichTextLabel.js.map +2 -2
- package/dist-cjs/lib/shapes/shared/defaultStyleDefs.js +17 -3
- package/dist-cjs/lib/shapes/shared/defaultStyleDefs.js.map +2 -2
- package/dist-cjs/lib/shapes/shared/freehand/core.js +424 -0
- package/dist-cjs/lib/shapes/shared/freehand/core.js.map +7 -0
- package/dist-cjs/lib/shapes/shared/freehand/fmt.js +106 -0
- package/dist-cjs/lib/shapes/shared/freehand/fmt.js.map +7 -0
- package/dist-cjs/lib/shapes/shared/freehand/getStroke.js +6 -6
- package/dist-cjs/lib/shapes/shared/freehand/getStroke.js.map +2 -2
- package/dist-cjs/lib/shapes/shared/freehand/getStrokeOutlinePoints.js +320 -86
- package/dist-cjs/lib/shapes/shared/freehand/getStrokeOutlinePoints.js.map +3 -3
- package/dist-cjs/lib/shapes/shared/freehand/getStrokePoints.js +20 -96
- package/dist-cjs/lib/shapes/shared/freehand/getStrokePoints.js.map +3 -3
- package/dist-cjs/lib/shapes/shared/freehand/svg.js +55 -19
- package/dist-cjs/lib/shapes/shared/freehand/svg.js.map +2 -2
- package/dist-cjs/lib/shapes/shared/freehand/svgInk.js +189 -97
- package/dist-cjs/lib/shapes/shared/freehand/svgInk.js.map +3 -3
- package/dist-cjs/lib/shapes/shared/freehand/types.js.map +1 -1
- package/dist-cjs/lib/shapes/shared/interpolate-props.js +6 -2
- package/dist-cjs/lib/shapes/shared/interpolate-props.js.map +2 -2
- package/dist-cjs/lib/shapes/text/toolStates/Pointing.js +3 -0
- package/dist-cjs/lib/shapes/text/toolStates/Pointing.js.map +2 -2
- package/dist-cjs/lib/tools/HandTool/HandTool.js +16 -6
- package/dist-cjs/lib/tools/HandTool/HandTool.js.map +2 -2
- package/dist-cjs/lib/tools/HandTool/childStates/Dragging.js +10 -1
- package/dist-cjs/lib/tools/HandTool/childStates/Dragging.js.map +2 -2
- package/dist-cjs/lib/tools/HandTool/childStates/OneFingerZooming.js +84 -0
- package/dist-cjs/lib/tools/HandTool/childStates/OneFingerZooming.js.map +7 -0
- package/dist-cjs/lib/tools/SelectTool/childStates/Idle.js +12 -0
- package/dist-cjs/lib/tools/SelectTool/childStates/Idle.js.map +2 -2
- package/dist-cjs/lib/tools/SelectTool/childStates/PointingShape.js +4 -0
- package/dist-cjs/lib/tools/SelectTool/childStates/PointingShape.js.map +2 -2
- package/dist-cjs/lib/tools/SelectTool/childStates/Resizing.js +107 -46
- package/dist-cjs/lib/tools/SelectTool/childStates/Resizing.js.map +2 -2
- package/dist-cjs/lib/ui/TldrawUi.js +4 -3
- package/dist-cjs/lib/ui/TldrawUi.js.map +2 -2
- package/dist-cjs/lib/ui/components/A11y.js +2 -0
- package/dist-cjs/lib/ui/components/A11y.js.map +2 -2
- package/dist-cjs/lib/ui/components/ContextMenu/DefaultContextMenu.js +14 -1
- package/dist-cjs/lib/ui/components/ContextMenu/DefaultContextMenu.js.map +2 -2
- package/dist-cjs/lib/ui/components/ContextMenu/DefaultContextMenuContent.js +0 -6
- package/dist-cjs/lib/ui/components/ContextMenu/DefaultContextMenuContent.js.map +2 -2
- package/dist-cjs/lib/ui/components/DefaultFollowingIndicator.js.map +2 -2
- package/dist-cjs/lib/ui/components/Dialogs.js +17 -37
- package/dist-cjs/lib/ui/components/Dialogs.js.map +2 -2
- package/dist-cjs/lib/ui/components/HelperButtons/BackToContent.js +19 -4
- package/dist-cjs/lib/ui/components/HelperButtons/BackToContent.js.map +2 -2
- package/dist-cjs/lib/ui/components/KeyboardShortcutsDialog/DefaultKeyboardShortcutsDialogContent.js +12 -2
- package/dist-cjs/lib/ui/components/KeyboardShortcutsDialog/DefaultKeyboardShortcutsDialogContent.js.map +2 -2
- package/dist-cjs/lib/ui/components/Minimap/DefaultMinimap.js +47 -70
- package/dist-cjs/lib/ui/components/Minimap/DefaultMinimap.js.map +2 -2
- package/dist-cjs/lib/ui/components/Minimap/MinimapManager.js +25 -46
- package/dist-cjs/lib/ui/components/Minimap/MinimapManager.js.map +2 -2
- package/dist-cjs/lib/ui/components/SharePanel/DefaultPeopleMenuAvatar.js.map +2 -2
- package/dist-cjs/lib/ui/components/SharePanel/DefaultPeopleMenuContent.js.map +2 -2
- package/dist-cjs/lib/ui/components/SharePanel/DefaultPeopleMenuFacePile.js.map +2 -2
- package/dist-cjs/lib/ui/components/SharePanel/DefaultPeopleMenuItem.js +1 -1
- package/dist-cjs/lib/ui/components/SharePanel/DefaultPeopleMenuItem.js.map +2 -2
- package/dist-cjs/lib/ui/components/StylePanel/StylePanelButtonPicker.js +1 -0
- package/dist-cjs/lib/ui/components/StylePanel/StylePanelButtonPicker.js.map +2 -2
- package/dist-cjs/lib/ui/components/menu-items.js +7 -0
- package/dist-cjs/lib/ui/components/menu-items.js.map +2 -2
- package/dist-cjs/lib/ui/components/primitives/TldrawUiDropdownMenu.js +2 -1
- package/dist-cjs/lib/ui/components/primitives/TldrawUiDropdownMenu.js.map +2 -2
- package/dist-cjs/lib/ui/components/primitives/TldrawUiIcon.js +14 -3
- package/dist-cjs/lib/ui/components/primitives/TldrawUiIcon.js.map +2 -2
- package/dist-cjs/lib/ui/components/primitives/TldrawUiInput.js +2 -0
- package/dist-cjs/lib/ui/components/primitives/TldrawUiInput.js.map +2 -2
- package/dist-cjs/lib/ui/components/primitives/TldrawUiPopover.js +2 -0
- package/dist-cjs/lib/ui/components/primitives/TldrawUiPopover.js.map +2 -2
- package/dist-cjs/lib/ui/components/primitives/menus/TldrawUiMenuCheckboxItem.js +0 -2
- package/dist-cjs/lib/ui/components/primitives/menus/TldrawUiMenuCheckboxItem.js.map +2 -2
- package/dist-cjs/lib/ui/components/primitives/menus/TldrawUiMenuSubmenu.js +1 -2
- package/dist-cjs/lib/ui/components/primitives/menus/TldrawUiMenuSubmenu.js.map +2 -2
- package/dist-cjs/lib/ui/context/actions.js +70 -1
- package/dist-cjs/lib/ui/context/actions.js.map +2 -2
- package/dist-cjs/lib/ui/context/asset-urls.js +5 -8
- package/dist-cjs/lib/ui/context/asset-urls.js.map +2 -2
- package/dist-cjs/lib/ui/context/events.js.map +2 -2
- package/dist-cjs/lib/ui/hooks/useKeyboardShortcuts.js +13 -0
- package/dist-cjs/lib/ui/hooks/useKeyboardShortcuts.js.map +2 -2
- package/dist-cjs/lib/ui/hooks/useTools.js +1 -1
- package/dist-cjs/lib/ui/hooks/useTools.js.map +2 -2
- package/dist-cjs/lib/ui/hooks/useTranslation/TLUiTranslationKey.js.map +1 -1
- package/dist-cjs/lib/ui/hooks/useTranslation/defaultTranslation.js +2 -0
- package/dist-cjs/lib/ui/hooks/useTranslation/defaultTranslation.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/embeds/embeds.js +4 -4
- package/dist-cjs/lib/utils/embeds/embeds.js.map +2 -2
- package/dist-cjs/lib/utils/test-helpers.js +2 -2
- package/dist-cjs/lib/utils/test-helpers.js.map +2 -2
- package/dist-cjs/lib/utils/text/richText.js +3 -1
- package/dist-cjs/lib/utils/text/richText.js.map +2 -2
- package/dist-esm/index.d.mts +110 -23
- package/dist-esm/index.mjs +5 -3
- package/dist-esm/index.mjs.map +2 -2
- package/dist-esm/lib/TldrawImage.mjs +0 -1
- package/dist-esm/lib/TldrawImage.mjs.map +2 -2
- package/dist-esm/lib/bindings/arrow/ArrowBindingUtil.mjs +2 -1
- package/dist-esm/lib/bindings/arrow/ArrowBindingUtil.mjs.map +2 -2
- package/dist-esm/lib/defaultEmbedDefinitions.mjs +3 -2
- package/dist-esm/lib/defaultEmbedDefinitions.mjs.map +2 -2
- package/dist-esm/lib/defaultOverlayUtils.mjs +11 -11
- package/dist-esm/lib/defaultOverlayUtils.mjs.map +2 -2
- package/dist-esm/lib/overlays/SelectionForegroundOverlayUtil.mjs +77 -65
- package/dist-esm/lib/overlays/SelectionForegroundOverlayUtil.mjs.map +2 -2
- package/dist-esm/lib/overlays/ShapeHandleOverlayUtil.mjs +1 -1
- package/dist-esm/lib/overlays/ShapeHandleOverlayUtil.mjs.map +2 -2
- package/dist-esm/lib/overlays/ShapeIndicatorOverlayUtil.mjs +87 -0
- package/dist-esm/lib/overlays/ShapeIndicatorOverlayUtil.mjs.map +7 -0
- package/dist-esm/lib/shapes/arrow/toolStates/Pointing.mjs +9 -1
- package/dist-esm/lib/shapes/arrow/toolStates/Pointing.mjs.map +2 -2
- package/dist-esm/lib/shapes/bookmark/BookmarkShapeUtil.mjs +15 -3
- package/dist-esm/lib/shapes/bookmark/BookmarkShapeUtil.mjs.map +2 -2
- package/dist-esm/lib/shapes/bookmark/bookmarks.mjs +54 -6
- package/dist-esm/lib/shapes/bookmark/bookmarks.mjs.map +2 -2
- package/dist-esm/lib/shapes/draw/DrawShapeUtil.mjs +3 -1
- package/dist-esm/lib/shapes/draw/DrawShapeUtil.mjs.map +2 -2
- package/dist-esm/lib/shapes/draw/getPath.mjs +1 -1
- package/dist-esm/lib/shapes/draw/getPath.mjs.map +2 -2
- package/dist-esm/lib/shapes/draw/toolStates/Drawing.mjs +46 -47
- package/dist-esm/lib/shapes/draw/toolStates/Drawing.mjs.map +2 -2
- package/dist-esm/lib/shapes/embed/EmbedShapeUtil.mjs +2 -1
- package/dist-esm/lib/shapes/embed/EmbedShapeUtil.mjs.map +2 -2
- package/dist-esm/lib/shapes/frame/FrameShapeTool.mjs +23 -18
- package/dist-esm/lib/shapes/frame/FrameShapeTool.mjs.map +2 -2
- package/dist-esm/lib/shapes/geo/GeoShapeUtil.mjs +2 -1
- package/dist-esm/lib/shapes/geo/GeoShapeUtil.mjs.map +2 -2
- package/dist-esm/lib/shapes/geo/toolStates/Pointing.mjs +4 -0
- package/dist-esm/lib/shapes/geo/toolStates/Pointing.mjs.map +2 -2
- package/dist-esm/lib/shapes/highlight/HighlightShapeUtil.mjs +12 -7
- package/dist-esm/lib/shapes/highlight/HighlightShapeUtil.mjs.map +2 -2
- package/dist-esm/lib/shapes/image/ImageShapeUtil.mjs +3 -11
- package/dist-esm/lib/shapes/image/ImageShapeUtil.mjs.map +2 -2
- package/dist-esm/lib/shapes/line/toolStates/Pointing.mjs +6 -1
- package/dist-esm/lib/shapes/line/toolStates/Pointing.mjs.map +2 -2
- package/dist-esm/lib/shapes/note/NoteShapeUtil.mjs +32 -42
- package/dist-esm/lib/shapes/note/NoteShapeUtil.mjs.map +2 -2
- package/dist-esm/lib/shapes/note/noteHelpers.mjs +1 -1
- package/dist-esm/lib/shapes/note/noteHelpers.mjs.map +2 -2
- package/dist-esm/lib/shapes/note/toolStates/Pointing.mjs +29 -6
- package/dist-esm/lib/shapes/note/toolStates/Pointing.mjs.map +2 -2
- package/dist-esm/lib/shapes/shared/PlainTextLabel.mjs +3 -2
- package/dist-esm/lib/shapes/shared/PlainTextLabel.mjs.map +2 -2
- package/dist-esm/lib/shapes/shared/RichTextLabel.mjs +4 -3
- package/dist-esm/lib/shapes/shared/RichTextLabel.mjs.map +2 -2
- package/dist-esm/lib/shapes/shared/defaultStyleDefs.mjs +17 -3
- package/dist-esm/lib/shapes/shared/defaultStyleDefs.mjs.map +2 -2
- package/dist-esm/lib/shapes/shared/freehand/core.mjs +404 -0
- package/dist-esm/lib/shapes/shared/freehand/core.mjs.map +7 -0
- package/dist-esm/lib/shapes/shared/freehand/fmt.mjs +86 -0
- package/dist-esm/lib/shapes/shared/freehand/fmt.mjs.map +7 -0
- package/dist-esm/lib/shapes/shared/freehand/getStroke.mjs +7 -7
- package/dist-esm/lib/shapes/shared/freehand/getStroke.mjs.map +2 -2
- package/dist-esm/lib/shapes/shared/freehand/getStrokeOutlinePoints.mjs +332 -86
- package/dist-esm/lib/shapes/shared/freehand/getStrokeOutlinePoints.mjs.map +3 -3
- package/dist-esm/lib/shapes/shared/freehand/getStrokePoints.mjs +31 -96
- package/dist-esm/lib/shapes/shared/freehand/getStrokePoints.mjs.map +3 -3
- package/dist-esm/lib/shapes/shared/freehand/svg.mjs +55 -19
- package/dist-esm/lib/shapes/shared/freehand/svg.mjs.map +2 -2
- package/dist-esm/lib/shapes/shared/freehand/svgInk.mjs +214 -99
- package/dist-esm/lib/shapes/shared/freehand/svgInk.mjs.map +3 -3
- package/dist-esm/lib/shapes/shared/interpolate-props.mjs +6 -2
- package/dist-esm/lib/shapes/shared/interpolate-props.mjs.map +2 -2
- package/dist-esm/lib/shapes/text/toolStates/Pointing.mjs +4 -0
- package/dist-esm/lib/shapes/text/toolStates/Pointing.mjs.map +2 -2
- package/dist-esm/lib/tools/HandTool/HandTool.mjs +16 -6
- package/dist-esm/lib/tools/HandTool/HandTool.mjs.map +2 -2
- package/dist-esm/lib/tools/HandTool/childStates/Dragging.mjs +10 -1
- package/dist-esm/lib/tools/HandTool/childStates/Dragging.mjs.map +2 -2
- package/dist-esm/lib/tools/HandTool/childStates/OneFingerZooming.mjs +64 -0
- package/dist-esm/lib/tools/HandTool/childStates/OneFingerZooming.mjs.map +7 -0
- package/dist-esm/lib/tools/SelectTool/childStates/Idle.mjs +12 -0
- package/dist-esm/lib/tools/SelectTool/childStates/Idle.mjs.map +2 -2
- package/dist-esm/lib/tools/SelectTool/childStates/PointingShape.mjs +4 -0
- package/dist-esm/lib/tools/SelectTool/childStates/PointingShape.mjs.map +2 -2
- package/dist-esm/lib/tools/SelectTool/childStates/Resizing.mjs +108 -46
- package/dist-esm/lib/tools/SelectTool/childStates/Resizing.mjs.map +2 -2
- package/dist-esm/lib/ui/TldrawUi.mjs +4 -3
- package/dist-esm/lib/ui/TldrawUi.mjs.map +2 -2
- package/dist-esm/lib/ui/components/A11y.mjs +2 -0
- package/dist-esm/lib/ui/components/A11y.mjs.map +2 -2
- package/dist-esm/lib/ui/components/ContextMenu/DefaultContextMenu.mjs +21 -2
- package/dist-esm/lib/ui/components/ContextMenu/DefaultContextMenu.mjs.map +2 -2
- package/dist-esm/lib/ui/components/ContextMenu/DefaultContextMenuContent.mjs +0 -6
- package/dist-esm/lib/ui/components/ContextMenu/DefaultContextMenuContent.mjs.map +2 -2
- package/dist-esm/lib/ui/components/DefaultFollowingIndicator.mjs.map +2 -2
- package/dist-esm/lib/ui/components/Dialogs.mjs +19 -39
- package/dist-esm/lib/ui/components/Dialogs.mjs.map +2 -2
- package/dist-esm/lib/ui/components/HelperButtons/BackToContent.mjs +20 -5
- package/dist-esm/lib/ui/components/HelperButtons/BackToContent.mjs.map +2 -2
- package/dist-esm/lib/ui/components/KeyboardShortcutsDialog/DefaultKeyboardShortcutsDialogContent.mjs +12 -2
- package/dist-esm/lib/ui/components/KeyboardShortcutsDialog/DefaultKeyboardShortcutsDialogContent.mjs.map +2 -2
- package/dist-esm/lib/ui/components/Minimap/DefaultMinimap.mjs +47 -70
- package/dist-esm/lib/ui/components/Minimap/DefaultMinimap.mjs.map +2 -2
- package/dist-esm/lib/ui/components/Minimap/MinimapManager.mjs +25 -46
- package/dist-esm/lib/ui/components/Minimap/MinimapManager.mjs.map +2 -2
- package/dist-esm/lib/ui/components/SharePanel/DefaultPeopleMenuAvatar.mjs.map +2 -2
- package/dist-esm/lib/ui/components/SharePanel/DefaultPeopleMenuContent.mjs.map +2 -2
- package/dist-esm/lib/ui/components/SharePanel/DefaultPeopleMenuFacePile.mjs.map +2 -2
- package/dist-esm/lib/ui/components/SharePanel/DefaultPeopleMenuItem.mjs +1 -1
- package/dist-esm/lib/ui/components/SharePanel/DefaultPeopleMenuItem.mjs.map +2 -2
- package/dist-esm/lib/ui/components/StylePanel/StylePanelButtonPicker.mjs +1 -0
- package/dist-esm/lib/ui/components/StylePanel/StylePanelButtonPicker.mjs.map +2 -2
- package/dist-esm/lib/ui/components/menu-items.mjs +7 -0
- package/dist-esm/lib/ui/components/menu-items.mjs.map +2 -2
- package/dist-esm/lib/ui/components/primitives/TldrawUiDropdownMenu.mjs +2 -1
- package/dist-esm/lib/ui/components/primitives/TldrawUiDropdownMenu.mjs.map +2 -2
- package/dist-esm/lib/ui/components/primitives/TldrawUiIcon.mjs +14 -3
- package/dist-esm/lib/ui/components/primitives/TldrawUiIcon.mjs.map +2 -2
- package/dist-esm/lib/ui/components/primitives/TldrawUiInput.mjs +2 -0
- package/dist-esm/lib/ui/components/primitives/TldrawUiInput.mjs.map +2 -2
- package/dist-esm/lib/ui/components/primitives/TldrawUiPopover.mjs +2 -0
- package/dist-esm/lib/ui/components/primitives/TldrawUiPopover.mjs.map +2 -2
- package/dist-esm/lib/ui/components/primitives/menus/TldrawUiMenuCheckboxItem.mjs +0 -2
- package/dist-esm/lib/ui/components/primitives/menus/TldrawUiMenuCheckboxItem.mjs.map +2 -2
- package/dist-esm/lib/ui/components/primitives/menus/TldrawUiMenuSubmenu.mjs +1 -2
- package/dist-esm/lib/ui/components/primitives/menus/TldrawUiMenuSubmenu.mjs.map +2 -2
- package/dist-esm/lib/ui/context/actions.mjs +71 -1
- package/dist-esm/lib/ui/context/actions.mjs.map +2 -2
- package/dist-esm/lib/ui/context/asset-urls.mjs +5 -8
- package/dist-esm/lib/ui/context/asset-urls.mjs.map +2 -2
- package/dist-esm/lib/ui/context/events.mjs.map +2 -2
- package/dist-esm/lib/ui/hooks/useKeyboardShortcuts.mjs +13 -0
- package/dist-esm/lib/ui/hooks/useKeyboardShortcuts.mjs.map +2 -2
- package/dist-esm/lib/ui/hooks/useTools.mjs +1 -1
- package/dist-esm/lib/ui/hooks/useTools.mjs.map +2 -2
- package/dist-esm/lib/ui/hooks/useTranslation/defaultTranslation.mjs +2 -0
- package/dist-esm/lib/ui/hooks/useTranslation/defaultTranslation.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/embeds/embeds.mjs +4 -4
- package/dist-esm/lib/utils/embeds/embeds.mjs.map +2 -2
- package/dist-esm/lib/utils/test-helpers.mjs +2 -2
- package/dist-esm/lib/utils/test-helpers.mjs.map +2 -2
- package/dist-esm/lib/utils/text/richText.mjs +3 -1
- package/dist-esm/lib/utils/text/richText.mjs.map +2 -2
- package/package.json +11 -6
- package/src/index.ts +6 -1
- package/src/lib/TldrawImage.tsx +2 -2
- package/src/lib/bindings/arrow/ArrowBindingUtil.ts +5 -1
- package/src/lib/defaultEmbedDefinitions.ts +28 -6
- package/src/lib/defaultOverlayUtils.ts +11 -11
- package/src/lib/overlays/SelectionForegroundOverlayUtil.ts +91 -72
- package/src/lib/overlays/ShapeHandleOverlayUtil.ts +3 -1
- package/src/lib/overlays/ShapeIndicatorOverlayUtil.ts +133 -0
- package/src/lib/shapes/arrow/toolStates/Pointing.tsx +11 -1
- package/src/lib/shapes/bookmark/BookmarkShapeUtil.tsx +16 -3
- package/src/lib/shapes/bookmark/bookmarks.ts +105 -15
- package/src/lib/shapes/draw/DrawShapeUtil.tsx +7 -5
- package/src/lib/shapes/draw/getPath.ts +1 -1
- package/src/lib/shapes/draw/toolStates/Drawing.ts +55 -48
- package/src/lib/shapes/embed/EmbedShapeUtil.tsx +14 -4
- package/src/lib/shapes/frame/FrameShapeTool.ts +35 -24
- package/src/lib/shapes/geo/GeoShapeUtil.test.tsx +46 -0
- package/src/lib/shapes/geo/GeoShapeUtil.tsx +2 -1
- package/src/lib/shapes/geo/toolStates/Pointing.ts +5 -0
- package/src/lib/shapes/highlight/HighlightShapeUtil.tsx +14 -11
- package/src/lib/shapes/image/ImageShapeUtil.tsx +7 -11
- package/src/lib/shapes/line/LineShapeTool.test.ts +41 -0
- package/src/lib/shapes/line/toolStates/Pointing.ts +12 -2
- package/src/lib/shapes/note/NoteShapeUtil.tsx +36 -51
- package/src/lib/shapes/note/noteCloning.test.ts +5 -5
- package/src/lib/shapes/note/noteHelpers.ts +1 -1
- package/src/lib/shapes/note/toolStates/Pointing.ts +40 -7
- package/src/lib/shapes/shared/PlainTextLabel.tsx +3 -3
- package/src/lib/shapes/shared/RichTextLabel.tsx +4 -3
- package/src/lib/shapes/shared/defaultStyleDefs.tsx +25 -3
- package/src/lib/shapes/shared/freehand/core.ts +547 -0
- package/src/lib/shapes/shared/freehand/fmt.ts +106 -0
- package/src/lib/shapes/shared/freehand/getStroke.ts +7 -7
- package/src/lib/shapes/shared/freehand/getStrokeOutlinePoints.ts +451 -139
- package/src/lib/shapes/shared/freehand/getStrokePoints.ts +33 -153
- package/src/lib/shapes/shared/freehand/svg.ts +72 -23
- package/src/lib/shapes/shared/freehand/svgInk.ts +281 -136
- package/src/lib/shapes/shared/freehand/types.ts +0 -1
- package/src/lib/shapes/shared/interpolate-props.ts +6 -2
- package/src/lib/shapes/text/toolStates/Pointing.ts +5 -0
- package/src/lib/tools/HandTool/HandTool.ts +19 -6
- package/src/lib/tools/HandTool/childStates/Dragging.ts +17 -1
- package/src/lib/tools/HandTool/childStates/OneFingerZooming.ts +79 -0
- package/src/lib/tools/SelectTool/childStates/Idle.ts +16 -2
- package/src/lib/tools/SelectTool/childStates/PointingShape.ts +8 -0
- package/src/lib/tools/SelectTool/childStates/Resizing.ts +137 -49
- package/src/lib/ui/TldrawUi.tsx +3 -3
- package/src/lib/ui/components/A11y.tsx +2 -0
- package/src/lib/ui/components/ContextMenu/DefaultContextMenu.tsx +32 -2
- package/src/lib/ui/components/ContextMenu/DefaultContextMenuContent.tsx +5 -6
- package/src/lib/ui/components/DefaultFollowingIndicator.tsx +2 -2
- package/src/lib/ui/components/Dialogs.tsx +20 -23
- package/src/lib/ui/components/HelperButtons/BackToContent.tsx +32 -4
- package/src/lib/ui/components/KeyboardShortcutsDialog/DefaultKeyboardShortcutsDialogContent.tsx +10 -0
- package/src/lib/ui/components/Minimap/DefaultMinimap.tsx +60 -74
- package/src/lib/ui/components/Minimap/MinimapManager.ts +35 -57
- package/src/lib/ui/components/SharePanel/DefaultPeopleMenuAvatar.tsx +2 -2
- package/src/lib/ui/components/SharePanel/DefaultPeopleMenuContent.tsx +2 -1
- package/src/lib/ui/components/SharePanel/DefaultPeopleMenuFacePile.tsx +2 -1
- package/src/lib/ui/components/SharePanel/DefaultPeopleMenuItem.tsx +3 -3
- package/src/lib/ui/components/StylePanel/StylePanelButtonPicker.tsx +5 -0
- package/src/lib/ui/components/menu-items.tsx +9 -0
- package/src/lib/ui/components/primitives/TldrawUiDropdownMenu.tsx +3 -1
- package/src/lib/ui/components/primitives/TldrawUiIcon.tsx +15 -3
- package/src/lib/ui/components/primitives/TldrawUiInput.tsx +4 -0
- package/src/lib/ui/components/primitives/TldrawUiPopover.tsx +7 -0
- package/src/lib/ui/components/primitives/menus/TldrawUiMenuCheckboxItem.tsx +0 -2
- package/src/lib/ui/components/primitives/menus/TldrawUiMenuSubmenu.tsx +0 -1
- package/src/lib/ui/context/actions.tsx +88 -1
- package/src/lib/ui/context/asset-urls.tsx +9 -8
- package/src/lib/ui/context/events.tsx +2 -0
- package/src/lib/ui/hooks/useKeyboardShortcuts.ts +45 -7
- package/src/lib/ui/hooks/useTools.tsx +7 -1
- package/src/lib/ui/hooks/useTranslation/TLUiTranslationKey.ts +2 -0
- package/src/lib/ui/hooks/useTranslation/defaultTranslation.ts +2 -0
- package/src/lib/ui/version.ts +3 -3
- package/src/lib/ui.css +20 -9
- package/src/lib/utils/embeds/embeds.test.ts +14 -12
- package/src/lib/utils/embeds/embeds.ts +10 -4
- package/src/lib/utils/test-helpers.ts +3 -3
- package/src/lib/utils/text/richText.test.ts +36 -0
- package/src/lib/utils/text/richText.ts +9 -1
- package/src/test/HandTool.test.ts +93 -0
- package/src/test/ImageShapeUtil.test.ts +88 -0
- package/src/test/SelectTool.test.ts +102 -1
- package/src/test/__snapshots__/drawing.test.ts.snap +2 -1
- package/src/test/attribution.test.ts +40 -29
- package/src/test/bookmark-shapes.test.ts +256 -28
- package/src/test/commands/__snapshots__/getSvgString.test.ts.snap +2 -2
- package/src/test/commands/clipboardCallbacks.test.ts +3 -1
- package/src/test/commands/getSvgString.test.ts +30 -0
- package/src/test/commands/penmode.test.ts +97 -1
- package/src/test/commands/setCamera.test.ts +12 -0
- package/src/test/dragFromToolbar.test.ts +67 -0
- package/src/test/drawing.test.ts +48 -7
- package/src/test/frames.test.ts +72 -0
- package/src/test/freehand/corpus/presets.ts +71 -0
- package/src/test/freehand/corpus/real.ts +370 -0
- package/src/test/freehand/corpus/strokes.ts +50 -0
- package/src/test/freehand/svg.test.ts +20 -0
- package/src/test/freehand/wellformed.test.ts +30 -0
- package/src/test/long-press-create.test.ts +102 -0
- package/src/test/overlays/CollaboratorBrushOverlayUtil.test.ts +4 -4
- package/src/test/overlays/CollaboratorCursorOverlayUtil.test.ts +18 -18
- package/src/test/overlays/CollaboratorHintOverlayUtil.test.ts +7 -7
- package/src/test/overlays/CollaboratorScribbleOverlayUtil.test.ts +3 -3
- package/src/test/overlays/OverlayManager.test.ts +1 -1
- package/src/test/overlays/SelectionForegroundOverlayUtil.test.ts +58 -0
- package/src/test/overlays/ShapeHandleOverlayUtil.test.ts +2 -2
- package/src/test/overlays/ShapeIndicatorOverlayUtil.test.ts +36 -0
- package/src/test/resizing.test.ts +250 -0
- package/src/test/right-click-context-menu.test.ts +90 -0
- package/src/test/rightClickPanning.test.ts +11 -0
- package/src/test/selection-omnibus.test.ts +15 -2
- package/src/test/spatialIndex.test.ts +132 -0
- package/src/test/translating.test.ts +0 -6
- package/src/test/ui/ContextMenu.test.tsx +146 -3
- package/src/test/ui/Dialogs.test.tsx +256 -0
- package/src/test/ui/copyHoveredStyles.test.tsx +154 -0
- package/src/test/ui/keyboardShortcuts.test.tsx +266 -0
- package/tldraw.css +35 -12
- package/dist-cjs/lib/shapes/shared/freehand/setStrokePointRadii.js +0 -100
- package/dist-cjs/lib/shapes/shared/freehand/setStrokePointRadii.js.map +0 -7
- package/dist-esm/lib/shapes/shared/freehand/setStrokePointRadii.mjs +0 -80
- package/dist-esm/lib/shapes/shared/freehand/setStrokePointRadii.mjs.map +0 -7
- package/src/lib/shapes/shared/freehand/setStrokePointRadii.ts +0 -127
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import { VecModel } from '@tldraw/editor'
|
|
2
|
+
import { StrokeOptions } from '../../../lib/shapes/shared/freehand/types'
|
|
3
|
+
import {
|
|
4
|
+
highlightSettings,
|
|
5
|
+
realPressureSettings,
|
|
6
|
+
simulatePressureSettings,
|
|
7
|
+
solidSettings,
|
|
8
|
+
} from './presets'
|
|
9
|
+
import { REAL_STROKES } from './real'
|
|
10
|
+
|
|
11
|
+
/** A single comparison case: recorded input points plus the options tldraw would use. */
|
|
12
|
+
export interface CorpusCase {
|
|
13
|
+
id: string
|
|
14
|
+
/** What kind of tldraw stroke this represents. */
|
|
15
|
+
kind: 'draw' | 'pen' | 'solid' | 'highlight'
|
|
16
|
+
points: VecModel[]
|
|
17
|
+
options: StrokeOptions
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
function makeCases(): CorpusCase[] {
|
|
21
|
+
const cases: CorpusCase[] = []
|
|
22
|
+
|
|
23
|
+
const add = (
|
|
24
|
+
id: string,
|
|
25
|
+
kind: CorpusCase['kind'],
|
|
26
|
+
points: VecModel[],
|
|
27
|
+
options: StrokeOptions,
|
|
28
|
+
last = true
|
|
29
|
+
) => {
|
|
30
|
+
cases.push({ id, kind, points, options: { ...options, last } })
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
// All strokes were drawn with a mouse at size 'xl' and scale 1, so tldraw passes
|
|
34
|
+
// strokeWidth = (theme.strokeWidth 2 * STROKE_SIZES.xl 5 + 1) * scale 1 = 11. Each
|
|
35
|
+
// stroke is also rendered mid-draw and through the other stroke kinds' settings, so
|
|
36
|
+
// every rendering path sees real input.
|
|
37
|
+
REAL_STROKES.forEach(({ points }, i) => {
|
|
38
|
+
const id = `real-${i + 1}`
|
|
39
|
+
add(id, 'draw', points, simulatePressureSettings(11))
|
|
40
|
+
add(`${id}-in-progress`, 'draw', points, simulatePressureSettings(11), false)
|
|
41
|
+
add(`${id}-pen`, 'pen', points, realPressureSettings(11))
|
|
42
|
+
add(`${id}-solid`, 'solid', points, solidSettings(11))
|
|
43
|
+
add(`${id}-highlight`, 'highlight', points, highlightSettings(22))
|
|
44
|
+
})
|
|
45
|
+
|
|
46
|
+
return cases
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
/** The full corpus of comparison cases: real hand-drawn strokes recorded in tldraw. */
|
|
50
|
+
export const CORPUS: CorpusCase[] = makeCases()
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { describe, expect, it } from 'vitest'
|
|
2
|
+
import { getSvgPathFromStrokePoints } from '../../lib/shapes/shared/freehand/svg'
|
|
3
|
+
import { StrokePoint } from '../../lib/shapes/shared/freehand/types'
|
|
4
|
+
|
|
5
|
+
function pt(x: number, y: number): StrokePoint {
|
|
6
|
+
return { point: { x, y } } as StrokePoint
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
// The corpus never produces a two-point stroke, so the parity gate doesn't
|
|
10
|
+
// cover this branch; keep a direct check on its output.
|
|
11
|
+
describe('getSvgPathFromStrokePoints', () => {
|
|
12
|
+
it('renders a two-point stroke as a single relative line', () => {
|
|
13
|
+
expect(getSvgPathFromStrokePoints([pt(0, 0), pt(10.5, 20.25)])).toBe('M0,0 l10.5,20.25 ')
|
|
14
|
+
})
|
|
15
|
+
|
|
16
|
+
it('renders nothing for fewer than two points', () => {
|
|
17
|
+
expect(getSvgPathFromStrokePoints([])).toBe('')
|
|
18
|
+
expect(getSvgPathFromStrokePoints([pt(5, 5)])).toBe('')
|
|
19
|
+
})
|
|
20
|
+
})
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { describe, expect, it } from 'vitest'
|
|
2
|
+
import { getStrokePoints } from '../../lib/shapes/shared/freehand/getStrokePoints'
|
|
3
|
+
import { getSvgPathFromStrokePoints } from '../../lib/shapes/shared/freehand/svg'
|
|
4
|
+
import { svgInk } from '../../lib/shapes/shared/freehand/svgInk'
|
|
5
|
+
import { CORPUS, CorpusCase } from './corpus/strokes'
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Produce the svg path data tldraw would actually render for this case. Strokes with the 'draw'
|
|
9
|
+
* dash style (mouse or pen) are rendered as a filled outline via svgInk; solid strokes and the
|
|
10
|
+
* highlighter are rendered as a stroked centerline path.
|
|
11
|
+
*/
|
|
12
|
+
function renderCase(c: CorpusCase): string {
|
|
13
|
+
if (c.kind === 'draw' || c.kind === 'pen') {
|
|
14
|
+
return svgInk(c.points, c.options)
|
|
15
|
+
}
|
|
16
|
+
return getSvgPathFromStrokePoints(getStrokePoints(c.points, c.options), false)
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
// The unit tests on the individual functions can't catch a malformed path string coming out of
|
|
20
|
+
// the full pipeline, so check the path data tldraw would render for every corpus case.
|
|
21
|
+
describe('svg path data is well formed', () => {
|
|
22
|
+
it.each(CORPUS.map((c) => [c.id, c] as const))('%s', (_id, c) => {
|
|
23
|
+
const svg = renderCase(c)
|
|
24
|
+
expect(svg.startsWith('M')).toBe(true)
|
|
25
|
+
expect(svg).not.toContain('NaN')
|
|
26
|
+
expect(svg).not.toContain('Infinity')
|
|
27
|
+
// only valid path characters
|
|
28
|
+
expect(svg).toMatch(/^[MLQTACZmlqtacz0-9 ,.-]+$/)
|
|
29
|
+
})
|
|
30
|
+
})
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
import { vi } from 'vitest'
|
|
2
|
+
import { TestEditor } from './TestEditor'
|
|
3
|
+
|
|
4
|
+
let editor: TestEditor
|
|
5
|
+
|
|
6
|
+
beforeEach(() => {
|
|
7
|
+
editor = new TestEditor()
|
|
8
|
+
})
|
|
9
|
+
afterEach(() => {
|
|
10
|
+
editor?.dispose()
|
|
11
|
+
})
|
|
12
|
+
|
|
13
|
+
vi.useFakeTimers()
|
|
14
|
+
|
|
15
|
+
// On a touch device a long press fires the browser `contextmenu` event. A discrete
|
|
16
|
+
// shape-creation tool (geo, note, line, text, arrow, frame) should respond by
|
|
17
|
+
// canceling any pending creation and returning to its own idle state, so the long
|
|
18
|
+
// press leaves no shape behind (#8277) and opens no menu — the context menu is a
|
|
19
|
+
// select-tool surface, reached on touch only from the select tool. The guard is
|
|
20
|
+
// `isCoarsePointer`, so fine-pointer (desktop) behavior must be preserved.
|
|
21
|
+
// Continuous-gesture tools (draw, highlight, eraser, laser) are excluded: their
|
|
22
|
+
// press is their own action, so a long press keeps that gesture going.
|
|
23
|
+
const CREATION_TOOLS = [
|
|
24
|
+
{ tool: 'geo', pointingState: 'geo.pointing' },
|
|
25
|
+
{ tool: 'note', pointingState: 'note.pointing' },
|
|
26
|
+
{ tool: 'text', pointingState: 'text.pointing' },
|
|
27
|
+
{ tool: 'line', pointingState: 'line.pointing' },
|
|
28
|
+
{ tool: 'arrow', pointingState: 'arrow.pointing' },
|
|
29
|
+
{ tool: 'frame', pointingState: 'frame.pointing' },
|
|
30
|
+
] as const
|
|
31
|
+
|
|
32
|
+
describe('long press on shape-creation tools', () => {
|
|
33
|
+
describe('with a coarse pointer', () => {
|
|
34
|
+
beforeEach(() => {
|
|
35
|
+
editor.updateInstanceState({ isCoarsePointer: true })
|
|
36
|
+
})
|
|
37
|
+
|
|
38
|
+
it.each(CREATION_TOOLS)(
|
|
39
|
+
'$tool cancels creation and returns to its idle state, leaving no shape behind',
|
|
40
|
+
({ tool }) => {
|
|
41
|
+
editor.setCurrentTool(tool)
|
|
42
|
+
editor.pointerDown(100, 100)
|
|
43
|
+
vi.advanceTimersByTime(editor.options.longPressDurationMs)
|
|
44
|
+
|
|
45
|
+
// back in the tool's own idle — not switched to select, no menu
|
|
46
|
+
editor.expectToBeIn(`${tool}.idle`)
|
|
47
|
+
expect(editor.getCurrentPageShapes()).toHaveLength(0)
|
|
48
|
+
|
|
49
|
+
// releasing the long press must not create a shape either
|
|
50
|
+
editor.pointerUp(100, 100)
|
|
51
|
+
expect(editor.getCurrentPageShapes()).toHaveLength(0)
|
|
52
|
+
}
|
|
53
|
+
)
|
|
54
|
+
|
|
55
|
+
it('continuous-gesture tools keep their gesture on long press', () => {
|
|
56
|
+
// Unlike the discrete tools, a freehand tool starts a stroke on
|
|
57
|
+
// pointer-down, so the long press is part of the stroke. It must not
|
|
58
|
+
// cancel — the stroke continues.
|
|
59
|
+
editor.setCurrentTool('draw')
|
|
60
|
+
editor.pointerDown(100, 100)
|
|
61
|
+
editor.expectToBeIn('draw.drawing')
|
|
62
|
+
|
|
63
|
+
vi.advanceTimersByTime(editor.options.longPressDurationMs)
|
|
64
|
+
|
|
65
|
+
editor.expectToBeIn('draw.drawing')
|
|
66
|
+
editor.pointerUp(100, 100)
|
|
67
|
+
expect(editor.getCurrentPageShapes()).toHaveLength(1)
|
|
68
|
+
})
|
|
69
|
+
|
|
70
|
+
it('defers note creation so a long press never flashes a note', () => {
|
|
71
|
+
// The note creates on press, so without deferral the long-press cancel
|
|
72
|
+
// would briefly show then remove it. On a coarse pointer it is created on
|
|
73
|
+
// release (or drag) instead, so nothing appears during the press.
|
|
74
|
+
editor.setCurrentTool('note')
|
|
75
|
+
editor.pointerDown(100, 100)
|
|
76
|
+
expect(editor.getCurrentPageShapes()).toHaveLength(0)
|
|
77
|
+
|
|
78
|
+
// a tap still creates the note on release
|
|
79
|
+
editor.pointerUp(100, 100)
|
|
80
|
+
const shapes = editor.getCurrentPageShapes()
|
|
81
|
+
expect(shapes).toHaveLength(1)
|
|
82
|
+
expect(shapes[0].type).toBe('note')
|
|
83
|
+
})
|
|
84
|
+
})
|
|
85
|
+
|
|
86
|
+
describe('with a fine pointer, the long press is ignored', () => {
|
|
87
|
+
beforeEach(() => {
|
|
88
|
+
editor.updateInstanceState({ isCoarsePointer: false })
|
|
89
|
+
})
|
|
90
|
+
|
|
91
|
+
it.each(CREATION_TOOLS)('$tool stays in $pointingState', ({ tool, pointingState }) => {
|
|
92
|
+
editor.setCurrentTool(tool)
|
|
93
|
+
editor.pointerDown(100, 100)
|
|
94
|
+
editor.expectToBeIn(pointingState)
|
|
95
|
+
|
|
96
|
+
vi.advanceTimersByTime(editor.options.longPressDurationMs)
|
|
97
|
+
|
|
98
|
+
// desktop behavior is preserved: the tool is still mid-creation
|
|
99
|
+
editor.expectToBeIn(pointingState)
|
|
100
|
+
})
|
|
101
|
+
})
|
|
102
|
+
})
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { InstancePresenceRecordType } from '@tldraw/tlschema'
|
|
1
|
+
import { createUserId, InstancePresenceRecordType } from '@tldraw/tlschema'
|
|
2
2
|
import { defaultOverlayUtils } from '../../lib/defaultOverlayUtils'
|
|
3
3
|
import { CollaboratorBrushOverlayUtil } from '../../lib/overlays/CollaboratorBrushOverlayUtil'
|
|
4
4
|
import { TestEditor } from '../TestEditor'
|
|
@@ -22,7 +22,7 @@ describe('CollaboratorBrushOverlayUtil', () => {
|
|
|
22
22
|
editor.store.put([
|
|
23
23
|
InstancePresenceRecordType.create({
|
|
24
24
|
id: InstancePresenceRecordType.createId('peer1'),
|
|
25
|
-
userId: 'peer1',
|
|
25
|
+
userId: createUserId('peer1'),
|
|
26
26
|
userName: 'Peer 1',
|
|
27
27
|
currentPageId: pageId,
|
|
28
28
|
brush: { x: 1, y: 2, w: 3, h: 4 },
|
|
@@ -46,7 +46,7 @@ describe('CollaboratorBrushOverlayUtil', () => {
|
|
|
46
46
|
editor.store.put([
|
|
47
47
|
InstancePresenceRecordType.create({
|
|
48
48
|
id: InstancePresenceRecordType.createId('peer1'),
|
|
49
|
-
userId: 'peer1',
|
|
49
|
+
userId: createUserId('peer1'),
|
|
50
50
|
userName: 'Peer 1',
|
|
51
51
|
currentPageId: pageId,
|
|
52
52
|
color: '#123456',
|
|
@@ -54,7 +54,7 @@ describe('CollaboratorBrushOverlayUtil', () => {
|
|
|
54
54
|
}),
|
|
55
55
|
InstancePresenceRecordType.create({
|
|
56
56
|
id: InstancePresenceRecordType.createId('peer2'),
|
|
57
|
-
userId: 'peer2',
|
|
57
|
+
userId: createUserId('peer2'),
|
|
58
58
|
userName: 'Peer 2',
|
|
59
59
|
currentPageId: pageId,
|
|
60
60
|
color: '#abcdef',
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { InstancePresenceRecordType } from '@tldraw/tlschema'
|
|
1
|
+
import { createUserId, InstancePresenceRecordType } from '@tldraw/tlschema'
|
|
2
2
|
import { vi } from 'vitest'
|
|
3
3
|
import { defaultOverlayUtils } from '../../lib/defaultOverlayUtils'
|
|
4
4
|
import { CollaboratorCursorOverlayUtil } from '../../lib/overlays/CollaboratorCursorOverlayUtil'
|
|
@@ -73,7 +73,7 @@ describe('CollaboratorCursorOverlayUtil', () => {
|
|
|
73
73
|
editor.store.put([
|
|
74
74
|
InstancePresenceRecordType.create({
|
|
75
75
|
id: InstancePresenceRecordType.createId('peer1'),
|
|
76
|
-
userId: 'peer1',
|
|
76
|
+
userId: createUserId('peer1'),
|
|
77
77
|
userName: 'Peer 1',
|
|
78
78
|
currentPageId: pageId,
|
|
79
79
|
cursor: { type: 'default', x: 10, y: 10, rotation: 0 },
|
|
@@ -98,7 +98,7 @@ describe('CollaboratorCursorOverlayUtil', () => {
|
|
|
98
98
|
editor.store.put([
|
|
99
99
|
InstancePresenceRecordType.create({
|
|
100
100
|
id: InstancePresenceRecordType.createId('peer1'),
|
|
101
|
-
userId: 'peer1',
|
|
101
|
+
userId: createUserId('peer1'),
|
|
102
102
|
userName: 'Alice',
|
|
103
103
|
currentPageId: pageId,
|
|
104
104
|
color: '#a',
|
|
@@ -107,7 +107,7 @@ describe('CollaboratorCursorOverlayUtil', () => {
|
|
|
107
107
|
}),
|
|
108
108
|
InstancePresenceRecordType.create({
|
|
109
109
|
id: InstancePresenceRecordType.createId('peer2'),
|
|
110
|
-
userId: 'peer2',
|
|
110
|
+
userId: createUserId('peer2'),
|
|
111
111
|
userName: 'Bob',
|
|
112
112
|
currentPageId: pageId,
|
|
113
113
|
color: '#b',
|
|
@@ -130,7 +130,7 @@ describe('CollaboratorCursorOverlayUtil', () => {
|
|
|
130
130
|
editor.store.put([
|
|
131
131
|
InstancePresenceRecordType.create({
|
|
132
132
|
id: InstancePresenceRecordType.createId('peer3'),
|
|
133
|
-
userId: 'peer3',
|
|
133
|
+
userId: createUserId('peer3'),
|
|
134
134
|
userName: 'Carol',
|
|
135
135
|
currentPageId: pageId,
|
|
136
136
|
color: '#c',
|
|
@@ -150,7 +150,7 @@ describe('CollaboratorCursorOverlayUtil', () => {
|
|
|
150
150
|
// inactive (way past timeout) — not shown
|
|
151
151
|
InstancePresenceRecordType.create({
|
|
152
152
|
id: InstancePresenceRecordType.createId('p_inactive'),
|
|
153
|
-
userId: 'p_inactive',
|
|
153
|
+
userId: createUserId('p_inactive'),
|
|
154
154
|
userName: 'Inactive',
|
|
155
155
|
currentPageId: pageId,
|
|
156
156
|
cursor: { type: 'default', x: 10, y: 10, rotation: 0 },
|
|
@@ -159,7 +159,7 @@ describe('CollaboratorCursorOverlayUtil', () => {
|
|
|
159
159
|
// idle (between thresholds) — shown
|
|
160
160
|
InstancePresenceRecordType.create({
|
|
161
161
|
id: InstancePresenceRecordType.createId('p_idle'),
|
|
162
|
-
userId: 'p_idle',
|
|
162
|
+
userId: createUserId('p_idle'),
|
|
163
163
|
userName: 'Idle',
|
|
164
164
|
currentPageId: pageId,
|
|
165
165
|
cursor: { type: 'default', x: 15, y: 15, rotation: 0 },
|
|
@@ -168,7 +168,7 @@ describe('CollaboratorCursorOverlayUtil', () => {
|
|
|
168
168
|
// active — shown
|
|
169
169
|
InstancePresenceRecordType.create({
|
|
170
170
|
id: InstancePresenceRecordType.createId('p_active'),
|
|
171
|
-
userId: 'p_active',
|
|
171
|
+
userId: createUserId('p_active'),
|
|
172
172
|
userName: 'Active',
|
|
173
173
|
currentPageId: pageId,
|
|
174
174
|
cursor: { type: 'default', x: 20, y: 20, rotation: 0 },
|
|
@@ -184,12 +184,12 @@ describe('CollaboratorCursorOverlayUtil', () => {
|
|
|
184
184
|
|
|
185
185
|
it('shows inactive collaborators when following them', () => {
|
|
186
186
|
const pageId = editor.getCurrentPageId()
|
|
187
|
-
editor.updateInstanceState({ followingUserId: 'peerF' })
|
|
187
|
+
editor.updateInstanceState({ followingUserId: createUserId('peerF') })
|
|
188
188
|
const now = Date.now()
|
|
189
189
|
editor.store.put([
|
|
190
190
|
InstancePresenceRecordType.create({
|
|
191
191
|
id: InstancePresenceRecordType.createId('presenceF'),
|
|
192
|
-
userId: 'peerF',
|
|
192
|
+
userId: createUserId('peerF'),
|
|
193
193
|
userName: 'Followed',
|
|
194
194
|
currentPageId: pageId,
|
|
195
195
|
cursor: { type: 'default', x: 10, y: 10, rotation: 0 },
|
|
@@ -204,12 +204,12 @@ describe('CollaboratorCursorOverlayUtil', () => {
|
|
|
204
204
|
|
|
205
205
|
it('shows inactive collaborators when they are highlighted', () => {
|
|
206
206
|
const pageId = editor.getCurrentPageId()
|
|
207
|
-
editor.updateInstanceState({ highlightedUserIds: ['peerH'] })
|
|
207
|
+
editor.updateInstanceState({ highlightedUserIds: [createUserId('peerH')] })
|
|
208
208
|
const now = Date.now()
|
|
209
209
|
editor.store.put([
|
|
210
210
|
InstancePresenceRecordType.create({
|
|
211
211
|
id: InstancePresenceRecordType.createId('presenceH'),
|
|
212
|
-
userId: 'peerH',
|
|
212
|
+
userId: createUserId('peerH'),
|
|
213
213
|
userName: 'Highlighted',
|
|
214
214
|
currentPageId: pageId,
|
|
215
215
|
cursor: { type: 'default', x: 20, y: 20, rotation: 0 },
|
|
@@ -228,12 +228,12 @@ describe('CollaboratorCursorOverlayUtil', () => {
|
|
|
228
228
|
editor.store.put([
|
|
229
229
|
InstancePresenceRecordType.create({
|
|
230
230
|
id: InstancePresenceRecordType.createId('presenceFU'),
|
|
231
|
-
userId: 'peerFU',
|
|
231
|
+
userId: createUserId('peerFU'),
|
|
232
232
|
userName: 'Follower',
|
|
233
233
|
currentPageId: pageId,
|
|
234
234
|
cursor: { type: 'default', x: 30, y: 30, rotation: 0 },
|
|
235
235
|
lastActivityTimestamp: now - 5 * 1000,
|
|
236
|
-
followingUserId: editor.user.
|
|
236
|
+
followingUserId: editor.user.getRecordId(),
|
|
237
237
|
}),
|
|
238
238
|
])
|
|
239
239
|
const overlays = editor.overlays
|
|
@@ -248,12 +248,12 @@ describe('CollaboratorCursorOverlayUtil', () => {
|
|
|
248
248
|
editor.store.put([
|
|
249
249
|
InstancePresenceRecordType.create({
|
|
250
250
|
id: InstancePresenceRecordType.createId('presenceChat'),
|
|
251
|
-
userId: 'peerChat',
|
|
251
|
+
userId: createUserId('peerChat'),
|
|
252
252
|
userName: 'Follower Chat',
|
|
253
253
|
currentPageId: pageId,
|
|
254
254
|
cursor: { type: 'default', x: 40, y: 40, rotation: 0 },
|
|
255
255
|
lastActivityTimestamp: now - 5 * 1000,
|
|
256
|
-
followingUserId: editor.user.
|
|
256
|
+
followingUserId: editor.user.getRecordId(),
|
|
257
257
|
chatMessage: 'Hello',
|
|
258
258
|
}),
|
|
259
259
|
])
|
|
@@ -268,7 +268,7 @@ describe('CollaboratorCursorOverlayUtil', () => {
|
|
|
268
268
|
editor.store.put([
|
|
269
269
|
InstancePresenceRecordType.create({
|
|
270
270
|
id: InstancePresenceRecordType.createId('peer4'),
|
|
271
|
-
userId: 'peer4',
|
|
271
|
+
userId: createUserId('peer4'),
|
|
272
272
|
userName: 'New User',
|
|
273
273
|
currentPageId: pageId,
|
|
274
274
|
cursor: { type: 'default', x: 10, y: 10, rotation: 0 },
|
|
@@ -290,7 +290,7 @@ describe('CollaboratorCursorOverlayUtil', () => {
|
|
|
290
290
|
timedEditor.store.put([
|
|
291
291
|
InstancePresenceRecordType.create({
|
|
292
292
|
id: InstancePresenceRecordType.createId('peer_timed'),
|
|
293
|
-
userId: 'peer_timed',
|
|
293
|
+
userId: createUserId('peer_timed'),
|
|
294
294
|
userName: 'Timed Peer',
|
|
295
295
|
currentPageId: pageId,
|
|
296
296
|
cursor: { type: 'default', x: 10, y: 10, rotation: 0 },
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { InstancePresenceRecordType } from '@tldraw/tlschema'
|
|
1
|
+
import { createUserId, InstancePresenceRecordType } from '@tldraw/tlschema'
|
|
2
2
|
import { defaultOverlayUtils } from '../../lib/defaultOverlayUtils'
|
|
3
3
|
import { CollaboratorHintOverlayUtil } from '../../lib/overlays/CollaboratorHintOverlayUtil'
|
|
4
4
|
import { TestEditor } from '../TestEditor'
|
|
@@ -22,7 +22,7 @@ describe('CollaboratorHintOverlayUtil', () => {
|
|
|
22
22
|
editor.store.put([
|
|
23
23
|
InstancePresenceRecordType.create({
|
|
24
24
|
id: InstancePresenceRecordType.createId('peer1'),
|
|
25
|
-
userId: 'peer1',
|
|
25
|
+
userId: createUserId('peer1'),
|
|
26
26
|
userName: 'Peer 1',
|
|
27
27
|
currentPageId: pageId,
|
|
28
28
|
cursor: { type: 'default', x: 100000, y: 100000, rotation: 0 },
|
|
@@ -46,7 +46,7 @@ describe('CollaboratorHintOverlayUtil', () => {
|
|
|
46
46
|
editor.store.put([
|
|
47
47
|
InstancePresenceRecordType.create({
|
|
48
48
|
id: InstancePresenceRecordType.createId('peer1'),
|
|
49
|
-
userId: 'peer1',
|
|
49
|
+
userId: createUserId('peer1'),
|
|
50
50
|
userName: 'Peer 1',
|
|
51
51
|
currentPageId: pageId,
|
|
52
52
|
color: '#c00',
|
|
@@ -55,7 +55,7 @@ describe('CollaboratorHintOverlayUtil', () => {
|
|
|
55
55
|
}),
|
|
56
56
|
InstancePresenceRecordType.create({
|
|
57
57
|
id: InstancePresenceRecordType.createId('peer2'),
|
|
58
|
-
userId: 'peer2',
|
|
58
|
+
userId: createUserId('peer2'),
|
|
59
59
|
userName: 'Peer 2',
|
|
60
60
|
currentPageId: pageId,
|
|
61
61
|
color: '#0c0',
|
|
@@ -77,7 +77,7 @@ describe('CollaboratorHintOverlayUtil', () => {
|
|
|
77
77
|
editor.store.put([
|
|
78
78
|
InstancePresenceRecordType.create({
|
|
79
79
|
id: InstancePresenceRecordType.createId('peer1'),
|
|
80
|
-
userId: 'peer1',
|
|
80
|
+
userId: createUserId('peer1'),
|
|
81
81
|
userName: 'Peer 1',
|
|
82
82
|
currentPageId: pageId,
|
|
83
83
|
color: '#c00',
|
|
@@ -95,13 +95,13 @@ describe('CollaboratorHintOverlayUtil', () => {
|
|
|
95
95
|
editor.store.put([
|
|
96
96
|
InstancePresenceRecordType.create({
|
|
97
97
|
id: InstancePresenceRecordType.createId('peer1'),
|
|
98
|
-
userId: 'peer1',
|
|
98
|
+
userId: createUserId('peer1'),
|
|
99
99
|
userName: 'Peer 1',
|
|
100
100
|
currentPageId: pageId,
|
|
101
101
|
color: '#c00',
|
|
102
102
|
cursor: { type: 'default', x: 100000, y: 100000, rotation: 0 },
|
|
103
103
|
lastActivityTimestamp: now - 5 * 1000,
|
|
104
|
-
followingUserId: editor.user.
|
|
104
|
+
followingUserId: editor.user.getRecordId(),
|
|
105
105
|
}),
|
|
106
106
|
])
|
|
107
107
|
const util = editor.overlays.getOverlayUtil<CollaboratorHintOverlayUtil>('collaborator_hint')
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { InstancePresenceRecordType } from '@tldraw/tlschema'
|
|
1
|
+
import { createUserId, InstancePresenceRecordType } from '@tldraw/tlschema'
|
|
2
2
|
import { defaultOverlayUtils } from '../../lib/defaultOverlayUtils'
|
|
3
3
|
import { CollaboratorScribbleOverlayUtil } from '../../lib/overlays/CollaboratorScribbleOverlayUtil'
|
|
4
4
|
import { TestEditor } from '../TestEditor'
|
|
@@ -22,7 +22,7 @@ describe('CollaboratorScribbleOverlayUtil', () => {
|
|
|
22
22
|
editor.store.put([
|
|
23
23
|
InstancePresenceRecordType.create({
|
|
24
24
|
id: InstancePresenceRecordType.createId('peer1'),
|
|
25
|
-
userId: 'peer1',
|
|
25
|
+
userId: createUserId('peer1'),
|
|
26
26
|
userName: 'Peer 1',
|
|
27
27
|
currentPageId: pageId,
|
|
28
28
|
scribbles: [
|
|
@@ -58,7 +58,7 @@ describe('CollaboratorScribbleOverlayUtil', () => {
|
|
|
58
58
|
editor.store.put([
|
|
59
59
|
InstancePresenceRecordType.create({
|
|
60
60
|
id: InstancePresenceRecordType.createId('peer1'),
|
|
61
|
-
userId: 'peer1',
|
|
61
|
+
userId: createUserId('peer1'),
|
|
62
62
|
userName: 'Peer 1',
|
|
63
63
|
currentPageId: pageId,
|
|
64
64
|
color: '#00FF00',
|
|
@@ -101,7 +101,7 @@ describe('OverlayManager', () => {
|
|
|
101
101
|
it('hits the bounded edge handle hit area regardless of margin', () => {
|
|
102
102
|
editor.createShapes([{ id: ids.box1, type: 'geo', x: 0, y: 0, props: { w: 100, h: 100 } }])
|
|
103
103
|
editor.select(ids.box1)
|
|
104
|
-
// Edge handles are filled polygons of half-thickness
|
|
104
|
+
// Edge handles are filled polygons of half-thickness hitTargetSizeY (~4.5px at zoom 1);
|
|
105
105
|
// a point inside that band hits with margin 0, and a point outside misses.
|
|
106
106
|
const insideTopEdge = { x: 50, y: -3 }
|
|
107
107
|
const outsideTopEdge = { x: 50, y: -20 }
|
|
@@ -93,6 +93,22 @@ describe('SelectionForegroundOverlayUtil', () => {
|
|
|
93
93
|
expect(idsSet.has('selection_fg:bottom_right_rotate')).toBe(true)
|
|
94
94
|
})
|
|
95
95
|
|
|
96
|
+
it.each(['top_left', 'top', 'top_left_rotate'] as const)(
|
|
97
|
+
'keeps selection foreground overlays visible while pointing the %s handle',
|
|
98
|
+
(handle) => {
|
|
99
|
+
editor.updateInstanceState({ isCoarsePointer: false })
|
|
100
|
+
editor.createShapes([{ id: ids.box1, type: 'geo', x: 0, y: 0, props: { w: 100, h: 100 } }])
|
|
101
|
+
editor.select(ids.box1)
|
|
102
|
+
editor.pointerDown(0, 0, { target: 'selection', handle })
|
|
103
|
+
|
|
104
|
+
const overlays = editor.overlays.getCurrentOverlays()
|
|
105
|
+
const idsSet = new Set(overlays.map((o) => o.id))
|
|
106
|
+
expect(idsSet.has('selection_fg:top_left')).toBe(true)
|
|
107
|
+
expect(idsSet.has('selection_fg:top')).toBe(true)
|
|
108
|
+
expect(idsSet.has('selection_fg:top_left_rotate')).toBe(true)
|
|
109
|
+
}
|
|
110
|
+
)
|
|
111
|
+
|
|
96
112
|
it('includes mobile rotate handle for coarse pointer', () => {
|
|
97
113
|
editor.updateInstanceState({ isCoarsePointer: true })
|
|
98
114
|
editor.createShapes([{ id: ids.box1, type: 'geo', x: 0, y: 0, props: { w: 60, h: 60 } }])
|
|
@@ -189,6 +205,48 @@ describe('SelectionForegroundOverlayUtil', () => {
|
|
|
189
205
|
expect(idsSet.has('selection_fg:bottom_right')).toBe(true)
|
|
190
206
|
})
|
|
191
207
|
|
|
208
|
+
it('keeps resize handles while pressing a resize edge', () => {
|
|
209
|
+
editor.createShapes([{ id: ids.box1, type: 'geo', x: 0, y: 0, props: { w: 100, h: 100 } }])
|
|
210
|
+
editor.select(ids.box1)
|
|
211
|
+
editor.pointerDownOnHandle('top')
|
|
212
|
+
expect(editor.getPath()).toBe('select.pointing_resize_handle')
|
|
213
|
+
|
|
214
|
+
const util =
|
|
215
|
+
editor.overlays.getOverlayUtil<SelectionForegroundOverlayUtil>('selection_foreground')
|
|
216
|
+
const idsSet = new Set(util.getOverlays().map((o) => o.id))
|
|
217
|
+
expect(idsSet.has('selection_fg:top_left')).toBe(true)
|
|
218
|
+
expect(idsSet.has('selection_fg:top_right')).toBe(true)
|
|
219
|
+
expect(idsSet.has('selection_fg:bottom_left')).toBe(true)
|
|
220
|
+
expect(idsSet.has('selection_fg:bottom_right')).toBe(true)
|
|
221
|
+
|
|
222
|
+
// Once an actual resize begins, the handles hide
|
|
223
|
+
editor.pointerMoveBy(0, -30)
|
|
224
|
+
expect(editor.getPath()).toBe('select.resizing')
|
|
225
|
+
expect(util.getOverlays()).toEqual([])
|
|
226
|
+
})
|
|
227
|
+
|
|
228
|
+
it('keeps resize handles while pressing a rotate handle', () => {
|
|
229
|
+
editor.updateInstanceState({ isCoarsePointer: false })
|
|
230
|
+
editor.createShapes([{ id: ids.box1, type: 'geo', x: 0, y: 0, props: { w: 100, h: 100 } }])
|
|
231
|
+
editor.select(ids.box1)
|
|
232
|
+
editor.pointerDownOnHandle('top_left_rotate')
|
|
233
|
+
expect(editor.getPath()).toBe('select.pointing_rotate_handle')
|
|
234
|
+
|
|
235
|
+
const util =
|
|
236
|
+
editor.overlays.getOverlayUtil<SelectionForegroundOverlayUtil>('selection_foreground')
|
|
237
|
+
expect(util.isActive()).toBe(true)
|
|
238
|
+
const idsSet = new Set(util.getOverlays().map((o) => o.id))
|
|
239
|
+
expect(idsSet.has('selection_fg:top_left')).toBe(true)
|
|
240
|
+
expect(idsSet.has('selection_fg:top_right')).toBe(true)
|
|
241
|
+
expect(idsSet.has('selection_fg:bottom_left')).toBe(true)
|
|
242
|
+
expect(idsSet.has('selection_fg:bottom_right')).toBe(true)
|
|
243
|
+
|
|
244
|
+
// Once an actual rotation begins, the selection foreground hides
|
|
245
|
+
editor.pointerMoveBy(-30, -30)
|
|
246
|
+
expect(editor.getPath()).toBe('select.rotating')
|
|
247
|
+
expect(util.isActive()).toBe(false)
|
|
248
|
+
})
|
|
249
|
+
|
|
192
250
|
it('hides edge handles on coarse pointer', () => {
|
|
193
251
|
editor.updateInstanceState({ isCoarsePointer: true })
|
|
194
252
|
editor.createShapes([{ id: ids.box1, type: 'geo', x: 0, y: 0, props: { w: 100, h: 100 } }])
|
|
@@ -64,13 +64,13 @@ describe('ShapeHandleOverlayUtil', () => {
|
|
|
64
64
|
editor.pointerUp()
|
|
65
65
|
})
|
|
66
66
|
|
|
67
|
-
it('returns
|
|
67
|
+
it('returns false in select.pointing_shape with a handle shape selected', () => {
|
|
68
68
|
editor.createShapes([{ id: ids.line1, type: 'line', x: 120, y: 120 }])
|
|
69
69
|
const shape = editor.getShape(ids.line1)!
|
|
70
70
|
editor.pointerDown(shape.x + 1, shape.y + 1, { target: 'shape', shape })
|
|
71
71
|
editor.expectToBeIn('select.pointing_shape')
|
|
72
72
|
const util = editor.overlays.getOverlayUtil<ShapeHandleOverlayUtil>('shape_handle')
|
|
73
|
-
expect(util.isActive()).toBe(
|
|
73
|
+
expect(util.isActive()).toBe(false)
|
|
74
74
|
editor.pointerUp()
|
|
75
75
|
})
|
|
76
76
|
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { createShapeId } from '@tldraw/editor'
|
|
2
|
+
import { defaultOverlayUtils } from '../../lib/defaultOverlayUtils'
|
|
3
|
+
import { ShapeIndicatorOverlayUtil } from '../../lib/overlays/ShapeIndicatorOverlayUtil'
|
|
4
|
+
import { TestEditor } from '../TestEditor'
|
|
5
|
+
|
|
6
|
+
let editor: TestEditor
|
|
7
|
+
|
|
8
|
+
const ids = {
|
|
9
|
+
box1: createShapeId('box1'),
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
beforeEach(() => {
|
|
13
|
+
editor = new TestEditor({ overlayUtils: defaultOverlayUtils })
|
|
14
|
+
})
|
|
15
|
+
|
|
16
|
+
describe('ShapeIndicatorOverlayUtil', () => {
|
|
17
|
+
describe('getOverlays', () => {
|
|
18
|
+
it.each(['top_left', 'top_left_rotate'] as const)(
|
|
19
|
+
'keeps selected shape indicators visible while pointing the %s selection handle',
|
|
20
|
+
(handle) => {
|
|
21
|
+
editor.createShapes([{ id: ids.box1, type: 'geo', x: 0, y: 0, props: { w: 100, h: 100 } }])
|
|
22
|
+
editor.select(ids.box1)
|
|
23
|
+
editor.pointerDown(0, 0, { target: 'selection', handle })
|
|
24
|
+
|
|
25
|
+
const util = editor.overlays.getOverlayUtil<ShapeIndicatorOverlayUtil>('shape_indicator')
|
|
26
|
+
expect(util.getOverlays()).toMatchObject([
|
|
27
|
+
{
|
|
28
|
+
id: 'shape_indicator',
|
|
29
|
+
type: 'shape_indicator',
|
|
30
|
+
props: { idsToDisplay: [ids.box1] },
|
|
31
|
+
},
|
|
32
|
+
])
|
|
33
|
+
}
|
|
34
|
+
)
|
|
35
|
+
})
|
|
36
|
+
})
|