tldraw 4.1.0-canary.9f9255bd7a83 → 4.1.0-canary.a152954244d2
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 +46 -12
- package/dist-cjs/index.js +6 -1
- package/dist-cjs/index.js.map +2 -2
- package/dist-cjs/lib/canvas/TldrawCropHandles.js +1 -1
- package/dist-cjs/lib/canvas/TldrawScribble.js +1 -1
- package/dist-cjs/lib/canvas/TldrawSelectionForeground.js +1 -1
- package/dist-cjs/lib/defaultEmbedDefinitions.js +25 -30
- package/dist-cjs/lib/defaultEmbedDefinitions.js.map +2 -2
- package/dist-cjs/lib/defaultExternalContentHandlers.js +10 -33
- package/dist-cjs/lib/defaultExternalContentHandlers.js.map +2 -2
- package/dist-cjs/lib/shapes/arrow/ArrowShapeUtil.js +3 -0
- package/dist-cjs/lib/shapes/arrow/ArrowShapeUtil.js.map +2 -2
- package/dist-cjs/lib/shapes/bookmark/BookmarkShapeUtil.js +44 -102
- package/dist-cjs/lib/shapes/bookmark/BookmarkShapeUtil.js.map +2 -2
- package/dist-cjs/lib/shapes/bookmark/bookmarks.js +138 -0
- package/dist-cjs/lib/shapes/bookmark/bookmarks.js.map +7 -0
- package/dist-cjs/lib/shapes/embed/EmbedShapeUtil.js +25 -3
- package/dist-cjs/lib/shapes/embed/EmbedShapeUtil.js.map +2 -2
- package/dist-cjs/lib/shapes/frame/FrameShapeUtil.js +1 -1
- package/dist-cjs/lib/shapes/image/ImageShapeUtil.js +1 -1
- package/dist-cjs/lib/shapes/line/LineShapeUtil.js +3 -0
- package/dist-cjs/lib/shapes/line/LineShapeUtil.js.map +2 -2
- package/dist-cjs/lib/shapes/shared/HyperlinkButton.js +1 -1
- package/dist-cjs/lib/shapes/shared/PlainTextLabel.js +1 -1
- package/dist-cjs/lib/shapes/shared/RichTextLabel.js +1 -1
- package/dist-cjs/lib/shapes/shared/ShapeFill.js +1 -1
- package/dist-cjs/lib/shapes/text/PlainTextArea.js +1 -1
- package/dist-cjs/lib/shapes/text/RichTextArea.js +1 -1
- package/dist-cjs/lib/shapes/video/VideoShapeUtil.js +1 -1
- package/dist-cjs/lib/tools/SelectTool/childStates/Crop/children/Cropping.js +20 -4
- package/dist-cjs/lib/tools/SelectTool/childStates/Crop/children/Cropping.js.map +2 -2
- package/dist-cjs/lib/tools/SelectTool/childStates/Crop/children/Idle.js +1 -1
- package/dist-cjs/lib/tools/SelectTool/childStates/Crop/children/Idle.js.map +2 -2
- package/dist-cjs/lib/tools/SelectTool/childStates/Crop/children/PointingCropHandle.js +23 -11
- package/dist-cjs/lib/tools/SelectTool/childStates/Crop/children/PointingCropHandle.js.map +2 -2
- package/dist-cjs/lib/tools/SelectTool/childStates/DraggingHandle.js +27 -6
- package/dist-cjs/lib/tools/SelectTool/childStates/DraggingHandle.js.map +2 -2
- package/dist-cjs/lib/tools/SelectTool/childStates/Idle.js +1 -1
- package/dist-cjs/lib/tools/SelectTool/childStates/Idle.js.map +2 -2
- package/dist-cjs/lib/tools/SelectTool/childStates/PointingArrowLabel.js +21 -9
- package/dist-cjs/lib/tools/SelectTool/childStates/PointingArrowLabel.js.map +2 -2
- package/dist-cjs/lib/tools/SelectTool/childStates/PointingResizeHandle.js +24 -8
- package/dist-cjs/lib/tools/SelectTool/childStates/PointingResizeHandle.js.map +2 -2
- package/dist-cjs/lib/tools/SelectTool/childStates/PointingRotateHandle.js +21 -9
- package/dist-cjs/lib/tools/SelectTool/childStates/PointingRotateHandle.js.map +2 -2
- package/dist-cjs/lib/tools/SelectTool/childStates/Resizing.js +23 -8
- package/dist-cjs/lib/tools/SelectTool/childStates/Resizing.js.map +2 -2
- package/dist-cjs/lib/tools/SelectTool/childStates/Rotating.js +21 -9
- package/dist-cjs/lib/tools/SelectTool/childStates/Rotating.js.map +2 -2
- package/dist-cjs/lib/tools/SelectTool/childStates/Translating.js +26 -11
- package/dist-cjs/lib/tools/SelectTool/childStates/Translating.js.map +2 -2
- package/dist-cjs/lib/ui/TldrawUi.js +2 -2
- package/dist-cjs/lib/ui/components/DebugMenu/DefaultDebugMenuContent.js +3 -3
- package/dist-cjs/lib/ui/components/DebugMenu/DefaultDebugMenuContent.js.map +1 -1
- package/dist-cjs/lib/ui/components/KeyboardShortcutsDialog/DefaultKeyboardShortcutsDialog.js +1 -1
- package/dist-cjs/lib/ui/components/Minimap/DefaultMinimap.js +1 -1
- package/dist-cjs/lib/ui/components/Minimap/MinimapManager.js +5 -0
- package/dist-cjs/lib/ui/components/Minimap/MinimapManager.js.map +2 -2
- package/dist-cjs/lib/ui/components/OfflineIndicator/OfflineIndicator.js +1 -1
- package/dist-cjs/lib/ui/components/SharePanel/PeopleMenu.js +6 -2
- package/dist-cjs/lib/ui/components/SharePanel/PeopleMenu.js.map +2 -2
- package/dist-cjs/lib/ui/components/SharePanel/UserPresenceColorPicker.js +1 -1
- package/dist-cjs/lib/ui/components/StylePanel/DefaultStylePanel.js +1 -1
- package/dist-cjs/lib/ui/components/StylePanel/DefaultStylePanelContent.js +64 -56
- package/dist-cjs/lib/ui/components/StylePanel/DefaultStylePanelContent.js.map +2 -2
- package/dist-cjs/lib/ui/components/StylePanel/StylePanelButtonPicker.js +54 -47
- package/dist-cjs/lib/ui/components/StylePanel/StylePanelButtonPicker.js.map +3 -3
- package/dist-cjs/lib/ui/components/StylePanel/StylePanelDoubleDropdownPicker.js +63 -56
- package/dist-cjs/lib/ui/components/StylePanel/StylePanelDoubleDropdownPicker.js.map +2 -2
- package/dist-cjs/lib/ui/components/StylePanel/StylePanelDropdownPicker.js +13 -6
- package/dist-cjs/lib/ui/components/StylePanel/StylePanelDropdownPicker.js.map +2 -2
- package/dist-cjs/lib/ui/components/Toolbar/DefaultToolbar.js +1 -1
- package/dist-cjs/lib/ui/components/Toolbar/OverflowingToolbar.js +1 -1
- package/dist-cjs/lib/ui/components/Toolbar/ToggleToolLockedButton.js +1 -1
- package/dist-cjs/lib/ui/components/menu-items.js +2 -2
- package/dist-cjs/lib/ui/components/menu-items.js.map +1 -1
- package/dist-cjs/lib/ui/components/primitives/Button/TldrawUiButton.js +2 -2
- package/dist-cjs/lib/ui/components/primitives/TldrawUiContextualToolbar.js +1 -1
- package/dist-cjs/lib/ui/components/primitives/TldrawUiDialog.js +1 -1
- package/dist-cjs/lib/ui/components/primitives/TldrawUiDropdownMenu.js +1 -1
- package/dist-cjs/lib/ui/components/primitives/TldrawUiIcon.js +1 -1
- package/dist-cjs/lib/ui/components/primitives/TldrawUiInput.js +2 -2
- package/dist-cjs/lib/ui/components/primitives/TldrawUiPopover.js +2 -2
- package/dist-cjs/lib/ui/components/primitives/TldrawUiSlider.js +1 -1
- package/dist-cjs/lib/ui/components/primitives/TldrawUiToolbar.js +2 -2
- package/dist-cjs/lib/ui/components/primitives/TldrawUiTooltip.js +1 -1
- package/dist-cjs/lib/ui/components/primitives/layout.js +1 -1
- package/dist-cjs/lib/ui/components/primitives/menus/TldrawUiMenuGroup.js +1 -1
- package/dist-cjs/lib/ui/context/actions.js +24 -30
- package/dist-cjs/lib/ui/context/actions.js.map +2 -2
- package/dist-cjs/lib/ui/context/breakpoints.js +1 -1
- package/dist-cjs/lib/ui/context/events.js +1 -1
- package/dist-cjs/lib/ui/hooks/useClipboardEvents.js +1 -1
- package/dist-cjs/lib/ui/hooks/useEditorEvents.js +1 -1
- package/dist-cjs/lib/ui/hooks/useEditorEvents.js.map +1 -1
- package/dist-cjs/lib/ui/hooks/useKeyboardShortcuts.js +1 -1
- package/dist-cjs/lib/ui/hooks/useLocalStorageState.js +1 -1
- package/dist-cjs/lib/ui/hooks/useTools.js +1 -1
- package/dist-cjs/lib/ui/hooks/useTranslation/defaultTranslation.js +4 -4
- package/dist-cjs/lib/ui/hooks/useTranslation/defaultTranslation.js.map +1 -1
- package/dist-cjs/lib/ui/hooks/useTranslation/useTranslation.js +1 -1
- package/dist-cjs/lib/ui/version.js +3 -3
- package/dist-cjs/lib/ui/version.js.map +1 -1
- package/dist-cjs/lib/utils/text/richText.js +4 -4
- package/dist-esm/index.d.mts +46 -12
- package/dist-esm/index.mjs +12 -4
- package/dist-esm/index.mjs.map +2 -2
- package/dist-esm/lib/defaultEmbedDefinitions.mjs +25 -30
- package/dist-esm/lib/defaultEmbedDefinitions.mjs.map +2 -2
- package/dist-esm/lib/defaultExternalContentHandlers.mjs +10 -33
- package/dist-esm/lib/defaultExternalContentHandlers.mjs.map +2 -2
- package/dist-esm/lib/shapes/arrow/ArrowShapeUtil.mjs +3 -0
- package/dist-esm/lib/shapes/arrow/ArrowShapeUtil.mjs.map +2 -2
- package/dist-esm/lib/shapes/bookmark/BookmarkShapeUtil.mjs +46 -101
- package/dist-esm/lib/shapes/bookmark/BookmarkShapeUtil.mjs.map +2 -2
- package/dist-esm/lib/shapes/bookmark/bookmarks.mjs +124 -0
- package/dist-esm/lib/shapes/bookmark/bookmarks.mjs.map +7 -0
- package/dist-esm/lib/shapes/embed/EmbedShapeUtil.mjs +26 -3
- package/dist-esm/lib/shapes/embed/EmbedShapeUtil.mjs.map +2 -2
- package/dist-esm/lib/shapes/line/LineShapeUtil.mjs +3 -0
- package/dist-esm/lib/shapes/line/LineShapeUtil.mjs.map +2 -2
- package/dist-esm/lib/tools/SelectTool/childStates/Crop/children/Cropping.mjs +20 -4
- package/dist-esm/lib/tools/SelectTool/childStates/Crop/children/Cropping.mjs.map +2 -2
- package/dist-esm/lib/tools/SelectTool/childStates/Crop/children/Idle.mjs +1 -1
- package/dist-esm/lib/tools/SelectTool/childStates/Crop/children/Idle.mjs.map +2 -2
- package/dist-esm/lib/tools/SelectTool/childStates/Crop/children/PointingCropHandle.mjs +23 -11
- package/dist-esm/lib/tools/SelectTool/childStates/Crop/children/PointingCropHandle.mjs.map +2 -2
- package/dist-esm/lib/tools/SelectTool/childStates/DraggingHandle.mjs +29 -7
- package/dist-esm/lib/tools/SelectTool/childStates/DraggingHandle.mjs.map +2 -2
- package/dist-esm/lib/tools/SelectTool/childStates/Idle.mjs +1 -1
- package/dist-esm/lib/tools/SelectTool/childStates/Idle.mjs.map +2 -2
- package/dist-esm/lib/tools/SelectTool/childStates/PointingArrowLabel.mjs +21 -9
- package/dist-esm/lib/tools/SelectTool/childStates/PointingArrowLabel.mjs.map +2 -2
- package/dist-esm/lib/tools/SelectTool/childStates/PointingResizeHandle.mjs +24 -8
- package/dist-esm/lib/tools/SelectTool/childStates/PointingResizeHandle.mjs.map +2 -2
- package/dist-esm/lib/tools/SelectTool/childStates/PointingRotateHandle.mjs +21 -9
- package/dist-esm/lib/tools/SelectTool/childStates/PointingRotateHandle.mjs.map +2 -2
- package/dist-esm/lib/tools/SelectTool/childStates/Resizing.mjs +23 -8
- package/dist-esm/lib/tools/SelectTool/childStates/Resizing.mjs.map +2 -2
- package/dist-esm/lib/tools/SelectTool/childStates/Rotating.mjs +21 -9
- package/dist-esm/lib/tools/SelectTool/childStates/Rotating.mjs.map +2 -2
- package/dist-esm/lib/tools/SelectTool/childStates/Translating.mjs +26 -11
- package/dist-esm/lib/tools/SelectTool/childStates/Translating.mjs.map +2 -2
- package/dist-esm/lib/ui/components/DebugMenu/DefaultDebugMenuContent.mjs +2 -2
- package/dist-esm/lib/ui/components/DebugMenu/DefaultDebugMenuContent.mjs.map +1 -1
- package/dist-esm/lib/ui/components/Minimap/MinimapManager.mjs +5 -0
- package/dist-esm/lib/ui/components/Minimap/MinimapManager.mjs.map +2 -2
- package/dist-esm/lib/ui/components/SharePanel/PeopleMenu.mjs +6 -2
- package/dist-esm/lib/ui/components/SharePanel/PeopleMenu.mjs.map +2 -2
- package/dist-esm/lib/ui/components/StylePanel/DefaultStylePanelContent.mjs +68 -57
- package/dist-esm/lib/ui/components/StylePanel/DefaultStylePanelContent.mjs.map +2 -2
- package/dist-esm/lib/ui/components/StylePanel/StylePanelButtonPicker.mjs +54 -47
- package/dist-esm/lib/ui/components/StylePanel/StylePanelButtonPicker.mjs.map +3 -3
- package/dist-esm/lib/ui/components/StylePanel/StylePanelDoubleDropdownPicker.mjs +63 -56
- package/dist-esm/lib/ui/components/StylePanel/StylePanelDoubleDropdownPicker.mjs.map +2 -2
- package/dist-esm/lib/ui/components/StylePanel/StylePanelDropdownPicker.mjs +12 -5
- package/dist-esm/lib/ui/components/StylePanel/StylePanelDropdownPicker.mjs.map +2 -2
- package/dist-esm/lib/ui/components/menu-items.mjs +2 -2
- package/dist-esm/lib/ui/components/menu-items.mjs.map +1 -1
- package/dist-esm/lib/ui/context/actions.mjs +23 -29
- package/dist-esm/lib/ui/context/actions.mjs.map +2 -2
- package/dist-esm/lib/ui/hooks/useEditorEvents.mjs +1 -1
- package/dist-esm/lib/ui/hooks/useEditorEvents.mjs.map +1 -1
- package/dist-esm/lib/ui/hooks/useTranslation/defaultTranslation.mjs +4 -4
- package/dist-esm/lib/ui/hooks/useTranslation/defaultTranslation.mjs.map +1 -1
- package/dist-esm/lib/ui/version.mjs +3 -3
- package/dist-esm/lib/ui/version.mjs.map +1 -1
- package/package.json +11 -11
- package/src/index.ts +4 -0
- package/src/lib/defaultEmbedDefinitions.ts +20 -24
- package/src/lib/defaultExternalContentHandlers.ts +12 -37
- package/src/lib/shapes/arrow/ArrowShapeUtil.tsx +3 -0
- package/src/lib/shapes/bookmark/BookmarkShapeUtil.tsx +51 -135
- package/src/lib/shapes/bookmark/bookmarks.ts +170 -0
- package/src/lib/shapes/embed/EmbedShapeUtil.tsx +28 -2
- package/src/lib/shapes/line/LineShapeUtil.tsx +3 -0
- package/src/lib/shapes/text/TextShapeTool.test.ts +74 -0
- package/src/lib/tools/SelectTool/childStates/Crop/children/Cropping.ts +23 -6
- package/src/lib/tools/SelectTool/childStates/Crop/children/Idle.ts +1 -1
- package/src/lib/tools/SelectTool/childStates/Crop/children/PointingCropHandle.ts +24 -12
- package/src/lib/tools/SelectTool/childStates/DraggingHandle.tsx +34 -11
- package/src/lib/tools/SelectTool/childStates/Idle.ts +1 -1
- package/src/lib/tools/SelectTool/childStates/PointingArrowLabel.ts +23 -11
- package/src/lib/tools/SelectTool/childStates/PointingResizeHandle.ts +26 -9
- package/src/lib/tools/SelectTool/childStates/PointingRotateHandle.ts +23 -10
- package/src/lib/tools/SelectTool/childStates/Resizing.ts +24 -9
- package/src/lib/tools/SelectTool/childStates/Rotating.ts +27 -11
- package/src/lib/tools/SelectTool/childStates/Translating.ts +28 -12
- package/src/lib/ui/components/DebugMenu/DefaultDebugMenuContent.tsx +2 -2
- package/src/lib/ui/components/Minimap/MinimapManager.ts +6 -0
- package/src/lib/ui/components/SharePanel/PeopleMenu.tsx +6 -2
- package/src/lib/ui/components/StylePanel/DefaultStylePanelContent.tsx +60 -49
- package/src/lib/ui/components/StylePanel/StylePanelButtonPicker.tsx +70 -53
- package/src/lib/ui/components/StylePanel/StylePanelDoubleDropdownPicker.tsx +105 -90
- package/src/lib/ui/components/StylePanel/StylePanelDropdownPicker.tsx +72 -51
- package/src/lib/ui/components/menu-items.tsx +2 -2
- package/src/lib/ui/context/actions.tsx +27 -31
- package/src/lib/ui/hooks/useEditorEvents.ts +1 -1
- package/src/lib/ui/hooks/useTranslation/defaultTranslation.ts +4 -4
- package/src/lib/ui/version.ts +3 -3
- package/src/lib/utils/embeds/embeds.test.ts +16 -34
- package/src/test/SelectTool.test.ts +251 -0
- package/src/test/bookmark-shapes.test.ts +129 -7
- package/src/test/customSnapping.test.tsx +55 -11
- package/tldraw.css +7 -2
|
@@ -482,11 +482,11 @@ export function MoveToPageMenu() {
|
|
|
482
482
|
|
|
483
483
|
if (toPage) {
|
|
484
484
|
addToast({
|
|
485
|
-
title: 'Changed
|
|
485
|
+
title: 'Changed page',
|
|
486
486
|
description: `Moved to ${toPage.name}.`,
|
|
487
487
|
actions: [
|
|
488
488
|
{
|
|
489
|
-
label: 'Go
|
|
489
|
+
label: 'Go back',
|
|
490
490
|
type: 'primary',
|
|
491
491
|
onClick: () => {
|
|
492
492
|
editor.markHistoryStoppingPoint('change-page')
|
|
@@ -5,6 +5,7 @@ import {
|
|
|
5
5
|
Editor,
|
|
6
6
|
HALF_PI,
|
|
7
7
|
PageRecordType,
|
|
8
|
+
Result,
|
|
8
9
|
TLBookmarkShape,
|
|
9
10
|
TLEmbedShape,
|
|
10
11
|
TLFrameShape,
|
|
@@ -24,6 +25,7 @@ import {
|
|
|
24
25
|
useMaybeEditor,
|
|
25
26
|
} from '@tldraw/editor'
|
|
26
27
|
import * as React from 'react'
|
|
28
|
+
import { createBookmarkFromUrl } from '../../shapes/bookmark/bookmarks'
|
|
27
29
|
import { fitFrameToContent, removeFrame } from '../../utils/frames/frames'
|
|
28
30
|
import { generateShapeAnnouncementMessage } from '../components/A11y'
|
|
29
31
|
import { EditLinkDialog } from '../components/EditLinkDialog'
|
|
@@ -387,45 +389,39 @@ export function ActionsProvider({ overrides, children }: ActionsProviderProps) {
|
|
|
387
389
|
{
|
|
388
390
|
id: 'convert-to-bookmark',
|
|
389
391
|
label: 'action.convert-to-bookmark',
|
|
390
|
-
onSelect(source) {
|
|
392
|
+
async onSelect(source) {
|
|
391
393
|
if (!canApplySelectionAction()) return
|
|
392
394
|
if (mustGoBackToSelectToolFirst()) return
|
|
393
395
|
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
const shapes = editor.getSelectedShapes()
|
|
396
|
+
trackEvent('convert-to-bookmark', { source })
|
|
397
|
+
const shapes = editor.getSelectedShapes()
|
|
397
398
|
|
|
398
|
-
|
|
399
|
-
const deleteList: TLShapeId[] = []
|
|
400
|
-
for (const shape of shapes) {
|
|
401
|
-
if (!shape || !editor.isShapeOfType<TLEmbedShape>(shape, 'embed') || !shape.props.url)
|
|
402
|
-
continue
|
|
399
|
+
const markId = editor.markHistoryStoppingPoint('convert shapes to bookmark')
|
|
403
400
|
|
|
404
|
-
|
|
405
|
-
newPos.rot(-shape.rotation)
|
|
406
|
-
newPos.add(new Vec(shape.props.w / 2 - 300 / 2, shape.props.h / 2 - 320 / 2)) // see bookmark shape util
|
|
407
|
-
newPos.rot(shape.rotation)
|
|
408
|
-
const partial: TLShapePartial<TLBookmarkShape> = {
|
|
409
|
-
id: createShapeId(),
|
|
410
|
-
type: 'bookmark',
|
|
411
|
-
rotation: shape.rotation,
|
|
412
|
-
x: newPos.x,
|
|
413
|
-
y: newPos.y,
|
|
414
|
-
opacity: 1,
|
|
415
|
-
props: {
|
|
416
|
-
url: shape.props.url,
|
|
417
|
-
},
|
|
418
|
-
}
|
|
401
|
+
const creationPromises: Promise<Result<any, any>>[] = []
|
|
419
402
|
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
403
|
+
for (const shape of shapes) {
|
|
404
|
+
if (!shape || !editor.isShapeOfType<TLEmbedShape>(shape, 'embed') || !shape.props.url)
|
|
405
|
+
continue
|
|
423
406
|
|
|
424
|
-
editor.
|
|
407
|
+
const center = editor.getShapePageBounds(shape)?.center
|
|
425
408
|
|
|
426
|
-
|
|
427
|
-
editor.deleteShapes(
|
|
428
|
-
|
|
409
|
+
if (!center) continue
|
|
410
|
+
editor.deleteShapes([shape.id])
|
|
411
|
+
|
|
412
|
+
creationPromises.push(
|
|
413
|
+
createBookmarkFromUrl(editor, { url: shape.props.url, center }).then((res) => {
|
|
414
|
+
if (!res.ok) {
|
|
415
|
+
throw new Error(res.error)
|
|
416
|
+
}
|
|
417
|
+
return res
|
|
418
|
+
})
|
|
419
|
+
)
|
|
420
|
+
}
|
|
421
|
+
|
|
422
|
+
await Promise.all(creationPromises).catch((error) => {
|
|
423
|
+
editor.bailToMark(markId)
|
|
424
|
+
console.error(error)
|
|
429
425
|
})
|
|
430
426
|
},
|
|
431
427
|
},
|
|
@@ -10,7 +10,7 @@ export function useEditorEvents() {
|
|
|
10
10
|
useEffect(() => {
|
|
11
11
|
function handleMaxShapes({ name, count }: { name: string; pageId: string; count: number }) {
|
|
12
12
|
addToast({
|
|
13
|
-
title: 'Maximum
|
|
13
|
+
title: 'Maximum shapes reached',
|
|
14
14
|
description: `You've reached the maximum number of shapes allowed on ${name} (${count}). Please delete some shapes or move to a different page to continue.`,
|
|
15
15
|
severity: 'warning',
|
|
16
16
|
})
|
|
@@ -8,8 +8,8 @@ export const DEFAULT_TRANSLATION = {
|
|
|
8
8
|
'action.toggle-auto-none': 'Auto',
|
|
9
9
|
'action.toggle-mouse': 'Mouse',
|
|
10
10
|
'action.toggle-trackpad': 'Trackpad',
|
|
11
|
-
'action.convert-to-bookmark': 'Convert to
|
|
12
|
-
'action.convert-to-embed': 'Convert to
|
|
11
|
+
'action.convert-to-bookmark': 'Convert to bookmark',
|
|
12
|
+
'action.convert-to-embed': 'Convert to embed',
|
|
13
13
|
'action.open-embed-link': 'Open link',
|
|
14
14
|
'action.align-bottom': 'Align bottom',
|
|
15
15
|
'action.align-center-horizontal': 'Align horizontally',
|
|
@@ -94,7 +94,7 @@ export const DEFAULT_TRANSLATION = {
|
|
|
94
94
|
'action.toggle-paste-at-cursor.menu': 'Paste at cursor',
|
|
95
95
|
'action.toggle-paste-at-cursor': 'Toggle paste at cursor',
|
|
96
96
|
'action.toggle-wrap-mode.menu': 'Select on wrap',
|
|
97
|
-
'action.toggle-wrap-mode': 'Toggle
|
|
97
|
+
'action.toggle-wrap-mode': 'Toggle select on wrap',
|
|
98
98
|
'action.toggle-reduce-motion.menu': 'Reduce motion',
|
|
99
99
|
'action.toggle-reduce-motion': 'Toggle reduce motion',
|
|
100
100
|
'action.toggle-keyboard-shortcuts.menu': 'Enable keyboard shortcuts',
|
|
@@ -364,7 +364,7 @@ export const DEFAULT_TRANSLATION = {
|
|
|
364
364
|
'people-menu.change-color': 'Change color',
|
|
365
365
|
'people-menu.follow': 'Following',
|
|
366
366
|
'people-menu.following': 'Following',
|
|
367
|
-
'people-menu.leading': 'Following
|
|
367
|
+
'people-menu.leading': 'Following you',
|
|
368
368
|
'people-menu.user': '(You)',
|
|
369
369
|
'people-menu.invite': 'Invite others',
|
|
370
370
|
'people-menu.anonymous-user': 'New user',
|
package/src/lib/ui/version.ts
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
// This file is automatically generated by internal/scripts/refresh-assets.ts.
|
|
2
2
|
// Do not edit manually. Or do, I'm a comment, not a cop.
|
|
3
3
|
|
|
4
|
-
export const version = '4.1.0-canary.
|
|
4
|
+
export const version = '4.1.0-canary.a152954244d2'
|
|
5
5
|
export const publishDates = {
|
|
6
6
|
major: '2025-09-18T14:39:22.803Z',
|
|
7
|
-
minor: '2025-
|
|
8
|
-
patch: '2025-
|
|
7
|
+
minor: '2025-10-15T10:12:21.273Z',
|
|
8
|
+
patch: '2025-10-15T10:12:21.273Z',
|
|
9
9
|
}
|
|
@@ -275,6 +275,14 @@ const MATCH_URL_TEST_URLS: (MatchUrlTestNoMatchDef | MatchUrlTestMatchDef)[] = [
|
|
|
275
275
|
embedUrl: `https://replit.com/@omar/Blob-Generator?embed=true`,
|
|
276
276
|
},
|
|
277
277
|
},
|
|
278
|
+
{
|
|
279
|
+
url: 'https://replit.com/@omar/Blob-Generator#index.html',
|
|
280
|
+
match: true,
|
|
281
|
+
output: {
|
|
282
|
+
type: 'replit',
|
|
283
|
+
embedUrl: `https://replit.com/@omar/Blob-Generator?embed=true#index.html`,
|
|
284
|
+
},
|
|
285
|
+
},
|
|
278
286
|
{
|
|
279
287
|
url: 'https://replit.com/foobar',
|
|
280
288
|
match: false,
|
|
@@ -347,23 +355,6 @@ const MATCH_URL_TEST_URLS: (MatchUrlTestNoMatchDef | MatchUrlTestMatchDef)[] = [
|
|
|
347
355
|
url: 'https://vimeo.com/foobar',
|
|
348
356
|
match: false,
|
|
349
357
|
},
|
|
350
|
-
// excalidraw
|
|
351
|
-
{
|
|
352
|
-
url: 'https://excalidraw.com/#room=asdkjashdkjhaskdjh,sadkjhakjshdkjahd',
|
|
353
|
-
match: true,
|
|
354
|
-
output: {
|
|
355
|
-
type: 'excalidraw',
|
|
356
|
-
embedUrl: `https://excalidraw.com/#room=asdkjashdkjhaskdjh,sadkjhakjshdkjahd`,
|
|
357
|
-
},
|
|
358
|
-
},
|
|
359
|
-
{
|
|
360
|
-
url: 'https://excalidraw.com',
|
|
361
|
-
match: false,
|
|
362
|
-
},
|
|
363
|
-
{
|
|
364
|
-
url: 'https://excalidraw.com/help',
|
|
365
|
-
match: false,
|
|
366
|
-
},
|
|
367
358
|
//desmos
|
|
368
359
|
{
|
|
369
360
|
url: 'https://www.desmos.com/calculator/js9hryvejc',
|
|
@@ -599,6 +590,14 @@ const MATCH_EMBED_TEST_URLS: (MatchEmbedTestMatchDef | MatchEmbedTestNoMatchDef)
|
|
|
599
590
|
url: `https://replit.com/@omar/Blob-Generator`,
|
|
600
591
|
},
|
|
601
592
|
},
|
|
593
|
+
{
|
|
594
|
+
embedUrl: 'https://replit.com/@omar/Blob-Generator?embed=true#index.html',
|
|
595
|
+
match: true,
|
|
596
|
+
output: {
|
|
597
|
+
type: 'replit',
|
|
598
|
+
url: `https://replit.com/@omar/Blob-Generator#index.html`,
|
|
599
|
+
},
|
|
600
|
+
},
|
|
602
601
|
{
|
|
603
602
|
embedUrl: 'https://replit.com/@omar/Blob-Generator',
|
|
604
603
|
match: false,
|
|
@@ -671,23 +670,6 @@ const MATCH_EMBED_TEST_URLS: (MatchEmbedTestMatchDef | MatchEmbedTestNoMatchDef)
|
|
|
671
670
|
embedUrl: 'https://vimeo.com/foobar',
|
|
672
671
|
match: false,
|
|
673
672
|
},
|
|
674
|
-
// excalidraw
|
|
675
|
-
{
|
|
676
|
-
embedUrl: 'https://excalidraw.com/#room=asdkjashdkjhaskdjh,sadkjhakjshdkjahd',
|
|
677
|
-
match: true,
|
|
678
|
-
output: {
|
|
679
|
-
type: 'excalidraw',
|
|
680
|
-
url: `https://excalidraw.com/#room=asdkjashdkjhaskdjh,sadkjhakjshdkjahd`,
|
|
681
|
-
},
|
|
682
|
-
},
|
|
683
|
-
{
|
|
684
|
-
embedUrl: 'https://excalidraw.com',
|
|
685
|
-
match: false,
|
|
686
|
-
},
|
|
687
|
-
{
|
|
688
|
-
embedUrl: 'https://excalidraw.com/help',
|
|
689
|
-
match: false,
|
|
690
|
-
},
|
|
691
673
|
// desmos
|
|
692
674
|
{
|
|
693
675
|
embedUrl: 'https://www.desmos.com/calculator/js9hryvejc?embed',
|
|
@@ -648,3 +648,254 @@ test('right clicking a shape inside of a group does not focus the group if the g
|
|
|
648
648
|
editor.pointerUp(100, 100, { target: 'shape', button: 0, shape: editor.getShape(boxAId)! })
|
|
649
649
|
expect(editor.getFocusedGroupId()).toBe(groupId)
|
|
650
650
|
})
|
|
651
|
+
|
|
652
|
+
describe('when passing a function to onInteractionEnd', () => {
|
|
653
|
+
it('calls the function for cropping', () => {
|
|
654
|
+
const id = createShapeId('image')
|
|
655
|
+
editor.createShapes([
|
|
656
|
+
{
|
|
657
|
+
id,
|
|
658
|
+
type: 'image',
|
|
659
|
+
x: 100,
|
|
660
|
+
y: 100,
|
|
661
|
+
props: {
|
|
662
|
+
w: 1200,
|
|
663
|
+
h: 800,
|
|
664
|
+
},
|
|
665
|
+
},
|
|
666
|
+
])
|
|
667
|
+
|
|
668
|
+
editor.select(id)
|
|
669
|
+
|
|
670
|
+
const fn = vi.fn()
|
|
671
|
+
editor.setCurrentTool('select.cropping', {
|
|
672
|
+
handle: 'bottom_right',
|
|
673
|
+
onInteractionEnd: fn,
|
|
674
|
+
})
|
|
675
|
+
editor.pointerUp(50, 50)
|
|
676
|
+
|
|
677
|
+
expect(fn).toHaveBeenCalled()
|
|
678
|
+
})
|
|
679
|
+
|
|
680
|
+
it('calls the function for pointing crop handle', () => {
|
|
681
|
+
const fn = vi.fn()
|
|
682
|
+
editor.setCurrentTool('select.crop.pointing_crop_handle', {
|
|
683
|
+
onInteractionEnd: fn,
|
|
684
|
+
})
|
|
685
|
+
editor.pointerUp(50, 50)
|
|
686
|
+
expect(fn).toHaveBeenCalled()
|
|
687
|
+
})
|
|
688
|
+
|
|
689
|
+
it('calls the function for pointing arrow label', () => {
|
|
690
|
+
const fn = vi.fn()
|
|
691
|
+
const id = createShapeId('arrow')
|
|
692
|
+
|
|
693
|
+
const arrow = {
|
|
694
|
+
id,
|
|
695
|
+
type: 'arrow' as const,
|
|
696
|
+
x: 100,
|
|
697
|
+
y: 100,
|
|
698
|
+
props: {
|
|
699
|
+
richText: toRichText('Test Label'),
|
|
700
|
+
start: { x: 0, y: 0 },
|
|
701
|
+
end: { x: 100, y: 0 },
|
|
702
|
+
},
|
|
703
|
+
}
|
|
704
|
+
|
|
705
|
+
editor.createShapes<TLArrowShape>([arrow])
|
|
706
|
+
|
|
707
|
+
editor.setCurrentTool('select.pointing_arrow_label', {
|
|
708
|
+
shape: arrow,
|
|
709
|
+
onInteractionEnd: fn,
|
|
710
|
+
})
|
|
711
|
+
editor.pointerUp(50, 50)
|
|
712
|
+
expect(fn).toHaveBeenCalled()
|
|
713
|
+
})
|
|
714
|
+
|
|
715
|
+
it('calls the function for pointing a resize handle', () => {
|
|
716
|
+
const fn = vi.fn()
|
|
717
|
+
editor.setCurrentTool('select.pointing_resize_handle', {
|
|
718
|
+
target: 'selection',
|
|
719
|
+
handle: 'bottom_right',
|
|
720
|
+
onInteractionEnd: fn,
|
|
721
|
+
})
|
|
722
|
+
editor.pointerUp(50, 50)
|
|
723
|
+
expect(fn).toHaveBeenCalled()
|
|
724
|
+
})
|
|
725
|
+
|
|
726
|
+
it('calls the function for pointing a rotate handle', () => {
|
|
727
|
+
const fn = vi.fn()
|
|
728
|
+
editor.setCurrentTool('select.pointing_rotate_handle', {
|
|
729
|
+
target: 'selection',
|
|
730
|
+
handle: 'bottom_right_rotate',
|
|
731
|
+
onInteractionEnd: fn,
|
|
732
|
+
})
|
|
733
|
+
editor.pointerUp(50, 50)
|
|
734
|
+
expect(fn).toHaveBeenCalled()
|
|
735
|
+
})
|
|
736
|
+
|
|
737
|
+
it('calls the function for resizing', () => {
|
|
738
|
+
const id = createShapeId('box')
|
|
739
|
+
editor.createShapes([
|
|
740
|
+
{
|
|
741
|
+
id,
|
|
742
|
+
type: 'geo',
|
|
743
|
+
x: 100,
|
|
744
|
+
y: 100,
|
|
745
|
+
},
|
|
746
|
+
])
|
|
747
|
+
|
|
748
|
+
editor.select(id)
|
|
749
|
+
|
|
750
|
+
const fn = vi.fn()
|
|
751
|
+
editor.setCurrentTool('select.resizing', {
|
|
752
|
+
target: 'selection',
|
|
753
|
+
handle: 'bottom_right',
|
|
754
|
+
onInteractionEnd: fn,
|
|
755
|
+
})
|
|
756
|
+
editor.pointerUp(50, 50)
|
|
757
|
+
expect(fn).toHaveBeenCalled()
|
|
758
|
+
})
|
|
759
|
+
|
|
760
|
+
it('calls the function for translating', () => {
|
|
761
|
+
const id = createShapeId('box')
|
|
762
|
+
editor.createShapes([
|
|
763
|
+
{
|
|
764
|
+
id,
|
|
765
|
+
type: 'geo',
|
|
766
|
+
x: 100,
|
|
767
|
+
y: 100,
|
|
768
|
+
},
|
|
769
|
+
])
|
|
770
|
+
editor.select(id)
|
|
771
|
+
|
|
772
|
+
const fn = vi.fn()
|
|
773
|
+
editor.setCurrentTool('select.translating', {
|
|
774
|
+
onInteractionEnd: fn,
|
|
775
|
+
})
|
|
776
|
+
editor.pointerUp(50, 50)
|
|
777
|
+
expect(fn).toHaveBeenCalled()
|
|
778
|
+
})
|
|
779
|
+
})
|
|
780
|
+
|
|
781
|
+
describe('when passing a string to onInteractionEnd', () => {
|
|
782
|
+
it('transitions to the tool for cropping', () => {
|
|
783
|
+
const id = createShapeId('image')
|
|
784
|
+
editor.createShapes([
|
|
785
|
+
{
|
|
786
|
+
id,
|
|
787
|
+
type: 'image',
|
|
788
|
+
x: 100,
|
|
789
|
+
y: 100,
|
|
790
|
+
props: {
|
|
791
|
+
w: 1200,
|
|
792
|
+
h: 800,
|
|
793
|
+
},
|
|
794
|
+
},
|
|
795
|
+
])
|
|
796
|
+
|
|
797
|
+
editor.select(id)
|
|
798
|
+
|
|
799
|
+
editor.setCurrentTool('select.cropping', {
|
|
800
|
+
handle: 'bottom_right',
|
|
801
|
+
onInteractionEnd: 'select.idle',
|
|
802
|
+
})
|
|
803
|
+
editor.pointerUp(50, 50)
|
|
804
|
+
|
|
805
|
+
editor.expectToBeIn('select.idle')
|
|
806
|
+
})
|
|
807
|
+
|
|
808
|
+
it('transitions to the tool for pointing crop handle', () => {
|
|
809
|
+
editor.setCurrentTool('select.crop.pointing_crop_handle', {
|
|
810
|
+
onInteractionEnd: 'select.idle',
|
|
811
|
+
})
|
|
812
|
+
editor.pointerUp(50, 50)
|
|
813
|
+
editor.expectToBeIn('select.idle')
|
|
814
|
+
})
|
|
815
|
+
|
|
816
|
+
it('transitions to the tool for pointing arrow label', () => {
|
|
817
|
+
const id = createShapeId('arrow')
|
|
818
|
+
|
|
819
|
+
const arrow = {
|
|
820
|
+
id,
|
|
821
|
+
type: 'arrow' as const,
|
|
822
|
+
x: 100,
|
|
823
|
+
y: 100,
|
|
824
|
+
props: {
|
|
825
|
+
richText: toRichText('Test Label'),
|
|
826
|
+
start: { x: 0, y: 0 },
|
|
827
|
+
end: { x: 100, y: 0 },
|
|
828
|
+
},
|
|
829
|
+
}
|
|
830
|
+
|
|
831
|
+
editor.createShapes<TLArrowShape>([arrow])
|
|
832
|
+
|
|
833
|
+
editor.setCurrentTool('select.pointing_arrow_label', {
|
|
834
|
+
shape: arrow,
|
|
835
|
+
onInteractionEnd: 'select.idle',
|
|
836
|
+
})
|
|
837
|
+
editor.pointerUp(50, 50)
|
|
838
|
+
editor.expectToBeIn('select.idle')
|
|
839
|
+
})
|
|
840
|
+
|
|
841
|
+
it('transitions to the tool for pointing a resize handle', () => {
|
|
842
|
+
editor.setCurrentTool('select.pointing_resize_handle', {
|
|
843
|
+
target: 'selection',
|
|
844
|
+
handle: 'bottom_right',
|
|
845
|
+
onInteractionEnd: 'select.idle',
|
|
846
|
+
})
|
|
847
|
+
editor.pointerUp(50, 50)
|
|
848
|
+
editor.expectToBeIn('select.idle')
|
|
849
|
+
})
|
|
850
|
+
|
|
851
|
+
it('transitions to the tool for pointing a rotate handle', () => {
|
|
852
|
+
editor.setCurrentTool('select.pointing_rotate_handle', {
|
|
853
|
+
target: 'selection',
|
|
854
|
+
handle: 'bottom_right_rotate',
|
|
855
|
+
onInteractionEnd: 'select.idle',
|
|
856
|
+
})
|
|
857
|
+
editor.pointerUp(50, 50)
|
|
858
|
+
editor.expectToBeIn('select.idle')
|
|
859
|
+
})
|
|
860
|
+
|
|
861
|
+
it('transitions to the tool for resizing', () => {
|
|
862
|
+
const id = createShapeId('box')
|
|
863
|
+
editor.createShapes([
|
|
864
|
+
{
|
|
865
|
+
id,
|
|
866
|
+
type: 'geo',
|
|
867
|
+
x: 100,
|
|
868
|
+
y: 100,
|
|
869
|
+
},
|
|
870
|
+
])
|
|
871
|
+
|
|
872
|
+
editor.select(id)
|
|
873
|
+
|
|
874
|
+
editor.setCurrentTool('select.resizing', {
|
|
875
|
+
target: 'selection',
|
|
876
|
+
handle: 'bottom_right',
|
|
877
|
+
onInteractionEnd: 'select.idle',
|
|
878
|
+
})
|
|
879
|
+
editor.pointerUp(50, 50)
|
|
880
|
+
editor.expectToBeIn('select.idle')
|
|
881
|
+
})
|
|
882
|
+
|
|
883
|
+
it('transitions to the tool for translating', () => {
|
|
884
|
+
const id = createShapeId('box')
|
|
885
|
+
editor.createShapes([
|
|
886
|
+
{
|
|
887
|
+
id,
|
|
888
|
+
type: 'geo',
|
|
889
|
+
x: 100,
|
|
890
|
+
y: 100,
|
|
891
|
+
},
|
|
892
|
+
])
|
|
893
|
+
editor.select(id)
|
|
894
|
+
|
|
895
|
+
editor.setCurrentTool('select.translating', {
|
|
896
|
+
onInteractionEnd: 'select.idle',
|
|
897
|
+
})
|
|
898
|
+
editor.pointerUp(50, 50)
|
|
899
|
+
editor.expectToBeIn('select.idle')
|
|
900
|
+
})
|
|
901
|
+
})
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { TLBookmarkShape, createShapeId } from '@tldraw/editor'
|
|
2
|
-
import {
|
|
2
|
+
import { vi } from 'vitest'
|
|
3
|
+
import { createBookmarkFromUrl, getHumanReadableAddress } from '../lib/shapes/bookmark/bookmarks'
|
|
3
4
|
import { TestEditor } from './TestEditor'
|
|
4
5
|
|
|
5
6
|
let editor: TestEditor
|
|
@@ -74,12 +75,12 @@ describe('The URL formatter', () => {
|
|
|
74
75
|
const e = editor.getShape<TLBookmarkShape>(ids.e)!
|
|
75
76
|
const f = editor.getShape<TLBookmarkShape>(ids.f)!
|
|
76
77
|
|
|
77
|
-
expect(getHumanReadableAddress(a)).toBe('github.com')
|
|
78
|
-
expect(getHumanReadableAddress(b)).toBe('github.com')
|
|
79
|
-
expect(getHumanReadableAddress(c)).toBe('github.com')
|
|
80
|
-
expect(getHumanReadableAddress(d)).toBe('github.com')
|
|
81
|
-
expect(getHumanReadableAddress(e)).toBe('github.com')
|
|
82
|
-
expect(getHumanReadableAddress(f)).toBe('github.com')
|
|
78
|
+
expect(getHumanReadableAddress(a.props.url)).toBe('github.com')
|
|
79
|
+
expect(getHumanReadableAddress(b.props.url)).toBe('github.com')
|
|
80
|
+
expect(getHumanReadableAddress(c.props.url)).toBe('github.com')
|
|
81
|
+
expect(getHumanReadableAddress(d.props.url)).toBe('github.com')
|
|
82
|
+
expect(getHumanReadableAddress(e.props.url)).toBe('github.com')
|
|
83
|
+
expect(getHumanReadableAddress(f.props.url)).toBe('github.com')
|
|
83
84
|
})
|
|
84
85
|
|
|
85
86
|
it("Doesn't resize bookmarks", () => {
|
|
@@ -132,3 +133,124 @@ describe('The URL formatter', () => {
|
|
|
132
133
|
expect(newBookmark.props.h).toBe(320)
|
|
133
134
|
})
|
|
134
135
|
})
|
|
136
|
+
|
|
137
|
+
describe('createBookmarkFromUrl', () => {
|
|
138
|
+
it('creates a bookmark shape with unfurled metadata', async () => {
|
|
139
|
+
const url = 'https://example.com'
|
|
140
|
+
const center = { x: 100, y: 200 }
|
|
141
|
+
|
|
142
|
+
// Mock the asset creation to return a test asset
|
|
143
|
+
const mockAsset = {
|
|
144
|
+
id: 'asset:test-asset-id' as any,
|
|
145
|
+
typeName: 'asset' as const,
|
|
146
|
+
type: 'bookmark' as const,
|
|
147
|
+
props: {
|
|
148
|
+
src: url,
|
|
149
|
+
title: 'Example Site',
|
|
150
|
+
description: 'An example website',
|
|
151
|
+
image: 'https://example.com/image.jpg',
|
|
152
|
+
favicon: 'https://example.com/favicon.ico',
|
|
153
|
+
},
|
|
154
|
+
meta: {},
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
// Mock the getAssetForExternalContent method
|
|
158
|
+
vi.spyOn(editor, 'getAssetForExternalContent').mockResolvedValue(mockAsset)
|
|
159
|
+
|
|
160
|
+
const result = await createBookmarkFromUrl(editor, { url, center })
|
|
161
|
+
|
|
162
|
+
assert(result.ok, 'Failed to create bookmark')
|
|
163
|
+
const shape = result.value
|
|
164
|
+
expect(shape.type).toBe('bookmark')
|
|
165
|
+
expect(shape.props.url).toBe(url)
|
|
166
|
+
expect(shape.props.assetId).toBe('asset:test-asset-id')
|
|
167
|
+
expect(shape.props.w).toBe(300)
|
|
168
|
+
expect(shape.props.h).toBe(320)
|
|
169
|
+
expect(shape.x).toBe(center.x - 150) // BOOKMARK_WIDTH / 2
|
|
170
|
+
expect(shape.y).toBe(center.y - 160) // BOOKMARK_HEIGHT / 2
|
|
171
|
+
|
|
172
|
+
// Verify the shape was created in the editor
|
|
173
|
+
const createdShape = editor.getShape(result.value.id)
|
|
174
|
+
expect(createdShape).toBeDefined()
|
|
175
|
+
expect(createdShape?.type).toBe('bookmark')
|
|
176
|
+
|
|
177
|
+
// Verify the asset was created
|
|
178
|
+
const createdAsset = editor.getAsset('asset:test-asset-id' as any)
|
|
179
|
+
expect(createdAsset).toBeDefined()
|
|
180
|
+
expect(createdAsset?.type).toBe('bookmark')
|
|
181
|
+
})
|
|
182
|
+
|
|
183
|
+
it('creates a bookmark shape with default center when no center provided', async () => {
|
|
184
|
+
const url = 'https://example.com'
|
|
185
|
+
const viewportCenter = { x: 500, y: 300 }
|
|
186
|
+
|
|
187
|
+
// Mock getViewportPageBounds to return a known center
|
|
188
|
+
vi.spyOn(editor, 'getViewportPageBounds').mockReturnValue({
|
|
189
|
+
x: 0,
|
|
190
|
+
y: 0,
|
|
191
|
+
w: 1000,
|
|
192
|
+
h: 600,
|
|
193
|
+
center: viewportCenter,
|
|
194
|
+
} as any)
|
|
195
|
+
|
|
196
|
+
const mockAsset = {
|
|
197
|
+
id: 'asset:test-asset-id' as any,
|
|
198
|
+
typeName: 'asset' as const,
|
|
199
|
+
type: 'bookmark' as const,
|
|
200
|
+
props: {
|
|
201
|
+
src: url,
|
|
202
|
+
title: 'Example Site',
|
|
203
|
+
description: 'An example website',
|
|
204
|
+
image: '',
|
|
205
|
+
favicon: '',
|
|
206
|
+
},
|
|
207
|
+
meta: {},
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
vi.spyOn(editor, 'getAssetForExternalContent').mockResolvedValue(mockAsset)
|
|
211
|
+
|
|
212
|
+
const result = await createBookmarkFromUrl(editor, { url })
|
|
213
|
+
|
|
214
|
+
assert(result.ok, 'Failed to create bookmark')
|
|
215
|
+
const shape = result.value
|
|
216
|
+
expect(shape.x).toBe(viewportCenter.x - 150)
|
|
217
|
+
expect(shape.y).toBe(viewportCenter.y - 160)
|
|
218
|
+
})
|
|
219
|
+
|
|
220
|
+
it('handles asset creation failure gracefully', async () => {
|
|
221
|
+
const url = 'https://invalid-url.com'
|
|
222
|
+
const center = { x: 100, y: 200 }
|
|
223
|
+
|
|
224
|
+
// Mock the asset creation to fail
|
|
225
|
+
vi.spyOn(editor, 'getAssetForExternalContent').mockRejectedValue(new Error('Failed to fetch'))
|
|
226
|
+
|
|
227
|
+
const result = await createBookmarkFromUrl(editor, { url, center })
|
|
228
|
+
|
|
229
|
+
assert(!result.ok, 'Failed to create bookmark')
|
|
230
|
+
expect(result.error).toBe('Failed to fetch')
|
|
231
|
+
|
|
232
|
+
// Verify no shape was created
|
|
233
|
+
const shapes = editor.getCurrentPageShapes()
|
|
234
|
+
expect(shapes).toHaveLength(0)
|
|
235
|
+
})
|
|
236
|
+
|
|
237
|
+
it('creates bookmark shape even when asset creation returns null', async () => {
|
|
238
|
+
const url = 'https://example.com'
|
|
239
|
+
const center = { x: 100, y: 200 }
|
|
240
|
+
|
|
241
|
+
// Mock the asset creation to return null
|
|
242
|
+
vi.spyOn(editor, 'getAssetForExternalContent').mockResolvedValue(null as any)
|
|
243
|
+
|
|
244
|
+
const result = await createBookmarkFromUrl(editor, { url, center })
|
|
245
|
+
|
|
246
|
+
assert(result.ok, 'Failed to create bookmark')
|
|
247
|
+
const shape = result.value
|
|
248
|
+
expect(shape.type).toBe('bookmark')
|
|
249
|
+
expect(shape.props.url).toBe(url)
|
|
250
|
+
expect(shape.props.assetId).toBe(null)
|
|
251
|
+
|
|
252
|
+
// Verify the shape was created
|
|
253
|
+
const createdShape = editor.getShape(result.value.id)
|
|
254
|
+
expect(createdShape).toBeDefined()
|
|
255
|
+
})
|
|
256
|
+
})
|