tldraw 3.16.0-canary.f60032f16651 → 3.16.0-canary.faec5de49906
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist-cjs/index.d.ts +323 -106
- package/dist-cjs/index.js +45 -14
- package/dist-cjs/index.js.map +2 -2
- package/dist-cjs/lib/Tldraw.js +12 -2
- package/dist-cjs/lib/Tldraw.js.map +2 -2
- package/dist-cjs/lib/canvas/TldrawScribble.js +1 -1
- package/dist-cjs/lib/canvas/TldrawScribble.js.map +2 -2
- package/dist-cjs/lib/defaultExternalContentHandlers.js +5 -4
- package/dist-cjs/lib/defaultExternalContentHandlers.js.map +2 -2
- package/dist-cjs/lib/shapes/arrow/ArrowShapeUtil.js +3 -3
- package/dist-cjs/lib/shapes/arrow/ArrowShapeUtil.js.map +2 -2
- package/dist-cjs/lib/shapes/arrow/arrowLabel.js +6 -0
- package/dist-cjs/lib/shapes/arrow/arrowLabel.js.map +3 -3
- package/dist-cjs/lib/shapes/arrow/elbow/ElbowArrowDebug.js +3 -3
- package/dist-cjs/lib/shapes/arrow/elbow/ElbowArrowDebug.js.map +1 -1
- package/dist-cjs/lib/shapes/draw/DrawShapeUtil.js +3 -3
- package/dist-cjs/lib/shapes/draw/DrawShapeUtil.js.map +2 -2
- package/dist-cjs/lib/shapes/embed/EmbedShapeUtil.js +1 -1
- package/dist-cjs/lib/shapes/embed/EmbedShapeUtil.js.map +1 -1
- package/dist-cjs/lib/shapes/frame/FrameShapeUtil.js +20 -13
- package/dist-cjs/lib/shapes/frame/FrameShapeUtil.js.map +2 -2
- package/dist-cjs/lib/shapes/frame/components/FrameHeading.js +1 -1
- package/dist-cjs/lib/shapes/frame/components/FrameHeading.js.map +2 -2
- package/dist-cjs/lib/shapes/geo/GeoShapeUtil.js +3 -2
- package/dist-cjs/lib/shapes/geo/GeoShapeUtil.js.map +2 -2
- package/dist-cjs/lib/shapes/geo/components/GeoShapeBody.js +2 -1
- package/dist-cjs/lib/shapes/geo/components/GeoShapeBody.js.map +2 -2
- package/dist-cjs/lib/shapes/highlight/HighlightShapeUtil.js +5 -1
- package/dist-cjs/lib/shapes/highlight/HighlightShapeUtil.js.map +2 -2
- package/dist-cjs/lib/shapes/image/ImageShapeUtil.js +6 -3
- package/dist-cjs/lib/shapes/image/ImageShapeUtil.js.map +2 -2
- package/dist-cjs/lib/shapes/line/LineShapeUtil.js +5 -1
- package/dist-cjs/lib/shapes/line/LineShapeUtil.js.map +2 -2
- package/dist-cjs/lib/shapes/note/NoteShapeUtil.js +6 -5
- package/dist-cjs/lib/shapes/note/NoteShapeUtil.js.map +2 -2
- package/dist-cjs/lib/shapes/shared/PlainTextLabel.js +1 -3
- package/dist-cjs/lib/shapes/shared/PlainTextLabel.js.map +2 -2
- package/dist-cjs/lib/shapes/shared/ShapeFill.js +4 -4
- package/dist-cjs/lib/shapes/shared/ShapeFill.js.map +2 -2
- package/dist-cjs/lib/shapes/shared/freehand/svg.js.map +2 -2
- package/dist-cjs/lib/shapes/shared/useEditablePlainText.js +0 -2
- package/dist-cjs/lib/shapes/shared/useEditablePlainText.js.map +2 -2
- package/dist-cjs/lib/shapes/shared/useImageOrVideoAsset.js +0 -2
- package/dist-cjs/lib/shapes/shared/useImageOrVideoAsset.js.map +2 -2
- package/dist-cjs/lib/shapes/shared/usePrefersReducedMotion.js +10 -1
- package/dist-cjs/lib/shapes/shared/usePrefersReducedMotion.js.map +2 -2
- package/dist-cjs/lib/shapes/text/TextShapeUtil.js +2 -2
- package/dist-cjs/lib/shapes/text/TextShapeUtil.js.map +2 -2
- package/dist-cjs/lib/shapes/video/VideoShapeUtil.js +3 -3
- package/dist-cjs/lib/shapes/video/VideoShapeUtil.js.map +1 -1
- package/dist-cjs/lib/tools/EraserTool/childStates/Erasing.js +25 -1
- package/dist-cjs/lib/tools/EraserTool/childStates/Erasing.js.map +2 -2
- package/dist-cjs/lib/tools/EraserTool/childStates/Pointing.js +12 -0
- package/dist-cjs/lib/tools/EraserTool/childStates/Pointing.js.map +2 -2
- package/dist-cjs/lib/ui/TldrawUi.js +27 -12
- package/dist-cjs/lib/ui/TldrawUi.js.map +3 -3
- package/dist-cjs/lib/ui/assetUrls.js +13 -10
- package/dist-cjs/lib/ui/assetUrls.js.map +2 -2
- package/dist-cjs/lib/ui/components/AccessibilityMenu.js +35 -0
- package/dist-cjs/lib/ui/components/AccessibilityMenu.js.map +7 -0
- package/dist-cjs/lib/ui/components/ActionsMenu/DefaultActionsMenu.js +12 -3
- package/dist-cjs/lib/ui/components/ActionsMenu/DefaultActionsMenu.js.map +2 -2
- package/dist-cjs/lib/ui/components/{FollowingIndicator.js → DefaultFollowingIndicator.js} +6 -6
- package/dist-cjs/lib/ui/components/DefaultFollowingIndicator.js.map +7 -0
- package/dist-cjs/lib/ui/components/DefaultMenuPanel.js +3 -2
- package/dist-cjs/lib/ui/components/DefaultMenuPanel.js.map +2 -2
- package/dist-cjs/lib/ui/components/KeyboardShortcutsDialog/DefaultKeyboardShortcutsDialogContent.js +6 -6
- package/dist-cjs/lib/ui/components/KeyboardShortcutsDialog/DefaultKeyboardShortcutsDialogContent.js.map +1 -1
- package/dist-cjs/lib/ui/components/MainMenu/DefaultMainMenuContent.js +3 -3
- package/dist-cjs/lib/ui/components/MainMenu/DefaultMainMenuContent.js.map +2 -2
- package/dist-cjs/lib/ui/components/Minimap/MinimapManager.js +4 -4
- package/dist-cjs/lib/ui/components/Minimap/MinimapManager.js.map +2 -2
- package/dist-cjs/lib/ui/components/MobileStylePanel.js +5 -3
- package/dist-cjs/lib/ui/components/MobileStylePanel.js.map +2 -2
- package/dist-cjs/lib/ui/components/NavigationPanel/DefaultNavigationPanel.js +1 -1
- package/dist-cjs/lib/ui/components/NavigationPanel/DefaultNavigationPanel.js.map +2 -2
- package/dist-cjs/lib/ui/components/PageMenu/DefaultPageMenu.js +2 -1
- package/dist-cjs/lib/ui/components/PageMenu/DefaultPageMenu.js.map +2 -2
- package/dist-cjs/lib/ui/components/SharePanel/PeopleMenuItem.js +3 -2
- package/dist-cjs/lib/ui/components/SharePanel/PeopleMenuItem.js.map +2 -2
- package/dist-cjs/lib/ui/components/SharePanel/UserPresenceColorPicker.js +2 -2
- package/dist-cjs/lib/ui/components/SharePanel/UserPresenceColorPicker.js.map +2 -2
- package/dist-cjs/lib/ui/components/StylePanel/DefaultStylePanel.js +11 -4
- package/dist-cjs/lib/ui/components/StylePanel/DefaultStylePanel.js.map +2 -2
- package/dist-cjs/lib/ui/components/StylePanel/DefaultStylePanelContent.js +249 -279
- package/dist-cjs/lib/ui/components/StylePanel/DefaultStylePanelContent.js.map +2 -2
- package/dist-cjs/lib/ui/components/{primitives/TldrawUiButtonPicker.js → StylePanel/StylePanelButtonPicker.js} +52 -56
- package/dist-cjs/lib/ui/components/StylePanel/StylePanelButtonPicker.js.map +7 -0
- package/dist-cjs/lib/ui/components/StylePanel/StylePanelContext.js +68 -0
- package/dist-cjs/lib/ui/components/StylePanel/StylePanelContext.js.map +7 -0
- package/dist-cjs/lib/ui/components/StylePanel/{DoubleDropdownPicker.js → StylePanelDoubleDropdownPicker.js} +26 -25
- package/dist-cjs/lib/ui/components/StylePanel/StylePanelDoubleDropdownPicker.js.map +7 -0
- package/dist-cjs/lib/ui/components/StylePanel/{DropdownPicker.js → StylePanelDropdownPicker.js} +47 -43
- package/dist-cjs/lib/ui/components/StylePanel/StylePanelDropdownPicker.js.map +7 -0
- package/dist-cjs/lib/ui/components/StylePanel/StylePanelSubheading.js +28 -0
- package/dist-cjs/lib/ui/components/StylePanel/StylePanelSubheading.js.map +7 -0
- package/dist-cjs/lib/ui/components/Toolbar/AltTextEditor.js +3 -2
- package/dist-cjs/lib/ui/components/Toolbar/AltTextEditor.js.map +2 -2
- package/dist-cjs/lib/ui/components/Toolbar/DefaultImageToolbarContent.js +39 -10
- package/dist-cjs/lib/ui/components/Toolbar/DefaultImageToolbarContent.js.map +2 -2
- package/dist-cjs/lib/ui/components/Toolbar/DefaultToolbar.js +66 -21
- package/dist-cjs/lib/ui/components/Toolbar/DefaultToolbar.js.map +3 -3
- package/dist-cjs/lib/ui/components/Toolbar/DefaultVideoToolbarContent.js +15 -3
- package/dist-cjs/lib/ui/components/Toolbar/DefaultVideoToolbarContent.js.map +2 -2
- package/dist-cjs/lib/ui/components/Toolbar/LinkEditor.js +3 -3
- package/dist-cjs/lib/ui/components/Toolbar/LinkEditor.js.map +2 -2
- package/dist-cjs/lib/ui/components/Toolbar/OverflowingToolbar.js +189 -80
- package/dist-cjs/lib/ui/components/Toolbar/OverflowingToolbar.js.map +3 -3
- package/dist-cjs/lib/ui/components/Toolbar/ToggleToolLockedButton.js +5 -4
- package/dist-cjs/lib/ui/components/Toolbar/ToggleToolLockedButton.js.map +2 -2
- package/dist-cjs/lib/ui/components/menu-items.js +6 -0
- package/dist-cjs/lib/ui/components/menu-items.js.map +2 -2
- package/dist-cjs/lib/ui/components/primitives/TldrawUiContextualToolbar.js +10 -1
- package/dist-cjs/lib/ui/components/primitives/TldrawUiContextualToolbar.js.map +2 -2
- package/dist-cjs/lib/ui/components/primitives/TldrawUiPopover.js +3 -2
- package/dist-cjs/lib/ui/components/primitives/TldrawUiPopover.js.map +3 -3
- package/dist-cjs/lib/ui/components/primitives/TldrawUiSlider.js +18 -5
- package/dist-cjs/lib/ui/components/primitives/TldrawUiSlider.js.map +2 -2
- package/dist-cjs/lib/ui/components/primitives/TldrawUiToolbar.js +32 -7
- package/dist-cjs/lib/ui/components/primitives/TldrawUiToolbar.js.map +2 -2
- package/dist-cjs/lib/ui/components/primitives/TldrawUiTooltip.js +294 -0
- package/dist-cjs/lib/ui/components/primitives/TldrawUiTooltip.js.map +7 -0
- package/dist-cjs/lib/ui/components/primitives/layout.js +76 -0
- package/dist-cjs/lib/ui/components/primitives/layout.js.map +7 -0
- package/dist-cjs/lib/ui/components/primitives/menus/TldrawUiMenuContext.js.map +2 -2
- package/dist-cjs/lib/ui/components/primitives/menus/TldrawUiMenuGroup.js +25 -12
- package/dist-cjs/lib/ui/components/primitives/menus/TldrawUiMenuGroup.js.map +2 -2
- package/dist-cjs/lib/ui/components/primitives/menus/TldrawUiMenuItem.js +17 -31
- package/dist-cjs/lib/ui/components/primitives/menus/TldrawUiMenuItem.js.map +2 -2
- package/dist-cjs/lib/ui/context/TldrawUiContextProvider.js +3 -2
- package/dist-cjs/lib/ui/context/TldrawUiContextProvider.js.map +2 -2
- package/dist-cjs/lib/ui/context/actions.js +38 -10
- package/dist-cjs/lib/ui/context/actions.js.map +2 -2
- package/dist-cjs/lib/ui/context/components.js +2 -0
- package/dist-cjs/lib/ui/context/components.js.map +2 -2
- package/dist-cjs/lib/ui/context/events.js.map +2 -2
- package/dist-cjs/lib/ui/hooks/useExportAs.js +3 -2
- package/dist-cjs/lib/ui/hooks/useExportAs.js.map +2 -2
- package/dist-cjs/lib/ui/hooks/useTools.js +22 -4
- package/dist-cjs/lib/ui/hooks/useTools.js.map +2 -2
- package/dist-cjs/lib/ui/hooks/useTranslation/TLUiTranslationKey.js.map +1 -1
- package/dist-cjs/lib/ui/hooks/useTranslation/defaultTranslation.js +6 -1
- package/dist-cjs/lib/ui/hooks/useTranslation/defaultTranslation.js.map +2 -2
- package/dist-cjs/lib/ui/kbd-utils.js +9 -3
- package/dist-cjs/lib/ui/kbd-utils.js.map +2 -2
- package/dist-cjs/lib/ui/version.js +3 -3
- package/dist-cjs/lib/ui/version.js.map +1 -1
- package/dist-cjs/lib/utils/export/copyAs.js +1 -2
- package/dist-cjs/lib/utils/export/copyAs.js.map +2 -2
- package/dist-cjs/lib/utils/export/export.js +0 -20
- package/dist-cjs/lib/utils/export/export.js.map +2 -2
- package/dist-cjs/lib/utils/export/exportAs.js +1 -2
- package/dist-cjs/lib/utils/export/exportAs.js.map +2 -2
- package/dist-esm/index.d.mts +323 -106
- package/dist-esm/index.mjs +83 -29
- package/dist-esm/index.mjs.map +2 -2
- package/dist-esm/lib/Tldraw.mjs +14 -4
- package/dist-esm/lib/Tldraw.mjs.map +2 -2
- package/dist-esm/lib/canvas/TldrawScribble.mjs +1 -1
- package/dist-esm/lib/canvas/TldrawScribble.mjs.map +2 -2
- package/dist-esm/lib/defaultExternalContentHandlers.mjs +5 -4
- package/dist-esm/lib/defaultExternalContentHandlers.mjs.map +2 -2
- package/dist-esm/lib/shapes/arrow/ArrowShapeUtil.mjs +4 -3
- package/dist-esm/lib/shapes/arrow/ArrowShapeUtil.mjs.map +2 -2
- package/dist-esm/lib/shapes/arrow/arrowLabel.mjs +6 -0
- package/dist-esm/lib/shapes/arrow/arrowLabel.mjs.map +3 -3
- package/dist-esm/lib/shapes/arrow/elbow/ElbowArrowDebug.mjs +3 -3
- package/dist-esm/lib/shapes/arrow/elbow/ElbowArrowDebug.mjs.map +1 -1
- package/dist-esm/lib/shapes/draw/DrawShapeUtil.mjs +4 -3
- package/dist-esm/lib/shapes/draw/DrawShapeUtil.mjs.map +2 -2
- package/dist-esm/lib/shapes/embed/EmbedShapeUtil.mjs +1 -1
- package/dist-esm/lib/shapes/embed/EmbedShapeUtil.mjs.map +1 -1
- package/dist-esm/lib/shapes/frame/FrameShapeUtil.mjs +21 -13
- package/dist-esm/lib/shapes/frame/FrameShapeUtil.mjs.map +2 -2
- package/dist-esm/lib/shapes/frame/components/FrameHeading.mjs +1 -1
- package/dist-esm/lib/shapes/frame/components/FrameHeading.mjs.map +2 -2
- package/dist-esm/lib/shapes/geo/GeoShapeUtil.mjs +4 -2
- package/dist-esm/lib/shapes/geo/GeoShapeUtil.mjs.map +2 -2
- package/dist-esm/lib/shapes/geo/components/GeoShapeBody.mjs +2 -1
- package/dist-esm/lib/shapes/geo/components/GeoShapeBody.mjs.map +2 -2
- package/dist-esm/lib/shapes/highlight/HighlightShapeUtil.mjs +6 -1
- package/dist-esm/lib/shapes/highlight/HighlightShapeUtil.mjs.map +2 -2
- package/dist-esm/lib/shapes/image/ImageShapeUtil.mjs +6 -3
- package/dist-esm/lib/shapes/image/ImageShapeUtil.mjs.map +2 -2
- package/dist-esm/lib/shapes/line/LineShapeUtil.mjs +6 -1
- package/dist-esm/lib/shapes/line/LineShapeUtil.mjs.map +2 -2
- package/dist-esm/lib/shapes/note/NoteShapeUtil.mjs +7 -5
- package/dist-esm/lib/shapes/note/NoteShapeUtil.mjs.map +2 -2
- package/dist-esm/lib/shapes/shared/PlainTextLabel.mjs +1 -3
- package/dist-esm/lib/shapes/shared/PlainTextLabel.mjs.map +2 -2
- package/dist-esm/lib/shapes/shared/ShapeFill.mjs +5 -4
- package/dist-esm/lib/shapes/shared/ShapeFill.mjs.map +2 -2
- package/dist-esm/lib/shapes/shared/freehand/svg.mjs.map +2 -2
- package/dist-esm/lib/shapes/shared/useEditablePlainText.mjs +0 -2
- package/dist-esm/lib/shapes/shared/useEditablePlainText.mjs.map +2 -2
- package/dist-esm/lib/shapes/shared/useImageOrVideoAsset.mjs +0 -2
- package/dist-esm/lib/shapes/shared/useImageOrVideoAsset.mjs.map +2 -2
- package/dist-esm/lib/shapes/shared/usePrefersReducedMotion.mjs +10 -1
- package/dist-esm/lib/shapes/shared/usePrefersReducedMotion.mjs.map +2 -2
- package/dist-esm/lib/shapes/text/TextShapeUtil.mjs +3 -2
- package/dist-esm/lib/shapes/text/TextShapeUtil.mjs.map +2 -2
- package/dist-esm/lib/shapes/video/VideoShapeUtil.mjs +3 -3
- package/dist-esm/lib/shapes/video/VideoShapeUtil.mjs.map +1 -1
- package/dist-esm/lib/tools/EraserTool/childStates/Erasing.mjs +26 -1
- package/dist-esm/lib/tools/EraserTool/childStates/Erasing.mjs.map +2 -2
- package/dist-esm/lib/tools/EraserTool/childStates/Pointing.mjs +13 -0
- package/dist-esm/lib/tools/EraserTool/childStates/Pointing.mjs.map +2 -2
- package/dist-esm/lib/ui/TldrawUi.mjs +29 -14
- package/dist-esm/lib/ui/TldrawUi.mjs.map +3 -3
- package/dist-esm/lib/ui/assetUrls.mjs +13 -10
- package/dist-esm/lib/ui/assetUrls.mjs.map +2 -2
- package/dist-esm/lib/ui/components/AccessibilityMenu.mjs +19 -0
- package/dist-esm/lib/ui/components/AccessibilityMenu.mjs.map +7 -0
- package/dist-esm/lib/ui/components/ActionsMenu/DefaultActionsMenu.mjs +12 -3
- package/dist-esm/lib/ui/components/ActionsMenu/DefaultActionsMenu.mjs.map +2 -2
- package/dist-esm/lib/ui/components/{FollowingIndicator.mjs → DefaultFollowingIndicator.mjs} +3 -3
- package/dist-esm/lib/ui/components/DefaultFollowingIndicator.mjs.map +7 -0
- package/dist-esm/lib/ui/components/DefaultMenuPanel.mjs +3 -2
- package/dist-esm/lib/ui/components/DefaultMenuPanel.mjs.map +2 -2
- package/dist-esm/lib/ui/components/KeyboardShortcutsDialog/DefaultKeyboardShortcutsDialogContent.mjs +6 -6
- package/dist-esm/lib/ui/components/KeyboardShortcutsDialog/DefaultKeyboardShortcutsDialogContent.mjs.map +1 -1
- package/dist-esm/lib/ui/components/MainMenu/DefaultMainMenuContent.mjs +3 -5
- package/dist-esm/lib/ui/components/MainMenu/DefaultMainMenuContent.mjs.map +2 -2
- package/dist-esm/lib/ui/components/Minimap/MinimapManager.mjs +4 -4
- package/dist-esm/lib/ui/components/Minimap/MinimapManager.mjs.map +2 -2
- package/dist-esm/lib/ui/components/MobileStylePanel.mjs +6 -3
- package/dist-esm/lib/ui/components/MobileStylePanel.mjs.map +2 -2
- package/dist-esm/lib/ui/components/NavigationPanel/DefaultNavigationPanel.mjs +1 -1
- package/dist-esm/lib/ui/components/NavigationPanel/DefaultNavigationPanel.mjs.map +2 -2
- package/dist-esm/lib/ui/components/PageMenu/DefaultPageMenu.mjs +2 -1
- package/dist-esm/lib/ui/components/PageMenu/DefaultPageMenu.mjs.map +2 -2
- package/dist-esm/lib/ui/components/SharePanel/PeopleMenuItem.mjs +3 -2
- package/dist-esm/lib/ui/components/SharePanel/PeopleMenuItem.mjs.map +2 -2
- package/dist-esm/lib/ui/components/SharePanel/UserPresenceColorPicker.mjs +2 -2
- package/dist-esm/lib/ui/components/SharePanel/UserPresenceColorPicker.mjs.map +2 -2
- package/dist-esm/lib/ui/components/StylePanel/DefaultStylePanel.mjs +16 -5
- package/dist-esm/lib/ui/components/StylePanel/DefaultStylePanel.mjs.map +2 -2
- package/dist-esm/lib/ui/components/StylePanel/DefaultStylePanelContent.mjs +251 -283
- package/dist-esm/lib/ui/components/StylePanel/DefaultStylePanelContent.mjs.map +2 -2
- package/dist-esm/lib/ui/components/StylePanel/StylePanelButtonPicker.mjs +126 -0
- package/dist-esm/lib/ui/components/StylePanel/StylePanelButtonPicker.mjs.map +7 -0
- package/dist-esm/lib/ui/components/StylePanel/StylePanelContext.mjs +48 -0
- package/dist-esm/lib/ui/components/StylePanel/StylePanelContext.mjs.map +7 -0
- package/dist-esm/lib/ui/components/StylePanel/{DoubleDropdownPicker.mjs → StylePanelDoubleDropdownPicker.mjs} +23 -22
- package/dist-esm/lib/ui/components/StylePanel/StylePanelDoubleDropdownPicker.mjs.map +7 -0
- package/dist-esm/lib/ui/components/StylePanel/{DropdownPicker.mjs → StylePanelDropdownPicker.mjs} +44 -40
- package/dist-esm/lib/ui/components/StylePanel/StylePanelDropdownPicker.mjs.map +7 -0
- package/dist-esm/lib/ui/components/StylePanel/StylePanelSubheading.mjs +8 -0
- package/dist-esm/lib/ui/components/StylePanel/StylePanelSubheading.mjs.map +7 -0
- package/dist-esm/lib/ui/components/Toolbar/AltTextEditor.mjs +3 -2
- package/dist-esm/lib/ui/components/Toolbar/AltTextEditor.mjs.map +2 -2
- package/dist-esm/lib/ui/components/Toolbar/DefaultImageToolbarContent.mjs +39 -10
- package/dist-esm/lib/ui/components/Toolbar/DefaultImageToolbarContent.mjs.map +2 -2
- package/dist-esm/lib/ui/components/Toolbar/DefaultToolbar.mjs +56 -21
- package/dist-esm/lib/ui/components/Toolbar/DefaultToolbar.mjs.map +2 -2
- package/dist-esm/lib/ui/components/Toolbar/DefaultVideoToolbarContent.mjs +15 -3
- package/dist-esm/lib/ui/components/Toolbar/DefaultVideoToolbarContent.mjs.map +2 -2
- package/dist-esm/lib/ui/components/Toolbar/LinkEditor.mjs +3 -3
- package/dist-esm/lib/ui/components/Toolbar/LinkEditor.mjs.map +2 -2
- package/dist-esm/lib/ui/components/Toolbar/OverflowingToolbar.mjs +192 -81
- package/dist-esm/lib/ui/components/Toolbar/OverflowingToolbar.mjs.map +3 -3
- package/dist-esm/lib/ui/components/Toolbar/ToggleToolLockedButton.mjs +5 -4
- package/dist-esm/lib/ui/components/Toolbar/ToggleToolLockedButton.mjs.map +2 -2
- package/dist-esm/lib/ui/components/menu-items.mjs +6 -0
- package/dist-esm/lib/ui/components/menu-items.mjs.map +2 -2
- package/dist-esm/lib/ui/components/primitives/TldrawUiContextualToolbar.mjs +10 -1
- package/dist-esm/lib/ui/components/primitives/TldrawUiContextualToolbar.mjs.map +2 -2
- package/dist-esm/lib/ui/components/primitives/TldrawUiPopover.mjs +3 -2
- package/dist-esm/lib/ui/components/primitives/TldrawUiPopover.mjs.map +2 -2
- package/dist-esm/lib/ui/components/primitives/TldrawUiSlider.mjs +18 -5
- package/dist-esm/lib/ui/components/primitives/TldrawUiSlider.mjs.map +2 -2
- package/dist-esm/lib/ui/components/primitives/TldrawUiToolbar.mjs +32 -7
- package/dist-esm/lib/ui/components/primitives/TldrawUiToolbar.mjs.map +2 -2
- package/dist-esm/lib/ui/components/primitives/TldrawUiTooltip.mjs +272 -0
- package/dist-esm/lib/ui/components/primitives/TldrawUiTooltip.mjs.map +7 -0
- package/dist-esm/lib/ui/components/primitives/layout.mjs +46 -0
- package/dist-esm/lib/ui/components/primitives/layout.mjs.map +7 -0
- package/dist-esm/lib/ui/components/primitives/menus/TldrawUiMenuContext.mjs.map +2 -2
- package/dist-esm/lib/ui/components/primitives/menus/TldrawUiMenuGroup.mjs +25 -12
- package/dist-esm/lib/ui/components/primitives/menus/TldrawUiMenuGroup.mjs.map +2 -2
- package/dist-esm/lib/ui/components/primitives/menus/TldrawUiMenuItem.mjs +17 -31
- package/dist-esm/lib/ui/components/primitives/menus/TldrawUiMenuItem.mjs.map +2 -2
- package/dist-esm/lib/ui/context/TldrawUiContextProvider.mjs +3 -2
- package/dist-esm/lib/ui/context/TldrawUiContextProvider.mjs.map +2 -2
- package/dist-esm/lib/ui/context/actions.mjs +38 -10
- package/dist-esm/lib/ui/context/actions.mjs.map +2 -2
- package/dist-esm/lib/ui/context/components.mjs +2 -0
- package/dist-esm/lib/ui/context/components.mjs.map +2 -2
- package/dist-esm/lib/ui/context/events.mjs.map +2 -2
- package/dist-esm/lib/ui/hooks/useExportAs.mjs +3 -2
- package/dist-esm/lib/ui/hooks/useExportAs.mjs.map +2 -2
- package/dist-esm/lib/ui/hooks/useTools.mjs +23 -4
- package/dist-esm/lib/ui/hooks/useTools.mjs.map +2 -2
- package/dist-esm/lib/ui/hooks/useTranslation/defaultTranslation.mjs +6 -1
- package/dist-esm/lib/ui/hooks/useTranslation/defaultTranslation.mjs.map +2 -2
- package/dist-esm/lib/ui/kbd-utils.mjs +9 -3
- package/dist-esm/lib/ui/kbd-utils.mjs.map +2 -2
- package/dist-esm/lib/ui/version.mjs +3 -3
- package/dist-esm/lib/ui/version.mjs.map +1 -1
- package/dist-esm/lib/utils/export/copyAs.mjs +1 -2
- package/dist-esm/lib/utils/export/copyAs.mjs.map +2 -2
- package/dist-esm/lib/utils/export/export.mjs +0 -20
- package/dist-esm/lib/utils/export/export.mjs.map +2 -2
- package/dist-esm/lib/utils/export/exportAs.mjs +1 -2
- package/dist-esm/lib/utils/export/exportAs.mjs.map +2 -2
- package/package.json +11 -34
- package/src/index.ts +62 -22
- package/src/lib/Tldraw.tsx +15 -2
- package/src/lib/canvas/TldrawScribble.tsx +1 -1
- package/src/lib/defaultExternalContentHandlers.ts +12 -4
- package/src/lib/shapes/arrow/ArrowShapeOptions.test.ts +2 -1
- package/src/lib/shapes/arrow/ArrowShapeTool.test.ts +4 -3
- package/src/lib/shapes/arrow/ArrowShapeUtil.test.ts +48 -6
- package/src/lib/shapes/arrow/ArrowShapeUtil.tsx +4 -3
- package/src/lib/shapes/arrow/arrowLabel.ts +8 -0
- package/src/lib/shapes/arrow/elbow/ElbowArrowDebug.tsx +3 -3
- package/src/lib/shapes/draw/DrawShapeTool.test.ts +0 -5
- package/src/lib/shapes/draw/DrawShapeUtil.tsx +4 -3
- package/src/lib/shapes/embed/EmbedShapeUtil.tsx +1 -1
- package/src/lib/shapes/frame/FrameShapeUtil.tsx +30 -14
- package/src/lib/shapes/frame/components/FrameHeading.tsx +1 -1
- package/src/lib/shapes/geo/GeoShapeUtil.tsx +4 -2
- package/src/lib/shapes/geo/components/GeoShapeBody.tsx +2 -2
- package/src/lib/shapes/highlight/HighlightShapeUtil.tsx +7 -1
- package/src/lib/shapes/image/ImageShapeUtil.tsx +6 -3
- package/src/lib/shapes/line/LineShapeUtil.test.tsx +4 -3
- package/src/lib/shapes/line/LineShapeUtil.tsx +6 -1
- package/src/lib/shapes/line/__snapshots__/LineShapeUtil.test.tsx.snap +2 -2
- package/src/lib/shapes/note/NoteShapeUtil.tsx +10 -4
- package/src/lib/shapes/shared/PlainTextLabel.tsx +0 -6
- package/src/lib/shapes/shared/ShapeFill.tsx +5 -4
- package/src/lib/shapes/shared/freehand/svg.ts +2 -0
- package/src/lib/shapes/shared/useEditablePlainText.ts +0 -6
- package/src/lib/shapes/shared/useImageOrVideoAsset.ts +0 -7
- package/src/lib/shapes/shared/usePrefersReducedMotion.tsx +11 -1
- package/src/lib/shapes/text/TextShapeTool.test.ts +6 -5
- package/src/lib/shapes/text/TextShapeUtil.tsx +3 -2
- package/src/lib/shapes/video/VideoShapeUtil.tsx +3 -3
- package/src/lib/tools/EraserTool/childStates/Erasing.ts +34 -1
- package/src/lib/tools/EraserTool/childStates/Pointing.ts +20 -0
- package/src/lib/ui/TldrawUi.tsx +33 -12
- package/src/lib/ui/assetUrls.ts +13 -10
- package/src/lib/ui/components/AccessibilityMenu.tsx +20 -0
- package/src/lib/ui/components/ActionsMenu/DefaultActionsMenu.tsx +15 -3
- package/src/lib/ui/components/{FollowingIndicator.tsx → DefaultFollowingIndicator.tsx} +2 -1
- package/src/lib/ui/components/DefaultMenuPanel.tsx +4 -3
- package/src/lib/ui/components/KeyboardShortcutsDialog/DefaultKeyboardShortcutsDialogContent.tsx +6 -6
- package/src/lib/ui/components/MainMenu/DefaultMainMenuContent.tsx +4 -4
- package/src/lib/ui/components/Minimap/MinimapManager.ts +4 -4
- package/src/lib/ui/components/MobileStylePanel.tsx +9 -6
- package/src/lib/ui/components/NavigationPanel/DefaultNavigationPanel.tsx +1 -1
- package/src/lib/ui/components/PageMenu/DefaultPageMenu.tsx +3 -2
- package/src/lib/ui/components/SharePanel/PeopleMenuItem.tsx +4 -3
- package/src/lib/ui/components/SharePanel/UserPresenceColorPicker.tsx +3 -3
- package/src/lib/ui/components/StylePanel/DefaultStylePanel.tsx +28 -12
- package/src/lib/ui/components/StylePanel/DefaultStylePanelContent.tsx +261 -343
- package/src/lib/ui/components/{primitives/TldrawUiButtonPicker.tsx → StylePanel/StylePanelButtonPicker.tsx} +66 -50
- package/src/lib/ui/components/StylePanel/StylePanelContext.tsx +63 -0
- package/src/lib/ui/components/StylePanel/{DoubleDropdownPicker.tsx → StylePanelDoubleDropdownPicker.tsx} +31 -22
- package/src/lib/ui/components/StylePanel/StylePanelDropdownPicker.tsx +119 -0
- package/src/lib/ui/components/StylePanel/StylePanelSubheading.tsx +9 -0
- package/src/lib/ui/components/Toolbar/AltTextEditor.tsx +4 -3
- package/src/lib/ui/components/Toolbar/DefaultImageToolbarContent.tsx +33 -16
- package/src/lib/ui/components/Toolbar/DefaultToolbar.tsx +55 -23
- package/src/lib/ui/components/Toolbar/DefaultVideoToolbarContent.tsx +12 -4
- package/src/lib/ui/components/Toolbar/LinkEditor.tsx +5 -5
- package/src/lib/ui/components/Toolbar/OverflowingToolbar.tsx +212 -61
- package/src/lib/ui/components/Toolbar/ToggleToolLockedButton.tsx +14 -11
- package/src/lib/ui/components/menu-items.tsx +8 -0
- package/src/lib/ui/components/primitives/TldrawUiContextualToolbar.tsx +6 -1
- package/src/lib/ui/components/primitives/TldrawUiPopover.tsx +4 -2
- package/src/lib/ui/components/primitives/TldrawUiSlider.tsx +52 -32
- package/src/lib/ui/components/primitives/TldrawUiToolbar.tsx +54 -12
- package/src/lib/ui/components/primitives/TldrawUiTooltip.tsx +365 -0
- package/src/lib/ui/components/primitives/layout.tsx +107 -0
- package/src/lib/ui/components/primitives/menus/TldrawUiMenuContext.tsx +0 -1
- package/src/lib/ui/components/primitives/menus/TldrawUiMenuGroup.tsx +29 -16
- package/src/lib/ui/components/primitives/menus/TldrawUiMenuItem.tsx +24 -33
- package/src/lib/ui/context/TldrawUiContextProvider.tsx +23 -20
- package/src/lib/ui/context/actions.tsx +38 -10
- package/src/lib/ui/context/components.tsx +3 -0
- package/src/lib/ui/context/events.tsx +2 -1
- package/src/lib/ui/hooks/useExportAs.ts +3 -2
- package/src/lib/ui/hooks/useTools.tsx +26 -4
- package/src/lib/ui/hooks/useTranslation/TLUiTranslationKey.ts +5 -0
- package/src/lib/ui/hooks/useTranslation/defaultTranslation.ts +6 -1
- package/src/lib/ui/kbd-utils.ts +10 -3
- package/src/lib/ui/version.ts +3 -3
- package/src/lib/ui.css +424 -293
- package/src/lib/utils/excalidraw/__snapshots__/putExcalidrawContent.test.tsx.snap +5 -5
- package/src/lib/utils/export/copyAs.ts +1 -24
- package/src/lib/utils/export/export.ts +0 -36
- package/src/lib/utils/export/exportAs.ts +1 -32
- package/src/lib/utils/tldr/__snapshots__/buildFromV1Document.test.ts.snap +4 -4
- package/src/test/A11y.test.tsx +3 -2
- package/src/test/ClickManager.test.ts +7 -6
- package/src/test/Editor.test.tsx +20 -19
- package/src/test/EraserTool.test.ts +184 -13
- package/src/test/HandTool.test.ts +10 -9
- package/src/test/HighlightShape.test.ts +2 -1
- package/src/test/SelectTool.test.ts +3 -2
- package/src/test/TLUserPreferences.test.ts +4 -3
- package/src/test/TestEditor.ts +13 -15
- package/src/test/TldrawEditor.test.tsx +11 -10
- package/src/test/ZoomTool.test.ts +7 -6
- package/src/test/__snapshots__/drawing.test.ts.snap +2 -2
- package/src/test/__snapshots__/groups.test.tsx.snap +6 -6
- package/src/test/__snapshots__/resizing.test.ts.snap +2 -2
- package/src/test/arrows-megabus.test.tsx +5 -4
- package/src/test/bindings.test.tsx +24 -37
- package/src/test/bookmark-shapes.test.ts +1 -8
- package/src/test/commands/__snapshots__/getSvgString.test.ts.snap +23 -7
- package/src/test/commands/__snapshots__/packShapes.test.ts.snap +8 -8
- package/src/test/commands/__snapshots__/zoomToFit.test.ts.snap +2 -2
- package/src/test/commands/alignShapes.test.tsx +25 -24
- package/src/test/commands/animationSpeed.test.ts +2 -1
- package/src/test/commands/centerOnPoint.test.ts +3 -2
- package/src/test/commands/clipboard.test.ts +3 -2
- package/src/test/commands/createShapes.test.ts +2 -1
- package/src/test/commands/deleteShapes.test.ts +2 -1
- package/src/test/commands/distributeShapes.test.tsx +11 -10
- package/src/test/commands/getSvgString.test.ts +2 -1
- package/src/test/commands/packShapes.test.ts +5 -4
- package/src/test/commands/resizeShape.test.ts +2 -1
- package/src/test/commands/rotateShapes.test.ts +7 -6
- package/src/test/commands/setCamera.test.ts +4 -3
- package/src/test/commands/setCurrentPage.test.ts +3 -2
- package/src/test/commands/stackShapes.test.ts +11 -10
- package/src/test/commands/stretch.test.tsx +13 -12
- package/src/test/createDeepLink.test.tsx +2 -1
- package/src/test/cropping.test.ts +3 -2
- package/src/test/custom-clipping.test.ts +436 -0
- package/src/test/drawing.test.ts +2 -1
- package/src/test/flipShapes.test.ts +4 -3
- package/src/test/frames.test.ts +25 -24
- package/src/test/getCulledShapes.test.tsx +74 -4
- package/src/test/groups.test.tsx +1 -1
- package/src/test/handleDeepLink.test.tsx +2 -1
- package/src/test/maxShapes.test.ts +3 -2
- package/src/test/modifiers.test.ts +5 -4
- package/src/test/navigation.test.ts +12 -11
- package/src/test/panning.test.ts +2 -1
- package/src/test/perf/perf.test.ts +2 -1
- package/src/test/registerDeepLinkListener.test.tsx +10 -9
- package/src/test/resizing.test.ts +39 -38
- package/src/test/select.test.tsx +4 -3
- package/src/test/selection-omnibus.test.ts +11 -10
- package/src/test/shapeutils.test.ts +4 -3
- package/src/test/translating.test.ts +9 -8
- package/tldraw.css +732 -583
- package/dist-cjs/lib/ui/components/FollowingIndicator.js.map +0 -7
- package/dist-cjs/lib/ui/components/StylePanel/DoubleDropdownPicker.js.map +0 -7
- package/dist-cjs/lib/ui/components/StylePanel/DropdownPicker.js.map +0 -7
- package/dist-cjs/lib/ui/components/primitives/TldrawUiButtonPicker.js.map +0 -7
- package/dist-esm/lib/ui/components/FollowingIndicator.mjs.map +0 -7
- package/dist-esm/lib/ui/components/StylePanel/DoubleDropdownPicker.mjs.map +0 -7
- package/dist-esm/lib/ui/components/StylePanel/DropdownPicker.mjs.map +0 -7
- package/dist-esm/lib/ui/components/primitives/TldrawUiButtonPicker.mjs +0 -115
- package/dist-esm/lib/ui/components/primitives/TldrawUiButtonPicker.mjs.map +0 -7
- package/src/lib/ui/components/StylePanel/DropdownPicker.tsx +0 -109
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../../src/lib/shapes/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\texcludeFromShapeBounds: true,\n\t\t\t\t}),\n\t\t\t],\n\t\t})\n\t}\n\n\toverride getHandles(shape: TLNoteShape): TLHandle[] {\n\t\tconst { scale } = shape.props\n\t\tconst isCoarsePointer = this.editor.getInstanceState().isCoarsePointer\n\t\tif (isCoarsePointer) return []\n\n\t\tconst zoom = this.editor.getZoomLevel()\n\t\tif (zoom * scale < 0.25) return []\n\n\t\tconst nh = getNoteHeight(shape)\n\t\tconst nw = NOTE_SIZE * scale\n\t\tconst offset = (CLONE_HANDLE_MARGIN / zoom) * scale\n\n\t\tif (zoom * scale < 0.5) {\n\t\t\treturn [\n\t\t\t\t{\n\t\t\t\t\tid: 'bottom',\n\t\t\t\t\tindex: 'a3' as IndexKey,\n\t\t\t\t\ttype: 'clone',\n\t\t\t\t\tx: nw / 2,\n\t\t\t\t\ty: nh + offset,\n\t\t\t\t},\n\t\t\t]\n\t\t}\n\n\t\treturn [\n\t\t\t{\n\t\t\t\tid: 'top',\n\t\t\t\tindex: 'a1' as IndexKey,\n\t\t\t\ttype: 'clone',\n\t\t\t\tx: nw / 2,\n\t\t\t\ty: -offset,\n\t\t\t},\n\t\t\t{\n\t\t\t\tid: 'right',\n\t\t\t\tindex: 'a2' as IndexKey,\n\t\t\t\ttype: 'clone',\n\t\t\t\tx: nw + offset,\n\t\t\t\ty: nh / 2,\n\t\t\t},\n\t\t\t{\n\t\t\t\tid: 'bottom',\n\t\t\t\tindex: 'a3' as IndexKey,\n\t\t\t\ttype: 'clone',\n\t\t\t\tx: nw / 2,\n\t\t\t\ty: nh + offset,\n\t\t\t},\n\t\t\t{\n\t\t\t\tid: 'left',\n\t\t\t\tindex: 'a4' as IndexKey,\n\t\t\t\ttype: 'clone',\n\t\t\t\tx: -offset,\n\t\t\t\ty: nh / 2,\n\t\t\t},\n\t\t]\n\t}\n\n\toverride onResize(shape: any, info: TLResizeInfo<any>) {\n\t\tconst { resizeMode } = this.options\n\t\tswitch (resizeMode) {\n\t\t\tcase 'none': {\n\t\t\t\treturn undefined\n\t\t\t}\n\t\t\tcase 'scale': {\n\t\t\t\treturn resizeScaled(shape, info)\n\t\t\t}\n\t\t\tdefault: {\n\t\t\t\tthrow exhaustiveSwitchError(resizeMode)\n\t\t\t}\n\t\t}\n\t}\n\n\toverride getText(shape: TLNoteShape) {\n\t\treturn renderPlaintextFromRichText(this.editor, shape.props.richText)\n\t}\n\n\toverride getFontFaces(shape: TLNoteShape) {\n\t\tif (isEmptyRichText(shape.props.richText)) {\n\t\t\treturn EMPTY_ARRAY\n\t\t}\n\t\treturn getFontsFromRichText(this.editor, shape.props.richText, {\n\t\t\tfamily: `tldraw_${shape.props.font}`,\n\t\t\tweight: 'normal',\n\t\t\tstyle: 'normal',\n\t\t})\n\t}\n\n\tcomponent(shape: TLNoteShape) {\n\t\tconst {\n\t\t\tid,\n\t\t\ttype,\n\t\t\tprops: {\n\t\t\t\tlabelColor,\n\t\t\t\tscale,\n\t\t\t\tcolor,\n\t\t\t\tfont,\n\t\t\t\tsize,\n\t\t\t\talign,\n\t\t\t\trichText,\n\t\t\t\tverticalAlign,\n\t\t\t\tfontSizeAdjustment,\n\t\t\t},\n\t\t} = shape\n\n\t\tconst handleKeyDown = useNoteKeydownHandler(id)\n\n\t\tconst theme = useDefaultColorTheme()\n\t\tconst nw = NOTE_SIZE * scale\n\t\tconst nh = getNoteHeight(shape)\n\n\t\tconst rotation = useValue(\n\t\t\t'shape rotation',\n\t\t\t() => this.editor.getShapePageTransform(id)?.rotation() ?? 0,\n\t\t\t[this.editor]\n\t\t)\n\n\t\t// todo: consider hiding shadows on dark mode if they're invisible anyway\n\n\t\tconst hideShadows = useValue('zoom', () => this.editor.getZoomLevel() < 0.35 / scale, [\n\t\t\tscale,\n\t\t\tthis.editor,\n\t\t])\n\n\t\tconst isDarkMode = useValue('dark mode', () => this.editor.user.getIsDarkMode(), [this.editor])\n\n\t\tconst isSelected = shape.id === this.editor.getOnlySelectedShapeId()\n\n\t\tconst isReadyForEditing = useIsReadyForEditing(this.editor, shape.id)\n\t\tconst isEmpty = isEmptyRichText(richText)\n\n\t\treturn (\n\t\t\t<>\n\t\t\t\t<div\n\t\t\t\t\tid={id}\n\t\t\t\t\tclassName=\"tl-note__container\"\n\t\t\t\t\tstyle={{\n\t\t\t\t\t\twidth: nw,\n\t\t\t\t\t\theight: nh,\n\t\t\t\t\t\tbackgroundColor: getColorValue(theme, color, 'noteFill'),\n\t\t\t\t\t\tborderBottom: hideShadows\n\t\t\t\t\t\t\t? isDarkMode\n\t\t\t\t\t\t\t\t? `${2 * scale}px solid rgb(20, 20, 20)`\n\t\t\t\t\t\t\t\t: `${2 * scale}px solid rgb(144, 144, 144)`\n\t\t\t\t\t\t\t: 'none',\n\t\t\t\t\t\tboxShadow: hideShadows ? 'none' : getNoteShadow(shape.id, rotation, scale),\n\t\t\t\t\t}}\n\t\t\t\t>\n\t\t\t\t\t{(isSelected || isReadyForEditing || !isEmpty) && (\n\t\t\t\t\t\t<RichTextLabel\n\t\t\t\t\t\t\tshapeId={id}\n\t\t\t\t\t\t\ttype={type}\n\t\t\t\t\t\t\tfont={font}\n\t\t\t\t\t\t\tfontSize={(fontSizeAdjustment || LABEL_FONT_SIZES[size]) * scale}\n\t\t\t\t\t\t\tlineHeight={TEXT_PROPS.lineHeight}\n\t\t\t\t\t\t\talign={align}\n\t\t\t\t\t\t\tverticalAlign={verticalAlign}\n\t\t\t\t\t\t\trichText={richText}\n\t\t\t\t\t\t\tisSelected={isSelected}\n\t\t\t\t\t\t\tlabelColor={\n\t\t\t\t\t\t\t\tlabelColor === 'black'\n\t\t\t\t\t\t\t\t\t? getColorValue(theme, color, 'noteText')\n\t\t\t\t\t\t\t\t\t: getColorValue(theme, labelColor, 'fill')\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\twrap\n\t\t\t\t\t\t\tpadding={LABEL_PADDING * scale}\n\t\t\t\t\t\t\thasCustomTabBehavior\n\t\t\t\t\t\t\tonKeyDown={handleKeyDown}\n\t\t\t\t\t\t/>\n\t\t\t\t\t)}\n\t\t\t\t</div>\n\t\t\t\t{'url' in shape.props && shape.props.url && <HyperlinkButton url={shape.props.url} />}\n\t\t\t</>\n\t\t)\n\t}\n\n\tindicator(shape: TLNoteShape) {\n\t\tconst { scale } = shape.props\n\t\treturn (\n\t\t\t<rect\n\t\t\t\trx={scale}\n\t\t\t\twidth={toDomPrecision(NOTE_SIZE * scale)}\n\t\t\t\theight={toDomPrecision(getNoteHeight(shape))}\n\t\t\t/>\n\t\t)\n\t}\n\n\toverride toSvg(shape: TLNoteShape, ctx: SvgExportContext) {\n\t\tconst theme = getDefaultColorTheme({ isDarkMode: ctx.isDarkMode })\n\t\tconst bounds = getBoundsForSVG(shape)\n\n\t\tconst textLabel = (\n\t\t\t<RichTextSVG\n\t\t\t\tfontSize={shape.props.fontSizeAdjustment || LABEL_FONT_SIZES[shape.props.size]}\n\t\t\t\tfont={shape.props.font}\n\t\t\t\talign={shape.props.align}\n\t\t\t\tverticalAlign={shape.props.verticalAlign}\n\t\t\t\trichText={shape.props.richText}\n\t\t\t\tlabelColor={getColorValue(theme, shape.props.color, 'noteText')}\n\t\t\t\tbounds={bounds}\n\t\t\t\tpadding={LABEL_PADDING}\n\t\t\t\tshowTextOutline={false}\n\t\t\t/>\n\t\t)\n\n\t\treturn (\n\t\t\t<>\n\t\t\t\t<rect x={5} y={5} rx={1} width={NOTE_SIZE - 10} height={bounds.h} fill=\"rgba(0,0,0,.1)\" />\n\t\t\t\t<rect\n\t\t\t\t\trx={1}\n\t\t\t\t\twidth={NOTE_SIZE}\n\t\t\t\t\theight={bounds.h}\n\t\t\t\t\tfill={getColorValue(theme, shape.props.color, 'noteFill')}\n\t\t\t\t/>\n\t\t\t\t{textLabel}\n\t\t\t</>\n\t\t)\n\t}\n\n\toverride onBeforeCreate(next: TLNoteShape) {\n\t\treturn getNoteSizeAdjustments(this.editor, next)\n\t}\n\n\toverride onBeforeUpdate(prev: TLNoteShape, next: TLNoteShape) {\n\t\tif (\n\t\t\tisEqual(prev.props.richText, next.props.richText) &&\n\t\t\tprev.props.font === next.props.font &&\n\t\t\tprev.props.size === next.props.size\n\t\t) {\n\t\t\treturn\n\t\t}\n\n\t\treturn getNoteSizeAdjustments(this.editor, next)\n\t}\n\n\toverride getInterpolatedProps(\n\t\tstartShape: TLNoteShape,\n\t\tendShape: TLNoteShape,\n\t\tt: number\n\t): TLNoteShapeProps {\n\t\treturn {\n\t\t\t...(t > 0.5 ? endShape.props : startShape.props),\n\t\t\tscale: lerp(startShape.props.scale, endShape.props.scale, t),\n\t\t}\n\t}\n}\n\n/**\n * Get the growY and fontSizeAdjustment for a shape.\n */\nfunction getNoteSizeAdjustments(editor: Editor, shape: TLNoteShape) {\n\tconst { labelHeight, fontSizeAdjustment } = getLabelSize(editor, shape)\n\t// When the label height is more than the height of the shape, we add extra height to it\n\tconst growY = Math.max(0, labelHeight - NOTE_SIZE)\n\n\tif (growY !== shape.props.growY || fontSizeAdjustment !== shape.props.fontSizeAdjustment) {\n\t\treturn {\n\t\t\t...shape,\n\t\t\tprops: {\n\t\t\t\t...shape.props,\n\t\t\t\tgrowY,\n\t\t\t\tfontSizeAdjustment,\n\t\t\t},\n\t\t}\n\t}\n}\n\n/**\n * Get the label size for a note.\n */\nfunction getNoteLabelSize(editor: Editor, shape: TLNoteShape) {\n\tconst { richText } = shape.props\n\n\tif (isEmptyRichText(richText)) {\n\t\tconst minHeight = LABEL_FONT_SIZES[shape.props.size] * TEXT_PROPS.lineHeight + LABEL_PADDING * 2\n\t\treturn { labelHeight: minHeight, labelWidth: 100, fontSizeAdjustment: 0 }\n\t}\n\n\tconst unadjustedFontSize = LABEL_FONT_SIZES[shape.props.size]\n\n\tlet fontSizeAdjustment = 0\n\tlet iterations = 0\n\tlet labelHeight = NOTE_SIZE\n\tlet labelWidth = NOTE_SIZE\n\n\t// N.B. For some note shapes with text like 'hjhjhjhjhjhjhjhj', you'll run into\n\t// some text measurement fuzziness where the browser swears there's no overflow (scrollWidth === width)\n\t// but really there is when you enable overflow-wrap again. This helps account for that little bit\n\t// of give.\n\tconst FUZZ = 1\n\n\t// We slightly make the font smaller if the text is too big for the note, width-wise.\n\tdo {\n\t\tfontSizeAdjustment = Math.min(unadjustedFontSize, unadjustedFontSize - iterations)\n\t\tconst html = renderHtmlFromRichTextForMeasurement(editor, richText)\n\t\tconst nextTextSize = editor.textMeasure.measureHtml(html, {\n\t\t\t...TEXT_PROPS,\n\t\t\tfontFamily: FONT_FAMILIES[shape.props.font],\n\t\t\tfontSize: fontSizeAdjustment,\n\t\t\tmaxWidth: NOTE_SIZE - LABEL_PADDING * 2 - FUZZ,\n\t\t\tdisableOverflowWrapBreaking: true,\n\t\t\tmeasureScrollWidth: true,\n\t\t})\n\n\t\tlabelHeight = nextTextSize.h + LABEL_PADDING * 2\n\t\tlabelWidth = nextTextSize.w + LABEL_PADDING * 2\n\n\t\tif (fontSizeAdjustment <= 14) {\n\t\t\t// Too small, just rely now on CSS `overflow-wrap: break-word`\n\t\t\t// We need to recalculate the text measurement here with break-word enabled.\n\t\t\tconst html = renderHtmlFromRichTextForMeasurement(editor, richText)\n\t\t\tconst nextTextSizeWithOverflowBreak = editor.textMeasure.measureHtml(html, {\n\t\t\t\t...TEXT_PROPS,\n\t\t\t\tfontFamily: FONT_FAMILIES[shape.props.font],\n\t\t\t\tfontSize: fontSizeAdjustment,\n\t\t\t\tmaxWidth: NOTE_SIZE - LABEL_PADDING * 2 - FUZZ,\n\t\t\t})\n\t\t\tlabelHeight = nextTextSizeWithOverflowBreak.h + LABEL_PADDING * 2\n\t\t\tlabelWidth = nextTextSizeWithOverflowBreak.w + LABEL_PADDING * 2\n\t\t\tbreak\n\t\t}\n\n\t\tif (nextTextSize.scrollWidth.toFixed(0) === nextTextSize.w.toFixed(0)) {\n\t\t\tbreak\n\t\t}\n\t} while (iterations++ < 50)\n\n\treturn {\n\t\tlabelHeight: labelHeight,\n\t\tlabelWidth: labelWidth,\n\t\tfontSizeAdjustment: fontSizeAdjustment,\n\t}\n}\n\nconst labelSizesForNote = new WeakCache<TLShape, ReturnType<typeof getNoteLabelSize>>()\n\nfunction getLabelSize(editor: Editor, shape: TLNoteShape) {\n\treturn labelSizesForNote.get(shape, () => getNoteLabelSize(editor, shape))\n}\n\nfunction useNoteKeydownHandler(id: TLShapeId) {\n\tconst editor = useEditor()\n\tconst translation = useCurrentTranslation()\n\n\treturn useCallback(\n\t\t(e: KeyboardEvent) => {\n\t\t\tconst shape = editor.getShape<TLNoteShape>(id)\n\t\t\tif (!shape) return\n\n\t\t\tconst isTab = e.key === 'Tab'\n\t\t\tconst isCmdEnter = (e.metaKey || e.ctrlKey) && e.key === 'Enter'\n\t\t\tif (isTab || isCmdEnter) {\n\t\t\t\te.preventDefault()\n\n\t\t\t\tconst pageTransform = editor.getShapePageTransform(id)\n\t\t\t\tconst pageRotation = pageTransform.rotation()\n\n\t\t\t\t// Based on the inputs, calculate the offset to the next note\n\t\t\t\t// tab controls x axis (shift inverts direction set by RTL)\n\t\t\t\t// cmd enter is the y axis (shift inverts direction)\n\t\t\t\tconst isRTL = !!(\n\t\t\t\t\ttranslation.dir === 'rtl' ||\n\t\t\t\t\t// todo: can we check a partial of the text, so that we don't have to render the whole thing?\n\t\t\t\t\tisRightToLeftLanguage(renderPlaintextFromRichText(editor, shape.props.richText))\n\t\t\t\t)\n\n\t\t\t\tconst offsetLength =\n\t\t\t\t\t(NOTE_SIZE +\n\t\t\t\t\t\teditor.options.adjacentShapeMargin +\n\t\t\t\t\t\t// If we're growing down, we need to account for the current shape's growY\n\t\t\t\t\t\t(isCmdEnter && !e.shiftKey ? shape.props.growY : 0)) *\n\t\t\t\t\tshape.props.scale\n\n\t\t\t\tconst adjacentCenter = new Vec(\n\t\t\t\t\tisTab ? (e.shiftKey != isRTL ? -1 : 1) : 0,\n\t\t\t\t\tisCmdEnter ? (e.shiftKey ? -1 : 1) : 0\n\t\t\t\t)\n\t\t\t\t\t.mul(offsetLength)\n\t\t\t\t\t.add(NOTE_CENTER_OFFSET.clone().mul(shape.props.scale))\n\t\t\t\t\t.rot(pageRotation)\n\t\t\t\t\t.add(pageTransform.point())\n\n\t\t\t\tconst newNote = getNoteShapeForAdjacentPosition(editor, shape, adjacentCenter, pageRotation)\n\n\t\t\t\tif (newNote) {\n\t\t\t\t\tstartEditingShapeWithLabel(editor, newNote, true /* selectAll */)\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\t\t[id, editor, translation.dir]\n\t)\n}\n\nfunction getNoteHeight(shape: TLNoteShape) {\n\treturn (NOTE_SIZE + shape.props.growY) * shape.props.scale\n}\n\nfunction getNoteShadow(id: string, rotation: number, scale: number) {\n\tconst random = rng(id) // seeded based on id\n\tconst lift = Math.abs(random()) + 0.5 // 0 to 1.5\n\tconst oy = Math.cos(rotation)\n\tconst a = 5 * scale\n\tconst b = 4 * scale\n\tconst c = 6 * scale\n\tconst d = 7 * scale\n\treturn `0px ${a - lift}px ${a}px -${a}px rgba(15, 23, 31, .6),\n\t0px ${(b + lift * d) * Math.max(0, oy)}px ${c + lift * d}px -${b + lift * c}px rgba(15, 23, 31, ${(0.3 + lift * 0.1).toFixed(2)}), \n\t0px ${48 * scale}px ${10 * scale}px -${10 * scale}px inset rgba(15, 23, 44, ${((0.022 + random() * 0.005) * ((1 + oy) / 2)).toFixed(2)})`\n}\n\nfunction getBoundsForSVG(shape: TLNoteShape) {\n\t// When rendering the SVG we don't want to adjust for scale\n\treturn new Box(0, 0, NOTE_SIZE, NOTE_SIZE + shape.props.growY)\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": ["html"]
|
|
7
7
|
}
|
|
@@ -28,8 +28,7 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
|
|
|
28
28
|
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
29
29
|
var PlainTextLabel_exports = {};
|
|
30
30
|
__export(PlainTextLabel_exports, {
|
|
31
|
-
PlainTextLabel: () => PlainTextLabel
|
|
32
|
-
TextLabel: () => TextLabel
|
|
31
|
+
PlainTextLabel: () => PlainTextLabel
|
|
33
32
|
});
|
|
34
33
|
module.exports = __toCommonJS(PlainTextLabel_exports);
|
|
35
34
|
var import_jsx_runtime = require("react/jsx-runtime");
|
|
@@ -115,5 +114,4 @@ const PlainTextLabel = import_react.default.memo(function PlainTextLabel2({
|
|
|
115
114
|
}
|
|
116
115
|
);
|
|
117
116
|
});
|
|
118
|
-
const TextLabel = PlainTextLabel;
|
|
119
117
|
//# sourceMappingURL=PlainTextLabel.js.map
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../../src/lib/shapes/shared/PlainTextLabel.tsx"],
|
|
4
|
-
"sourcesContent": ["import {\n\tBox,\n\tTLDefaultFillStyle,\n\tTLDefaultFontStyle,\n\tTLDefaultHorizontalAlignStyle,\n\tTLDefaultVerticalAlignStyle,\n\tTLShapeId,\n} from '@tldraw/editor'\nimport React from 'react'\nimport { PlainTextArea } from '../text/PlainTextArea'\nimport { TextHelpers } from './TextHelpers'\nimport { isLegacyAlign } from './legacyProps'\nimport { useEditablePlainText } from './useEditablePlainText'\n\n/** @public */\nexport interface PlainTextLabelProps {\n\tshapeId: TLShapeId\n\ttype: string\n\tfont: TLDefaultFontStyle\n\tfontSize: number\n\tlineHeight: number\n\tfill?: TLDefaultFillStyle\n\talign: TLDefaultHorizontalAlignStyle\n\tverticalAlign: TLDefaultVerticalAlignStyle\n\twrap?: boolean\n\ttext?: string\n\tlabelColor: string\n\tbounds?: Box\n\tisSelected: boolean\n\tonKeyDown?(e: KeyboardEvent): void\n\tclassNamePrefix?: string\n\tstyle?: React.CSSProperties\n\ttextWidth?: number\n\ttextHeight?: number\n\tpadding?: number\n}\n\n/**\n * Renders a text label that can be used inside of shapes.\n * The component has the ability to be edited in place and furthermore\n * supports rich text editing.\n *\n * @public @react\n */\nexport const PlainTextLabel = React.memo(function PlainTextLabel({\n\tshapeId,\n\ttype,\n\ttext: plaintext,\n\tlabelColor,\n\tfont,\n\tfontSize,\n\tlineHeight,\n\talign,\n\tverticalAlign,\n\twrap,\n\tisSelected,\n\tpadding = 0,\n\tonKeyDown: handleKeyDownCustom,\n\tclassNamePrefix,\n\tstyle,\n\ttextWidth,\n\ttextHeight,\n}: PlainTextLabelProps) {\n\tconst { rInput, isEmpty, isEditing, isReadyForEditing, ...editableTextRest } =\n\t\tuseEditablePlainText(shapeId, type, plaintext)\n\n\tconst finalPlainText = TextHelpers.normalizeTextForDom(plaintext || '')\n\tconst hasText = finalPlainText.length > 0\n\n\tconst legacyAlign = isLegacyAlign(align)\n\n\tif (!isEditing && !hasText) {\n\t\treturn null\n\t}\n\n\t// TODO: probably combine tl-text and tl-arrow eventually\n\t// In case you're grepping for this, it breaks down as follows:\n\t// tl-text-label, tl-text-label__inner, tl-text-shape-label, tl-text\n\t// tl-arrow-label, tl-arrow-label__inner, tl-arrow\n\tconst cssPrefix = classNamePrefix || 'tl-text'\n\treturn (\n\t\t<div\n\t\t\tclassName={`${cssPrefix}-label tl-text-wrapper tl-plain-text-wrapper`}\n\t\t\taria-hidden={!isEditing}\n\t\t\tdata-font={font}\n\t\t\tdata-align={align}\n\t\t\tdata-hastext={!isEmpty}\n\t\t\tdata-isediting={isEditing}\n\t\t\tdata-is-ready-for-editing={isReadyForEditing}\n\t\t\tdata-textwrap={!!wrap}\n\t\t\tdata-isselected={isSelected}\n\t\t\tstyle={{\n\t\t\t\tjustifyContent: align === 'middle' || legacyAlign ? 'center' : align,\n\t\t\t\talignItems: verticalAlign === 'middle' ? 'center' : verticalAlign,\n\t\t\t\tpadding,\n\t\t\t\t...style,\n\t\t\t}}\n\t\t>\n\t\t\t<div\n\t\t\t\tclassName={`${cssPrefix}-label__inner tl-text-content__wrapper`}\n\t\t\t\tstyle={{\n\t\t\t\t\tfontSize,\n\t\t\t\t\tlineHeight: lineHeight.toString(),\n\t\t\t\t\tminHeight: Math.floor(fontSize * lineHeight) + 'px',\n\t\t\t\t\tminWidth: Math.ceil(textWidth || 0),\n\t\t\t\t\tcolor: labelColor,\n\t\t\t\t\twidth: textWidth ? Math.ceil(textWidth) : undefined,\n\t\t\t\t\theight: textHeight ? Math.ceil(textHeight) : undefined,\n\t\t\t\t}}\n\t\t\t>\n\t\t\t\t<div className={`${cssPrefix} tl-text tl-text-content`} dir=\"auto\">\n\t\t\t\t\t{finalPlainText.split('\\n').map((lineOfText, index) => (\n\t\t\t\t\t\t<div key={index} dir=\"auto\">\n\t\t\t\t\t\t\t{lineOfText}\n\t\t\t\t\t\t</div>\n\t\t\t\t\t))}\n\t\t\t\t</div>\n\t\t\t\t{(isReadyForEditing || isSelected) && (\n\t\t\t\t\t<PlainTextArea\n\t\t\t\t\t\t// Fudge the ref type because we're using forwardRef and it's not typed correctly.\n\t\t\t\t\t\tref={rInput as any}\n\t\t\t\t\t\ttext={plaintext}\n\t\t\t\t\t\tisEditing={isEditing}\n\t\t\t\t\t\tshapeId={shapeId}\n\t\t\t\t\t\t{...editableTextRest}\n\t\t\t\t\t\thandleKeyDown={handleKeyDownCustom ?? editableTextRest.handleKeyDown}\n\t\t\t\t\t/>\n\t\t\t\t)}\n\t\t\t</div>\n\t\t</div>\n\t)\n})\n
|
|
5
|
-
"mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;
|
|
4
|
+
"sourcesContent": ["import {\n\tBox,\n\tTLDefaultFillStyle,\n\tTLDefaultFontStyle,\n\tTLDefaultHorizontalAlignStyle,\n\tTLDefaultVerticalAlignStyle,\n\tTLShapeId,\n} from '@tldraw/editor'\nimport React from 'react'\nimport { PlainTextArea } from '../text/PlainTextArea'\nimport { TextHelpers } from './TextHelpers'\nimport { isLegacyAlign } from './legacyProps'\nimport { useEditablePlainText } from './useEditablePlainText'\n\n/** @public */\nexport interface PlainTextLabelProps {\n\tshapeId: TLShapeId\n\ttype: string\n\tfont: TLDefaultFontStyle\n\tfontSize: number\n\tlineHeight: number\n\tfill?: TLDefaultFillStyle\n\talign: TLDefaultHorizontalAlignStyle\n\tverticalAlign: TLDefaultVerticalAlignStyle\n\twrap?: boolean\n\ttext?: string\n\tlabelColor: string\n\tbounds?: Box\n\tisSelected: boolean\n\tonKeyDown?(e: KeyboardEvent): void\n\tclassNamePrefix?: string\n\tstyle?: React.CSSProperties\n\ttextWidth?: number\n\ttextHeight?: number\n\tpadding?: number\n}\n\n/**\n * Renders a text label that can be used inside of shapes.\n * The component has the ability to be edited in place and furthermore\n * supports rich text editing.\n *\n * @public @react\n */\nexport const PlainTextLabel = React.memo(function PlainTextLabel({\n\tshapeId,\n\ttype,\n\ttext: plaintext,\n\tlabelColor,\n\tfont,\n\tfontSize,\n\tlineHeight,\n\talign,\n\tverticalAlign,\n\twrap,\n\tisSelected,\n\tpadding = 0,\n\tonKeyDown: handleKeyDownCustom,\n\tclassNamePrefix,\n\tstyle,\n\ttextWidth,\n\ttextHeight,\n}: PlainTextLabelProps) {\n\tconst { rInput, isEmpty, isEditing, isReadyForEditing, ...editableTextRest } =\n\t\tuseEditablePlainText(shapeId, type, plaintext)\n\n\tconst finalPlainText = TextHelpers.normalizeTextForDom(plaintext || '')\n\tconst hasText = finalPlainText.length > 0\n\n\tconst legacyAlign = isLegacyAlign(align)\n\n\tif (!isEditing && !hasText) {\n\t\treturn null\n\t}\n\n\t// TODO: probably combine tl-text and tl-arrow eventually\n\t// In case you're grepping for this, it breaks down as follows:\n\t// tl-text-label, tl-text-label__inner, tl-text-shape-label, tl-text\n\t// tl-arrow-label, tl-arrow-label__inner, tl-arrow\n\tconst cssPrefix = classNamePrefix || 'tl-text'\n\treturn (\n\t\t<div\n\t\t\tclassName={`${cssPrefix}-label tl-text-wrapper tl-plain-text-wrapper`}\n\t\t\taria-hidden={!isEditing}\n\t\t\tdata-font={font}\n\t\t\tdata-align={align}\n\t\t\tdata-hastext={!isEmpty}\n\t\t\tdata-isediting={isEditing}\n\t\t\tdata-is-ready-for-editing={isReadyForEditing}\n\t\t\tdata-textwrap={!!wrap}\n\t\t\tdata-isselected={isSelected}\n\t\t\tstyle={{\n\t\t\t\tjustifyContent: align === 'middle' || legacyAlign ? 'center' : align,\n\t\t\t\talignItems: verticalAlign === 'middle' ? 'center' : verticalAlign,\n\t\t\t\tpadding,\n\t\t\t\t...style,\n\t\t\t}}\n\t\t>\n\t\t\t<div\n\t\t\t\tclassName={`${cssPrefix}-label__inner tl-text-content__wrapper`}\n\t\t\t\tstyle={{\n\t\t\t\t\tfontSize,\n\t\t\t\t\tlineHeight: lineHeight.toString(),\n\t\t\t\t\tminHeight: Math.floor(fontSize * lineHeight) + 'px',\n\t\t\t\t\tminWidth: Math.ceil(textWidth || 0),\n\t\t\t\t\tcolor: labelColor,\n\t\t\t\t\twidth: textWidth ? Math.ceil(textWidth) : undefined,\n\t\t\t\t\theight: textHeight ? Math.ceil(textHeight) : undefined,\n\t\t\t\t}}\n\t\t\t>\n\t\t\t\t<div className={`${cssPrefix} tl-text tl-text-content`} dir=\"auto\">\n\t\t\t\t\t{finalPlainText.split('\\n').map((lineOfText, index) => (\n\t\t\t\t\t\t<div key={index} dir=\"auto\">\n\t\t\t\t\t\t\t{lineOfText}\n\t\t\t\t\t\t</div>\n\t\t\t\t\t))}\n\t\t\t\t</div>\n\t\t\t\t{(isReadyForEditing || isSelected) && (\n\t\t\t\t\t<PlainTextArea\n\t\t\t\t\t\t// Fudge the ref type because we're using forwardRef and it's not typed correctly.\n\t\t\t\t\t\tref={rInput as any}\n\t\t\t\t\t\ttext={plaintext}\n\t\t\t\t\t\tisEditing={isEditing}\n\t\t\t\t\t\tshapeId={shapeId}\n\t\t\t\t\t\t{...editableTextRest}\n\t\t\t\t\t\thandleKeyDown={handleKeyDownCustom ?? editableTextRest.handleKeyDown}\n\t\t\t\t\t/>\n\t\t\t\t)}\n\t\t\t</div>\n\t\t</div>\n\t)\n})\n"],
|
|
5
|
+
"mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAkGG;AA1FH,mBAAkB;AAClB,2BAA8B;AAC9B,yBAA4B;AAC5B,yBAA8B;AAC9B,kCAAqC;AAgC9B,MAAM,iBAAiB,aAAAA,QAAM,KAAK,SAASC,gBAAe;AAAA,EAChE;AAAA,EACA;AAAA,EACA,MAAM;AAAA,EACN;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,UAAU;AAAA,EACV,WAAW;AAAA,EACX;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACD,GAAwB;AACvB,QAAM,EAAE,QAAQ,SAAS,WAAW,mBAAmB,GAAG,iBAAiB,QAC1E,kDAAqB,SAAS,MAAM,SAAS;AAE9C,QAAM,iBAAiB,+BAAY,oBAAoB,aAAa,EAAE;AACtE,QAAM,UAAU,eAAe,SAAS;AAExC,QAAM,kBAAc,kCAAc,KAAK;AAEvC,MAAI,CAAC,aAAa,CAAC,SAAS;AAC3B,WAAO;AAAA,EACR;AAMA,QAAM,YAAY,mBAAmB;AACrC,SACC;AAAA,IAAC;AAAA;AAAA,MACA,WAAW,GAAG,SAAS;AAAA,MACvB,eAAa,CAAC;AAAA,MACd,aAAW;AAAA,MACX,cAAY;AAAA,MACZ,gBAAc,CAAC;AAAA,MACf,kBAAgB;AAAA,MAChB,6BAA2B;AAAA,MAC3B,iBAAe,CAAC,CAAC;AAAA,MACjB,mBAAiB;AAAA,MACjB,OAAO;AAAA,QACN,gBAAgB,UAAU,YAAY,cAAc,WAAW;AAAA,QAC/D,YAAY,kBAAkB,WAAW,WAAW;AAAA,QACpD;AAAA,QACA,GAAG;AAAA,MACJ;AAAA,MAEA;AAAA,QAAC;AAAA;AAAA,UACA,WAAW,GAAG,SAAS;AAAA,UACvB,OAAO;AAAA,YACN;AAAA,YACA,YAAY,WAAW,SAAS;AAAA,YAChC,WAAW,KAAK,MAAM,WAAW,UAAU,IAAI;AAAA,YAC/C,UAAU,KAAK,KAAK,aAAa,CAAC;AAAA,YAClC,OAAO;AAAA,YACP,OAAO,YAAY,KAAK,KAAK,SAAS,IAAI;AAAA,YAC1C,QAAQ,aAAa,KAAK,KAAK,UAAU,IAAI;AAAA,UAC9C;AAAA,UAEA;AAAA,wDAAC,SAAI,WAAW,GAAG,SAAS,4BAA4B,KAAI,QAC1D,yBAAe,MAAM,IAAI,EAAE,IAAI,CAAC,YAAY,UAC5C,4CAAC,SAAgB,KAAI,QACnB,wBADQ,KAEV,CACA,GACF;AAAA,aACE,qBAAqB,eACtB;AAAA,cAAC;AAAA;AAAA,gBAEA,KAAK;AAAA,gBACL,MAAM;AAAA,gBACN;AAAA,gBACA;AAAA,gBACC,GAAG;AAAA,gBACJ,eAAe,uBAAuB,iBAAiB;AAAA;AAAA,YACxD;AAAA;AAAA;AAAA,MAEF;AAAA;AAAA,EACD;AAEF,CAAC;",
|
|
6
6
|
"names": ["React", "PlainTextLabel"]
|
|
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
|
}
|
|
@@ -19,7 +19,6 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
|
|
|
19
19
|
var useEditablePlainText_exports = {};
|
|
20
20
|
__export(useEditablePlainText_exports, {
|
|
21
21
|
useEditablePlainText: () => useEditablePlainText,
|
|
22
|
-
useEditableText: () => useEditableText,
|
|
23
22
|
useEditableTextCommon: () => useEditableTextCommon,
|
|
24
23
|
useIsReadyForEditing: () => useIsReadyForEditing
|
|
25
24
|
});
|
|
@@ -145,5 +144,4 @@ function useEditableTextCommon(shapeId) {
|
|
|
145
144
|
isReadyForEditing
|
|
146
145
|
};
|
|
147
146
|
}
|
|
148
|
-
const useEditableText = useEditablePlainText;
|
|
149
147
|
//# sourceMappingURL=useEditablePlainText.js.map
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../../src/lib/shapes/shared/useEditablePlainText.ts"],
|
|
4
|
-
"sourcesContent": ["import {\n\tEditor,\n\tTLShapeId,\n\tTLUnknownShape,\n\tgetPointerInfo,\n\tnoop,\n\tpreventDefault,\n\tstopEventPropagation,\n\ttlenv,\n\tuseEditor,\n\tuseValue,\n} from '@tldraw/editor'\nimport React, { useCallback, useEffect, useRef } from 'react'\nimport { TextHelpers } from './TextHelpers'\n\n/** @public */\nexport function useEditablePlainText(shapeId: TLShapeId, type: string, text?: string) {\n\tconst commonUseEditableTextHandlers = useEditableTextCommon(shapeId)\n\tconst isEditing = commonUseEditableTextHandlers.isEditing\n\tconst editor = useEditor()\n\tconst rInput = useRef<HTMLTextAreaElement>(null)\n\tconst isEmpty = (text || '').trim().length === 0\n\n\tuseEffect(() => {\n\t\tfunction selectAllIfEditing(event: { shapeId: TLShapeId }) {\n\t\t\tif (event.shapeId === shapeId) {\n\t\t\t\trInput.current?.select?.()\n\t\t\t}\n\t\t}\n\n\t\teditor.on('select-all-text', selectAllIfEditing)\n\t\treturn () => {\n\t\t\teditor.off('select-all-text', selectAllIfEditing)\n\t\t}\n\t}, [editor, shapeId, isEditing])\n\n\tuseEffect(() => {\n\t\tif (!isEditing) return\n\n\t\tif (document.activeElement !== rInput.current) {\n\t\t\trInput.current?.focus()\n\t\t}\n\n\t\tif (editor.getInstanceState().isCoarsePointer) {\n\t\t\trInput.current?.select()\n\t\t}\n\n\t\t// XXX(mime): This fixes iOS not showing the caret sometimes.\n\t\t// This \"shakes\" the caret awake.\n\t\tif (tlenv.isSafari) {\n\t\t\trInput.current?.blur()\n\t\t\trInput.current?.focus()\n\t\t}\n\t}, [editor, isEditing])\n\n\t// When the user presses ctrl / meta enter, complete the editing state.\n\tconst handleKeyDown = useCallback(\n\t\t(e: KeyboardEvent) => {\n\t\t\tif (editor.getEditingShapeId() !== shapeId) 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, shapeId]\n\t)\n\n\t// When the text changes, update the text value.\n\tconst handleChange = useCallback(\n\t\t({ plaintext }: { plaintext: string }) => {\n\t\t\tif (editor.getEditingShapeId() !== shapeId) return\n\n\t\t\tconst normalizedPlaintext = TextHelpers.normalizeText(plaintext || '')\n\t\t\teditor.updateShape<TLUnknownShape & { props: { text: string } }>({\n\t\t\t\tid: shapeId,\n\t\t\t\ttype,\n\t\t\t\tprops: { text: normalizedPlaintext },\n\t\t\t})\n\t\t},\n\t\t[editor, shapeId, type]\n\t)\n\n\treturn {\n\t\trInput,\n\t\thandleKeyDown,\n\t\thandleChange,\n\t\tisEmpty,\n\t\t...commonUseEditableTextHandlers,\n\t}\n}\n\n/** @internal */\nexport function useIsReadyForEditing(editor: Editor, shapeId: TLShapeId) {\n\treturn useValue(\n\t\t'isReadyForEditing',\n\t\t() => {\n\t\t\tconst editingShapeId = editor.getEditingShapeId()\n\t\t\treturn (\n\t\t\t\t// something's being editing... and either it's this shape OR this shape is hovered\n\t\t\t\teditingShapeId !== null &&\n\t\t\t\t(editingShapeId === shapeId || editor.getHoveredShapeId() === shapeId)\n\t\t\t)\n\t\t},\n\t\t[editor, shapeId]\n\t)\n}\n\n/** @internal */\nexport function useEditableTextCommon(shapeId: TLShapeId) {\n\tconst editor = useEditor()\n\tconst isEditing = useValue('isEditing', () => editor.getEditingShapeId() === shapeId, [editor])\n\tconst isReadyForEditing = useIsReadyForEditing(editor, shapeId)\n\n\tconst handleInputPointerDown = useCallback(\n\t\t(e: React.PointerEvent) => {\n\t\t\t// N.B. We used to only do this only when isEditing to help\n\t\t\t// prevent an issue where you could drag a selected shape\n\t\t\t// behind another shape. That is addressed now by the CSS logic\n\t\t\t// looking at data-isselectinganything.\n\t\t\t//\n\t\t\t// We still need to follow this logic even if not isEditing\n\t\t\t// because otherwise there is some flakiness in selection.\n\t\t\t// When selecting text, it would sometimes select some text\n\t\t\t// partially if we didn't dispatch/stop below.\n\n\t\t\teditor.dispatch({\n\t\t\t\t...getPointerInfo(e),\n\t\t\t\ttype: 'pointer',\n\t\t\t\tname: 'pointer_down',\n\t\t\t\ttarget: 'shape',\n\t\t\t\tshape: editor.getShape(shapeId)!,\n\t\t\t})\n\n\t\t\tstopEventPropagation(e) // we need to prevent blurring the input\n\t\t},\n\t\t[editor, shapeId]\n\t)\n\n\tconst handlePaste = useCallback(\n\t\t(e: ClipboardEvent | React.ClipboardEvent<HTMLTextAreaElement>) => {\n\t\t\tif (editor.getEditingShapeId() !== shapeId) return\n\t\t\tif (e.clipboardData) {\n\t\t\t\t// find html in the clipboard and look for the tldraw data\n\t\t\t\tconst html = e.clipboardData.getData('text/html')\n\t\t\t\tif (html) {\n\t\t\t\t\tif (html.includes('<div data-tldraw')) {\n\t\t\t\t\t\tpreventDefault(e)\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\t\t[editor, shapeId]\n\t)\n\n\treturn {\n\t\thandleFocus: noop,\n\t\thandleBlur: noop,\n\t\thandleInputPointerDown,\n\t\thandleDoubleClick: stopEventPropagation,\n\t\thandlePaste,\n\t\tisEditing,\n\t\tisReadyForEditing,\n\t}\n}\n
|
|
5
|
-
"mappings": ";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA
|
|
4
|
+
"sourcesContent": ["import {\n\tEditor,\n\tTLShapeId,\n\tTLUnknownShape,\n\tgetPointerInfo,\n\tnoop,\n\tpreventDefault,\n\tstopEventPropagation,\n\ttlenv,\n\tuseEditor,\n\tuseValue,\n} from '@tldraw/editor'\nimport React, { useCallback, useEffect, useRef } from 'react'\nimport { TextHelpers } from './TextHelpers'\n\n/** @public */\nexport function useEditablePlainText(shapeId: TLShapeId, type: string, text?: string) {\n\tconst commonUseEditableTextHandlers = useEditableTextCommon(shapeId)\n\tconst isEditing = commonUseEditableTextHandlers.isEditing\n\tconst editor = useEditor()\n\tconst rInput = useRef<HTMLTextAreaElement>(null)\n\tconst isEmpty = (text || '').trim().length === 0\n\n\tuseEffect(() => {\n\t\tfunction selectAllIfEditing(event: { shapeId: TLShapeId }) {\n\t\t\tif (event.shapeId === shapeId) {\n\t\t\t\trInput.current?.select?.()\n\t\t\t}\n\t\t}\n\n\t\teditor.on('select-all-text', selectAllIfEditing)\n\t\treturn () => {\n\t\t\teditor.off('select-all-text', selectAllIfEditing)\n\t\t}\n\t}, [editor, shapeId, isEditing])\n\n\tuseEffect(() => {\n\t\tif (!isEditing) return\n\n\t\tif (document.activeElement !== rInput.current) {\n\t\t\trInput.current?.focus()\n\t\t}\n\n\t\tif (editor.getInstanceState().isCoarsePointer) {\n\t\t\trInput.current?.select()\n\t\t}\n\n\t\t// XXX(mime): This fixes iOS not showing the caret sometimes.\n\t\t// This \"shakes\" the caret awake.\n\t\tif (tlenv.isSafari) {\n\t\t\trInput.current?.blur()\n\t\t\trInput.current?.focus()\n\t\t}\n\t}, [editor, isEditing])\n\n\t// When the user presses ctrl / meta enter, complete the editing state.\n\tconst handleKeyDown = useCallback(\n\t\t(e: KeyboardEvent) => {\n\t\t\tif (editor.getEditingShapeId() !== shapeId) 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, shapeId]\n\t)\n\n\t// When the text changes, update the text value.\n\tconst handleChange = useCallback(\n\t\t({ plaintext }: { plaintext: string }) => {\n\t\t\tif (editor.getEditingShapeId() !== shapeId) return\n\n\t\t\tconst normalizedPlaintext = TextHelpers.normalizeText(plaintext || '')\n\t\t\teditor.updateShape<TLUnknownShape & { props: { text: string } }>({\n\t\t\t\tid: shapeId,\n\t\t\t\ttype,\n\t\t\t\tprops: { text: normalizedPlaintext },\n\t\t\t})\n\t\t},\n\t\t[editor, shapeId, type]\n\t)\n\n\treturn {\n\t\trInput,\n\t\thandleKeyDown,\n\t\thandleChange,\n\t\tisEmpty,\n\t\t...commonUseEditableTextHandlers,\n\t}\n}\n\n/** @internal */\nexport function useIsReadyForEditing(editor: Editor, shapeId: TLShapeId) {\n\treturn useValue(\n\t\t'isReadyForEditing',\n\t\t() => {\n\t\t\tconst editingShapeId = editor.getEditingShapeId()\n\t\t\treturn (\n\t\t\t\t// something's being editing... and either it's this shape OR this shape is hovered\n\t\t\t\teditingShapeId !== null &&\n\t\t\t\t(editingShapeId === shapeId || editor.getHoveredShapeId() === shapeId)\n\t\t\t)\n\t\t},\n\t\t[editor, shapeId]\n\t)\n}\n\n/** @internal */\nexport function useEditableTextCommon(shapeId: TLShapeId) {\n\tconst editor = useEditor()\n\tconst isEditing = useValue('isEditing', () => editor.getEditingShapeId() === shapeId, [editor])\n\tconst isReadyForEditing = useIsReadyForEditing(editor, shapeId)\n\n\tconst handleInputPointerDown = useCallback(\n\t\t(e: React.PointerEvent) => {\n\t\t\t// N.B. We used to only do this only when isEditing to help\n\t\t\t// prevent an issue where you could drag a selected shape\n\t\t\t// behind another shape. That is addressed now by the CSS logic\n\t\t\t// looking at data-isselectinganything.\n\t\t\t//\n\t\t\t// We still need to follow this logic even if not isEditing\n\t\t\t// because otherwise there is some flakiness in selection.\n\t\t\t// When selecting text, it would sometimes select some text\n\t\t\t// partially if we didn't dispatch/stop below.\n\n\t\t\teditor.dispatch({\n\t\t\t\t...getPointerInfo(e),\n\t\t\t\ttype: 'pointer',\n\t\t\t\tname: 'pointer_down',\n\t\t\t\ttarget: 'shape',\n\t\t\t\tshape: editor.getShape(shapeId)!,\n\t\t\t})\n\n\t\t\tstopEventPropagation(e) // we need to prevent blurring the input\n\t\t},\n\t\t[editor, shapeId]\n\t)\n\n\tconst handlePaste = useCallback(\n\t\t(e: ClipboardEvent | React.ClipboardEvent<HTMLTextAreaElement>) => {\n\t\t\tif (editor.getEditingShapeId() !== shapeId) return\n\t\t\tif (e.clipboardData) {\n\t\t\t\t// find html in the clipboard and look for the tldraw data\n\t\t\t\tconst html = e.clipboardData.getData('text/html')\n\t\t\t\tif (html) {\n\t\t\t\t\tif (html.includes('<div data-tldraw')) {\n\t\t\t\t\t\tpreventDefault(e)\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\t\t[editor, shapeId]\n\t)\n\n\treturn {\n\t\thandleFocus: noop,\n\t\thandleBlur: noop,\n\t\thandleInputPointerDown,\n\t\thandleDoubleClick: stopEventPropagation,\n\t\thandlePaste,\n\t\tisEditing,\n\t\tisReadyForEditing,\n\t}\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -18,7 +18,6 @@ var __copyProps = (to, from, except, desc) => {
|
|
|
18
18
|
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
19
|
var useImageOrVideoAsset_exports = {};
|
|
20
20
|
__export(useImageOrVideoAsset_exports, {
|
|
21
|
-
useAsset: () => useAsset,
|
|
22
21
|
useImageOrVideoAsset: () => useImageOrVideoAsset
|
|
23
22
|
});
|
|
24
23
|
module.exports = __toCommonJS(useImageOrVideoAsset_exports);
|
|
@@ -98,5 +97,4 @@ function resolveAssetUrl(editor, assetId, screenScale, exportInfo, callback) {
|
|
|
98
97
|
callback(url);
|
|
99
98
|
});
|
|
100
99
|
}
|
|
101
|
-
const useAsset = useImageOrVideoAsset;
|
|
102
100
|
//# sourceMappingURL=useImageOrVideoAsset.js.map
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../../src/lib/shapes/shared/useImageOrVideoAsset.ts"],
|
|
4
|
-
"sourcesContent": ["import {\n\tEditor,\n\tSvgExportContext,\n\tTLAssetId,\n\tTLImageAsset,\n\tTLShapeId,\n\tTLVideoAsset,\n\treact,\n\tuseDelaySvgExport,\n\tuseEditor,\n\tuseSvgExportContext,\n} from '@tldraw/editor'\nimport { useEffect, useRef, useState } from 'react'\n\n/**\n * Options for {@link useImageOrVideoAsset}.\n *\n * @public\n */\nexport interface UseImageOrVideoAssetOptions {\n\t/** The asset ID you want a URL for. */\n\tassetId: TLAssetId | null\n\t/**\n\t * The shape the asset is being used for. We won't update the resolved URL while the shape is\n\t * off-screen.\n\t */\n\tshapeId?: TLShapeId\n\t/**\n\t * The width at which the asset will be displayed, in shape-space pixels.\n\t */\n\twidth: number\n}\n\n/**\n * This is a handy helper hook that resolves an asset to an optimized URL for a given shape, or its\n * {@link @tldraw/editor#Editor.createTemporaryAssetPreview | placeholder} if the asset is still\n * uploading. This is used in particular for high-resolution images when you want lower and higher\n * resolution depending on the size of the image on the canvas and the zoom level.\n *\n * For image scaling to work, you need to implement scaled URLs in\n * {@link @tldraw/tlschema#TLAssetStore.resolve}.\n *\n * @public\n */\nexport function useImageOrVideoAsset({ shapeId, assetId, width }: UseImageOrVideoAssetOptions) {\n\tconst editor = useEditor()\n\tconst exportInfo = useSvgExportContext()\n\tconst exportIsReady = useDelaySvgExport()\n\n\t// We use a state to store the result of the asset resolution, and we're going to avoid updating this whenever we can\n\tconst [result, setResult] = useState<{\n\t\tasset: (TLImageAsset | TLVideoAsset) | null\n\t\turl: string | null\n\t}>(() => ({\n\t\tasset: assetId ? (editor.getAsset<TLImageAsset | TLVideoAsset>(assetId) ?? null) : null,\n\t\turl: null as string | null,\n\t}))\n\n\t// A flag for whether we've resolved the asset URL at least once, after which we can debounce\n\tconst didAlreadyResolve = useRef(false)\n\n\t// The last URL that we've seen for the shape\n\tconst previousUrl = useRef<string | null>(null)\n\n\tuseEffect(() => {\n\t\tif (!assetId) return\n\n\t\tlet isCancelled = false\n\t\tlet cancelDebounceFn: (() => void) | undefined\n\n\t\tconst cleanupEffectScheduler = react('update state', () => {\n\t\t\tif (!exportInfo && shapeId && editor.getCulledShapes().has(shapeId)) return\n\n\t\t\t// Get the fresh asset\n\t\t\tconst asset = editor.getAsset<TLImageAsset | TLVideoAsset>(assetId)\n\t\t\tif (!asset) {\n\t\t\t\t// If the asset is deleted, such as when an upload fails, set the URL to null\n\t\t\t\tsetResult((prev) => ({ ...prev, asset: null, url: null }))\n\t\t\t\treturn\n\t\t\t}\n\n\t\t\t// Set initial preview for the shape if it has no source (if it was pasted into a local project as base64)\n\t\t\tif (!asset.props.src) {\n\t\t\t\tconst preview = editor.getTemporaryAssetPreview(asset.id)\n\t\t\t\tif (preview) {\n\t\t\t\t\tif (previousUrl.current !== preview) {\n\t\t\t\t\t\tpreviousUrl.current = preview // just for kicks, let's save the url as the previous URL\n\t\t\t\t\t\tsetResult((prev) => ({ ...prev, isPlaceholder: true, url: preview })) // set the preview as the URL\n\t\t\t\t\t\texportIsReady() // let the SVG export know we're ready for export\n\t\t\t\t\t}\n\t\t\t\t\treturn\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// aside ...we could bail here if the only thing that has changed is the shape has changed from culled to not culled\n\n\t\t\tconst screenScale = exportInfo\n\t\t\t\t? exportInfo.scale * (width / asset.props.w)\n\t\t\t\t: editor.getZoomLevel() * (width / asset.props.w)\n\n\t\t\tfunction resolve(asset: TLImageAsset | TLVideoAsset, url: string | null) {\n\t\t\t\tif (isCancelled) return // don't update if the hook has remounted\n\t\t\t\tif (previousUrl.current === url) return // don't update the state if the url is the same\n\t\t\t\tdidAlreadyResolve.current = true // mark that we've resolved our first image\n\t\t\t\tpreviousUrl.current = url // keep the url around to compare with the next one\n\t\t\t\tsetResult({ asset, url })\n\t\t\t\texportIsReady() // let the SVG export know we're ready for export\n\t\t\t}\n\n\t\t\t// If we already resolved the URL, debounce fetching potentially multiple image variations.\n\t\t\tif (didAlreadyResolve.current) {\n\t\t\t\tlet tick = 0\n\n\t\t\t\tconst resolveAssetAfterAWhile = () => {\n\t\t\t\t\ttick++\n\t\t\t\t\tif (tick > 500 / 16) {\n\t\t\t\t\t\t// debounce for 500ms\n\t\t\t\t\t\tresolveAssetUrl(editor, assetId, screenScale, exportInfo, (url) => resolve(asset, url))\n\t\t\t\t\t\tcancelDebounceFn?.()\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tcancelDebounceFn?.()\n\t\t\t\teditor.on('tick', resolveAssetAfterAWhile)\n\t\t\t\tcancelDebounceFn = () => editor.off('tick', resolveAssetAfterAWhile)\n\t\t\t} else {\n\t\t\t\tresolveAssetUrl(editor, assetId, screenScale, exportInfo, (url) => resolve(asset, url))\n\t\t\t}\n\t\t})\n\n\t\treturn () => {\n\t\t\tcleanupEffectScheduler()\n\t\t\tcancelDebounceFn?.()\n\t\t\tisCancelled = true\n\t\t}\n\t}, [editor, assetId, exportInfo, exportIsReady, shapeId, width])\n\n\treturn result\n}\n\nfunction resolveAssetUrl(\n\teditor: Editor,\n\tassetId: TLAssetId,\n\tscreenScale: number,\n\texportInfo: SvgExportContext | null,\n\tcallback: (url: string | null) => void\n) {\n\teditor\n\t\t.resolveAssetUrl(assetId, {\n\t\t\tscreenScale,\n\t\t\tshouldResolveToOriginal: exportInfo ? exportInfo.pixelRatio === null : false,\n\t\t\tdpr: exportInfo?.pixelRatio ?? undefined,\n\t\t})\n\t\t// There's a weird bug with out debounce function that doesn't\n\t\t// make it work right with async functions, so we use a callback\n\t\t// here instead of returning a promise.\n\t\t.then((url) => {\n\t\t\tcallback(url)\n\t\t})\n}\n
|
|
5
|
-
"mappings": ";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA
|
|
4
|
+
"sourcesContent": ["import {\n\tEditor,\n\tSvgExportContext,\n\tTLAssetId,\n\tTLImageAsset,\n\tTLShapeId,\n\tTLVideoAsset,\n\treact,\n\tuseDelaySvgExport,\n\tuseEditor,\n\tuseSvgExportContext,\n} from '@tldraw/editor'\nimport { useEffect, useRef, useState } from 'react'\n\n/**\n * Options for {@link useImageOrVideoAsset}.\n *\n * @public\n */\nexport interface UseImageOrVideoAssetOptions {\n\t/** The asset ID you want a URL for. */\n\tassetId: TLAssetId | null\n\t/**\n\t * The shape the asset is being used for. We won't update the resolved URL while the shape is\n\t * off-screen.\n\t */\n\tshapeId?: TLShapeId\n\t/**\n\t * The width at which the asset will be displayed, in shape-space pixels.\n\t */\n\twidth: number\n}\n\n/**\n * This is a handy helper hook that resolves an asset to an optimized URL for a given shape, or its\n * {@link @tldraw/editor#Editor.createTemporaryAssetPreview | placeholder} if the asset is still\n * uploading. This is used in particular for high-resolution images when you want lower and higher\n * resolution depending on the size of the image on the canvas and the zoom level.\n *\n * For image scaling to work, you need to implement scaled URLs in\n * {@link @tldraw/tlschema#TLAssetStore.resolve}.\n *\n * @public\n */\nexport function useImageOrVideoAsset({ shapeId, assetId, width }: UseImageOrVideoAssetOptions) {\n\tconst editor = useEditor()\n\tconst exportInfo = useSvgExportContext()\n\tconst exportIsReady = useDelaySvgExport()\n\n\t// We use a state to store the result of the asset resolution, and we're going to avoid updating this whenever we can\n\tconst [result, setResult] = useState<{\n\t\tasset: (TLImageAsset | TLVideoAsset) | null\n\t\turl: string | null\n\t}>(() => ({\n\t\tasset: assetId ? (editor.getAsset<TLImageAsset | TLVideoAsset>(assetId) ?? null) : null,\n\t\turl: null as string | null,\n\t}))\n\n\t// A flag for whether we've resolved the asset URL at least once, after which we can debounce\n\tconst didAlreadyResolve = useRef(false)\n\n\t// The last URL that we've seen for the shape\n\tconst previousUrl = useRef<string | null>(null)\n\n\tuseEffect(() => {\n\t\tif (!assetId) return\n\n\t\tlet isCancelled = false\n\t\tlet cancelDebounceFn: (() => void) | undefined\n\n\t\tconst cleanupEffectScheduler = react('update state', () => {\n\t\t\tif (!exportInfo && shapeId && editor.getCulledShapes().has(shapeId)) return\n\n\t\t\t// Get the fresh asset\n\t\t\tconst asset = editor.getAsset<TLImageAsset | TLVideoAsset>(assetId)\n\t\t\tif (!asset) {\n\t\t\t\t// If the asset is deleted, such as when an upload fails, set the URL to null\n\t\t\t\tsetResult((prev) => ({ ...prev, asset: null, url: null }))\n\t\t\t\treturn\n\t\t\t}\n\n\t\t\t// Set initial preview for the shape if it has no source (if it was pasted into a local project as base64)\n\t\t\tif (!asset.props.src) {\n\t\t\t\tconst preview = editor.getTemporaryAssetPreview(asset.id)\n\t\t\t\tif (preview) {\n\t\t\t\t\tif (previousUrl.current !== preview) {\n\t\t\t\t\t\tpreviousUrl.current = preview // just for kicks, let's save the url as the previous URL\n\t\t\t\t\t\tsetResult((prev) => ({ ...prev, isPlaceholder: true, url: preview })) // set the preview as the URL\n\t\t\t\t\t\texportIsReady() // let the SVG export know we're ready for export\n\t\t\t\t\t}\n\t\t\t\t\treturn\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// aside ...we could bail here if the only thing that has changed is the shape has changed from culled to not culled\n\n\t\t\tconst screenScale = exportInfo\n\t\t\t\t? exportInfo.scale * (width / asset.props.w)\n\t\t\t\t: editor.getZoomLevel() * (width / asset.props.w)\n\n\t\t\tfunction resolve(asset: TLImageAsset | TLVideoAsset, url: string | null) {\n\t\t\t\tif (isCancelled) return // don't update if the hook has remounted\n\t\t\t\tif (previousUrl.current === url) return // don't update the state if the url is the same\n\t\t\t\tdidAlreadyResolve.current = true // mark that we've resolved our first image\n\t\t\t\tpreviousUrl.current = url // keep the url around to compare with the next one\n\t\t\t\tsetResult({ asset, url })\n\t\t\t\texportIsReady() // let the SVG export know we're ready for export\n\t\t\t}\n\n\t\t\t// If we already resolved the URL, debounce fetching potentially multiple image variations.\n\t\t\tif (didAlreadyResolve.current) {\n\t\t\t\tlet tick = 0\n\n\t\t\t\tconst resolveAssetAfterAWhile = () => {\n\t\t\t\t\ttick++\n\t\t\t\t\tif (tick > 500 / 16) {\n\t\t\t\t\t\t// debounce for 500ms\n\t\t\t\t\t\tresolveAssetUrl(editor, assetId, screenScale, exportInfo, (url) => resolve(asset, url))\n\t\t\t\t\t\tcancelDebounceFn?.()\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tcancelDebounceFn?.()\n\t\t\t\teditor.on('tick', resolveAssetAfterAWhile)\n\t\t\t\tcancelDebounceFn = () => editor.off('tick', resolveAssetAfterAWhile)\n\t\t\t} else {\n\t\t\t\tresolveAssetUrl(editor, assetId, screenScale, exportInfo, (url) => resolve(asset, url))\n\t\t\t}\n\t\t})\n\n\t\treturn () => {\n\t\t\tcleanupEffectScheduler()\n\t\t\tcancelDebounceFn?.()\n\t\t\tisCancelled = true\n\t\t}\n\t}, [editor, assetId, exportInfo, exportIsReady, shapeId, width])\n\n\treturn result\n}\n\nfunction resolveAssetUrl(\n\teditor: Editor,\n\tassetId: TLAssetId,\n\tscreenScale: number,\n\texportInfo: SvgExportContext | null,\n\tcallback: (url: string | null) => void\n) {\n\teditor\n\t\t.resolveAssetUrl(assetId, {\n\t\t\tscreenScale,\n\t\t\tshouldResolveToOriginal: exportInfo ? exportInfo.pixelRatio === null : false,\n\t\t\tdpr: exportInfo?.pixelRatio ?? undefined,\n\t\t})\n\t\t// There's a weird bug with out debounce function that doesn't\n\t\t// make it work right with async functions, so we use a callback\n\t\t// here instead of returning a promise.\n\t\t.then((url) => {\n\t\t\tcallback(url)\n\t\t})\n}\n"],
|
|
5
|
+
"mappings": ";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,oBAWO;AACP,mBAA4C;AAgCrC,SAAS,qBAAqB,EAAE,SAAS,SAAS,MAAM,GAAgC;AAC9F,QAAM,aAAS,yBAAU;AACzB,QAAM,iBAAa,mCAAoB;AACvC,QAAM,oBAAgB,iCAAkB;AAGxC,QAAM,CAAC,QAAQ,SAAS,QAAI,uBAGzB,OAAO;AAAA,IACT,OAAO,UAAW,OAAO,SAAsC,OAAO,KAAK,OAAQ;AAAA,IACnF,KAAK;AAAA,EACN,EAAE;AAGF,QAAM,wBAAoB,qBAAO,KAAK;AAGtC,QAAM,kBAAc,qBAAsB,IAAI;AAE9C,8BAAU,MAAM;AACf,QAAI,CAAC,QAAS;AAEd,QAAI,cAAc;AAClB,QAAI;AAEJ,UAAM,6BAAyB,qBAAM,gBAAgB,MAAM;AAC1D,UAAI,CAAC,cAAc,WAAW,OAAO,gBAAgB,EAAE,IAAI,OAAO,EAAG;AAGrE,YAAM,QAAQ,OAAO,SAAsC,OAAO;AAClE,UAAI,CAAC,OAAO;AAEX,kBAAU,CAAC,UAAU,EAAE,GAAG,MAAM,OAAO,MAAM,KAAK,KAAK,EAAE;AACzD;AAAA,MACD;AAGA,UAAI,CAAC,MAAM,MAAM,KAAK;AACrB,cAAM,UAAU,OAAO,yBAAyB,MAAM,EAAE;AACxD,YAAI,SAAS;AACZ,cAAI,YAAY,YAAY,SAAS;AACpC,wBAAY,UAAU;AACtB,sBAAU,CAAC,UAAU,EAAE,GAAG,MAAM,eAAe,MAAM,KAAK,QAAQ,EAAE;AACpE,0BAAc;AAAA,UACf;AACA;AAAA,QACD;AAAA,MACD;AAIA,YAAM,cAAc,aACjB,WAAW,SAAS,QAAQ,MAAM,MAAM,KACxC,OAAO,aAAa,KAAK,QAAQ,MAAM,MAAM;AAEhD,eAAS,QAAQA,QAAoC,KAAoB;AACxE,YAAI,YAAa;AACjB,YAAI,YAAY,YAAY,IAAK;AACjC,0BAAkB,UAAU;AAC5B,oBAAY,UAAU;AACtB,kBAAU,EAAE,OAAAA,QAAO,IAAI,CAAC;AACxB,sBAAc;AAAA,MACf;AAGA,UAAI,kBAAkB,SAAS;AAC9B,YAAI,OAAO;AAEX,cAAM,0BAA0B,MAAM;AACrC;AACA,cAAI,OAAO,MAAM,IAAI;AAEpB,4BAAgB,QAAQ,SAAS,aAAa,YAAY,CAAC,QAAQ,QAAQ,OAAO,GAAG,CAAC;AACtF,+BAAmB;AAAA,UACpB;AAAA,QACD;AAEA,2BAAmB;AACnB,eAAO,GAAG,QAAQ,uBAAuB;AACzC,2BAAmB,MAAM,OAAO,IAAI,QAAQ,uBAAuB;AAAA,MACpE,OAAO;AACN,wBAAgB,QAAQ,SAAS,aAAa,YAAY,CAAC,QAAQ,QAAQ,OAAO,GAAG,CAAC;AAAA,MACvF;AAAA,IACD,CAAC;AAED,WAAO,MAAM;AACZ,6BAAuB;AACvB,yBAAmB;AACnB,oBAAc;AAAA,IACf;AAAA,EACD,GAAG,CAAC,QAAQ,SAAS,YAAY,eAAe,SAAS,KAAK,CAAC;AAE/D,SAAO;AACR;AAEA,SAAS,gBACR,QACA,SACA,aACA,YACA,UACC;AACD,SACE,gBAAgB,SAAS;AAAA,IACzB;AAAA,IACA,yBAAyB,aAAa,WAAW,eAAe,OAAO;AAAA,IACvE,KAAK,YAAY,cAAc;AAAA,EAChC,CAAC,EAIA,KAAK,CAAC,QAAQ;AACd,aAAS,GAAG;AAAA,EACb,CAAC;AACH;",
|
|
6
6
|
"names": ["asset"]
|
|
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": ";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAgIG;AA/HH,oBAsBO;AACP,mBAA4B;AAC5B,sBAGO;AACP,2BAA2C;AAC3C,qCAAsD;AACtD,kCAAqC;AAErC,MAAM,gBAAY;AAAA,EACjB;AAAA,EACA,CAAC,QAAgB,UAAuB;AACvC,WAAO,MAAM,mBAAmB,KAAK;AACrC,WAAO,YAAY,QAAQ,MAAM,KAAK;AAAA,EACvC;AAAA,EACA,EAAE,iBAAiB,CAAC,GAAG,MAAM,EAAE,UAAU,EAAE,MAAM;AAClD;AAQO,MAAM,sBAAsB,wBAAuB;AAAA,EACzD,OAAgB,OAAO;AAAA,EACvB,OAAgB,QAAQ;AAAA,EACxB,OAAgB,aAAa;AAAA,EAEpB,UAA4B;AAAA,IACpC,6BAA6B;AAAA,EAC9B;AAAA,EAEA,kBAAwC;AACvC,WAAO;AAAA,MACN,OAAO;AAAA,MACP,MAAM;AAAA,MACN,GAAG;AAAA,MACH,MAAM;AAAA,MACN,WAAW;AAAA,MACX,UAAU;AAAA,MACV,OAAO;AAAA,MACP,cAAU,0BAAW,EAAE;AAAA,IACxB;AAAA,EACD;AAAA,EAEA,iBAAiB,OAAoB;AACpC,WAAO,UAAU,IAAI,KAAK,QAAQ,MAAM,EAAE;AAAA,EAC3C;AAAA,EAEA,YAAY,OAAoB,MAAsB;AACrD,UAAM,EAAE,MAAM,IAAI,MAAM;AACxB,UAAM,EAAE,OAAO,OAAO,IAAI,KAAK,iBAAiB,KAAK;AACrD,UAAM,UAAU,MAAM,WAAW;AACjC,WAAO,IAAI,0BAAY;AAAA,MACtB,IACE,YAAY,oCACV,CAAC,KAAK,QAAQ,8BACd,KAAK;AAAA,MACT,QACE,SACC,YAAY,oCACV,KAAK,QAAQ,8BAA8B,IAC3C,MACJ;AAAA,MACD,QAAQ,SAAS;AAAA,MACjB,UAAU;AAAA,MACV,SAAS;AAAA,IACV,CAAC;AAAA,EACF;AAAA,EAES,aAAa,OAAoB;AAEzC,eAAO,oCAAqB,KAAK,QAAQ,MAAM,MAAM,UAAU;AAAA,MAC9D,QAAQ,UAAU,MAAM,MAAM,IAAI;AAAA,MAClC,QAAQ;AAAA,MACR,OAAO;AAAA,IACR,CAAC;AAAA,EACF;AAAA,EAES,QAAQ,OAAoB;AACpC,eAAO,6CAA4B,KAAK,QAAQ,MAAM,MAAM,QAAQ;AAAA,EACrE;AAAA,EAES,UAAU;AAClB,WAAO;AAAA,EACR;AAAA,EAES,sBAAsB;AAC9B,WAAO;AAAA,EACR;AAAA;AAAA,EAEA,UAAU,OAAoB;AAC7B,UAAM;AAAA,MACL;AAAA,MACA,OAAO,EAAE,MAAM,MAAM,UAAU,OAAO,OAAO,UAAU;AAAA,IACxD,IAAI;AAEJ,UAAM,EAAE,OAAO,OAAO,IAAI,KAAK,iBAAiB,KAAK;AACrD,UAAM,aAAa,MAAM,OAAO,KAAK,OAAO,uBAAuB;AACnE,UAAM,YAAQ,kDAAqB;AACnC,UAAM,gBAAgB,2BAA2B,EAAE;AAEnD,WACC;AAAA,MAAC;AAAA;AAAA,QACA,SAAS;AAAA,QACT,iBAAgB;AAAA,QAChB,MAAK;AAAA,QACL;AAAA,QACA,UAAU,0CAAW,IAAI;AAAA,QACzB,YAAY,0CAAW;AAAA,QACvB,OAAO;AAAA,QACP,eAAc;AAAA,QACd;AAAA,QACA,gBAAY,6BAAc,OAAO,OAAO,OAAO;AAAA,QAC/C;AAAA,QACA,WAAW;AAAA,QACX,YAAY;AAAA,QACZ,OAAO;AAAA,UACN,WAAW,SAAS,KAAK;AAAA,UACzB,iBAAiB;AAAA,QAClB;AAAA,QACA,MAAI;AAAA,QACJ,WAAW;AAAA;AAAA,IACZ;AAAA,EAEF;AAAA,EAEA,UAAU,OAAoB;AAC7B,UAAM,SAAS,KAAK,OAAO,iBAAiB,KAAK,EAAE;AACnD,UAAM,aAAS,yBAAU;AACzB,QAAI,MAAM,MAAM,YAAY,OAAO,kBAAkB,MAAM,MAAM,GAAI,QAAO;AAC5E,WAAO,4CAAC,UAAK,WAAO,8BAAe,OAAO,KAAK,GAAG,YAAQ,8BAAe,OAAO,MAAM,GAAG;AAAA,EAC1F;AAAA,EAES,MAAM,OAAoB,KAAuB;AACzD,UAAM,SAAS,KAAK,OAAO,iBAAiB,KAAK,EAAE;AACnD,UAAM,QAAQ,OAAO,SAAS,MAAM,MAAM,SAAS;AACnD,UAAM,SAAS,OAAO,UAAU,MAAM,MAAM,SAAS;AAErD,UAAM,YAAQ,oCAAqB,GAAG;AAEtC,UAAM,eAAe,IAAI,kBAAI,GAAG,GAAG,OAAO,MAAM;AAChD,WACC;AAAA,MAAC;AAAA;AAAA,QACA,UAAU,0CAAW,MAAM,MAAM,IAAI;AAAA,QACrC,MAAM,MAAM,MAAM;AAAA,QAClB,OAAO,MAAM,MAAM;AAAA,QACnB,eAAc;AAAA,QACd,UAAU,MAAM,MAAM;AAAA,QACtB,gBAAY,6BAAc,OAAO,MAAM,MAAM,OAAO,OAAO;AAAA,QAC3D,QAAQ;AAAA,QACR,SAAS;AAAA;AAAA,IACV;AAAA,EAEF;AAAA,EAES,SAAS,OAAoB,MAAiC;AACtE,UAAM,EAAE,UAAU,eAAe,cAAc,QAAQ,OAAO,IAAI;AAElE,QAAI,KAAK,SAAS,iBAAkB,WAAW,WAAW,WAAW,QAAS;AAC7E,aAAO;AAAA,QACN,IAAI,MAAM;AAAA,QACV,MAAM,MAAM;AAAA,QACZ,OAAG,4BAAa,OAAO,IAAI;AAAA,MAC5B;AAAA,IACD,OAAO;AACN,YAAM,YAAY,KAAK,IAAI,GAAG,KAAK,IAAI,cAAc,QAAQ,MAAM,CAAC;AACpE,YAAM,EAAE,GAAG,EAAE,IACZ,SAAS,IAAI,kBAAI,IAAI,UAAU,kBAAI,UAAU,MAAM,QAAQ,EAAE,IAAI,SAAS,CAAC,IAAI;AAEhF,aAAO;AAAA,QACN,IAAI,MAAM;AAAA,QACV,MAAM,MAAM;AAAA,QACZ;AAAA,QACA;AAAA,QACA,OAAO;AAAA,UACN,GAAG,YAAY,aAAa,MAAM;AAAA,UAClC,UAAU;AAAA,QACX;AAAA,MACD;AAAA,IACD;AAAA,EACD;AAAA,EAES,UAAU,OAAoB;AAEtC,UAAM,kBAAc,6CAA4B,KAAK,QAAQ,MAAM,MAAM,QAAQ,EAAE,QAAQ;AAE3F,QAAI,YAAY,WAAW,GAAG;AAC7B,WAAK,OAAO,aAAa,CAAC,MAAM,EAAE,CAAC;AAAA,IACpC;AAAA,EACD;AAAA,EAES,eAAe,MAAmB,MAAmB;AAC7D,QAAI,CAAC,KAAK,MAAM,SAAU;AAE1B,UAAM,iBACL,KAAK,MAAM,SAAS,KAAK,MAAM,QAC/B,KAAK,MAAM,cAAc,KAAK,MAAM,aACpC,KAAK,MAAM,SAAS,KAAK,MAAM,QAC9B,KAAK,MAAM,UAAU,KAAK,KAAK,MAAM,UAAU;AAEjD,UAAM,gBAAgB,KAAC,uBAAQ,KAAK,MAAM,UAAU,KAAK,MAAM,QAAQ;AAGvE,QAAI,CAAC,kBAAkB,CAAC,cAAe;AAGvC,UAAM,UAAU,KAAK,iBAAiB,IAAI;AAG1C,UAAM,UAAU,YAAY,KAAK,QAAQ,KAAK,KAAK;AAEnD,UAAM,KAAK,QAAQ,QAAQ,KAAK,MAAM;AACtC,UAAM,KAAK,QAAQ,SAAS,KAAK,MAAM;AACvC,UAAM,KAAK,QAAQ,QAAQ,KAAK,MAAM;AACtC,UAAM,KAAK,QAAQ,SAAS,KAAK,MAAM;AAEvC,QAAI;AAEJ,YAAQ,KAAK,MAAM,WAAW;AAAA,MAC7B,KAAK,UAAU;AACd,gBAAQ,IAAI,mBAAK,KAAK,MAAM,GAAG,gBAAgB,KAAK,KAAK,MAAM,CAAC;AAChE;AAAA,MACD;AAAA,MACA,KAAK,OAAO;AACX,gBAAQ,IAAI,kBAAI,KAAK,IAAI,gBAAgB,KAAK,KAAK,MAAM,CAAC;AAC1D;AAAA,MACD;AAAA,MACA,SAAS;AACR,YAAI,cAAe;AACnB,gBAAQ,IAAI,kBAAI,IAAI,KAAK,MAAM,CAAC;AAChC;AAAA,MACD;AAAA,IACD;AAEA,QAAI,OAAO;AAEV,YAAM,IAAI,KAAK,QAAQ;AACvB,YAAM,EAAE,GAAG,EAAE,IAAI;AACjB,aAAO;AAAA,QACN,GAAG;AAAA,QACH,GAAG,IAAI,MAAM;AAAA,QACb,GAAG,IAAI,MAAM;AAAA,QACb,OAAO,EAAE,GAAG,KAAK,OAAO,GAAG,GAAG;AAAA,MAC/B;AAAA,IACD,OAAO;AACN,aAAO;AAAA,QACN,GAAG;AAAA,QACH,OAAO,EAAE,GAAG,KAAK,OAAO,GAAG,GAAG;AAAA,MAC/B;AAAA,IACD;AAAA,EACD;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AA2BD;AAEA,SAAS,YAAY,QAAgB,OAA6B;AACjE,QAAM,EAAE,MAAM,UAAU,MAAM,EAAE,IAAI;AAEpC,QAAM,WAAW;AACjB,QAAM,WAAW,0CAAW,IAAI;AAEhC,QAAM,kBAAkB,MAAM,WAAW,OAAO,KAAK,IAAI,UAAU,KAAK,MAAM,CAAC,CAAC;AAEhF,QAAM,WAAO,sDAAqC,QAAQ,QAAQ;AAClE,QAAM,SAAS,OAAO,YAAY,YAAY,MAAM;AAAA,IACnD,GAAG;AAAA,IACH,YAAY,6CAAc,IAAI;AAAA,IAC9B;AAAA,IACA,UAAU;AAAA,EACX,CAAC;AAKD,SAAO;AAAA,IACN,OAAO,mBAAmB,KAAK,IAAI,UAAU,OAAO,IAAI,CAAC;AAAA,IACzD,QAAQ,KAAK,IAAI,UAAU,OAAO,CAAC;AAAA,EACpC;AACD;AAEA,SAAS,2BAA2B,IAAe;AAClD,QAAM,aAAS,yBAAU;AAEzB,aAAO;AAAA,IACN,CAAC,MAAqB;AACrB,UAAI,OAAO,kBAAkB,MAAM,GAAI;AAEvC,cAAQ,EAAE,KAAK;AAAA,QACd,KAAK,SAAS;AACb,cAAI,EAAE,WAAW,EAAE,SAAS;AAC3B,mBAAO,SAAS;AAAA,UACjB;AACA;AAAA,QACD;AAAA,MACD;AAAA,IACD;AAAA,IACA,CAAC,QAAQ,EAAE;AAAA,EACZ;AACD;",
|
|
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
|
}
|