tldraw 3.16.0-canary.dfdf6b7de8c2 → 3.16.0-canary.e1d5c8aeb399
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist-cjs/index.d.ts +323 -106
- package/dist-cjs/index.js +45 -14
- package/dist-cjs/index.js.map +2 -2
- package/dist-cjs/lib/Tldraw.js +12 -2
- package/dist-cjs/lib/Tldraw.js.map +2 -2
- package/dist-cjs/lib/canvas/TldrawScribble.js +1 -1
- package/dist-cjs/lib/canvas/TldrawScribble.js.map +2 -2
- package/dist-cjs/lib/defaultExternalContentHandlers.js +5 -4
- package/dist-cjs/lib/defaultExternalContentHandlers.js.map +2 -2
- package/dist-cjs/lib/shapes/arrow/ArrowShapeUtil.js +3 -3
- package/dist-cjs/lib/shapes/arrow/ArrowShapeUtil.js.map +2 -2
- package/dist-cjs/lib/shapes/arrow/arrowLabel.js +6 -0
- package/dist-cjs/lib/shapes/arrow/arrowLabel.js.map +3 -3
- package/dist-cjs/lib/shapes/arrow/arrowTargetState.js +1 -1
- package/dist-cjs/lib/shapes/arrow/arrowTargetState.js.map +2 -2
- package/dist-cjs/lib/shapes/arrow/elbow/ElbowArrowDebug.js +3 -3
- package/dist-cjs/lib/shapes/arrow/elbow/ElbowArrowDebug.js.map +1 -1
- package/dist-cjs/lib/shapes/draw/DrawShapeUtil.js +3 -3
- package/dist-cjs/lib/shapes/draw/DrawShapeUtil.js.map +2 -2
- package/dist-cjs/lib/shapes/embed/EmbedShapeUtil.js +1 -1
- package/dist-cjs/lib/shapes/embed/EmbedShapeUtil.js.map +1 -1
- package/dist-cjs/lib/shapes/frame/FrameShapeUtil.js +20 -13
- package/dist-cjs/lib/shapes/frame/FrameShapeUtil.js.map +2 -2
- package/dist-cjs/lib/shapes/frame/components/FrameHeading.js +1 -1
- package/dist-cjs/lib/shapes/frame/components/FrameHeading.js.map +2 -2
- package/dist-cjs/lib/shapes/geo/GeoShapeUtil.js +3 -2
- package/dist-cjs/lib/shapes/geo/GeoShapeUtil.js.map +2 -2
- package/dist-cjs/lib/shapes/geo/components/GeoShapeBody.js +2 -1
- package/dist-cjs/lib/shapes/geo/components/GeoShapeBody.js.map +2 -2
- package/dist-cjs/lib/shapes/highlight/HighlightShapeUtil.js +5 -1
- package/dist-cjs/lib/shapes/highlight/HighlightShapeUtil.js.map +2 -2
- package/dist-cjs/lib/shapes/image/ImageShapeUtil.js +6 -3
- package/dist-cjs/lib/shapes/image/ImageShapeUtil.js.map +2 -2
- package/dist-cjs/lib/shapes/line/LineShapeUtil.js +5 -1
- package/dist-cjs/lib/shapes/line/LineShapeUtil.js.map +2 -2
- package/dist-cjs/lib/shapes/note/NoteShapeUtil.js +6 -5
- package/dist-cjs/lib/shapes/note/NoteShapeUtil.js.map +2 -2
- package/dist-cjs/lib/shapes/shared/PlainTextLabel.js +1 -3
- package/dist-cjs/lib/shapes/shared/PlainTextLabel.js.map +2 -2
- package/dist-cjs/lib/shapes/shared/ShapeFill.js +4 -4
- package/dist-cjs/lib/shapes/shared/ShapeFill.js.map +2 -2
- package/dist-cjs/lib/shapes/shared/freehand/svg.js.map +2 -2
- package/dist-cjs/lib/shapes/shared/useEditablePlainText.js +0 -2
- package/dist-cjs/lib/shapes/shared/useEditablePlainText.js.map +2 -2
- package/dist-cjs/lib/shapes/shared/useImageOrVideoAsset.js +0 -2
- package/dist-cjs/lib/shapes/shared/useImageOrVideoAsset.js.map +2 -2
- package/dist-cjs/lib/shapes/shared/usePrefersReducedMotion.js +10 -1
- package/dist-cjs/lib/shapes/shared/usePrefersReducedMotion.js.map +2 -2
- package/dist-cjs/lib/shapes/text/TextShapeUtil.js +2 -2
- package/dist-cjs/lib/shapes/text/TextShapeUtil.js.map +2 -2
- package/dist-cjs/lib/shapes/video/VideoShapeUtil.js +3 -3
- package/dist-cjs/lib/shapes/video/VideoShapeUtil.js.map +1 -1
- package/dist-cjs/lib/tools/EraserTool/childStates/Erasing.js +25 -1
- package/dist-cjs/lib/tools/EraserTool/childStates/Erasing.js.map +2 -2
- package/dist-cjs/lib/tools/EraserTool/childStates/Pointing.js +12 -0
- package/dist-cjs/lib/tools/EraserTool/childStates/Pointing.js.map +2 -2
- package/dist-cjs/lib/ui/TldrawUi.js +27 -12
- package/dist-cjs/lib/ui/TldrawUi.js.map +3 -3
- package/dist-cjs/lib/ui/assetUrls.js +13 -10
- package/dist-cjs/lib/ui/assetUrls.js.map +2 -2
- package/dist-cjs/lib/ui/components/AccessibilityMenu.js +35 -0
- package/dist-cjs/lib/ui/components/AccessibilityMenu.js.map +7 -0
- package/dist-cjs/lib/ui/components/ActionsMenu/DefaultActionsMenu.js +12 -3
- package/dist-cjs/lib/ui/components/ActionsMenu/DefaultActionsMenu.js.map +2 -2
- package/dist-cjs/lib/ui/components/{FollowingIndicator.js → DefaultFollowingIndicator.js} +6 -6
- package/dist-cjs/lib/ui/components/DefaultFollowingIndicator.js.map +7 -0
- package/dist-cjs/lib/ui/components/DefaultMenuPanel.js +3 -2
- package/dist-cjs/lib/ui/components/DefaultMenuPanel.js.map +2 -2
- package/dist-cjs/lib/ui/components/KeyboardShortcutsDialog/DefaultKeyboardShortcutsDialogContent.js +6 -6
- package/dist-cjs/lib/ui/components/KeyboardShortcutsDialog/DefaultKeyboardShortcutsDialogContent.js.map +1 -1
- package/dist-cjs/lib/ui/components/MainMenu/DefaultMainMenuContent.js +3 -3
- package/dist-cjs/lib/ui/components/MainMenu/DefaultMainMenuContent.js.map +2 -2
- package/dist-cjs/lib/ui/components/Minimap/MinimapManager.js +4 -4
- package/dist-cjs/lib/ui/components/Minimap/MinimapManager.js.map +2 -2
- package/dist-cjs/lib/ui/components/MobileStylePanel.js +5 -3
- package/dist-cjs/lib/ui/components/MobileStylePanel.js.map +2 -2
- package/dist-cjs/lib/ui/components/NavigationPanel/DefaultNavigationPanel.js +1 -1
- package/dist-cjs/lib/ui/components/NavigationPanel/DefaultNavigationPanel.js.map +2 -2
- package/dist-cjs/lib/ui/components/PageMenu/DefaultPageMenu.js +2 -1
- package/dist-cjs/lib/ui/components/PageMenu/DefaultPageMenu.js.map +2 -2
- package/dist-cjs/lib/ui/components/SharePanel/PeopleMenuItem.js +3 -2
- package/dist-cjs/lib/ui/components/SharePanel/PeopleMenuItem.js.map +2 -2
- package/dist-cjs/lib/ui/components/SharePanel/UserPresenceColorPicker.js +2 -2
- package/dist-cjs/lib/ui/components/SharePanel/UserPresenceColorPicker.js.map +2 -2
- package/dist-cjs/lib/ui/components/StylePanel/DefaultStylePanel.js +11 -4
- package/dist-cjs/lib/ui/components/StylePanel/DefaultStylePanel.js.map +2 -2
- package/dist-cjs/lib/ui/components/StylePanel/DefaultStylePanelContent.js +249 -279
- package/dist-cjs/lib/ui/components/StylePanel/DefaultStylePanelContent.js.map +2 -2
- package/dist-cjs/lib/ui/components/{primitives/TldrawUiButtonPicker.js → StylePanel/StylePanelButtonPicker.js} +52 -56
- package/dist-cjs/lib/ui/components/StylePanel/StylePanelButtonPicker.js.map +7 -0
- package/dist-cjs/lib/ui/components/StylePanel/StylePanelContext.js +68 -0
- package/dist-cjs/lib/ui/components/StylePanel/StylePanelContext.js.map +7 -0
- package/dist-cjs/lib/ui/components/StylePanel/{DoubleDropdownPicker.js → StylePanelDoubleDropdownPicker.js} +26 -25
- package/dist-cjs/lib/ui/components/StylePanel/StylePanelDoubleDropdownPicker.js.map +7 -0
- package/dist-cjs/lib/ui/components/StylePanel/{DropdownPicker.js → StylePanelDropdownPicker.js} +47 -43
- package/dist-cjs/lib/ui/components/StylePanel/StylePanelDropdownPicker.js.map +7 -0
- package/dist-cjs/lib/ui/components/StylePanel/StylePanelSubheading.js +28 -0
- package/dist-cjs/lib/ui/components/StylePanel/StylePanelSubheading.js.map +7 -0
- package/dist-cjs/lib/ui/components/Toolbar/AltTextEditor.js +3 -2
- package/dist-cjs/lib/ui/components/Toolbar/AltTextEditor.js.map +2 -2
- package/dist-cjs/lib/ui/components/Toolbar/DefaultImageToolbarContent.js +39 -10
- package/dist-cjs/lib/ui/components/Toolbar/DefaultImageToolbarContent.js.map +2 -2
- package/dist-cjs/lib/ui/components/Toolbar/DefaultToolbar.js +66 -21
- package/dist-cjs/lib/ui/components/Toolbar/DefaultToolbar.js.map +3 -3
- package/dist-cjs/lib/ui/components/Toolbar/DefaultVideoToolbarContent.js +15 -3
- package/dist-cjs/lib/ui/components/Toolbar/DefaultVideoToolbarContent.js.map +2 -2
- package/dist-cjs/lib/ui/components/Toolbar/LinkEditor.js +3 -3
- package/dist-cjs/lib/ui/components/Toolbar/LinkEditor.js.map +2 -2
- package/dist-cjs/lib/ui/components/Toolbar/OverflowingToolbar.js +189 -80
- package/dist-cjs/lib/ui/components/Toolbar/OverflowingToolbar.js.map +3 -3
- package/dist-cjs/lib/ui/components/Toolbar/ToggleToolLockedButton.js +5 -4
- package/dist-cjs/lib/ui/components/Toolbar/ToggleToolLockedButton.js.map +2 -2
- package/dist-cjs/lib/ui/components/menu-items.js +6 -0
- package/dist-cjs/lib/ui/components/menu-items.js.map +2 -2
- package/dist-cjs/lib/ui/components/primitives/TldrawUiContextualToolbar.js +10 -1
- package/dist-cjs/lib/ui/components/primitives/TldrawUiContextualToolbar.js.map +2 -2
- package/dist-cjs/lib/ui/components/primitives/TldrawUiPopover.js +3 -2
- package/dist-cjs/lib/ui/components/primitives/TldrawUiPopover.js.map +3 -3
- package/dist-cjs/lib/ui/components/primitives/TldrawUiSlider.js +18 -5
- package/dist-cjs/lib/ui/components/primitives/TldrawUiSlider.js.map +2 -2
- package/dist-cjs/lib/ui/components/primitives/TldrawUiToolbar.js +32 -7
- package/dist-cjs/lib/ui/components/primitives/TldrawUiToolbar.js.map +2 -2
- package/dist-cjs/lib/ui/components/primitives/TldrawUiTooltip.js +294 -0
- package/dist-cjs/lib/ui/components/primitives/TldrawUiTooltip.js.map +7 -0
- package/dist-cjs/lib/ui/components/primitives/layout.js +76 -0
- package/dist-cjs/lib/ui/components/primitives/layout.js.map +7 -0
- package/dist-cjs/lib/ui/components/primitives/menus/TldrawUiMenuContext.js.map +2 -2
- package/dist-cjs/lib/ui/components/primitives/menus/TldrawUiMenuGroup.js +25 -12
- package/dist-cjs/lib/ui/components/primitives/menus/TldrawUiMenuGroup.js.map +2 -2
- package/dist-cjs/lib/ui/components/primitives/menus/TldrawUiMenuItem.js +17 -31
- package/dist-cjs/lib/ui/components/primitives/menus/TldrawUiMenuItem.js.map +2 -2
- package/dist-cjs/lib/ui/context/TldrawUiContextProvider.js +3 -2
- package/dist-cjs/lib/ui/context/TldrawUiContextProvider.js.map +2 -2
- package/dist-cjs/lib/ui/context/actions.js +38 -10
- package/dist-cjs/lib/ui/context/actions.js.map +2 -2
- package/dist-cjs/lib/ui/context/components.js +2 -0
- package/dist-cjs/lib/ui/context/components.js.map +2 -2
- package/dist-cjs/lib/ui/context/events.js.map +2 -2
- package/dist-cjs/lib/ui/hooks/useExportAs.js +3 -2
- package/dist-cjs/lib/ui/hooks/useExportAs.js.map +2 -2
- package/dist-cjs/lib/ui/hooks/useTools.js +22 -4
- 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 +6 -1
- package/dist-cjs/lib/ui/hooks/useTranslation/defaultTranslation.js.map +2 -2
- package/dist-cjs/lib/ui/kbd-utils.js +9 -3
- package/dist-cjs/lib/ui/kbd-utils.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/export/copyAs.js +1 -2
- package/dist-cjs/lib/utils/export/copyAs.js.map +2 -2
- package/dist-cjs/lib/utils/export/export.js +0 -20
- package/dist-cjs/lib/utils/export/export.js.map +2 -2
- package/dist-cjs/lib/utils/export/exportAs.js +1 -2
- package/dist-cjs/lib/utils/export/exportAs.js.map +2 -2
- package/dist-esm/index.d.mts +323 -106
- package/dist-esm/index.mjs +83 -29
- package/dist-esm/index.mjs.map +2 -2
- package/dist-esm/lib/Tldraw.mjs +14 -4
- package/dist-esm/lib/Tldraw.mjs.map +2 -2
- package/dist-esm/lib/canvas/TldrawScribble.mjs +1 -1
- package/dist-esm/lib/canvas/TldrawScribble.mjs.map +2 -2
- package/dist-esm/lib/defaultExternalContentHandlers.mjs +5 -4
- package/dist-esm/lib/defaultExternalContentHandlers.mjs.map +2 -2
- package/dist-esm/lib/shapes/arrow/ArrowShapeUtil.mjs +4 -3
- package/dist-esm/lib/shapes/arrow/ArrowShapeUtil.mjs.map +2 -2
- package/dist-esm/lib/shapes/arrow/arrowLabel.mjs +6 -0
- package/dist-esm/lib/shapes/arrow/arrowLabel.mjs.map +3 -3
- package/dist-esm/lib/shapes/arrow/arrowTargetState.mjs +1 -1
- package/dist-esm/lib/shapes/arrow/arrowTargetState.mjs.map +2 -2
- package/dist-esm/lib/shapes/arrow/elbow/ElbowArrowDebug.mjs +3 -3
- package/dist-esm/lib/shapes/arrow/elbow/ElbowArrowDebug.mjs.map +1 -1
- package/dist-esm/lib/shapes/draw/DrawShapeUtil.mjs +4 -3
- package/dist-esm/lib/shapes/draw/DrawShapeUtil.mjs.map +2 -2
- package/dist-esm/lib/shapes/embed/EmbedShapeUtil.mjs +1 -1
- package/dist-esm/lib/shapes/embed/EmbedShapeUtil.mjs.map +1 -1
- package/dist-esm/lib/shapes/frame/FrameShapeUtil.mjs +21 -13
- package/dist-esm/lib/shapes/frame/FrameShapeUtil.mjs.map +2 -2
- package/dist-esm/lib/shapes/frame/components/FrameHeading.mjs +1 -1
- package/dist-esm/lib/shapes/frame/components/FrameHeading.mjs.map +2 -2
- package/dist-esm/lib/shapes/geo/GeoShapeUtil.mjs +4 -2
- package/dist-esm/lib/shapes/geo/GeoShapeUtil.mjs.map +2 -2
- package/dist-esm/lib/shapes/geo/components/GeoShapeBody.mjs +2 -1
- package/dist-esm/lib/shapes/geo/components/GeoShapeBody.mjs.map +2 -2
- package/dist-esm/lib/shapes/highlight/HighlightShapeUtil.mjs +6 -1
- package/dist-esm/lib/shapes/highlight/HighlightShapeUtil.mjs.map +2 -2
- package/dist-esm/lib/shapes/image/ImageShapeUtil.mjs +6 -3
- package/dist-esm/lib/shapes/image/ImageShapeUtil.mjs.map +2 -2
- package/dist-esm/lib/shapes/line/LineShapeUtil.mjs +6 -1
- package/dist-esm/lib/shapes/line/LineShapeUtil.mjs.map +2 -2
- package/dist-esm/lib/shapes/note/NoteShapeUtil.mjs +7 -5
- package/dist-esm/lib/shapes/note/NoteShapeUtil.mjs.map +2 -2
- package/dist-esm/lib/shapes/shared/PlainTextLabel.mjs +1 -3
- package/dist-esm/lib/shapes/shared/PlainTextLabel.mjs.map +2 -2
- package/dist-esm/lib/shapes/shared/ShapeFill.mjs +5 -4
- package/dist-esm/lib/shapes/shared/ShapeFill.mjs.map +2 -2
- package/dist-esm/lib/shapes/shared/freehand/svg.mjs.map +2 -2
- package/dist-esm/lib/shapes/shared/useEditablePlainText.mjs +0 -2
- package/dist-esm/lib/shapes/shared/useEditablePlainText.mjs.map +2 -2
- package/dist-esm/lib/shapes/shared/useImageOrVideoAsset.mjs +0 -2
- package/dist-esm/lib/shapes/shared/useImageOrVideoAsset.mjs.map +2 -2
- package/dist-esm/lib/shapes/shared/usePrefersReducedMotion.mjs +10 -1
- package/dist-esm/lib/shapes/shared/usePrefersReducedMotion.mjs.map +2 -2
- package/dist-esm/lib/shapes/text/TextShapeUtil.mjs +3 -2
- package/dist-esm/lib/shapes/text/TextShapeUtil.mjs.map +2 -2
- package/dist-esm/lib/shapes/video/VideoShapeUtil.mjs +3 -3
- package/dist-esm/lib/shapes/video/VideoShapeUtil.mjs.map +1 -1
- package/dist-esm/lib/tools/EraserTool/childStates/Erasing.mjs +26 -1
- package/dist-esm/lib/tools/EraserTool/childStates/Erasing.mjs.map +2 -2
- package/dist-esm/lib/tools/EraserTool/childStates/Pointing.mjs +13 -0
- package/dist-esm/lib/tools/EraserTool/childStates/Pointing.mjs.map +2 -2
- package/dist-esm/lib/ui/TldrawUi.mjs +29 -14
- package/dist-esm/lib/ui/TldrawUi.mjs.map +3 -3
- package/dist-esm/lib/ui/assetUrls.mjs +13 -10
- package/dist-esm/lib/ui/assetUrls.mjs.map +2 -2
- package/dist-esm/lib/ui/components/AccessibilityMenu.mjs +19 -0
- package/dist-esm/lib/ui/components/AccessibilityMenu.mjs.map +7 -0
- package/dist-esm/lib/ui/components/ActionsMenu/DefaultActionsMenu.mjs +12 -3
- package/dist-esm/lib/ui/components/ActionsMenu/DefaultActionsMenu.mjs.map +2 -2
- package/dist-esm/lib/ui/components/{FollowingIndicator.mjs → DefaultFollowingIndicator.mjs} +3 -3
- package/dist-esm/lib/ui/components/DefaultFollowingIndicator.mjs.map +7 -0
- package/dist-esm/lib/ui/components/DefaultMenuPanel.mjs +3 -2
- package/dist-esm/lib/ui/components/DefaultMenuPanel.mjs.map +2 -2
- package/dist-esm/lib/ui/components/KeyboardShortcutsDialog/DefaultKeyboardShortcutsDialogContent.mjs +6 -6
- package/dist-esm/lib/ui/components/KeyboardShortcutsDialog/DefaultKeyboardShortcutsDialogContent.mjs.map +1 -1
- package/dist-esm/lib/ui/components/MainMenu/DefaultMainMenuContent.mjs +3 -5
- package/dist-esm/lib/ui/components/MainMenu/DefaultMainMenuContent.mjs.map +2 -2
- package/dist-esm/lib/ui/components/Minimap/MinimapManager.mjs +4 -4
- package/dist-esm/lib/ui/components/Minimap/MinimapManager.mjs.map +2 -2
- package/dist-esm/lib/ui/components/MobileStylePanel.mjs +6 -3
- package/dist-esm/lib/ui/components/MobileStylePanel.mjs.map +2 -2
- package/dist-esm/lib/ui/components/NavigationPanel/DefaultNavigationPanel.mjs +1 -1
- package/dist-esm/lib/ui/components/NavigationPanel/DefaultNavigationPanel.mjs.map +2 -2
- package/dist-esm/lib/ui/components/PageMenu/DefaultPageMenu.mjs +2 -1
- package/dist-esm/lib/ui/components/PageMenu/DefaultPageMenu.mjs.map +2 -2
- package/dist-esm/lib/ui/components/SharePanel/PeopleMenuItem.mjs +3 -2
- package/dist-esm/lib/ui/components/SharePanel/PeopleMenuItem.mjs.map +2 -2
- package/dist-esm/lib/ui/components/SharePanel/UserPresenceColorPicker.mjs +2 -2
- package/dist-esm/lib/ui/components/SharePanel/UserPresenceColorPicker.mjs.map +2 -2
- package/dist-esm/lib/ui/components/StylePanel/DefaultStylePanel.mjs +16 -5
- package/dist-esm/lib/ui/components/StylePanel/DefaultStylePanel.mjs.map +2 -2
- package/dist-esm/lib/ui/components/StylePanel/DefaultStylePanelContent.mjs +251 -283
- package/dist-esm/lib/ui/components/StylePanel/DefaultStylePanelContent.mjs.map +2 -2
- package/dist-esm/lib/ui/components/StylePanel/StylePanelButtonPicker.mjs +126 -0
- package/dist-esm/lib/ui/components/StylePanel/StylePanelButtonPicker.mjs.map +7 -0
- package/dist-esm/lib/ui/components/StylePanel/StylePanelContext.mjs +48 -0
- package/dist-esm/lib/ui/components/StylePanel/StylePanelContext.mjs.map +7 -0
- package/dist-esm/lib/ui/components/StylePanel/{DoubleDropdownPicker.mjs → StylePanelDoubleDropdownPicker.mjs} +23 -22
- package/dist-esm/lib/ui/components/StylePanel/StylePanelDoubleDropdownPicker.mjs.map +7 -0
- package/dist-esm/lib/ui/components/StylePanel/{DropdownPicker.mjs → StylePanelDropdownPicker.mjs} +44 -40
- package/dist-esm/lib/ui/components/StylePanel/StylePanelDropdownPicker.mjs.map +7 -0
- package/dist-esm/lib/ui/components/StylePanel/StylePanelSubheading.mjs +8 -0
- package/dist-esm/lib/ui/components/StylePanel/StylePanelSubheading.mjs.map +7 -0
- package/dist-esm/lib/ui/components/Toolbar/AltTextEditor.mjs +3 -2
- package/dist-esm/lib/ui/components/Toolbar/AltTextEditor.mjs.map +2 -2
- package/dist-esm/lib/ui/components/Toolbar/DefaultImageToolbarContent.mjs +39 -10
- package/dist-esm/lib/ui/components/Toolbar/DefaultImageToolbarContent.mjs.map +2 -2
- package/dist-esm/lib/ui/components/Toolbar/DefaultToolbar.mjs +56 -21
- package/dist-esm/lib/ui/components/Toolbar/DefaultToolbar.mjs.map +2 -2
- package/dist-esm/lib/ui/components/Toolbar/DefaultVideoToolbarContent.mjs +15 -3
- package/dist-esm/lib/ui/components/Toolbar/DefaultVideoToolbarContent.mjs.map +2 -2
- package/dist-esm/lib/ui/components/Toolbar/LinkEditor.mjs +3 -3
- package/dist-esm/lib/ui/components/Toolbar/LinkEditor.mjs.map +2 -2
- package/dist-esm/lib/ui/components/Toolbar/OverflowingToolbar.mjs +192 -81
- package/dist-esm/lib/ui/components/Toolbar/OverflowingToolbar.mjs.map +3 -3
- package/dist-esm/lib/ui/components/Toolbar/ToggleToolLockedButton.mjs +5 -4
- package/dist-esm/lib/ui/components/Toolbar/ToggleToolLockedButton.mjs.map +2 -2
- package/dist-esm/lib/ui/components/menu-items.mjs +6 -0
- package/dist-esm/lib/ui/components/menu-items.mjs.map +2 -2
- package/dist-esm/lib/ui/components/primitives/TldrawUiContextualToolbar.mjs +10 -1
- package/dist-esm/lib/ui/components/primitives/TldrawUiContextualToolbar.mjs.map +2 -2
- package/dist-esm/lib/ui/components/primitives/TldrawUiPopover.mjs +3 -2
- package/dist-esm/lib/ui/components/primitives/TldrawUiPopover.mjs.map +2 -2
- package/dist-esm/lib/ui/components/primitives/TldrawUiSlider.mjs +18 -5
- package/dist-esm/lib/ui/components/primitives/TldrawUiSlider.mjs.map +2 -2
- package/dist-esm/lib/ui/components/primitives/TldrawUiToolbar.mjs +32 -7
- package/dist-esm/lib/ui/components/primitives/TldrawUiToolbar.mjs.map +2 -2
- package/dist-esm/lib/ui/components/primitives/TldrawUiTooltip.mjs +272 -0
- package/dist-esm/lib/ui/components/primitives/TldrawUiTooltip.mjs.map +7 -0
- package/dist-esm/lib/ui/components/primitives/layout.mjs +46 -0
- package/dist-esm/lib/ui/components/primitives/layout.mjs.map +7 -0
- package/dist-esm/lib/ui/components/primitives/menus/TldrawUiMenuContext.mjs.map +2 -2
- package/dist-esm/lib/ui/components/primitives/menus/TldrawUiMenuGroup.mjs +25 -12
- package/dist-esm/lib/ui/components/primitives/menus/TldrawUiMenuGroup.mjs.map +2 -2
- package/dist-esm/lib/ui/components/primitives/menus/TldrawUiMenuItem.mjs +17 -31
- package/dist-esm/lib/ui/components/primitives/menus/TldrawUiMenuItem.mjs.map +2 -2
- package/dist-esm/lib/ui/context/TldrawUiContextProvider.mjs +3 -2
- package/dist-esm/lib/ui/context/TldrawUiContextProvider.mjs.map +2 -2
- package/dist-esm/lib/ui/context/actions.mjs +38 -10
- package/dist-esm/lib/ui/context/actions.mjs.map +2 -2
- package/dist-esm/lib/ui/context/components.mjs +2 -0
- package/dist-esm/lib/ui/context/components.mjs.map +2 -2
- package/dist-esm/lib/ui/context/events.mjs.map +2 -2
- package/dist-esm/lib/ui/hooks/useExportAs.mjs +3 -2
- package/dist-esm/lib/ui/hooks/useExportAs.mjs.map +2 -2
- package/dist-esm/lib/ui/hooks/useTools.mjs +23 -4
- package/dist-esm/lib/ui/hooks/useTools.mjs.map +2 -2
- package/dist-esm/lib/ui/hooks/useTranslation/defaultTranslation.mjs +6 -1
- package/dist-esm/lib/ui/hooks/useTranslation/defaultTranslation.mjs.map +2 -2
- package/dist-esm/lib/ui/kbd-utils.mjs +9 -3
- package/dist-esm/lib/ui/kbd-utils.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/export/copyAs.mjs +1 -2
- package/dist-esm/lib/utils/export/copyAs.mjs.map +2 -2
- package/dist-esm/lib/utils/export/export.mjs +0 -20
- package/dist-esm/lib/utils/export/export.mjs.map +2 -2
- package/dist-esm/lib/utils/export/exportAs.mjs +1 -2
- package/dist-esm/lib/utils/export/exportAs.mjs.map +2 -2
- package/package.json +11 -34
- package/src/index.ts +62 -22
- package/src/lib/Tldraw.tsx +15 -2
- package/src/lib/canvas/TldrawScribble.tsx +1 -1
- package/src/lib/defaultExternalContentHandlers.ts +12 -4
- package/src/lib/shapes/arrow/ArrowShapeOptions.test.ts +2 -1
- package/src/lib/shapes/arrow/ArrowShapeTool.test.ts +6 -5
- package/src/lib/shapes/arrow/ArrowShapeUtil.test.ts +48 -6
- package/src/lib/shapes/arrow/ArrowShapeUtil.tsx +4 -3
- package/src/lib/shapes/arrow/arrowLabel.ts +8 -0
- package/src/lib/shapes/arrow/arrowTargetState.ts +2 -1
- package/src/lib/shapes/arrow/elbow/ElbowArrowDebug.tsx +3 -3
- package/src/lib/shapes/draw/DrawShapeTool.test.ts +0 -5
- package/src/lib/shapes/draw/DrawShapeUtil.tsx +4 -3
- package/src/lib/shapes/embed/EmbedShapeUtil.tsx +1 -1
- package/src/lib/shapes/frame/FrameShapeUtil.tsx +30 -14
- package/src/lib/shapes/frame/components/FrameHeading.tsx +1 -1
- package/src/lib/shapes/geo/GeoShapeUtil.tsx +4 -2
- package/src/lib/shapes/geo/components/GeoShapeBody.tsx +2 -2
- package/src/lib/shapes/highlight/HighlightShapeUtil.tsx +7 -1
- package/src/lib/shapes/image/ImageShapeUtil.tsx +6 -3
- package/src/lib/shapes/line/LineShapeUtil.test.tsx +4 -3
- package/src/lib/shapes/line/LineShapeUtil.tsx +6 -1
- package/src/lib/shapes/line/__snapshots__/LineShapeUtil.test.tsx.snap +2 -2
- package/src/lib/shapes/note/NoteShapeUtil.tsx +10 -4
- package/src/lib/shapes/shared/PlainTextLabel.tsx +0 -6
- package/src/lib/shapes/shared/ShapeFill.tsx +5 -4
- package/src/lib/shapes/shared/freehand/svg.ts +2 -0
- package/src/lib/shapes/shared/useEditablePlainText.ts +0 -6
- package/src/lib/shapes/shared/useImageOrVideoAsset.ts +0 -7
- package/src/lib/shapes/shared/usePrefersReducedMotion.tsx +11 -1
- package/src/lib/shapes/text/TextShapeTool.test.ts +6 -5
- package/src/lib/shapes/text/TextShapeUtil.tsx +3 -2
- package/src/lib/shapes/video/VideoShapeUtil.tsx +3 -3
- package/src/lib/tools/EraserTool/childStates/Erasing.ts +34 -1
- package/src/lib/tools/EraserTool/childStates/Pointing.ts +20 -0
- package/src/lib/ui/TldrawUi.tsx +33 -12
- package/src/lib/ui/assetUrls.ts +13 -10
- package/src/lib/ui/components/AccessibilityMenu.tsx +20 -0
- package/src/lib/ui/components/ActionsMenu/DefaultActionsMenu.tsx +15 -3
- package/src/lib/ui/components/{FollowingIndicator.tsx → DefaultFollowingIndicator.tsx} +2 -1
- package/src/lib/ui/components/DefaultMenuPanel.tsx +4 -3
- package/src/lib/ui/components/KeyboardShortcutsDialog/DefaultKeyboardShortcutsDialogContent.tsx +6 -6
- package/src/lib/ui/components/MainMenu/DefaultMainMenuContent.tsx +4 -4
- package/src/lib/ui/components/Minimap/MinimapManager.ts +4 -4
- package/src/lib/ui/components/MobileStylePanel.tsx +9 -6
- package/src/lib/ui/components/NavigationPanel/DefaultNavigationPanel.tsx +1 -1
- package/src/lib/ui/components/PageMenu/DefaultPageMenu.tsx +3 -2
- package/src/lib/ui/components/SharePanel/PeopleMenuItem.tsx +4 -3
- package/src/lib/ui/components/SharePanel/UserPresenceColorPicker.tsx +3 -3
- package/src/lib/ui/components/StylePanel/DefaultStylePanel.tsx +28 -12
- package/src/lib/ui/components/StylePanel/DefaultStylePanelContent.tsx +261 -343
- package/src/lib/ui/components/{primitives/TldrawUiButtonPicker.tsx → StylePanel/StylePanelButtonPicker.tsx} +66 -50
- package/src/lib/ui/components/StylePanel/StylePanelContext.tsx +63 -0
- package/src/lib/ui/components/StylePanel/{DoubleDropdownPicker.tsx → StylePanelDoubleDropdownPicker.tsx} +31 -22
- package/src/lib/ui/components/StylePanel/StylePanelDropdownPicker.tsx +119 -0
- package/src/lib/ui/components/StylePanel/StylePanelSubheading.tsx +9 -0
- package/src/lib/ui/components/Toolbar/AltTextEditor.tsx +4 -3
- package/src/lib/ui/components/Toolbar/DefaultImageToolbarContent.tsx +33 -16
- package/src/lib/ui/components/Toolbar/DefaultToolbar.tsx +55 -23
- package/src/lib/ui/components/Toolbar/DefaultVideoToolbarContent.tsx +12 -4
- package/src/lib/ui/components/Toolbar/LinkEditor.tsx +5 -5
- package/src/lib/ui/components/Toolbar/OverflowingToolbar.tsx +212 -61
- package/src/lib/ui/components/Toolbar/ToggleToolLockedButton.tsx +14 -11
- package/src/lib/ui/components/menu-items.tsx +8 -0
- package/src/lib/ui/components/primitives/TldrawUiContextualToolbar.tsx +6 -1
- package/src/lib/ui/components/primitives/TldrawUiPopover.tsx +4 -2
- package/src/lib/ui/components/primitives/TldrawUiSlider.tsx +52 -32
- package/src/lib/ui/components/primitives/TldrawUiToolbar.tsx +54 -12
- package/src/lib/ui/components/primitives/TldrawUiTooltip.tsx +365 -0
- package/src/lib/ui/components/primitives/layout.tsx +107 -0
- package/src/lib/ui/components/primitives/menus/TldrawUiMenuContext.tsx +0 -1
- package/src/lib/ui/components/primitives/menus/TldrawUiMenuGroup.tsx +29 -16
- package/src/lib/ui/components/primitives/menus/TldrawUiMenuItem.tsx +24 -33
- package/src/lib/ui/context/TldrawUiContextProvider.tsx +23 -20
- package/src/lib/ui/context/actions.tsx +38 -10
- package/src/lib/ui/context/components.tsx +3 -0
- package/src/lib/ui/context/events.tsx +2 -1
- package/src/lib/ui/hooks/useExportAs.ts +3 -2
- package/src/lib/ui/hooks/useTools.tsx +26 -4
- package/src/lib/ui/hooks/useTranslation/TLUiTranslationKey.ts +5 -0
- package/src/lib/ui/hooks/useTranslation/defaultTranslation.ts +6 -1
- package/src/lib/ui/kbd-utils.ts +10 -3
- package/src/lib/ui/version.ts +3 -3
- package/src/lib/ui.css +424 -293
- package/src/lib/utils/excalidraw/__snapshots__/putExcalidrawContent.test.tsx.snap +5 -5
- package/src/lib/utils/export/copyAs.ts +1 -24
- package/src/lib/utils/export/export.ts +0 -36
- package/src/lib/utils/export/exportAs.ts +1 -32
- package/src/lib/utils/tldr/__snapshots__/buildFromV1Document.test.ts.snap +4 -4
- package/src/test/A11y.test.tsx +3 -2
- package/src/test/ClickManager.test.ts +7 -6
- package/src/test/Editor.test.tsx +20 -19
- package/src/test/EraserTool.test.ts +184 -13
- package/src/test/HandTool.test.ts +10 -9
- package/src/test/HighlightShape.test.ts +2 -1
- package/src/test/SelectTool.test.ts +3 -2
- package/src/test/TLUserPreferences.test.ts +4 -3
- package/src/test/TestEditor.ts +13 -15
- package/src/test/TldrawEditor.test.tsx +11 -10
- package/src/test/ZoomTool.test.ts +7 -6
- package/src/test/__snapshots__/drawing.test.ts.snap +2 -2
- package/src/test/__snapshots__/groups.test.tsx.snap +6 -6
- package/src/test/__snapshots__/resizing.test.ts.snap +2 -2
- package/src/test/arrows-megabus.test.tsx +17 -10
- package/src/test/bindings.test.tsx +24 -37
- package/src/test/bookmark-shapes.test.ts +1 -8
- package/src/test/commands/__snapshots__/getSvgString.test.ts.snap +23 -7
- package/src/test/commands/__snapshots__/packShapes.test.ts.snap +8 -8
- package/src/test/commands/__snapshots__/zoomToFit.test.ts.snap +2 -2
- package/src/test/commands/alignShapes.test.tsx +25 -24
- package/src/test/commands/animationSpeed.test.ts +2 -1
- package/src/test/commands/centerOnPoint.test.ts +3 -2
- package/src/test/commands/clipboard.test.ts +3 -2
- package/src/test/commands/createShapes.test.ts +2 -1
- package/src/test/commands/deleteShapes.test.ts +2 -1
- package/src/test/commands/distributeShapes.test.tsx +11 -10
- package/src/test/commands/getSvgString.test.ts +2 -1
- package/src/test/commands/packShapes.test.ts +5 -4
- package/src/test/commands/resizeShape.test.ts +2 -1
- package/src/test/commands/rotateShapes.test.ts +7 -6
- package/src/test/commands/setCamera.test.ts +4 -3
- package/src/test/commands/setCurrentPage.test.ts +3 -2
- package/src/test/commands/stackShapes.test.ts +11 -10
- package/src/test/commands/stretch.test.tsx +13 -12
- package/src/test/createDeepLink.test.tsx +2 -1
- package/src/test/cropping.test.ts +3 -2
- package/src/test/custom-clipping.test.ts +436 -0
- package/src/test/drawing.test.ts +2 -1
- package/src/test/flipShapes.test.ts +4 -3
- package/src/test/frames.test.ts +25 -24
- package/src/test/getCulledShapes.test.tsx +74 -4
- package/src/test/groups.test.tsx +1 -1
- package/src/test/handleDeepLink.test.tsx +2 -1
- package/src/test/inner-outer-margin.test.ts +315 -0
- package/src/test/maxShapes.test.ts +3 -2
- package/src/test/modifiers.test.ts +5 -4
- package/src/test/navigation.test.ts +12 -11
- package/src/test/panning.test.ts +2 -1
- package/src/test/perf/perf.test.ts +2 -1
- package/src/test/registerDeepLinkListener.test.tsx +10 -9
- package/src/test/resizing.test.ts +39 -38
- package/src/test/select.test.tsx +4 -3
- package/src/test/selection-omnibus.test.ts +11 -10
- package/src/test/shapeutils.test.ts +4 -3
- package/src/test/translating.test.ts +9 -8
- package/tldraw.css +732 -583
- package/dist-cjs/lib/ui/components/FollowingIndicator.js.map +0 -7
- package/dist-cjs/lib/ui/components/StylePanel/DoubleDropdownPicker.js.map +0 -7
- package/dist-cjs/lib/ui/components/StylePanel/DropdownPicker.js.map +0 -7
- package/dist-cjs/lib/ui/components/primitives/TldrawUiButtonPicker.js.map +0 -7
- package/dist-esm/lib/ui/components/FollowingIndicator.mjs.map +0 -7
- package/dist-esm/lib/ui/components/StylePanel/DoubleDropdownPicker.mjs.map +0 -7
- package/dist-esm/lib/ui/components/StylePanel/DropdownPicker.mjs.map +0 -7
- package/dist-esm/lib/ui/components/primitives/TldrawUiButtonPicker.mjs +0 -115
- package/dist-esm/lib/ui/components/primitives/TldrawUiButtonPicker.mjs.map +0 -7
- package/src/lib/ui/components/StylePanel/DropdownPicker.tsx +0 -109
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../../src/lib/shapes/image/ImageShapeUtil.tsx"],
|
|
4
|
-
"sourcesContent": ["import {\n\tBaseBoxShapeUtil,\n\tEditor,\n\tEllipse2d,\n\tFileHelpers,\n\tGeometry2d,\n\tHTMLContainer,\n\tImage,\n\tMediaHelpers,\n\tRectangle2d,\n\tSvgExportContext,\n\tTLAsset,\n\tTLAssetId,\n\tTLImageShape,\n\tTLImageShapeProps,\n\tTLResizeInfo,\n\tTLShapePartial,\n\tVec,\n\tWeakCache,\n\tfetch,\n\timageShapeMigrations,\n\timageShapeProps,\n\tlerp,\n\tmodulate,\n\tresizeBox,\n\tstructuredClone,\n\ttoDomPrecision,\n\tuseEditor,\n\tuseUniqueSafeId,\n\tuseValue,\n} from '@tldraw/editor'\nimport classNames from 'classnames'\nimport { memo, useEffect, useState } from 'react'\nimport { BrokenAssetIcon } from '../shared/BrokenAssetIcon'\nimport { HyperlinkButton } from '../shared/HyperlinkButton'\nimport { getUncroppedSize } from '../shared/crop'\nimport { useImageOrVideoAsset } from '../shared/useImageOrVideoAsset'\nimport { usePrefersReducedMotion } from '../shared/usePrefersReducedMotion'\n\nasync function getDataURIFromURL(url: string): Promise<string> {\n\tconst response = await fetch(url)\n\tconst blob = await response.blob()\n\treturn FileHelpers.blobToDataUrl(blob)\n}\n\nconst imageSvgExportCache = new WeakCache<TLAsset, Promise<string | null>>()\n\n/** @public */\nexport class ImageShapeUtil extends BaseBoxShapeUtil<TLImageShape> {\n\tstatic override type = 'image' as const\n\tstatic override props = imageShapeProps\n\tstatic override migrations = imageShapeMigrations\n\n\toverride isAspectRatioLocked() {\n\t\treturn true\n\t}\n\toverride canCrop() {\n\t\treturn true\n\t}\n\n\toverride getDefaultProps(): TLImageShape['props'] {\n\t\treturn {\n\t\t\tw: 100,\n\t\t\th: 100,\n\t\t\tassetId: null,\n\t\t\tplaying: true,\n\t\t\turl: '',\n\t\t\tcrop: null,\n\t\t\tflipX: false,\n\t\t\tflipY: false,\n\t\t\taltText: '',\n\t\t}\n\t}\n\n\toverride getGeometry(shape: TLImageShape): Geometry2d {\n\t\tif (shape.props.crop?.isCircle) {\n\t\t\treturn new Ellipse2d({\n\t\t\t\twidth: shape.props.w,\n\t\t\t\theight: shape.props.h,\n\t\t\t\tisFilled: true,\n\t\t\t})\n\t\t}\n\n\t\treturn new Rectangle2d({\n\t\t\twidth: shape.props.w,\n\t\t\theight: shape.props.h,\n\t\t\tisFilled: true,\n\t\t})\n\t}\n\n\toverride getAriaDescriptor(shape: TLImageShape) {\n\t\treturn shape.props.altText\n\t}\n\n\toverride onResize(shape: TLImageShape, info: TLResizeInfo<TLImageShape>) {\n\t\tlet resized: TLImageShape = resizeBox(shape, info)\n\t\tconst { flipX, flipY } = info.initialShape.props\n\t\tconst { scaleX, scaleY, mode } = info\n\n\t\tresized = {\n\t\t\t...resized,\n\t\t\tprops: {\n\t\t\t\t...resized.props,\n\t\t\t\tflipX: scaleX < 0 !== flipX,\n\t\t\t\tflipY: scaleY < 0 !== flipY,\n\t\t\t},\n\t\t}\n\t\tif (!shape.props.crop) return resized\n\n\t\tconst flipCropHorizontally =\n\t\t\t// We used the flip horizontally feature\n\t\t\t(mode === 'scale_shape' && scaleX === -1) ||\n\t\t\t// We resized the shape past it's bounds, so it flipped\n\t\t\t(mode === 'resize_bounds' && flipX !== resized.props.flipX)\n\t\tconst flipCropVertically =\n\t\t\t// We used the flip vertically feature\n\t\t\t(mode === 'scale_shape' && scaleY === -1) ||\n\t\t\t// We resized the shape past it's bounds, so it flipped\n\t\t\t(mode === 'resize_bounds' && flipY !== resized.props.flipY)\n\n\t\tconst { topLeft, bottomRight } = shape.props.crop\n\t\tresized.props.crop = {\n\t\t\ttopLeft: {\n\t\t\t\tx: flipCropHorizontally ? 1 - bottomRight.x : topLeft.x,\n\t\t\t\ty: flipCropVertically ? 1 - bottomRight.y : topLeft.y,\n\t\t\t},\n\t\t\tbottomRight: {\n\t\t\t\tx: flipCropHorizontally ? 1 - topLeft.x : bottomRight.x,\n\t\t\t\ty: flipCropVertically ? 1 - topLeft.y : bottomRight.y,\n\t\t\t},\n\t\t\tisCircle: shape.props.crop.isCircle,\n\t\t}\n\t\treturn resized\n\t}\n\n\tcomponent(shape: TLImageShape) {\n\t\treturn <ImageShape shape={shape} />\n\t}\n\n\tindicator(shape: TLImageShape) {\n\t\tconst isCropping = this.editor.getCroppingShapeId() === shape.id\n\t\tif (isCropping) return null\n\n\t\tif (shape.props.crop?.isCircle) {\n\t\t\treturn (\n\t\t\t\t<ellipse\n\t\t\t\t\tcx={toDomPrecision(shape.props.w / 2)}\n\t\t\t\t\tcy={toDomPrecision(shape.props.h / 2)}\n\t\t\t\t\trx={toDomPrecision(shape.props.w / 2)}\n\t\t\t\t\try={toDomPrecision(shape.props.h / 2)}\n\t\t\t\t/>\n\t\t\t)\n\t\t}\n\n\t\treturn <rect width={toDomPrecision(shape.props.w)} height={toDomPrecision(shape.props.h)} />\n\t}\n\n\toverride async toSvg(shape: TLImageShape, ctx: SvgExportContext) {\n\t\tconst props = shape.props\n\t\tif (!props.assetId) return null\n\n\t\tconst asset = this.editor.getAsset(props.assetId)\n\n\t\tif (!asset) return null\n\n\t\tconst { w } = getUncroppedSize(shape.props, props.crop)\n\n\t\tconst src = await imageSvgExportCache.get(asset, async () => {\n\t\t\tlet src = await ctx.resolveAssetUrl(asset.id, w)\n\t\t\tif (!src) return null\n\t\t\tif (\n\t\t\t\tsrc.startsWith('blob:') ||\n\t\t\t\tsrc.startsWith('http') ||\n\t\t\t\tsrc.startsWith('/') ||\n\t\t\t\tsrc.startsWith('./')\n\t\t\t) {\n\t\t\t\t// If it's a remote image, we need to fetch it and convert it to a data URI\n\t\t\t\tsrc = (await getDataURIFromURL(src)) || ''\n\t\t\t}\n\n\t\t\t// If it's animated then we need to get the first frame\n\t\t\tif (getIsAnimated(this.editor, asset.id)) {\n\t\t\t\tconst { promise } = getFirstFrameOfAnimatedImage(src)\n\t\t\t\tsrc = await promise\n\t\t\t}\n\t\t\treturn src\n\t\t})\n\n\t\tif (!src) return null\n\n\t\treturn <SvgImage shape={shape} src={src} />\n\t}\n\n\toverride onDoubleClickEdge(shape: TLImageShape) {\n\t\tconst props = shape.props\n\t\tif (!props) return\n\n\t\tif (this.editor.getCroppingShapeId() !== shape.id) {\n\t\t\treturn\n\t\t}\n\n\t\tconst crop = structuredClone(props.crop) || {\n\t\t\ttopLeft: { x: 0, y: 0 },\n\t\t\tbottomRight: { x: 1, y: 1 },\n\t\t}\n\n\t\t// The true asset dimensions\n\t\tconst { w, h } = getUncroppedSize(shape.props, crop)\n\n\t\tconst pointDelta = new Vec(crop.topLeft.x * w, crop.topLeft.y * h).rot(shape.rotation)\n\n\t\tconst partial: TLShapePartial<TLImageShape> = {\n\t\t\tid: shape.id,\n\t\t\ttype: shape.type,\n\t\t\tx: shape.x - pointDelta.x,\n\t\t\ty: shape.y - pointDelta.y,\n\t\t\tprops: {\n\t\t\t\tcrop: {\n\t\t\t\t\ttopLeft: { x: 0, y: 0 },\n\t\t\t\t\tbottomRight: { x: 1, y: 1 },\n\t\t\t\t},\n\t\t\t\tw,\n\t\t\t\th,\n\t\t\t},\n\t\t}\n\n\t\tthis.editor.updateShapes([partial])\n\t}\n\toverride getInterpolatedProps(\n\t\tstartShape: TLImageShape,\n\t\tendShape: TLImageShape,\n\t\tt: number\n\t): TLImageShapeProps {\n\t\tfunction interpolateCrop(\n\t\t\tstartShape: TLImageShape,\n\t\t\tendShape: TLImageShape\n\t\t): TLImageShapeProps['crop'] {\n\t\t\tif (startShape.props.crop === null && endShape.props.crop === null) return null\n\n\t\t\tconst startTL = startShape.props.crop?.topLeft || { x: 0, y: 0 }\n\t\t\tconst startBR = startShape.props.crop?.bottomRight || { x: 1, y: 1 }\n\t\t\tconst endTL = endShape.props.crop?.topLeft || { x: 0, y: 0 }\n\t\t\tconst endBR = endShape.props.crop?.bottomRight || { x: 1, y: 1 }\n\n\t\t\treturn {\n\t\t\t\ttopLeft: { x: lerp(startTL.x, endTL.x, t), y: lerp(startTL.y, endTL.y, t) },\n\t\t\t\tbottomRight: { x: lerp(startBR.x, endBR.x, t), y: lerp(startBR.y, endBR.y, t) },\n\t\t\t}\n\t\t}\n\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\tcrop: interpolateCrop(startShape, endShape),\n\t\t}\n\t}\n}\n\nconst ImageShape = memo(function ImageShape({ shape }: { shape: TLImageShape }) {\n\tconst editor = useEditor()\n\n\tconst { w } = getUncroppedSize(shape.props, shape.props.crop)\n\tconst { asset, url } = useImageOrVideoAsset({\n\t\tshapeId: shape.id,\n\t\tassetId: shape.props.assetId,\n\t\twidth: w,\n\t})\n\n\tconst prefersReducedMotion = usePrefersReducedMotion()\n\tconst [staticFrameSrc, setStaticFrameSrc] = useState('')\n\tconst [loadedUrl, setLoadedUrl] = useState<null | string>(null)\n\tconst isAnimated = asset && getIsAnimated(editor, asset.id)\n\n\tuseEffect(() => {\n\t\tif (url && isAnimated) {\n\t\t\tconst { promise, cancel } = getFirstFrameOfAnimatedImage(url)\n\n\t\t\tpromise.then((dataUrl) => {\n\t\t\t\tsetStaticFrameSrc(dataUrl)\n\t\t\t\tsetLoadedUrl(url)\n\t\t\t})\n\n\t\t\treturn () => {\n\t\t\t\tcancel()\n\t\t\t}\n\t\t}\n\t}, [editor, isAnimated, prefersReducedMotion, url])\n\n\tconst showCropPreview = useValue(\n\t\t'show crop preview',\n\t\t() =>\n\t\t\tshape.id === editor.getOnlySelectedShapeId() &&\n\t\t\teditor.getCroppingShapeId() === shape.id &&\n\t\t\teditor.isIn('select.crop'),\n\t\t[editor, shape.id]\n\t)\n\n\t// We only want to reduce motion for mimeTypes that have motion\n\tconst reduceMotion =\n\t\tprefersReducedMotion && (asset?.props.mimeType?.includes('video') || isAnimated)\n\n\tconst containerStyle = getCroppedContainerStyle(shape)\n\n\tconst nextSrc = url === loadedUrl ? null : url\n\tconst loadedSrc = reduceMotion ? staticFrameSrc : loadedUrl\n\n\t// This logic path is for when it's broken/missing asset.\n\tif (!url && !asset?.props.src) {\n\t\treturn (\n\t\t\t<HTMLContainer\n\t\t\t\tid={shape.id}\n\t\t\t\tstyle={{\n\t\t\t\t\toverflow: 'hidden',\n\t\t\t\t\twidth: shape.props.w,\n\t\t\t\t\theight: shape.props.h,\n\t\t\t\t\tcolor: 'var(--color-text-3)',\n\t\t\t\t\tbackgroundColor: 'var(--color-low)',\n\t\t\t\t\tborder: '1px solid var(--color-low-border)',\n\t\t\t\t}}\n\t\t\t>\n\t\t\t\t<div\n\t\t\t\t\tclassName={classNames('tl-image-container', asset && 'tl-image-container-loading')}\n\t\t\t\t\tstyle={containerStyle}\n\t\t\t\t>\n\t\t\t\t\t{asset ? null : <BrokenAssetIcon />}\n\t\t\t\t</div>\n\t\t\t\t{'url' in shape.props && shape.props.url && <HyperlinkButton url={shape.props.url} />}\n\t\t\t</HTMLContainer>\n\t\t)\n\t}\n\n\t// We don't set crossOrigin for non-animated images because for Cloudflare we don't currently\n\t// have that set up.\n\tconst crossOrigin = isAnimated ? 'anonymous' : undefined\n\n\treturn (\n\t\t<>\n\t\t\t{showCropPreview && loadedSrc && (\n\t\t\t\t<div style={containerStyle}>\n\t\t\t\t\t<img\n\t\t\t\t\t\tclassName=\"tl-image\"\n\t\t\t\t\t\tstyle={{ ...getFlipStyle(shape), opacity: 0.1 }}\n\t\t\t\t\t\tcrossOrigin={crossOrigin}\n\t\t\t\t\t\tsrc={loadedSrc}\n\t\t\t\t\t\treferrerPolicy=\"strict-origin-when-cross-origin\"\n\t\t\t\t\t\tdraggable={false}\n\t\t\t\t\t\talt=\"\"\n\t\t\t\t\t/>\n\t\t\t\t</div>\n\t\t\t)}\n\t\t\t<HTMLContainer\n\t\t\t\tid={shape.id}\n\t\t\t\tstyle={{\n\t\t\t\t\toverflow: 'hidden',\n\t\t\t\t\twidth: shape.props.w,\n\t\t\t\t\theight: shape.props.h,\n\t\t\t\t\tborderRadius: shape.props.crop?.isCircle ? '50%' : undefined,\n\t\t\t\t}}\n\t\t\t>\n\t\t\t\t<div className={classNames('tl-image-container')} style={containerStyle}>\n\t\t\t\t\t{/* We have two images: the currently loaded image, and the next image that\n\t\t\t\t\twe're waiting to load. we keep the loaded image mounted while we're waiting\n\t\t\t\t\tfor the next one by storing the loaded URL in state. We use `key` props with\n\t\t\t\t\tthe src of the image so that when the next image is ready, the previous one will\n\t\t\t\t\tbe unmounted and the next will be shown with the browser having to remount a\n\t\t\t\t\tfresh image and decoded it again from the cache. */}\n\t\t\t\t\t{loadedSrc && (\n\t\t\t\t\t\t<img\n\t\t\t\t\t\t\tkey={loadedSrc}\n\t\t\t\t\t\t\tclassName=\"tl-image\"\n\t\t\t\t\t\t\tstyle={getFlipStyle(shape)}\n\t\t\t\t\t\t\tcrossOrigin={crossOrigin}\n\t\t\t\t\t\t\tsrc={loadedSrc}\n\t\t\t\t\t\t\treferrerPolicy=\"strict-origin-when-cross-origin\"\n\t\t\t\t\t\t\tdraggable={false}\n\t\t\t\t\t\t\talt=\"\"\n\t\t\t\t\t\t/>\n\t\t\t\t\t)}\n\t\t\t\t\t{nextSrc && (\n\t\t\t\t\t\t<img\n\t\t\t\t\t\t\tkey={nextSrc}\n\t\t\t\t\t\t\tclassName=\"tl-image\"\n\t\t\t\t\t\t\tstyle={getFlipStyle(shape)}\n\t\t\t\t\t\t\tcrossOrigin={crossOrigin}\n\t\t\t\t\t\t\tsrc={nextSrc}\n\t\t\t\t\t\t\treferrerPolicy=\"strict-origin-when-cross-origin\"\n\t\t\t\t\t\t\tdraggable={false}\n\t\t\t\t\t\t\talt={shape.props.altText}\n\t\t\t\t\t\t\tonLoad={() => setLoadedUrl(nextSrc)}\n\t\t\t\t\t\t/>\n\t\t\t\t\t)}\n\t\t\t\t</div>\n\t\t\t\t{shape.props.url && <HyperlinkButton url={shape.props.url} />}\n\t\t\t</HTMLContainer>\n\t\t</>\n\t)\n})\n\nfunction getIsAnimated(editor: Editor, assetId: TLAssetId) {\n\tconst asset = assetId ? editor.getAsset(assetId) : undefined\n\n\tif (!asset) return false\n\n\treturn (\n\t\t('mimeType' in asset.props && MediaHelpers.isAnimatedImageType(asset?.props.mimeType)) ||\n\t\t('isAnimated' in asset.props && asset.props.isAnimated)\n\t)\n}\n\n/**\n * When an image is cropped we need to translate the image to show the portion withing the cropped\n * area. We do this by translating the image by the negative of the top left corner of the crop\n * area.\n *\n * @param shape - Shape The image shape for which to get the container style\n * @returns - Styles to apply to the image container\n */\nfunction getCroppedContainerStyle(shape: TLImageShape) {\n\tconst crop = shape.props.crop\n\tconst topLeft = crop?.topLeft\n\tif (!topLeft) {\n\t\treturn {\n\t\t\twidth: shape.props.w,\n\t\t\theight: shape.props.h,\n\t\t}\n\t}\n\n\tconst { w, h } = getUncroppedSize(shape.props, crop)\n\tconst offsetX = -topLeft.x * w\n\tconst offsetY = -topLeft.y * h\n\treturn {\n\t\ttransform: `translate(${offsetX}px, ${offsetY}px)`,\n\t\twidth: w,\n\t\theight: h,\n\t}\n}\n\nfunction getFlipStyle(shape: TLImageShape, size?: { width: number; height: number }) {\n\tconst { flipX, flipY, crop } = shape.props\n\tif (!flipX && !flipY) return undefined\n\n\tlet cropOffsetX\n\tlet cropOffsetY\n\tif (crop) {\n\t\t// We have to do all this extra math because of the whole transform origin around 0,0\n\t\t// instead of center in SVG-land, ugh.\n\t\tconst { w, h } = getUncroppedSize(shape.props, crop)\n\n\t\t// Find the resulting w/h of the crop in normalized (0-1) coordinates\n\t\tconst cropWidth = crop.bottomRight.x - crop.topLeft.x\n\t\tconst cropHeight = crop.bottomRight.y - crop.topLeft.y\n\n\t\t// Map from the normalized crop coordinate space to shape pixel space\n\t\tcropOffsetX = modulate(crop.topLeft.x, [0, 1 - cropWidth], [0, w - shape.props.w])\n\t\tcropOffsetY = modulate(crop.topLeft.y, [0, 1 - cropHeight], [0, h - shape.props.h])\n\t}\n\n\tconst scale = `scale(${flipX ? -1 : 1}, ${flipY ? -1 : 1})`\n\tconst translate = size\n\t\t? `translate(${(flipX ? size.width : 0) - (cropOffsetX ? cropOffsetX : 0)}px,\n\t\t ${(flipY ? size.height : 0) - (cropOffsetY ? cropOffsetY : 0)}px)`\n\t\t: ''\n\n\treturn {\n\t\ttransform: `${translate} ${scale}`,\n\t\t// in SVG, flipping around the center doesn't work so we use explicit width/height\n\t\ttransformOrigin: size ? '0 0' : 'center center',\n\t}\n}\n\nfunction SvgImage({ shape, src }: { shape: TLImageShape; src: string }) {\n\tconst cropClipId = useUniqueSafeId()\n\tconst containerStyle = getCroppedContainerStyle(shape)\n\tconst crop = shape.props.crop\n\n\tif (containerStyle.transform && crop) {\n\t\tconst { transform: cropTransform, width, height } = containerStyle\n\t\tconst croppedWidth = (crop.bottomRight.x - crop.topLeft.x) * width\n\t\tconst croppedHeight = (crop.bottomRight.y - crop.topLeft.y) * height\n\n\t\tconst points = [\n\t\t\tnew Vec(0, 0),\n\t\t\tnew Vec(croppedWidth, 0),\n\t\t\tnew Vec(croppedWidth, croppedHeight),\n\t\t\tnew Vec(0, croppedHeight),\n\t\t]\n\n\t\tconst flip = getFlipStyle(shape, { width, height })\n\n\t\treturn (\n\t\t\t<>\n\t\t\t\t<defs>\n\t\t\t\t\t<clipPath id={cropClipId}>\n\t\t\t\t\t\t{crop.isCircle ? (\n\t\t\t\t\t\t\t<ellipse\n\t\t\t\t\t\t\t\tcx={croppedWidth / 2}\n\t\t\t\t\t\t\t\tcy={croppedHeight / 2}\n\t\t\t\t\t\t\t\trx={croppedWidth / 2}\n\t\t\t\t\t\t\t\try={croppedHeight / 2}\n\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t) : (\n\t\t\t\t\t\t\t<polygon points={points.map((p) => `${p.x},${p.y}`).join(' ')} />\n\t\t\t\t\t\t)}\n\t\t\t\t\t</clipPath>\n\t\t\t\t</defs>\n\t\t\t\t<g clipPath={`url(#${cropClipId})`}>\n\t\t\t\t\t<image\n\t\t\t\t\t\thref={src}\n\t\t\t\t\t\twidth={width}\n\t\t\t\t\t\theight={height}\n\t\t\t\t\t\taria-label={shape.props.altText}\n\t\t\t\t\t\tstyle={flip ? { ...flip } : { transform: cropTransform }}\n\t\t\t\t\t/>\n\t\t\t\t</g>\n\t\t\t</>\n\t\t)\n\t} else {\n\t\treturn (\n\t\t\t<image\n\t\t\t\thref={src}\n\t\t\t\twidth={shape.props.w}\n\t\t\t\theight={shape.props.h}\n\t\t\t\taria-label={shape.props.altText}\n\t\t\t\tstyle={getFlipStyle(shape, { width: shape.props.w, height: shape.props.h })}\n\t\t\t/>\n\t\t)\n\t}\n}\n\nfunction getFirstFrameOfAnimatedImage(url: string) {\n\tlet cancelled = false\n\n\tconst promise = new Promise<string>((resolve) => {\n\t\tconst image = Image()\n\t\timage.onload = () => {\n\t\t\tif (cancelled) return\n\n\t\t\tconst canvas = document.createElement('canvas')\n\t\t\tcanvas.width = image.width\n\t\t\tcanvas.height = image.height\n\n\t\t\tconst ctx = canvas.getContext('2d')\n\t\t\tif (!ctx) return\n\n\t\t\tctx.drawImage(image, 0, 0)\n\t\t\tresolve(canvas.toDataURL())\n\t\t}\n\t\timage.crossOrigin = 'anonymous'\n\t\timage.src = url\n\t})\n\n\treturn { promise, cancel: () => (cancelled = true) }\n}\n"],
|
|
5
|
-
"mappings": "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",
|
|
4
|
+
"sourcesContent": ["import {\n\tBaseBoxShapeUtil,\n\tEditor,\n\tEllipse2d,\n\tFileHelpers,\n\tGeometry2d,\n\tHTMLContainer,\n\tImage,\n\tMediaHelpers,\n\tRectangle2d,\n\tSvgExportContext,\n\tTLAsset,\n\tTLAssetId,\n\tTLImageShape,\n\tTLImageShapeProps,\n\tTLResizeInfo,\n\tTLShapePartial,\n\tVec,\n\tWeakCache,\n\tfetch,\n\timageShapeMigrations,\n\timageShapeProps,\n\tlerp,\n\tmodulate,\n\tresizeBox,\n\tstructuredClone,\n\ttoDomPrecision,\n\tuseEditor,\n\tuseUniqueSafeId,\n\tuseValue,\n} from '@tldraw/editor'\nimport classNames from 'classnames'\nimport { memo, useEffect, useState } from 'react'\nimport { BrokenAssetIcon } from '../shared/BrokenAssetIcon'\nimport { HyperlinkButton } from '../shared/HyperlinkButton'\nimport { getUncroppedSize } from '../shared/crop'\nimport { useImageOrVideoAsset } from '../shared/useImageOrVideoAsset'\nimport { usePrefersReducedMotion } from '../shared/usePrefersReducedMotion'\n\nasync function getDataURIFromURL(url: string): Promise<string> {\n\tconst response = await fetch(url)\n\tconst blob = await response.blob()\n\treturn FileHelpers.blobToDataUrl(blob)\n}\n\nconst imageSvgExportCache = new WeakCache<TLAsset, Promise<string | null>>()\n\n/** @public */\nexport class ImageShapeUtil extends BaseBoxShapeUtil<TLImageShape> {\n\tstatic override type = 'image' as const\n\tstatic override props = imageShapeProps\n\tstatic override migrations = imageShapeMigrations\n\n\toverride isAspectRatioLocked() {\n\t\treturn true\n\t}\n\toverride canCrop() {\n\t\treturn true\n\t}\n\toverride isExportBoundsContainer(): boolean {\n\t\treturn true\n\t}\n\n\toverride getDefaultProps(): TLImageShape['props'] {\n\t\treturn {\n\t\t\tw: 100,\n\t\t\th: 100,\n\t\t\tassetId: null,\n\t\t\tplaying: true,\n\t\t\turl: '',\n\t\t\tcrop: null,\n\t\t\tflipX: false,\n\t\t\tflipY: false,\n\t\t\taltText: '',\n\t\t}\n\t}\n\n\toverride getGeometry(shape: TLImageShape): Geometry2d {\n\t\tif (shape.props.crop?.isCircle) {\n\t\t\treturn new Ellipse2d({\n\t\t\t\twidth: shape.props.w,\n\t\t\t\theight: shape.props.h,\n\t\t\t\tisFilled: true,\n\t\t\t})\n\t\t}\n\n\t\treturn new Rectangle2d({\n\t\t\twidth: shape.props.w,\n\t\t\theight: shape.props.h,\n\t\t\tisFilled: true,\n\t\t})\n\t}\n\n\toverride getAriaDescriptor(shape: TLImageShape) {\n\t\treturn shape.props.altText\n\t}\n\n\toverride onResize(shape: TLImageShape, info: TLResizeInfo<TLImageShape>) {\n\t\tlet resized: TLImageShape = resizeBox(shape, info)\n\t\tconst { flipX, flipY } = info.initialShape.props\n\t\tconst { scaleX, scaleY, mode } = info\n\n\t\tresized = {\n\t\t\t...resized,\n\t\t\tprops: {\n\t\t\t\t...resized.props,\n\t\t\t\tflipX: scaleX < 0 !== flipX,\n\t\t\t\tflipY: scaleY < 0 !== flipY,\n\t\t\t},\n\t\t}\n\t\tif (!shape.props.crop) return resized\n\n\t\tconst flipCropHorizontally =\n\t\t\t// We used the flip horizontally feature\n\t\t\t(mode === 'scale_shape' && scaleX === -1) ||\n\t\t\t// We resized the shape past it's bounds, so it flipped\n\t\t\t(mode === 'resize_bounds' && flipX !== resized.props.flipX)\n\t\tconst flipCropVertically =\n\t\t\t// We used the flip vertically feature\n\t\t\t(mode === 'scale_shape' && scaleY === -1) ||\n\t\t\t// We resized the shape past it's bounds, so it flipped\n\t\t\t(mode === 'resize_bounds' && flipY !== resized.props.flipY)\n\n\t\tconst { topLeft, bottomRight } = shape.props.crop\n\t\tresized.props.crop = {\n\t\t\ttopLeft: {\n\t\t\t\tx: flipCropHorizontally ? 1 - bottomRight.x : topLeft.x,\n\t\t\t\ty: flipCropVertically ? 1 - bottomRight.y : topLeft.y,\n\t\t\t},\n\t\t\tbottomRight: {\n\t\t\t\tx: flipCropHorizontally ? 1 - topLeft.x : bottomRight.x,\n\t\t\t\ty: flipCropVertically ? 1 - topLeft.y : bottomRight.y,\n\t\t\t},\n\t\t\tisCircle: shape.props.crop.isCircle,\n\t\t}\n\t\treturn resized\n\t}\n\n\tcomponent(shape: TLImageShape) {\n\t\treturn <ImageShape shape={shape} />\n\t}\n\n\tindicator(shape: TLImageShape) {\n\t\tconst isCropping = this.editor.getCroppingShapeId() === shape.id\n\t\tif (isCropping) return null\n\n\t\tif (shape.props.crop?.isCircle) {\n\t\t\treturn (\n\t\t\t\t<ellipse\n\t\t\t\t\tcx={toDomPrecision(shape.props.w / 2)}\n\t\t\t\t\tcy={toDomPrecision(shape.props.h / 2)}\n\t\t\t\t\trx={toDomPrecision(shape.props.w / 2)}\n\t\t\t\t\try={toDomPrecision(shape.props.h / 2)}\n\t\t\t\t/>\n\t\t\t)\n\t\t}\n\n\t\treturn <rect width={toDomPrecision(shape.props.w)} height={toDomPrecision(shape.props.h)} />\n\t}\n\n\toverride async toSvg(shape: TLImageShape, ctx: SvgExportContext) {\n\t\tconst props = shape.props\n\t\tif (!props.assetId) return null\n\n\t\tconst asset = this.editor.getAsset(props.assetId)\n\n\t\tif (!asset) return null\n\n\t\tconst { w } = getUncroppedSize(shape.props, props.crop)\n\n\t\tconst src = await imageSvgExportCache.get(asset, async () => {\n\t\t\tlet src = await ctx.resolveAssetUrl(asset.id, w)\n\t\t\tif (!src) return null\n\t\t\tif (\n\t\t\t\tsrc.startsWith('blob:') ||\n\t\t\t\tsrc.startsWith('http') ||\n\t\t\t\tsrc.startsWith('/') ||\n\t\t\t\tsrc.startsWith('./')\n\t\t\t) {\n\t\t\t\t// If it's a remote image, we need to fetch it and convert it to a data URI\n\t\t\t\tsrc = (await getDataURIFromURL(src)) || ''\n\t\t\t}\n\n\t\t\t// If it's animated then we need to get the first frame\n\t\t\tif (getIsAnimated(this.editor, asset.id)) {\n\t\t\t\tconst { promise } = getFirstFrameOfAnimatedImage(src)\n\t\t\t\tsrc = await promise\n\t\t\t}\n\t\t\treturn src\n\t\t})\n\n\t\tif (!src) return null\n\n\t\treturn <SvgImage shape={shape} src={src} />\n\t}\n\n\toverride onDoubleClickEdge(shape: TLImageShape) {\n\t\tconst props = shape.props\n\t\tif (!props) return\n\n\t\tif (this.editor.getCroppingShapeId() !== shape.id) {\n\t\t\treturn\n\t\t}\n\n\t\tconst crop = structuredClone(props.crop) || {\n\t\t\ttopLeft: { x: 0, y: 0 },\n\t\t\tbottomRight: { x: 1, y: 1 },\n\t\t}\n\n\t\t// The true asset dimensions\n\t\tconst { w, h } = getUncroppedSize(shape.props, crop)\n\n\t\tconst pointDelta = new Vec(crop.topLeft.x * w, crop.topLeft.y * h).rot(shape.rotation)\n\n\t\tconst partial: TLShapePartial<TLImageShape> = {\n\t\t\tid: shape.id,\n\t\t\ttype: shape.type,\n\t\t\tx: shape.x - pointDelta.x,\n\t\t\ty: shape.y - pointDelta.y,\n\t\t\tprops: {\n\t\t\t\tcrop: {\n\t\t\t\t\ttopLeft: { x: 0, y: 0 },\n\t\t\t\t\tbottomRight: { x: 1, y: 1 },\n\t\t\t\t},\n\t\t\t\tw,\n\t\t\t\th,\n\t\t\t},\n\t\t}\n\n\t\tthis.editor.updateShapes([partial])\n\t}\n\toverride getInterpolatedProps(\n\t\tstartShape: TLImageShape,\n\t\tendShape: TLImageShape,\n\t\tt: number\n\t): TLImageShapeProps {\n\t\tfunction interpolateCrop(\n\t\t\tstartShape: TLImageShape,\n\t\t\tendShape: TLImageShape\n\t\t): TLImageShapeProps['crop'] {\n\t\t\tif (startShape.props.crop === null && endShape.props.crop === null) return null\n\n\t\t\tconst startTL = startShape.props.crop?.topLeft || { x: 0, y: 0 }\n\t\t\tconst startBR = startShape.props.crop?.bottomRight || { x: 1, y: 1 }\n\t\t\tconst endTL = endShape.props.crop?.topLeft || { x: 0, y: 0 }\n\t\t\tconst endBR = endShape.props.crop?.bottomRight || { x: 1, y: 1 }\n\n\t\t\treturn {\n\t\t\t\ttopLeft: { x: lerp(startTL.x, endTL.x, t), y: lerp(startTL.y, endTL.y, t) },\n\t\t\t\tbottomRight: { x: lerp(startBR.x, endBR.x, t), y: lerp(startBR.y, endBR.y, t) },\n\t\t\t}\n\t\t}\n\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\tcrop: interpolateCrop(startShape, endShape),\n\t\t}\n\t}\n}\n\nconst ImageShape = memo(function ImageShape({ shape }: { shape: TLImageShape }) {\n\tconst editor = useEditor()\n\n\tconst { w } = getUncroppedSize(shape.props, shape.props.crop)\n\tconst { asset, url } = useImageOrVideoAsset({\n\t\tshapeId: shape.id,\n\t\tassetId: shape.props.assetId,\n\t\twidth: w,\n\t})\n\n\tconst prefersReducedMotion = usePrefersReducedMotion()\n\tconst [staticFrameSrc, setStaticFrameSrc] = useState('')\n\tconst [loadedUrl, setLoadedUrl] = useState<null | string>(null)\n\tconst isAnimated = asset && getIsAnimated(editor, asset.id)\n\n\tuseEffect(() => {\n\t\tif (url && isAnimated) {\n\t\t\tconst { promise, cancel } = getFirstFrameOfAnimatedImage(url)\n\n\t\t\tpromise.then((dataUrl) => {\n\t\t\t\tsetStaticFrameSrc(dataUrl)\n\t\t\t\tsetLoadedUrl(url)\n\t\t\t})\n\n\t\t\treturn () => {\n\t\t\t\tcancel()\n\t\t\t}\n\t\t}\n\t}, [editor, isAnimated, prefersReducedMotion, url])\n\n\tconst showCropPreview = useValue(\n\t\t'show crop preview',\n\t\t() =>\n\t\t\tshape.id === editor.getOnlySelectedShapeId() &&\n\t\t\teditor.getCroppingShapeId() === shape.id &&\n\t\t\teditor.isIn('select.crop'),\n\t\t[editor, shape.id]\n\t)\n\n\t// We only want to reduce motion for mimeTypes that have motion\n\tconst reduceMotion =\n\t\tprefersReducedMotion && (asset?.props.mimeType?.includes('video') || isAnimated)\n\n\tconst containerStyle = getCroppedContainerStyle(shape)\n\n\tconst nextSrc = url === loadedUrl ? null : url\n\tconst loadedSrc = reduceMotion ? staticFrameSrc : loadedUrl\n\n\t// This logic path is for when it's broken/missing asset.\n\tif (!url && !asset?.props.src) {\n\t\treturn (\n\t\t\t<HTMLContainer\n\t\t\t\tid={shape.id}\n\t\t\t\tstyle={{\n\t\t\t\t\toverflow: 'hidden',\n\t\t\t\t\twidth: shape.props.w,\n\t\t\t\t\theight: shape.props.h,\n\t\t\t\t\tcolor: 'var(--tl-color-text-3)',\n\t\t\t\t\tbackgroundColor: 'var(--tl-color-low)',\n\t\t\t\t\tborder: '1px solid var(--tl-color-low-border)',\n\t\t\t\t}}\n\t\t\t>\n\t\t\t\t<div\n\t\t\t\t\tclassName={classNames('tl-image-container', asset && 'tl-image-container-loading')}\n\t\t\t\t\tstyle={containerStyle}\n\t\t\t\t>\n\t\t\t\t\t{asset ? null : <BrokenAssetIcon />}\n\t\t\t\t</div>\n\t\t\t\t{'url' in shape.props && shape.props.url && <HyperlinkButton url={shape.props.url} />}\n\t\t\t</HTMLContainer>\n\t\t)\n\t}\n\n\t// We don't set crossOrigin for non-animated images because for Cloudflare we don't currently\n\t// have that set up.\n\tconst crossOrigin = isAnimated ? 'anonymous' : undefined\n\n\treturn (\n\t\t<>\n\t\t\t{showCropPreview && loadedSrc && (\n\t\t\t\t<div style={containerStyle}>\n\t\t\t\t\t<img\n\t\t\t\t\t\tclassName=\"tl-image\"\n\t\t\t\t\t\tstyle={{ ...getFlipStyle(shape), opacity: 0.1 }}\n\t\t\t\t\t\tcrossOrigin={crossOrigin}\n\t\t\t\t\t\tsrc={loadedSrc}\n\t\t\t\t\t\treferrerPolicy=\"strict-origin-when-cross-origin\"\n\t\t\t\t\t\tdraggable={false}\n\t\t\t\t\t\talt=\"\"\n\t\t\t\t\t/>\n\t\t\t\t</div>\n\t\t\t)}\n\t\t\t<HTMLContainer\n\t\t\t\tid={shape.id}\n\t\t\t\tstyle={{\n\t\t\t\t\toverflow: 'hidden',\n\t\t\t\t\twidth: shape.props.w,\n\t\t\t\t\theight: shape.props.h,\n\t\t\t\t\tborderRadius: shape.props.crop?.isCircle ? '50%' : undefined,\n\t\t\t\t}}\n\t\t\t>\n\t\t\t\t<div className={classNames('tl-image-container')} style={containerStyle}>\n\t\t\t\t\t{/* We have two images: the currently loaded image, and the next image that\n\t\t\t\t\twe're waiting to load. we keep the loaded image mounted while we're waiting\n\t\t\t\t\tfor the next one by storing the loaded URL in state. We use `key` props with\n\t\t\t\t\tthe src of the image so that when the next image is ready, the previous one will\n\t\t\t\t\tbe unmounted and the next will be shown with the browser having to remount a\n\t\t\t\t\tfresh image and decoded it again from the cache. */}\n\t\t\t\t\t{loadedSrc && (\n\t\t\t\t\t\t<img\n\t\t\t\t\t\t\tkey={loadedSrc}\n\t\t\t\t\t\t\tclassName=\"tl-image\"\n\t\t\t\t\t\t\tstyle={getFlipStyle(shape)}\n\t\t\t\t\t\t\tcrossOrigin={crossOrigin}\n\t\t\t\t\t\t\tsrc={loadedSrc}\n\t\t\t\t\t\t\treferrerPolicy=\"strict-origin-when-cross-origin\"\n\t\t\t\t\t\t\tdraggable={false}\n\t\t\t\t\t\t\talt=\"\"\n\t\t\t\t\t\t/>\n\t\t\t\t\t)}\n\t\t\t\t\t{nextSrc && (\n\t\t\t\t\t\t<img\n\t\t\t\t\t\t\tkey={nextSrc}\n\t\t\t\t\t\t\tclassName=\"tl-image\"\n\t\t\t\t\t\t\tstyle={getFlipStyle(shape)}\n\t\t\t\t\t\t\tcrossOrigin={crossOrigin}\n\t\t\t\t\t\t\tsrc={nextSrc}\n\t\t\t\t\t\t\treferrerPolicy=\"strict-origin-when-cross-origin\"\n\t\t\t\t\t\t\tdraggable={false}\n\t\t\t\t\t\t\talt={shape.props.altText}\n\t\t\t\t\t\t\tonLoad={() => setLoadedUrl(nextSrc)}\n\t\t\t\t\t\t/>\n\t\t\t\t\t)}\n\t\t\t\t</div>\n\t\t\t\t{shape.props.url && <HyperlinkButton url={shape.props.url} />}\n\t\t\t</HTMLContainer>\n\t\t</>\n\t)\n})\n\nfunction getIsAnimated(editor: Editor, assetId: TLAssetId) {\n\tconst asset = assetId ? editor.getAsset(assetId) : undefined\n\n\tif (!asset) return false\n\n\treturn (\n\t\t('mimeType' in asset.props && MediaHelpers.isAnimatedImageType(asset?.props.mimeType)) ||\n\t\t('isAnimated' in asset.props && asset.props.isAnimated)\n\t)\n}\n\n/**\n * When an image is cropped we need to translate the image to show the portion withing the cropped\n * area. We do this by translating the image by the negative of the top left corner of the crop\n * area.\n *\n * @param shape - Shape The image shape for which to get the container style\n * @returns - Styles to apply to the image container\n */\nfunction getCroppedContainerStyle(shape: TLImageShape) {\n\tconst crop = shape.props.crop\n\tconst topLeft = crop?.topLeft\n\tif (!topLeft) {\n\t\treturn {\n\t\t\twidth: shape.props.w,\n\t\t\theight: shape.props.h,\n\t\t}\n\t}\n\n\tconst { w, h } = getUncroppedSize(shape.props, crop)\n\tconst offsetX = -topLeft.x * w\n\tconst offsetY = -topLeft.y * h\n\treturn {\n\t\ttransform: `translate(${offsetX}px, ${offsetY}px)`,\n\t\twidth: w,\n\t\theight: h,\n\t}\n}\n\nfunction getFlipStyle(shape: TLImageShape, size?: { width: number; height: number }) {\n\tconst { flipX, flipY, crop } = shape.props\n\tif (!flipX && !flipY) return undefined\n\n\tlet cropOffsetX\n\tlet cropOffsetY\n\tif (crop) {\n\t\t// We have to do all this extra math because of the whole transform origin around 0,0\n\t\t// instead of center in SVG-land, ugh.\n\t\tconst { w, h } = getUncroppedSize(shape.props, crop)\n\n\t\t// Find the resulting w/h of the crop in normalized (0-1) coordinates\n\t\tconst cropWidth = crop.bottomRight.x - crop.topLeft.x\n\t\tconst cropHeight = crop.bottomRight.y - crop.topLeft.y\n\n\t\t// Map from the normalized crop coordinate space to shape pixel space\n\t\tcropOffsetX = modulate(crop.topLeft.x, [0, 1 - cropWidth], [0, w - shape.props.w])\n\t\tcropOffsetY = modulate(crop.topLeft.y, [0, 1 - cropHeight], [0, h - shape.props.h])\n\t}\n\n\tconst scale = `scale(${flipX ? -1 : 1}, ${flipY ? -1 : 1})`\n\tconst translate = size\n\t\t? `translate(${(flipX ? size.width : 0) - (cropOffsetX ? cropOffsetX : 0)}px,\n\t\t ${(flipY ? size.height : 0) - (cropOffsetY ? cropOffsetY : 0)}px)`\n\t\t: ''\n\n\treturn {\n\t\ttransform: `${translate} ${scale}`,\n\t\t// in SVG, flipping around the center doesn't work so we use explicit width/height\n\t\ttransformOrigin: size ? '0 0' : 'center center',\n\t}\n}\n\nfunction SvgImage({ shape, src }: { shape: TLImageShape; src: string }) {\n\tconst cropClipId = useUniqueSafeId()\n\tconst containerStyle = getCroppedContainerStyle(shape)\n\tconst crop = shape.props.crop\n\n\tif (containerStyle.transform && crop) {\n\t\tconst { transform: cropTransform, width, height } = containerStyle\n\t\tconst croppedWidth = (crop.bottomRight.x - crop.topLeft.x) * width\n\t\tconst croppedHeight = (crop.bottomRight.y - crop.topLeft.y) * height\n\n\t\tconst points = [\n\t\t\tnew Vec(0, 0),\n\t\t\tnew Vec(croppedWidth, 0),\n\t\t\tnew Vec(croppedWidth, croppedHeight),\n\t\t\tnew Vec(0, croppedHeight),\n\t\t]\n\n\t\tconst flip = getFlipStyle(shape, { width, height })\n\n\t\treturn (\n\t\t\t<>\n\t\t\t\t<defs>\n\t\t\t\t\t<clipPath id={cropClipId}>\n\t\t\t\t\t\t{crop.isCircle ? (\n\t\t\t\t\t\t\t<ellipse\n\t\t\t\t\t\t\t\tcx={croppedWidth / 2}\n\t\t\t\t\t\t\t\tcy={croppedHeight / 2}\n\t\t\t\t\t\t\t\trx={croppedWidth / 2}\n\t\t\t\t\t\t\t\try={croppedHeight / 2}\n\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t) : (\n\t\t\t\t\t\t\t<polygon points={points.map((p) => `${p.x},${p.y}`).join(' ')} />\n\t\t\t\t\t\t)}\n\t\t\t\t\t</clipPath>\n\t\t\t\t</defs>\n\t\t\t\t<g clipPath={`url(#${cropClipId})`}>\n\t\t\t\t\t<image\n\t\t\t\t\t\thref={src}\n\t\t\t\t\t\twidth={width}\n\t\t\t\t\t\theight={height}\n\t\t\t\t\t\taria-label={shape.props.altText}\n\t\t\t\t\t\tstyle={flip ? { ...flip } : { transform: cropTransform }}\n\t\t\t\t\t/>\n\t\t\t\t</g>\n\t\t\t</>\n\t\t)\n\t} else {\n\t\treturn (\n\t\t\t<image\n\t\t\t\thref={src}\n\t\t\t\twidth={shape.props.w}\n\t\t\t\theight={shape.props.h}\n\t\t\t\taria-label={shape.props.altText}\n\t\t\t\tstyle={getFlipStyle(shape, { width: shape.props.w, height: shape.props.h })}\n\t\t\t/>\n\t\t)\n\t}\n}\n\nfunction getFirstFrameOfAnimatedImage(url: string) {\n\tlet cancelled = false\n\n\tconst promise = new Promise<string>((resolve) => {\n\t\tconst image = Image()\n\t\timage.onload = () => {\n\t\t\tif (cancelled) return\n\n\t\t\tconst canvas = document.createElement('canvas')\n\t\t\tcanvas.width = image.width\n\t\t\tcanvas.height = image.height\n\n\t\t\tconst ctx = canvas.getContext('2d')\n\t\t\tif (!ctx) return\n\n\t\t\tctx.drawImage(image, 0, 0)\n\t\t\tresolve(canvas.toDataURL())\n\t\t}\n\t\timage.crossOrigin = 'anonymous'\n\t\timage.src = url\n\t})\n\n\treturn { promise, cancel: () => (cancelled = true) }\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": ["src", "startShape", "endShape", "ImageShape"]
|
|
7
7
|
}
|
|
@@ -7,6 +7,7 @@ import {
|
|
|
7
7
|
WeakCache,
|
|
8
8
|
ZERO_INDEX_KEY,
|
|
9
9
|
assert,
|
|
10
|
+
getColorValue,
|
|
10
11
|
getIndexAbove,
|
|
11
12
|
getIndexBetween,
|
|
12
13
|
getIndices,
|
|
@@ -271,7 +272,11 @@ function LineShapeSvg({
|
|
|
271
272
|
strokeWidth,
|
|
272
273
|
forceSolid,
|
|
273
274
|
randomSeed: shape.id,
|
|
274
|
-
props: {
|
|
275
|
+
props: {
|
|
276
|
+
transform: `scale(${scale})`,
|
|
277
|
+
stroke: getColorValue(theme, color, "solid"),
|
|
278
|
+
fill: "none"
|
|
279
|
+
}
|
|
275
280
|
});
|
|
276
281
|
}
|
|
277
282
|
export {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../../src/lib/shapes/line/LineShapeUtil.tsx"],
|
|
4
|
-
"sourcesContent": ["import {\n\tGroup2d,\n\tHandleSnapGeometry,\n\tSVGContainer,\n\tShapeUtil,\n\tTLHandle,\n\tTLHandleDragInfo,\n\tTLLineShape,\n\tTLLineShapePoint,\n\tTLResizeInfo,\n\tVec,\n\tWeakCache,\n\tZERO_INDEX_KEY,\n\tassert,\n\tgetIndexAbove,\n\tgetIndexBetween,\n\tgetIndices,\n\tlerp,\n\tlineShapeMigrations,\n\tlineShapeProps,\n\tmapObjectMapValues,\n\tmaybeSnapToGrid,\n\tsortByIndex,\n} from '@tldraw/editor'\n\nimport { STROKE_SIZES } from '../arrow/shared'\nimport { PathBuilder, PathBuilderGeometry2d } from '../shared/PathBuilder'\nimport { useDefaultColorTheme } from '../shared/useDefaultColorTheme'\n\nconst handlesCache = new WeakCache<TLLineShape['props'], TLHandle[]>()\n\n/** @public */\nexport class LineShapeUtil extends ShapeUtil<TLLineShape> {\n\tstatic override type = 'line' as const\n\tstatic override props = lineShapeProps\n\tstatic override migrations = lineShapeMigrations\n\n\toverride hideResizeHandles() {\n\t\treturn true\n\t}\n\toverride hideRotateHandle() {\n\t\treturn true\n\t}\n\toverride hideSelectionBoundsFg() {\n\t\treturn true\n\t}\n\toverride hideSelectionBoundsBg() {\n\t\treturn true\n\t}\n\n\toverride getDefaultProps(): TLLineShape['props'] {\n\t\tconst [start, end] = getIndices(2)\n\t\treturn {\n\t\t\tdash: 'draw',\n\t\t\tsize: 'm',\n\t\t\tcolor: 'black',\n\t\t\tspline: 'line',\n\t\t\tpoints: {\n\t\t\t\t[start]: { id: start, index: start, x: 0, y: 0 },\n\t\t\t\t[end]: { id: end, index: end, x: 0.1, y: 0.1 },\n\t\t\t},\n\t\t\tscale: 1,\n\t\t}\n\t}\n\n\tgetGeometry(shape: TLLineShape) {\n\t\t// todo: should we have min size?\n\t\tconst geometry = getPathForLineShape(shape).toGeometry()\n\t\tassert(geometry instanceof PathBuilderGeometry2d)\n\t\treturn geometry\n\t}\n\n\toverride getHandles(shape: TLLineShape) {\n\t\treturn handlesCache.get(shape.props, () => {\n\t\t\tconst spline = this.getGeometry(shape)\n\n\t\t\tconst points = linePointsToArray(shape)\n\t\t\tconst results: TLHandle[] = points.map((point) => ({\n\t\t\t\t...point,\n\t\t\t\tid: point.index,\n\t\t\t\ttype: 'vertex',\n\t\t\t\tcanSnap: true,\n\t\t\t}))\n\n\t\t\tfor (let i = 0; i < points.length - 1; i++) {\n\t\t\t\tconst index = getIndexBetween(points[i].index, points[i + 1].index)\n\t\t\t\tconst segment = spline.getSegments()[i]\n\t\t\t\tconst point = segment.interpolateAlongEdge(0.5)\n\t\t\t\tresults.push({\n\t\t\t\t\tid: index,\n\t\t\t\t\ttype: 'create',\n\t\t\t\t\tindex,\n\t\t\t\t\tx: point.x,\n\t\t\t\t\ty: point.y,\n\t\t\t\t\tcanSnap: true,\n\t\t\t\t})\n\t\t\t}\n\n\t\t\treturn results.sort(sortByIndex)\n\t\t})\n\t}\n\n\t// Events\n\n\toverride onResize(shape: TLLineShape, info: TLResizeInfo<TLLineShape>) {\n\t\tconst { scaleX, scaleY } = info\n\n\t\treturn {\n\t\t\tprops: {\n\t\t\t\tpoints: mapObjectMapValues(shape.props.points, (_, { id, index, x, y }) => ({\n\t\t\t\t\tid,\n\t\t\t\t\tindex,\n\t\t\t\t\tx: x * scaleX,\n\t\t\t\t\ty: y * scaleY,\n\t\t\t\t})),\n\t\t\t},\n\t\t}\n\t}\n\n\toverride onBeforeCreate(next: TLLineShape): void | TLLineShape {\n\t\tconst {\n\t\t\tprops: { points },\n\t\t} = next\n\t\tconst pointKeys = Object.keys(points)\n\n\t\tif (pointKeys.length < 2) {\n\t\t\treturn\n\t\t}\n\n\t\tconst firstPoint = points[pointKeys[0]]\n\t\tconst allSame = pointKeys.every((key) => {\n\t\t\tconst point = points[key]\n\t\t\treturn point.x === firstPoint.x && point.y === firstPoint.y\n\t\t})\n\t\tif (allSame) {\n\t\t\tconst lastKey = pointKeys[pointKeys.length - 1]\n\t\t\tpoints[lastKey] = {\n\t\t\t\t...points[lastKey],\n\t\t\t\tx: points[lastKey].x + 0.1,\n\t\t\t\ty: points[lastKey].y + 0.1,\n\t\t\t}\n\t\t\treturn next\n\t\t}\n\t\treturn\n\t}\n\n\toverride onHandleDrag(shape: TLLineShape, { handle }: TLHandleDragInfo<TLLineShape>) {\n\t\tconst newPoint = maybeSnapToGrid(new Vec(handle.x, handle.y), this.editor)\n\t\treturn {\n\t\t\t...shape,\n\t\t\tprops: {\n\t\t\t\t...shape.props,\n\t\t\t\tpoints: {\n\t\t\t\t\t...shape.props.points,\n\t\t\t\t\t[handle.id]: { id: handle.id, index: handle.index, x: newPoint.x, y: newPoint.y },\n\t\t\t\t},\n\t\t\t},\n\t\t}\n\t}\n\n\toverride onHandleDragStart(shape: TLLineShape, { handle }: TLHandleDragInfo<TLLineShape>) {\n\t\t// For line shapes, if we're dragging a \"create\" handle, then\n\t\t// create a new vertex handle at that point; and make this handle\n\t\t// the handle that we're dragging.\n\t\tif (handle.type === 'create') {\n\t\t\treturn {\n\t\t\t\t...shape,\n\t\t\t\tprops: {\n\t\t\t\t\t...shape.props,\n\t\t\t\t\tpoints: {\n\t\t\t\t\t\t...shape.props.points,\n\t\t\t\t\t\t[handle.index]: { id: handle.index, index: handle.index, x: handle.x, y: handle.y },\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t}\n\t\t}\n\t\treturn\n\t}\n\n\tcomponent(shape: TLLineShape) {\n\t\treturn (\n\t\t\t<SVGContainer style={{ minWidth: 50, minHeight: 50 }}>\n\t\t\t\t<LineShapeSvg shape={shape} />\n\t\t\t</SVGContainer>\n\t\t)\n\t}\n\n\tindicator(shape: TLLineShape) {\n\t\tconst strokeWidth = STROKE_SIZES[shape.props.size] * shape.props.scale\n\t\tconst path = getPathForLineShape(shape)\n\t\tconst { dash } = shape.props\n\n\t\treturn path.toSvg({\n\t\t\tstyle: dash === 'draw' ? 'draw' : 'solid',\n\t\t\tstrokeWidth: 1,\n\t\t\tpasses: 1,\n\t\t\trandomSeed: shape.id,\n\t\t\toffset: 0,\n\t\t\troundness: strokeWidth * 2,\n\t\t\tprops: { strokeWidth: undefined },\n\t\t})\n\t}\n\n\toverride toSvg(shape: TLLineShape) {\n\t\treturn <LineShapeSvg shouldScale shape={shape} />\n\t}\n\n\toverride getHandleSnapGeometry(shape: TLLineShape): HandleSnapGeometry {\n\t\tconst points = linePointsToArray(shape)\n\t\treturn {\n\t\t\tpoints,\n\t\t\tgetSelfSnapPoints: (handle) => {\n\t\t\t\tconst index = this.getHandles(shape)\n\t\t\t\t\t.filter((h) => h.type === 'vertex')\n\t\t\t\t\t.findIndex((h) => h.id === handle.id)!\n\n\t\t\t\t// We want to skip the current and adjacent handles\n\t\t\t\treturn points.filter((_, i) => Math.abs(i - index) > 1).map(Vec.From)\n\t\t\t},\n\t\t\tgetSelfSnapOutline: (handle) => {\n\t\t\t\t// We want to skip the segments that include the handle, so\n\t\t\t\t// find the index of the handle that shares the same index property\n\t\t\t\t// as the initial dragging handle; this catches a quirk of create handles\n\t\t\t\tconst index = this.getHandles(shape)\n\t\t\t\t\t.filter((h) => h.type === 'vertex')\n\t\t\t\t\t.findIndex((h) => h.id === handle.id)!\n\n\t\t\t\t// Get all the outline segments from the shape that don't include the handle\n\t\t\t\tconst segments = this.getGeometry(shape)\n\t\t\t\t\t.getSegments()\n\t\t\t\t\t.filter((_, i) => i !== index - 1 && i !== index)\n\n\t\t\t\tif (!segments.length) return null\n\t\t\t\treturn new Group2d({ children: segments })\n\t\t\t},\n\t\t}\n\t}\n\toverride getInterpolatedProps(\n\t\tstartShape: TLLineShape,\n\t\tendShape: TLLineShape,\n\t\tt: number\n\t): TLLineShape['props'] {\n\t\tconst startPoints = linePointsToArray(startShape)\n\t\tconst endPoints = linePointsToArray(endShape)\n\n\t\tconst pointsToUseStart: TLLineShapePoint[] = []\n\t\tconst pointsToUseEnd: TLLineShapePoint[] = []\n\n\t\tlet index = ZERO_INDEX_KEY\n\n\t\tif (startPoints.length > endPoints.length) {\n\t\t\t// we'll need to expand points\n\t\t\tfor (let i = 0; i < startPoints.length; i++) {\n\t\t\t\tpointsToUseStart[i] = { ...startPoints[i] }\n\t\t\t\tif (endPoints[i] === undefined) {\n\t\t\t\t\tpointsToUseEnd[i] = { ...endPoints[endPoints.length - 1], id: index }\n\t\t\t\t} else {\n\t\t\t\t\tpointsToUseEnd[i] = { ...endPoints[i], id: index }\n\t\t\t\t}\n\t\t\t\tindex = getIndexAbove(index)\n\t\t\t}\n\t\t} else if (endPoints.length > startPoints.length) {\n\t\t\t// we'll need to converge points\n\t\t\tfor (let i = 0; i < endPoints.length; i++) {\n\t\t\t\tpointsToUseEnd[i] = { ...endPoints[i] }\n\t\t\t\tif (startPoints[i] === undefined) {\n\t\t\t\t\tpointsToUseStart[i] = {\n\t\t\t\t\t\t...startPoints[startPoints.length - 1],\n\t\t\t\t\t\tid: index,\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tpointsToUseStart[i] = { ...startPoints[i], id: index }\n\t\t\t\t}\n\t\t\t\tindex = getIndexAbove(index)\n\t\t\t}\n\t\t} else {\n\t\t\t// noop, easy\n\t\t\tfor (let i = 0; i < endPoints.length; i++) {\n\t\t\t\tpointsToUseStart[i] = startPoints[i]\n\t\t\t\tpointsToUseEnd[i] = endPoints[i]\n\t\t\t}\n\t\t}\n\n\t\treturn {\n\t\t\t...(t > 0.5 ? endShape.props : startShape.props),\n\t\t\tpoints: Object.fromEntries(\n\t\t\t\tpointsToUseStart.map((point, i) => {\n\t\t\t\t\tconst endPoint = pointsToUseEnd[i]\n\t\t\t\t\treturn [\n\t\t\t\t\t\tpoint.id,\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t...point,\n\t\t\t\t\t\t\tx: lerp(point.x, endPoint.x, t),\n\t\t\t\t\t\t\ty: lerp(point.y, endPoint.y, t),\n\t\t\t\t\t\t},\n\t\t\t\t\t]\n\t\t\t\t})\n\t\t\t),\n\t\t\tscale: lerp(startShape.props.scale, endShape.props.scale, t),\n\t\t}\n\t}\n}\n\nfunction linePointsToArray(shape: TLLineShape) {\n\treturn Object.values(shape.props.points).sort(sortByIndex)\n}\n\nconst pathCache = new WeakCache<TLLineShape, PathBuilder>()\nfunction getPathForLineShape(shape: TLLineShape): PathBuilder {\n\treturn pathCache.get(shape, () => {\n\t\tconst points = linePointsToArray(shape).map(Vec.From)\n\n\t\tswitch (shape.props.spline) {\n\t\t\tcase 'cubic': {\n\t\t\t\treturn PathBuilder.cubicSplineThroughPoints(points, { endOffsets: 0 })\n\t\t\t}\n\t\t\tcase 'line': {\n\t\t\t\treturn PathBuilder.lineThroughPoints(points, { endOffsets: 0 })\n\t\t\t}\n\t\t}\n\t})\n}\n\nfunction LineShapeSvg({\n\tshape,\n\tshouldScale = false,\n\tforceSolid = false,\n}: {\n\tshape: TLLineShape\n\tshouldScale?: boolean\n\tforceSolid?: boolean\n}) {\n\tconst theme = useDefaultColorTheme()\n\n\tconst path = getPathForLineShape(shape)\n\tconst { dash, color, size } = shape.props\n\n\tconst scaleFactor = 1 / shape.props.scale\n\n\tconst scale = shouldScale ? scaleFactor : 1\n\n\tconst strokeWidth = STROKE_SIZES[size] * shape.props.scale\n\n\treturn path.toSvg({\n\t\tstyle: dash,\n\t\tstrokeWidth,\n\t\tforceSolid,\n\t\trandomSeed: shape.id,\n\t\tprops: { transform: `scale(${scale})`, stroke: theme[color].solid, fill: 'none' },\n\t})\n}\n"],
|
|
5
|
-
"mappings": "
|
|
4
|
+
"sourcesContent": ["import {\n\tGroup2d,\n\tHandleSnapGeometry,\n\tSVGContainer,\n\tShapeUtil,\n\tTLHandle,\n\tTLHandleDragInfo,\n\tTLLineShape,\n\tTLLineShapePoint,\n\tTLResizeInfo,\n\tVec,\n\tWeakCache,\n\tZERO_INDEX_KEY,\n\tassert,\n\tgetColorValue,\n\tgetIndexAbove,\n\tgetIndexBetween,\n\tgetIndices,\n\tlerp,\n\tlineShapeMigrations,\n\tlineShapeProps,\n\tmapObjectMapValues,\n\tmaybeSnapToGrid,\n\tsortByIndex,\n} from '@tldraw/editor'\n\nimport { STROKE_SIZES } from '../arrow/shared'\nimport { PathBuilder, PathBuilderGeometry2d } from '../shared/PathBuilder'\nimport { useDefaultColorTheme } from '../shared/useDefaultColorTheme'\n\nconst handlesCache = new WeakCache<TLLineShape['props'], TLHandle[]>()\n\n/** @public */\nexport class LineShapeUtil extends ShapeUtil<TLLineShape> {\n\tstatic override type = 'line' as const\n\tstatic override props = lineShapeProps\n\tstatic override migrations = lineShapeMigrations\n\n\toverride hideResizeHandles() {\n\t\treturn true\n\t}\n\toverride hideRotateHandle() {\n\t\treturn true\n\t}\n\toverride hideSelectionBoundsFg() {\n\t\treturn true\n\t}\n\toverride hideSelectionBoundsBg() {\n\t\treturn true\n\t}\n\n\toverride getDefaultProps(): TLLineShape['props'] {\n\t\tconst [start, end] = getIndices(2)\n\t\treturn {\n\t\t\tdash: 'draw',\n\t\t\tsize: 'm',\n\t\t\tcolor: 'black',\n\t\t\tspline: 'line',\n\t\t\tpoints: {\n\t\t\t\t[start]: { id: start, index: start, x: 0, y: 0 },\n\t\t\t\t[end]: { id: end, index: end, x: 0.1, y: 0.1 },\n\t\t\t},\n\t\t\tscale: 1,\n\t\t}\n\t}\n\n\tgetGeometry(shape: TLLineShape) {\n\t\t// todo: should we have min size?\n\t\tconst geometry = getPathForLineShape(shape).toGeometry()\n\t\tassert(geometry instanceof PathBuilderGeometry2d)\n\t\treturn geometry\n\t}\n\n\toverride getHandles(shape: TLLineShape) {\n\t\treturn handlesCache.get(shape.props, () => {\n\t\t\tconst spline = this.getGeometry(shape)\n\n\t\t\tconst points = linePointsToArray(shape)\n\t\t\tconst results: TLHandle[] = points.map((point) => ({\n\t\t\t\t...point,\n\t\t\t\tid: point.index,\n\t\t\t\ttype: 'vertex',\n\t\t\t\tcanSnap: true,\n\t\t\t}))\n\n\t\t\tfor (let i = 0; i < points.length - 1; i++) {\n\t\t\t\tconst index = getIndexBetween(points[i].index, points[i + 1].index)\n\t\t\t\tconst segment = spline.getSegments()[i]\n\t\t\t\tconst point = segment.interpolateAlongEdge(0.5)\n\t\t\t\tresults.push({\n\t\t\t\t\tid: index,\n\t\t\t\t\ttype: 'create',\n\t\t\t\t\tindex,\n\t\t\t\t\tx: point.x,\n\t\t\t\t\ty: point.y,\n\t\t\t\t\tcanSnap: true,\n\t\t\t\t})\n\t\t\t}\n\n\t\t\treturn results.sort(sortByIndex)\n\t\t})\n\t}\n\n\t// Events\n\n\toverride onResize(shape: TLLineShape, info: TLResizeInfo<TLLineShape>) {\n\t\tconst { scaleX, scaleY } = info\n\n\t\treturn {\n\t\t\tprops: {\n\t\t\t\tpoints: mapObjectMapValues(shape.props.points, (_, { id, index, x, y }) => ({\n\t\t\t\t\tid,\n\t\t\t\t\tindex,\n\t\t\t\t\tx: x * scaleX,\n\t\t\t\t\ty: y * scaleY,\n\t\t\t\t})),\n\t\t\t},\n\t\t}\n\t}\n\n\toverride onBeforeCreate(next: TLLineShape): void | TLLineShape {\n\t\tconst {\n\t\t\tprops: { points },\n\t\t} = next\n\t\tconst pointKeys = Object.keys(points)\n\n\t\tif (pointKeys.length < 2) {\n\t\t\treturn\n\t\t}\n\n\t\tconst firstPoint = points[pointKeys[0]]\n\t\tconst allSame = pointKeys.every((key) => {\n\t\t\tconst point = points[key]\n\t\t\treturn point.x === firstPoint.x && point.y === firstPoint.y\n\t\t})\n\t\tif (allSame) {\n\t\t\tconst lastKey = pointKeys[pointKeys.length - 1]\n\t\t\tpoints[lastKey] = {\n\t\t\t\t...points[lastKey],\n\t\t\t\tx: points[lastKey].x + 0.1,\n\t\t\t\ty: points[lastKey].y + 0.1,\n\t\t\t}\n\t\t\treturn next\n\t\t}\n\t\treturn\n\t}\n\n\toverride onHandleDrag(shape: TLLineShape, { handle }: TLHandleDragInfo<TLLineShape>) {\n\t\tconst newPoint = maybeSnapToGrid(new Vec(handle.x, handle.y), this.editor)\n\t\treturn {\n\t\t\t...shape,\n\t\t\tprops: {\n\t\t\t\t...shape.props,\n\t\t\t\tpoints: {\n\t\t\t\t\t...shape.props.points,\n\t\t\t\t\t[handle.id]: { id: handle.id, index: handle.index, x: newPoint.x, y: newPoint.y },\n\t\t\t\t},\n\t\t\t},\n\t\t}\n\t}\n\n\toverride onHandleDragStart(shape: TLLineShape, { handle }: TLHandleDragInfo<TLLineShape>) {\n\t\t// For line shapes, if we're dragging a \"create\" handle, then\n\t\t// create a new vertex handle at that point; and make this handle\n\t\t// the handle that we're dragging.\n\t\tif (handle.type === 'create') {\n\t\t\treturn {\n\t\t\t\t...shape,\n\t\t\t\tprops: {\n\t\t\t\t\t...shape.props,\n\t\t\t\t\tpoints: {\n\t\t\t\t\t\t...shape.props.points,\n\t\t\t\t\t\t[handle.index]: { id: handle.index, index: handle.index, x: handle.x, y: handle.y },\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t}\n\t\t}\n\t\treturn\n\t}\n\n\tcomponent(shape: TLLineShape) {\n\t\treturn (\n\t\t\t<SVGContainer style={{ minWidth: 50, minHeight: 50 }}>\n\t\t\t\t<LineShapeSvg shape={shape} />\n\t\t\t</SVGContainer>\n\t\t)\n\t}\n\n\tindicator(shape: TLLineShape) {\n\t\tconst strokeWidth = STROKE_SIZES[shape.props.size] * shape.props.scale\n\t\tconst path = getPathForLineShape(shape)\n\t\tconst { dash } = shape.props\n\n\t\treturn path.toSvg({\n\t\t\tstyle: dash === 'draw' ? 'draw' : 'solid',\n\t\t\tstrokeWidth: 1,\n\t\t\tpasses: 1,\n\t\t\trandomSeed: shape.id,\n\t\t\toffset: 0,\n\t\t\troundness: strokeWidth * 2,\n\t\t\tprops: { strokeWidth: undefined },\n\t\t})\n\t}\n\n\toverride toSvg(shape: TLLineShape) {\n\t\treturn <LineShapeSvg shouldScale shape={shape} />\n\t}\n\n\toverride getHandleSnapGeometry(shape: TLLineShape): HandleSnapGeometry {\n\t\tconst points = linePointsToArray(shape)\n\t\treturn {\n\t\t\tpoints,\n\t\t\tgetSelfSnapPoints: (handle) => {\n\t\t\t\tconst index = this.getHandles(shape)\n\t\t\t\t\t.filter((h) => h.type === 'vertex')\n\t\t\t\t\t.findIndex((h) => h.id === handle.id)!\n\n\t\t\t\t// We want to skip the current and adjacent handles\n\t\t\t\treturn points.filter((_, i) => Math.abs(i - index) > 1).map(Vec.From)\n\t\t\t},\n\t\t\tgetSelfSnapOutline: (handle) => {\n\t\t\t\t// We want to skip the segments that include the handle, so\n\t\t\t\t// find the index of the handle that shares the same index property\n\t\t\t\t// as the initial dragging handle; this catches a quirk of create handles\n\t\t\t\tconst index = this.getHandles(shape)\n\t\t\t\t\t.filter((h) => h.type === 'vertex')\n\t\t\t\t\t.findIndex((h) => h.id === handle.id)!\n\n\t\t\t\t// Get all the outline segments from the shape that don't include the handle\n\t\t\t\tconst segments = this.getGeometry(shape)\n\t\t\t\t\t.getSegments()\n\t\t\t\t\t.filter((_, i) => i !== index - 1 && i !== index)\n\n\t\t\t\tif (!segments.length) return null\n\t\t\t\treturn new Group2d({ children: segments })\n\t\t\t},\n\t\t}\n\t}\n\toverride getInterpolatedProps(\n\t\tstartShape: TLLineShape,\n\t\tendShape: TLLineShape,\n\t\tt: number\n\t): TLLineShape['props'] {\n\t\tconst startPoints = linePointsToArray(startShape)\n\t\tconst endPoints = linePointsToArray(endShape)\n\n\t\tconst pointsToUseStart: TLLineShapePoint[] = []\n\t\tconst pointsToUseEnd: TLLineShapePoint[] = []\n\n\t\tlet index = ZERO_INDEX_KEY\n\n\t\tif (startPoints.length > endPoints.length) {\n\t\t\t// we'll need to expand points\n\t\t\tfor (let i = 0; i < startPoints.length; i++) {\n\t\t\t\tpointsToUseStart[i] = { ...startPoints[i] }\n\t\t\t\tif (endPoints[i] === undefined) {\n\t\t\t\t\tpointsToUseEnd[i] = { ...endPoints[endPoints.length - 1], id: index }\n\t\t\t\t} else {\n\t\t\t\t\tpointsToUseEnd[i] = { ...endPoints[i], id: index }\n\t\t\t\t}\n\t\t\t\tindex = getIndexAbove(index)\n\t\t\t}\n\t\t} else if (endPoints.length > startPoints.length) {\n\t\t\t// we'll need to converge points\n\t\t\tfor (let i = 0; i < endPoints.length; i++) {\n\t\t\t\tpointsToUseEnd[i] = { ...endPoints[i] }\n\t\t\t\tif (startPoints[i] === undefined) {\n\t\t\t\t\tpointsToUseStart[i] = {\n\t\t\t\t\t\t...startPoints[startPoints.length - 1],\n\t\t\t\t\t\tid: index,\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tpointsToUseStart[i] = { ...startPoints[i], id: index }\n\t\t\t\t}\n\t\t\t\tindex = getIndexAbove(index)\n\t\t\t}\n\t\t} else {\n\t\t\t// noop, easy\n\t\t\tfor (let i = 0; i < endPoints.length; i++) {\n\t\t\t\tpointsToUseStart[i] = startPoints[i]\n\t\t\t\tpointsToUseEnd[i] = endPoints[i]\n\t\t\t}\n\t\t}\n\n\t\treturn {\n\t\t\t...(t > 0.5 ? endShape.props : startShape.props),\n\t\t\tpoints: Object.fromEntries(\n\t\t\t\tpointsToUseStart.map((point, i) => {\n\t\t\t\t\tconst endPoint = pointsToUseEnd[i]\n\t\t\t\t\treturn [\n\t\t\t\t\t\tpoint.id,\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t...point,\n\t\t\t\t\t\t\tx: lerp(point.x, endPoint.x, t),\n\t\t\t\t\t\t\ty: lerp(point.y, endPoint.y, t),\n\t\t\t\t\t\t},\n\t\t\t\t\t]\n\t\t\t\t})\n\t\t\t),\n\t\t\tscale: lerp(startShape.props.scale, endShape.props.scale, t),\n\t\t}\n\t}\n}\n\nfunction linePointsToArray(shape: TLLineShape) {\n\treturn Object.values(shape.props.points).sort(sortByIndex)\n}\n\nconst pathCache = new WeakCache<TLLineShape, PathBuilder>()\nfunction getPathForLineShape(shape: TLLineShape): PathBuilder {\n\treturn pathCache.get(shape, () => {\n\t\tconst points = linePointsToArray(shape).map(Vec.From)\n\n\t\tswitch (shape.props.spline) {\n\t\t\tcase 'cubic': {\n\t\t\t\treturn PathBuilder.cubicSplineThroughPoints(points, { endOffsets: 0 })\n\t\t\t}\n\t\t\tcase 'line': {\n\t\t\t\treturn PathBuilder.lineThroughPoints(points, { endOffsets: 0 })\n\t\t\t}\n\t\t}\n\t})\n}\n\nfunction LineShapeSvg({\n\tshape,\n\tshouldScale = false,\n\tforceSolid = false,\n}: {\n\tshape: TLLineShape\n\tshouldScale?: boolean\n\tforceSolid?: boolean\n}) {\n\tconst theme = useDefaultColorTheme()\n\n\tconst path = getPathForLineShape(shape)\n\tconst { dash, color, size } = shape.props\n\n\tconst scaleFactor = 1 / shape.props.scale\n\n\tconst scale = shouldScale ? scaleFactor : 1\n\n\tconst strokeWidth = STROKE_SIZES[size] * shape.props.scale\n\n\treturn path.toSvg({\n\t\tstyle: dash,\n\t\tstrokeWidth,\n\t\tforceSolid,\n\t\trandomSeed: shape.id,\n\t\tprops: {\n\t\t\ttransform: `scale(${scale})`,\n\t\t\tstroke: getColorValue(theme, color, 'solid'),\n\t\t\tfill: 'none',\n\t\t},\n\t})\n}\n"],
|
|
5
|
+
"mappings": "AAuLI;AAvLJ;AAAA,EACC;AAAA,EAEA;AAAA,EACA;AAAA,EAMA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACM;AAEP,SAAS,oBAAoB;AAC7B,SAAS,aAAa,6BAA6B;AACnD,SAAS,4BAA4B;AAErC,MAAM,eAAe,IAAI,UAA4C;AAG9D,MAAM,sBAAsB,UAAuB;AAAA,EACzD,OAAgB,OAAO;AAAA,EACvB,OAAgB,QAAQ;AAAA,EACxB,OAAgB,aAAa;AAAA,EAEpB,oBAAoB;AAC5B,WAAO;AAAA,EACR;AAAA,EACS,mBAAmB;AAC3B,WAAO;AAAA,EACR;AAAA,EACS,wBAAwB;AAChC,WAAO;AAAA,EACR;AAAA,EACS,wBAAwB;AAChC,WAAO;AAAA,EACR;AAAA,EAES,kBAAwC;AAChD,UAAM,CAAC,OAAO,GAAG,IAAI,WAAW,CAAC;AACjC,WAAO;AAAA,MACN,MAAM;AAAA,MACN,MAAM;AAAA,MACN,OAAO;AAAA,MACP,QAAQ;AAAA,MACR,QAAQ;AAAA,QACP,CAAC,KAAK,GAAG,EAAE,IAAI,OAAO,OAAO,OAAO,GAAG,GAAG,GAAG,EAAE;AAAA,QAC/C,CAAC,GAAG,GAAG,EAAE,IAAI,KAAK,OAAO,KAAK,GAAG,KAAK,GAAG,IAAI;AAAA,MAC9C;AAAA,MACA,OAAO;AAAA,IACR;AAAA,EACD;AAAA,EAEA,YAAY,OAAoB;AAE/B,UAAM,WAAW,oBAAoB,KAAK,EAAE,WAAW;AACvD,WAAO,oBAAoB,qBAAqB;AAChD,WAAO;AAAA,EACR;AAAA,EAES,WAAW,OAAoB;AACvC,WAAO,aAAa,IAAI,MAAM,OAAO,MAAM;AAC1C,YAAM,SAAS,KAAK,YAAY,KAAK;AAErC,YAAM,SAAS,kBAAkB,KAAK;AACtC,YAAM,UAAsB,OAAO,IAAI,CAAC,WAAW;AAAA,QAClD,GAAG;AAAA,QACH,IAAI,MAAM;AAAA,QACV,MAAM;AAAA,QACN,SAAS;AAAA,MACV,EAAE;AAEF,eAAS,IAAI,GAAG,IAAI,OAAO,SAAS,GAAG,KAAK;AAC3C,cAAM,QAAQ,gBAAgB,OAAO,CAAC,EAAE,OAAO,OAAO,IAAI,CAAC,EAAE,KAAK;AAClE,cAAM,UAAU,OAAO,YAAY,EAAE,CAAC;AACtC,cAAM,QAAQ,QAAQ,qBAAqB,GAAG;AAC9C,gBAAQ,KAAK;AAAA,UACZ,IAAI;AAAA,UACJ,MAAM;AAAA,UACN;AAAA,UACA,GAAG,MAAM;AAAA,UACT,GAAG,MAAM;AAAA,UACT,SAAS;AAAA,QACV,CAAC;AAAA,MACF;AAEA,aAAO,QAAQ,KAAK,WAAW;AAAA,IAChC,CAAC;AAAA,EACF;AAAA;AAAA,EAIS,SAAS,OAAoB,MAAiC;AACtE,UAAM,EAAE,QAAQ,OAAO,IAAI;AAE3B,WAAO;AAAA,MACN,OAAO;AAAA,QACN,QAAQ,mBAAmB,MAAM,MAAM,QAAQ,CAAC,GAAG,EAAE,IAAI,OAAO,GAAG,EAAE,OAAO;AAAA,UAC3E;AAAA,UACA;AAAA,UACA,GAAG,IAAI;AAAA,UACP,GAAG,IAAI;AAAA,QACR,EAAE;AAAA,MACH;AAAA,IACD;AAAA,EACD;AAAA,EAES,eAAe,MAAuC;AAC9D,UAAM;AAAA,MACL,OAAO,EAAE,OAAO;AAAA,IACjB,IAAI;AACJ,UAAM,YAAY,OAAO,KAAK,MAAM;AAEpC,QAAI,UAAU,SAAS,GAAG;AACzB;AAAA,IACD;AAEA,UAAM,aAAa,OAAO,UAAU,CAAC,CAAC;AACtC,UAAM,UAAU,UAAU,MAAM,CAAC,QAAQ;AACxC,YAAM,QAAQ,OAAO,GAAG;AACxB,aAAO,MAAM,MAAM,WAAW,KAAK,MAAM,MAAM,WAAW;AAAA,IAC3D,CAAC;AACD,QAAI,SAAS;AACZ,YAAM,UAAU,UAAU,UAAU,SAAS,CAAC;AAC9C,aAAO,OAAO,IAAI;AAAA,QACjB,GAAG,OAAO,OAAO;AAAA,QACjB,GAAG,OAAO,OAAO,EAAE,IAAI;AAAA,QACvB,GAAG,OAAO,OAAO,EAAE,IAAI;AAAA,MACxB;AACA,aAAO;AAAA,IACR;AACA;AAAA,EACD;AAAA,EAES,aAAa,OAAoB,EAAE,OAAO,GAAkC;AACpF,UAAM,WAAW,gBAAgB,IAAI,IAAI,OAAO,GAAG,OAAO,CAAC,GAAG,KAAK,MAAM;AACzE,WAAO;AAAA,MACN,GAAG;AAAA,MACH,OAAO;AAAA,QACN,GAAG,MAAM;AAAA,QACT,QAAQ;AAAA,UACP,GAAG,MAAM,MAAM;AAAA,UACf,CAAC,OAAO,EAAE,GAAG,EAAE,IAAI,OAAO,IAAI,OAAO,OAAO,OAAO,GAAG,SAAS,GAAG,GAAG,SAAS,EAAE;AAAA,QACjF;AAAA,MACD;AAAA,IACD;AAAA,EACD;AAAA,EAES,kBAAkB,OAAoB,EAAE,OAAO,GAAkC;AAIzF,QAAI,OAAO,SAAS,UAAU;AAC7B,aAAO;AAAA,QACN,GAAG;AAAA,QACH,OAAO;AAAA,UACN,GAAG,MAAM;AAAA,UACT,QAAQ;AAAA,YACP,GAAG,MAAM,MAAM;AAAA,YACf,CAAC,OAAO,KAAK,GAAG,EAAE,IAAI,OAAO,OAAO,OAAO,OAAO,OAAO,GAAG,OAAO,GAAG,GAAG,OAAO,EAAE;AAAA,UACnF;AAAA,QACD;AAAA,MACD;AAAA,IACD;AACA;AAAA,EACD;AAAA,EAEA,UAAU,OAAoB;AAC7B,WACC,oBAAC,gBAAa,OAAO,EAAE,UAAU,IAAI,WAAW,GAAG,GAClD,8BAAC,gBAAa,OAAc,GAC7B;AAAA,EAEF;AAAA,EAEA,UAAU,OAAoB;AAC7B,UAAM,cAAc,aAAa,MAAM,MAAM,IAAI,IAAI,MAAM,MAAM;AACjE,UAAM,OAAO,oBAAoB,KAAK;AACtC,UAAM,EAAE,KAAK,IAAI,MAAM;AAEvB,WAAO,KAAK,MAAM;AAAA,MACjB,OAAO,SAAS,SAAS,SAAS;AAAA,MAClC,aAAa;AAAA,MACb,QAAQ;AAAA,MACR,YAAY,MAAM;AAAA,MAClB,QAAQ;AAAA,MACR,WAAW,cAAc;AAAA,MACzB,OAAO,EAAE,aAAa,OAAU;AAAA,IACjC,CAAC;AAAA,EACF;AAAA,EAES,MAAM,OAAoB;AAClC,WAAO,oBAAC,gBAAa,aAAW,MAAC,OAAc;AAAA,EAChD;AAAA,EAES,sBAAsB,OAAwC;AACtE,UAAM,SAAS,kBAAkB,KAAK;AACtC,WAAO;AAAA,MACN;AAAA,MACA,mBAAmB,CAAC,WAAW;AAC9B,cAAM,QAAQ,KAAK,WAAW,KAAK,EACjC,OAAO,CAAC,MAAM,EAAE,SAAS,QAAQ,EACjC,UAAU,CAAC,MAAM,EAAE,OAAO,OAAO,EAAE;AAGrC,eAAO,OAAO,OAAO,CAAC,GAAG,MAAM,KAAK,IAAI,IAAI,KAAK,IAAI,CAAC,EAAE,IAAI,IAAI,IAAI;AAAA,MACrE;AAAA,MACA,oBAAoB,CAAC,WAAW;AAI/B,cAAM,QAAQ,KAAK,WAAW,KAAK,EACjC,OAAO,CAAC,MAAM,EAAE,SAAS,QAAQ,EACjC,UAAU,CAAC,MAAM,EAAE,OAAO,OAAO,EAAE;AAGrC,cAAM,WAAW,KAAK,YAAY,KAAK,EACrC,YAAY,EACZ,OAAO,CAAC,GAAG,MAAM,MAAM,QAAQ,KAAK,MAAM,KAAK;AAEjD,YAAI,CAAC,SAAS,OAAQ,QAAO;AAC7B,eAAO,IAAI,QAAQ,EAAE,UAAU,SAAS,CAAC;AAAA,MAC1C;AAAA,IACD;AAAA,EACD;AAAA,EACS,qBACR,YACA,UACA,GACuB;AACvB,UAAM,cAAc,kBAAkB,UAAU;AAChD,UAAM,YAAY,kBAAkB,QAAQ;AAE5C,UAAM,mBAAuC,CAAC;AAC9C,UAAM,iBAAqC,CAAC;AAE5C,QAAI,QAAQ;AAEZ,QAAI,YAAY,SAAS,UAAU,QAAQ;AAE1C,eAAS,IAAI,GAAG,IAAI,YAAY,QAAQ,KAAK;AAC5C,yBAAiB,CAAC,IAAI,EAAE,GAAG,YAAY,CAAC,EAAE;AAC1C,YAAI,UAAU,CAAC,MAAM,QAAW;AAC/B,yBAAe,CAAC,IAAI,EAAE,GAAG,UAAU,UAAU,SAAS,CAAC,GAAG,IAAI,MAAM;AAAA,QACrE,OAAO;AACN,yBAAe,CAAC,IAAI,EAAE,GAAG,UAAU,CAAC,GAAG,IAAI,MAAM;AAAA,QAClD;AACA,gBAAQ,cAAc,KAAK;AAAA,MAC5B;AAAA,IACD,WAAW,UAAU,SAAS,YAAY,QAAQ;AAEjD,eAAS,IAAI,GAAG,IAAI,UAAU,QAAQ,KAAK;AAC1C,uBAAe,CAAC,IAAI,EAAE,GAAG,UAAU,CAAC,EAAE;AACtC,YAAI,YAAY,CAAC,MAAM,QAAW;AACjC,2BAAiB,CAAC,IAAI;AAAA,YACrB,GAAG,YAAY,YAAY,SAAS,CAAC;AAAA,YACrC,IAAI;AAAA,UACL;AAAA,QACD,OAAO;AACN,2BAAiB,CAAC,IAAI,EAAE,GAAG,YAAY,CAAC,GAAG,IAAI,MAAM;AAAA,QACtD;AACA,gBAAQ,cAAc,KAAK;AAAA,MAC5B;AAAA,IACD,OAAO;AAEN,eAAS,IAAI,GAAG,IAAI,UAAU,QAAQ,KAAK;AAC1C,yBAAiB,CAAC,IAAI,YAAY,CAAC;AACnC,uBAAe,CAAC,IAAI,UAAU,CAAC;AAAA,MAChC;AAAA,IACD;AAEA,WAAO;AAAA,MACN,GAAI,IAAI,MAAM,SAAS,QAAQ,WAAW;AAAA,MAC1C,QAAQ,OAAO;AAAA,QACd,iBAAiB,IAAI,CAAC,OAAO,MAAM;AAClC,gBAAM,WAAW,eAAe,CAAC;AACjC,iBAAO;AAAA,YACN,MAAM;AAAA,YACN;AAAA,cACC,GAAG;AAAA,cACH,GAAG,KAAK,MAAM,GAAG,SAAS,GAAG,CAAC;AAAA,cAC9B,GAAG,KAAK,MAAM,GAAG,SAAS,GAAG,CAAC;AAAA,YAC/B;AAAA,UACD;AAAA,QACD,CAAC;AAAA,MACF;AAAA,MACA,OAAO,KAAK,WAAW,MAAM,OAAO,SAAS,MAAM,OAAO,CAAC;AAAA,IAC5D;AAAA,EACD;AACD;AAEA,SAAS,kBAAkB,OAAoB;AAC9C,SAAO,OAAO,OAAO,MAAM,MAAM,MAAM,EAAE,KAAK,WAAW;AAC1D;AAEA,MAAM,YAAY,IAAI,UAAoC;AAC1D,SAAS,oBAAoB,OAAiC;AAC7D,SAAO,UAAU,IAAI,OAAO,MAAM;AACjC,UAAM,SAAS,kBAAkB,KAAK,EAAE,IAAI,IAAI,IAAI;AAEpD,YAAQ,MAAM,MAAM,QAAQ;AAAA,MAC3B,KAAK,SAAS;AACb,eAAO,YAAY,yBAAyB,QAAQ,EAAE,YAAY,EAAE,CAAC;AAAA,MACtE;AAAA,MACA,KAAK,QAAQ;AACZ,eAAO,YAAY,kBAAkB,QAAQ,EAAE,YAAY,EAAE,CAAC;AAAA,MAC/D;AAAA,IACD;AAAA,EACD,CAAC;AACF;AAEA,SAAS,aAAa;AAAA,EACrB;AAAA,EACA,cAAc;AAAA,EACd,aAAa;AACd,GAIG;AACF,QAAM,QAAQ,qBAAqB;AAEnC,QAAM,OAAO,oBAAoB,KAAK;AACtC,QAAM,EAAE,MAAM,OAAO,KAAK,IAAI,MAAM;AAEpC,QAAM,cAAc,IAAI,MAAM,MAAM;AAEpC,QAAM,QAAQ,cAAc,cAAc;AAE1C,QAAM,cAAc,aAAa,IAAI,IAAI,MAAM,MAAM;AAErD,SAAO,KAAK,MAAM;AAAA,IACjB,OAAO;AAAA,IACP;AAAA,IACA;AAAA,IACA,YAAY,MAAM;AAAA,IAClB,OAAO;AAAA,MACN,WAAW,SAAS,KAAK;AAAA,MACzB,QAAQ,cAAc,OAAO,OAAO,OAAO;AAAA,MAC3C,MAAM;AAAA,IACP;AAAA,EACD,CAAC;AACF;",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -8,6 +8,7 @@ import {
|
|
|
8
8
|
Vec,
|
|
9
9
|
WeakCache,
|
|
10
10
|
exhaustiveSwitchError,
|
|
11
|
+
getColorValue,
|
|
11
12
|
getDefaultColorTheme,
|
|
12
13
|
getFontsFromRichText,
|
|
13
14
|
isEqual,
|
|
@@ -107,7 +108,8 @@ class NoteShapeUtil extends ShapeUtil {
|
|
|
107
108
|
width: lw,
|
|
108
109
|
height: lh,
|
|
109
110
|
isFilled: true,
|
|
110
|
-
isLabel: true
|
|
111
|
+
isLabel: true,
|
|
112
|
+
excludeFromShapeBounds: true
|
|
111
113
|
})
|
|
112
114
|
]
|
|
113
115
|
});
|
|
@@ -232,7 +234,7 @@ class NoteShapeUtil extends ShapeUtil {
|
|
|
232
234
|
style: {
|
|
233
235
|
width: nw,
|
|
234
236
|
height: nh,
|
|
235
|
-
backgroundColor: theme
|
|
237
|
+
backgroundColor: getColorValue(theme, color, "noteFill"),
|
|
236
238
|
borderBottom: hideShadows ? isDarkMode ? `${2 * scale}px solid rgb(20, 20, 20)` : `${2 * scale}px solid rgb(144, 144, 144)` : "none",
|
|
237
239
|
boxShadow: hideShadows ? "none" : getNoteShadow(shape.id, rotation, scale)
|
|
238
240
|
},
|
|
@@ -248,7 +250,7 @@ class NoteShapeUtil extends ShapeUtil {
|
|
|
248
250
|
verticalAlign,
|
|
249
251
|
richText,
|
|
250
252
|
isSelected,
|
|
251
|
-
labelColor: labelColor === "black" ? theme
|
|
253
|
+
labelColor: labelColor === "black" ? getColorValue(theme, color, "noteText") : getColorValue(theme, labelColor, "fill"),
|
|
252
254
|
wrap: true,
|
|
253
255
|
padding: LABEL_PADDING * scale,
|
|
254
256
|
hasCustomTabBehavior: true,
|
|
@@ -282,7 +284,7 @@ class NoteShapeUtil extends ShapeUtil {
|
|
|
282
284
|
align: shape.props.align,
|
|
283
285
|
verticalAlign: shape.props.verticalAlign,
|
|
284
286
|
richText: shape.props.richText,
|
|
285
|
-
labelColor: theme
|
|
287
|
+
labelColor: getColorValue(theme, shape.props.color, "noteText"),
|
|
286
288
|
bounds,
|
|
287
289
|
padding: LABEL_PADDING,
|
|
288
290
|
showTextOutline: false
|
|
@@ -296,7 +298,7 @@ class NoteShapeUtil extends ShapeUtil {
|
|
|
296
298
|
rx: 1,
|
|
297
299
|
width: NOTE_SIZE,
|
|
298
300
|
height: bounds.h,
|
|
299
|
-
fill: theme
|
|
301
|
+
fill: getColorValue(theme, shape.props.color, "noteFill")
|
|
300
302
|
}
|
|
301
303
|
),
|
|
302
304
|
textLabel
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../../src/lib/shapes/note/NoteShapeUtil.tsx"],
|
|
4
|
-
"sourcesContent": ["/* eslint-disable react-hooks/rules-of-hooks */\nimport {\n\tBox,\n\tEMPTY_ARRAY,\n\tEditor,\n\tGroup2d,\n\tIndexKey,\n\tRectangle2d,\n\tShapeUtil,\n\tSvgExportContext,\n\tTLHandle,\n\tTLNoteShape,\n\tTLNoteShapeProps,\n\tTLResizeInfo,\n\tTLShape,\n\tTLShapeId,\n\tVec,\n\tWeakCache,\n\texhaustiveSwitchError,\n\tgetDefaultColorTheme,\n\tgetFontsFromRichText,\n\tisEqual,\n\tlerp,\n\tnoteShapeMigrations,\n\tnoteShapeProps,\n\tresizeScaled,\n\trng,\n\ttoDomPrecision,\n\ttoRichText,\n\tuseEditor,\n\tuseValue,\n} from '@tldraw/editor'\nimport { useCallback } from 'react'\nimport { startEditingShapeWithLabel } from '../../tools/SelectTool/selectHelpers'\nimport { useCurrentTranslation } from '../../ui/hooks/useTranslation/useTranslation'\nimport {\n\tisEmptyRichText,\n\trenderHtmlFromRichTextForMeasurement,\n\trenderPlaintextFromRichText,\n} from '../../utils/text/richText'\nimport { isRightToLeftLanguage } from '../../utils/text/text'\nimport { HyperlinkButton } from '../shared/HyperlinkButton'\nimport { RichTextLabel, RichTextSVG } from '../shared/RichTextLabel'\nimport {\n\tFONT_FAMILIES,\n\tLABEL_FONT_SIZES,\n\tLABEL_PADDING,\n\tTEXT_PROPS,\n} from '../shared/default-shape-constants'\nimport { useDefaultColorTheme } from '../shared/useDefaultColorTheme'\nimport { useIsReadyForEditing } from '../shared/useEditablePlainText'\nimport {\n\tCLONE_HANDLE_MARGIN,\n\tNOTE_CENTER_OFFSET,\n\tNOTE_SIZE,\n\tgetNoteShapeForAdjacentPosition,\n} from './noteHelpers'\n\n/** @public */\nexport interface NoteShapeOptions {\n\t/**\n\t * How should the note shape resize? By default it does not resize (except automatically based on its text content),\n\t * but you can set it to be user-resizable using scale.\n\t */\n\tresizeMode: 'none' | 'scale'\n}\n\n/** @public */\nexport class NoteShapeUtil extends ShapeUtil<TLNoteShape> {\n\tstatic override type = 'note' as const\n\tstatic override props = noteShapeProps\n\tstatic override migrations = noteShapeMigrations\n\n\toverride options: NoteShapeOptions = {\n\t\tresizeMode: 'none',\n\t}\n\n\toverride canEdit() {\n\t\treturn true\n\t}\n\toverride hideResizeHandles() {\n\t\tconst { resizeMode } = this.options\n\t\tswitch (resizeMode) {\n\t\t\tcase 'none': {\n\t\t\t\treturn true\n\t\t\t}\n\t\t\tcase 'scale': {\n\t\t\t\treturn false\n\t\t\t}\n\t\t\tdefault: {\n\t\t\t\tthrow exhaustiveSwitchError(resizeMode)\n\t\t\t}\n\t\t}\n\t}\n\n\toverride isAspectRatioLocked() {\n\t\treturn this.options.resizeMode === 'scale'\n\t}\n\n\toverride hideSelectionBoundsFg() {\n\t\treturn false\n\t}\n\n\tgetDefaultProps(): TLNoteShape['props'] {\n\t\treturn {\n\t\t\tcolor: 'black',\n\t\t\trichText: toRichText(''),\n\t\t\tsize: 'm',\n\t\t\tfont: 'draw',\n\t\t\talign: 'middle',\n\t\t\tverticalAlign: 'middle',\n\t\t\tlabelColor: 'black',\n\t\t\tgrowY: 0,\n\t\t\tfontSizeAdjustment: 0,\n\t\t\turl: '',\n\t\t\tscale: 1,\n\t\t}\n\t}\n\n\tgetGeometry(shape: TLNoteShape) {\n\t\tconst { labelHeight, labelWidth } = getLabelSize(this.editor, shape)\n\t\tconst { scale } = shape.props\n\n\t\tconst lh = labelHeight * scale\n\t\tconst lw = labelWidth * scale\n\t\tconst nw = NOTE_SIZE * scale\n\t\tconst nh = getNoteHeight(shape)\n\n\t\treturn new Group2d({\n\t\t\tchildren: [\n\t\t\t\tnew Rectangle2d({ width: nw, height: nh, isFilled: true }),\n\t\t\t\tnew Rectangle2d({\n\t\t\t\t\tx:\n\t\t\t\t\t\tshape.props.align === 'start'\n\t\t\t\t\t\t\t? 0\n\t\t\t\t\t\t\t: shape.props.align === 'end'\n\t\t\t\t\t\t\t\t? nw - lw\n\t\t\t\t\t\t\t\t: (nw - lw) / 2,\n\t\t\t\t\ty:\n\t\t\t\t\t\tshape.props.verticalAlign === 'start'\n\t\t\t\t\t\t\t? 0\n\t\t\t\t\t\t\t: shape.props.verticalAlign === 'end'\n\t\t\t\t\t\t\t\t? nh - lh\n\t\t\t\t\t\t\t\t: (nh - lh) / 2,\n\t\t\t\t\twidth: lw,\n\t\t\t\t\theight: lh,\n\t\t\t\t\tisFilled: true,\n\t\t\t\t\tisLabel: true,\n\t\t\t\t}),\n\t\t\t],\n\t\t})\n\t}\n\n\toverride getHandles(shape: TLNoteShape): TLHandle[] {\n\t\tconst { scale } = shape.props\n\t\tconst isCoarsePointer = this.editor.getInstanceState().isCoarsePointer\n\t\tif (isCoarsePointer) return []\n\n\t\tconst zoom = this.editor.getZoomLevel()\n\t\tif (zoom * scale < 0.25) return []\n\n\t\tconst nh = getNoteHeight(shape)\n\t\tconst nw = NOTE_SIZE * scale\n\t\tconst offset = (CLONE_HANDLE_MARGIN / zoom) * scale\n\n\t\tif (zoom * scale < 0.5) {\n\t\t\treturn [\n\t\t\t\t{\n\t\t\t\t\tid: 'bottom',\n\t\t\t\t\tindex: 'a3' as IndexKey,\n\t\t\t\t\ttype: 'clone',\n\t\t\t\t\tx: nw / 2,\n\t\t\t\t\ty: nh + offset,\n\t\t\t\t},\n\t\t\t]\n\t\t}\n\n\t\treturn [\n\t\t\t{\n\t\t\t\tid: 'top',\n\t\t\t\tindex: 'a1' as IndexKey,\n\t\t\t\ttype: 'clone',\n\t\t\t\tx: nw / 2,\n\t\t\t\ty: -offset,\n\t\t\t},\n\t\t\t{\n\t\t\t\tid: 'right',\n\t\t\t\tindex: 'a2' as IndexKey,\n\t\t\t\ttype: 'clone',\n\t\t\t\tx: nw + offset,\n\t\t\t\ty: nh / 2,\n\t\t\t},\n\t\t\t{\n\t\t\t\tid: 'bottom',\n\t\t\t\tindex: 'a3' as IndexKey,\n\t\t\t\ttype: 'clone',\n\t\t\t\tx: nw / 2,\n\t\t\t\ty: nh + offset,\n\t\t\t},\n\t\t\t{\n\t\t\t\tid: 'left',\n\t\t\t\tindex: 'a4' as IndexKey,\n\t\t\t\ttype: 'clone',\n\t\t\t\tx: -offset,\n\t\t\t\ty: nh / 2,\n\t\t\t},\n\t\t]\n\t}\n\n\toverride onResize(shape: any, info: TLResizeInfo<any>) {\n\t\tconst { resizeMode } = this.options\n\t\tswitch (resizeMode) {\n\t\t\tcase 'none': {\n\t\t\t\treturn undefined\n\t\t\t}\n\t\t\tcase 'scale': {\n\t\t\t\treturn resizeScaled(shape, info)\n\t\t\t}\n\t\t\tdefault: {\n\t\t\t\tthrow exhaustiveSwitchError(resizeMode)\n\t\t\t}\n\t\t}\n\t}\n\n\toverride getText(shape: TLNoteShape) {\n\t\treturn renderPlaintextFromRichText(this.editor, shape.props.richText)\n\t}\n\n\toverride getFontFaces(shape: TLNoteShape) {\n\t\tif (isEmptyRichText(shape.props.richText)) {\n\t\t\treturn EMPTY_ARRAY\n\t\t}\n\t\treturn getFontsFromRichText(this.editor, shape.props.richText, {\n\t\t\tfamily: `tldraw_${shape.props.font}`,\n\t\t\tweight: 'normal',\n\t\t\tstyle: 'normal',\n\t\t})\n\t}\n\n\tcomponent(shape: TLNoteShape) {\n\t\tconst {\n\t\t\tid,\n\t\t\ttype,\n\t\t\tprops: {\n\t\t\t\tlabelColor,\n\t\t\t\tscale,\n\t\t\t\tcolor,\n\t\t\t\tfont,\n\t\t\t\tsize,\n\t\t\t\talign,\n\t\t\t\trichText,\n\t\t\t\tverticalAlign,\n\t\t\t\tfontSizeAdjustment,\n\t\t\t},\n\t\t} = shape\n\n\t\tconst handleKeyDown = useNoteKeydownHandler(id)\n\n\t\tconst theme = useDefaultColorTheme()\n\t\tconst nw = NOTE_SIZE * scale\n\t\tconst nh = getNoteHeight(shape)\n\n\t\tconst rotation = useValue(\n\t\t\t'shape rotation',\n\t\t\t() => this.editor.getShapePageTransform(id)?.rotation() ?? 0,\n\t\t\t[this.editor]\n\t\t)\n\n\t\t// todo: consider hiding shadows on dark mode if they're invisible anyway\n\n\t\tconst hideShadows = useValue('zoom', () => this.editor.getZoomLevel() < 0.35 / scale, [\n\t\t\tscale,\n\t\t\tthis.editor,\n\t\t])\n\n\t\tconst isDarkMode = useValue('dark mode', () => this.editor.user.getIsDarkMode(), [this.editor])\n\n\t\tconst isSelected = shape.id === this.editor.getOnlySelectedShapeId()\n\n\t\tconst isReadyForEditing = useIsReadyForEditing(this.editor, shape.id)\n\t\tconst isEmpty = isEmptyRichText(richText)\n\n\t\treturn (\n\t\t\t<>\n\t\t\t\t<div\n\t\t\t\t\tid={id}\n\t\t\t\t\tclassName=\"tl-note__container\"\n\t\t\t\t\tstyle={{\n\t\t\t\t\t\twidth: nw,\n\t\t\t\t\t\theight: nh,\n\t\t\t\t\t\tbackgroundColor: theme[color].note.fill,\n\t\t\t\t\t\tborderBottom: hideShadows\n\t\t\t\t\t\t\t? isDarkMode\n\t\t\t\t\t\t\t\t? `${2 * scale}px solid rgb(20, 20, 20)`\n\t\t\t\t\t\t\t\t: `${2 * scale}px solid rgb(144, 144, 144)`\n\t\t\t\t\t\t\t: 'none',\n\t\t\t\t\t\tboxShadow: hideShadows ? 'none' : getNoteShadow(shape.id, rotation, scale),\n\t\t\t\t\t}}\n\t\t\t\t>\n\t\t\t\t\t{(isSelected || isReadyForEditing || !isEmpty) && (\n\t\t\t\t\t\t<RichTextLabel\n\t\t\t\t\t\t\tshapeId={id}\n\t\t\t\t\t\t\ttype={type}\n\t\t\t\t\t\t\tfont={font}\n\t\t\t\t\t\t\tfontSize={(fontSizeAdjustment || LABEL_FONT_SIZES[size]) * scale}\n\t\t\t\t\t\t\tlineHeight={TEXT_PROPS.lineHeight}\n\t\t\t\t\t\t\talign={align}\n\t\t\t\t\t\t\tverticalAlign={verticalAlign}\n\t\t\t\t\t\t\trichText={richText}\n\t\t\t\t\t\t\tisSelected={isSelected}\n\t\t\t\t\t\t\tlabelColor={labelColor === 'black' ? theme[color].note.text : theme[labelColor].fill}\n\t\t\t\t\t\t\twrap\n\t\t\t\t\t\t\tpadding={LABEL_PADDING * scale}\n\t\t\t\t\t\t\thasCustomTabBehavior\n\t\t\t\t\t\t\tonKeyDown={handleKeyDown}\n\t\t\t\t\t\t/>\n\t\t\t\t\t)}\n\t\t\t\t</div>\n\t\t\t\t{'url' in shape.props && shape.props.url && <HyperlinkButton url={shape.props.url} />}\n\t\t\t</>\n\t\t)\n\t}\n\n\tindicator(shape: TLNoteShape) {\n\t\tconst { scale } = shape.props\n\t\treturn (\n\t\t\t<rect\n\t\t\t\trx={scale}\n\t\t\t\twidth={toDomPrecision(NOTE_SIZE * scale)}\n\t\t\t\theight={toDomPrecision(getNoteHeight(shape))}\n\t\t\t/>\n\t\t)\n\t}\n\n\toverride toSvg(shape: TLNoteShape, ctx: SvgExportContext) {\n\t\tconst theme = getDefaultColorTheme({ isDarkMode: ctx.isDarkMode })\n\t\tconst bounds = getBoundsForSVG(shape)\n\n\t\tconst textLabel = (\n\t\t\t<RichTextSVG\n\t\t\t\tfontSize={shape.props.fontSizeAdjustment || LABEL_FONT_SIZES[shape.props.size]}\n\t\t\t\tfont={shape.props.font}\n\t\t\t\talign={shape.props.align}\n\t\t\t\tverticalAlign={shape.props.verticalAlign}\n\t\t\t\trichText={shape.props.richText}\n\t\t\t\tlabelColor={theme[shape.props.color].note.text}\n\t\t\t\tbounds={bounds}\n\t\t\t\tpadding={LABEL_PADDING}\n\t\t\t\tshowTextOutline={false}\n\t\t\t/>\n\t\t)\n\n\t\treturn (\n\t\t\t<>\n\t\t\t\t<rect x={5} y={5} rx={1} width={NOTE_SIZE - 10} height={bounds.h} fill=\"rgba(0,0,0,.1)\" />\n\t\t\t\t<rect\n\t\t\t\t\trx={1}\n\t\t\t\t\twidth={NOTE_SIZE}\n\t\t\t\t\theight={bounds.h}\n\t\t\t\t\tfill={theme[shape.props.color].note.fill}\n\t\t\t\t/>\n\t\t\t\t{textLabel}\n\t\t\t</>\n\t\t)\n\t}\n\n\toverride onBeforeCreate(next: TLNoteShape) {\n\t\treturn getNoteSizeAdjustments(this.editor, next)\n\t}\n\n\toverride onBeforeUpdate(prev: TLNoteShape, next: TLNoteShape) {\n\t\tif (\n\t\t\tisEqual(prev.props.richText, next.props.richText) &&\n\t\t\tprev.props.font === next.props.font &&\n\t\t\tprev.props.size === next.props.size\n\t\t) {\n\t\t\treturn\n\t\t}\n\n\t\treturn getNoteSizeAdjustments(this.editor, next)\n\t}\n\n\toverride getInterpolatedProps(\n\t\tstartShape: TLNoteShape,\n\t\tendShape: TLNoteShape,\n\t\tt: number\n\t): TLNoteShapeProps {\n\t\treturn {\n\t\t\t...(t > 0.5 ? endShape.props : startShape.props),\n\t\t\tscale: lerp(startShape.props.scale, endShape.props.scale, t),\n\t\t}\n\t}\n}\n\n/**\n * Get the growY and fontSizeAdjustment for a shape.\n */\nfunction getNoteSizeAdjustments(editor: Editor, shape: TLNoteShape) {\n\tconst { labelHeight, fontSizeAdjustment } = getLabelSize(editor, shape)\n\t// When the label height is more than the height of the shape, we add extra height to it\n\tconst growY = Math.max(0, labelHeight - NOTE_SIZE)\n\n\tif (growY !== shape.props.growY || fontSizeAdjustment !== shape.props.fontSizeAdjustment) {\n\t\treturn {\n\t\t\t...shape,\n\t\t\tprops: {\n\t\t\t\t...shape.props,\n\t\t\t\tgrowY,\n\t\t\t\tfontSizeAdjustment,\n\t\t\t},\n\t\t}\n\t}\n}\n\n/**\n * Get the label size for a note.\n */\nfunction getNoteLabelSize(editor: Editor, shape: TLNoteShape) {\n\tconst { richText } = shape.props\n\n\tif (isEmptyRichText(richText)) {\n\t\tconst minHeight = LABEL_FONT_SIZES[shape.props.size] * TEXT_PROPS.lineHeight + LABEL_PADDING * 2\n\t\treturn { labelHeight: minHeight, labelWidth: 100, fontSizeAdjustment: 0 }\n\t}\n\n\tconst unadjustedFontSize = LABEL_FONT_SIZES[shape.props.size]\n\n\tlet fontSizeAdjustment = 0\n\tlet iterations = 0\n\tlet labelHeight = NOTE_SIZE\n\tlet labelWidth = NOTE_SIZE\n\n\t// N.B. For some note shapes with text like 'hjhjhjhjhjhjhjhj', you'll run into\n\t// some text measurement fuzziness where the browser swears there's no overflow (scrollWidth === width)\n\t// but really there is when you enable overflow-wrap again. This helps account for that little bit\n\t// of give.\n\tconst FUZZ = 1\n\n\t// We slightly make the font smaller if the text is too big for the note, width-wise.\n\tdo {\n\t\tfontSizeAdjustment = Math.min(unadjustedFontSize, unadjustedFontSize - iterations)\n\t\tconst html = renderHtmlFromRichTextForMeasurement(editor, richText)\n\t\tconst nextTextSize = editor.textMeasure.measureHtml(html, {\n\t\t\t...TEXT_PROPS,\n\t\t\tfontFamily: FONT_FAMILIES[shape.props.font],\n\t\t\tfontSize: fontSizeAdjustment,\n\t\t\tmaxWidth: NOTE_SIZE - LABEL_PADDING * 2 - FUZZ,\n\t\t\tdisableOverflowWrapBreaking: true,\n\t\t\tmeasureScrollWidth: true,\n\t\t})\n\n\t\tlabelHeight = nextTextSize.h + LABEL_PADDING * 2\n\t\tlabelWidth = nextTextSize.w + LABEL_PADDING * 2\n\n\t\tif (fontSizeAdjustment <= 14) {\n\t\t\t// Too small, just rely now on CSS `overflow-wrap: break-word`\n\t\t\t// We need to recalculate the text measurement here with break-word enabled.\n\t\t\tconst html = renderHtmlFromRichTextForMeasurement(editor, richText)\n\t\t\tconst nextTextSizeWithOverflowBreak = editor.textMeasure.measureHtml(html, {\n\t\t\t\t...TEXT_PROPS,\n\t\t\t\tfontFamily: FONT_FAMILIES[shape.props.font],\n\t\t\t\tfontSize: fontSizeAdjustment,\n\t\t\t\tmaxWidth: NOTE_SIZE - LABEL_PADDING * 2 - FUZZ,\n\t\t\t})\n\t\t\tlabelHeight = nextTextSizeWithOverflowBreak.h + LABEL_PADDING * 2\n\t\t\tlabelWidth = nextTextSizeWithOverflowBreak.w + LABEL_PADDING * 2\n\t\t\tbreak\n\t\t}\n\n\t\tif (nextTextSize.scrollWidth.toFixed(0) === nextTextSize.w.toFixed(0)) {\n\t\t\tbreak\n\t\t}\n\t} while (iterations++ < 50)\n\n\treturn {\n\t\tlabelHeight: labelHeight,\n\t\tlabelWidth: labelWidth,\n\t\tfontSizeAdjustment: fontSizeAdjustment,\n\t}\n}\n\nconst labelSizesForNote = new WeakCache<TLShape, ReturnType<typeof getNoteLabelSize>>()\n\nfunction getLabelSize(editor: Editor, shape: TLNoteShape) {\n\treturn labelSizesForNote.get(shape, () => getNoteLabelSize(editor, shape))\n}\n\nfunction useNoteKeydownHandler(id: TLShapeId) {\n\tconst editor = useEditor()\n\tconst translation = useCurrentTranslation()\n\n\treturn useCallback(\n\t\t(e: KeyboardEvent) => {\n\t\t\tconst shape = editor.getShape<TLNoteShape>(id)\n\t\t\tif (!shape) return\n\n\t\t\tconst isTab = e.key === 'Tab'\n\t\t\tconst isCmdEnter = (e.metaKey || e.ctrlKey) && e.key === 'Enter'\n\t\t\tif (isTab || isCmdEnter) {\n\t\t\t\te.preventDefault()\n\n\t\t\t\tconst pageTransform = editor.getShapePageTransform(id)\n\t\t\t\tconst pageRotation = pageTransform.rotation()\n\n\t\t\t\t// Based on the inputs, calculate the offset to the next note\n\t\t\t\t// tab controls x axis (shift inverts direction set by RTL)\n\t\t\t\t// cmd enter is the y axis (shift inverts direction)\n\t\t\t\tconst isRTL = !!(\n\t\t\t\t\ttranslation.dir === 'rtl' ||\n\t\t\t\t\t// todo: can we check a partial of the text, so that we don't have to render the whole thing?\n\t\t\t\t\tisRightToLeftLanguage(renderPlaintextFromRichText(editor, shape.props.richText))\n\t\t\t\t)\n\n\t\t\t\tconst offsetLength =\n\t\t\t\t\t(NOTE_SIZE +\n\t\t\t\t\t\teditor.options.adjacentShapeMargin +\n\t\t\t\t\t\t// If we're growing down, we need to account for the current shape's growY\n\t\t\t\t\t\t(isCmdEnter && !e.shiftKey ? shape.props.growY : 0)) *\n\t\t\t\t\tshape.props.scale\n\n\t\t\t\tconst adjacentCenter = new Vec(\n\t\t\t\t\tisTab ? (e.shiftKey != isRTL ? -1 : 1) : 0,\n\t\t\t\t\tisCmdEnter ? (e.shiftKey ? -1 : 1) : 0\n\t\t\t\t)\n\t\t\t\t\t.mul(offsetLength)\n\t\t\t\t\t.add(NOTE_CENTER_OFFSET.clone().mul(shape.props.scale))\n\t\t\t\t\t.rot(pageRotation)\n\t\t\t\t\t.add(pageTransform.point())\n\n\t\t\t\tconst newNote = getNoteShapeForAdjacentPosition(editor, shape, adjacentCenter, pageRotation)\n\n\t\t\t\tif (newNote) {\n\t\t\t\t\tstartEditingShapeWithLabel(editor, newNote, true /* selectAll */)\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\t\t[id, editor, translation.dir]\n\t)\n}\n\nfunction getNoteHeight(shape: TLNoteShape) {\n\treturn (NOTE_SIZE + shape.props.growY) * shape.props.scale\n}\n\nfunction getNoteShadow(id: string, rotation: number, scale: number) {\n\tconst random = rng(id) // seeded based on id\n\tconst lift = Math.abs(random()) + 0.5 // 0 to 1.5\n\tconst oy = Math.cos(rotation)\n\tconst a = 5 * scale\n\tconst b = 4 * scale\n\tconst c = 6 * scale\n\tconst d = 7 * scale\n\treturn `0px ${a - lift}px ${a}px -${a}px rgba(15, 23, 31, .6),\n\t0px ${(b + lift * d) * Math.max(0, oy)}px ${c + lift * d}px -${b + lift * c}px rgba(15, 23, 31, ${(0.3 + lift * 0.1).toFixed(2)}), \n\t0px ${48 * scale}px ${10 * scale}px -${10 * scale}px inset rgba(15, 23, 44, ${((0.022 + random() * 0.005) * ((1 + oy) / 2)).toFixed(2)})`\n}\n\nfunction getBoundsForSVG(shape: TLNoteShape) {\n\t// When rendering the SVG we don't want to adjust for scale\n\treturn new Box(0, 0, NOTE_SIZE, NOTE_SIZE + shape.props.growY)\n}\n"],
|
|
5
|
-
"mappings": "
|
|
4
|
+
"sourcesContent": ["/* eslint-disable react-hooks/rules-of-hooks */\nimport {\n\tBox,\n\tEMPTY_ARRAY,\n\tEditor,\n\tGroup2d,\n\tIndexKey,\n\tRectangle2d,\n\tShapeUtil,\n\tSvgExportContext,\n\tTLHandle,\n\tTLNoteShape,\n\tTLNoteShapeProps,\n\tTLResizeInfo,\n\tTLShape,\n\tTLShapeId,\n\tVec,\n\tWeakCache,\n\texhaustiveSwitchError,\n\tgetColorValue,\n\tgetDefaultColorTheme,\n\tgetFontsFromRichText,\n\tisEqual,\n\tlerp,\n\tnoteShapeMigrations,\n\tnoteShapeProps,\n\tresizeScaled,\n\trng,\n\ttoDomPrecision,\n\ttoRichText,\n\tuseEditor,\n\tuseValue,\n} from '@tldraw/editor'\nimport { useCallback } from 'react'\nimport { startEditingShapeWithLabel } from '../../tools/SelectTool/selectHelpers'\nimport { useCurrentTranslation } from '../../ui/hooks/useTranslation/useTranslation'\nimport {\n\tisEmptyRichText,\n\trenderHtmlFromRichTextForMeasurement,\n\trenderPlaintextFromRichText,\n} from '../../utils/text/richText'\nimport { isRightToLeftLanguage } from '../../utils/text/text'\nimport { HyperlinkButton } from '../shared/HyperlinkButton'\nimport { RichTextLabel, RichTextSVG } from '../shared/RichTextLabel'\nimport {\n\tFONT_FAMILIES,\n\tLABEL_FONT_SIZES,\n\tLABEL_PADDING,\n\tTEXT_PROPS,\n} from '../shared/default-shape-constants'\nimport { useDefaultColorTheme } from '../shared/useDefaultColorTheme'\nimport { useIsReadyForEditing } from '../shared/useEditablePlainText'\nimport {\n\tCLONE_HANDLE_MARGIN,\n\tNOTE_CENTER_OFFSET,\n\tNOTE_SIZE,\n\tgetNoteShapeForAdjacentPosition,\n} from './noteHelpers'\n\n/** @public */\nexport interface NoteShapeOptions {\n\t/**\n\t * How should the note shape resize? By default it does not resize (except automatically based on its text content),\n\t * but you can set it to be user-resizable using scale.\n\t */\n\tresizeMode: 'none' | 'scale'\n}\n\n/** @public */\nexport class NoteShapeUtil extends ShapeUtil<TLNoteShape> {\n\tstatic override type = 'note' as const\n\tstatic override props = noteShapeProps\n\tstatic override migrations = noteShapeMigrations\n\n\toverride options: NoteShapeOptions = {\n\t\tresizeMode: 'none',\n\t}\n\n\toverride canEdit() {\n\t\treturn true\n\t}\n\toverride hideResizeHandles() {\n\t\tconst { resizeMode } = this.options\n\t\tswitch (resizeMode) {\n\t\t\tcase 'none': {\n\t\t\t\treturn true\n\t\t\t}\n\t\t\tcase 'scale': {\n\t\t\t\treturn false\n\t\t\t}\n\t\t\tdefault: {\n\t\t\t\tthrow exhaustiveSwitchError(resizeMode)\n\t\t\t}\n\t\t}\n\t}\n\n\toverride isAspectRatioLocked() {\n\t\treturn this.options.resizeMode === 'scale'\n\t}\n\n\toverride hideSelectionBoundsFg() {\n\t\treturn false\n\t}\n\n\tgetDefaultProps(): TLNoteShape['props'] {\n\t\treturn {\n\t\t\tcolor: 'black',\n\t\t\trichText: toRichText(''),\n\t\t\tsize: 'm',\n\t\t\tfont: 'draw',\n\t\t\talign: 'middle',\n\t\t\tverticalAlign: 'middle',\n\t\t\tlabelColor: 'black',\n\t\t\tgrowY: 0,\n\t\t\tfontSizeAdjustment: 0,\n\t\t\turl: '',\n\t\t\tscale: 1,\n\t\t}\n\t}\n\n\tgetGeometry(shape: TLNoteShape) {\n\t\tconst { labelHeight, labelWidth } = getLabelSize(this.editor, shape)\n\t\tconst { scale } = shape.props\n\n\t\tconst lh = labelHeight * scale\n\t\tconst lw = labelWidth * scale\n\t\tconst nw = NOTE_SIZE * scale\n\t\tconst nh = getNoteHeight(shape)\n\n\t\treturn new Group2d({\n\t\t\tchildren: [\n\t\t\t\tnew Rectangle2d({ width: nw, height: nh, isFilled: true }),\n\t\t\t\tnew Rectangle2d({\n\t\t\t\t\tx:\n\t\t\t\t\t\tshape.props.align === 'start'\n\t\t\t\t\t\t\t? 0\n\t\t\t\t\t\t\t: shape.props.align === 'end'\n\t\t\t\t\t\t\t\t? nw - lw\n\t\t\t\t\t\t\t\t: (nw - lw) / 2,\n\t\t\t\t\ty:\n\t\t\t\t\t\tshape.props.verticalAlign === 'start'\n\t\t\t\t\t\t\t? 0\n\t\t\t\t\t\t\t: shape.props.verticalAlign === 'end'\n\t\t\t\t\t\t\t\t? nh - lh\n\t\t\t\t\t\t\t\t: (nh - lh) / 2,\n\t\t\t\t\twidth: lw,\n\t\t\t\t\theight: lh,\n\t\t\t\t\tisFilled: true,\n\t\t\t\t\tisLabel: true,\n\t\t\t\t\texcludeFromShapeBounds: true,\n\t\t\t\t}),\n\t\t\t],\n\t\t})\n\t}\n\n\toverride getHandles(shape: TLNoteShape): TLHandle[] {\n\t\tconst { scale } = shape.props\n\t\tconst isCoarsePointer = this.editor.getInstanceState().isCoarsePointer\n\t\tif (isCoarsePointer) return []\n\n\t\tconst zoom = this.editor.getZoomLevel()\n\t\tif (zoom * scale < 0.25) return []\n\n\t\tconst nh = getNoteHeight(shape)\n\t\tconst nw = NOTE_SIZE * scale\n\t\tconst offset = (CLONE_HANDLE_MARGIN / zoom) * scale\n\n\t\tif (zoom * scale < 0.5) {\n\t\t\treturn [\n\t\t\t\t{\n\t\t\t\t\tid: 'bottom',\n\t\t\t\t\tindex: 'a3' as IndexKey,\n\t\t\t\t\ttype: 'clone',\n\t\t\t\t\tx: nw / 2,\n\t\t\t\t\ty: nh + offset,\n\t\t\t\t},\n\t\t\t]\n\t\t}\n\n\t\treturn [\n\t\t\t{\n\t\t\t\tid: 'top',\n\t\t\t\tindex: 'a1' as IndexKey,\n\t\t\t\ttype: 'clone',\n\t\t\t\tx: nw / 2,\n\t\t\t\ty: -offset,\n\t\t\t},\n\t\t\t{\n\t\t\t\tid: 'right',\n\t\t\t\tindex: 'a2' as IndexKey,\n\t\t\t\ttype: 'clone',\n\t\t\t\tx: nw + offset,\n\t\t\t\ty: nh / 2,\n\t\t\t},\n\t\t\t{\n\t\t\t\tid: 'bottom',\n\t\t\t\tindex: 'a3' as IndexKey,\n\t\t\t\ttype: 'clone',\n\t\t\t\tx: nw / 2,\n\t\t\t\ty: nh + offset,\n\t\t\t},\n\t\t\t{\n\t\t\t\tid: 'left',\n\t\t\t\tindex: 'a4' as IndexKey,\n\t\t\t\ttype: 'clone',\n\t\t\t\tx: -offset,\n\t\t\t\ty: nh / 2,\n\t\t\t},\n\t\t]\n\t}\n\n\toverride onResize(shape: any, info: TLResizeInfo<any>) {\n\t\tconst { resizeMode } = this.options\n\t\tswitch (resizeMode) {\n\t\t\tcase 'none': {\n\t\t\t\treturn undefined\n\t\t\t}\n\t\t\tcase 'scale': {\n\t\t\t\treturn resizeScaled(shape, info)\n\t\t\t}\n\t\t\tdefault: {\n\t\t\t\tthrow exhaustiveSwitchError(resizeMode)\n\t\t\t}\n\t\t}\n\t}\n\n\toverride getText(shape: TLNoteShape) {\n\t\treturn renderPlaintextFromRichText(this.editor, shape.props.richText)\n\t}\n\n\toverride getFontFaces(shape: TLNoteShape) {\n\t\tif (isEmptyRichText(shape.props.richText)) {\n\t\t\treturn EMPTY_ARRAY\n\t\t}\n\t\treturn getFontsFromRichText(this.editor, shape.props.richText, {\n\t\t\tfamily: `tldraw_${shape.props.font}`,\n\t\t\tweight: 'normal',\n\t\t\tstyle: 'normal',\n\t\t})\n\t}\n\n\tcomponent(shape: TLNoteShape) {\n\t\tconst {\n\t\t\tid,\n\t\t\ttype,\n\t\t\tprops: {\n\t\t\t\tlabelColor,\n\t\t\t\tscale,\n\t\t\t\tcolor,\n\t\t\t\tfont,\n\t\t\t\tsize,\n\t\t\t\talign,\n\t\t\t\trichText,\n\t\t\t\tverticalAlign,\n\t\t\t\tfontSizeAdjustment,\n\t\t\t},\n\t\t} = shape\n\n\t\tconst handleKeyDown = useNoteKeydownHandler(id)\n\n\t\tconst theme = useDefaultColorTheme()\n\t\tconst nw = NOTE_SIZE * scale\n\t\tconst nh = getNoteHeight(shape)\n\n\t\tconst rotation = useValue(\n\t\t\t'shape rotation',\n\t\t\t() => this.editor.getShapePageTransform(id)?.rotation() ?? 0,\n\t\t\t[this.editor]\n\t\t)\n\n\t\t// todo: consider hiding shadows on dark mode if they're invisible anyway\n\n\t\tconst hideShadows = useValue('zoom', () => this.editor.getZoomLevel() < 0.35 / scale, [\n\t\t\tscale,\n\t\t\tthis.editor,\n\t\t])\n\n\t\tconst isDarkMode = useValue('dark mode', () => this.editor.user.getIsDarkMode(), [this.editor])\n\n\t\tconst isSelected = shape.id === this.editor.getOnlySelectedShapeId()\n\n\t\tconst isReadyForEditing = useIsReadyForEditing(this.editor, shape.id)\n\t\tconst isEmpty = isEmptyRichText(richText)\n\n\t\treturn (\n\t\t\t<>\n\t\t\t\t<div\n\t\t\t\t\tid={id}\n\t\t\t\t\tclassName=\"tl-note__container\"\n\t\t\t\t\tstyle={{\n\t\t\t\t\t\twidth: nw,\n\t\t\t\t\t\theight: nh,\n\t\t\t\t\t\tbackgroundColor: getColorValue(theme, color, 'noteFill'),\n\t\t\t\t\t\tborderBottom: hideShadows\n\t\t\t\t\t\t\t? isDarkMode\n\t\t\t\t\t\t\t\t? `${2 * scale}px solid rgb(20, 20, 20)`\n\t\t\t\t\t\t\t\t: `${2 * scale}px solid rgb(144, 144, 144)`\n\t\t\t\t\t\t\t: 'none',\n\t\t\t\t\t\tboxShadow: hideShadows ? 'none' : getNoteShadow(shape.id, rotation, scale),\n\t\t\t\t\t}}\n\t\t\t\t>\n\t\t\t\t\t{(isSelected || isReadyForEditing || !isEmpty) && (\n\t\t\t\t\t\t<RichTextLabel\n\t\t\t\t\t\t\tshapeId={id}\n\t\t\t\t\t\t\ttype={type}\n\t\t\t\t\t\t\tfont={font}\n\t\t\t\t\t\t\tfontSize={(fontSizeAdjustment || LABEL_FONT_SIZES[size]) * scale}\n\t\t\t\t\t\t\tlineHeight={TEXT_PROPS.lineHeight}\n\t\t\t\t\t\t\talign={align}\n\t\t\t\t\t\t\tverticalAlign={verticalAlign}\n\t\t\t\t\t\t\trichText={richText}\n\t\t\t\t\t\t\tisSelected={isSelected}\n\t\t\t\t\t\t\tlabelColor={\n\t\t\t\t\t\t\t\tlabelColor === 'black'\n\t\t\t\t\t\t\t\t\t? getColorValue(theme, color, 'noteText')\n\t\t\t\t\t\t\t\t\t: getColorValue(theme, labelColor, 'fill')\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\twrap\n\t\t\t\t\t\t\tpadding={LABEL_PADDING * scale}\n\t\t\t\t\t\t\thasCustomTabBehavior\n\t\t\t\t\t\t\tonKeyDown={handleKeyDown}\n\t\t\t\t\t\t/>\n\t\t\t\t\t)}\n\t\t\t\t</div>\n\t\t\t\t{'url' in shape.props && shape.props.url && <HyperlinkButton url={shape.props.url} />}\n\t\t\t</>\n\t\t)\n\t}\n\n\tindicator(shape: TLNoteShape) {\n\t\tconst { scale } = shape.props\n\t\treturn (\n\t\t\t<rect\n\t\t\t\trx={scale}\n\t\t\t\twidth={toDomPrecision(NOTE_SIZE * scale)}\n\t\t\t\theight={toDomPrecision(getNoteHeight(shape))}\n\t\t\t/>\n\t\t)\n\t}\n\n\toverride toSvg(shape: TLNoteShape, ctx: SvgExportContext) {\n\t\tconst theme = getDefaultColorTheme({ isDarkMode: ctx.isDarkMode })\n\t\tconst bounds = getBoundsForSVG(shape)\n\n\t\tconst textLabel = (\n\t\t\t<RichTextSVG\n\t\t\t\tfontSize={shape.props.fontSizeAdjustment || LABEL_FONT_SIZES[shape.props.size]}\n\t\t\t\tfont={shape.props.font}\n\t\t\t\talign={shape.props.align}\n\t\t\t\tverticalAlign={shape.props.verticalAlign}\n\t\t\t\trichText={shape.props.richText}\n\t\t\t\tlabelColor={getColorValue(theme, shape.props.color, 'noteText')}\n\t\t\t\tbounds={bounds}\n\t\t\t\tpadding={LABEL_PADDING}\n\t\t\t\tshowTextOutline={false}\n\t\t\t/>\n\t\t)\n\n\t\treturn (\n\t\t\t<>\n\t\t\t\t<rect x={5} y={5} rx={1} width={NOTE_SIZE - 10} height={bounds.h} fill=\"rgba(0,0,0,.1)\" />\n\t\t\t\t<rect\n\t\t\t\t\trx={1}\n\t\t\t\t\twidth={NOTE_SIZE}\n\t\t\t\t\theight={bounds.h}\n\t\t\t\t\tfill={getColorValue(theme, shape.props.color, 'noteFill')}\n\t\t\t\t/>\n\t\t\t\t{textLabel}\n\t\t\t</>\n\t\t)\n\t}\n\n\toverride onBeforeCreate(next: TLNoteShape) {\n\t\treturn getNoteSizeAdjustments(this.editor, next)\n\t}\n\n\toverride onBeforeUpdate(prev: TLNoteShape, next: TLNoteShape) {\n\t\tif (\n\t\t\tisEqual(prev.props.richText, next.props.richText) &&\n\t\t\tprev.props.font === next.props.font &&\n\t\t\tprev.props.size === next.props.size\n\t\t) {\n\t\t\treturn\n\t\t}\n\n\t\treturn getNoteSizeAdjustments(this.editor, next)\n\t}\n\n\toverride getInterpolatedProps(\n\t\tstartShape: TLNoteShape,\n\t\tendShape: TLNoteShape,\n\t\tt: number\n\t): TLNoteShapeProps {\n\t\treturn {\n\t\t\t...(t > 0.5 ? endShape.props : startShape.props),\n\t\t\tscale: lerp(startShape.props.scale, endShape.props.scale, t),\n\t\t}\n\t}\n}\n\n/**\n * Get the growY and fontSizeAdjustment for a shape.\n */\nfunction getNoteSizeAdjustments(editor: Editor, shape: TLNoteShape) {\n\tconst { labelHeight, fontSizeAdjustment } = getLabelSize(editor, shape)\n\t// When the label height is more than the height of the shape, we add extra height to it\n\tconst growY = Math.max(0, labelHeight - NOTE_SIZE)\n\n\tif (growY !== shape.props.growY || fontSizeAdjustment !== shape.props.fontSizeAdjustment) {\n\t\treturn {\n\t\t\t...shape,\n\t\t\tprops: {\n\t\t\t\t...shape.props,\n\t\t\t\tgrowY,\n\t\t\t\tfontSizeAdjustment,\n\t\t\t},\n\t\t}\n\t}\n}\n\n/**\n * Get the label size for a note.\n */\nfunction getNoteLabelSize(editor: Editor, shape: TLNoteShape) {\n\tconst { richText } = shape.props\n\n\tif (isEmptyRichText(richText)) {\n\t\tconst minHeight = LABEL_FONT_SIZES[shape.props.size] * TEXT_PROPS.lineHeight + LABEL_PADDING * 2\n\t\treturn { labelHeight: minHeight, labelWidth: 100, fontSizeAdjustment: 0 }\n\t}\n\n\tconst unadjustedFontSize = LABEL_FONT_SIZES[shape.props.size]\n\n\tlet fontSizeAdjustment = 0\n\tlet iterations = 0\n\tlet labelHeight = NOTE_SIZE\n\tlet labelWidth = NOTE_SIZE\n\n\t// N.B. For some note shapes with text like 'hjhjhjhjhjhjhjhj', you'll run into\n\t// some text measurement fuzziness where the browser swears there's no overflow (scrollWidth === width)\n\t// but really there is when you enable overflow-wrap again. This helps account for that little bit\n\t// of give.\n\tconst FUZZ = 1\n\n\t// We slightly make the font smaller if the text is too big for the note, width-wise.\n\tdo {\n\t\tfontSizeAdjustment = Math.min(unadjustedFontSize, unadjustedFontSize - iterations)\n\t\tconst html = renderHtmlFromRichTextForMeasurement(editor, richText)\n\t\tconst nextTextSize = editor.textMeasure.measureHtml(html, {\n\t\t\t...TEXT_PROPS,\n\t\t\tfontFamily: FONT_FAMILIES[shape.props.font],\n\t\t\tfontSize: fontSizeAdjustment,\n\t\t\tmaxWidth: NOTE_SIZE - LABEL_PADDING * 2 - FUZZ,\n\t\t\tdisableOverflowWrapBreaking: true,\n\t\t\tmeasureScrollWidth: true,\n\t\t})\n\n\t\tlabelHeight = nextTextSize.h + LABEL_PADDING * 2\n\t\tlabelWidth = nextTextSize.w + LABEL_PADDING * 2\n\n\t\tif (fontSizeAdjustment <= 14) {\n\t\t\t// Too small, just rely now on CSS `overflow-wrap: break-word`\n\t\t\t// We need to recalculate the text measurement here with break-word enabled.\n\t\t\tconst html = renderHtmlFromRichTextForMeasurement(editor, richText)\n\t\t\tconst nextTextSizeWithOverflowBreak = editor.textMeasure.measureHtml(html, {\n\t\t\t\t...TEXT_PROPS,\n\t\t\t\tfontFamily: FONT_FAMILIES[shape.props.font],\n\t\t\t\tfontSize: fontSizeAdjustment,\n\t\t\t\tmaxWidth: NOTE_SIZE - LABEL_PADDING * 2 - FUZZ,\n\t\t\t})\n\t\t\tlabelHeight = nextTextSizeWithOverflowBreak.h + LABEL_PADDING * 2\n\t\t\tlabelWidth = nextTextSizeWithOverflowBreak.w + LABEL_PADDING * 2\n\t\t\tbreak\n\t\t}\n\n\t\tif (nextTextSize.scrollWidth.toFixed(0) === nextTextSize.w.toFixed(0)) {\n\t\t\tbreak\n\t\t}\n\t} while (iterations++ < 50)\n\n\treturn {\n\t\tlabelHeight: labelHeight,\n\t\tlabelWidth: labelWidth,\n\t\tfontSizeAdjustment: fontSizeAdjustment,\n\t}\n}\n\nconst labelSizesForNote = new WeakCache<TLShape, ReturnType<typeof getNoteLabelSize>>()\n\nfunction getLabelSize(editor: Editor, shape: TLNoteShape) {\n\treturn labelSizesForNote.get(shape, () => getNoteLabelSize(editor, shape))\n}\n\nfunction useNoteKeydownHandler(id: TLShapeId) {\n\tconst editor = useEditor()\n\tconst translation = useCurrentTranslation()\n\n\treturn useCallback(\n\t\t(e: KeyboardEvent) => {\n\t\t\tconst shape = editor.getShape<TLNoteShape>(id)\n\t\t\tif (!shape) return\n\n\t\t\tconst isTab = e.key === 'Tab'\n\t\t\tconst isCmdEnter = (e.metaKey || e.ctrlKey) && e.key === 'Enter'\n\t\t\tif (isTab || isCmdEnter) {\n\t\t\t\te.preventDefault()\n\n\t\t\t\tconst pageTransform = editor.getShapePageTransform(id)\n\t\t\t\tconst pageRotation = pageTransform.rotation()\n\n\t\t\t\t// Based on the inputs, calculate the offset to the next note\n\t\t\t\t// tab controls x axis (shift inverts direction set by RTL)\n\t\t\t\t// cmd enter is the y axis (shift inverts direction)\n\t\t\t\tconst isRTL = !!(\n\t\t\t\t\ttranslation.dir === 'rtl' ||\n\t\t\t\t\t// todo: can we check a partial of the text, so that we don't have to render the whole thing?\n\t\t\t\t\tisRightToLeftLanguage(renderPlaintextFromRichText(editor, shape.props.richText))\n\t\t\t\t)\n\n\t\t\t\tconst offsetLength =\n\t\t\t\t\t(NOTE_SIZE +\n\t\t\t\t\t\teditor.options.adjacentShapeMargin +\n\t\t\t\t\t\t// If we're growing down, we need to account for the current shape's growY\n\t\t\t\t\t\t(isCmdEnter && !e.shiftKey ? shape.props.growY : 0)) *\n\t\t\t\t\tshape.props.scale\n\n\t\t\t\tconst adjacentCenter = new Vec(\n\t\t\t\t\tisTab ? (e.shiftKey != isRTL ? -1 : 1) : 0,\n\t\t\t\t\tisCmdEnter ? (e.shiftKey ? -1 : 1) : 0\n\t\t\t\t)\n\t\t\t\t\t.mul(offsetLength)\n\t\t\t\t\t.add(NOTE_CENTER_OFFSET.clone().mul(shape.props.scale))\n\t\t\t\t\t.rot(pageRotation)\n\t\t\t\t\t.add(pageTransform.point())\n\n\t\t\t\tconst newNote = getNoteShapeForAdjacentPosition(editor, shape, adjacentCenter, pageRotation)\n\n\t\t\t\tif (newNote) {\n\t\t\t\t\tstartEditingShapeWithLabel(editor, newNote, true /* selectAll */)\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\t\t[id, editor, translation.dir]\n\t)\n}\n\nfunction getNoteHeight(shape: TLNoteShape) {\n\treturn (NOTE_SIZE + shape.props.growY) * shape.props.scale\n}\n\nfunction getNoteShadow(id: string, rotation: number, scale: number) {\n\tconst random = rng(id) // seeded based on id\n\tconst lift = Math.abs(random()) + 0.5 // 0 to 1.5\n\tconst oy = Math.cos(rotation)\n\tconst a = 5 * scale\n\tconst b = 4 * scale\n\tconst c = 6 * scale\n\tconst d = 7 * scale\n\treturn `0px ${a - lift}px ${a}px -${a}px rgba(15, 23, 31, .6),\n\t0px ${(b + lift * d) * Math.max(0, oy)}px ${c + lift * d}px -${b + lift * c}px rgba(15, 23, 31, ${(0.3 + lift * 0.1).toFixed(2)}), \n\t0px ${48 * scale}px ${10 * scale}px -${10 * scale}px inset rgba(15, 23, 44, ${((0.022 + random() * 0.005) * ((1 + oy) / 2)).toFixed(2)})`\n}\n\nfunction getBoundsForSVG(shape: TLNoteShape) {\n\t// When rendering the SVG we don't want to adjust for scale\n\treturn new Box(0, 0, NOTE_SIZE, NOTE_SIZE + shape.props.growY)\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": ["html"]
|
|
7
7
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../../src/lib/shapes/shared/PlainTextLabel.tsx"],
|
|
4
|
-
"sourcesContent": ["import {\n\tBox,\n\tTLDefaultFillStyle,\n\tTLDefaultFontStyle,\n\tTLDefaultHorizontalAlignStyle,\n\tTLDefaultVerticalAlignStyle,\n\tTLShapeId,\n} from '@tldraw/editor'\nimport React from 'react'\nimport { PlainTextArea } from '../text/PlainTextArea'\nimport { TextHelpers } from './TextHelpers'\nimport { isLegacyAlign } from './legacyProps'\nimport { useEditablePlainText } from './useEditablePlainText'\n\n/** @public */\nexport interface PlainTextLabelProps {\n\tshapeId: TLShapeId\n\ttype: string\n\tfont: TLDefaultFontStyle\n\tfontSize: number\n\tlineHeight: number\n\tfill?: TLDefaultFillStyle\n\talign: TLDefaultHorizontalAlignStyle\n\tverticalAlign: TLDefaultVerticalAlignStyle\n\twrap?: boolean\n\ttext?: string\n\tlabelColor: string\n\tbounds?: Box\n\tisSelected: boolean\n\tonKeyDown?(e: KeyboardEvent): void\n\tclassNamePrefix?: string\n\tstyle?: React.CSSProperties\n\ttextWidth?: number\n\ttextHeight?: number\n\tpadding?: number\n}\n\n/**\n * Renders a text label that can be used inside of shapes.\n * The component has the ability to be edited in place and furthermore\n * supports rich text editing.\n *\n * @public @react\n */\nexport const PlainTextLabel = React.memo(function PlainTextLabel({\n\tshapeId,\n\ttype,\n\ttext: plaintext,\n\tlabelColor,\n\tfont,\n\tfontSize,\n\tlineHeight,\n\talign,\n\tverticalAlign,\n\twrap,\n\tisSelected,\n\tpadding = 0,\n\tonKeyDown: handleKeyDownCustom,\n\tclassNamePrefix,\n\tstyle,\n\ttextWidth,\n\ttextHeight,\n}: PlainTextLabelProps) {\n\tconst { rInput, isEmpty, isEditing, isReadyForEditing, ...editableTextRest } =\n\t\tuseEditablePlainText(shapeId, type, plaintext)\n\n\tconst finalPlainText = TextHelpers.normalizeTextForDom(plaintext || '')\n\tconst hasText = finalPlainText.length > 0\n\n\tconst legacyAlign = isLegacyAlign(align)\n\n\tif (!isEditing && !hasText) {\n\t\treturn null\n\t}\n\n\t// TODO: probably combine tl-text and tl-arrow eventually\n\t// In case you're grepping for this, it breaks down as follows:\n\t// tl-text-label, tl-text-label__inner, tl-text-shape-label, tl-text\n\t// tl-arrow-label, tl-arrow-label__inner, tl-arrow\n\tconst cssPrefix = classNamePrefix || 'tl-text'\n\treturn (\n\t\t<div\n\t\t\tclassName={`${cssPrefix}-label tl-text-wrapper tl-plain-text-wrapper`}\n\t\t\taria-hidden={!isEditing}\n\t\t\tdata-font={font}\n\t\t\tdata-align={align}\n\t\t\tdata-hastext={!isEmpty}\n\t\t\tdata-isediting={isEditing}\n\t\t\tdata-is-ready-for-editing={isReadyForEditing}\n\t\t\tdata-textwrap={!!wrap}\n\t\t\tdata-isselected={isSelected}\n\t\t\tstyle={{\n\t\t\t\tjustifyContent: align === 'middle' || legacyAlign ? 'center' : align,\n\t\t\t\talignItems: verticalAlign === 'middle' ? 'center' : verticalAlign,\n\t\t\t\tpadding,\n\t\t\t\t...style,\n\t\t\t}}\n\t\t>\n\t\t\t<div\n\t\t\t\tclassName={`${cssPrefix}-label__inner tl-text-content__wrapper`}\n\t\t\t\tstyle={{\n\t\t\t\t\tfontSize,\n\t\t\t\t\tlineHeight: lineHeight.toString(),\n\t\t\t\t\tminHeight: Math.floor(fontSize * lineHeight) + 'px',\n\t\t\t\t\tminWidth: Math.ceil(textWidth || 0),\n\t\t\t\t\tcolor: labelColor,\n\t\t\t\t\twidth: textWidth ? Math.ceil(textWidth) : undefined,\n\t\t\t\t\theight: textHeight ? Math.ceil(textHeight) : undefined,\n\t\t\t\t}}\n\t\t\t>\n\t\t\t\t<div className={`${cssPrefix} tl-text tl-text-content`} dir=\"auto\">\n\t\t\t\t\t{finalPlainText.split('\\n').map((lineOfText, index) => (\n\t\t\t\t\t\t<div key={index} dir=\"auto\">\n\t\t\t\t\t\t\t{lineOfText}\n\t\t\t\t\t\t</div>\n\t\t\t\t\t))}\n\t\t\t\t</div>\n\t\t\t\t{(isReadyForEditing || isSelected) && (\n\t\t\t\t\t<PlainTextArea\n\t\t\t\t\t\t// Fudge the ref type because we're using forwardRef and it's not typed correctly.\n\t\t\t\t\t\tref={rInput as any}\n\t\t\t\t\t\ttext={plaintext}\n\t\t\t\t\t\tisEditing={isEditing}\n\t\t\t\t\t\tshapeId={shapeId}\n\t\t\t\t\t\t{...editableTextRest}\n\t\t\t\t\t\thandleKeyDown={handleKeyDownCustom ?? editableTextRest.handleKeyDown}\n\t\t\t\t\t/>\n\t\t\t\t)}\n\t\t\t</div>\n\t\t</div>\n\t)\n})\n
|
|
5
|
-
"mappings": "AAkGG,SAcG,KAdH;AA1FH,OAAO,WAAW;AAClB,SAAS,qBAAqB;AAC9B,SAAS,mBAAmB;AAC5B,SAAS,qBAAqB;AAC9B,SAAS,4BAA4B;AAgC9B,MAAM,iBAAiB,MAAM,KAAK,SAASA,gBAAe;AAAA,EAChE;AAAA,EACA;AAAA,EACA,MAAM;AAAA,EACN;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,UAAU;AAAA,EACV,WAAW;AAAA,EACX;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACD,GAAwB;AACvB,QAAM,EAAE,QAAQ,SAAS,WAAW,mBAAmB,GAAG,iBAAiB,IAC1E,qBAAqB,SAAS,MAAM,SAAS;AAE9C,QAAM,iBAAiB,YAAY,oBAAoB,aAAa,EAAE;AACtE,QAAM,UAAU,eAAe,SAAS;AAExC,QAAM,cAAc,cAAc,KAAK;AAEvC,MAAI,CAAC,aAAa,CAAC,SAAS;AAC3B,WAAO;AAAA,EACR;AAMA,QAAM,YAAY,mBAAmB;AACrC,SACC;AAAA,IAAC;AAAA;AAAA,MACA,WAAW,GAAG,SAAS;AAAA,MACvB,eAAa,CAAC;AAAA,MACd,aAAW;AAAA,MACX,cAAY;AAAA,MACZ,gBAAc,CAAC;AAAA,MACf,kBAAgB;AAAA,MAChB,6BAA2B;AAAA,MAC3B,iBAAe,CAAC,CAAC;AAAA,MACjB,mBAAiB;AAAA,MACjB,OAAO;AAAA,QACN,gBAAgB,UAAU,YAAY,cAAc,WAAW;AAAA,QAC/D,YAAY,kBAAkB,WAAW,WAAW;AAAA,QACpD;AAAA,QACA,GAAG;AAAA,MACJ;AAAA,MAEA;AAAA,QAAC;AAAA;AAAA,UACA,WAAW,GAAG,SAAS;AAAA,UACvB,OAAO;AAAA,YACN;AAAA,YACA,YAAY,WAAW,SAAS;AAAA,YAChC,WAAW,KAAK,MAAM,WAAW,UAAU,IAAI;AAAA,YAC/C,UAAU,KAAK,KAAK,aAAa,CAAC;AAAA,YAClC,OAAO;AAAA,YACP,OAAO,YAAY,KAAK,KAAK,SAAS,IAAI;AAAA,YAC1C,QAAQ,aAAa,KAAK,KAAK,UAAU,IAAI;AAAA,UAC9C;AAAA,UAEA;AAAA,gCAAC,SAAI,WAAW,GAAG,SAAS,4BAA4B,KAAI,QAC1D,yBAAe,MAAM,IAAI,EAAE,IAAI,CAAC,YAAY,UAC5C,oBAAC,SAAgB,KAAI,QACnB,wBADQ,KAEV,CACA,GACF;AAAA,aACE,qBAAqB,eACtB;AAAA,cAAC;AAAA;AAAA,gBAEA,KAAK;AAAA,gBACL,MAAM;AAAA,gBACN;AAAA,gBACA;AAAA,gBACC,GAAG;AAAA,gBACJ,eAAe,uBAAuB,iBAAiB;AAAA;AAAA,YACxD;AAAA;AAAA;AAAA,MAEF;AAAA;AAAA,EACD;AAEF,CAAC;
|
|
4
|
+
"sourcesContent": ["import {\n\tBox,\n\tTLDefaultFillStyle,\n\tTLDefaultFontStyle,\n\tTLDefaultHorizontalAlignStyle,\n\tTLDefaultVerticalAlignStyle,\n\tTLShapeId,\n} from '@tldraw/editor'\nimport React from 'react'\nimport { PlainTextArea } from '../text/PlainTextArea'\nimport { TextHelpers } from './TextHelpers'\nimport { isLegacyAlign } from './legacyProps'\nimport { useEditablePlainText } from './useEditablePlainText'\n\n/** @public */\nexport interface PlainTextLabelProps {\n\tshapeId: TLShapeId\n\ttype: string\n\tfont: TLDefaultFontStyle\n\tfontSize: number\n\tlineHeight: number\n\tfill?: TLDefaultFillStyle\n\talign: TLDefaultHorizontalAlignStyle\n\tverticalAlign: TLDefaultVerticalAlignStyle\n\twrap?: boolean\n\ttext?: string\n\tlabelColor: string\n\tbounds?: Box\n\tisSelected: boolean\n\tonKeyDown?(e: KeyboardEvent): void\n\tclassNamePrefix?: string\n\tstyle?: React.CSSProperties\n\ttextWidth?: number\n\ttextHeight?: number\n\tpadding?: number\n}\n\n/**\n * Renders a text label that can be used inside of shapes.\n * The component has the ability to be edited in place and furthermore\n * supports rich text editing.\n *\n * @public @react\n */\nexport const PlainTextLabel = React.memo(function PlainTextLabel({\n\tshapeId,\n\ttype,\n\ttext: plaintext,\n\tlabelColor,\n\tfont,\n\tfontSize,\n\tlineHeight,\n\talign,\n\tverticalAlign,\n\twrap,\n\tisSelected,\n\tpadding = 0,\n\tonKeyDown: handleKeyDownCustom,\n\tclassNamePrefix,\n\tstyle,\n\ttextWidth,\n\ttextHeight,\n}: PlainTextLabelProps) {\n\tconst { rInput, isEmpty, isEditing, isReadyForEditing, ...editableTextRest } =\n\t\tuseEditablePlainText(shapeId, type, plaintext)\n\n\tconst finalPlainText = TextHelpers.normalizeTextForDom(plaintext || '')\n\tconst hasText = finalPlainText.length > 0\n\n\tconst legacyAlign = isLegacyAlign(align)\n\n\tif (!isEditing && !hasText) {\n\t\treturn null\n\t}\n\n\t// TODO: probably combine tl-text and tl-arrow eventually\n\t// In case you're grepping for this, it breaks down as follows:\n\t// tl-text-label, tl-text-label__inner, tl-text-shape-label, tl-text\n\t// tl-arrow-label, tl-arrow-label__inner, tl-arrow\n\tconst cssPrefix = classNamePrefix || 'tl-text'\n\treturn (\n\t\t<div\n\t\t\tclassName={`${cssPrefix}-label tl-text-wrapper tl-plain-text-wrapper`}\n\t\t\taria-hidden={!isEditing}\n\t\t\tdata-font={font}\n\t\t\tdata-align={align}\n\t\t\tdata-hastext={!isEmpty}\n\t\t\tdata-isediting={isEditing}\n\t\t\tdata-is-ready-for-editing={isReadyForEditing}\n\t\t\tdata-textwrap={!!wrap}\n\t\t\tdata-isselected={isSelected}\n\t\t\tstyle={{\n\t\t\t\tjustifyContent: align === 'middle' || legacyAlign ? 'center' : align,\n\t\t\t\talignItems: verticalAlign === 'middle' ? 'center' : verticalAlign,\n\t\t\t\tpadding,\n\t\t\t\t...style,\n\t\t\t}}\n\t\t>\n\t\t\t<div\n\t\t\t\tclassName={`${cssPrefix}-label__inner tl-text-content__wrapper`}\n\t\t\t\tstyle={{\n\t\t\t\t\tfontSize,\n\t\t\t\t\tlineHeight: lineHeight.toString(),\n\t\t\t\t\tminHeight: Math.floor(fontSize * lineHeight) + 'px',\n\t\t\t\t\tminWidth: Math.ceil(textWidth || 0),\n\t\t\t\t\tcolor: labelColor,\n\t\t\t\t\twidth: textWidth ? Math.ceil(textWidth) : undefined,\n\t\t\t\t\theight: textHeight ? Math.ceil(textHeight) : undefined,\n\t\t\t\t}}\n\t\t\t>\n\t\t\t\t<div className={`${cssPrefix} tl-text tl-text-content`} dir=\"auto\">\n\t\t\t\t\t{finalPlainText.split('\\n').map((lineOfText, index) => (\n\t\t\t\t\t\t<div key={index} dir=\"auto\">\n\t\t\t\t\t\t\t{lineOfText}\n\t\t\t\t\t\t</div>\n\t\t\t\t\t))}\n\t\t\t\t</div>\n\t\t\t\t{(isReadyForEditing || isSelected) && (\n\t\t\t\t\t<PlainTextArea\n\t\t\t\t\t\t// Fudge the ref type because we're using forwardRef and it's not typed correctly.\n\t\t\t\t\t\tref={rInput as any}\n\t\t\t\t\t\ttext={plaintext}\n\t\t\t\t\t\tisEditing={isEditing}\n\t\t\t\t\t\tshapeId={shapeId}\n\t\t\t\t\t\t{...editableTextRest}\n\t\t\t\t\t\thandleKeyDown={handleKeyDownCustom ?? editableTextRest.handleKeyDown}\n\t\t\t\t\t/>\n\t\t\t\t)}\n\t\t\t</div>\n\t\t</div>\n\t)\n})\n"],
|
|
5
|
+
"mappings": "AAkGG,SAcG,KAdH;AA1FH,OAAO,WAAW;AAClB,SAAS,qBAAqB;AAC9B,SAAS,mBAAmB;AAC5B,SAAS,qBAAqB;AAC9B,SAAS,4BAA4B;AAgC9B,MAAM,iBAAiB,MAAM,KAAK,SAASA,gBAAe;AAAA,EAChE;AAAA,EACA;AAAA,EACA,MAAM;AAAA,EACN;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,UAAU;AAAA,EACV,WAAW;AAAA,EACX;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACD,GAAwB;AACvB,QAAM,EAAE,QAAQ,SAAS,WAAW,mBAAmB,GAAG,iBAAiB,IAC1E,qBAAqB,SAAS,MAAM,SAAS;AAE9C,QAAM,iBAAiB,YAAY,oBAAoB,aAAa,EAAE;AACtE,QAAM,UAAU,eAAe,SAAS;AAExC,QAAM,cAAc,cAAc,KAAK;AAEvC,MAAI,CAAC,aAAa,CAAC,SAAS;AAC3B,WAAO;AAAA,EACR;AAMA,QAAM,YAAY,mBAAmB;AACrC,SACC;AAAA,IAAC;AAAA;AAAA,MACA,WAAW,GAAG,SAAS;AAAA,MACvB,eAAa,CAAC;AAAA,MACd,aAAW;AAAA,MACX,cAAY;AAAA,MACZ,gBAAc,CAAC;AAAA,MACf,kBAAgB;AAAA,MAChB,6BAA2B;AAAA,MAC3B,iBAAe,CAAC,CAAC;AAAA,MACjB,mBAAiB;AAAA,MACjB,OAAO;AAAA,QACN,gBAAgB,UAAU,YAAY,cAAc,WAAW;AAAA,QAC/D,YAAY,kBAAkB,WAAW,WAAW;AAAA,QACpD;AAAA,QACA,GAAG;AAAA,MACJ;AAAA,MAEA;AAAA,QAAC;AAAA;AAAA,UACA,WAAW,GAAG,SAAS;AAAA,UACvB,OAAO;AAAA,YACN;AAAA,YACA,YAAY,WAAW,SAAS;AAAA,YAChC,WAAW,KAAK,MAAM,WAAW,UAAU,IAAI;AAAA,YAC/C,UAAU,KAAK,KAAK,aAAa,CAAC;AAAA,YAClC,OAAO;AAAA,YACP,OAAO,YAAY,KAAK,KAAK,SAAS,IAAI;AAAA,YAC1C,QAAQ,aAAa,KAAK,KAAK,UAAU,IAAI;AAAA,UAC9C;AAAA,UAEA;AAAA,gCAAC,SAAI,WAAW,GAAG,SAAS,4BAA4B,KAAI,QAC1D,yBAAe,MAAM,IAAI,EAAE,IAAI,CAAC,YAAY,UAC5C,oBAAC,SAAgB,KAAI,QACnB,wBADQ,KAEV,CACA,GACF;AAAA,aACE,qBAAqB,eACtB;AAAA,cAAC;AAAA;AAAA,gBAEA,KAAK;AAAA,gBACL,MAAM;AAAA,gBACN;AAAA,gBACA;AAAA,gBACC,GAAG;AAAA,gBACJ,eAAe,uBAAuB,iBAAiB;AAAA;AAAA,YACxD;AAAA;AAAA;AAAA,MAEF;AAAA;AAAA,EACD;AAEF,CAAC;",
|
|
6
6
|
"names": ["PlainTextLabel"]
|
|
7
7
|
}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
2
2
|
import {
|
|
3
|
+
getColorValue,
|
|
3
4
|
useEditor,
|
|
4
5
|
useSvgExportContext,
|
|
5
6
|
useValue
|
|
@@ -18,13 +19,13 @@ const ShapeFill = React.memo(function ShapeFill2({
|
|
|
18
19
|
return null;
|
|
19
20
|
}
|
|
20
21
|
case "solid": {
|
|
21
|
-
return /* @__PURE__ */ jsx("path", { fill: theme
|
|
22
|
+
return /* @__PURE__ */ jsx("path", { fill: getColorValue(theme, color, "semi"), d });
|
|
22
23
|
}
|
|
23
24
|
case "semi": {
|
|
24
25
|
return /* @__PURE__ */ jsx("path", { fill: theme.solid, d });
|
|
25
26
|
}
|
|
26
27
|
case "fill": {
|
|
27
|
-
return /* @__PURE__ */ jsx("path", { fill: theme
|
|
28
|
+
return /* @__PURE__ */ jsx("path", { fill: getColorValue(theme, color, "fill"), d });
|
|
28
29
|
}
|
|
29
30
|
case "pattern": {
|
|
30
31
|
return /* @__PURE__ */ jsx(PatternFill, { theme, color, fill, d, scale });
|
|
@@ -38,11 +39,11 @@ function PatternFill({ d, color, theme }) {
|
|
|
38
39
|
const getHashPatternZoomName = useGetHashPatternZoomName();
|
|
39
40
|
const teenyTiny = editor.getZoomLevel() <= 0.18;
|
|
40
41
|
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
41
|
-
/* @__PURE__ */ jsx("path", { fill: theme
|
|
42
|
+
/* @__PURE__ */ jsx("path", { fill: getColorValue(theme, color, "pattern"), d }),
|
|
42
43
|
/* @__PURE__ */ jsx(
|
|
43
44
|
"path",
|
|
44
45
|
{
|
|
45
|
-
fill: svgExport ? `url(#${getHashPatternZoomName(1, theme.id)})` : teenyTiny ? theme
|
|
46
|
+
fill: svgExport ? `url(#${getHashPatternZoomName(1, theme.id)})` : teenyTiny ? getColorValue(theme, color, "semi") : `url(#${getHashPatternZoomName(zoomLevel, theme.id)})`,
|
|
46
47
|
d
|
|
47
48
|
}
|
|
48
49
|
)
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../../src/lib/shapes/shared/ShapeFill.tsx"],
|
|
4
|
-
"sourcesContent": ["import {\n\tTLDefaultColorStyle,\n\tTLDefaultColorTheme,\n\tTLDefaultFillStyle,\n\tuseEditor,\n\tuseSvgExportContext,\n\tuseValue,\n} from '@tldraw/editor'\nimport React from 'react'\nimport { useGetHashPatternZoomName } from './defaultStyleDefs'\n\ninterface ShapeFillProps {\n\td: string\n\tfill: TLDefaultFillStyle\n\tcolor: TLDefaultColorStyle\n\ttheme: TLDefaultColorTheme\n\tscale: number\n}\n\nexport const ShapeFill = React.memo(function ShapeFill({\n\ttheme,\n\td,\n\tcolor,\n\tfill,\n\tscale,\n}: ShapeFillProps) {\n\tswitch (fill) {\n\t\tcase 'none': {\n\t\t\treturn null\n\t\t}\n\t\tcase 'solid': {\n\t\t\treturn <path fill={theme
|
|
5
|
-
"mappings": "
|
|
4
|
+
"sourcesContent": ["import {\n\tgetColorValue,\n\tTLDefaultColorStyle,\n\tTLDefaultColorTheme,\n\tTLDefaultFillStyle,\n\tuseEditor,\n\tuseSvgExportContext,\n\tuseValue,\n} from '@tldraw/editor'\nimport React from 'react'\nimport { useGetHashPatternZoomName } from './defaultStyleDefs'\n\ninterface ShapeFillProps {\n\td: string\n\tfill: TLDefaultFillStyle\n\tcolor: TLDefaultColorStyle\n\ttheme: TLDefaultColorTheme\n\tscale: number\n}\n\nexport const ShapeFill = React.memo(function ShapeFill({\n\ttheme,\n\td,\n\tcolor,\n\tfill,\n\tscale,\n}: ShapeFillProps) {\n\tswitch (fill) {\n\t\tcase 'none': {\n\t\t\treturn null\n\t\t}\n\t\tcase 'solid': {\n\t\t\treturn <path fill={getColorValue(theme, color, 'semi')} d={d} />\n\t\t}\n\t\tcase 'semi': {\n\t\t\treturn <path fill={theme.solid} d={d} />\n\t\t}\n\t\tcase 'fill': {\n\t\t\treturn <path fill={getColorValue(theme, color, 'fill')} d={d} />\n\t\t}\n\t\tcase 'pattern': {\n\t\t\treturn <PatternFill theme={theme} color={color} fill={fill} d={d} scale={scale} />\n\t\t}\n\t}\n})\n\nexport function PatternFill({ d, color, theme }: ShapeFillProps) {\n\tconst editor = useEditor()\n\tconst svgExport = useSvgExportContext()\n\tconst zoomLevel = useValue('zoomLevel', () => editor.getZoomLevel(), [editor])\n\tconst getHashPatternZoomName = useGetHashPatternZoomName()\n\n\tconst teenyTiny = editor.getZoomLevel() <= 0.18\n\n\treturn (\n\t\t<>\n\t\t\t<path fill={getColorValue(theme, color, 'pattern')} d={d} />\n\t\t\t<path\n\t\t\t\tfill={\n\t\t\t\t\tsvgExport\n\t\t\t\t\t\t? `url(#${getHashPatternZoomName(1, theme.id)})`\n\t\t\t\t\t\t: teenyTiny\n\t\t\t\t\t\t\t? getColorValue(theme, color, 'semi')\n\t\t\t\t\t\t\t: `url(#${getHashPatternZoomName(zoomLevel, theme.id)})`\n\t\t\t\t}\n\t\t\t\td={d}\n\t\t\t/>\n\t\t</>\n\t)\n}\n"],
|
|
5
|
+
"mappings": "AAgCU,SAuBR,UAvBQ,KAuBR,YAvBQ;AAhCV;AAAA,EACC;AAAA,EAIA;AAAA,EACA;AAAA,EACA;AAAA,OACM;AACP,OAAO,WAAW;AAClB,SAAS,iCAAiC;AAUnC,MAAM,YAAY,MAAM,KAAK,SAASA,WAAU;AAAA,EACtD;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACD,GAAmB;AAClB,UAAQ,MAAM;AAAA,IACb,KAAK,QAAQ;AACZ,aAAO;AAAA,IACR;AAAA,IACA,KAAK,SAAS;AACb,aAAO,oBAAC,UAAK,MAAM,cAAc,OAAO,OAAO,MAAM,GAAG,GAAM;AAAA,IAC/D;AAAA,IACA,KAAK,QAAQ;AACZ,aAAO,oBAAC,UAAK,MAAM,MAAM,OAAO,GAAM;AAAA,IACvC;AAAA,IACA,KAAK,QAAQ;AACZ,aAAO,oBAAC,UAAK,MAAM,cAAc,OAAO,OAAO,MAAM,GAAG,GAAM;AAAA,IAC/D;AAAA,IACA,KAAK,WAAW;AACf,aAAO,oBAAC,eAAY,OAAc,OAAc,MAAY,GAAM,OAAc;AAAA,IACjF;AAAA,EACD;AACD,CAAC;AAEM,SAAS,YAAY,EAAE,GAAG,OAAO,MAAM,GAAmB;AAChE,QAAM,SAAS,UAAU;AACzB,QAAM,YAAY,oBAAoB;AACtC,QAAM,YAAY,SAAS,aAAa,MAAM,OAAO,aAAa,GAAG,CAAC,MAAM,CAAC;AAC7E,QAAM,yBAAyB,0BAA0B;AAEzD,QAAM,YAAY,OAAO,aAAa,KAAK;AAE3C,SACC,iCACC;AAAA,wBAAC,UAAK,MAAM,cAAc,OAAO,OAAO,SAAS,GAAG,GAAM;AAAA,IAC1D;AAAA,MAAC;AAAA;AAAA,QACA,MACC,YACG,QAAQ,uBAAuB,GAAG,MAAM,EAAE,CAAC,MAC3C,YACC,cAAc,OAAO,OAAO,MAAM,IAClC,QAAQ,uBAAuB,WAAW,MAAM,EAAE,CAAC;AAAA,QAExD;AAAA;AAAA,IACD;AAAA,KACD;AAEF;",
|
|
6
6
|
"names": ["ShapeFill"]
|
|
7
7
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../../../src/lib/shapes/shared/freehand/svg.ts"],
|
|
4
|
-
"sourcesContent": ["import { average, precise } from '@tldraw/editor'\nimport { StrokePoint } from './types'\n\n/**\n * Turn an array of stroke points into a path of quadradic curves.\n *\n * @param points - The stroke points returned from perfect-freehand\n * @param closed - Whether the shape is closed\n */\nexport function getSvgPathFromStrokePoints(points: StrokePoint[], closed = false): string {\n\tconst len = points.length\n\n\tif (len < 2) {\n\t\treturn ''\n\t}\n\n\tlet a = points[0].point\n\tlet b = points[1].point\n\n\tif (len === 2) {\n\t\treturn `M${precise(a)}L${precise(b)}`\n\t}\n\n\tlet result = ''\n\n\tfor (let i = 2, max = len - 1; i < max; i++) {\n\t\ta = points[i].point\n\t\tb = points[i + 1].point\n\t\tresult += average(a, b)\n\t}\n\n\tif (closed) {\n\t\t// If closed, draw a curve from the last point to the first\n\t\treturn `M${average(points[0].point, points[1].point)}Q${precise(points[1].point)}${average(\n\t\t\tpoints[1].point,\n\t\t\tpoints[2].point\n\t\t)}T${result}${average(points[len - 1].point, points[0].point)}${average(\n\t\t\tpoints[0].point,\n\t\t\tpoints[1].point\n\t\t)}Z`\n\t} else {\n\t\t// If not closed, draw a curve starting at the first point and\n\t\t// ending at the midpoint of the last and second-last point, then\n\t\t// complete the curve with a line segment to the last point.\n\t\treturn `M${precise(points[0].point)}Q${precise(points[1].point)}${average(\n\t\t\tpoints[1].point,\n\t\t\tpoints[2].point\n\t\t)}${points.length > 3 ? 'T' : ''}${result}L${precise(points[len - 1].point)}`\n\t}\n}\n"],
|
|
5
|
-
"mappings": "AAAA,SAAS,SAAS,eAAe;
|
|
4
|
+
"sourcesContent": ["import { average, precise } from '@tldraw/editor'\nimport { StrokePoint } from './types'\n\n/**\n * Turn an array of stroke points into a path of quadradic curves.\n *\n * @param points - The stroke points returned from perfect-freehand\n * @param closed - Whether the shape is closed\n *\n * @public\n */\nexport function getSvgPathFromStrokePoints(points: StrokePoint[], closed = false): string {\n\tconst len = points.length\n\n\tif (len < 2) {\n\t\treturn ''\n\t}\n\n\tlet a = points[0].point\n\tlet b = points[1].point\n\n\tif (len === 2) {\n\t\treturn `M${precise(a)}L${precise(b)}`\n\t}\n\n\tlet result = ''\n\n\tfor (let i = 2, max = len - 1; i < max; i++) {\n\t\ta = points[i].point\n\t\tb = points[i + 1].point\n\t\tresult += average(a, b)\n\t}\n\n\tif (closed) {\n\t\t// If closed, draw a curve from the last point to the first\n\t\treturn `M${average(points[0].point, points[1].point)}Q${precise(points[1].point)}${average(\n\t\t\tpoints[1].point,\n\t\t\tpoints[2].point\n\t\t)}T${result}${average(points[len - 1].point, points[0].point)}${average(\n\t\t\tpoints[0].point,\n\t\t\tpoints[1].point\n\t\t)}Z`\n\t} else {\n\t\t// If not closed, draw a curve starting at the first point and\n\t\t// ending at the midpoint of the last and second-last point, then\n\t\t// complete the curve with a line segment to the last point.\n\t\treturn `M${precise(points[0].point)}Q${precise(points[1].point)}${average(\n\t\t\tpoints[1].point,\n\t\t\tpoints[2].point\n\t\t)}${points.length > 3 ? 'T' : ''}${result}L${precise(points[len - 1].point)}`\n\t}\n}\n"],
|
|
5
|
+
"mappings": "AAAA,SAAS,SAAS,eAAe;AAW1B,SAAS,2BAA2B,QAAuB,SAAS,OAAe;AACzF,QAAM,MAAM,OAAO;AAEnB,MAAI,MAAM,GAAG;AACZ,WAAO;AAAA,EACR;AAEA,MAAI,IAAI,OAAO,CAAC,EAAE;AAClB,MAAI,IAAI,OAAO,CAAC,EAAE;AAElB,MAAI,QAAQ,GAAG;AACd,WAAO,IAAI,QAAQ,CAAC,CAAC,IAAI,QAAQ,CAAC,CAAC;AAAA,EACpC;AAEA,MAAI,SAAS;AAEb,WAAS,IAAI,GAAG,MAAM,MAAM,GAAG,IAAI,KAAK,KAAK;AAC5C,QAAI,OAAO,CAAC,EAAE;AACd,QAAI,OAAO,IAAI,CAAC,EAAE;AAClB,cAAU,QAAQ,GAAG,CAAC;AAAA,EACvB;AAEA,MAAI,QAAQ;AAEX,WAAO,IAAI,QAAQ,OAAO,CAAC,EAAE,OAAO,OAAO,CAAC,EAAE,KAAK,CAAC,IAAI,QAAQ,OAAO,CAAC,EAAE,KAAK,CAAC,GAAG;AAAA,MAClF,OAAO,CAAC,EAAE;AAAA,MACV,OAAO,CAAC,EAAE;AAAA,IACX,CAAC,IAAI,MAAM,GAAG,QAAQ,OAAO,MAAM,CAAC,EAAE,OAAO,OAAO,CAAC,EAAE,KAAK,CAAC,GAAG;AAAA,MAC/D,OAAO,CAAC,EAAE;AAAA,MACV,OAAO,CAAC,EAAE;AAAA,IACX,CAAC;AAAA,EACF,OAAO;AAIN,WAAO,IAAI,QAAQ,OAAO,CAAC,EAAE,KAAK,CAAC,IAAI,QAAQ,OAAO,CAAC,EAAE,KAAK,CAAC,GAAG;AAAA,MACjE,OAAO,CAAC,EAAE;AAAA,MACV,OAAO,CAAC,EAAE;AAAA,IACX,CAAC,GAAG,OAAO,SAAS,IAAI,MAAM,EAAE,GAAG,MAAM,IAAI,QAAQ,OAAO,MAAM,CAAC,EAAE,KAAK,CAAC;AAAA,EAC5E;AACD;",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -127,10 +127,8 @@ function useEditableTextCommon(shapeId) {
|
|
|
127
127
|
isReadyForEditing
|
|
128
128
|
};
|
|
129
129
|
}
|
|
130
|
-
const useEditableText = useEditablePlainText;
|
|
131
130
|
export {
|
|
132
131
|
useEditablePlainText,
|
|
133
|
-
useEditableText,
|
|
134
132
|
useEditableTextCommon,
|
|
135
133
|
useIsReadyForEditing
|
|
136
134
|
};
|