tldraw 3.16.0-canary.fa3749606e52 → 3.16.0-internal.51e99e128bd4
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 +171 -5
- package/dist-cjs/index.js +17 -1
- package/dist-cjs/index.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/shapes/arrow/ArrowShapeUtil.js +3 -3
- package/dist-cjs/lib/shapes/arrow/ArrowShapeUtil.js.map +2 -2
- 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 +12 -12
- 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 +2 -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 +3 -3
- package/dist-cjs/lib/shapes/image/ImageShapeUtil.js.map +1 -1
- 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 +4 -4
- package/dist-cjs/lib/shapes/note/NoteShapeUtil.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/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 +14 -0
- 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/DefaultMenuPanel.js +3 -2
- package/dist-cjs/lib/ui/components/DefaultMenuPanel.js.map +2 -2
- 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 +2 -0
- package/dist-cjs/lib/ui/components/StylePanel/DefaultStylePanel.js.map +2 -2
- package/dist-cjs/lib/ui/components/StylePanel/DefaultStylePanelContent.js +171 -140
- package/dist-cjs/lib/ui/components/StylePanel/DefaultStylePanelContent.js.map +2 -2
- package/dist-cjs/lib/ui/components/StylePanel/DoubleDropdownPicker.js +3 -3
- package/dist-cjs/lib/ui/components/StylePanel/DoubleDropdownPicker.js.map +2 -2
- package/dist-cjs/lib/ui/components/StylePanel/DropdownPicker.js +26 -25
- package/dist-cjs/lib/ui/components/StylePanel/DropdownPicker.js.map +3 -3
- package/dist-cjs/lib/ui/components/Toolbar/DefaultImageToolbarContent.js +1 -1
- 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/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/TldrawUiButtonPicker.js +5 -16
- package/dist-cjs/lib/ui/components/primitives/TldrawUiButtonPicker.js.map +3 -3
- package/dist-cjs/lib/ui/components/primitives/TldrawUiContextualToolbar.js +1 -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/TldrawUiToolbar.js +30 -7
- package/dist-cjs/lib/ui/components/primitives/TldrawUiToolbar.js.map +2 -2
- package/dist-cjs/lib/ui/components/primitives/TldrawUiTooltip.js +268 -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 +12 -26
- 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 +15 -0
- package/dist-cjs/lib/ui/context/actions.js.map +2 -2
- package/dist-cjs/lib/ui/context/events.js.map +2 -2
- package/dist-cjs/lib/ui/hooks/useTools.js +21 -3
- 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 +3 -0
- package/dist-cjs/lib/ui/hooks/useTranslation/defaultTranslation.js.map +2 -2
- package/dist-cjs/lib/ui/version.js +3 -3
- package/dist-cjs/lib/ui/version.js.map +1 -1
- package/dist-esm/index.d.mts +171 -5
- package/dist-esm/index.mjs +27 -1
- package/dist-esm/index.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/shapes/arrow/ArrowShapeUtil.mjs +4 -3
- package/dist-esm/lib/shapes/arrow/ArrowShapeUtil.mjs.map +2 -2
- 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 +13 -12
- 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 +3 -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 +3 -3
- package/dist-esm/lib/shapes/image/ImageShapeUtil.mjs.map +1 -1
- 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 +5 -4
- package/dist-esm/lib/shapes/note/NoteShapeUtil.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/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 +16 -2
- 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/DefaultMenuPanel.mjs +3 -2
- package/dist-esm/lib/ui/components/DefaultMenuPanel.mjs.map +2 -2
- 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 +3 -1
- package/dist-esm/lib/ui/components/StylePanel/DefaultStylePanel.mjs.map +2 -2
- package/dist-esm/lib/ui/components/StylePanel/DefaultStylePanelContent.mjs +171 -140
- package/dist-esm/lib/ui/components/StylePanel/DefaultStylePanelContent.mjs.map +2 -2
- package/dist-esm/lib/ui/components/StylePanel/DoubleDropdownPicker.mjs +3 -3
- package/dist-esm/lib/ui/components/StylePanel/DoubleDropdownPicker.mjs.map +2 -2
- package/dist-esm/lib/ui/components/StylePanel/DropdownPicker.mjs +26 -25
- package/dist-esm/lib/ui/components/StylePanel/DropdownPicker.mjs.map +2 -2
- package/dist-esm/lib/ui/components/Toolbar/DefaultImageToolbarContent.mjs +1 -1
- 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/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/TldrawUiButtonPicker.mjs +6 -6
- package/dist-esm/lib/ui/components/primitives/TldrawUiButtonPicker.mjs.map +2 -2
- package/dist-esm/lib/ui/components/primitives/TldrawUiContextualToolbar.mjs +1 -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/TldrawUiToolbar.mjs +30 -7
- package/dist-esm/lib/ui/components/primitives/TldrawUiToolbar.mjs.map +2 -2
- package/dist-esm/lib/ui/components/primitives/TldrawUiTooltip.mjs +245 -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 +12 -26
- 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 +15 -0
- package/dist-esm/lib/ui/context/actions.mjs.map +2 -2
- package/dist-esm/lib/ui/context/events.mjs.map +2 -2
- package/dist-esm/lib/ui/hooks/useTools.mjs +22 -3
- package/dist-esm/lib/ui/hooks/useTools.mjs.map +2 -2
- package/dist-esm/lib/ui/hooks/useTranslation/defaultTranslation.mjs +3 -0
- package/dist-esm/lib/ui/hooks/useTranslation/defaultTranslation.mjs.map +2 -2
- package/dist-esm/lib/ui/version.mjs +3 -3
- package/dist-esm/lib/ui/version.mjs.map +1 -1
- package/package.json +11 -34
- package/src/index.ts +21 -0
- package/src/lib/canvas/TldrawScribble.tsx +1 -1
- package/src/lib/shapes/arrow/ArrowShapeOptions.test.ts +2 -1
- package/src/lib/shapes/arrow/ArrowShapeTool.test.ts +4 -3
- package/src/lib/shapes/arrow/ArrowShapeUtil.test.ts +7 -6
- package/src/lib/shapes/arrow/ArrowShapeUtil.tsx +4 -3
- 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 +21 -14
- package/src/lib/shapes/frame/components/FrameHeading.tsx +1 -1
- package/src/lib/shapes/geo/GeoShapeUtil.tsx +3 -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 +3 -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 +9 -4
- package/src/lib/shapes/shared/ShapeFill.tsx +5 -4
- package/src/lib/shapes/shared/freehand/svg.ts +2 -0
- 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 +17 -2
- 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/DefaultMenuPanel.tsx +4 -3
- 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 +3 -1
- package/src/lib/ui/components/StylePanel/DefaultStylePanelContent.tsx +146 -107
- package/src/lib/ui/components/StylePanel/DoubleDropdownPicker.tsx +3 -3
- package/src/lib/ui/components/StylePanel/DropdownPicker.tsx +7 -6
- package/src/lib/ui/components/Toolbar/DefaultImageToolbarContent.tsx +1 -1
- package/src/lib/ui/components/Toolbar/DefaultToolbar.tsx +55 -23
- 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/TldrawUiButtonPicker.tsx +40 -37
- package/src/lib/ui/components/primitives/TldrawUiContextualToolbar.tsx +1 -1
- package/src/lib/ui/components/primitives/TldrawUiPopover.tsx +4 -2
- package/src/lib/ui/components/primitives/TldrawUiToolbar.tsx +51 -12
- package/src/lib/ui/components/primitives/TldrawUiTooltip.tsx +327 -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 +18 -27
- package/src/lib/ui/context/TldrawUiContextProvider.tsx +23 -20
- package/src/lib/ui/context/actions.tsx +15 -0
- package/src/lib/ui/context/events.tsx +1 -0
- package/src/lib/ui/hooks/useTools.tsx +25 -3
- package/src/lib/ui/hooks/useTranslation/TLUiTranslationKey.ts +3 -0
- package/src/lib/ui/hooks/useTranslation/defaultTranslation.ts +3 -0
- package/src/lib/ui/version.ts +3 -3
- package/src/lib/ui.css +406 -292
- package/src/lib/utils/excalidraw/__snapshots__/putExcalidrawContent.test.tsx.snap +5 -5
- 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/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 +3 -2
- 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 +699 -580
|
@@ -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": ";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;
|
|
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}),\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
|
}
|
|
@@ -48,13 +48,13 @@ const ShapeFill = import_react.default.memo(function ShapeFill2({
|
|
|
48
48
|
return null;
|
|
49
49
|
}
|
|
50
50
|
case "solid": {
|
|
51
|
-
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { fill: theme
|
|
51
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { fill: (0, import_editor.getColorValue)(theme, color, "semi"), d });
|
|
52
52
|
}
|
|
53
53
|
case "semi": {
|
|
54
54
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { fill: theme.solid, d });
|
|
55
55
|
}
|
|
56
56
|
case "fill": {
|
|
57
|
-
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { fill: theme
|
|
57
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { fill: (0, import_editor.getColorValue)(theme, color, "fill"), d });
|
|
58
58
|
}
|
|
59
59
|
case "pattern": {
|
|
60
60
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(PatternFill, { theme, color, fill, d, scale });
|
|
@@ -68,11 +68,11 @@ function PatternFill({ d, color, theme }) {
|
|
|
68
68
|
const getHashPatternZoomName = (0, import_defaultStyleDefs.useGetHashPatternZoomName)();
|
|
69
69
|
const teenyTiny = editor.getZoomLevel() <= 0.18;
|
|
70
70
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
|
|
71
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { fill: theme
|
|
71
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { fill: (0, import_editor.getColorValue)(theme, color, "pattern"), d }),
|
|
72
72
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
73
73
|
"path",
|
|
74
74
|
{
|
|
75
|
-
fill: svgExport ? `url(#${getHashPatternZoomName(1, theme.id)})` : teenyTiny ? theme
|
|
75
|
+
fill: svgExport ? `url(#${getHashPatternZoomName(1, theme.id)})` : teenyTiny ? (0, import_editor.getColorValue)(theme, color, "semi") : `url(#${getHashPatternZoomName(zoomLevel, theme.id)})`,
|
|
76
76
|
d
|
|
77
77
|
}
|
|
78
78
|
)
|
|
@@ -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": ";;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;
|
|
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": ";;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAgCU;AAhCV,oBAQO;AACP,mBAAkB;AAClB,8BAA0C;AAUnC,MAAM,YAAY,aAAAA,QAAM,KAAK,SAASC,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,4CAAC,UAAK,UAAM,6BAAc,OAAO,OAAO,MAAM,GAAG,GAAM;AAAA,IAC/D;AAAA,IACA,KAAK,QAAQ;AACZ,aAAO,4CAAC,UAAK,MAAM,MAAM,OAAO,GAAM;AAAA,IACvC;AAAA,IACA,KAAK,QAAQ;AACZ,aAAO,4CAAC,UAAK,UAAM,6BAAc,OAAO,OAAO,MAAM,GAAG,GAAM;AAAA,IAC/D;AAAA,IACA,KAAK,WAAW;AACf,aAAO,4CAAC,eAAY,OAAc,OAAc,MAAY,GAAM,OAAc;AAAA,IACjF;AAAA,EACD;AACD,CAAC;AAEM,SAAS,YAAY,EAAE,GAAG,OAAO,MAAM,GAAmB;AAChE,QAAM,aAAS,yBAAU;AACzB,QAAM,gBAAY,mCAAoB;AACtC,QAAM,gBAAY,wBAAS,aAAa,MAAM,OAAO,aAAa,GAAG,CAAC,MAAM,CAAC;AAC7E,QAAM,6BAAyB,mDAA0B;AAEzD,QAAM,YAAY,OAAO,aAAa,KAAK;AAE3C,SACC,4EACC;AAAA,gDAAC,UAAK,UAAM,6BAAc,OAAO,OAAO,SAAS,GAAG,GAAM;AAAA,IAC1D;AAAA,MAAC;AAAA;AAAA,QACA,MACC,YACG,QAAQ,uBAAuB,GAAG,MAAM,EAAE,CAAC,MAC3C,gBACC,6BAAc,OAAO,OAAO,MAAM,IAClC,QAAQ,uBAAuB,WAAW,MAAM,EAAE,CAAC;AAAA,QAExD;AAAA;AAAA,IACD;AAAA,KACD;AAEF;",
|
|
6
6
|
"names": ["React", "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;AAAA;AAAA;AAAA;AAAA;AAAA,oBAAiC;
|
|
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;AAAA;AAAA;AAAA;AAAA;AAAA,oBAAiC;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,QAAI,uBAAQ,CAAC,CAAC,QAAI,uBAAQ,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,kBAAU,uBAAQ,GAAG,CAAC;AAAA,EACvB;AAEA,MAAI,QAAQ;AAEX,WAAO,QAAI,uBAAQ,OAAO,CAAC,EAAE,OAAO,OAAO,CAAC,EAAE,KAAK,CAAC,QAAI,uBAAQ,OAAO,CAAC,EAAE,KAAK,CAAC,OAAG;AAAA,MAClF,OAAO,CAAC,EAAE;AAAA,MACV,OAAO,CAAC,EAAE;AAAA,IACX,CAAC,IAAI,MAAM,OAAG,uBAAQ,OAAO,MAAM,CAAC,EAAE,OAAO,OAAO,CAAC,EAAE,KAAK,CAAC,OAAG;AAAA,MAC/D,OAAO,CAAC,EAAE;AAAA,MACV,OAAO,CAAC,EAAE;AAAA,IACX,CAAC;AAAA,EACF,OAAO;AAIN,WAAO,QAAI,uBAAQ,OAAO,CAAC,EAAE,KAAK,CAAC,QAAI,uBAAQ,OAAO,CAAC,EAAE,KAAK,CAAC,OAAG;AAAA,MACjE,OAAO,CAAC,EAAE;AAAA,MACV,OAAO,CAAC,EAAE;AAAA,IACX,CAAC,GAAG,OAAO,SAAS,IAAI,MAAM,EAAE,GAAG,MAAM,QAAI,uBAAQ,OAAO,MAAM,CAAC,EAAE,KAAK,CAAC;AAAA,EAC5E;AACD;",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -21,10 +21,19 @@ __export(usePrefersReducedMotion_exports, {
|
|
|
21
21
|
usePrefersReducedMotion: () => usePrefersReducedMotion
|
|
22
22
|
});
|
|
23
23
|
module.exports = __toCommonJS(usePrefersReducedMotion_exports);
|
|
24
|
+
var import_editor = require("@tldraw/editor");
|
|
24
25
|
var import_react = require("react");
|
|
25
26
|
function usePrefersReducedMotion() {
|
|
27
|
+
const editor = (0, import_editor.useMaybeEditor)();
|
|
28
|
+
const animationSpeed = (0, import_editor.useValue)("animationSpeed", () => editor?.user.getAnimationSpeed(), [
|
|
29
|
+
editor
|
|
30
|
+
]);
|
|
26
31
|
const [prefersReducedMotion, setPrefersReducedMotion] = (0, import_react.useState)(false);
|
|
27
32
|
(0, import_react.useEffect)(() => {
|
|
33
|
+
if (animationSpeed !== void 0) {
|
|
34
|
+
setPrefersReducedMotion(animationSpeed === 0 ? true : false);
|
|
35
|
+
return;
|
|
36
|
+
}
|
|
28
37
|
if (typeof window === "undefined" || !("matchMedia" in window)) return;
|
|
29
38
|
const mql = window.matchMedia("(prefers-reduced-motion: reduce)");
|
|
30
39
|
const handler = () => {
|
|
@@ -33,7 +42,7 @@ function usePrefersReducedMotion() {
|
|
|
33
42
|
handler();
|
|
34
43
|
mql.addEventListener("change", handler);
|
|
35
44
|
return () => mql.removeEventListener("change", handler);
|
|
36
|
-
}, []);
|
|
45
|
+
}, [animationSpeed]);
|
|
37
46
|
return prefersReducedMotion;
|
|
38
47
|
}
|
|
39
48
|
//# sourceMappingURL=usePrefersReducedMotion.js.map
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../../src/lib/shapes/shared/usePrefersReducedMotion.tsx"],
|
|
4
|
-
"sourcesContent": ["import { useEffect, useState } from 'react'\n\n/** @public */\nexport function usePrefersReducedMotion() {\n\tconst [prefersReducedMotion, setPrefersReducedMotion] = useState(false)\n\n\tuseEffect(() => {\n\t\tif (typeof window === 'undefined' || !('matchMedia' in window)) return\n\t\tconst mql = window.matchMedia('(prefers-reduced-motion: reduce)')\n\t\tconst handler = () => {\n\t\t\tsetPrefersReducedMotion(mql.matches)\n\t\t}\n\t\thandler()\n\t\tmql.addEventListener('change', handler)\n\t\treturn () => mql.removeEventListener('change', handler)\n\t}, [])\n\n\treturn prefersReducedMotion\n}\n"],
|
|
5
|
-
"mappings": ";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,mBAAoC;AAG7B,SAAS,0BAA0B;AACzC,QAAM,CAAC,sBAAsB,uBAAuB,QAAI,uBAAS,KAAK;AAEtE,8BAAU,MAAM;AACf,QAAI,OAAO,WAAW,eAAe,EAAE,gBAAgB,QAAS;AAChE,UAAM,MAAM,OAAO,WAAW,kCAAkC;AAChE,UAAM,UAAU,MAAM;AACrB,8BAAwB,IAAI,OAAO;AAAA,IACpC;AACA,YAAQ;AACR,QAAI,iBAAiB,UAAU,OAAO;AACtC,WAAO,MAAM,IAAI,oBAAoB,UAAU,OAAO;AAAA,EACvD,GAAG,CAAC,CAAC;
|
|
4
|
+
"sourcesContent": ["import { useMaybeEditor, useValue } from '@tldraw/editor'\nimport { useEffect, useState } from 'react'\n\n/** @public */\nexport function usePrefersReducedMotion() {\n\tconst editor = useMaybeEditor()\n\tconst animationSpeed = useValue('animationSpeed', () => editor?.user.getAnimationSpeed(), [\n\t\teditor,\n\t])\n\tconst [prefersReducedMotion, setPrefersReducedMotion] = useState(false)\n\n\tuseEffect(() => {\n\t\tif (animationSpeed !== undefined) {\n\t\t\tsetPrefersReducedMotion(animationSpeed === 0 ? true : false)\n\t\t\treturn\n\t\t}\n\n\t\tif (typeof window === 'undefined' || !('matchMedia' in window)) return\n\t\tconst mql = window.matchMedia('(prefers-reduced-motion: reduce)')\n\t\tconst handler = () => {\n\t\t\tsetPrefersReducedMotion(mql.matches)\n\t\t}\n\t\thandler()\n\t\tmql.addEventListener('change', handler)\n\t\treturn () => mql.removeEventListener('change', handler)\n\t}, [animationSpeed])\n\n\treturn prefersReducedMotion\n}\n"],
|
|
5
|
+
"mappings": ";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,oBAAyC;AACzC,mBAAoC;AAG7B,SAAS,0BAA0B;AACzC,QAAM,aAAS,8BAAe;AAC9B,QAAM,qBAAiB,wBAAS,kBAAkB,MAAM,QAAQ,KAAK,kBAAkB,GAAG;AAAA,IACzF;AAAA,EACD,CAAC;AACD,QAAM,CAAC,sBAAsB,uBAAuB,QAAI,uBAAS,KAAK;AAEtE,8BAAU,MAAM;AACf,QAAI,mBAAmB,QAAW;AACjC,8BAAwB,mBAAmB,IAAI,OAAO,KAAK;AAC3D;AAAA,IACD;AAEA,QAAI,OAAO,WAAW,eAAe,EAAE,gBAAgB,QAAS;AAChE,UAAM,MAAM,OAAO,WAAW,kCAAkC;AAChE,UAAM,UAAU,MAAM;AACrB,8BAAwB,IAAI,OAAO;AAAA,IACpC;AACA,YAAQ;AACR,QAAI,iBAAiB,UAAU,OAAO;AACtC,WAAO,MAAM,IAAI,oBAAoB,UAAU,OAAO;AAAA,EACvD,GAAG,CAAC,cAAc,CAAC;AAEnB,SAAO;AACR;",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -108,7 +108,7 @@ class TextShapeUtil extends import_editor.ShapeUtil {
|
|
|
108
108
|
align: textAlign,
|
|
109
109
|
verticalAlign: "middle",
|
|
110
110
|
richText,
|
|
111
|
-
labelColor: theme
|
|
111
|
+
labelColor: (0, import_editor.getColorValue)(theme, color, "solid"),
|
|
112
112
|
isSelected,
|
|
113
113
|
textWidth: width,
|
|
114
114
|
textHeight: height,
|
|
@@ -141,7 +141,7 @@ class TextShapeUtil extends import_editor.ShapeUtil {
|
|
|
141
141
|
align: shape.props.textAlign,
|
|
142
142
|
verticalAlign: "middle",
|
|
143
143
|
richText: shape.props.richText,
|
|
144
|
-
labelColor: theme
|
|
144
|
+
labelColor: (0, import_editor.getColorValue)(theme, shape.props.color, "solid"),
|
|
145
145
|
bounds: exportBounds,
|
|
146
146
|
padding: 0
|
|
147
147
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../../src/lib/shapes/text/TextShapeUtil.tsx"],
|
|
4
|
-
"sourcesContent": ["/* eslint-disable react-hooks/rules-of-hooks */\nimport {\n\tBox,\n\tEditor,\n\tRectangle2d,\n\tShapeUtil,\n\tSvgExportContext,\n\tTLGeometryOpts,\n\tTLResizeInfo,\n\tTLShapeId,\n\tTLTextShape,\n\tVec,\n\tcreateComputedCache,\n\tgetDefaultColorTheme,\n\tgetFontsFromRichText,\n\tisEqual,\n\tresizeScaled,\n\ttextShapeMigrations,\n\ttextShapeProps,\n\ttoDomPrecision,\n\ttoRichText,\n\tuseEditor,\n} from '@tldraw/editor'\nimport { useCallback } from 'react'\nimport {\n\trenderHtmlFromRichTextForMeasurement,\n\trenderPlaintextFromRichText,\n} from '../../utils/text/richText'\nimport { RichTextLabel, RichTextSVG } from '../shared/RichTextLabel'\nimport { FONT_FAMILIES, FONT_SIZES, TEXT_PROPS } from '../shared/default-shape-constants'\nimport { useDefaultColorTheme } from '../shared/useDefaultColorTheme'\n\nconst sizeCache = createComputedCache(\n\t'text size',\n\t(editor: Editor, shape: TLTextShape) => {\n\t\teditor.fonts.trackFontsForShape(shape)\n\t\treturn getTextSize(editor, shape.props)\n\t},\n\t{ areRecordsEqual: (a, b) => a.props === b.props }\n)\n/** @public */\nexport interface TextShapeOptions {\n\t/** How much addition padding should be added to the horizontal geometry of the shape when binding to an arrow? */\n\textraArrowHorizontalPadding: number\n}\n\n/** @public */\nexport class TextShapeUtil extends ShapeUtil<TLTextShape> {\n\tstatic override type = 'text' as const\n\tstatic override props = textShapeProps\n\tstatic override migrations = textShapeMigrations\n\n\toverride options: TextShapeOptions = {\n\t\textraArrowHorizontalPadding: 10,\n\t}\n\n\tgetDefaultProps(): TLTextShape['props'] {\n\t\treturn {\n\t\t\tcolor: 'black',\n\t\t\tsize: 'm',\n\t\t\tw: 8,\n\t\t\tfont: 'draw',\n\t\t\ttextAlign: 'start',\n\t\t\tautoSize: true,\n\t\t\tscale: 1,\n\t\t\trichText: toRichText(''),\n\t\t}\n\t}\n\n\tgetMinDimensions(shape: TLTextShape) {\n\t\treturn sizeCache.get(this.editor, shape.id)!\n\t}\n\n\tgetGeometry(shape: TLTextShape, opts: TLGeometryOpts) {\n\t\tconst { scale } = shape.props\n\t\tconst { width, height } = this.getMinDimensions(shape)!\n\t\tconst context = opts?.context ?? 'none'\n\t\treturn new Rectangle2d({\n\t\t\tx:\n\t\t\t\t(context === '@tldraw/arrow-without-arrowhead'\n\t\t\t\t\t? -this.options.extraArrowHorizontalPadding\n\t\t\t\t\t: 0) * scale,\n\t\t\twidth:\n\t\t\t\t(width +\n\t\t\t\t\t(context === '@tldraw/arrow-without-arrowhead'\n\t\t\t\t\t\t? this.options.extraArrowHorizontalPadding * 2\n\t\t\t\t\t\t: 0)) *\n\t\t\t\tscale,\n\t\t\theight: height * scale,\n\t\t\tisFilled: true,\n\t\t\tisLabel: true,\n\t\t})\n\t}\n\n\toverride getFontFaces(shape: TLTextShape) {\n\t\t// no need for an empty rich text check here\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\toverride getText(shape: TLTextShape) {\n\t\treturn renderPlaintextFromRichText(this.editor, shape.props.richText)\n\t}\n\n\toverride canEdit() {\n\t\treturn true\n\t}\n\n\toverride isAspectRatioLocked() {\n\t\treturn true\n\t} // WAIT NO THIS IS HARD CODED IN THE RESIZE HANDLER\n\n\tcomponent(shape: TLTextShape) {\n\t\tconst {\n\t\t\tid,\n\t\t\tprops: { font, size, richText, color, scale, textAlign },\n\t\t} = shape\n\n\t\tconst { width, height } = this.getMinDimensions(shape)\n\t\tconst isSelected = shape.id === this.editor.getOnlySelectedShapeId()\n\t\tconst theme = useDefaultColorTheme()\n\t\tconst handleKeyDown = useTextShapeKeydownHandler(id)\n\n\t\treturn (\n\t\t\t<RichTextLabel\n\t\t\t\tshapeId={id}\n\t\t\t\tclassNamePrefix=\"tl-text-shape\"\n\t\t\t\ttype=\"text\"\n\t\t\t\tfont={font}\n\t\t\t\tfontSize={FONT_SIZES[size]}\n\t\t\t\tlineHeight={TEXT_PROPS.lineHeight}\n\t\t\t\talign={textAlign}\n\t\t\t\tverticalAlign=\"middle\"\n\t\t\t\trichText={richText}\n\t\t\t\tlabelColor={theme[color].solid}\n\t\t\t\tisSelected={isSelected}\n\t\t\t\ttextWidth={width}\n\t\t\t\ttextHeight={height}\n\t\t\t\tstyle={{\n\t\t\t\t\ttransform: `scale(${scale})`,\n\t\t\t\t\ttransformOrigin: 'top left',\n\t\t\t\t}}\n\t\t\t\twrap\n\t\t\t\tonKeyDown={handleKeyDown}\n\t\t\t/>\n\t\t)\n\t}\n\n\tindicator(shape: TLTextShape) {\n\t\tconst bounds = this.editor.getShapeGeometry(shape).bounds\n\t\tconst editor = useEditor()\n\t\tif (shape.props.autoSize && editor.getEditingShapeId() === shape.id) return null\n\t\treturn <rect width={toDomPrecision(bounds.width)} height={toDomPrecision(bounds.height)} />\n\t}\n\n\toverride toSvg(shape: TLTextShape, ctx: SvgExportContext) {\n\t\tconst bounds = this.editor.getShapeGeometry(shape).bounds\n\t\tconst width = bounds.width / (shape.props.scale ?? 1)\n\t\tconst height = bounds.height / (shape.props.scale ?? 1)\n\n\t\tconst theme = getDefaultColorTheme(ctx)\n\n\t\tconst exportBounds = new Box(0, 0, width, height)\n\t\treturn (\n\t\t\t<RichTextSVG\n\t\t\t\tfontSize={FONT_SIZES[shape.props.size]}\n\t\t\t\tfont={shape.props.font}\n\t\t\t\talign={shape.props.textAlign}\n\t\t\t\tverticalAlign=\"middle\"\n\t\t\t\trichText={shape.props.richText}\n\t\t\t\tlabelColor={theme[shape.props.color].solid}\n\t\t\t\tbounds={exportBounds}\n\t\t\t\tpadding={0}\n\t\t\t/>\n\t\t)\n\t}\n\n\toverride onResize(shape: TLTextShape, info: TLResizeInfo<TLTextShape>) {\n\t\tconst { newPoint, initialBounds, initialShape, scaleX, handle } = info\n\n\t\tif (info.mode === 'scale_shape' || (handle !== 'right' && handle !== 'left')) {\n\t\t\treturn {\n\t\t\t\tid: shape.id,\n\t\t\t\ttype: shape.type,\n\t\t\t\t...resizeScaled(shape, info),\n\t\t\t}\n\t\t} else {\n\t\t\tconst nextWidth = Math.max(1, Math.abs(initialBounds.width * scaleX))\n\t\t\tconst { x, y } =\n\t\t\t\tscaleX < 0 ? Vec.Sub(newPoint, Vec.FromAngle(shape.rotation).mul(nextWidth)) : newPoint\n\n\t\t\treturn {\n\t\t\t\tid: shape.id,\n\t\t\t\ttype: shape.type,\n\t\t\t\tx,\n\t\t\t\ty,\n\t\t\t\tprops: {\n\t\t\t\t\tw: nextWidth / initialShape.props.scale,\n\t\t\t\t\tautoSize: false,\n\t\t\t\t},\n\t\t\t}\n\t\t}\n\t}\n\n\toverride onEditEnd(shape: TLTextShape) {\n\t\t// todo: find a way to check if the rich text has any nodes that aren't empty spaces\n\t\tconst trimmedText = renderPlaintextFromRichText(this.editor, shape.props.richText).trimEnd()\n\n\t\tif (trimmedText.length === 0) {\n\t\t\tthis.editor.deleteShapes([shape.id])\n\t\t}\n\t}\n\n\toverride onBeforeUpdate(prev: TLTextShape, next: TLTextShape) {\n\t\tif (!next.props.autoSize) return\n\n\t\tconst styleDidChange =\n\t\t\tprev.props.size !== next.props.size ||\n\t\t\tprev.props.textAlign !== next.props.textAlign ||\n\t\t\tprev.props.font !== next.props.font ||\n\t\t\t(prev.props.scale !== 1 && next.props.scale === 1)\n\n\t\tconst textDidChange = !isEqual(prev.props.richText, next.props.richText)\n\n\t\t// Only update position if either changed\n\t\tif (!styleDidChange && !textDidChange) return\n\n\t\t// Might return a cached value for the bounds\n\t\tconst boundsA = this.getMinDimensions(prev)\n\n\t\t// Will always be a fresh call to getTextSize\n\t\tconst boundsB = getTextSize(this.editor, next.props)\n\n\t\tconst wA = boundsA.width * prev.props.scale\n\t\tconst hA = boundsA.height * prev.props.scale\n\t\tconst wB = boundsB.width * next.props.scale\n\t\tconst hB = boundsB.height * next.props.scale\n\n\t\tlet delta: Vec | undefined\n\n\t\tswitch (next.props.textAlign) {\n\t\t\tcase 'middle': {\n\t\t\t\tdelta = new Vec((wB - wA) / 2, textDidChange ? 0 : (hB - hA) / 2)\n\t\t\t\tbreak\n\t\t\t}\n\t\t\tcase 'end': {\n\t\t\t\tdelta = new Vec(wB - wA, textDidChange ? 0 : (hB - hA) / 2)\n\t\t\t\tbreak\n\t\t\t}\n\t\t\tdefault: {\n\t\t\t\tif (textDidChange) break\n\t\t\t\tdelta = new Vec(0, (hB - hA) / 2)\n\t\t\t\tbreak\n\t\t\t}\n\t\t}\n\n\t\tif (delta) {\n\t\t\t// account for shape rotation when writing text:\n\t\t\tdelta.rot(next.rotation)\n\t\t\tconst { x, y } = next\n\t\t\treturn {\n\t\t\t\t...next,\n\t\t\t\tx: x - delta.x,\n\t\t\t\ty: y - delta.y,\n\t\t\t\tprops: { ...next.props, w: wB },\n\t\t\t}\n\t\t} else {\n\t\t\treturn {\n\t\t\t\t...next,\n\t\t\t\tprops: { ...next.props, w: wB },\n\t\t\t}\n\t\t}\n\t}\n\n\t// \ttodo: The edge doubleclicking feels like a mistake more often than\n\t// not, especially on multiline text. Removed June 16 2024\n\n\t// override onDoubleClickEdge = (shape: TLTextShape) => {\n\t// \t// If the shape has a fixed width, set it to autoSize.\n\t// \tif (!shape.props.autoSize) {\n\t// \t\treturn {\n\t// \t\t\tid: shape.id,\n\t// \t\t\ttype: shape.type,\n\t// \t\t\tprops: {\n\t// \t\t\t\tautoSize: true,\n\t// \t\t\t},\n\t// \t\t}\n\t// \t}\n\t// \t// If the shape is scaled, reset the scale to 1.\n\t// \tif (shape.props.scale !== 1) {\n\t// \t\treturn {\n\t// \t\t\tid: shape.id,\n\t// \t\t\ttype: shape.type,\n\t// \t\t\tprops: {\n\t// \t\t\t\tscale: 1,\n\t// \t\t\t},\n\t// \t\t}\n\t// \t}\n\t// }\n}\n\nfunction getTextSize(editor: Editor, props: TLTextShape['props']) {\n\tconst { font, richText, size, w } = props\n\n\tconst minWidth = 16\n\tconst fontSize = FONT_SIZES[size]\n\n\tconst maybeFixedWidth = props.autoSize ? null : Math.max(minWidth, Math.floor(w))\n\n\tconst html = renderHtmlFromRichTextForMeasurement(editor, richText)\n\tconst result = editor.textMeasure.measureHtml(html, {\n\t\t...TEXT_PROPS,\n\t\tfontFamily: FONT_FAMILIES[font],\n\t\tfontSize: fontSize,\n\t\tmaxWidth: maybeFixedWidth,\n\t})\n\n\t// If we're autosizing the measureText will essentially `Math.floor`\n\t// the numbers so `19` rather than `19.3`, this means we must +1 to\n\t// whatever we get to avoid wrapping.\n\treturn {\n\t\twidth: maybeFixedWidth ?? Math.max(minWidth, result.w + 1),\n\t\theight: Math.max(fontSize, result.h),\n\t}\n}\n\nfunction useTextShapeKeydownHandler(id: TLShapeId) {\n\tconst editor = useEditor()\n\n\treturn useCallback(\n\t\t(e: KeyboardEvent) => {\n\t\t\tif (editor.getEditingShapeId() !== id) return\n\n\t\t\tswitch (e.key) {\n\t\t\t\tcase 'Enter': {\n\t\t\t\t\tif (e.ctrlKey || e.metaKey) {\n\t\t\t\t\t\teditor.complete()\n\t\t\t\t\t}\n\t\t\t\t\tbreak\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\t\t[editor, id]\n\t)\n}\n"],
|
|
5
|
-
"mappings": ";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AA
|
|
4
|
+
"sourcesContent": ["/* eslint-disable react-hooks/rules-of-hooks */\nimport {\n\tBox,\n\tEditor,\n\tRectangle2d,\n\tShapeUtil,\n\tSvgExportContext,\n\tTLGeometryOpts,\n\tTLResizeInfo,\n\tTLShapeId,\n\tTLTextShape,\n\tVec,\n\tcreateComputedCache,\n\tgetColorValue,\n\tgetDefaultColorTheme,\n\tgetFontsFromRichText,\n\tisEqual,\n\tresizeScaled,\n\ttextShapeMigrations,\n\ttextShapeProps,\n\ttoDomPrecision,\n\ttoRichText,\n\tuseEditor,\n} from '@tldraw/editor'\nimport { useCallback } from 'react'\nimport {\n\trenderHtmlFromRichTextForMeasurement,\n\trenderPlaintextFromRichText,\n} from '../../utils/text/richText'\nimport { RichTextLabel, RichTextSVG } from '../shared/RichTextLabel'\nimport { FONT_FAMILIES, FONT_SIZES, TEXT_PROPS } from '../shared/default-shape-constants'\nimport { useDefaultColorTheme } from '../shared/useDefaultColorTheme'\n\nconst sizeCache = createComputedCache(\n\t'text size',\n\t(editor: Editor, shape: TLTextShape) => {\n\t\teditor.fonts.trackFontsForShape(shape)\n\t\treturn getTextSize(editor, shape.props)\n\t},\n\t{ areRecordsEqual: (a, b) => a.props === b.props }\n)\n/** @public */\nexport interface TextShapeOptions {\n\t/** How much addition padding should be added to the horizontal geometry of the shape when binding to an arrow? */\n\textraArrowHorizontalPadding: number\n}\n\n/** @public */\nexport class TextShapeUtil extends ShapeUtil<TLTextShape> {\n\tstatic override type = 'text' as const\n\tstatic override props = textShapeProps\n\tstatic override migrations = textShapeMigrations\n\n\toverride options: TextShapeOptions = {\n\t\textraArrowHorizontalPadding: 10,\n\t}\n\n\tgetDefaultProps(): TLTextShape['props'] {\n\t\treturn {\n\t\t\tcolor: 'black',\n\t\t\tsize: 'm',\n\t\t\tw: 8,\n\t\t\tfont: 'draw',\n\t\t\ttextAlign: 'start',\n\t\t\tautoSize: true,\n\t\t\tscale: 1,\n\t\t\trichText: toRichText(''),\n\t\t}\n\t}\n\n\tgetMinDimensions(shape: TLTextShape) {\n\t\treturn sizeCache.get(this.editor, shape.id)!\n\t}\n\n\tgetGeometry(shape: TLTextShape, opts: TLGeometryOpts) {\n\t\tconst { scale } = shape.props\n\t\tconst { width, height } = this.getMinDimensions(shape)!\n\t\tconst context = opts?.context ?? 'none'\n\t\treturn new Rectangle2d({\n\t\t\tx:\n\t\t\t\t(context === '@tldraw/arrow-without-arrowhead'\n\t\t\t\t\t? -this.options.extraArrowHorizontalPadding\n\t\t\t\t\t: 0) * scale,\n\t\t\twidth:\n\t\t\t\t(width +\n\t\t\t\t\t(context === '@tldraw/arrow-without-arrowhead'\n\t\t\t\t\t\t? this.options.extraArrowHorizontalPadding * 2\n\t\t\t\t\t\t: 0)) *\n\t\t\t\tscale,\n\t\t\theight: height * scale,\n\t\t\tisFilled: true,\n\t\t\tisLabel: true,\n\t\t})\n\t}\n\n\toverride getFontFaces(shape: TLTextShape) {\n\t\t// no need for an empty rich text check here\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\toverride getText(shape: TLTextShape) {\n\t\treturn renderPlaintextFromRichText(this.editor, shape.props.richText)\n\t}\n\n\toverride canEdit() {\n\t\treturn true\n\t}\n\n\toverride isAspectRatioLocked() {\n\t\treturn true\n\t} // WAIT NO THIS IS HARD CODED IN THE RESIZE HANDLER\n\n\tcomponent(shape: TLTextShape) {\n\t\tconst {\n\t\t\tid,\n\t\t\tprops: { font, size, richText, color, scale, textAlign },\n\t\t} = shape\n\n\t\tconst { width, height } = this.getMinDimensions(shape)\n\t\tconst isSelected = shape.id === this.editor.getOnlySelectedShapeId()\n\t\tconst theme = useDefaultColorTheme()\n\t\tconst handleKeyDown = useTextShapeKeydownHandler(id)\n\n\t\treturn (\n\t\t\t<RichTextLabel\n\t\t\t\tshapeId={id}\n\t\t\t\tclassNamePrefix=\"tl-text-shape\"\n\t\t\t\ttype=\"text\"\n\t\t\t\tfont={font}\n\t\t\t\tfontSize={FONT_SIZES[size]}\n\t\t\t\tlineHeight={TEXT_PROPS.lineHeight}\n\t\t\t\talign={textAlign}\n\t\t\t\tverticalAlign=\"middle\"\n\t\t\t\trichText={richText}\n\t\t\t\tlabelColor={getColorValue(theme, color, 'solid')}\n\t\t\t\tisSelected={isSelected}\n\t\t\t\ttextWidth={width}\n\t\t\t\ttextHeight={height}\n\t\t\t\tstyle={{\n\t\t\t\t\ttransform: `scale(${scale})`,\n\t\t\t\t\ttransformOrigin: 'top left',\n\t\t\t\t}}\n\t\t\t\twrap\n\t\t\t\tonKeyDown={handleKeyDown}\n\t\t\t/>\n\t\t)\n\t}\n\n\tindicator(shape: TLTextShape) {\n\t\tconst bounds = this.editor.getShapeGeometry(shape).bounds\n\t\tconst editor = useEditor()\n\t\tif (shape.props.autoSize && editor.getEditingShapeId() === shape.id) return null\n\t\treturn <rect width={toDomPrecision(bounds.width)} height={toDomPrecision(bounds.height)} />\n\t}\n\n\toverride toSvg(shape: TLTextShape, ctx: SvgExportContext) {\n\t\tconst bounds = this.editor.getShapeGeometry(shape).bounds\n\t\tconst width = bounds.width / (shape.props.scale ?? 1)\n\t\tconst height = bounds.height / (shape.props.scale ?? 1)\n\n\t\tconst theme = getDefaultColorTheme(ctx)\n\n\t\tconst exportBounds = new Box(0, 0, width, height)\n\t\treturn (\n\t\t\t<RichTextSVG\n\t\t\t\tfontSize={FONT_SIZES[shape.props.size]}\n\t\t\t\tfont={shape.props.font}\n\t\t\t\talign={shape.props.textAlign}\n\t\t\t\tverticalAlign=\"middle\"\n\t\t\t\trichText={shape.props.richText}\n\t\t\t\tlabelColor={getColorValue(theme, shape.props.color, 'solid')}\n\t\t\t\tbounds={exportBounds}\n\t\t\t\tpadding={0}\n\t\t\t/>\n\t\t)\n\t}\n\n\toverride onResize(shape: TLTextShape, info: TLResizeInfo<TLTextShape>) {\n\t\tconst { newPoint, initialBounds, initialShape, scaleX, handle } = info\n\n\t\tif (info.mode === 'scale_shape' || (handle !== 'right' && handle !== 'left')) {\n\t\t\treturn {\n\t\t\t\tid: shape.id,\n\t\t\t\ttype: shape.type,\n\t\t\t\t...resizeScaled(shape, info),\n\t\t\t}\n\t\t} else {\n\t\t\tconst nextWidth = Math.max(1, Math.abs(initialBounds.width * scaleX))\n\t\t\tconst { x, y } =\n\t\t\t\tscaleX < 0 ? Vec.Sub(newPoint, Vec.FromAngle(shape.rotation).mul(nextWidth)) : newPoint\n\n\t\t\treturn {\n\t\t\t\tid: shape.id,\n\t\t\t\ttype: shape.type,\n\t\t\t\tx,\n\t\t\t\ty,\n\t\t\t\tprops: {\n\t\t\t\t\tw: nextWidth / initialShape.props.scale,\n\t\t\t\t\tautoSize: false,\n\t\t\t\t},\n\t\t\t}\n\t\t}\n\t}\n\n\toverride onEditEnd(shape: TLTextShape) {\n\t\t// todo: find a way to check if the rich text has any nodes that aren't empty spaces\n\t\tconst trimmedText = renderPlaintextFromRichText(this.editor, shape.props.richText).trimEnd()\n\n\t\tif (trimmedText.length === 0) {\n\t\t\tthis.editor.deleteShapes([shape.id])\n\t\t}\n\t}\n\n\toverride onBeforeUpdate(prev: TLTextShape, next: TLTextShape) {\n\t\tif (!next.props.autoSize) return\n\n\t\tconst styleDidChange =\n\t\t\tprev.props.size !== next.props.size ||\n\t\t\tprev.props.textAlign !== next.props.textAlign ||\n\t\t\tprev.props.font !== next.props.font ||\n\t\t\t(prev.props.scale !== 1 && next.props.scale === 1)\n\n\t\tconst textDidChange = !isEqual(prev.props.richText, next.props.richText)\n\n\t\t// Only update position if either changed\n\t\tif (!styleDidChange && !textDidChange) return\n\n\t\t// Might return a cached value for the bounds\n\t\tconst boundsA = this.getMinDimensions(prev)\n\n\t\t// Will always be a fresh call to getTextSize\n\t\tconst boundsB = getTextSize(this.editor, next.props)\n\n\t\tconst wA = boundsA.width * prev.props.scale\n\t\tconst hA = boundsA.height * prev.props.scale\n\t\tconst wB = boundsB.width * next.props.scale\n\t\tconst hB = boundsB.height * next.props.scale\n\n\t\tlet delta: Vec | undefined\n\n\t\tswitch (next.props.textAlign) {\n\t\t\tcase 'middle': {\n\t\t\t\tdelta = new Vec((wB - wA) / 2, textDidChange ? 0 : (hB - hA) / 2)\n\t\t\t\tbreak\n\t\t\t}\n\t\t\tcase 'end': {\n\t\t\t\tdelta = new Vec(wB - wA, textDidChange ? 0 : (hB - hA) / 2)\n\t\t\t\tbreak\n\t\t\t}\n\t\t\tdefault: {\n\t\t\t\tif (textDidChange) break\n\t\t\t\tdelta = new Vec(0, (hB - hA) / 2)\n\t\t\t\tbreak\n\t\t\t}\n\t\t}\n\n\t\tif (delta) {\n\t\t\t// account for shape rotation when writing text:\n\t\t\tdelta.rot(next.rotation)\n\t\t\tconst { x, y } = next\n\t\t\treturn {\n\t\t\t\t...next,\n\t\t\t\tx: x - delta.x,\n\t\t\t\ty: y - delta.y,\n\t\t\t\tprops: { ...next.props, w: wB },\n\t\t\t}\n\t\t} else {\n\t\t\treturn {\n\t\t\t\t...next,\n\t\t\t\tprops: { ...next.props, w: wB },\n\t\t\t}\n\t\t}\n\t}\n\n\t// \ttodo: The edge doubleclicking feels like a mistake more often than\n\t// not, especially on multiline text. Removed June 16 2024\n\n\t// override onDoubleClickEdge = (shape: TLTextShape) => {\n\t// \t// If the shape has a fixed width, set it to autoSize.\n\t// \tif (!shape.props.autoSize) {\n\t// \t\treturn {\n\t// \t\t\tid: shape.id,\n\t// \t\t\ttype: shape.type,\n\t// \t\t\tprops: {\n\t// \t\t\t\tautoSize: true,\n\t// \t\t\t},\n\t// \t\t}\n\t// \t}\n\t// \t// If the shape is scaled, reset the scale to 1.\n\t// \tif (shape.props.scale !== 1) {\n\t// \t\treturn {\n\t// \t\t\tid: shape.id,\n\t// \t\t\ttype: shape.type,\n\t// \t\t\tprops: {\n\t// \t\t\t\tscale: 1,\n\t// \t\t\t},\n\t// \t\t}\n\t// \t}\n\t// }\n}\n\nfunction getTextSize(editor: Editor, props: TLTextShape['props']) {\n\tconst { font, richText, size, w } = props\n\n\tconst minWidth = 16\n\tconst fontSize = FONT_SIZES[size]\n\n\tconst maybeFixedWidth = props.autoSize ? null : Math.max(minWidth, Math.floor(w))\n\n\tconst html = renderHtmlFromRichTextForMeasurement(editor, richText)\n\tconst result = editor.textMeasure.measureHtml(html, {\n\t\t...TEXT_PROPS,\n\t\tfontFamily: FONT_FAMILIES[font],\n\t\tfontSize: fontSize,\n\t\tmaxWidth: maybeFixedWidth,\n\t})\n\n\t// If we're autosizing the measureText will essentially `Math.floor`\n\t// the numbers so `19` rather than `19.3`, this means we must +1 to\n\t// whatever we get to avoid wrapping.\n\treturn {\n\t\twidth: maybeFixedWidth ?? Math.max(minWidth, result.w + 1),\n\t\theight: Math.max(fontSize, result.h),\n\t}\n}\n\nfunction useTextShapeKeydownHandler(id: TLShapeId) {\n\tconst editor = useEditor()\n\n\treturn useCallback(\n\t\t(e: KeyboardEvent) => {\n\t\t\tif (editor.getEditingShapeId() !== id) return\n\n\t\t\tswitch (e.key) {\n\t\t\t\tcase 'Enter': {\n\t\t\t\t\tif (e.ctrlKey || e.metaKey) {\n\t\t\t\t\t\teditor.complete()\n\t\t\t\t\t}\n\t\t\t\t\tbreak\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\t\t[editor, id]\n\t)\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -129,9 +129,9 @@ const VideoShape = (0, import_react.memo)(function VideoShape2({ shape }) {
|
|
|
129
129
|
{
|
|
130
130
|
id: shape.id,
|
|
131
131
|
style: {
|
|
132
|
-
color: "var(--color-text-3)",
|
|
133
|
-
backgroundColor: asset ? "transparent" : "var(--color-low)",
|
|
134
|
-
border: asset ? "none" : "1px solid var(--color-low-border)"
|
|
132
|
+
color: "var(--tl-color-text-3)",
|
|
133
|
+
backgroundColor: asset ? "transparent" : "var(--tl-color-low)",
|
|
134
|
+
border: asset ? "none" : "1px solid var(--tl-color-low-border)"
|
|
135
135
|
},
|
|
136
136
|
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "tl-counter-scaled", children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "tl-video-container", children: !asset ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_BrokenAssetIcon.BrokenAssetIcon, {}) : Spinner && !asset.props.src ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Spinner, {}) : url ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
|
|
137
137
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../../src/lib/shapes/video/VideoShapeUtil.tsx"],
|
|
4
|
-
"sourcesContent": ["import {\n\tBaseBoxShapeUtil,\n\tHTMLContainer,\n\tMediaHelpers,\n\tSvgExportContext,\n\tTLAsset,\n\tTLVideoShape,\n\tWeakCache,\n\ttoDomPrecision,\n\tuseEditor,\n\tuseEditorComponents,\n\tuseIsEditing,\n\tvideoShapeMigrations,\n\tvideoShapeProps,\n} from '@tldraw/editor'\nimport classNames from 'classnames'\nimport { ReactEventHandler, memo, useCallback, useEffect, useRef, useState } from 'react'\nimport { BrokenAssetIcon } from '../shared/BrokenAssetIcon'\nimport { HyperlinkButton } from '../shared/HyperlinkButton'\nimport { useImageOrVideoAsset } from '../shared/useImageOrVideoAsset'\nimport { usePrefersReducedMotion } from '../shared/usePrefersReducedMotion'\n\nconst videoSvgExportCache = new WeakCache<TLAsset, Promise<string | null>>()\n\n/** @public */\nexport interface VideoShapeOptions {\n\t/**\n\t * Should videos play automatically?\n\t */\n\tautoplay: boolean\n}\n\n/** @public */\nexport class VideoShapeUtil extends BaseBoxShapeUtil<TLVideoShape> {\n\tstatic override type = 'video' as const\n\tstatic override props = videoShapeProps\n\tstatic override migrations = videoShapeMigrations\n\n\toverride options: VideoShapeOptions = {\n\t\tautoplay: true,\n\t}\n\n\toverride canEdit() {\n\t\treturn true\n\t}\n\toverride isAspectRatioLocked() {\n\t\treturn true\n\t}\n\n\toverride getDefaultProps(): TLVideoShape['props'] {\n\t\treturn {\n\t\t\tw: 100,\n\t\t\th: 100,\n\t\t\tassetId: null,\n\t\t\tautoplay: this.options.autoplay,\n\t\t\turl: '',\n\t\t\taltText: '',\n\t\t\t// Not used, but once upon a time were used to sync video state between users\n\t\t\ttime: 0,\n\t\t\tplaying: true,\n\t\t}\n\t}\n\n\toverride getAriaDescriptor(shape: TLVideoShape) {\n\t\treturn shape.props.altText\n\t}\n\n\tcomponent(shape: TLVideoShape) {\n\t\treturn <VideoShape shape={shape} />\n\t}\n\n\tindicator(shape: TLVideoShape) {\n\t\treturn <rect width={toDomPrecision(shape.props.w)} height={toDomPrecision(shape.props.h)} />\n\t}\n\n\toverride async toSvg(shape: TLVideoShape, ctx: SvgExportContext) {\n\t\tconst props = shape.props\n\t\tif (!props.assetId) return null\n\n\t\tconst asset = this.editor.getAsset<TLAsset>(props.assetId)\n\t\tif (!asset) return null\n\n\t\tconst src = await videoSvgExportCache.get(asset, async () => {\n\t\t\tconst assetUrl = await ctx.resolveAssetUrl(asset.id, props.w)\n\t\t\tif (!assetUrl) return null\n\t\t\tconst video = await MediaHelpers.loadVideo(assetUrl)\n\t\t\treturn await MediaHelpers.getVideoFrameAsDataUrl(video, 0)\n\t\t})\n\n\t\tif (!src) return null\n\n\t\treturn <image href={src} width={props.w} height={props.h} aria-label={shape.props.altText} />\n\t}\n}\n\nconst VideoShape = memo(function VideoShape({ shape }: { shape: TLVideoShape }) {\n\tconst editor = useEditor()\n\tconst showControls = editor.getShapeGeometry(shape).bounds.w * editor.getZoomLevel() >= 110\n\tconst isEditing = useIsEditing(shape.id)\n\tconst prefersReducedMotion = usePrefersReducedMotion()\n\tconst { Spinner } = useEditorComponents()\n\n\tconst { asset, url } = useImageOrVideoAsset({\n\t\tshapeId: shape.id,\n\t\tassetId: shape.props.assetId,\n\t\twidth: shape.props.w,\n\t})\n\n\tconst rVideo = useRef<HTMLVideoElement>(null!)\n\n\tconst [isLoaded, setIsLoaded] = useState(false)\n\n\tconst handleLoadedData = useCallback<ReactEventHandler<HTMLVideoElement>>((e) => {\n\t\tconst video = e.currentTarget\n\t\tif (!video) return\n\t\tsetIsLoaded(true)\n\t}, [])\n\n\tconst [isFullscreen, setIsFullscreen] = useState(false)\n\n\tuseEffect(() => {\n\t\tconst fullscreenChange = () => setIsFullscreen(document.fullscreenElement === rVideo.current)\n\t\tdocument.addEventListener('fullscreenchange', fullscreenChange)\n\n\t\treturn () => document.removeEventListener('fullscreenchange', fullscreenChange)\n\t})\n\n\t// Focus the video when editing\n\tuseEffect(() => {\n\t\tconst video = rVideo.current\n\t\tif (!video) return\n\n\t\tif (isEditing) {\n\t\t\tif (document.activeElement !== video) {\n\t\t\t\tvideo.focus()\n\t\t\t}\n\t\t}\n\t}, [isEditing, isLoaded])\n\n\treturn (\n\t\t<>\n\t\t\t<HTMLContainer\n\t\t\t\tid={shape.id}\n\t\t\t\tstyle={{\n\t\t\t\t\tcolor: 'var(--color-text-3)',\n\t\t\t\t\tbackgroundColor: asset ? 'transparent' : 'var(--color-low)',\n\t\t\t\t\tborder: asset ? 'none' : '1px solid var(--color-low-border)',\n\t\t\t\t}}\n\t\t\t>\n\t\t\t\t<div className=\"tl-counter-scaled\">\n\t\t\t\t\t<div className=\"tl-video-container\">\n\t\t\t\t\t\t{!asset ? (\n\t\t\t\t\t\t\t<BrokenAssetIcon />\n\t\t\t\t\t\t) : Spinner && !asset.props.src ? (\n\t\t\t\t\t\t\t<Spinner />\n\t\t\t\t\t\t) : url ? (\n\t\t\t\t\t\t\t<>\n\t\t\t\t\t\t\t\t<video\n\t\t\t\t\t\t\t\t\tkey={url}\n\t\t\t\t\t\t\t\t\tref={rVideo}\n\t\t\t\t\t\t\t\t\tstyle={\n\t\t\t\t\t\t\t\t\t\tisEditing\n\t\t\t\t\t\t\t\t\t\t\t? { pointerEvents: 'all' }\n\t\t\t\t\t\t\t\t\t\t\t: !isLoaded\n\t\t\t\t\t\t\t\t\t\t\t\t? { display: 'none' }\n\t\t\t\t\t\t\t\t\t\t\t\t: undefined\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\tclassName={classNames('tl-video', `tl-video-shape-${shape.id.split(':')[1]}`, {\n\t\t\t\t\t\t\t\t\t\t'tl-video-is-fullscreen': isFullscreen,\n\t\t\t\t\t\t\t\t\t})}\n\t\t\t\t\t\t\t\t\twidth=\"100%\"\n\t\t\t\t\t\t\t\t\theight=\"100%\"\n\t\t\t\t\t\t\t\t\tdraggable={false}\n\t\t\t\t\t\t\t\t\tplaysInline\n\t\t\t\t\t\t\t\t\tautoPlay={shape.props.autoplay && !prefersReducedMotion}\n\t\t\t\t\t\t\t\t\tmuted\n\t\t\t\t\t\t\t\t\tloop\n\t\t\t\t\t\t\t\t\tdisableRemotePlayback\n\t\t\t\t\t\t\t\t\tdisablePictureInPicture\n\t\t\t\t\t\t\t\t\tcontrols={isEditing && showControls}\n\t\t\t\t\t\t\t\t\tonLoadedData={handleLoadedData}\n\t\t\t\t\t\t\t\t\thidden={!isLoaded}\n\t\t\t\t\t\t\t\t\taria-label={shape.props.altText}\n\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t<source src={url} />\n\t\t\t\t\t\t\t\t</video>\n\t\t\t\t\t\t\t\t{!isLoaded && Spinner && <Spinner />}\n\t\t\t\t\t\t\t</>\n\t\t\t\t\t\t) : null}\n\t\t\t\t\t</div>\n\t\t\t\t</div>\n\t\t\t</HTMLContainer>\n\t\t\t{'url' in shape.props && shape.props.url && <HyperlinkButton url={shape.props.url} />}\n\t\t</>\n\t)\n})\n"],
|
|
4
|
+
"sourcesContent": ["import {\n\tBaseBoxShapeUtil,\n\tHTMLContainer,\n\tMediaHelpers,\n\tSvgExportContext,\n\tTLAsset,\n\tTLVideoShape,\n\tWeakCache,\n\ttoDomPrecision,\n\tuseEditor,\n\tuseEditorComponents,\n\tuseIsEditing,\n\tvideoShapeMigrations,\n\tvideoShapeProps,\n} from '@tldraw/editor'\nimport classNames from 'classnames'\nimport { ReactEventHandler, memo, useCallback, useEffect, useRef, useState } from 'react'\nimport { BrokenAssetIcon } from '../shared/BrokenAssetIcon'\nimport { HyperlinkButton } from '../shared/HyperlinkButton'\nimport { useImageOrVideoAsset } from '../shared/useImageOrVideoAsset'\nimport { usePrefersReducedMotion } from '../shared/usePrefersReducedMotion'\n\nconst videoSvgExportCache = new WeakCache<TLAsset, Promise<string | null>>()\n\n/** @public */\nexport interface VideoShapeOptions {\n\t/**\n\t * Should videos play automatically?\n\t */\n\tautoplay: boolean\n}\n\n/** @public */\nexport class VideoShapeUtil extends BaseBoxShapeUtil<TLVideoShape> {\n\tstatic override type = 'video' as const\n\tstatic override props = videoShapeProps\n\tstatic override migrations = videoShapeMigrations\n\n\toverride options: VideoShapeOptions = {\n\t\tautoplay: true,\n\t}\n\n\toverride canEdit() {\n\t\treturn true\n\t}\n\toverride isAspectRatioLocked() {\n\t\treturn true\n\t}\n\n\toverride getDefaultProps(): TLVideoShape['props'] {\n\t\treturn {\n\t\t\tw: 100,\n\t\t\th: 100,\n\t\t\tassetId: null,\n\t\t\tautoplay: this.options.autoplay,\n\t\t\turl: '',\n\t\t\taltText: '',\n\t\t\t// Not used, but once upon a time were used to sync video state between users\n\t\t\ttime: 0,\n\t\t\tplaying: true,\n\t\t}\n\t}\n\n\toverride getAriaDescriptor(shape: TLVideoShape) {\n\t\treturn shape.props.altText\n\t}\n\n\tcomponent(shape: TLVideoShape) {\n\t\treturn <VideoShape shape={shape} />\n\t}\n\n\tindicator(shape: TLVideoShape) {\n\t\treturn <rect width={toDomPrecision(shape.props.w)} height={toDomPrecision(shape.props.h)} />\n\t}\n\n\toverride async toSvg(shape: TLVideoShape, ctx: SvgExportContext) {\n\t\tconst props = shape.props\n\t\tif (!props.assetId) return null\n\n\t\tconst asset = this.editor.getAsset<TLAsset>(props.assetId)\n\t\tif (!asset) return null\n\n\t\tconst src = await videoSvgExportCache.get(asset, async () => {\n\t\t\tconst assetUrl = await ctx.resolveAssetUrl(asset.id, props.w)\n\t\t\tif (!assetUrl) return null\n\t\t\tconst video = await MediaHelpers.loadVideo(assetUrl)\n\t\t\treturn await MediaHelpers.getVideoFrameAsDataUrl(video, 0)\n\t\t})\n\n\t\tif (!src) return null\n\n\t\treturn <image href={src} width={props.w} height={props.h} aria-label={shape.props.altText} />\n\t}\n}\n\nconst VideoShape = memo(function VideoShape({ shape }: { shape: TLVideoShape }) {\n\tconst editor = useEditor()\n\tconst showControls = editor.getShapeGeometry(shape).bounds.w * editor.getZoomLevel() >= 110\n\tconst isEditing = useIsEditing(shape.id)\n\tconst prefersReducedMotion = usePrefersReducedMotion()\n\tconst { Spinner } = useEditorComponents()\n\n\tconst { asset, url } = useImageOrVideoAsset({\n\t\tshapeId: shape.id,\n\t\tassetId: shape.props.assetId,\n\t\twidth: shape.props.w,\n\t})\n\n\tconst rVideo = useRef<HTMLVideoElement>(null!)\n\n\tconst [isLoaded, setIsLoaded] = useState(false)\n\n\tconst handleLoadedData = useCallback<ReactEventHandler<HTMLVideoElement>>((e) => {\n\t\tconst video = e.currentTarget\n\t\tif (!video) return\n\t\tsetIsLoaded(true)\n\t}, [])\n\n\tconst [isFullscreen, setIsFullscreen] = useState(false)\n\n\tuseEffect(() => {\n\t\tconst fullscreenChange = () => setIsFullscreen(document.fullscreenElement === rVideo.current)\n\t\tdocument.addEventListener('fullscreenchange', fullscreenChange)\n\n\t\treturn () => document.removeEventListener('fullscreenchange', fullscreenChange)\n\t})\n\n\t// Focus the video when editing\n\tuseEffect(() => {\n\t\tconst video = rVideo.current\n\t\tif (!video) return\n\n\t\tif (isEditing) {\n\t\t\tif (document.activeElement !== video) {\n\t\t\t\tvideo.focus()\n\t\t\t}\n\t\t}\n\t}, [isEditing, isLoaded])\n\n\treturn (\n\t\t<>\n\t\t\t<HTMLContainer\n\t\t\t\tid={shape.id}\n\t\t\t\tstyle={{\n\t\t\t\t\tcolor: 'var(--tl-color-text-3)',\n\t\t\t\t\tbackgroundColor: asset ? 'transparent' : 'var(--tl-color-low)',\n\t\t\t\t\tborder: asset ? 'none' : '1px solid var(--tl-color-low-border)',\n\t\t\t\t}}\n\t\t\t>\n\t\t\t\t<div className=\"tl-counter-scaled\">\n\t\t\t\t\t<div className=\"tl-video-container\">\n\t\t\t\t\t\t{!asset ? (\n\t\t\t\t\t\t\t<BrokenAssetIcon />\n\t\t\t\t\t\t) : Spinner && !asset.props.src ? (\n\t\t\t\t\t\t\t<Spinner />\n\t\t\t\t\t\t) : url ? (\n\t\t\t\t\t\t\t<>\n\t\t\t\t\t\t\t\t<video\n\t\t\t\t\t\t\t\t\tkey={url}\n\t\t\t\t\t\t\t\t\tref={rVideo}\n\t\t\t\t\t\t\t\t\tstyle={\n\t\t\t\t\t\t\t\t\t\tisEditing\n\t\t\t\t\t\t\t\t\t\t\t? { pointerEvents: 'all' }\n\t\t\t\t\t\t\t\t\t\t\t: !isLoaded\n\t\t\t\t\t\t\t\t\t\t\t\t? { display: 'none' }\n\t\t\t\t\t\t\t\t\t\t\t\t: undefined\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\tclassName={classNames('tl-video', `tl-video-shape-${shape.id.split(':')[1]}`, {\n\t\t\t\t\t\t\t\t\t\t'tl-video-is-fullscreen': isFullscreen,\n\t\t\t\t\t\t\t\t\t})}\n\t\t\t\t\t\t\t\t\twidth=\"100%\"\n\t\t\t\t\t\t\t\t\theight=\"100%\"\n\t\t\t\t\t\t\t\t\tdraggable={false}\n\t\t\t\t\t\t\t\t\tplaysInline\n\t\t\t\t\t\t\t\t\tautoPlay={shape.props.autoplay && !prefersReducedMotion}\n\t\t\t\t\t\t\t\t\tmuted\n\t\t\t\t\t\t\t\t\tloop\n\t\t\t\t\t\t\t\t\tdisableRemotePlayback\n\t\t\t\t\t\t\t\t\tdisablePictureInPicture\n\t\t\t\t\t\t\t\t\tcontrols={isEditing && showControls}\n\t\t\t\t\t\t\t\t\tonLoadedData={handleLoadedData}\n\t\t\t\t\t\t\t\t\thidden={!isLoaded}\n\t\t\t\t\t\t\t\t\taria-label={shape.props.altText}\n\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t<source src={url} />\n\t\t\t\t\t\t\t\t</video>\n\t\t\t\t\t\t\t\t{!isLoaded && Spinner && <Spinner />}\n\t\t\t\t\t\t\t</>\n\t\t\t\t\t\t) : null}\n\t\t\t\t\t</div>\n\t\t\t\t</div>\n\t\t\t</HTMLContainer>\n\t\t\t{'url' in shape.props && shape.props.url && <HyperlinkButton url={shape.props.url} />}\n\t\t</>\n\t)\n})\n"],
|
|
5
5
|
"mappings": "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",
|
|
6
6
|
"names": ["VideoShape", "classNames"]
|
|
7
7
|
}
|
|
@@ -28,7 +28,13 @@ class Erasing extends import_editor.StateNode {
|
|
|
28
28
|
scribbleId = "id";
|
|
29
29
|
markId = "";
|
|
30
30
|
excludedShapeIds = /* @__PURE__ */ new Set();
|
|
31
|
+
_isHoldingAccelKey = false;
|
|
32
|
+
_firstErasingShapeId = null;
|
|
33
|
+
_erasingShapeIds = [];
|
|
31
34
|
onEnter(info) {
|
|
35
|
+
this._isHoldingAccelKey = (0, import_editor.isAccelKey)(this.editor.inputs);
|
|
36
|
+
this._firstErasingShapeId = this.editor.getErasingShapeIds()[0];
|
|
37
|
+
this._erasingShapeIds = this.editor.getErasingShapeIds();
|
|
32
38
|
this.markId = this.editor.markHistoryStoppingPoint("erase scribble begin");
|
|
33
39
|
this.info = info;
|
|
34
40
|
const { originPagePoint } = this.editor.inputs;
|
|
@@ -70,6 +76,14 @@ class Erasing extends import_editor.StateNode {
|
|
|
70
76
|
onComplete() {
|
|
71
77
|
this.complete();
|
|
72
78
|
}
|
|
79
|
+
onKeyUp() {
|
|
80
|
+
this._isHoldingAccelKey = (0, import_editor.isAccelKey)(this.editor.inputs);
|
|
81
|
+
this.update();
|
|
82
|
+
}
|
|
83
|
+
onKeyDown() {
|
|
84
|
+
this._isHoldingAccelKey = (0, import_editor.isAccelKey)(this.editor.inputs);
|
|
85
|
+
this.update();
|
|
86
|
+
}
|
|
73
87
|
update() {
|
|
74
88
|
const { editor, excludedShapeIds } = this;
|
|
75
89
|
const erasingShapeIds = editor.getErasingShapeIds();
|
|
@@ -100,13 +114,23 @@ class Erasing extends import_editor.StateNode {
|
|
|
100
114
|
if (geometry.hitTestLineSegment(A, B, minDist)) {
|
|
101
115
|
erasing.add(editor.getOutermostSelectableShape(shape).id);
|
|
102
116
|
}
|
|
117
|
+
this._erasingShapeIds = [...erasing];
|
|
118
|
+
}
|
|
119
|
+
if (this._isHoldingAccelKey && this._firstErasingShapeId) {
|
|
120
|
+
const erasingShapeId = this._firstErasingShapeId;
|
|
121
|
+
if (erasingShapeId && this.editor.getShape(erasingShapeId)) {
|
|
122
|
+
editor.setErasingShapes([erasingShapeId]);
|
|
123
|
+
}
|
|
124
|
+
return;
|
|
103
125
|
}
|
|
104
|
-
this.editor.setErasingShapes(
|
|
126
|
+
this.editor.setErasingShapes(this._erasingShapeIds.filter((id) => !excludedShapeIds.has(id)));
|
|
105
127
|
}
|
|
106
128
|
complete() {
|
|
107
129
|
const { editor } = this;
|
|
108
130
|
editor.deleteShapes(editor.getCurrentPageState().erasingShapeIds);
|
|
109
131
|
this.parent.transition("idle");
|
|
132
|
+
this._erasingShapeIds = [];
|
|
133
|
+
this._firstErasingShapeId = null;
|
|
110
134
|
}
|
|
111
135
|
cancel() {
|
|
112
136
|
const { editor } = this;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../../../src/lib/tools/EraserTool/childStates/Erasing.ts"],
|
|
4
|
-
"sourcesContent": ["import {\n\tStateNode,\n\tTLFrameShape,\n\tTLGroupShape,\n\tTLPointerEventInfo,\n\tTLShapeId,\n\tpointInPolygon,\n} from '@tldraw/editor'\n\nexport class Erasing extends StateNode {\n\tstatic override id = 'erasing'\n\n\tprivate info = {} as TLPointerEventInfo\n\tprivate scribbleId = 'id'\n\tprivate markId = ''\n\tprivate excludedShapeIds = new Set<TLShapeId>()\n\n\toverride onEnter(info: TLPointerEventInfo) {\n\t\tthis.markId = this.editor.markHistoryStoppingPoint('erase scribble begin')\n\t\tthis.info = info\n\n\t\tconst { originPagePoint } = this.editor.inputs\n\t\tthis.excludedShapeIds = new Set(\n\t\t\tthis.editor\n\t\t\t\t.getCurrentPageShapes()\n\t\t\t\t.filter((shape) => {\n\t\t\t\t\t//If the shape is locked, we shouldn't erase it\n\t\t\t\t\tif (this.editor.isShapeOrAncestorLocked(shape)) return true\n\t\t\t\t\t//If the shape is a group or frame, check we're inside it when we start erasing\n\t\t\t\t\tif (\n\t\t\t\t\t\tthis.editor.isShapeOfType<TLGroupShape>(shape, 'group') ||\n\t\t\t\t\t\tthis.editor.isShapeOfType<TLFrameShape>(shape, 'frame')\n\t\t\t\t\t) {\n\t\t\t\t\t\tconst pointInShapeShape = this.editor.getPointInShapeSpace(shape, originPagePoint)\n\t\t\t\t\t\tconst geometry = this.editor.getShapeGeometry(shape)\n\t\t\t\t\t\treturn geometry.bounds.containsPoint(pointInShapeShape)\n\t\t\t\t\t}\n\n\t\t\t\t\treturn false\n\t\t\t\t})\n\t\t\t\t.map((shape) => shape.id)\n\t\t)\n\n\t\tconst scribble = this.editor.scribbles.addScribble({\n\t\t\tcolor: 'muted-1',\n\t\t\tsize: 12,\n\t\t})\n\t\tthis.scribbleId = scribble.id\n\n\t\tthis.update()\n\t}\n\n\tprivate pushPointToScribble() {\n\t\tconst { x, y } = this.editor.inputs.currentPagePoint\n\t\tthis.editor.scribbles.addPoint(this.scribbleId, x, y)\n\t}\n\n\toverride onExit() {\n\t\tthis.editor.setErasingShapes([])\n\t\tthis.editor.scribbles.stop(this.scribbleId)\n\t}\n\n\toverride onPointerMove() {\n\t\tthis.update()\n\t}\n\n\toverride onPointerUp() {\n\t\tthis.complete()\n\t}\n\n\toverride onCancel() {\n\t\tthis.cancel()\n\t}\n\n\toverride onComplete() {\n\t\tthis.complete()\n\t}\n\n\tupdate() {\n\t\tconst { editor, excludedShapeIds } = this\n\t\tconst erasingShapeIds = editor.getErasingShapeIds()\n\t\tconst zoomLevel = editor.getZoomLevel()\n\t\tconst currentPageShapes = editor.getCurrentPageRenderingShapesSorted()\n\t\tconst {\n\t\t\tinputs: { currentPagePoint, previousPagePoint },\n\t\t} = editor\n\n\t\tthis.pushPointToScribble()\n\n\t\tconst erasing = new Set<TLShapeId>(erasingShapeIds)\n\t\tconst minDist = this.editor.options.hitTestMargin / zoomLevel\n\n\t\tfor (const shape of currentPageShapes) {\n\t\t\tif (editor.isShapeOfType<TLGroupShape>(shape, 'group')) continue\n\n\t\t\t// Avoid testing masked shapes, unless the pointer is inside the mask\n\t\t\tconst pageMask = editor.getShapeMask(shape.id)\n\t\t\tif (pageMask && !pointInPolygon(currentPagePoint, pageMask)) {\n\t\t\t\tcontinue\n\t\t\t}\n\n\t\t\t// Hit test the shape using a line segment\n\t\t\tconst geometry = editor.getShapeGeometry(shape)\n\t\t\tconst pageTransform = editor.getShapePageTransform(shape)\n\t\t\tif (!geometry || !pageTransform) continue\n\t\t\tconst pt = pageTransform.clone().invert()\n\t\t\tconst A = pt.applyToPoint(previousPagePoint)\n\t\t\tconst B = pt.applyToPoint(currentPagePoint)\n\n\t\t\t// If the line segment is entirely above / below / left / right of the shape's bounding box, skip the hit test\n\t\t\tconst { bounds } = geometry\n\t\t\tif (\n\t\t\t\tbounds.minX - minDist > Math.max(A.x, B.x) ||\n\t\t\t\tbounds.minY - minDist > Math.max(A.y, B.y) ||\n\t\t\t\tbounds.maxX + minDist < Math.min(A.x, B.x) ||\n\t\t\t\tbounds.maxY + minDist < Math.min(A.y, B.y)\n\t\t\t) {\n\t\t\t\tcontinue\n\t\t\t}\n\n\t\t\tif (geometry.hitTestLineSegment(A, B, minDist)) {\n\t\t\t\terasing.add(editor.getOutermostSelectableShape(shape).id)\n\t\t\t}\n\t\t}\n\n\t\t// Remove the hit shapes, except if they're in the list of excluded shapes\n\t\t// (these excluded shapes will be any frames or groups the pointer was inside of\n\t\t// when the user started erasing)\n\t\tthis.editor.setErasingShapes(
|
|
5
|
-
"mappings": ";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,
|
|
4
|
+
"sourcesContent": ["import {\n\tStateNode,\n\tTLFrameShape,\n\tTLGroupShape,\n\tTLPointerEventInfo,\n\tTLShapeId,\n\tisAccelKey,\n\tpointInPolygon,\n} from '@tldraw/editor'\n\nexport class Erasing extends StateNode {\n\tstatic override id = 'erasing'\n\n\tprivate info = {} as TLPointerEventInfo\n\tprivate scribbleId = 'id'\n\tprivate markId = ''\n\tprivate excludedShapeIds = new Set<TLShapeId>()\n\n\t_isHoldingAccelKey = false\n\t_firstErasingShapeId: TLShapeId | null = null\n\t_erasingShapeIds: TLShapeId[] = []\n\n\toverride onEnter(info: TLPointerEventInfo) {\n\t\tthis._isHoldingAccelKey = isAccelKey(this.editor.inputs)\n\t\tthis._firstErasingShapeId = this.editor.getErasingShapeIds()[0] // the first one should be the first one we hit... is it?\n\t\tthis._erasingShapeIds = this.editor.getErasingShapeIds()\n\n\t\tthis.markId = this.editor.markHistoryStoppingPoint('erase scribble begin')\n\t\tthis.info = info\n\n\t\tconst { originPagePoint } = this.editor.inputs\n\t\tthis.excludedShapeIds = new Set(\n\t\t\tthis.editor\n\t\t\t\t.getCurrentPageShapes()\n\t\t\t\t.filter((shape) => {\n\t\t\t\t\t//If the shape is locked, we shouldn't erase it\n\t\t\t\t\tif (this.editor.isShapeOrAncestorLocked(shape)) return true\n\t\t\t\t\t//If the shape is a group or frame, check we're inside it when we start erasing\n\t\t\t\t\tif (\n\t\t\t\t\t\tthis.editor.isShapeOfType<TLGroupShape>(shape, 'group') ||\n\t\t\t\t\t\tthis.editor.isShapeOfType<TLFrameShape>(shape, 'frame')\n\t\t\t\t\t) {\n\t\t\t\t\t\tconst pointInShapeShape = this.editor.getPointInShapeSpace(shape, originPagePoint)\n\t\t\t\t\t\tconst geometry = this.editor.getShapeGeometry(shape)\n\t\t\t\t\t\treturn geometry.bounds.containsPoint(pointInShapeShape)\n\t\t\t\t\t}\n\n\t\t\t\t\treturn false\n\t\t\t\t})\n\t\t\t\t.map((shape) => shape.id)\n\t\t)\n\n\t\tconst scribble = this.editor.scribbles.addScribble({\n\t\t\tcolor: 'muted-1',\n\t\t\tsize: 12,\n\t\t})\n\t\tthis.scribbleId = scribble.id\n\n\t\tthis.update()\n\t}\n\n\tprivate pushPointToScribble() {\n\t\tconst { x, y } = this.editor.inputs.currentPagePoint\n\t\tthis.editor.scribbles.addPoint(this.scribbleId, x, y)\n\t}\n\n\toverride onExit() {\n\t\tthis.editor.setErasingShapes([])\n\t\tthis.editor.scribbles.stop(this.scribbleId)\n\t}\n\n\toverride onPointerMove() {\n\t\tthis.update()\n\t}\n\n\toverride onPointerUp() {\n\t\tthis.complete()\n\t}\n\n\toverride onCancel() {\n\t\tthis.cancel()\n\t}\n\n\toverride onComplete() {\n\t\tthis.complete()\n\t}\n\n\toverride onKeyUp() {\n\t\tthis._isHoldingAccelKey = isAccelKey(this.editor.inputs)\n\t\tthis.update()\n\t}\n\n\toverride onKeyDown() {\n\t\tthis._isHoldingAccelKey = isAccelKey(this.editor.inputs)\n\t\tthis.update()\n\t}\n\n\tupdate() {\n\t\tconst { editor, excludedShapeIds } = this\n\t\tconst erasingShapeIds = editor.getErasingShapeIds()\n\t\tconst zoomLevel = editor.getZoomLevel()\n\t\tconst currentPageShapes = editor.getCurrentPageRenderingShapesSorted()\n\t\tconst {\n\t\t\tinputs: { currentPagePoint, previousPagePoint },\n\t\t} = editor\n\n\t\tthis.pushPointToScribble()\n\n\t\t// Otherwise, erasing shapes are all the shapes that were hit before plus any new shapes that are hit\n\t\tconst erasing = new Set<TLShapeId>(erasingShapeIds)\n\t\tconst minDist = this.editor.options.hitTestMargin / zoomLevel\n\n\t\tfor (const shape of currentPageShapes) {\n\t\t\tif (editor.isShapeOfType<TLGroupShape>(shape, 'group')) continue\n\n\t\t\t// Avoid testing masked shapes, unless the pointer is inside the mask\n\t\t\tconst pageMask = editor.getShapeMask(shape.id)\n\t\t\tif (pageMask && !pointInPolygon(currentPagePoint, pageMask)) {\n\t\t\t\tcontinue\n\t\t\t}\n\n\t\t\t// Hit test the shape using a line segment\n\t\t\tconst geometry = editor.getShapeGeometry(shape)\n\t\t\tconst pageTransform = editor.getShapePageTransform(shape)\n\t\t\tif (!geometry || !pageTransform) continue\n\t\t\tconst pt = pageTransform.clone().invert()\n\t\t\tconst A = pt.applyToPoint(previousPagePoint)\n\t\t\tconst B = pt.applyToPoint(currentPagePoint)\n\n\t\t\t// If the line segment is entirely above / below / left / right of the shape's bounding box, skip the hit test\n\t\t\tconst { bounds } = geometry\n\t\t\tif (\n\t\t\t\tbounds.minX - minDist > Math.max(A.x, B.x) ||\n\t\t\t\tbounds.minY - minDist > Math.max(A.y, B.y) ||\n\t\t\t\tbounds.maxX + minDist < Math.min(A.x, B.x) ||\n\t\t\t\tbounds.maxY + minDist < Math.min(A.y, B.y)\n\t\t\t) {\n\t\t\t\tcontinue\n\t\t\t}\n\n\t\t\tif (geometry.hitTestLineSegment(A, B, minDist)) {\n\t\t\t\terasing.add(editor.getOutermostSelectableShape(shape).id)\n\t\t\t}\n\n\t\t\tthis._erasingShapeIds = [...erasing]\n\t\t}\n\n\t\t// If the user is holding the meta / ctrl key, we should only erase the first shape we hit\n\t\tif (this._isHoldingAccelKey && this._firstErasingShapeId) {\n\t\t\tconst erasingShapeId = this._firstErasingShapeId\n\t\t\tif (erasingShapeId && this.editor.getShape(erasingShapeId)) {\n\t\t\t\teditor.setErasingShapes([erasingShapeId])\n\t\t\t}\n\t\t\treturn\n\t\t}\n\n\t\t// Remove the hit shapes, except if they're in the list of excluded shapes\n\t\t// (these excluded shapes will be any frames or groups the pointer was inside of\n\t\t// when the user started erasing)\n\t\tthis.editor.setErasingShapes(this._erasingShapeIds.filter((id) => !excludedShapeIds.has(id)))\n\t}\n\n\tcomplete() {\n\t\tconst { editor } = this\n\t\teditor.deleteShapes(editor.getCurrentPageState().erasingShapeIds)\n\t\tthis.parent.transition('idle')\n\t\tthis._erasingShapeIds = []\n\t\tthis._firstErasingShapeId = null\n\t}\n\n\tcancel() {\n\t\tconst { editor } = this\n\t\teditor.bailToMark(this.markId)\n\t\tthis.parent.transition('idle', this.info)\n\t}\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -24,7 +24,9 @@ module.exports = __toCommonJS(Pointing_exports);
|
|
|
24
24
|
var import_editor = require("@tldraw/editor");
|
|
25
25
|
class Pointing extends import_editor.StateNode {
|
|
26
26
|
static id = "pointing";
|
|
27
|
+
_isHoldingAccelKey = false;
|
|
27
28
|
onEnter() {
|
|
29
|
+
this._isHoldingAccelKey = (0, import_editor.isAccelKey)(this.editor.inputs);
|
|
28
30
|
const zoomLevel = this.editor.getZoomLevel();
|
|
29
31
|
const currentPageShapesSorted = this.editor.getCurrentPageRenderingShapesSorted();
|
|
30
32
|
const {
|
|
@@ -46,10 +48,19 @@ class Pointing extends import_editor.StateNode {
|
|
|
46
48
|
break;
|
|
47
49
|
}
|
|
48
50
|
erasing.add(hitShape.id);
|
|
51
|
+
if (this._isHoldingAccelKey) {
|
|
52
|
+
break;
|
|
53
|
+
}
|
|
49
54
|
}
|
|
50
55
|
}
|
|
51
56
|
this.editor.setErasingShapes([...erasing]);
|
|
52
57
|
}
|
|
58
|
+
onKeyUp() {
|
|
59
|
+
this._isHoldingAccelKey = (0, import_editor.isAccelKey)(this.editor.inputs);
|
|
60
|
+
}
|
|
61
|
+
onKeyDown() {
|
|
62
|
+
this._isHoldingAccelKey = (0, import_editor.isAccelKey)(this.editor.inputs);
|
|
63
|
+
}
|
|
53
64
|
onLongPress(info) {
|
|
54
65
|
this.startErasing(info);
|
|
55
66
|
}
|
|
@@ -59,6 +70,7 @@ class Pointing extends import_editor.StateNode {
|
|
|
59
70
|
}
|
|
60
71
|
}
|
|
61
72
|
onPointerMove(info) {
|
|
73
|
+
if (this._isHoldingAccelKey) return;
|
|
62
74
|
if (this.editor.inputs.isDragging) {
|
|
63
75
|
this.startErasing(info);
|
|
64
76
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../../../src/lib/tools/EraserTool/childStates/Pointing.ts"],
|
|
4
|
-
"sourcesContent": ["import {\n\tStateNode,\n\tTLFrameShape,\n\tTLGroupShape,\n\tTLPointerEventInfo,\n\tTLShapeId,\n} from '@tldraw/editor'\n\nexport class Pointing extends StateNode {\n\tstatic override id = 'pointing'\n\n\toverride onEnter() {\n\t\tconst zoomLevel = this.editor.getZoomLevel()\n\t\tconst currentPageShapesSorted = this.editor.getCurrentPageRenderingShapesSorted()\n\t\tconst {\n\t\t\tinputs: { currentPagePoint },\n\t\t} = this.editor\n\n\t\tconst erasing = new Set<TLShapeId>()\n\n\t\tconst initialSize = erasing.size\n\n\t\tfor (let n = currentPageShapesSorted.length, i = n - 1; i >= 0; i--) {\n\t\t\tconst shape = currentPageShapesSorted[i]\n\t\t\tif (\n\t\t\t\tthis.editor.isShapeOrAncestorLocked(shape) ||\n\t\t\t\tthis.editor.isShapeOfType<TLGroupShape>(shape, 'group')\n\t\t\t) {\n\t\t\t\tcontinue\n\t\t\t}\n\n\t\t\tif (\n\t\t\t\tthis.editor.isPointInShape(shape, currentPagePoint, {\n\t\t\t\t\thitInside: false,\n\t\t\t\t\tmargin: this.editor.options.hitTestMargin / zoomLevel,\n\t\t\t\t})\n\t\t\t) {\n\t\t\t\tconst hitShape = this.editor.getOutermostSelectableShape(shape)\n\t\t\t\t// If we've hit a frame after hitting any other shape, stop here\n\t\t\t\tif (\n\t\t\t\t\tthis.editor.isShapeOfType<TLFrameShape>(hitShape, 'frame') &&\n\t\t\t\t\terasing.size > initialSize\n\t\t\t\t) {\n\t\t\t\t\tbreak\n\t\t\t\t}\n\n\t\t\t\terasing.add(hitShape.id)\n\t\t\t}\n\t\t}\n\n\t\tthis.editor.setErasingShapes([...erasing])\n\t}\n\n\toverride onLongPress(info: TLPointerEventInfo) {\n\t\tthis.startErasing(info)\n\t}\n\n\toverride onExit(_info: any, to: string) {\n\t\tif (to !== 'erasing') {\n\t\t\tthis.editor.setErasingShapes([])\n\t\t}\n\t}\n\n\toverride onPointerMove(info: TLPointerEventInfo) {\n\t\tif (this.editor.inputs.isDragging) {\n\t\t\tthis.startErasing(info)\n\t\t}\n\t}\n\n\toverride onPointerUp() {\n\t\tthis.complete()\n\t}\n\n\toverride onCancel() {\n\t\tthis.cancel()\n\t}\n\n\toverride onComplete() {\n\t\tthis.complete()\n\t}\n\n\toverride onInterrupt() {\n\t\tthis.cancel()\n\t}\n\n\tprivate startErasing(info: TLPointerEventInfo) {\n\t\tthis.parent.transition('erasing', info)\n\t}\n\n\tcomplete() {\n\t\tconst erasingShapeIds = this.editor.getErasingShapeIds()\n\n\t\tif (erasingShapeIds.length) {\n\t\t\tthis.editor.markHistoryStoppingPoint('erase end')\n\t\t\tthis.editor.deleteShapes(erasingShapeIds)\n\t\t}\n\n\t\tthis.parent.transition('idle')\n\t}\n\n\tcancel() {\n\t\tthis.parent.transition('idle')\n\t}\n}\n"],
|
|
5
|
-
"mappings": ";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,
|
|
4
|
+
"sourcesContent": ["import {\n\tisAccelKey,\n\tStateNode,\n\tTLFrameShape,\n\tTLGroupShape,\n\tTLPointerEventInfo,\n\tTLShapeId,\n} from '@tldraw/editor'\n\nexport class Pointing extends StateNode {\n\tstatic override id = 'pointing'\n\n\t_isHoldingAccelKey = false\n\n\toverride onEnter() {\n\t\tthis._isHoldingAccelKey = isAccelKey(this.editor.inputs)\n\n\t\tconst zoomLevel = this.editor.getZoomLevel()\n\t\tconst currentPageShapesSorted = this.editor.getCurrentPageRenderingShapesSorted()\n\t\tconst {\n\t\t\tinputs: { currentPagePoint },\n\t\t} = this.editor\n\n\t\tconst erasing = new Set<TLShapeId>()\n\n\t\tconst initialSize = erasing.size\n\n\t\tfor (let n = currentPageShapesSorted.length, i = n - 1; i >= 0; i--) {\n\t\t\tconst shape = currentPageShapesSorted[i]\n\t\t\tif (\n\t\t\t\tthis.editor.isShapeOrAncestorLocked(shape) ||\n\t\t\t\tthis.editor.isShapeOfType<TLGroupShape>(shape, 'group')\n\t\t\t) {\n\t\t\t\tcontinue\n\t\t\t}\n\n\t\t\tif (\n\t\t\t\tthis.editor.isPointInShape(shape, currentPagePoint, {\n\t\t\t\t\thitInside: false,\n\t\t\t\t\tmargin: this.editor.options.hitTestMargin / zoomLevel,\n\t\t\t\t})\n\t\t\t) {\n\t\t\t\tconst hitShape = this.editor.getOutermostSelectableShape(shape)\n\t\t\t\t// If we've hit a frame after hitting any other shape, stop here\n\t\t\t\tif (\n\t\t\t\t\tthis.editor.isShapeOfType<TLFrameShape>(hitShape, 'frame') &&\n\t\t\t\t\terasing.size > initialSize\n\t\t\t\t) {\n\t\t\t\t\tbreak\n\t\t\t\t}\n\n\t\t\t\terasing.add(hitShape.id)\n\n\t\t\t\t// If the user is holding the meta / ctrl key, stop after the first shape\n\t\t\t\tif (this._isHoldingAccelKey) {\n\t\t\t\t\tbreak\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tthis.editor.setErasingShapes([...erasing])\n\t}\n\n\toverride onKeyUp() {\n\t\tthis._isHoldingAccelKey = isAccelKey(this.editor.inputs)\n\t}\n\n\toverride onKeyDown() {\n\t\tthis._isHoldingAccelKey = isAccelKey(this.editor.inputs)\n\t}\n\n\toverride onLongPress(info: TLPointerEventInfo) {\n\t\tthis.startErasing(info)\n\t}\n\n\toverride onExit(_info: any, to: string) {\n\t\tif (to !== 'erasing') {\n\t\t\tthis.editor.setErasingShapes([])\n\t\t}\n\t}\n\n\toverride onPointerMove(info: TLPointerEventInfo) {\n\t\tif (this._isHoldingAccelKey) return\n\n\t\tif (this.editor.inputs.isDragging) {\n\t\t\tthis.startErasing(info)\n\t\t}\n\t}\n\n\toverride onPointerUp() {\n\t\tthis.complete()\n\t}\n\n\toverride onCancel() {\n\t\tthis.cancel()\n\t}\n\n\toverride onComplete() {\n\t\tthis.complete()\n\t}\n\n\toverride onInterrupt() {\n\t\tthis.cancel()\n\t}\n\n\tprivate startErasing(info: TLPointerEventInfo) {\n\t\tthis.parent.transition('erasing', info)\n\t}\n\n\tcomplete() {\n\t\tconst erasingShapeIds = this.editor.getErasingShapeIds()\n\n\t\tif (erasingShapeIds.length) {\n\t\t\tthis.editor.markHistoryStoppingPoint('erase end')\n\t\t\tthis.editor.deleteShapes(erasingShapeIds)\n\t\t}\n\n\t\tthis.parent.transition('idle')\n\t}\n\n\tcancel() {\n\t\tthis.parent.transition('idle')\n\t}\n}\n"],
|
|
5
|
+
"mappings": ";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,oBAOO;AAEA,MAAM,iBAAiB,wBAAU;AAAA,EACvC,OAAgB,KAAK;AAAA,EAErB,qBAAqB;AAAA,EAEZ,UAAU;AAClB,SAAK,yBAAqB,0BAAW,KAAK,OAAO,MAAM;AAEvD,UAAM,YAAY,KAAK,OAAO,aAAa;AAC3C,UAAM,0BAA0B,KAAK,OAAO,oCAAoC;AAChF,UAAM;AAAA,MACL,QAAQ,EAAE,iBAAiB;AAAA,IAC5B,IAAI,KAAK;AAET,UAAM,UAAU,oBAAI,IAAe;AAEnC,UAAM,cAAc,QAAQ;AAE5B,aAAS,IAAI,wBAAwB,QAAQ,IAAI,IAAI,GAAG,KAAK,GAAG,KAAK;AACpE,YAAM,QAAQ,wBAAwB,CAAC;AACvC,UACC,KAAK,OAAO,wBAAwB,KAAK,KACzC,KAAK,OAAO,cAA4B,OAAO,OAAO,GACrD;AACD;AAAA,MACD;AAEA,UACC,KAAK,OAAO,eAAe,OAAO,kBAAkB;AAAA,QACnD,WAAW;AAAA,QACX,QAAQ,KAAK,OAAO,QAAQ,gBAAgB;AAAA,MAC7C,CAAC,GACA;AACD,cAAM,WAAW,KAAK,OAAO,4BAA4B,KAAK;AAE9D,YACC,KAAK,OAAO,cAA4B,UAAU,OAAO,KACzD,QAAQ,OAAO,aACd;AACD;AAAA,QACD;AAEA,gBAAQ,IAAI,SAAS,EAAE;AAGvB,YAAI,KAAK,oBAAoB;AAC5B;AAAA,QACD;AAAA,MACD;AAAA,IACD;AAEA,SAAK,OAAO,iBAAiB,CAAC,GAAG,OAAO,CAAC;AAAA,EAC1C;AAAA,EAES,UAAU;AAClB,SAAK,yBAAqB,0BAAW,KAAK,OAAO,MAAM;AAAA,EACxD;AAAA,EAES,YAAY;AACpB,SAAK,yBAAqB,0BAAW,KAAK,OAAO,MAAM;AAAA,EACxD;AAAA,EAES,YAAY,MAA0B;AAC9C,SAAK,aAAa,IAAI;AAAA,EACvB;AAAA,EAES,OAAO,OAAY,IAAY;AACvC,QAAI,OAAO,WAAW;AACrB,WAAK,OAAO,iBAAiB,CAAC,CAAC;AAAA,IAChC;AAAA,EACD;AAAA,EAES,cAAc,MAA0B;AAChD,QAAI,KAAK,mBAAoB;AAE7B,QAAI,KAAK,OAAO,OAAO,YAAY;AAClC,WAAK,aAAa,IAAI;AAAA,IACvB;AAAA,EACD;AAAA,EAES,cAAc;AACtB,SAAK,SAAS;AAAA,EACf;AAAA,EAES,WAAW;AACnB,SAAK,OAAO;AAAA,EACb;AAAA,EAES,aAAa;AACrB,SAAK,SAAS;AAAA,EACf;AAAA,EAES,cAAc;AACtB,SAAK,OAAO;AAAA,EACb;AAAA,EAEQ,aAAa,MAA0B;AAC9C,SAAK,OAAO,WAAW,WAAW,IAAI;AAAA,EACvC;AAAA,EAEA,WAAW;AACV,UAAM,kBAAkB,KAAK,OAAO,mBAAmB;AAEvD,QAAI,gBAAgB,QAAQ;AAC3B,WAAK,OAAO,yBAAyB,WAAW;AAChD,WAAK,OAAO,aAAa,eAAe;AAAA,IACzC;AAEA,SAAK,OAAO,WAAW,MAAM;AAAA,EAC9B;AAAA,EAEA,SAAS;AACR,SAAK,OAAO,WAAW,MAAM;AAAA,EAC9B;AACD;",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|