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
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import {
|
|
2
2
|
Mat,
|
|
3
3
|
StateNode,
|
|
4
|
+
DIM_2D,
|
|
4
5
|
Vec,
|
|
5
6
|
b64Vecs,
|
|
6
7
|
createShapeId,
|
|
@@ -21,6 +22,10 @@ class Drawing extends StateNode {
|
|
|
21
22
|
util = this.editor.getShapeUtil(this.shapeType);
|
|
22
23
|
isPen = false;
|
|
23
24
|
isPenOrStylus = false;
|
|
25
|
+
// Encoding dimension for segments created during this stroke. `2` drops the
|
|
26
|
+
// constant pressure value (non-pressure devices), `undefined` keeps full 3D.
|
|
27
|
+
// Decided once in startShape from the input device — see the note there.
|
|
28
|
+
segmentDim = void 0;
|
|
24
29
|
segmentMode = "free";
|
|
25
30
|
didJustShiftClickToExtendPreviousShapeLine = false;
|
|
26
31
|
pagePointWhereCurrentSegmentChanged = {};
|
|
@@ -108,9 +113,9 @@ class Drawing extends StateNode {
|
|
|
108
113
|
const theme = this.editor.getCurrentTheme();
|
|
109
114
|
strokeWidth = theme.strokeWidth * STROKE_SIZES[size];
|
|
110
115
|
}
|
|
111
|
-
const firstPoint = b64Vecs.decodeFirstPoint(segments[0].path);
|
|
116
|
+
const firstPoint = b64Vecs.decodeFirstPoint(segments[0].path, segments[0].dim);
|
|
112
117
|
const lastSegment = segments[segments.length - 1];
|
|
113
|
-
const lastPoint = b64Vecs.decodeLastPoint(lastSegment.path);
|
|
118
|
+
const lastPoint = b64Vecs.decodeLastPoint(lastSegment.path, lastSegment.dim);
|
|
114
119
|
const isDynamicResizingEnabled = this.editor.user.getIsDynamicResizeMode();
|
|
115
120
|
const threshold = isDynamicResizingEnabled ? (strokeWidth + 2) * scale : (
|
|
116
121
|
// 6 is a base floor, 2 is stroke influence, 0.8 tempers width growth
|
|
@@ -119,6 +124,15 @@ class Drawing extends StateNode {
|
|
|
119
124
|
);
|
|
120
125
|
return firstPoint !== null && lastPoint !== null && firstPoint !== lastPoint && this.currentLineLength > strokeWidth * 4 * scale && Vec.DistMin(firstPoint, lastPoint, threshold);
|
|
121
126
|
}
|
|
127
|
+
/**
|
|
128
|
+
* Build a segment from points, encoding `path` at this stroke's `segmentDim` and
|
|
129
|
+
* attaching `dim: 2` only when z was dropped. 3D segments omit `dim` so they
|
|
130
|
+
* serialize byte-identically to pre-#8879 data.
|
|
131
|
+
*/
|
|
132
|
+
makeSegment(type, points) {
|
|
133
|
+
const path = b64Vecs.encodePoints(points, this.segmentDim);
|
|
134
|
+
return this.segmentDim === DIM_2D ? { type, path, dim: DIM_2D } : { type, path };
|
|
135
|
+
}
|
|
122
136
|
startShape() {
|
|
123
137
|
const inputs = this.editor.inputs;
|
|
124
138
|
const originPagePoint = inputs.getOriginPagePoint();
|
|
@@ -127,6 +141,7 @@ class Drawing extends StateNode {
|
|
|
127
141
|
const { z = 0.5 } = this.info.point;
|
|
128
142
|
this.isPen = isPen;
|
|
129
143
|
this.isPenOrStylus = isPen && z !== 0 || z > 0 && z < 0.5 || z > 0.5 && z < 1;
|
|
144
|
+
this.segmentDim = this.isPenOrStylus ? void 0 : DIM_2D;
|
|
130
145
|
const pressure = this.isPenOrStylus ? z * 1.25 : 0.5;
|
|
131
146
|
this.segmentMode = this.editor.inputs.getShiftKey() ? "straight" : "free";
|
|
132
147
|
this.didJustShiftClickToExtendPreviousShapeLine = false;
|
|
@@ -137,16 +152,13 @@ class Drawing extends StateNode {
|
|
|
137
152
|
this.didJustShiftClickToExtendPreviousShapeLine = true;
|
|
138
153
|
const prevSegment = last(shape2.props.segments);
|
|
139
154
|
if (!prevSegment) throw Error("Expected a previous segment!");
|
|
140
|
-
const prevPoint = b64Vecs.decodeLastPoint(prevSegment.path);
|
|
155
|
+
const prevPoint = b64Vecs.decodeLastPoint(prevSegment.path, prevSegment.dim);
|
|
141
156
|
if (!prevPoint) throw Error("Expected a previous point!");
|
|
142
157
|
const { x, y } = this.editor.getPointInShapeSpace(shape2, originPagePoint).toFixed();
|
|
143
|
-
const newSegment =
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
{ x, y, z: +pressure.toFixed(2) }
|
|
148
|
-
])
|
|
149
|
-
};
|
|
158
|
+
const newSegment = this.makeSegment(this.segmentMode, [
|
|
159
|
+
{ x: prevPoint.x, y: prevPoint.y, z: +pressure.toFixed(2) },
|
|
160
|
+
{ x, y, z: +pressure.toFixed(2) }
|
|
161
|
+
]);
|
|
150
162
|
const prevPointPageSpace = Mat.applyToPoint(
|
|
151
163
|
this.editor.getShapePageTransform(shape2.id),
|
|
152
164
|
prevPoint
|
|
@@ -189,12 +201,7 @@ class Drawing extends StateNode {
|
|
|
189
201
|
props: {
|
|
190
202
|
isPen: this.isPenOrStylus,
|
|
191
203
|
scale: this.editor.getResizeScaleFactor(),
|
|
192
|
-
segments: [
|
|
193
|
-
{
|
|
194
|
-
type: this.segmentMode,
|
|
195
|
-
path: b64Vecs.encodePoints([initialPoint])
|
|
196
|
-
}
|
|
197
|
-
]
|
|
204
|
+
segments: [this.makeSegment(this.segmentMode, [initialPoint])]
|
|
198
205
|
}
|
|
199
206
|
});
|
|
200
207
|
const shape = this.editor.getShape(id);
|
|
@@ -233,23 +240,17 @@ class Drawing extends StateNode {
|
|
|
233
240
|
this.segmentMode = "straight";
|
|
234
241
|
const prevSegment = last(segments);
|
|
235
242
|
if (!prevSegment) throw Error("Expected a previous segment!");
|
|
236
|
-
const prevLastPoint = b64Vecs.decodeLastPoint(prevSegment.path);
|
|
243
|
+
const prevLastPoint = b64Vecs.decodeLastPoint(prevSegment.path, prevSegment.dim);
|
|
237
244
|
if (!prevLastPoint) throw Error("Expected a previous last point!");
|
|
238
245
|
let newSegment;
|
|
239
246
|
const newLastPoint = this.editor.getPointInShapeSpace(shape, this.pagePointWhereCurrentSegmentChanged).toFixed().toJson();
|
|
240
247
|
if (prevSegment.type === "straight") {
|
|
241
248
|
this.currentLineLength += Vec.Dist(prevLastPoint, newLastPoint);
|
|
242
|
-
newSegment =
|
|
243
|
-
type: "straight",
|
|
244
|
-
path: b64Vecs.encodePoints([prevLastPoint, newLastPoint])
|
|
245
|
-
};
|
|
249
|
+
newSegment = this.makeSegment("straight", [prevLastPoint, newLastPoint]);
|
|
246
250
|
const transform = this.editor.getShapePageTransform(shape);
|
|
247
251
|
this.pagePointWhereCurrentSegmentChanged = Mat.applyToPoint(transform, prevLastPoint);
|
|
248
252
|
} else {
|
|
249
|
-
newSegment =
|
|
250
|
-
type: "straight",
|
|
251
|
-
path: b64Vecs.encodePoints([newLastPoint, newPoint])
|
|
252
|
-
};
|
|
253
|
+
newSegment = this.makeSegment("straight", [newLastPoint, newPoint]);
|
|
253
254
|
}
|
|
254
255
|
const shapePartial = {
|
|
255
256
|
id,
|
|
@@ -282,7 +283,10 @@ class Drawing extends StateNode {
|
|
|
282
283
|
this.segmentMode = "free";
|
|
283
284
|
const newSegments = segments.slice();
|
|
284
285
|
const prevStraightSegment = newSegments[newSegments.length - 1];
|
|
285
|
-
const prevPoint = b64Vecs.decodeLastPoint(
|
|
286
|
+
const prevPoint = b64Vecs.decodeLastPoint(
|
|
287
|
+
prevStraightSegment.path,
|
|
288
|
+
prevStraightSegment.dim
|
|
289
|
+
);
|
|
286
290
|
if (!prevPoint) {
|
|
287
291
|
throw Error("No previous point!");
|
|
288
292
|
}
|
|
@@ -290,10 +294,7 @@ class Drawing extends StateNode {
|
|
|
290
294
|
(p) => new Vec(toFixed(p.x), toFixed(p.y), toFixed(p.z))
|
|
291
295
|
);
|
|
292
296
|
this.currentSegmentPoints = interpolatedPoints;
|
|
293
|
-
const newFreeSegment =
|
|
294
|
-
type: "free",
|
|
295
|
-
path: b64Vecs.encodePoints(interpolatedPoints)
|
|
296
|
-
};
|
|
297
|
+
const newFreeSegment = this.makeSegment("free", interpolatedPoints);
|
|
297
298
|
const finalSegments = [...newSegments, newFreeSegment];
|
|
298
299
|
const dvStrokeWidth = getDisplayValues(this.util, shape).strokeWidth;
|
|
299
300
|
if (this.currentLineLength < dvStrokeWidth * 4) {
|
|
@@ -350,8 +351,8 @@ class Drawing extends StateNode {
|
|
|
350
351
|
const segment = segments[i];
|
|
351
352
|
if (!segment) break;
|
|
352
353
|
if (segment.type === "free") continue;
|
|
353
|
-
const first = b64Vecs.decodeFirstPoint(segment.path);
|
|
354
|
-
const lastPoint = b64Vecs.decodeLastPoint(segment.path);
|
|
354
|
+
const first = b64Vecs.decodeFirstPoint(segment.path, segment.dim);
|
|
355
|
+
const lastPoint = b64Vecs.decodeLastPoint(segment.path, segment.dim);
|
|
355
356
|
if (!(first && lastPoint)) continue;
|
|
356
357
|
const nearestPointOnSegment = Vec.NearestPointOnLineSegment(
|
|
357
358
|
first,
|
|
@@ -373,8 +374,8 @@ class Drawing extends StateNode {
|
|
|
373
374
|
}
|
|
374
375
|
if (didSnap && snapSegment) {
|
|
375
376
|
const transform = this.editor.getShapePageTransform(shape);
|
|
376
|
-
const first = b64Vecs.decodeFirstPoint(snapSegment.path);
|
|
377
|
-
const lastPoint = b64Vecs.decodeLastPoint(snapSegment.path);
|
|
377
|
+
const first = b64Vecs.decodeFirstPoint(snapSegment.path, snapSegment.dim);
|
|
378
|
+
const lastPoint = b64Vecs.decodeLastPoint(snapSegment.path, snapSegment.dim);
|
|
378
379
|
if (!first || !lastPoint) throw Error("Expected a last point!");
|
|
379
380
|
const A = Mat.applyToPoint(transform, first);
|
|
380
381
|
const B = Mat.applyToPoint(transform, lastPoint);
|
|
@@ -402,14 +403,17 @@ class Drawing extends StateNode {
|
|
|
402
403
|
}
|
|
403
404
|
newPoint2 = this.editor.getPointInShapeSpace(shape, pagePoint).toFixed().toJson();
|
|
404
405
|
}
|
|
405
|
-
this.currentLineLength += newSegments.length && b64Vecs.decodeFirstPoint(newSegment.path) ? Vec.Dist(
|
|
406
|
+
this.currentLineLength += newSegments.length && b64Vecs.decodeFirstPoint(newSegment.path, newSegment.dim) ? Vec.Dist(
|
|
407
|
+
b64Vecs.decodeFirstPoint(newSegment.path, newSegment.dim),
|
|
408
|
+
Vec.From(newPoint2)
|
|
409
|
+
) : 0;
|
|
406
410
|
newSegments[newSegments.length - 1] = {
|
|
407
411
|
...newSegment,
|
|
408
412
|
type: "straight",
|
|
409
|
-
path: b64Vecs.encodePoints(
|
|
410
|
-
b64Vecs.decodeFirstPoint(newSegment.path),
|
|
411
|
-
|
|
412
|
-
|
|
413
|
+
path: b64Vecs.encodePoints(
|
|
414
|
+
[b64Vecs.decodeFirstPoint(newSegment.path, newSegment.dim), Vec.From(newPoint2)],
|
|
415
|
+
newSegment.dim
|
|
416
|
+
)
|
|
413
417
|
};
|
|
414
418
|
const shapePartial = {
|
|
415
419
|
id,
|
|
@@ -444,7 +448,7 @@ class Drawing extends StateNode {
|
|
|
444
448
|
const newSegment = newSegments[newSegments.length - 1];
|
|
445
449
|
newSegments[newSegments.length - 1] = {
|
|
446
450
|
...newSegment,
|
|
447
|
-
path: b64Vecs.encodePoints(cachedPoints)
|
|
451
|
+
path: b64Vecs.encodePoints(cachedPoints, newSegment.dim)
|
|
448
452
|
};
|
|
449
453
|
const dvStrokeWidth = getDisplayValues(this.util, shape).strokeWidth;
|
|
450
454
|
if (this.currentLineLength < dvStrokeWidth * 4) {
|
|
@@ -482,12 +486,7 @@ class Drawing extends StateNode {
|
|
|
482
486
|
props: {
|
|
483
487
|
isPen: this.isPenOrStylus,
|
|
484
488
|
scale: props.scale,
|
|
485
|
-
segments: [
|
|
486
|
-
{
|
|
487
|
-
type: "free",
|
|
488
|
-
path: b64Vecs.encodePoints([initialPoint])
|
|
489
|
-
}
|
|
490
|
-
]
|
|
489
|
+
segments: [this.makeSegment("free", [initialPoint])]
|
|
491
490
|
}
|
|
492
491
|
});
|
|
493
492
|
const shape2 = this.editor.getShape(newShapeId);
|
|
@@ -506,7 +505,7 @@ class Drawing extends StateNode {
|
|
|
506
505
|
getLineLength(segments) {
|
|
507
506
|
let length = 0;
|
|
508
507
|
for (let j = 0; j < segments.length; j++) {
|
|
509
|
-
const points = b64Vecs.decodePoints(segments[j].path);
|
|
508
|
+
const points = b64Vecs.decodePoints(segments[j].path, segments[j].dim);
|
|
510
509
|
for (let i = 0; i < points.length - 1; i++) {
|
|
511
510
|
length += Vec.Dist2(points[i], points[i + 1]);
|
|
512
511
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../../../src/lib/shapes/draw/toolStates/Drawing.ts"],
|
|
4
|
-
"sourcesContent": ["import {\n\tMat,\n\tStateNode,\n\tTLDefaultSizeStyle,\n\tTLDrawShape,\n\tTLDrawShapeSegment,\n\tTLHighlightShape,\n\tTLKeyboardEventInfo,\n\tTLPointerEventInfo,\n\tTLShapePartial,\n\tVec,\n\tVecModel,\n\tb64Vecs,\n\tcreateShapeId,\n\tlast,\n\tsnapAngle,\n\tstructuredClone,\n\ttoFixed,\n\tuniqueId,\n} from '@tldraw/editor'\nimport { HighlightShapeUtil } from '../../highlight/HighlightShapeUtil'\nimport { STROKE_SIZES } from '../../shared/default-shape-constants'\nimport { getDisplayValues } from '../../shared/getDisplayValues'\nimport { DrawShapeUtil } from '../DrawShapeUtil'\n\ntype DrawableShape = TLDrawShape | TLHighlightShape\n\nexport class Drawing extends StateNode {\n\tstatic override id = 'drawing'\n\tstatic override trackPerformance = true\n\n\tinfo = {} as TLPointerEventInfo\n\n\tinitialShape?: DrawableShape\n\n\toverride shapeType = this.parent.id === 'highlight' ? ('highlight' as const) : ('draw' as const)\n\n\tutil = this.editor.getShapeUtil(this.shapeType) as DrawShapeUtil | HighlightShapeUtil\n\n\tisPen = false\n\tisPenOrStylus = false\n\n\tsegmentMode = 'free' as 'free' | 'straight' | 'starting_straight' | 'starting_free'\n\n\tdidJustShiftClickToExtendPreviousShapeLine = false\n\n\tpagePointWhereCurrentSegmentChanged = {} as Vec\n\n\tpagePointWhereNextSegmentChanged = null as Vec | null\n\n\tlastRecordedPoint = {} as Vec\n\tmergeNextPoint = false\n\tcurrentLineLength = 0\n\tzoomOnEnter = 1\n\n\t// Cache for current segment's points to avoid repeated b64 decode/encode\n\tcurrentSegmentPoints: Vec[] = []\n\n\tmarkId = null as null | string\n\n\toverride onEnter(info: TLPointerEventInfo) {\n\t\tthis.markId = null\n\t\tthis.info = info\n\t\tthis.lastRecordedPoint = this.editor.inputs.getCurrentPagePoint().clone()\n\t\tthis.zoomOnEnter = this.editor.getZoomLevel()\n\t\tthis.startShape()\n\t}\n\n\toverride onPointerMove() {\n\t\tconst { inputs } = this.editor\n\t\tconst isPen = inputs.getIsPen()\n\n\t\tif (this.isPen && !isPen) {\n\t\t\t// The user made a palm gesture before starting a pen gesture;\n\t\t\t// ideally we'd start the new shape here but we could also just bail\n\t\t\t// as the next interaction will work correctly\n\t\t\tif (this.markId) {\n\t\t\t\tthis.editor.bailToMark(this.markId)\n\t\t\t\tthis.startShape()\n\t\t\t\treturn\n\t\t\t}\n\t\t}\n\n\t\tif (this.isPenOrStylus) {\n\t\t\t// Don't update the shape if we haven't moved far enough from the last time we recorded a point\n\t\t\tconst currentPagePoint = inputs.getCurrentPagePoint()\n\t\t\tif (Vec.Dist(currentPagePoint, this.lastRecordedPoint) >= 1 / this.zoomOnEnter) {\n\t\t\t\tthis.lastRecordedPoint = currentPagePoint.clone()\n\t\t\t\tthis.mergeNextPoint = false\n\t\t\t} else {\n\t\t\t\tthis.mergeNextPoint = true\n\t\t\t}\n\t\t} else {\n\t\t\tthis.mergeNextPoint = false\n\t\t}\n\n\t\tthis.updateDrawingShape()\n\t}\n\n\toverride onKeyDown(info: TLKeyboardEventInfo) {\n\t\tif (info.key === 'Shift') {\n\t\t\tswitch (this.segmentMode) {\n\t\t\t\tcase 'free': {\n\t\t\t\t\t// We've just entered straight mode, go to straight mode\n\t\t\t\t\tthis.segmentMode = 'starting_straight'\n\t\t\t\t\tthis.pagePointWhereNextSegmentChanged = this.editor.inputs.getCurrentPagePoint().clone()\n\t\t\t\t\tbreak\n\t\t\t\t}\n\t\t\t\tcase 'starting_free': {\n\t\t\t\t\tthis.segmentMode = 'starting_straight'\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tthis.updateDrawingShape()\n\t}\n\n\toverride onKeyUp(info: TLKeyboardEventInfo) {\n\t\tif (info.key === 'Shift') {\n\t\t\tthis.editor.snaps.clearIndicators()\n\n\t\t\tswitch (this.segmentMode) {\n\t\t\t\tcase 'straight': {\n\t\t\t\t\t// We've just exited straight mode, go back to free mode\n\t\t\t\t\tthis.segmentMode = 'starting_free'\n\t\t\t\t\tthis.pagePointWhereNextSegmentChanged = this.editor.inputs.getCurrentPagePoint().clone()\n\t\t\t\t\tbreak\n\t\t\t\t}\n\t\t\t\tcase 'starting_straight': {\n\t\t\t\t\tthis.pagePointWhereNextSegmentChanged = null\n\t\t\t\t\tthis.segmentMode = 'free'\n\t\t\t\t\tbreak\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tthis.updateDrawingShape()\n\t}\n\n\toverride onExit() {\n\t\tthis.editor.snaps.clearIndicators()\n\t\tthis.pagePointWhereCurrentSegmentChanged = this.editor.inputs.getCurrentPagePoint().clone()\n\t}\n\n\tcanClose() {\n\t\treturn this.shapeType !== 'highlight'\n\t}\n\n\tgetIsClosed(\n\t\tsegments: TLDrawShapeSegment[],\n\t\tsize: TLDefaultSizeStyle,\n\t\tscale: number,\n\t\tstrokeWidth?: number\n\t) {\n\t\tif (!this.canClose()) return false\n\n\t\tif (strokeWidth === undefined) {\n\t\t\tconst theme = this.editor.getCurrentTheme()\n\t\t\tstrokeWidth = theme.strokeWidth * STROKE_SIZES[size]\n\t\t}\n\t\tconst firstPoint = b64Vecs.decodeFirstPoint(segments[0].path)\n\t\tconst lastSegment = segments[segments.length - 1]\n\t\tconst lastPoint = b64Vecs.decodeLastPoint(lastSegment.path)\n\n\t\tconst isDynamicResizingEnabled = this.editor.user.getIsDynamicResizeMode()\n\n\t\tconst threshold = isDynamicResizingEnabled // when dynamic resizing is enabled scale is 1/zoom, so the threshold should not scale directly with zoom at all\n\t\t\t? (strokeWidth + 2) * scale // +2 keeps tiny strokes from being too hard to close\n\t\t\t: // 6 is a base floor, 2 is stroke influence, 0.8 tempers width growth\n\t\t\t\t6 +\n\t\t\t\t2 * Math.sqrt(strokeWidth * 0.8) +\n\t\t\t\t// 100 is low-zoom boost, 0.18 is the zoom knee, 3 controls falloff steepness\n\t\t\t\t100 / (1 + Math.pow(this.zoomOnEnter / 0.18, 3))\n\n\t\treturn (\n\t\t\tfirstPoint !== null &&\n\t\t\tlastPoint !== null &&\n\t\t\tfirstPoint !== lastPoint &&\n\t\t\tthis.currentLineLength > strokeWidth * 4 * scale &&\n\t\t\tVec.DistMin(firstPoint, lastPoint, threshold)\n\t\t)\n\t}\n\n\tprivate startShape() {\n\t\tconst inputs = this.editor.inputs\n\t\tconst originPagePoint = inputs.getOriginPagePoint()\n\t\tconst isPen = inputs.getIsPen()\n\n\t\tthis.markId = this.editor.markHistoryStoppingPoint('draw start')\n\n\t\t// If the pressure is weird, then it's probably a stylus reporting as a mouse\n\t\t// We treat pen/stylus inputs differently in the drawing tool, so we need to\n\t\t// have our own value for this. The inputs.isPen is only if the input is a regular\n\t\t// pen, like an iPad pen, which needs to trigger \"pen mode\" in order to avoid\n\t\t// accidental palm touches. We don't have to worry about that with styluses though.\n\t\tconst { z = 0.5 } = this.info.point\n\n\t\tthis.isPen = isPen\n\t\t// if z === 0 on the initial point, treat this pen as a mouse because it's likely a broken pen\n\t\t// or a broken OS.\n\t\tthis.isPenOrStylus = (isPen && z !== 0) || (z > 0 && z < 0.5) || (z > 0.5 && z < 1)\n\n\t\tconst pressure = this.isPenOrStylus ? z * 1.25 : 0.5\n\n\t\tthis.segmentMode = this.editor.inputs.getShiftKey() ? 'straight' : 'free'\n\n\t\tthis.didJustShiftClickToExtendPreviousShapeLine = false\n\n\t\tthis.lastRecordedPoint = originPagePoint.clone()\n\n\t\tif (this.initialShape) {\n\t\t\tconst shape = this.editor.getShape<DrawableShape>(this.initialShape.id)\n\n\t\t\tif (shape && this.segmentMode === 'straight') {\n\t\t\t\t// Connect dots\n\n\t\t\t\tthis.didJustShiftClickToExtendPreviousShapeLine = true\n\n\t\t\t\tconst prevSegment = last(shape.props.segments)\n\t\t\t\tif (!prevSegment) throw Error('Expected a previous segment!')\n\t\t\t\tconst prevPoint = b64Vecs.decodeLastPoint(prevSegment.path)\n\t\t\t\tif (!prevPoint) throw Error('Expected a previous point!')\n\n\t\t\t\tconst { x, y } = this.editor.getPointInShapeSpace(shape, originPagePoint).toFixed()\n\n\t\t\t\tconst newSegment: TLDrawShapeSegment = {\n\t\t\t\t\ttype: this.segmentMode,\n\t\t\t\t\tpath: b64Vecs.encodePoints([\n\t\t\t\t\t\t{ x: prevPoint.x, y: prevPoint.y, z: +pressure.toFixed(2) },\n\t\t\t\t\t\t{ x, y, z: +pressure.toFixed(2) },\n\t\t\t\t\t]),\n\t\t\t\t}\n\n\t\t\t\t// Convert prevPoint to page space\n\t\t\t\tconst prevPointPageSpace = Mat.applyToPoint(\n\t\t\t\t\tthis.editor.getShapePageTransform(shape.id)!,\n\t\t\t\t\tprevPoint\n\t\t\t\t)\n\t\t\t\tthis.pagePointWhereCurrentSegmentChanged = prevPointPageSpace\n\t\t\t\tthis.pagePointWhereNextSegmentChanged = null\n\t\t\t\tconst segments = [...shape.props.segments, newSegment]\n\n\t\t\t\tconst dvStrokeWidth = (getDisplayValues(this.util as any, shape) as { strokeWidth: number })\n\t\t\t\t\t.strokeWidth\n\t\t\t\tif (this.currentLineLength < dvStrokeWidth * 4) {\n\t\t\t\t\tthis.currentLineLength = this.getLineLength(segments)\n\t\t\t\t}\n\n\t\t\t\tconst shapePartial: TLShapePartial<DrawableShape> = {\n\t\t\t\t\tid: shape.id,\n\t\t\t\t\ttype: this.shapeType,\n\t\t\t\t\tprops: {\n\t\t\t\t\t\tsegments,\n\t\t\t\t\t},\n\t\t\t\t}\n\n\t\t\t\tif (this.canClose()) {\n\t\t\t\t\t;(shapePartial as TLShapePartial<TLDrawShape>).props!.isClosed = this.getIsClosed(\n\t\t\t\t\t\tsegments,\n\t\t\t\t\t\tshape.props.size,\n\t\t\t\t\t\tshape.props.scale\n\t\t\t\t\t)\n\t\t\t\t}\n\n\t\t\t\tthis.editor.updateShapes([shapePartial])\n\n\t\t\t\treturn\n\t\t\t}\n\t\t}\n\n\t\t// Create a new shape\n\n\t\tthis.pagePointWhereCurrentSegmentChanged = originPagePoint.clone()\n\t\tconst id = createShapeId()\n\n\t\t// Initialize the segment points cache\n\t\tconst initialPoint = new Vec(0, 0, +pressure.toFixed(2))\n\t\tthis.currentSegmentPoints = [initialPoint]\n\n\t\t// Allow this to trigger the max shapes reached alert\n\t\tthis.editor.createShape({\n\t\t\tid,\n\t\t\ttype: this.shapeType,\n\t\t\tx: originPagePoint.x,\n\t\t\ty: originPagePoint.y,\n\t\t\tprops: {\n\t\t\t\tisPen: this.isPenOrStylus,\n\t\t\t\tscale: this.editor.getResizeScaleFactor(),\n\t\t\t\tsegments: [\n\t\t\t\t\t{\n\t\t\t\t\t\ttype: this.segmentMode,\n\t\t\t\t\t\tpath: b64Vecs.encodePoints([initialPoint]),\n\t\t\t\t\t},\n\t\t\t\t],\n\t\t\t},\n\t\t})\n\t\tconst shape = this.editor.getShape<DrawableShape>(id)\n\t\tif (!shape) {\n\t\t\tthis.cancel()\n\t\t\treturn\n\t\t}\n\t\tthis.currentLineLength = 0\n\t\tthis.initialShape = this.editor.getShape<DrawableShape>(id)\n\t}\n\n\tprivate updateDrawingShape() {\n\t\tconst { initialShape } = this\n\t\tconst { inputs } = this.editor\n\n\t\tif (!initialShape) return\n\n\t\tconst {\n\t\t\tid,\n\t\t\tprops: { size, scale },\n\t\t} = initialShape\n\n\t\tconst shape = this.editor.getShape<DrawableShape>(id)!\n\n\t\tif (!shape) return\n\n\t\tconst { segments } = shape.props\n\n\t\tconst currentPagePoint = inputs.getCurrentPagePoint()\n\t\tconst { x, y, z } = this.editor.getPointInShapeSpace(shape, currentPagePoint).toFixed()\n\t\tconst pressure = this.isPenOrStylus ? +(currentPagePoint.z! * 1.25).toFixed(2) : 0.5\n\t\tconst newPoint = { x, y, z: pressure }\n\n\t\tswitch (this.segmentMode) {\n\t\t\tcase 'starting_straight': {\n\t\t\t\tconst { pagePointWhereNextSegmentChanged } = this\n\n\t\t\t\tif (pagePointWhereNextSegmentChanged === null) {\n\t\t\t\t\tthrow Error('We should have a point where the segment changed')\n\t\t\t\t}\n\n\t\t\t\tconst hasMovedFarEnough =\n\t\t\t\t\tVec.Dist2(pagePointWhereNextSegmentChanged, inputs.getCurrentPagePoint()) >\n\t\t\t\t\tthis.editor.options.dragDistanceSquared\n\n\t\t\t\t// Find the distance from where the pointer was when shift was released and\n\t\t\t\t// where it is now; if it's far enough away, then update the page point where\n\t\t\t\t// the current segment changed (to match the pagepoint where next segment changed)\n\t\t\t\t// and set the pagepoint where next segment changed to null.\n\t\t\t\tif (hasMovedFarEnough) {\n\t\t\t\t\tthis.pagePointWhereCurrentSegmentChanged = this.pagePointWhereNextSegmentChanged!.clone()\n\t\t\t\t\tthis.pagePointWhereNextSegmentChanged = null\n\n\t\t\t\t\t// Set the new mode\n\t\t\t\t\tthis.segmentMode = 'straight'\n\n\t\t\t\t\tconst prevSegment = last(segments)\n\t\t\t\t\tif (!prevSegment) throw Error('Expected a previous segment!')\n\n\t\t\t\t\tconst prevLastPoint = b64Vecs.decodeLastPoint(prevSegment.path)\n\t\t\t\t\tif (!prevLastPoint) throw Error('Expected a previous last point!')\n\n\t\t\t\t\tlet newSegment: TLDrawShapeSegment\n\n\t\t\t\t\tconst newLastPoint = this.editor\n\t\t\t\t\t\t.getPointInShapeSpace(shape, this.pagePointWhereCurrentSegmentChanged)\n\t\t\t\t\t\t.toFixed()\n\t\t\t\t\t\t.toJson()\n\n\t\t\t\t\tif (prevSegment.type === 'straight') {\n\t\t\t\t\t\tthis.currentLineLength += Vec.Dist(prevLastPoint, newLastPoint)\n\n\t\t\t\t\t\tnewSegment = {\n\t\t\t\t\t\t\ttype: 'straight',\n\t\t\t\t\t\t\tpath: b64Vecs.encodePoints([prevLastPoint, newLastPoint]),\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tconst transform = this.editor.getShapePageTransform(shape)!\n\n\t\t\t\t\t\tthis.pagePointWhereCurrentSegmentChanged = Mat.applyToPoint(transform, prevLastPoint)\n\t\t\t\t\t} else {\n\t\t\t\t\t\tnewSegment = {\n\t\t\t\t\t\t\ttype: 'straight',\n\t\t\t\t\t\t\tpath: b64Vecs.encodePoints([newLastPoint, newPoint]),\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\tconst shapePartial: TLShapePartial<DrawableShape> = {\n\t\t\t\t\t\tid,\n\t\t\t\t\t\ttype: this.shapeType,\n\t\t\t\t\t\tprops: {\n\t\t\t\t\t\t\tsegments: [...segments, newSegment],\n\t\t\t\t\t\t},\n\t\t\t\t\t}\n\n\t\t\t\t\tif (this.canClose()) {\n\t\t\t\t\t\t;(shapePartial as TLShapePartial<TLDrawShape>).props!.isClosed = this.getIsClosed(\n\t\t\t\t\t\t\tsegments,\n\t\t\t\t\t\t\tsize,\n\t\t\t\t\t\t\tscale\n\t\t\t\t\t\t)\n\t\t\t\t\t}\n\n\t\t\t\t\tthis.editor.updateShapes([shapePartial])\n\t\t\t\t}\n\t\t\t\tbreak\n\t\t\t}\n\t\t\tcase 'starting_free': {\n\t\t\t\tconst { pagePointWhereNextSegmentChanged } = this\n\n\t\t\t\tif (pagePointWhereNextSegmentChanged === null) {\n\t\t\t\t\tthrow Error('We should have a point where the segment changed')\n\t\t\t\t}\n\n\t\t\t\tconst hasMovedFarEnough =\n\t\t\t\t\tVec.Dist2(pagePointWhereNextSegmentChanged, inputs.getCurrentPagePoint()) >\n\t\t\t\t\tthis.editor.options.dragDistanceSquared\n\n\t\t\t\t// Find the distance from where the pointer was when shift was released and\n\t\t\t\t// where it is now; if it's far enough away, then update the page point where\n\t\t\t\t// the current segment changed (to match the pagepoint where next segment changed)\n\t\t\t\t// and set the pagepoint where next segment changed to null.\n\t\t\t\tif (hasMovedFarEnough) {\n\t\t\t\t\tthis.pagePointWhereCurrentSegmentChanged = this.pagePointWhereNextSegmentChanged!.clone()\n\t\t\t\t\tthis.pagePointWhereNextSegmentChanged = null\n\n\t\t\t\t\t// Set the new mode\n\t\t\t\t\tthis.segmentMode = 'free'\n\n\t\t\t\t\tconst newSegments = segments.slice()\n\t\t\t\t\tconst prevStraightSegment = newSegments[newSegments.length - 1]\n\t\t\t\t\tconst prevPoint = b64Vecs.decodeLastPoint(prevStraightSegment.path)\n\n\t\t\t\t\tif (!prevPoint) {\n\t\t\t\t\t\tthrow Error('No previous point!')\n\t\t\t\t\t}\n\n\t\t\t\t\t// Create the new free segment and interpolate the points between where the last line\n\t\t\t\t\t// ended and where the pointer is now\n\t\t\t\t\tconst interpolatedPoints = Vec.PointsBetween(prevPoint, newPoint, 6).map(\n\t\t\t\t\t\t(p) => new Vec(toFixed(p.x), toFixed(p.y), toFixed(p.z))\n\t\t\t\t\t)\n\t\t\t\t\t// Initialize cache for the new free segment\n\t\t\t\t\tthis.currentSegmentPoints = interpolatedPoints\n\n\t\t\t\t\tconst newFreeSegment: TLDrawShapeSegment = {\n\t\t\t\t\t\ttype: 'free',\n\t\t\t\t\t\tpath: b64Vecs.encodePoints(interpolatedPoints),\n\t\t\t\t\t}\n\n\t\t\t\t\tconst finalSegments = [...newSegments, newFreeSegment]\n\n\t\t\t\t\tconst dvStrokeWidth = (\n\t\t\t\t\t\tgetDisplayValues(this.util as any, shape) as { strokeWidth: number }\n\t\t\t\t\t).strokeWidth\n\t\t\t\t\tif (this.currentLineLength < dvStrokeWidth * 4) {\n\t\t\t\t\t\tthis.currentLineLength = this.getLineLength(finalSegments)\n\t\t\t\t\t}\n\n\t\t\t\t\tconst shapePartial: TLShapePartial<DrawableShape> = {\n\t\t\t\t\t\tid,\n\t\t\t\t\t\ttype: this.shapeType,\n\t\t\t\t\t\tprops: {\n\t\t\t\t\t\t\tsegments: finalSegments,\n\t\t\t\t\t\t},\n\t\t\t\t\t}\n\n\t\t\t\t\tif (this.canClose()) {\n\t\t\t\t\t\t;(shapePartial as TLShapePartial<TLDrawShape>).props!.isClosed = this.getIsClosed(\n\t\t\t\t\t\t\tfinalSegments,\n\t\t\t\t\t\t\tsize,\n\t\t\t\t\t\t\tscale\n\t\t\t\t\t\t)\n\t\t\t\t\t}\n\n\t\t\t\t\tthis.editor.updateShapes([shapePartial])\n\t\t\t\t}\n\n\t\t\t\tbreak\n\t\t\t}\n\t\t\tcase 'straight': {\n\t\t\t\tconst newSegments = segments.slice()\n\t\t\t\tconst newSegment = newSegments[newSegments.length - 1]\n\n\t\t\t\tconst { pagePointWhereCurrentSegmentChanged } = this\n\t\t\t\tconst inputs = this.editor.inputs\n\t\t\t\tconst ctrlKey = inputs.getCtrlKey()\n\t\t\t\tconst currentPagePoint = inputs.getCurrentPagePoint()\n\n\t\t\t\tif (!pagePointWhereCurrentSegmentChanged)\n\t\t\t\t\tthrow Error('We should have a point where the segment changed')\n\n\t\t\t\tlet pagePoint: VecModel\n\t\t\t\tlet shouldSnapToAngle = false\n\n\t\t\t\tif (this.didJustShiftClickToExtendPreviousShapeLine) {\n\t\t\t\t\tif (this.editor.inputs.getIsDragging()) {\n\t\t\t\t\t\t// If we've just shift clicked to extend a line, only snap once we've started dragging\n\t\t\t\t\t\tshouldSnapToAngle = !ctrlKey\n\t\t\t\t\t\tthis.didJustShiftClickToExtendPreviousShapeLine = false\n\t\t\t\t\t} else {\n\t\t\t\t\t\t// noop\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\t// If we're not shift clicking to extend a line, but we're holding shift, then we should snap\n\t\t\t\t\tshouldSnapToAngle = !ctrlKey // don't snap angle while snapping line\n\t\t\t\t}\n\n\t\t\t\tlet newPoint = this.editor.getPointInShapeSpace(shape, currentPagePoint).toFixed().toJson()\n\t\t\t\tlet didSnap = false\n\t\t\t\tlet snapSegment: TLDrawShapeSegment | undefined = undefined\n\n\t\t\t\tconst shouldSnap = this.editor.user.getIsSnapMode() ? !ctrlKey : ctrlKey\n\n\t\t\t\tif (shouldSnap) {\n\t\t\t\t\tif (newSegments.length > 2) {\n\t\t\t\t\t\tlet nearestPoint: VecModel | undefined = undefined\n\t\t\t\t\t\tlet minDistance = 8 / this.zoomOnEnter\n\n\t\t\t\t\t\t// Don't try to snap to the last two segments\n\t\t\t\t\t\tfor (let i = 0, n = segments.length - 2; i < n; i++) {\n\t\t\t\t\t\t\tconst segment = segments[i]\n\t\t\t\t\t\t\tif (!segment) break\n\t\t\t\t\t\t\tif (segment.type === 'free') continue\n\n\t\t\t\t\t\t\tconst first = b64Vecs.decodeFirstPoint(segment.path)\n\t\t\t\t\t\t\tconst lastPoint = b64Vecs.decodeLastPoint(segment.path)\n\t\t\t\t\t\t\tif (!(first && lastPoint)) continue\n\n\t\t\t\t\t\t\t// Snap to the nearest point on the segment, if it's closer than the previous snapped point\n\t\t\t\t\t\t\tconst nearestPointOnSegment = Vec.NearestPointOnLineSegment(\n\t\t\t\t\t\t\t\tfirst,\n\t\t\t\t\t\t\t\tlastPoint,\n\t\t\t\t\t\t\t\tnewPoint\n\t\t\t\t\t\t\t)\n\n\t\t\t\t\t\t\tif (Vec.DistMin(nearestPointOnSegment, newPoint, minDistance)) {\n\t\t\t\t\t\t\t\tnearestPoint = nearestPointOnSegment.toFixed().toJson()\n\t\t\t\t\t\t\t\tminDistance = Vec.Dist(nearestPointOnSegment, newPoint)\n\t\t\t\t\t\t\t\tsnapSegment = segment\n\t\t\t\t\t\t\t\tbreak\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tif (nearestPoint) {\n\t\t\t\t\t\t\tdidSnap = true\n\t\t\t\t\t\t\tnewPoint = nearestPoint\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tif (didSnap && snapSegment) {\n\t\t\t\t\tconst transform = this.editor.getShapePageTransform(shape)!\n\t\t\t\t\tconst first = b64Vecs.decodeFirstPoint(snapSegment.path)\n\t\t\t\t\tconst lastPoint = b64Vecs.decodeLastPoint(snapSegment.path)\n\t\t\t\t\tif (!first || !lastPoint) throw Error('Expected a last point!')\n\n\t\t\t\t\tconst A = Mat.applyToPoint(transform, first)\n\n\t\t\t\t\tconst B = Mat.applyToPoint(transform, lastPoint)\n\n\t\t\t\t\tconst snappedPoint = Mat.applyToPoint(transform, newPoint)\n\n\t\t\t\t\tthis.editor.snaps.setIndicators([\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tid: uniqueId(),\n\t\t\t\t\t\t\ttype: 'points',\n\t\t\t\t\t\t\tpoints: [A, snappedPoint, B],\n\t\t\t\t\t\t},\n\t\t\t\t\t])\n\t\t\t\t} else {\n\t\t\t\t\tthis.editor.snaps.clearIndicators()\n\n\t\t\t\t\tif (shouldSnapToAngle) {\n\t\t\t\t\t\t// Snap line angle to nearest 15 degrees\n\t\t\t\t\t\tconst currentAngle = Vec.Angle(pagePointWhereCurrentSegmentChanged, currentPagePoint)\n\t\t\t\t\t\tconst snappedAngle = snapAngle(currentAngle, 24)\n\t\t\t\t\t\tconst angleDiff = snappedAngle - currentAngle\n\n\t\t\t\t\t\tpagePoint = Vec.RotWith(\n\t\t\t\t\t\t\tcurrentPagePoint,\n\t\t\t\t\t\t\tpagePointWhereCurrentSegmentChanged,\n\t\t\t\t\t\t\tangleDiff\n\t\t\t\t\t\t)\n\t\t\t\t\t} else {\n\t\t\t\t\t\tpagePoint = currentPagePoint.clone()\n\t\t\t\t\t}\n\n\t\t\t\t\tnewPoint = this.editor.getPointInShapeSpace(shape, pagePoint).toFixed().toJson()\n\t\t\t\t}\n\n\t\t\t\t// If the previous segment is a one point free shape and is the first segment of the line,\n\t\t\t\t// then the user just did a click-and-immediately-press-shift to create a new straight line\n\t\t\t\t// without continuing the previous line. In this case, we want to remove the previous segment.\n\n\t\t\t\tthis.currentLineLength +=\n\t\t\t\t\tnewSegments.length && b64Vecs.decodeFirstPoint(newSegment.path)\n\t\t\t\t\t\t? Vec.Dist(b64Vecs.decodeFirstPoint(newSegment.path)!, Vec.From(newPoint))\n\t\t\t\t\t\t: 0\n\n\t\t\t\tnewSegments[newSegments.length - 1] = {\n\t\t\t\t\t...newSegment,\n\t\t\t\t\ttype: 'straight',\n\t\t\t\t\tpath: b64Vecs.encodePoints([\n\t\t\t\t\t\tb64Vecs.decodeFirstPoint(newSegment.path)!,\n\t\t\t\t\t\tVec.From(newPoint),\n\t\t\t\t\t]),\n\t\t\t\t}\n\n\t\t\t\tconst shapePartial: TLShapePartial<DrawableShape> = {\n\t\t\t\t\tid,\n\t\t\t\t\ttype: this.shapeType,\n\t\t\t\t\tprops: {\n\t\t\t\t\t\tsegments: newSegments,\n\t\t\t\t\t},\n\t\t\t\t}\n\n\t\t\t\tif (this.canClose()) {\n\t\t\t\t\t;(shapePartial as TLShapePartial<TLDrawShape>).props!.isClosed = this.getIsClosed(\n\t\t\t\t\t\tsegments,\n\t\t\t\t\t\tsize,\n\t\t\t\t\t\tscale\n\t\t\t\t\t)\n\t\t\t\t}\n\n\t\t\t\tthis.editor.updateShapes([shapePartial])\n\n\t\t\t\tbreak\n\t\t\t}\n\t\t\tcase 'free': {\n\t\t\t\t// Use cached points instead of decoding from b64 on every update\n\t\t\t\tconst cachedPoints = this.currentSegmentPoints\n\n\t\t\t\tif (cachedPoints.length && this.mergeNextPoint) {\n\t\t\t\t\tconst lastPoint = cachedPoints[cachedPoints.length - 1]\n\t\t\t\t\tlastPoint.x = newPoint.x\n\t\t\t\t\tlastPoint.y = newPoint.y\n\t\t\t\t\tlastPoint.z = lastPoint.z ? Math.max(lastPoint.z, newPoint.z) : newPoint.z\n\t\t\t\t\t// Note: we could recompute the line length here, but it's not really necessary\n\t\t\t\t\t// this.currentLineLength = this.getLineLength(newSegments)\n\t\t\t\t} else {\n\t\t\t\t\tthis.currentLineLength += cachedPoints.length\n\t\t\t\t\t\t? Vec.Dist(cachedPoints[cachedPoints.length - 1], newPoint)\n\t\t\t\t\t\t: 0\n\t\t\t\t\tcachedPoints.push(new Vec(newPoint.x, newPoint.y, newPoint.z))\n\t\t\t\t}\n\n\t\t\t\tconst newSegments = segments.slice()\n\t\t\t\tconst newSegment = newSegments[newSegments.length - 1]\n\t\t\t\tnewSegments[newSegments.length - 1] = {\n\t\t\t\t\t...newSegment,\n\t\t\t\t\tpath: b64Vecs.encodePoints(cachedPoints),\n\t\t\t\t}\n\n\t\t\t\tconst dvStrokeWidth = (getDisplayValues(this.util as any, shape) as { strokeWidth: number })\n\t\t\t\t\t.strokeWidth\n\t\t\t\tif (this.currentLineLength < dvStrokeWidth * 4) {\n\t\t\t\t\tthis.currentLineLength = this.getLineLength(newSegments)\n\t\t\t\t}\n\n\t\t\t\tconst shapePartial: TLShapePartial<DrawableShape> = {\n\t\t\t\t\tid,\n\t\t\t\t\ttype: this.shapeType,\n\t\t\t\t\tprops: {\n\t\t\t\t\t\tsegments: newSegments,\n\t\t\t\t\t},\n\t\t\t\t}\n\n\t\t\t\tif (this.canClose()) {\n\t\t\t\t\t;(shapePartial as TLShapePartial<TLDrawShape>).props!.isClosed = this.getIsClosed(\n\t\t\t\t\t\tnewSegments,\n\t\t\t\t\t\tsize,\n\t\t\t\t\t\tscale\n\t\t\t\t\t)\n\t\t\t\t}\n\n\t\t\t\tthis.editor.updateShapes([shapePartial])\n\n\t\t\t\t// Set a maximum length for the lines array; after 200 points, complete the line.\n\t\t\t\tif (cachedPoints.length > this.util.options.maxPointsPerShape) {\n\t\t\t\t\tthis.editor.updateShapes([{ id, type: this.shapeType, props: { isComplete: true } }])\n\n\t\t\t\t\tconst newShapeId = createShapeId()\n\n\t\t\t\t\tconst props = this.editor.getShape<DrawableShape>(id)!.props\n\n\t\t\t\t\tif (!this.editor.canCreateShapes([newShapeId])) return this.cancel()\n\t\t\t\t\tconst currentPagePoint = inputs.getCurrentPagePoint()\n\n\t\t\t\t\t// Reset cache for the new shape's segment\n\t\t\t\t\tconst initialPoint = new Vec(0, 0, this.isPenOrStylus ? +(z! * 1.25).toFixed() : 0.5)\n\t\t\t\t\tthis.currentSegmentPoints = [initialPoint]\n\n\t\t\t\t\tthis.editor.createShape({\n\t\t\t\t\t\tid: newShapeId,\n\t\t\t\t\t\ttype: this.shapeType,\n\t\t\t\t\t\tx: toFixed(currentPagePoint.x),\n\t\t\t\t\t\ty: toFixed(currentPagePoint.y),\n\t\t\t\t\t\tprops: {\n\t\t\t\t\t\t\tisPen: this.isPenOrStylus,\n\t\t\t\t\t\t\tscale: props.scale,\n\t\t\t\t\t\t\tsegments: [\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\ttype: 'free',\n\t\t\t\t\t\t\t\t\tpath: b64Vecs.encodePoints([initialPoint]),\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t],\n\t\t\t\t\t\t},\n\t\t\t\t\t})\n\n\t\t\t\t\tconst shape = this.editor.getShape<DrawableShape>(newShapeId)\n\n\t\t\t\t\tif (!shape) {\n\t\t\t\t\t\t// This would only happen if the page is full and no more shapes can be created. The bug would manifest as a crash when we try to clone the shape.\n\t\t\t\t\t\t// todo: handle this type of thing better\n\t\t\t\t\t\treturn this.cancel()\n\t\t\t\t\t}\n\n\t\t\t\t\tthis.initialShape = structuredClone(shape)\n\t\t\t\t\tthis.mergeNextPoint = false\n\t\t\t\t\tthis.lastRecordedPoint = currentPagePoint.clone()\n\t\t\t\t\tthis.currentLineLength = 0\n\t\t\t\t}\n\n\t\t\t\tbreak\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate getLineLength(segments: TLDrawShapeSegment[]) {\n\t\tlet length = 0\n\n\t\tfor (let j = 0; j < segments.length; j++) {\n\t\t\tconst points = b64Vecs.decodePoints(segments[j].path)\n\t\t\tfor (let i = 0; i < points.length - 1; i++) {\n\t\t\t\tlength += Vec.Dist2(points[i], points[i + 1])\n\t\t\t}\n\t\t}\n\n\t\treturn Math.sqrt(length)\n\t}\n\n\toverride onPointerUp() {\n\t\tthis.complete()\n\t}\n\n\toverride onCancel() {\n\t\tthis.cancel()\n\t}\n\n\toverride onComplete() {\n\t\tthis.complete()\n\t}\n\n\toverride onInterrupt() {\n\t\tif (this.editor.inputs.getIsDragging()) {\n\t\t\treturn\n\t\t}\n\n\t\tif (this.markId) {\n\t\t\tthis.editor.bailToMark(this.markId)\n\t\t}\n\t\tthis.cancel()\n\t}\n\n\tcomplete() {\n\t\tconst { initialShape } = this\n\t\tif (!initialShape) return\n\t\tthis.editor.updateShapes([\n\t\t\t{ id: initialShape.id, type: initialShape.type, props: { isComplete: true } },\n\t\t])\n\n\t\tthis.parent.transition('idle')\n\t}\n\n\tcancel() {\n\t\tthis.parent.transition('idle', this.info)\n\t}\n}\n"],
|
|
5
|
-
"mappings": "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",
|
|
4
|
+
"sourcesContent": ["import {\n\tMat,\n\tStateNode,\n\tTLDefaultSizeStyle,\n\tTLDrawShape,\n\tTLDrawShapeSegment,\n\tTLHighlightShape,\n\tTLKeyboardEventInfo,\n\tTLPointerEventInfo,\n\tTLShapePartial,\n\tDIM_2D,\n\tVec,\n\tVecModel,\n\tb64Vecs,\n\tcreateShapeId,\n\tlast,\n\tsnapAngle,\n\tstructuredClone,\n\ttoFixed,\n\tuniqueId,\n} from '@tldraw/editor'\nimport { HighlightShapeUtil } from '../../highlight/HighlightShapeUtil'\nimport { STROKE_SIZES } from '../../shared/default-shape-constants'\nimport { getDisplayValues } from '../../shared/getDisplayValues'\nimport { DrawShapeUtil } from '../DrawShapeUtil'\n\ntype DrawableShape = TLDrawShape | TLHighlightShape\n\nexport class Drawing extends StateNode {\n\tstatic override id = 'drawing'\n\tstatic override trackPerformance = true\n\n\tinfo = {} as TLPointerEventInfo\n\n\tinitialShape?: DrawableShape\n\n\toverride shapeType = this.parent.id === 'highlight' ? ('highlight' as const) : ('draw' as const)\n\n\tutil = this.editor.getShapeUtil(this.shapeType) as DrawShapeUtil | HighlightShapeUtil\n\n\tisPen = false\n\tisPenOrStylus = false\n\n\t// Encoding dimension for segments created during this stroke. `2` drops the\n\t// constant pressure value (non-pressure devices), `undefined` keeps full 3D.\n\t// Decided once in startShape from the input device \u2014 see the note there.\n\tsegmentDim: 2 | undefined = undefined\n\n\tsegmentMode = 'free' as 'free' | 'straight' | 'starting_straight' | 'starting_free'\n\n\tdidJustShiftClickToExtendPreviousShapeLine = false\n\n\tpagePointWhereCurrentSegmentChanged = {} as Vec\n\n\tpagePointWhereNextSegmentChanged = null as Vec | null\n\n\tlastRecordedPoint = {} as Vec\n\tmergeNextPoint = false\n\tcurrentLineLength = 0\n\tzoomOnEnter = 1\n\n\t// Cache for current segment's points to avoid repeated b64 decode/encode\n\tcurrentSegmentPoints: Vec[] = []\n\n\tmarkId = null as null | string\n\n\toverride onEnter(info: TLPointerEventInfo) {\n\t\tthis.markId = null\n\t\tthis.info = info\n\t\tthis.lastRecordedPoint = this.editor.inputs.getCurrentPagePoint().clone()\n\t\tthis.zoomOnEnter = this.editor.getZoomLevel()\n\t\tthis.startShape()\n\t}\n\n\toverride onPointerMove() {\n\t\tconst { inputs } = this.editor\n\t\tconst isPen = inputs.getIsPen()\n\n\t\tif (this.isPen && !isPen) {\n\t\t\t// The user made a palm gesture before starting a pen gesture;\n\t\t\t// ideally we'd start the new shape here but we could also just bail\n\t\t\t// as the next interaction will work correctly\n\t\t\tif (this.markId) {\n\t\t\t\tthis.editor.bailToMark(this.markId)\n\t\t\t\tthis.startShape()\n\t\t\t\treturn\n\t\t\t}\n\t\t}\n\n\t\tif (this.isPenOrStylus) {\n\t\t\t// Don't update the shape if we haven't moved far enough from the last time we recorded a point\n\t\t\tconst currentPagePoint = inputs.getCurrentPagePoint()\n\t\t\tif (Vec.Dist(currentPagePoint, this.lastRecordedPoint) >= 1 / this.zoomOnEnter) {\n\t\t\t\tthis.lastRecordedPoint = currentPagePoint.clone()\n\t\t\t\tthis.mergeNextPoint = false\n\t\t\t} else {\n\t\t\t\tthis.mergeNextPoint = true\n\t\t\t}\n\t\t} else {\n\t\t\tthis.mergeNextPoint = false\n\t\t}\n\n\t\tthis.updateDrawingShape()\n\t}\n\n\toverride onKeyDown(info: TLKeyboardEventInfo) {\n\t\tif (info.key === 'Shift') {\n\t\t\tswitch (this.segmentMode) {\n\t\t\t\tcase 'free': {\n\t\t\t\t\t// We've just entered straight mode, go to straight mode\n\t\t\t\t\tthis.segmentMode = 'starting_straight'\n\t\t\t\t\tthis.pagePointWhereNextSegmentChanged = this.editor.inputs.getCurrentPagePoint().clone()\n\t\t\t\t\tbreak\n\t\t\t\t}\n\t\t\t\tcase 'starting_free': {\n\t\t\t\t\tthis.segmentMode = 'starting_straight'\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tthis.updateDrawingShape()\n\t}\n\n\toverride onKeyUp(info: TLKeyboardEventInfo) {\n\t\tif (info.key === 'Shift') {\n\t\t\tthis.editor.snaps.clearIndicators()\n\n\t\t\tswitch (this.segmentMode) {\n\t\t\t\tcase 'straight': {\n\t\t\t\t\t// We've just exited straight mode, go back to free mode\n\t\t\t\t\tthis.segmentMode = 'starting_free'\n\t\t\t\t\tthis.pagePointWhereNextSegmentChanged = this.editor.inputs.getCurrentPagePoint().clone()\n\t\t\t\t\tbreak\n\t\t\t\t}\n\t\t\t\tcase 'starting_straight': {\n\t\t\t\t\tthis.pagePointWhereNextSegmentChanged = null\n\t\t\t\t\tthis.segmentMode = 'free'\n\t\t\t\t\tbreak\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tthis.updateDrawingShape()\n\t}\n\n\toverride onExit() {\n\t\tthis.editor.snaps.clearIndicators()\n\t\tthis.pagePointWhereCurrentSegmentChanged = this.editor.inputs.getCurrentPagePoint().clone()\n\t}\n\n\tcanClose() {\n\t\treturn this.shapeType !== 'highlight'\n\t}\n\n\tgetIsClosed(\n\t\tsegments: TLDrawShapeSegment[],\n\t\tsize: TLDefaultSizeStyle,\n\t\tscale: number,\n\t\tstrokeWidth?: number\n\t) {\n\t\tif (!this.canClose()) return false\n\n\t\tif (strokeWidth === undefined) {\n\t\t\tconst theme = this.editor.getCurrentTheme()\n\t\t\tstrokeWidth = theme.strokeWidth * STROKE_SIZES[size]\n\t\t}\n\t\tconst firstPoint = b64Vecs.decodeFirstPoint(segments[0].path, segments[0].dim)\n\t\tconst lastSegment = segments[segments.length - 1]\n\t\tconst lastPoint = b64Vecs.decodeLastPoint(lastSegment.path, lastSegment.dim)\n\n\t\tconst isDynamicResizingEnabled = this.editor.user.getIsDynamicResizeMode()\n\n\t\tconst threshold = isDynamicResizingEnabled // when dynamic resizing is enabled scale is 1/zoom, so the threshold should not scale directly with zoom at all\n\t\t\t? (strokeWidth + 2) * scale // +2 keeps tiny strokes from being too hard to close\n\t\t\t: // 6 is a base floor, 2 is stroke influence, 0.8 tempers width growth\n\t\t\t\t6 +\n\t\t\t\t2 * Math.sqrt(strokeWidth * 0.8) +\n\t\t\t\t// 100 is low-zoom boost, 0.18 is the zoom knee, 3 controls falloff steepness\n\t\t\t\t100 / (1 + Math.pow(this.zoomOnEnter / 0.18, 3))\n\n\t\treturn (\n\t\t\tfirstPoint !== null &&\n\t\t\tlastPoint !== null &&\n\t\t\tfirstPoint !== lastPoint &&\n\t\t\tthis.currentLineLength > strokeWidth * 4 * scale &&\n\t\t\tVec.DistMin(firstPoint, lastPoint, threshold)\n\t\t)\n\t}\n\n\t/**\n\t * Build a segment from points, encoding `path` at this stroke's `segmentDim` and\n\t * attaching `dim: 2` only when z was dropped. 3D segments omit `dim` so they\n\t * serialize byte-identically to pre-#8879 data.\n\t */\n\tprivate makeSegment(type: TLDrawShapeSegment['type'], points: VecModel[]): TLDrawShapeSegment {\n\t\tconst path = b64Vecs.encodePoints(points, this.segmentDim)\n\t\treturn this.segmentDim === DIM_2D ? { type, path, dim: DIM_2D } : { type, path }\n\t}\n\n\tprivate startShape() {\n\t\tconst inputs = this.editor.inputs\n\t\tconst originPagePoint = inputs.getOriginPagePoint()\n\t\tconst isPen = inputs.getIsPen()\n\n\t\tthis.markId = this.editor.markHistoryStoppingPoint('draw start')\n\n\t\t// If the pressure is weird, then it's probably a stylus reporting as a mouse\n\t\t// We treat pen/stylus inputs differently in the drawing tool, so we need to\n\t\t// have our own value for this. The inputs.isPen is only if the input is a regular\n\t\t// pen, like an iPad pen, which needs to trigger \"pen mode\" in order to avoid\n\t\t// accidental palm touches. We don't have to worry about that with styluses though.\n\t\tconst { z = 0.5 } = this.info.point\n\n\t\tthis.isPen = isPen\n\t\t// if z === 0 on the initial point, treat this pen as a mouse because it's likely a broken pen\n\t\t// or a broken OS.\n\t\tthis.isPenOrStylus = (isPen && z !== 0) || (z > 0 && z < 0.5) || (z > 0.5 && z < 1)\n\n\t\t// Decide the encoding dimension once, here, from the input device \u2014 not by\n\t\t// scanning point data (content-driven). Device-driven keeps the encoded bytes\n\t\t// deterministic and is O(1) at stroke start. Non-pressure devices report a\n\t\t// constant z (0 / 0.5 / 1) that we normalize to 0.5 and omit entirely (2D);\n\t\t// pen/stylus input keeps the full 3D encoding.\n\t\tthis.segmentDim = this.isPenOrStylus ? undefined : DIM_2D\n\n\t\tconst pressure = this.isPenOrStylus ? z * 1.25 : 0.5\n\n\t\tthis.segmentMode = this.editor.inputs.getShiftKey() ? 'straight' : 'free'\n\n\t\tthis.didJustShiftClickToExtendPreviousShapeLine = false\n\n\t\tthis.lastRecordedPoint = originPagePoint.clone()\n\n\t\tif (this.initialShape) {\n\t\t\tconst shape = this.editor.getShape<DrawableShape>(this.initialShape.id)\n\n\t\t\tif (shape && this.segmentMode === 'straight') {\n\t\t\t\t// Connect dots\n\n\t\t\t\tthis.didJustShiftClickToExtendPreviousShapeLine = true\n\n\t\t\t\tconst prevSegment = last(shape.props.segments)\n\t\t\t\tif (!prevSegment) throw Error('Expected a previous segment!')\n\t\t\t\tconst prevPoint = b64Vecs.decodeLastPoint(prevSegment.path, prevSegment.dim)\n\t\t\t\tif (!prevPoint) throw Error('Expected a previous point!')\n\n\t\t\t\tconst { x, y } = this.editor.getPointInShapeSpace(shape, originPagePoint).toFixed()\n\n\t\t\t\tconst newSegment = this.makeSegment(this.segmentMode, [\n\t\t\t\t\t{ x: prevPoint.x, y: prevPoint.y, z: +pressure.toFixed(2) },\n\t\t\t\t\t{ x, y, z: +pressure.toFixed(2) },\n\t\t\t\t])\n\n\t\t\t\t// Convert prevPoint to page space\n\t\t\t\tconst prevPointPageSpace = Mat.applyToPoint(\n\t\t\t\t\tthis.editor.getShapePageTransform(shape.id)!,\n\t\t\t\t\tprevPoint\n\t\t\t\t)\n\t\t\t\tthis.pagePointWhereCurrentSegmentChanged = prevPointPageSpace\n\t\t\t\tthis.pagePointWhereNextSegmentChanged = null\n\t\t\t\tconst segments = [...shape.props.segments, newSegment]\n\n\t\t\t\tconst dvStrokeWidth = (getDisplayValues(this.util as any, shape) as { strokeWidth: number })\n\t\t\t\t\t.strokeWidth\n\t\t\t\tif (this.currentLineLength < dvStrokeWidth * 4) {\n\t\t\t\t\tthis.currentLineLength = this.getLineLength(segments)\n\t\t\t\t}\n\n\t\t\t\tconst shapePartial: TLShapePartial<DrawableShape> = {\n\t\t\t\t\tid: shape.id,\n\t\t\t\t\ttype: this.shapeType,\n\t\t\t\t\tprops: {\n\t\t\t\t\t\tsegments,\n\t\t\t\t\t},\n\t\t\t\t}\n\n\t\t\t\tif (this.canClose()) {\n\t\t\t\t\t;(shapePartial as TLShapePartial<TLDrawShape>).props!.isClosed = this.getIsClosed(\n\t\t\t\t\t\tsegments,\n\t\t\t\t\t\tshape.props.size,\n\t\t\t\t\t\tshape.props.scale\n\t\t\t\t\t)\n\t\t\t\t}\n\n\t\t\t\tthis.editor.updateShapes([shapePartial])\n\n\t\t\t\treturn\n\t\t\t}\n\t\t}\n\n\t\t// Create a new shape\n\n\t\tthis.pagePointWhereCurrentSegmentChanged = originPagePoint.clone()\n\t\tconst id = createShapeId()\n\n\t\t// Initialize the segment points cache\n\t\tconst initialPoint = new Vec(0, 0, +pressure.toFixed(2))\n\t\tthis.currentSegmentPoints = [initialPoint]\n\n\t\t// Allow this to trigger the max shapes reached alert\n\t\tthis.editor.createShape({\n\t\t\tid,\n\t\t\ttype: this.shapeType,\n\t\t\tx: originPagePoint.x,\n\t\t\ty: originPagePoint.y,\n\t\t\tprops: {\n\t\t\t\tisPen: this.isPenOrStylus,\n\t\t\t\tscale: this.editor.getResizeScaleFactor(),\n\t\t\t\tsegments: [this.makeSegment(this.segmentMode, [initialPoint])],\n\t\t\t},\n\t\t})\n\t\tconst shape = this.editor.getShape<DrawableShape>(id)\n\t\tif (!shape) {\n\t\t\tthis.cancel()\n\t\t\treturn\n\t\t}\n\t\tthis.currentLineLength = 0\n\t\tthis.initialShape = this.editor.getShape<DrawableShape>(id)\n\t}\n\n\tprivate updateDrawingShape() {\n\t\tconst { initialShape } = this\n\t\tconst { inputs } = this.editor\n\n\t\tif (!initialShape) return\n\n\t\tconst {\n\t\t\tid,\n\t\t\tprops: { size, scale },\n\t\t} = initialShape\n\n\t\tconst shape = this.editor.getShape<DrawableShape>(id)!\n\n\t\tif (!shape) return\n\n\t\tconst { segments } = shape.props\n\n\t\tconst currentPagePoint = inputs.getCurrentPagePoint()\n\t\tconst { x, y, z } = this.editor.getPointInShapeSpace(shape, currentPagePoint).toFixed()\n\t\tconst pressure = this.isPenOrStylus ? +(currentPagePoint.z! * 1.25).toFixed(2) : 0.5\n\t\tconst newPoint = { x, y, z: pressure }\n\n\t\tswitch (this.segmentMode) {\n\t\t\tcase 'starting_straight': {\n\t\t\t\tconst { pagePointWhereNextSegmentChanged } = this\n\n\t\t\t\tif (pagePointWhereNextSegmentChanged === null) {\n\t\t\t\t\tthrow Error('We should have a point where the segment changed')\n\t\t\t\t}\n\n\t\t\t\tconst hasMovedFarEnough =\n\t\t\t\t\tVec.Dist2(pagePointWhereNextSegmentChanged, inputs.getCurrentPagePoint()) >\n\t\t\t\t\tthis.editor.options.dragDistanceSquared\n\n\t\t\t\t// Find the distance from where the pointer was when shift was released and\n\t\t\t\t// where it is now; if it's far enough away, then update the page point where\n\t\t\t\t// the current segment changed (to match the pagepoint where next segment changed)\n\t\t\t\t// and set the pagepoint where next segment changed to null.\n\t\t\t\tif (hasMovedFarEnough) {\n\t\t\t\t\tthis.pagePointWhereCurrentSegmentChanged = this.pagePointWhereNextSegmentChanged!.clone()\n\t\t\t\t\tthis.pagePointWhereNextSegmentChanged = null\n\n\t\t\t\t\t// Set the new mode\n\t\t\t\t\tthis.segmentMode = 'straight'\n\n\t\t\t\t\tconst prevSegment = last(segments)\n\t\t\t\t\tif (!prevSegment) throw Error('Expected a previous segment!')\n\n\t\t\t\t\tconst prevLastPoint = b64Vecs.decodeLastPoint(prevSegment.path, prevSegment.dim)\n\t\t\t\t\tif (!prevLastPoint) throw Error('Expected a previous last point!')\n\n\t\t\t\t\tlet newSegment: TLDrawShapeSegment\n\n\t\t\t\t\tconst newLastPoint = this.editor\n\t\t\t\t\t\t.getPointInShapeSpace(shape, this.pagePointWhereCurrentSegmentChanged)\n\t\t\t\t\t\t.toFixed()\n\t\t\t\t\t\t.toJson()\n\n\t\t\t\t\tif (prevSegment.type === 'straight') {\n\t\t\t\t\t\tthis.currentLineLength += Vec.Dist(prevLastPoint, newLastPoint)\n\n\t\t\t\t\t\tnewSegment = this.makeSegment('straight', [prevLastPoint, newLastPoint])\n\n\t\t\t\t\t\tconst transform = this.editor.getShapePageTransform(shape)!\n\n\t\t\t\t\t\tthis.pagePointWhereCurrentSegmentChanged = Mat.applyToPoint(transform, prevLastPoint)\n\t\t\t\t\t} else {\n\t\t\t\t\t\tnewSegment = this.makeSegment('straight', [newLastPoint, newPoint])\n\t\t\t\t\t}\n\n\t\t\t\t\tconst shapePartial: TLShapePartial<DrawableShape> = {\n\t\t\t\t\t\tid,\n\t\t\t\t\t\ttype: this.shapeType,\n\t\t\t\t\t\tprops: {\n\t\t\t\t\t\t\tsegments: [...segments, newSegment],\n\t\t\t\t\t\t},\n\t\t\t\t\t}\n\n\t\t\t\t\tif (this.canClose()) {\n\t\t\t\t\t\t;(shapePartial as TLShapePartial<TLDrawShape>).props!.isClosed = this.getIsClosed(\n\t\t\t\t\t\t\tsegments,\n\t\t\t\t\t\t\tsize,\n\t\t\t\t\t\t\tscale\n\t\t\t\t\t\t)\n\t\t\t\t\t}\n\n\t\t\t\t\tthis.editor.updateShapes([shapePartial])\n\t\t\t\t}\n\t\t\t\tbreak\n\t\t\t}\n\t\t\tcase 'starting_free': {\n\t\t\t\tconst { pagePointWhereNextSegmentChanged } = this\n\n\t\t\t\tif (pagePointWhereNextSegmentChanged === null) {\n\t\t\t\t\tthrow Error('We should have a point where the segment changed')\n\t\t\t\t}\n\n\t\t\t\tconst hasMovedFarEnough =\n\t\t\t\t\tVec.Dist2(pagePointWhereNextSegmentChanged, inputs.getCurrentPagePoint()) >\n\t\t\t\t\tthis.editor.options.dragDistanceSquared\n\n\t\t\t\t// Find the distance from where the pointer was when shift was released and\n\t\t\t\t// where it is now; if it's far enough away, then update the page point where\n\t\t\t\t// the current segment changed (to match the pagepoint where next segment changed)\n\t\t\t\t// and set the pagepoint where next segment changed to null.\n\t\t\t\tif (hasMovedFarEnough) {\n\t\t\t\t\tthis.pagePointWhereCurrentSegmentChanged = this.pagePointWhereNextSegmentChanged!.clone()\n\t\t\t\t\tthis.pagePointWhereNextSegmentChanged = null\n\n\t\t\t\t\t// Set the new mode\n\t\t\t\t\tthis.segmentMode = 'free'\n\n\t\t\t\t\tconst newSegments = segments.slice()\n\t\t\t\t\tconst prevStraightSegment = newSegments[newSegments.length - 1]\n\t\t\t\t\tconst prevPoint = b64Vecs.decodeLastPoint(\n\t\t\t\t\t\tprevStraightSegment.path,\n\t\t\t\t\t\tprevStraightSegment.dim\n\t\t\t\t\t)\n\n\t\t\t\t\tif (!prevPoint) {\n\t\t\t\t\t\tthrow Error('No previous point!')\n\t\t\t\t\t}\n\n\t\t\t\t\t// Create the new free segment and interpolate the points between where the last line\n\t\t\t\t\t// ended and where the pointer is now\n\t\t\t\t\tconst interpolatedPoints = Vec.PointsBetween(prevPoint, newPoint, 6).map(\n\t\t\t\t\t\t(p) => new Vec(toFixed(p.x), toFixed(p.y), toFixed(p.z))\n\t\t\t\t\t)\n\t\t\t\t\t// Initialize cache for the new free segment\n\t\t\t\t\tthis.currentSegmentPoints = interpolatedPoints\n\n\t\t\t\t\tconst newFreeSegment = this.makeSegment('free', interpolatedPoints)\n\n\t\t\t\t\tconst finalSegments = [...newSegments, newFreeSegment]\n\n\t\t\t\t\tconst dvStrokeWidth = (\n\t\t\t\t\t\tgetDisplayValues(this.util as any, shape) as { strokeWidth: number }\n\t\t\t\t\t).strokeWidth\n\t\t\t\t\tif (this.currentLineLength < dvStrokeWidth * 4) {\n\t\t\t\t\t\tthis.currentLineLength = this.getLineLength(finalSegments)\n\t\t\t\t\t}\n\n\t\t\t\t\tconst shapePartial: TLShapePartial<DrawableShape> = {\n\t\t\t\t\t\tid,\n\t\t\t\t\t\ttype: this.shapeType,\n\t\t\t\t\t\tprops: {\n\t\t\t\t\t\t\tsegments: finalSegments,\n\t\t\t\t\t\t},\n\t\t\t\t\t}\n\n\t\t\t\t\tif (this.canClose()) {\n\t\t\t\t\t\t;(shapePartial as TLShapePartial<TLDrawShape>).props!.isClosed = this.getIsClosed(\n\t\t\t\t\t\t\tfinalSegments,\n\t\t\t\t\t\t\tsize,\n\t\t\t\t\t\t\tscale\n\t\t\t\t\t\t)\n\t\t\t\t\t}\n\n\t\t\t\t\tthis.editor.updateShapes([shapePartial])\n\t\t\t\t}\n\n\t\t\t\tbreak\n\t\t\t}\n\t\t\tcase 'straight': {\n\t\t\t\tconst newSegments = segments.slice()\n\t\t\t\tconst newSegment = newSegments[newSegments.length - 1]\n\n\t\t\t\tconst { pagePointWhereCurrentSegmentChanged } = this\n\t\t\t\tconst inputs = this.editor.inputs\n\t\t\t\tconst ctrlKey = inputs.getCtrlKey()\n\t\t\t\tconst currentPagePoint = inputs.getCurrentPagePoint()\n\n\t\t\t\tif (!pagePointWhereCurrentSegmentChanged)\n\t\t\t\t\tthrow Error('We should have a point where the segment changed')\n\n\t\t\t\tlet pagePoint: VecModel\n\t\t\t\tlet shouldSnapToAngle = false\n\n\t\t\t\tif (this.didJustShiftClickToExtendPreviousShapeLine) {\n\t\t\t\t\tif (this.editor.inputs.getIsDragging()) {\n\t\t\t\t\t\t// If we've just shift clicked to extend a line, only snap once we've started dragging\n\t\t\t\t\t\tshouldSnapToAngle = !ctrlKey\n\t\t\t\t\t\tthis.didJustShiftClickToExtendPreviousShapeLine = false\n\t\t\t\t\t} else {\n\t\t\t\t\t\t// noop\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\t// If we're not shift clicking to extend a line, but we're holding shift, then we should snap\n\t\t\t\t\tshouldSnapToAngle = !ctrlKey // don't snap angle while snapping line\n\t\t\t\t}\n\n\t\t\t\tlet newPoint = this.editor.getPointInShapeSpace(shape, currentPagePoint).toFixed().toJson()\n\t\t\t\tlet didSnap = false\n\t\t\t\tlet snapSegment: TLDrawShapeSegment | undefined = undefined\n\n\t\t\t\tconst shouldSnap = this.editor.user.getIsSnapMode() ? !ctrlKey : ctrlKey\n\n\t\t\t\tif (shouldSnap) {\n\t\t\t\t\tif (newSegments.length > 2) {\n\t\t\t\t\t\tlet nearestPoint: VecModel | undefined = undefined\n\t\t\t\t\t\tlet minDistance = 8 / this.zoomOnEnter\n\n\t\t\t\t\t\t// Don't try to snap to the last two segments\n\t\t\t\t\t\tfor (let i = 0, n = segments.length - 2; i < n; i++) {\n\t\t\t\t\t\t\tconst segment = segments[i]\n\t\t\t\t\t\t\tif (!segment) break\n\t\t\t\t\t\t\tif (segment.type === 'free') continue\n\n\t\t\t\t\t\t\tconst first = b64Vecs.decodeFirstPoint(segment.path, segment.dim)\n\t\t\t\t\t\t\tconst lastPoint = b64Vecs.decodeLastPoint(segment.path, segment.dim)\n\t\t\t\t\t\t\tif (!(first && lastPoint)) continue\n\n\t\t\t\t\t\t\t// Snap to the nearest point on the segment, if it's closer than the previous snapped point\n\t\t\t\t\t\t\tconst nearestPointOnSegment = Vec.NearestPointOnLineSegment(\n\t\t\t\t\t\t\t\tfirst,\n\t\t\t\t\t\t\t\tlastPoint,\n\t\t\t\t\t\t\t\tnewPoint\n\t\t\t\t\t\t\t)\n\n\t\t\t\t\t\t\tif (Vec.DistMin(nearestPointOnSegment, newPoint, minDistance)) {\n\t\t\t\t\t\t\t\tnearestPoint = nearestPointOnSegment.toFixed().toJson()\n\t\t\t\t\t\t\t\tminDistance = Vec.Dist(nearestPointOnSegment, newPoint)\n\t\t\t\t\t\t\t\tsnapSegment = segment\n\t\t\t\t\t\t\t\tbreak\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tif (nearestPoint) {\n\t\t\t\t\t\t\tdidSnap = true\n\t\t\t\t\t\t\tnewPoint = nearestPoint\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tif (didSnap && snapSegment) {\n\t\t\t\t\tconst transform = this.editor.getShapePageTransform(shape)!\n\t\t\t\t\tconst first = b64Vecs.decodeFirstPoint(snapSegment.path, snapSegment.dim)\n\t\t\t\t\tconst lastPoint = b64Vecs.decodeLastPoint(snapSegment.path, snapSegment.dim)\n\t\t\t\t\tif (!first || !lastPoint) throw Error('Expected a last point!')\n\n\t\t\t\t\tconst A = Mat.applyToPoint(transform, first)\n\n\t\t\t\t\tconst B = Mat.applyToPoint(transform, lastPoint)\n\n\t\t\t\t\tconst snappedPoint = Mat.applyToPoint(transform, newPoint)\n\n\t\t\t\t\tthis.editor.snaps.setIndicators([\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tid: uniqueId(),\n\t\t\t\t\t\t\ttype: 'points',\n\t\t\t\t\t\t\tpoints: [A, snappedPoint, B],\n\t\t\t\t\t\t},\n\t\t\t\t\t])\n\t\t\t\t} else {\n\t\t\t\t\tthis.editor.snaps.clearIndicators()\n\n\t\t\t\t\tif (shouldSnapToAngle) {\n\t\t\t\t\t\t// Snap line angle to nearest 15 degrees\n\t\t\t\t\t\tconst currentAngle = Vec.Angle(pagePointWhereCurrentSegmentChanged, currentPagePoint)\n\t\t\t\t\t\tconst snappedAngle = snapAngle(currentAngle, 24)\n\t\t\t\t\t\tconst angleDiff = snappedAngle - currentAngle\n\n\t\t\t\t\t\tpagePoint = Vec.RotWith(\n\t\t\t\t\t\t\tcurrentPagePoint,\n\t\t\t\t\t\t\tpagePointWhereCurrentSegmentChanged,\n\t\t\t\t\t\t\tangleDiff\n\t\t\t\t\t\t)\n\t\t\t\t\t} else {\n\t\t\t\t\t\tpagePoint = currentPagePoint.clone()\n\t\t\t\t\t}\n\n\t\t\t\t\tnewPoint = this.editor.getPointInShapeSpace(shape, pagePoint).toFixed().toJson()\n\t\t\t\t}\n\n\t\t\t\t// If the previous segment is a one point free shape and is the first segment of the line,\n\t\t\t\t// then the user just did a click-and-immediately-press-shift to create a new straight line\n\t\t\t\t// without continuing the previous line. In this case, we want to remove the previous segment.\n\n\t\t\t\tthis.currentLineLength +=\n\t\t\t\t\tnewSegments.length && b64Vecs.decodeFirstPoint(newSegment.path, newSegment.dim)\n\t\t\t\t\t\t? Vec.Dist(\n\t\t\t\t\t\t\t\tb64Vecs.decodeFirstPoint(newSegment.path, newSegment.dim)!,\n\t\t\t\t\t\t\t\tVec.From(newPoint)\n\t\t\t\t\t\t\t)\n\t\t\t\t\t\t: 0\n\n\t\t\t\tnewSegments[newSegments.length - 1] = {\n\t\t\t\t\t...newSegment,\n\t\t\t\t\ttype: 'straight',\n\t\t\t\t\tpath: b64Vecs.encodePoints(\n\t\t\t\t\t\t[b64Vecs.decodeFirstPoint(newSegment.path, newSegment.dim)!, Vec.From(newPoint)],\n\t\t\t\t\t\tnewSegment.dim\n\t\t\t\t\t),\n\t\t\t\t}\n\n\t\t\t\tconst shapePartial: TLShapePartial<DrawableShape> = {\n\t\t\t\t\tid,\n\t\t\t\t\ttype: this.shapeType,\n\t\t\t\t\tprops: {\n\t\t\t\t\t\tsegments: newSegments,\n\t\t\t\t\t},\n\t\t\t\t}\n\n\t\t\t\tif (this.canClose()) {\n\t\t\t\t\t;(shapePartial as TLShapePartial<TLDrawShape>).props!.isClosed = this.getIsClosed(\n\t\t\t\t\t\tsegments,\n\t\t\t\t\t\tsize,\n\t\t\t\t\t\tscale\n\t\t\t\t\t)\n\t\t\t\t}\n\n\t\t\t\tthis.editor.updateShapes([shapePartial])\n\n\t\t\t\tbreak\n\t\t\t}\n\t\t\tcase 'free': {\n\t\t\t\t// Use cached points instead of decoding from b64 on every update\n\t\t\t\tconst cachedPoints = this.currentSegmentPoints\n\n\t\t\t\tif (cachedPoints.length && this.mergeNextPoint) {\n\t\t\t\t\tconst lastPoint = cachedPoints[cachedPoints.length - 1]\n\t\t\t\t\tlastPoint.x = newPoint.x\n\t\t\t\t\tlastPoint.y = newPoint.y\n\t\t\t\t\tlastPoint.z = lastPoint.z ? Math.max(lastPoint.z, newPoint.z) : newPoint.z\n\t\t\t\t\t// Note: we could recompute the line length here, but it's not really necessary\n\t\t\t\t\t// this.currentLineLength = this.getLineLength(newSegments)\n\t\t\t\t} else {\n\t\t\t\t\tthis.currentLineLength += cachedPoints.length\n\t\t\t\t\t\t? Vec.Dist(cachedPoints[cachedPoints.length - 1], newPoint)\n\t\t\t\t\t\t: 0\n\t\t\t\t\tcachedPoints.push(new Vec(newPoint.x, newPoint.y, newPoint.z))\n\t\t\t\t}\n\n\t\t\t\tconst newSegments = segments.slice()\n\t\t\t\tconst newSegment = newSegments[newSegments.length - 1]\n\t\t\t\tnewSegments[newSegments.length - 1] = {\n\t\t\t\t\t...newSegment,\n\t\t\t\t\tpath: b64Vecs.encodePoints(cachedPoints, newSegment.dim),\n\t\t\t\t}\n\n\t\t\t\tconst dvStrokeWidth = (getDisplayValues(this.util as any, shape) as { strokeWidth: number })\n\t\t\t\t\t.strokeWidth\n\t\t\t\tif (this.currentLineLength < dvStrokeWidth * 4) {\n\t\t\t\t\tthis.currentLineLength = this.getLineLength(newSegments)\n\t\t\t\t}\n\n\t\t\t\tconst shapePartial: TLShapePartial<DrawableShape> = {\n\t\t\t\t\tid,\n\t\t\t\t\ttype: this.shapeType,\n\t\t\t\t\tprops: {\n\t\t\t\t\t\tsegments: newSegments,\n\t\t\t\t\t},\n\t\t\t\t}\n\n\t\t\t\tif (this.canClose()) {\n\t\t\t\t\t;(shapePartial as TLShapePartial<TLDrawShape>).props!.isClosed = this.getIsClosed(\n\t\t\t\t\t\tnewSegments,\n\t\t\t\t\t\tsize,\n\t\t\t\t\t\tscale\n\t\t\t\t\t)\n\t\t\t\t}\n\n\t\t\t\tthis.editor.updateShapes([shapePartial])\n\n\t\t\t\t// Set a maximum length for the lines array; after 200 points, complete the line.\n\t\t\t\tif (cachedPoints.length > this.util.options.maxPointsPerShape) {\n\t\t\t\t\tthis.editor.updateShapes([{ id, type: this.shapeType, props: { isComplete: true } }])\n\n\t\t\t\t\tconst newShapeId = createShapeId()\n\n\t\t\t\t\tconst props = this.editor.getShape<DrawableShape>(id)!.props\n\n\t\t\t\t\tif (!this.editor.canCreateShapes([newShapeId])) return this.cancel()\n\t\t\t\t\tconst currentPagePoint = inputs.getCurrentPagePoint()\n\n\t\t\t\t\t// Reset cache for the new shape's segment\n\t\t\t\t\tconst initialPoint = new Vec(0, 0, this.isPenOrStylus ? +(z! * 1.25).toFixed() : 0.5)\n\t\t\t\t\tthis.currentSegmentPoints = [initialPoint]\n\n\t\t\t\t\tthis.editor.createShape({\n\t\t\t\t\t\tid: newShapeId,\n\t\t\t\t\t\ttype: this.shapeType,\n\t\t\t\t\t\tx: toFixed(currentPagePoint.x),\n\t\t\t\t\t\ty: toFixed(currentPagePoint.y),\n\t\t\t\t\t\tprops: {\n\t\t\t\t\t\t\tisPen: this.isPenOrStylus,\n\t\t\t\t\t\t\tscale: props.scale,\n\t\t\t\t\t\t\tsegments: [this.makeSegment('free', [initialPoint])],\n\t\t\t\t\t\t},\n\t\t\t\t\t})\n\n\t\t\t\t\tconst shape = this.editor.getShape<DrawableShape>(newShapeId)\n\n\t\t\t\t\tif (!shape) {\n\t\t\t\t\t\t// This would only happen if the page is full and no more shapes can be created. The bug would manifest as a crash when we try to clone the shape.\n\t\t\t\t\t\t// todo: handle this type of thing better\n\t\t\t\t\t\treturn this.cancel()\n\t\t\t\t\t}\n\n\t\t\t\t\tthis.initialShape = structuredClone(shape)\n\t\t\t\t\tthis.mergeNextPoint = false\n\t\t\t\t\tthis.lastRecordedPoint = currentPagePoint.clone()\n\t\t\t\t\tthis.currentLineLength = 0\n\t\t\t\t}\n\n\t\t\t\tbreak\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate getLineLength(segments: TLDrawShapeSegment[]) {\n\t\tlet length = 0\n\n\t\tfor (let j = 0; j < segments.length; j++) {\n\t\t\tconst points = b64Vecs.decodePoints(segments[j].path, segments[j].dim)\n\t\t\tfor (let i = 0; i < points.length - 1; i++) {\n\t\t\t\tlength += Vec.Dist2(points[i], points[i + 1])\n\t\t\t}\n\t\t}\n\n\t\treturn Math.sqrt(length)\n\t}\n\n\toverride onPointerUp() {\n\t\tthis.complete()\n\t}\n\n\toverride onCancel() {\n\t\tthis.cancel()\n\t}\n\n\toverride onComplete() {\n\t\tthis.complete()\n\t}\n\n\toverride onInterrupt() {\n\t\tif (this.editor.inputs.getIsDragging()) {\n\t\t\treturn\n\t\t}\n\n\t\tif (this.markId) {\n\t\t\tthis.editor.bailToMark(this.markId)\n\t\t}\n\t\tthis.cancel()\n\t}\n\n\tcomplete() {\n\t\tconst { initialShape } = this\n\t\tif (!initialShape) return\n\t\tthis.editor.updateShapes([\n\t\t\t{ id: initialShape.id, type: initialShape.type, props: { isComplete: true } },\n\t\t])\n\n\t\tthis.parent.transition('idle')\n\t}\n\n\tcancel() {\n\t\tthis.parent.transition('idle', this.info)\n\t}\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": ["shape", "inputs", "currentPagePoint", "newPoint"]
|
|
7
7
|
}
|
|
@@ -30,6 +30,7 @@ class EmbedShapeUtil extends BaseBoxShapeUtil {
|
|
|
30
30
|
static migrations = embedShapeMigrations;
|
|
31
31
|
options = {
|
|
32
32
|
embedDefinitions: DEFAULT_EMBED_DEFINITIONS,
|
|
33
|
+
embedConfig: {},
|
|
33
34
|
getDefaultDisplayValues() {
|
|
34
35
|
return {
|
|
35
36
|
showShadow: true
|
|
@@ -56,7 +57,7 @@ class EmbedShapeUtil extends BaseBoxShapeUtil {
|
|
|
56
57
|
return this.getEmbedDefs();
|
|
57
58
|
}
|
|
58
59
|
getEmbedDefinition(url) {
|
|
59
|
-
return getEmbedInfo(this.getEmbedDefs(), url);
|
|
60
|
+
return getEmbedInfo(this.getEmbedDefs(), url, this.options.embedConfig);
|
|
60
61
|
}
|
|
61
62
|
getText(shape) {
|
|
62
63
|
return shape.props.url;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../../src/lib/shapes/embed/EmbedShapeUtil.tsx"],
|
|
4
|
-
"sourcesContent": ["/* eslint-disable react-hooks/rules-of-hooks */\n\nimport {\n\tBaseBoxShapeUtil,\n\tHTMLContainer,\n\tTLEmbedShape,\n\tTLEmbedShapeProps,\n\tTLResizeInfo,\n\tembedShapeMigrations,\n\tembedShapeProps,\n\tlerp,\n\tresizeBox,\n\ttoDomPrecision,\n\tuseColorMode,\n\tuseIsEditing,\n\tuseSvgExportContext,\n\tuseValue,\n} from '@tldraw/editor'\nimport {\n\tDEFAULT_EMBED_DEFINITIONS,\n\tEmbedDefinition,\n\tTLEmbedDefinition,\n\tTLEmbedShapePermissions,\n\tembedShapePermissionDefaults,\n\tunknownEmbedShapePermissionOverrides,\n} from '../../defaultEmbedDefinitions'\nimport { TLEmbedResult, getEmbedInfo } from '../../utils/embeds/embeds'\nimport { BookmarkShapeComponent } from '../bookmark/BookmarkShapeUtil'\nimport { ShapeOptionsWithDisplayValues, getDisplayValues } from '../shared/getDisplayValues'\nimport { getRotatedBoxShadow } from '../shared/rotated-box-shadow'\n\n/** @public */\nexport interface EmbedShapeUtilDisplayValues {\n\tshowShadow: boolean\n}\n\n/** @public */\nexport interface EmbedShapeOptions extends ShapeOptionsWithDisplayValues<\n\tTLEmbedShape,\n\tEmbedShapeUtilDisplayValues\n> {\n\t/** The embed definitions to use for this shape util. */\n\treadonly embedDefinitions: readonly TLEmbedDefinition[]\n}\n\nconst getSandboxPermissions = (permissions: TLEmbedShapePermissions) => {\n\treturn Object.entries(permissions)\n\t\t.filter(([_perm, isEnabled]) => isEnabled)\n\t\t.map(([perm]) => perm)\n\t\t.join(' ')\n}\n\n/** @public */\nexport class EmbedShapeUtil extends BaseBoxShapeUtil<TLEmbedShape> {\n\tstatic override type = 'embed' as const\n\tstatic override props = embedShapeProps\n\tstatic override migrations = embedShapeMigrations\n\n\toverride options: EmbedShapeOptions = {\n\t\tembedDefinitions: DEFAULT_EMBED_DEFINITIONS,\n\t\tgetDefaultDisplayValues(): EmbedShapeUtilDisplayValues {\n\t\t\treturn {\n\t\t\t\tshowShadow: true,\n\t\t\t}\n\t\t},\n\t\tgetCustomDisplayValues(): Partial<EmbedShapeUtilDisplayValues> {\n\t\t\treturn {}\n\t\t},\n\t}\n\n\toverride canEditWhileLocked(shape: TLEmbedShape) {\n\t\tconst result = this.getEmbedDefinition(shape.props.url)\n\t\tif (!result) return true\n\t\treturn result.definition.canEditWhileLocked ?? true\n\t}\n\n\tprivate static legacyEmbedDefinitions: readonly EmbedDefinition[] | null = null\n\n\t/** @deprecated - Use `EmbedShapeUtil.configure({ embedDefinitions: [...] })` instead. */\n\tstatic setEmbedDefinitions(embedDefinitions: readonly EmbedDefinition[]) {\n\t\tEmbedShapeUtil.legacyEmbedDefinitions = embedDefinitions\n\t}\n\n\tprivate getEmbedDefs(): readonly TLEmbedDefinition[] {\n\t\treturn EmbedShapeUtil.legacyEmbedDefinitions ?? this.options.embedDefinitions\n\t}\n\n\tgetEmbedDefinitions(): readonly TLEmbedDefinition[] {\n\t\treturn this.getEmbedDefs()\n\t}\n\n\tgetEmbedDefinition(url: string): TLEmbedResult {\n\t\treturn getEmbedInfo(this.getEmbedDefs(), url)\n\t}\n\n\toverride getText(shape: TLEmbedShape) {\n\t\treturn shape.props.url\n\t}\n\n\toverride getAriaDescriptor(shape: TLEmbedShape) {\n\t\tconst embedInfo = this.getEmbedDefinition(shape.props.url)\n\t\treturn embedInfo?.definition.title\n\t}\n\n\toverride hideSelectionBoundsFg(shape: TLEmbedShape) {\n\t\treturn !this.canResize(shape)\n\t}\n\toverride canEdit(shape: TLEmbedShape) {\n\t\treturn true\n\t}\n\toverride canResize(shape: TLEmbedShape) {\n\t\treturn this.getEmbedDefinition(shape.props.url)?.definition?.doesResize ?? true\n\t}\n\toverride canEditInReadonly(shape: TLEmbedShape) {\n\t\treturn true\n\t}\n\n\toverride getDefaultProps(): TLEmbedShape['props'] {\n\t\treturn {\n\t\t\tw: 300,\n\t\t\th: 300,\n\t\t\turl: '',\n\t\t}\n\t}\n\n\toverride getGeometry(shape: TLEmbedShape) {\n\t\treturn super.getGeometry(shape)\n\t}\n\n\toverride isAspectRatioLocked(shape: TLEmbedShape) {\n\t\tconst embedInfo = this.getEmbedDefinition(shape.props.url)\n\t\treturn embedInfo?.definition.isAspectRatioLocked ?? false\n\t}\n\n\toverride onResize(shape: TLEmbedShape, info: TLResizeInfo<TLEmbedShape>) {\n\t\tconst isAspectRatioLocked = this.isAspectRatioLocked(shape)\n\t\tconst embedInfo = this.getEmbedDefinition(shape.props.url)\n\t\tlet minWidth = embedInfo?.definition.minWidth ?? 200\n\t\tlet minHeight = embedInfo?.definition.minHeight ?? 200\n\t\tif (isAspectRatioLocked) {\n\t\t\t// Enforce aspect ratio\n\t\t\t// Neither the width or height can be less than 200\n\t\t\tconst aspectRatio = shape.props.w / shape.props.h\n\t\t\tif (aspectRatio > 1) {\n\t\t\t\t// Landscape\n\t\t\t\tminWidth *= aspectRatio\n\t\t\t} else {\n\t\t\t\t// Portrait\n\t\t\t\tminHeight /= aspectRatio\n\t\t\t}\n\t\t}\n\n\t\treturn resizeBox(shape, info, { minWidth, minHeight })\n\t}\n\n\toverride component(shape: TLEmbedShape) {\n\t\tconst svgExport = useSvgExportContext()\n\t\tconst { w, h, url } = shape.props\n\t\tconst isEditing = useIsEditing(shape.id)\n\t\tconst colorMode = useColorMode()\n\t\tconst dv = getDisplayValues(this, shape, colorMode)\n\n\t\tconst embedInfo = this.getEmbedDefinition(url)\n\n\t\tconst isHoveringWhileEditingSameShape = useValue(\n\t\t\t'is hovering',\n\t\t\t() => {\n\t\t\t\tconst { editingShapeId, hoveredShapeId } = this.editor.getCurrentPageState()\n\n\t\t\t\tif (editingShapeId && hoveredShapeId !== editingShapeId) {\n\t\t\t\t\tconst editingShape = this.editor.getShape(editingShapeId)\n\t\t\t\t\tif (editingShape && this.editor.isShapeOfType(editingShape, 'embed')) {\n\t\t\t\t\t\treturn true\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\treturn false\n\t\t\t},\n\t\t\t[]\n\t\t)\n\n\t\tconst pageRotation = this.editor.getShapePageTransform(shape)!.rotation()\n\n\t\tif (svgExport) {\n\t\t\t// for SVG exports, we show a blank embed\n\t\t\treturn (\n\t\t\t\t<HTMLContainer className=\"tl-embed-container\" id={shape.id}>\n\t\t\t\t\t<div\n\t\t\t\t\t\tclassName=\"tl-embed\"\n\t\t\t\t\t\tstyle={{\n\t\t\t\t\t\t\tborder: 0,\n\t\t\t\t\t\t\tboxShadow: dv.showShadow ? getRotatedBoxShadow(pageRotation) : 'none',\n\t\t\t\t\t\t\tborderRadius: embedInfo?.definition.overrideOutlineRadius ?? 8,\n\t\t\t\t\t\t\tbackground: embedInfo?.definition.backgroundColor ?? 'var(--tl-color-background)',\n\t\t\t\t\t\t\twidth: w,\n\t\t\t\t\t\t\theight: h,\n\t\t\t\t\t\t}}\n\t\t\t\t\t/>\n\t\t\t\t</HTMLContainer>\n\t\t\t)\n\t\t}\n\n\t\tconst isInteractive = isEditing || isHoveringWhileEditingSameShape\n\n\t\t// Prevent nested embedding of tldraw\n\t\tconst isIframe =\n\t\t\ttypeof window !== 'undefined' && (window !== window.top || window.self !== window.parent)\n\t\tif (isIframe && embedInfo?.definition.type === 'tldraw') return null\n\n\t\tconst sandbox = getSandboxPermissions({\n\t\t\t...embedShapePermissionDefaults,\n\t\t\t...(embedInfo\n\t\t\t\t? (embedInfo.definition.overridePermissions ?? {})\n\t\t\t\t: unknownEmbedShapePermissionOverrides),\n\t\t})\n\n\t\tif (embedInfo?.definition.type === 'github_gist') {\n\t\t\tconst idFromGistUrl = embedInfo.url.split('/').pop()\n\t\t\tif (!idFromGistUrl) throw Error('No gist id!')\n\n\t\t\t// Gist embeds use srcDoc, so we must disable allow-same-origin. Otherwise\n\t\t\t// the embedded script shares the parent's origin and can escape the sandbox.\n\t\t\tconst gistSandbox = getSandboxPermissions({\n\t\t\t\t...embedShapePermissionDefaults,\n\t\t\t\t...(embedInfo?.definition?.overridePermissions ?? {}),\n\t\t\t\t'allow-same-origin': false,\n\t\t\t})\n\n\t\t\treturn (\n\t\t\t\t<HTMLContainer className=\"tl-embed-container\" id={shape.id}>\n\t\t\t\t\t<Gist\n\t\t\t\t\t\tid={idFromGistUrl}\n\t\t\t\t\t\tsandbox={gistSandbox}\n\t\t\t\t\t\twidth={toDomPrecision(w)!}\n\t\t\t\t\t\theight={toDomPrecision(h)!}\n\t\t\t\t\t\tisInteractive={isInteractive}\n\t\t\t\t\t\tpageRotation={pageRotation}\n\t\t\t\t\t\tshowShadow={dv.showShadow}\n\t\t\t\t\t/>\n\t\t\t\t</HTMLContainer>\n\t\t\t)\n\t\t}\n\n\t\tconst iframeSrc = embedInfo?.embedUrl ?? url\n\n\t\treturn (\n\t\t\t<HTMLContainer className=\"tl-embed-container\" id={shape.id}>\n\t\t\t\t{iframeSrc ? (\n\t\t\t\t\t<iframe\n\t\t\t\t\t\tclassName=\"tl-embed\"\n\t\t\t\t\t\tsandbox={sandbox}\n\t\t\t\t\t\tsrc={iframeSrc}\n\t\t\t\t\t\twidth={toDomPrecision(w)}\n\t\t\t\t\t\theight={toDomPrecision(h)}\n\t\t\t\t\t\tdraggable={false}\n\t\t\t\t\t\t// eslint-disable-next-line @typescript-eslint/no-deprecated\n\t\t\t\t\t\tframeBorder=\"0\"\n\t\t\t\t\t\treferrerPolicy=\"strict-origin-when-cross-origin\"\n\t\t\t\t\t\ttabIndex={isEditing ? 0 : -1}\n\t\t\t\t\t\tallowFullScreen\n\t\t\t\t\t\tstyle={{\n\t\t\t\t\t\t\tborder: 0,\n\t\t\t\t\t\t\tpointerEvents: isInteractive ? 'auto' : 'none',\n\t\t\t\t\t\t\t// Fix for safari <https://stackoverflow.com/a/49150908>\n\t\t\t\t\t\t\tzIndex: isInteractive ? '' : '-1',\n\t\t\t\t\t\t\tboxShadow: dv.showShadow ? getRotatedBoxShadow(pageRotation) : 'none',\n\t\t\t\t\t\t\tborderRadius: embedInfo?.definition?.overrideOutlineRadius ?? 8,\n\t\t\t\t\t\t\tbackground: embedInfo?.definition?.backgroundColor,\n\t\t\t\t\t\t}}\n\t\t\t\t\t/>\n\t\t\t\t) : (\n\t\t\t\t\t<BookmarkShapeComponent\n\t\t\t\t\t\turl={url}\n\t\t\t\t\t\th={h}\n\t\t\t\t\t\trotation={pageRotation}\n\t\t\t\t\t\tassetId={null}\n\t\t\t\t\t\tshowImageContainer={false}\n\t\t\t\t\t/>\n\t\t\t\t)}\n\t\t\t</HTMLContainer>\n\t\t)\n\t}\n\n\toverride getIndicatorPath(shape: TLEmbedShape): Path2D {\n\t\tconst path = new Path2D()\n\t\tpath.rect(0, 0, shape.props.w, shape.props.h)\n\t\treturn path\n\t}\n\n\toverride getInterpolatedProps(\n\t\tstartShape: TLEmbedShape,\n\t\tendShape: TLEmbedShape,\n\t\tt: number\n\t): TLEmbedShapeProps {\n\t\treturn {\n\t\t\t...(t > 0.5 ? endShape.props : startShape.props),\n\t\t\tw: lerp(startShape.props.w, endShape.props.w, t),\n\t\t\th: lerp(startShape.props.h, endShape.props.h, t),\n\t\t}\n\t}\n}\n\nfunction Gist({\n\tid,\n\tsandbox,\n\tisInteractive,\n\twidth,\n\theight,\n\tstyle,\n\tpageRotation,\n\tshowShadow,\n}: {\n\tid: string\n\tsandbox: string\n\tisInteractive: boolean\n\twidth: number\n\theight: number\n\tpageRotation: number\n\tshowShadow: boolean\n\tstyle?: React.CSSProperties\n}) {\n\t// Security warning:\n\t// Gists allow adding .json extensions to the URL which return JSONP.\n\t// Furthermore, the JSONP can include callbacks that execute arbitrary JavaScript.\n\t// It _is_ sandboxed by the iframe but we still want to disable it nonetheless.\n\t// We restrict the id to only allow hexdecimal characters to prevent this.\n\t// Read more:\n\t// https://github.com/bhaveshk90/Content-Security-Policy-CSP-Bypass-Techniques\n\t// https://github.com/renniepak/CSPBypass\n\tif (!id.match(/^[0-9a-f]+$/)) throw Error('No gist id!')\n\n\treturn (\n\t\t<iframe\n\t\t\tclassName=\"tl-embed\"\n\t\t\tsandbox={sandbox}\n\t\t\tdraggable={false}\n\t\t\twidth={toDomPrecision(width)}\n\t\t\theight={toDomPrecision(height)}\n\t\t\t// eslint-disable-next-line @typescript-eslint/no-deprecated\n\t\t\tframeBorder=\"0\"\n\t\t\t// eslint-disable-next-line @typescript-eslint/no-deprecated\n\t\t\tscrolling=\"no\"\n\t\t\treferrerPolicy=\"strict-origin-when-cross-origin\"\n\t\t\ttabIndex={isInteractive ? 0 : -1}\n\t\t\tstyle={{\n\t\t\t\t...style,\n\t\t\t\tpointerEvents: isInteractive ? 'all' : 'none',\n\t\t\t\t// Fix for safari <https://stackoverflow.com/a/49150908>\n\t\t\t\tzIndex: isInteractive ? '' : '-1',\n\t\t\t\tboxShadow: showShadow ? getRotatedBoxShadow(pageRotation) : 'none',\n\t\t\t}}\n\t\t\tsrcDoc={`\n\t\t\t<html>\n\t\t\t\t<head>\n\t\t\t\t\t<base target=\"_blank\">\n\t\t\t\t</head>\n\t\t\t\t<body>\n\t\t\t\t\t<script src=${`https://gist.github.com/${id}.js`}></script>\n\t\t\t\t\t<style type=\"text/css\">\n\t\t\t\t\t\t* { margin: 0px; }\n\t\t\t\t\t\ttable { height: 100%; background-color: red; }\n\t\t\t\t\t\t.gist { background-color: none; height: 100%; }\n\t\t\t\t\t\t.gist .gist-file { height: calc(100vh - 2px); padding: 0px; display: grid; grid-template-rows: 1fr auto; }\n\t\t\t\t\t</style>\n\t\t\t\t</body>\n\t\t\t</html>`}\n\t\t/>\n\t)\n}\n"],
|
|
5
|
-
"mappings": "
|
|
4
|
+
"sourcesContent": ["/* eslint-disable react-hooks/rules-of-hooks */\n\nimport {\n\tBaseBoxShapeUtil,\n\tHTMLContainer,\n\tTLEmbedShape,\n\tTLEmbedShapeProps,\n\tTLResizeInfo,\n\tembedShapeMigrations,\n\tembedShapeProps,\n\tlerp,\n\tresizeBox,\n\ttoDomPrecision,\n\tuseColorMode,\n\tuseIsEditing,\n\tuseSvgExportContext,\n\tuseValue,\n} from '@tldraw/editor'\nimport {\n\tDEFAULT_EMBED_DEFINITIONS,\n\tDefaultEmbedConfig,\n\tTLEmbedDefinition,\n\tTLEmbedShapePermissions,\n\tembedShapePermissionDefaults,\n\tunknownEmbedShapePermissionOverrides,\n} from '../../defaultEmbedDefinitions'\nimport { TLEmbedResult, getEmbedInfo } from '../../utils/embeds/embeds'\nimport { BookmarkShapeComponent } from '../bookmark/BookmarkShapeUtil'\nimport { ShapeOptionsWithDisplayValues, getDisplayValues } from '../shared/getDisplayValues'\nimport { getRotatedBoxShadow } from '../shared/rotated-box-shadow'\n\n/** @public */\nexport interface EmbedShapeUtilDisplayValues {\n\tshowShadow: boolean\n}\n\n/** @public */\nexport interface EmbedShapeOptions extends ShapeOptionsWithDisplayValues<\n\tTLEmbedShape,\n\tEmbedShapeUtilDisplayValues\n> {\n\t/** The embed definitions to use for this shape util. */\n\treadonly embedDefinitions: readonly TLEmbedDefinition[]\n\t/**\n\t * Per-embed configuration, keyed by embed type. Passed to each definition's `toEmbedUrl` when\n\t * building its embed URL \u2014 for example, an API key for the default Google Maps embed:\n\t *\n\t * ```ts\n\t * EmbedShapeUtil.configure({ embedConfig: { google_maps: { apiKey: '...' } } })\n\t * ```\n\t */\n\treadonly embedConfig?: DefaultEmbedConfig & Record<string, unknown>\n}\n\nconst getSandboxPermissions = (permissions: TLEmbedShapePermissions) => {\n\treturn Object.entries(permissions)\n\t\t.filter(([_perm, isEnabled]) => isEnabled)\n\t\t.map(([perm]) => perm)\n\t\t.join(' ')\n}\n\n/** @public */\nexport class EmbedShapeUtil extends BaseBoxShapeUtil<TLEmbedShape> {\n\tstatic override type = 'embed' as const\n\tstatic override props = embedShapeProps\n\tstatic override migrations = embedShapeMigrations\n\n\toverride options: EmbedShapeOptions = {\n\t\tembedDefinitions: DEFAULT_EMBED_DEFINITIONS,\n\t\tembedConfig: {},\n\t\tgetDefaultDisplayValues(): EmbedShapeUtilDisplayValues {\n\t\t\treturn {\n\t\t\t\tshowShadow: true,\n\t\t\t}\n\t\t},\n\t\tgetCustomDisplayValues(): Partial<EmbedShapeUtilDisplayValues> {\n\t\t\treturn {}\n\t\t},\n\t}\n\n\toverride canEditWhileLocked(shape: TLEmbedShape) {\n\t\tconst result = this.getEmbedDefinition(shape.props.url)\n\t\tif (!result) return true\n\t\treturn result.definition.canEditWhileLocked ?? true\n\t}\n\n\tprivate static legacyEmbedDefinitions: readonly TLEmbedDefinition[] | null = null\n\n\t/** @deprecated - Use `EmbedShapeUtil.configure({ embedDefinitions: [...] })` instead. */\n\tstatic setEmbedDefinitions(embedDefinitions: readonly TLEmbedDefinition[]) {\n\t\tEmbedShapeUtil.legacyEmbedDefinitions = embedDefinitions\n\t}\n\n\tprivate getEmbedDefs(): readonly TLEmbedDefinition[] {\n\t\treturn EmbedShapeUtil.legacyEmbedDefinitions ?? this.options.embedDefinitions\n\t}\n\n\tgetEmbedDefinitions(): readonly TLEmbedDefinition[] {\n\t\treturn this.getEmbedDefs()\n\t}\n\n\tgetEmbedDefinition(url: string): TLEmbedResult {\n\t\treturn getEmbedInfo(this.getEmbedDefs(), url, this.options.embedConfig)\n\t}\n\n\toverride getText(shape: TLEmbedShape) {\n\t\treturn shape.props.url\n\t}\n\n\toverride getAriaDescriptor(shape: TLEmbedShape) {\n\t\tconst embedInfo = this.getEmbedDefinition(shape.props.url)\n\t\treturn embedInfo?.definition.title\n\t}\n\n\toverride hideSelectionBoundsFg(shape: TLEmbedShape) {\n\t\treturn !this.canResize(shape)\n\t}\n\toverride canEdit(shape: TLEmbedShape) {\n\t\treturn true\n\t}\n\toverride canResize(shape: TLEmbedShape) {\n\t\treturn this.getEmbedDefinition(shape.props.url)?.definition?.doesResize ?? true\n\t}\n\toverride canEditInReadonly(shape: TLEmbedShape) {\n\t\treturn true\n\t}\n\n\toverride getDefaultProps(): TLEmbedShape['props'] {\n\t\treturn {\n\t\t\tw: 300,\n\t\t\th: 300,\n\t\t\turl: '',\n\t\t}\n\t}\n\n\toverride getGeometry(shape: TLEmbedShape) {\n\t\treturn super.getGeometry(shape)\n\t}\n\n\toverride isAspectRatioLocked(shape: TLEmbedShape) {\n\t\tconst embedInfo = this.getEmbedDefinition(shape.props.url)\n\t\treturn embedInfo?.definition.isAspectRatioLocked ?? false\n\t}\n\n\toverride onResize(shape: TLEmbedShape, info: TLResizeInfo<TLEmbedShape>) {\n\t\tconst isAspectRatioLocked = this.isAspectRatioLocked(shape)\n\t\tconst embedInfo = this.getEmbedDefinition(shape.props.url)\n\t\tlet minWidth = embedInfo?.definition.minWidth ?? 200\n\t\tlet minHeight = embedInfo?.definition.minHeight ?? 200\n\t\tif (isAspectRatioLocked) {\n\t\t\t// Enforce aspect ratio\n\t\t\t// Neither the width or height can be less than 200\n\t\t\tconst aspectRatio = shape.props.w / shape.props.h\n\t\t\tif (aspectRatio > 1) {\n\t\t\t\t// Landscape\n\t\t\t\tminWidth *= aspectRatio\n\t\t\t} else {\n\t\t\t\t// Portrait\n\t\t\t\tminHeight /= aspectRatio\n\t\t\t}\n\t\t}\n\n\t\treturn resizeBox(shape, info, { minWidth, minHeight })\n\t}\n\n\toverride component(shape: TLEmbedShape) {\n\t\tconst svgExport = useSvgExportContext()\n\t\tconst { w, h, url } = shape.props\n\t\tconst isEditing = useIsEditing(shape.id)\n\t\tconst colorMode = useColorMode()\n\t\tconst dv = getDisplayValues(this, shape, colorMode)\n\n\t\tconst embedInfo = this.getEmbedDefinition(url)\n\n\t\tconst isHoveringWhileEditingSameShape = useValue(\n\t\t\t'is hovering',\n\t\t\t() => {\n\t\t\t\tconst { editingShapeId, hoveredShapeId } = this.editor.getCurrentPageState()\n\n\t\t\t\tif (editingShapeId && hoveredShapeId !== editingShapeId) {\n\t\t\t\t\tconst editingShape = this.editor.getShape(editingShapeId)\n\t\t\t\t\tif (editingShape && this.editor.isShapeOfType(editingShape, 'embed')) {\n\t\t\t\t\t\treturn true\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\treturn false\n\t\t\t},\n\t\t\t[]\n\t\t)\n\n\t\tconst pageRotation = this.editor.getShapePageTransform(shape)!.rotation()\n\n\t\tif (svgExport) {\n\t\t\t// for SVG exports, we show a blank embed\n\t\t\treturn (\n\t\t\t\t<HTMLContainer className=\"tl-embed-container\" id={shape.id}>\n\t\t\t\t\t<div\n\t\t\t\t\t\tclassName=\"tl-embed\"\n\t\t\t\t\t\tstyle={{\n\t\t\t\t\t\t\tborder: 0,\n\t\t\t\t\t\t\tboxShadow: dv.showShadow ? getRotatedBoxShadow(pageRotation) : 'none',\n\t\t\t\t\t\t\tborderRadius: embedInfo?.definition.overrideOutlineRadius ?? 8,\n\t\t\t\t\t\t\tbackground: embedInfo?.definition.backgroundColor ?? 'var(--tl-color-background)',\n\t\t\t\t\t\t\twidth: w,\n\t\t\t\t\t\t\theight: h,\n\t\t\t\t\t\t}}\n\t\t\t\t\t/>\n\t\t\t\t</HTMLContainer>\n\t\t\t)\n\t\t}\n\n\t\tconst isInteractive = isEditing || isHoveringWhileEditingSameShape\n\n\t\t// Prevent nested embedding of tldraw\n\t\tconst isIframe =\n\t\t\ttypeof window !== 'undefined' && (window !== window.top || window.self !== window.parent)\n\t\tif (isIframe && embedInfo?.definition.type === 'tldraw') return null\n\n\t\tconst sandbox = getSandboxPermissions({\n\t\t\t...embedShapePermissionDefaults,\n\t\t\t...(embedInfo\n\t\t\t\t? (embedInfo.definition.overridePermissions ?? {})\n\t\t\t\t: unknownEmbedShapePermissionOverrides),\n\t\t})\n\n\t\tif (embedInfo?.definition.type === 'github_gist') {\n\t\t\tconst idFromGistUrl = embedInfo.url.split('/').pop()\n\t\t\tif (!idFromGistUrl) throw Error('No gist id!')\n\n\t\t\t// Gist embeds use srcDoc, so we must disable allow-same-origin. Otherwise\n\t\t\t// the embedded script shares the parent's origin and can escape the sandbox.\n\t\t\tconst gistSandbox = getSandboxPermissions({\n\t\t\t\t...embedShapePermissionDefaults,\n\t\t\t\t...(embedInfo?.definition?.overridePermissions ?? {}),\n\t\t\t\t'allow-same-origin': false,\n\t\t\t})\n\n\t\t\treturn (\n\t\t\t\t<HTMLContainer className=\"tl-embed-container\" id={shape.id}>\n\t\t\t\t\t<Gist\n\t\t\t\t\t\tid={idFromGistUrl}\n\t\t\t\t\t\tsandbox={gistSandbox}\n\t\t\t\t\t\twidth={toDomPrecision(w)!}\n\t\t\t\t\t\theight={toDomPrecision(h)!}\n\t\t\t\t\t\tisInteractive={isInteractive}\n\t\t\t\t\t\tpageRotation={pageRotation}\n\t\t\t\t\t\tshowShadow={dv.showShadow}\n\t\t\t\t\t/>\n\t\t\t\t</HTMLContainer>\n\t\t\t)\n\t\t}\n\n\t\tconst iframeSrc = embedInfo?.embedUrl ?? url\n\n\t\treturn (\n\t\t\t<HTMLContainer className=\"tl-embed-container\" id={shape.id}>\n\t\t\t\t{iframeSrc ? (\n\t\t\t\t\t<iframe\n\t\t\t\t\t\tclassName=\"tl-embed\"\n\t\t\t\t\t\tsandbox={sandbox}\n\t\t\t\t\t\tsrc={iframeSrc}\n\t\t\t\t\t\twidth={toDomPrecision(w)}\n\t\t\t\t\t\theight={toDomPrecision(h)}\n\t\t\t\t\t\tdraggable={false}\n\t\t\t\t\t\t// eslint-disable-next-line @typescript-eslint/no-deprecated\n\t\t\t\t\t\tframeBorder=\"0\"\n\t\t\t\t\t\treferrerPolicy=\"strict-origin-when-cross-origin\"\n\t\t\t\t\t\ttabIndex={isEditing ? 0 : -1}\n\t\t\t\t\t\tallowFullScreen\n\t\t\t\t\t\tstyle={{\n\t\t\t\t\t\t\tborder: 0,\n\t\t\t\t\t\t\tpointerEvents: isInteractive ? 'auto' : 'none',\n\t\t\t\t\t\t\t// Fix for safari <https://stackoverflow.com/a/49150908>\n\t\t\t\t\t\t\tzIndex: isInteractive ? '' : '-1',\n\t\t\t\t\t\t\tboxShadow: dv.showShadow ? getRotatedBoxShadow(pageRotation) : 'none',\n\t\t\t\t\t\t\tborderRadius: embedInfo?.definition?.overrideOutlineRadius ?? 8,\n\t\t\t\t\t\t\tbackground: embedInfo?.definition?.backgroundColor,\n\t\t\t\t\t\t}}\n\t\t\t\t\t/>\n\t\t\t\t) : (\n\t\t\t\t\t<BookmarkShapeComponent\n\t\t\t\t\t\turl={url}\n\t\t\t\t\t\th={h}\n\t\t\t\t\t\trotation={pageRotation}\n\t\t\t\t\t\tassetId={null}\n\t\t\t\t\t\tshowImageContainer={false}\n\t\t\t\t\t/>\n\t\t\t\t)}\n\t\t\t</HTMLContainer>\n\t\t)\n\t}\n\n\toverride getIndicatorPath(shape: TLEmbedShape): Path2D {\n\t\tconst path = new Path2D()\n\t\tpath.rect(0, 0, shape.props.w, shape.props.h)\n\t\treturn path\n\t}\n\n\toverride getInterpolatedProps(\n\t\tstartShape: TLEmbedShape,\n\t\tendShape: TLEmbedShape,\n\t\tt: number\n\t): TLEmbedShapeProps {\n\t\treturn {\n\t\t\t...(t > 0.5 ? endShape.props : startShape.props),\n\t\t\tw: lerp(startShape.props.w, endShape.props.w, t),\n\t\t\th: lerp(startShape.props.h, endShape.props.h, t),\n\t\t}\n\t}\n}\n\nfunction Gist({\n\tid,\n\tsandbox,\n\tisInteractive,\n\twidth,\n\theight,\n\tstyle,\n\tpageRotation,\n\tshowShadow,\n}: {\n\tid: string\n\tsandbox: string\n\tisInteractive: boolean\n\twidth: number\n\theight: number\n\tpageRotation: number\n\tshowShadow: boolean\n\tstyle?: React.CSSProperties\n}) {\n\t// Security warning:\n\t// Gists allow adding .json extensions to the URL which return JSONP.\n\t// Furthermore, the JSONP can include callbacks that execute arbitrary JavaScript.\n\t// It _is_ sandboxed by the iframe but we still want to disable it nonetheless.\n\t// We restrict the id to only allow hexdecimal characters to prevent this.\n\t// Read more:\n\t// https://github.com/bhaveshk90/Content-Security-Policy-CSP-Bypass-Techniques\n\t// https://github.com/renniepak/CSPBypass\n\tif (!id.match(/^[0-9a-f]+$/)) throw Error('No gist id!')\n\n\treturn (\n\t\t<iframe\n\t\t\tclassName=\"tl-embed\"\n\t\t\tsandbox={sandbox}\n\t\t\tdraggable={false}\n\t\t\twidth={toDomPrecision(width)}\n\t\t\theight={toDomPrecision(height)}\n\t\t\t// eslint-disable-next-line @typescript-eslint/no-deprecated\n\t\t\tframeBorder=\"0\"\n\t\t\t// eslint-disable-next-line @typescript-eslint/no-deprecated\n\t\t\tscrolling=\"no\"\n\t\t\treferrerPolicy=\"strict-origin-when-cross-origin\"\n\t\t\ttabIndex={isInteractive ? 0 : -1}\n\t\t\tstyle={{\n\t\t\t\t...style,\n\t\t\t\tpointerEvents: isInteractive ? 'all' : 'none',\n\t\t\t\t// Fix for safari <https://stackoverflow.com/a/49150908>\n\t\t\t\tzIndex: isInteractive ? '' : '-1',\n\t\t\t\tboxShadow: showShadow ? getRotatedBoxShadow(pageRotation) : 'none',\n\t\t\t}}\n\t\t\tsrcDoc={`\n\t\t\t<html>\n\t\t\t\t<head>\n\t\t\t\t\t<base target=\"_blank\">\n\t\t\t\t</head>\n\t\t\t\t<body>\n\t\t\t\t\t<script src=${`https://gist.github.com/${id}.js`}></script>\n\t\t\t\t\t<style type=\"text/css\">\n\t\t\t\t\t\t* { margin: 0px; }\n\t\t\t\t\t\ttable { height: 100%; background-color: red; }\n\t\t\t\t\t\t.gist { background-color: none; height: 100%; }\n\t\t\t\t\t\t.gist .gist-file { height: calc(100vh - 2px); padding: 0px; display: grid; grid-template-rows: 1fr auto; }\n\t\t\t\t\t</style>\n\t\t\t\t</body>\n\t\t\t</html>`}\n\t\t/>\n\t)\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -5,23 +5,7 @@ class FrameShapeTool extends BaseBoxShapeTool {
|
|
|
5
5
|
shapeType = "frame";
|
|
6
6
|
onCreate(shape) {
|
|
7
7
|
if (!shape) return;
|
|
8
|
-
|
|
9
|
-
const shapesToAddToFrame = [];
|
|
10
|
-
const ancestorIds = this.editor.getShapeAncestors(shape).map((shape2) => shape2.id);
|
|
11
|
-
this.editor.getSortedChildIdsForParent(shape.parentId).map((siblingShapeId) => {
|
|
12
|
-
const siblingShape = this.editor.getShape(siblingShapeId);
|
|
13
|
-
if (!siblingShape) return;
|
|
14
|
-
if (siblingShape.id === shape.id) return;
|
|
15
|
-
if (siblingShape.isLocked) return;
|
|
16
|
-
const pageShapeBounds = this.editor.getShapePageBounds(siblingShape);
|
|
17
|
-
if (!pageShapeBounds) return;
|
|
18
|
-
if (bounds.contains(pageShapeBounds)) {
|
|
19
|
-
if (canEnclose(siblingShape, ancestorIds, shape)) {
|
|
20
|
-
shapesToAddToFrame.push(siblingShape.id);
|
|
21
|
-
}
|
|
22
|
-
}
|
|
23
|
-
});
|
|
24
|
-
this.editor.reparentShapes(shapesToAddToFrame, shape.id);
|
|
8
|
+
this.editor.reparentShapes(getEnclosedShapeIds(this.editor, shape), shape.id);
|
|
25
9
|
if (this.editor.getInstanceState().isToolLocked) {
|
|
26
10
|
this.editor.setCurrentTool("frame");
|
|
27
11
|
} else {
|
|
@@ -29,6 +13,26 @@ class FrameShapeTool extends BaseBoxShapeTool {
|
|
|
29
13
|
}
|
|
30
14
|
}
|
|
31
15
|
}
|
|
16
|
+
function getEnclosedShapeIds(editor, shape) {
|
|
17
|
+
const bounds = editor.getShapePageBounds(shape);
|
|
18
|
+
if (!bounds) return [];
|
|
19
|
+
const enclosedShapeIds = [];
|
|
20
|
+
const ancestorIds = editor.getShapeAncestors(shape).map((shape2) => shape2.id);
|
|
21
|
+
editor.getSortedChildIdsForParent(shape.parentId).map((siblingShapeId) => {
|
|
22
|
+
const siblingShape = editor.getShape(siblingShapeId);
|
|
23
|
+
if (!siblingShape) return;
|
|
24
|
+
if (siblingShape.id === shape.id) return;
|
|
25
|
+
if (siblingShape.isLocked) return;
|
|
26
|
+
const pageShapeBounds = editor.getShapePageBounds(siblingShape);
|
|
27
|
+
if (!pageShapeBounds) return;
|
|
28
|
+
if (bounds.contains(pageShapeBounds)) {
|
|
29
|
+
if (canEnclose(siblingShape, ancestorIds, shape)) {
|
|
30
|
+
enclosedShapeIds.push(siblingShape.id);
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
});
|
|
34
|
+
return enclosedShapeIds;
|
|
35
|
+
}
|
|
32
36
|
function canEnclose(shape, ancestorIds, frame) {
|
|
33
37
|
if (ancestorIds.includes(shape.id)) {
|
|
34
38
|
return false;
|
|
@@ -39,6 +43,7 @@ function canEnclose(shape, ancestorIds, frame) {
|
|
|
39
43
|
return false;
|
|
40
44
|
}
|
|
41
45
|
export {
|
|
42
|
-
FrameShapeTool
|
|
46
|
+
FrameShapeTool,
|
|
47
|
+
getEnclosedShapeIds
|
|
43
48
|
};
|
|
44
49
|
//# sourceMappingURL=FrameShapeTool.mjs.map
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../../src/lib/shapes/frame/FrameShapeTool.ts"],
|
|
4
|
-
"sourcesContent": ["import { BaseBoxShapeTool, TLShape, TLShapeId } from '@tldraw/editor'\n\n/** @public */\nexport class FrameShapeTool extends BaseBoxShapeTool {\n\tstatic override id = 'frame'\n\tstatic override initial = 'idle'\n\toverride shapeType = 'frame' as const\n\n\toverride onCreate(shape: TLShape | null): void {\n\t\tif (!shape) return\n\n\t\tconst bounds =
|
|
5
|
-
"mappings": "AAAA,SAAS,
|
|
4
|
+
"sourcesContent": ["import { BaseBoxShapeTool, Editor, TLShape, TLShapeId } from '@tldraw/editor'\n\n/** @public */\nexport class FrameShapeTool extends BaseBoxShapeTool {\n\tstatic override id = 'frame'\n\tstatic override initial = 'idle'\n\toverride shapeType = 'frame' as const\n\n\toverride onCreate(shape: TLShape | null): void {\n\t\tif (!shape) return\n\n\t\tthis.editor.reparentShapes(getEnclosedShapeIds(this.editor, shape), shape.id)\n\n\t\tif (this.editor.getInstanceState().isToolLocked) {\n\t\t\tthis.editor.setCurrentTool('frame')\n\t\t} else {\n\t\t\tthis.editor.setCurrentTool('select.idle')\n\t\t}\n\t}\n}\n\n/**\n * Get the ids of the sibling shapes that a frame would enclose at its current page bounds.\n *\n * @internal\n */\nexport function getEnclosedShapeIds(editor: Editor, shape: TLShape): TLShapeId[] {\n\tconst bounds = editor.getShapePageBounds(shape)\n\tif (!bounds) return []\n\n\tconst enclosedShapeIds: TLShapeId[] = []\n\tconst ancestorIds = editor.getShapeAncestors(shape).map((shape) => shape.id)\n\n\teditor.getSortedChildIdsForParent(shape.parentId).map((siblingShapeId) => {\n\t\tconst siblingShape = editor.getShape(siblingShapeId)\n\t\tif (!siblingShape) return\n\t\t// We don't want to frame the frame itself\n\t\tif (siblingShape.id === shape.id) return\n\t\tif (siblingShape.isLocked) return\n\n\t\tconst pageShapeBounds = editor.getShapePageBounds(siblingShape)\n\t\tif (!pageShapeBounds) return\n\n\t\t// Frame shape encloses page shape\n\t\tif (bounds.contains(pageShapeBounds)) {\n\t\t\tif (canEnclose(siblingShape, ancestorIds, shape)) {\n\t\t\t\tenclosedShapeIds.push(siblingShape.id)\n\t\t\t}\n\t\t}\n\t})\n\n\treturn enclosedShapeIds\n}\n\n/** @internal */\nfunction canEnclose(shape: TLShape, ancestorIds: TLShapeId[], frame: TLShape): boolean {\n\t// We don't want to pull in shapes that are ancestors of the frame (can create a cycle)\n\tif (ancestorIds.includes(shape.id)) {\n\t\treturn false\n\t}\n\t// We only want to pull in shapes that are siblings of the frame\n\tif (shape.parentId === frame.parentId) {\n\t\treturn true\n\t}\n\treturn false\n}\n"],
|
|
5
|
+
"mappings": "AAAA,SAAS,wBAAoD;AAGtD,MAAM,uBAAuB,iBAAiB;AAAA,EACpD,OAAgB,KAAK;AAAA,EACrB,OAAgB,UAAU;AAAA,EACjB,YAAY;AAAA,EAEZ,SAAS,OAA6B;AAC9C,QAAI,CAAC,MAAO;AAEZ,SAAK,OAAO,eAAe,oBAAoB,KAAK,QAAQ,KAAK,GAAG,MAAM,EAAE;AAE5E,QAAI,KAAK,OAAO,iBAAiB,EAAE,cAAc;AAChD,WAAK,OAAO,eAAe,OAAO;AAAA,IACnC,OAAO;AACN,WAAK,OAAO,eAAe,aAAa;AAAA,IACzC;AAAA,EACD;AACD;AAOO,SAAS,oBAAoB,QAAgB,OAA6B;AAChF,QAAM,SAAS,OAAO,mBAAmB,KAAK;AAC9C,MAAI,CAAC,OAAQ,QAAO,CAAC;AAErB,QAAM,mBAAgC,CAAC;AACvC,QAAM,cAAc,OAAO,kBAAkB,KAAK,EAAE,IAAI,CAACA,WAAUA,OAAM,EAAE;AAE3E,SAAO,2BAA2B,MAAM,QAAQ,EAAE,IAAI,CAAC,mBAAmB;AACzE,UAAM,eAAe,OAAO,SAAS,cAAc;AACnD,QAAI,CAAC,aAAc;AAEnB,QAAI,aAAa,OAAO,MAAM,GAAI;AAClC,QAAI,aAAa,SAAU;AAE3B,UAAM,kBAAkB,OAAO,mBAAmB,YAAY;AAC9D,QAAI,CAAC,gBAAiB;AAGtB,QAAI,OAAO,SAAS,eAAe,GAAG;AACrC,UAAI,WAAW,cAAc,aAAa,KAAK,GAAG;AACjD,yBAAiB,KAAK,aAAa,EAAE;AAAA,MACtC;AAAA,IACD;AAAA,EACD,CAAC;AAED,SAAO;AACR;AAGA,SAAS,WAAW,OAAgB,aAA0B,OAAyB;AAEtF,MAAI,YAAY,SAAS,MAAM,EAAE,GAAG;AACnC,WAAO;AAAA,EACR;AAEA,MAAI,MAAM,aAAa,MAAM,UAAU;AACtC,WAAO;AAAA,EACR;AACA,SAAO;AACR;",
|
|
6
6
|
"names": ["shape"]
|
|
7
7
|
}
|
|
@@ -18,6 +18,7 @@ import {
|
|
|
18
18
|
getFontsFromRichText,
|
|
19
19
|
isEqual,
|
|
20
20
|
lerp,
|
|
21
|
+
resolveLineHeightPx,
|
|
21
22
|
toRichText,
|
|
22
23
|
useColorMode,
|
|
23
24
|
useValue
|
|
@@ -169,7 +170,7 @@ class GeoShapeUtil extends BaseBoxShapeUtil {
|
|
|
169
170
|
const unscaledLabelSize = isEmptyLabel ? GEO_SHAPE_EMPTY_LABEL_SIZE : this.getUnscaledLabelSize(shape);
|
|
170
171
|
const unscaledMinWidth = Math.min(100, unscaledShapeW / 2);
|
|
171
172
|
const unscaledMinHeight = Math.min(
|
|
172
|
-
dv.labelFontSize
|
|
173
|
+
resolveLineHeightPx(dv.labelFontSize, dv.labelLineHeight) + dv.labelPadding * 2,
|
|
173
174
|
unscaledShapeH / 2
|
|
174
175
|
);
|
|
175
176
|
const unscaledLabelW = Math.min(
|