tldraw 4.3.0-next.a10a6b62725c → 4.3.0-next.bad71ed2ab6a
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 +14 -5
- package/dist-cjs/index.js +1 -1
- package/dist-cjs/lib/bindings/arrow/ArrowBindingUtil.js.map +2 -2
- package/dist-cjs/lib/canvas/TldrawSelectionForeground.js.map +2 -2
- package/dist-cjs/lib/defaultExternalContentHandlers.js.map +2 -2
- package/dist-cjs/lib/shapes/arrow/ArrowShapeUtil.js.map +2 -2
- package/dist-cjs/lib/shapes/arrow/arrowLabel.js.map +2 -2
- package/dist-cjs/lib/shapes/arrow/arrowTargetState.js.map +2 -2
- package/dist-cjs/lib/shapes/arrow/elbow/elbowArrowSnapLines.js.map +2 -2
- package/dist-cjs/lib/shapes/arrow/shared.js.map +2 -2
- package/dist-cjs/lib/shapes/arrow/toolStates/Pointing.js.map +2 -2
- package/dist-cjs/lib/shapes/bookmark/bookmarks.js.map +2 -2
- package/dist-cjs/lib/shapes/draw/toolStates/Drawing.js.map +2 -2
- package/dist-cjs/lib/shapes/embed/EmbedShapeUtil.js.map +2 -2
- package/dist-cjs/lib/shapes/frame/FrameShapeTool.js.map +1 -1
- package/dist-cjs/lib/shapes/geo/toolStates/Pointing.js.map +2 -2
- package/dist-cjs/lib/shapes/line/toolStates/Pointing.js.map +2 -2
- package/dist-cjs/lib/shapes/note/noteHelpers.js.map +2 -2
- package/dist-cjs/lib/shapes/shared/PlainTextLabel.js.map +2 -2
- package/dist-cjs/lib/shapes/shared/RichTextLabel.js.map +2 -2
- package/dist-cjs/lib/shapes/shared/crop.js +1 -0
- package/dist-cjs/lib/shapes/shared/crop.js.map +2 -2
- package/dist-cjs/lib/shapes/shared/useEditablePlainText.js.map +2 -2
- package/dist-cjs/lib/shapes/shared/useEditableRichText.js.map +2 -2
- package/dist-cjs/lib/shapes/text/toolStates/Pointing.js.map +2 -2
- package/dist-cjs/lib/tools/EraserTool/childStates/Erasing.js.map +2 -2
- package/dist-cjs/lib/tools/EraserTool/childStates/Pointing.js.map +2 -2
- package/dist-cjs/lib/tools/SelectTool/DragAndDropManager.js +1 -4
- package/dist-cjs/lib/tools/SelectTool/DragAndDropManager.js.map +2 -2
- package/dist-cjs/lib/tools/SelectTool/childStates/Brushing.js.map +2 -2
- package/dist-cjs/lib/tools/SelectTool/childStates/Crop/children/Idle.js.map +2 -2
- package/dist-cjs/lib/tools/SelectTool/childStates/DraggingHandle.js +1 -1
- package/dist-cjs/lib/tools/SelectTool/childStates/DraggingHandle.js.map +2 -2
- package/dist-cjs/lib/tools/SelectTool/childStates/EditingShape.js.map +2 -2
- package/dist-cjs/lib/tools/SelectTool/childStates/Idle.js.map +2 -2
- package/dist-cjs/lib/tools/SelectTool/childStates/PointingArrowLabel.js.map +2 -2
- package/dist-cjs/lib/tools/SelectTool/childStates/PointingHandle.js.map +2 -2
- package/dist-cjs/lib/tools/SelectTool/childStates/PointingSelection.js.map +2 -2
- package/dist-cjs/lib/tools/SelectTool/childStates/Resizing.js.map +2 -2
- package/dist-cjs/lib/tools/SelectTool/childStates/ScribbleBrushing.js.map +2 -2
- package/dist-cjs/lib/tools/SelectTool/childStates/Translating.js.map +2 -2
- package/dist-cjs/lib/ui/components/EditLinkDialog.js +11 -1
- package/dist-cjs/lib/ui/components/EditLinkDialog.js.map +2 -2
- package/dist-cjs/lib/ui/components/Toolbar/AltTextEditor.js.map +2 -2
- package/dist-cjs/lib/ui/components/menu-items.js.map +2 -2
- package/dist-cjs/lib/ui/context/actions.js +1 -2
- package/dist-cjs/lib/ui/context/actions.js.map +2 -2
- package/dist-cjs/lib/ui/hooks/menu-hooks.js.map +2 -2
- package/dist-cjs/lib/ui/hooks/useFlatten.js.map +2 -2
- package/dist-cjs/lib/ui/hooks/useTools.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/excalidraw/putExcalidrawContent.js +8 -0
- package/dist-cjs/lib/utils/excalidraw/putExcalidrawContent.js.map +2 -2
- package/dist-cjs/lib/utils/export/exportAs.js.map +2 -2
- package/dist-cjs/lib/utils/frames/frames.js.map +2 -2
- package/dist-cjs/lib/utils/tldr/buildFromV1Document.js.map +2 -2
- package/dist-esm/index.d.mts +14 -5
- package/dist-esm/index.mjs +1 -1
- package/dist-esm/lib/bindings/arrow/ArrowBindingUtil.mjs.map +2 -2
- package/dist-esm/lib/canvas/TldrawSelectionForeground.mjs.map +2 -2
- package/dist-esm/lib/defaultExternalContentHandlers.mjs.map +2 -2
- package/dist-esm/lib/shapes/arrow/ArrowShapeUtil.mjs.map +2 -2
- package/dist-esm/lib/shapes/arrow/arrowLabel.mjs.map +2 -2
- package/dist-esm/lib/shapes/arrow/arrowTargetState.mjs.map +2 -2
- package/dist-esm/lib/shapes/arrow/elbow/elbowArrowSnapLines.mjs.map +2 -2
- package/dist-esm/lib/shapes/arrow/shared.mjs.map +2 -2
- package/dist-esm/lib/shapes/arrow/toolStates/Pointing.mjs.map +2 -2
- package/dist-esm/lib/shapes/bookmark/bookmarks.mjs.map +2 -2
- package/dist-esm/lib/shapes/draw/toolStates/Drawing.mjs.map +2 -2
- package/dist-esm/lib/shapes/embed/EmbedShapeUtil.mjs.map +2 -2
- package/dist-esm/lib/shapes/frame/FrameShapeTool.mjs.map +1 -1
- package/dist-esm/lib/shapes/geo/toolStates/Pointing.mjs.map +2 -2
- package/dist-esm/lib/shapes/line/toolStates/Pointing.mjs.map +2 -2
- package/dist-esm/lib/shapes/note/noteHelpers.mjs.map +2 -2
- package/dist-esm/lib/shapes/shared/PlainTextLabel.mjs.map +2 -2
- package/dist-esm/lib/shapes/shared/RichTextLabel.mjs.map +2 -2
- package/dist-esm/lib/shapes/shared/crop.mjs +1 -0
- package/dist-esm/lib/shapes/shared/crop.mjs.map +2 -2
- package/dist-esm/lib/shapes/shared/useEditablePlainText.mjs.map +2 -2
- package/dist-esm/lib/shapes/shared/useEditableRichText.mjs.map +2 -2
- package/dist-esm/lib/shapes/text/toolStates/Pointing.mjs.map +2 -2
- package/dist-esm/lib/tools/EraserTool/childStates/Erasing.mjs.map +2 -2
- package/dist-esm/lib/tools/EraserTool/childStates/Pointing.mjs +1 -4
- package/dist-esm/lib/tools/EraserTool/childStates/Pointing.mjs.map +2 -2
- package/dist-esm/lib/tools/SelectTool/DragAndDropManager.mjs +1 -4
- package/dist-esm/lib/tools/SelectTool/DragAndDropManager.mjs.map +2 -2
- package/dist-esm/lib/tools/SelectTool/childStates/Brushing.mjs.map +2 -2
- package/dist-esm/lib/tools/SelectTool/childStates/Crop/children/Idle.mjs.map +2 -2
- package/dist-esm/lib/tools/SelectTool/childStates/DraggingHandle.mjs +1 -1
- package/dist-esm/lib/tools/SelectTool/childStates/DraggingHandle.mjs.map +2 -2
- package/dist-esm/lib/tools/SelectTool/childStates/EditingShape.mjs.map +2 -2
- package/dist-esm/lib/tools/SelectTool/childStates/Idle.mjs.map +2 -2
- package/dist-esm/lib/tools/SelectTool/childStates/PointingArrowLabel.mjs.map +2 -2
- package/dist-esm/lib/tools/SelectTool/childStates/PointingHandle.mjs +1 -4
- package/dist-esm/lib/tools/SelectTool/childStates/PointingHandle.mjs.map +2 -2
- package/dist-esm/lib/tools/SelectTool/childStates/PointingSelection.mjs.map +2 -2
- package/dist-esm/lib/tools/SelectTool/childStates/Resizing.mjs.map +2 -2
- package/dist-esm/lib/tools/SelectTool/childStates/ScribbleBrushing.mjs.map +2 -2
- package/dist-esm/lib/tools/SelectTool/childStates/Translating.mjs.map +2 -2
- package/dist-esm/lib/ui/components/EditLinkDialog.mjs +11 -1
- package/dist-esm/lib/ui/components/EditLinkDialog.mjs.map +2 -2
- package/dist-esm/lib/ui/components/Toolbar/AltTextEditor.mjs.map +2 -2
- package/dist-esm/lib/ui/components/menu-items.mjs +1 -4
- package/dist-esm/lib/ui/components/menu-items.mjs.map +2 -2
- package/dist-esm/lib/ui/context/actions.mjs +1 -2
- package/dist-esm/lib/ui/context/actions.mjs.map +2 -2
- package/dist-esm/lib/ui/hooks/menu-hooks.mjs +1 -4
- package/dist-esm/lib/ui/hooks/menu-hooks.mjs.map +2 -2
- package/dist-esm/lib/ui/hooks/useFlatten.mjs.map +2 -2
- package/dist-esm/lib/ui/hooks/useTools.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/excalidraw/putExcalidrawContent.mjs +8 -0
- package/dist-esm/lib/utils/excalidraw/putExcalidrawContent.mjs.map +2 -2
- package/dist-esm/lib/utils/export/exportAs.mjs +1 -3
- package/dist-esm/lib/utils/export/exportAs.mjs.map +2 -2
- package/dist-esm/lib/utils/frames/frames.mjs.map +2 -2
- package/dist-esm/lib/utils/tldr/buildFromV1Document.mjs.map +2 -2
- package/package.json +10 -10
- package/src/lib/bindings/arrow/ArrowBindingUtil.ts +1 -1
- package/src/lib/canvas/TldrawSelectionForeground.tsx +4 -9
- package/src/lib/defaultExternalContentHandlers.ts +3 -4
- package/src/lib/shapes/arrow/ArrowShapeUtil.test.ts +2 -2
- package/src/lib/shapes/arrow/ArrowShapeUtil.tsx +1 -1
- package/src/lib/shapes/arrow/arrowLabel.ts +1 -1
- package/src/lib/shapes/arrow/arrowTargetState.ts +1 -1
- package/src/lib/shapes/arrow/elbow/elbowArrowSnapLines.tsx +3 -3
- package/src/lib/shapes/arrow/shared.ts +4 -4
- package/src/lib/shapes/arrow/toolStates/Pointing.tsx +1 -1
- package/src/lib/shapes/bookmark/bookmarks.ts +3 -3
- package/src/lib/shapes/draw/toolStates/Drawing.ts +4 -4
- package/src/lib/shapes/embed/EmbedShapeUtil.tsx +1 -1
- package/src/lib/shapes/frame/FrameShapeTool.ts +1 -1
- package/src/lib/shapes/geo/GeoShapeUtil.test.tsx +10 -2
- package/src/lib/shapes/geo/toolStates/Pointing.ts +3 -3
- package/src/lib/shapes/line/LineShapeTool.test.ts +6 -6
- package/src/lib/shapes/line/LineShapeUtil.test.tsx +5 -5
- package/src/lib/shapes/line/toolStates/Pointing.ts +1 -1
- package/src/lib/shapes/note/NoteShapeTool.test.ts +2 -1
- package/src/lib/shapes/note/noteHelpers.ts +2 -2
- package/src/lib/shapes/shared/PlainTextLabel.tsx +2 -1
- package/src/lib/shapes/shared/RichTextLabel.tsx +2 -1
- package/src/lib/shapes/shared/crop.ts +1 -0
- package/src/lib/shapes/shared/useEditablePlainText.ts +7 -3
- package/src/lib/shapes/shared/useEditableRichText.ts +7 -3
- package/src/lib/shapes/text/TextShapeTool.test.ts +4 -4
- package/src/lib/shapes/text/toolStates/Pointing.ts +1 -1
- package/src/lib/tools/EraserTool/childStates/Erasing.ts +3 -5
- package/src/lib/tools/EraserTool/childStates/Pointing.ts +3 -16
- package/src/lib/tools/SelectTool/DragAndDropManager.ts +2 -4
- package/src/lib/tools/SelectTool/childStates/Brushing.ts +2 -6
- package/src/lib/tools/SelectTool/childStates/Crop/children/Idle.ts +2 -3
- package/src/lib/tools/SelectTool/childStates/DraggingHandle.tsx +4 -7
- package/src/lib/tools/SelectTool/childStates/EditingShape.ts +2 -4
- package/src/lib/tools/SelectTool/childStates/Idle.ts +6 -10
- package/src/lib/tools/SelectTool/childStates/PointingArrowLabel.ts +1 -1
- package/src/lib/tools/SelectTool/childStates/PointingHandle.ts +4 -12
- package/src/lib/tools/SelectTool/childStates/PointingSelection.ts +2 -2
- package/src/lib/tools/SelectTool/childStates/Resizing.ts +2 -4
- package/src/lib/tools/SelectTool/childStates/ScribbleBrushing.ts +2 -4
- package/src/lib/tools/SelectTool/childStates/Translating.ts +1 -3
- package/src/lib/ui/components/EditLinkDialog.tsx +16 -6
- package/src/lib/ui/components/Toolbar/AltTextEditor.tsx +2 -2
- package/src/lib/ui/components/menu-items.tsx +6 -14
- package/src/lib/ui/context/actions.tsx +9 -13
- package/src/lib/ui/hooks/menu-hooks.ts +9 -19
- package/src/lib/ui/hooks/useFlatten.ts +1 -2
- package/src/lib/ui/hooks/useTools.tsx +1 -2
- package/src/lib/ui/version.ts +3 -3
- package/src/lib/utils/excalidraw/putExcalidrawContent.ts +8 -0
- package/src/lib/utils/export/exportAs.ts +2 -9
- package/src/lib/utils/frames/frames.ts +1 -1
- package/src/lib/utils/tldr/buildFromV1Document.ts +12 -17
- package/src/test/Editor.test.tsx +38 -12
- package/src/test/SelectTool.test.ts +11 -19
- package/src/test/TestEditor.ts +1 -4
- package/src/test/TldrawEditor.test.tsx +18 -16
- package/src/test/bindings.test.tsx +29 -25
- package/src/test/bindingsIndex.test.tsx +4 -4
- package/src/test/commands/createShape.test.ts +64 -0
- package/src/test/commands/createShapes.test.ts +15 -1
- package/src/test/commands/getSvgString.test.ts +2 -2
- package/src/test/commands/isShapeOfType.test.ts +44 -0
- package/src/test/commands/putContent.test.ts +1 -0
- package/src/test/commands/updateShape.test.ts +67 -0
- package/src/test/commands/updateShapes.test.ts +21 -5
- package/src/test/custom-clipping.test.ts +36 -35
- package/src/test/customSnapping.test.tsx +77 -62
- package/src/test/duplicate.test.ts +1 -1
- package/src/test/frames.test.ts +2 -2
- package/src/test/getCulledShapes.test.tsx +11 -3
- package/src/test/getShapeAtPoint.test.ts +2 -2
- package/src/test/groups.test.tsx +6 -3
- package/src/test/resizing.test.ts +9 -13
- package/src/test/selection-omnibus.test.ts +11 -11
- package/src/test/shapeutils.test.ts +1 -1
- package/src/test/styles2.test.tsx +1 -1
- package/src/test/styles3.test.ts +5 -5
- package/src/test/test-jsx.tsx +69 -57
- package/src/test/text.test.ts +15 -17
- package/src/test/translating.test.ts +6 -8
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../../src/lib/shapes/embed/EmbedShapeUtil.tsx"],
|
|
4
|
-
"sourcesContent": ["/* eslint-disable react-hooks/rules-of-hooks */\n\nimport {\n\tBaseBoxShapeUtil,\n\tHTMLContainer,\n\tRectangle2d,\n\tTLEmbedShape,\n\tTLEmbedShapeProps,\n\tTLResizeInfo,\n\tembedShapeMigrations,\n\tembedShapeProps,\n\tlerp,\n\tresizeBox,\n\ttoDomPrecision,\n\tuseIsEditing,\n\tuseSvgExportContext,\n\tuseValue,\n} from '@tldraw/editor'\n\nimport {\n\tDEFAULT_EMBED_DEFINITIONS,\n\tEmbedDefinition,\n\tTLEmbedDefinition,\n\tTLEmbedShapePermissions,\n\tembedShapePermissionDefaults,\n} from '../../defaultEmbedDefinitions'\nimport { TLEmbedResult, getEmbedInfo } from '../../utils/embeds/embeds'\nimport { BookmarkIndicatorComponent, BookmarkShapeComponent } from '../bookmark/BookmarkShapeUtil'\nimport { BOOKMARK_JUST_URL_HEIGHT, BOOKMARK_WIDTH } from '../bookmark/bookmarks'\nimport { getRotatedBoxShadow } from '../shared/rotated-box-shadow'\n\nconst getSandboxPermissions = (permissions: TLEmbedShapePermissions) => {\n\treturn Object.entries(permissions)\n\t\t.filter(([_perm, isEnabled]) => isEnabled)\n\t\t.map(([perm]) => perm)\n\t\t.join(' ')\n}\n\n/** @public */\nexport class EmbedShapeUtil extends BaseBoxShapeUtil<TLEmbedShape> {\n\tstatic override type = 'embed' as const\n\tstatic override props = embedShapeProps\n\tstatic override migrations = embedShapeMigrations\n\tprivate static embedDefinitions: readonly EmbedDefinition[] = DEFAULT_EMBED_DEFINITIONS\n\n\tstatic setEmbedDefinitions(embedDefinitions: readonly TLEmbedDefinition[]) {\n\t\tEmbedShapeUtil.embedDefinitions = embedDefinitions\n\t}\n\n\tgetEmbedDefinitions(): readonly TLEmbedDefinition[] {\n\t\treturn EmbedShapeUtil.embedDefinitions\n\t}\n\n\tgetEmbedDefinition(url: string): TLEmbedResult {\n\t\treturn getEmbedInfo(EmbedShapeUtil.embedDefinitions, url)\n\t}\n\n\toverride getText(shape: TLEmbedShape) {\n\t\treturn shape.props.url\n\t}\n\n\toverride getAriaDescriptor(shape: TLEmbedShape) {\n\t\tconst embedInfo = this.getEmbedDefinition(shape.props.url)\n\t\treturn embedInfo?.definition.title\n\t}\n\n\toverride hideSelectionBoundsFg(shape: TLEmbedShape) {\n\t\treturn !this.canResize(shape)\n\t}\n\toverride canEdit() {\n\t\treturn true\n\t}\n\toverride canResize(shape: TLEmbedShape) {\n\t\treturn !!this.getEmbedDefinition(shape.props.url)?.definition?.doesResize\n\t}\n\toverride canEditInReadonly() {\n\t\treturn true\n\t}\n\n\toverride getDefaultProps(): TLEmbedShape['props'] {\n\t\treturn {\n\t\t\tw: 300,\n\t\t\th: 300,\n\t\t\turl: '',\n\t\t}\n\t}\n\n\toverride getGeometry(shape: TLEmbedShape) {\n\t\tconst embedInfo = this.getEmbedDefinition(shape.props.url)\n\t\tif (!embedInfo?.definition) {\n\t\t\treturn new Rectangle2d({\n\t\t\t\twidth: BOOKMARK_WIDTH,\n\t\t\t\theight: BOOKMARK_JUST_URL_HEIGHT,\n\t\t\t\tisFilled: true,\n\t\t\t})\n\t\t}\n\t\treturn super.getGeometry(shape)\n\t}\n\n\toverride isAspectRatioLocked(shape: TLEmbedShape) {\n\t\tconst embedInfo = this.getEmbedDefinition(shape.props.url)\n\t\treturn embedInfo?.definition.isAspectRatioLocked ?? false\n\t}\n\n\toverride onResize(shape: TLEmbedShape, info: TLResizeInfo<TLEmbedShape>) {\n\t\tconst isAspectRatioLocked = this.isAspectRatioLocked(shape)\n\t\tconst embedInfo = this.getEmbedDefinition(shape.props.url)\n\t\tlet minWidth = embedInfo?.definition.minWidth ?? 200\n\t\tlet minHeight = embedInfo?.definition.minHeight ?? 200\n\t\tif (isAspectRatioLocked) {\n\t\t\t// Enforce aspect ratio\n\t\t\t// Neither the width or height can be less than 200\n\t\t\tconst aspectRatio = shape.props.w / shape.props.h\n\t\t\tif (aspectRatio > 1) {\n\t\t\t\t// Landscape\n\t\t\t\tminWidth *= aspectRatio\n\t\t\t} else {\n\t\t\t\t// Portrait\n\t\t\t\tminHeight /= aspectRatio\n\t\t\t}\n\t\t}\n\n\t\treturn resizeBox(shape, info, { minWidth, minHeight })\n\t}\n\n\toverride component(shape: TLEmbedShape) {\n\t\tconst svgExport = useSvgExportContext()\n\t\tconst { w, h, url } = shape.props\n\t\tconst isEditing = useIsEditing(shape.id)\n\n\t\tconst embedInfo = this.getEmbedDefinition(url)\n\n\t\tconst isHoveringWhileEditingSameShape = useValue(\n\t\t\t'is hovering',\n\t\t\t() => {\n\t\t\t\tconst { editingShapeId, hoveredShapeId } = this.editor.getCurrentPageState()\n\n\t\t\t\tif (editingShapeId && hoveredShapeId !== editingShapeId) {\n\t\t\t\t\tconst editingShape = this.editor.getShape(editingShapeId)\n\t\t\t\t\tif (editingShape && this.editor.isShapeOfType<TLEmbedShape>(editingShape, 'embed')) {\n\t\t\t\t\t\treturn true\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\treturn false\n\t\t\t},\n\t\t\t[]\n\t\t)\n\n\t\tconst pageRotation = this.editor.getShapePageTransform(shape)!.rotation()\n\n\t\tif (svgExport) {\n\t\t\t// for SVG exports, we show a blank embed\n\t\t\treturn (\n\t\t\t\t<HTMLContainer className=\"tl-embed-container\" id={shape.id}>\n\t\t\t\t\t<div\n\t\t\t\t\t\tclassName=\"tl-embed\"\n\t\t\t\t\t\tstyle={{\n\t\t\t\t\t\t\tborder: 0,\n\t\t\t\t\t\t\tboxShadow: getRotatedBoxShadow(pageRotation),\n\t\t\t\t\t\t\tborderRadius: embedInfo?.definition.overrideOutlineRadius ?? 8,\n\t\t\t\t\t\t\tbackground: embedInfo?.definition.backgroundColor ?? 'var(--tl-color-background)',\n\t\t\t\t\t\t\twidth: w,\n\t\t\t\t\t\t\theight: h,\n\t\t\t\t\t\t}}\n\t\t\t\t\t/>\n\t\t\t\t</HTMLContainer>\n\t\t\t)\n\t\t}\n\n\t\tconst isInteractive = isEditing || isHoveringWhileEditingSameShape\n\n\t\t// Prevent nested embedding of tldraw\n\t\tconst isIframe =\n\t\t\ttypeof window !== 'undefined' && (window !== window.top || window.self !== window.parent)\n\t\tif (isIframe && embedInfo?.definition.type === 'tldraw') return null\n\n\t\tif (embedInfo?.definition.type === 'github_gist') {\n\t\t\tconst idFromGistUrl = embedInfo.url.split('/').pop()\n\t\t\tif (!idFromGistUrl) throw Error('No gist id!')\n\n\t\t\treturn (\n\t\t\t\t<HTMLContainer className=\"tl-embed-container\" id={shape.id}>\n\t\t\t\t\t<Gist\n\t\t\t\t\t\tid={idFromGistUrl}\n\t\t\t\t\t\twidth={toDomPrecision(w)!}\n\t\t\t\t\t\theight={toDomPrecision(h)!}\n\t\t\t\t\t\tisInteractive={isInteractive}\n\t\t\t\t\t\tpageRotation={pageRotation}\n\t\t\t\t\t/>\n\t\t\t\t</HTMLContainer>\n\t\t\t)\n\t\t}\n\n\t\tconst sandbox = getSandboxPermissions({\n\t\t\t...embedShapePermissionDefaults,\n\t\t\t...(embedInfo?.definition.overridePermissions ?? {}),\n\t\t})\n\n\t\treturn (\n\t\t\t<HTMLContainer className=\"tl-embed-container\" id={shape.id}>\n\t\t\t\t{embedInfo?.definition ? (\n\t\t\t\t\t<iframe\n\t\t\t\t\t\tclassName=\"tl-embed\"\n\t\t\t\t\t\tsandbox={sandbox}\n\t\t\t\t\t\tsrc={embedInfo.embedUrl}\n\t\t\t\t\t\twidth={toDomPrecision(w)}\n\t\t\t\t\t\theight={toDomPrecision(h)}\n\t\t\t\t\t\tdraggable={false}\n\t\t\t\t\t\t// eslint-disable-next-line @typescript-eslint/no-deprecated\n\t\t\t\t\t\tframeBorder=\"0\"\n\t\t\t\t\t\treferrerPolicy=\"no-referrer-when-downgrade\"\n\t\t\t\t\t\ttabIndex={isEditing ? 0 : -1}\n\t\t\t\t\t\tstyle={{\n\t\t\t\t\t\t\tborder: 0,\n\t\t\t\t\t\t\tpointerEvents: isInteractive ? 'auto' : 'none',\n\t\t\t\t\t\t\t// Fix for safari <https://stackoverflow.com/a/49150908>\n\t\t\t\t\t\t\tzIndex: isInteractive ? '' : '-1',\n\t\t\t\t\t\t\tboxShadow: getRotatedBoxShadow(pageRotation),\n\t\t\t\t\t\t\tborderRadius: embedInfo?.definition.overrideOutlineRadius ?? 8,\n\t\t\t\t\t\t\tbackground: embedInfo?.definition.backgroundColor,\n\t\t\t\t\t\t}}\n\t\t\t\t\t/>\n\t\t\t\t) : (\n\t\t\t\t\t<BookmarkShapeComponent\n\t\t\t\t\t\turl={url}\n\t\t\t\t\t\th={h}\n\t\t\t\t\t\trotation={pageRotation}\n\t\t\t\t\t\tassetId={null}\n\t\t\t\t\t\tshowImageContainer={false}\n\t\t\t\t\t/>\n\t\t\t\t)}\n\t\t\t</HTMLContainer>\n\t\t)\n\t}\n\n\toverride indicator(shape: TLEmbedShape) {\n\t\tconst embedInfo = this.getEmbedDefinition(shape.props.url)\n\n\t\treturn embedInfo?.definition ? (\n\t\t\t<rect\n\t\t\t\twidth={toDomPrecision(shape.props.w)}\n\t\t\t\theight={toDomPrecision(shape.props.h)}\n\t\t\t\trx={embedInfo?.definition.overrideOutlineRadius ?? 8}\n\t\t\t\try={embedInfo?.definition.overrideOutlineRadius ?? 8}\n\t\t\t/>\n\t\t) : (\n\t\t\t<BookmarkIndicatorComponent w={BOOKMARK_WIDTH} h={BOOKMARK_JUST_URL_HEIGHT} />\n\t\t)\n\t}\n\toverride getInterpolatedProps(\n\t\tstartShape: TLEmbedShape,\n\t\tendShape: TLEmbedShape,\n\t\tt: number\n\t): TLEmbedShapeProps {\n\t\treturn {\n\t\t\t...(t > 0.5 ? endShape.props : startShape.props),\n\t\t\tw: lerp(startShape.props.w, endShape.props.w, t),\n\t\t\th: lerp(startShape.props.h, endShape.props.h, t),\n\t\t}\n\t}\n}\n\nfunction Gist({\n\tid,\n\tisInteractive,\n\twidth,\n\theight,\n\tstyle,\n\tpageRotation,\n}: {\n\tid: string\n\tisInteractive: boolean\n\twidth: number\n\theight: number\n\tpageRotation: number\n\tstyle?: React.CSSProperties\n}) {\n\t// Security warning:\n\t// Gists allow adding .json extensions to the URL which return JSONP.\n\t// Furthermore, the JSONP can include callbacks that execute arbitrary JavaScript.\n\t// It _is_ sandboxed by the iframe but we still want to disable it nonetheless.\n\t// We restrict the id to only allow hexdecimal characters to prevent this.\n\t// Read more:\n\t// https://github.com/bhaveshk90/Content-Security-Policy-CSP-Bypass-Techniques\n\t// https://github.com/renniepak/CSPBypass\n\tif (!id.match(/^[0-9a-f]+$/)) throw Error('No gist id!')\n\n\treturn (\n\t\t<iframe\n\t\t\tclassName=\"tl-embed\"\n\t\t\tdraggable={false}\n\t\t\twidth={toDomPrecision(width)}\n\t\t\theight={toDomPrecision(height)}\n\t\t\t// eslint-disable-next-line @typescript-eslint/no-deprecated\n\t\t\tframeBorder=\"0\"\n\t\t\t// eslint-disable-next-line @typescript-eslint/no-deprecated\n\t\t\tscrolling=\"no\"\n\t\t\treferrerPolicy=\"no-referrer-when-downgrade\"\n\t\t\ttabIndex={isInteractive ? 0 : -1}\n\t\t\tstyle={{\n\t\t\t\t...style,\n\t\t\t\tpointerEvents: isInteractive ? 'all' : 'none',\n\t\t\t\t// Fix for safari <https://stackoverflow.com/a/49150908>\n\t\t\t\tzIndex: isInteractive ? '' : '-1',\n\t\t\t\tboxShadow: getRotatedBoxShadow(pageRotation),\n\t\t\t}}\n\t\t\tsrcDoc={`\n\t\t\t<html>\n\t\t\t\t<head>\n\t\t\t\t\t<base target=\"_blank\">\n\t\t\t\t</head>\n\t\t\t\t<body>\n\t\t\t\t\t<script src=${`https://gist.github.com/${id}.js`}></script>\n\t\t\t\t\t<style type=\"text/css\">\n\t\t\t\t\t\t* { margin: 0px; }\n\t\t\t\t\t\ttable { height: 100%; background-color: red; }\n\t\t\t\t\t\t.gist { background-color: none; height: 100%; }\n\t\t\t\t\t\t.gist .gist-file { height: calc(100vh - 2px); padding: 0px; display: grid; grid-template-rows: 1fr auto; }\n\t\t\t\t\t</style>\n\t\t\t\t</body>\n\t\t\t</html>`}\n\t\t/>\n\t)\n}\n"],
|
|
5
|
-
"mappings": "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
|
|
4
|
+
"sourcesContent": ["/* eslint-disable react-hooks/rules-of-hooks */\n\nimport {\n\tBaseBoxShapeUtil,\n\tHTMLContainer,\n\tRectangle2d,\n\tTLEmbedShape,\n\tTLEmbedShapeProps,\n\tTLResizeInfo,\n\tembedShapeMigrations,\n\tembedShapeProps,\n\tlerp,\n\tresizeBox,\n\ttoDomPrecision,\n\tuseIsEditing,\n\tuseSvgExportContext,\n\tuseValue,\n} from '@tldraw/editor'\n\nimport {\n\tDEFAULT_EMBED_DEFINITIONS,\n\tEmbedDefinition,\n\tTLEmbedDefinition,\n\tTLEmbedShapePermissions,\n\tembedShapePermissionDefaults,\n} from '../../defaultEmbedDefinitions'\nimport { TLEmbedResult, getEmbedInfo } from '../../utils/embeds/embeds'\nimport { BookmarkIndicatorComponent, BookmarkShapeComponent } from '../bookmark/BookmarkShapeUtil'\nimport { BOOKMARK_JUST_URL_HEIGHT, BOOKMARK_WIDTH } from '../bookmark/bookmarks'\nimport { getRotatedBoxShadow } from '../shared/rotated-box-shadow'\n\nconst getSandboxPermissions = (permissions: TLEmbedShapePermissions) => {\n\treturn Object.entries(permissions)\n\t\t.filter(([_perm, isEnabled]) => isEnabled)\n\t\t.map(([perm]) => perm)\n\t\t.join(' ')\n}\n\n/** @public */\nexport class EmbedShapeUtil extends BaseBoxShapeUtil<TLEmbedShape> {\n\tstatic override type = 'embed' as const\n\tstatic override props = embedShapeProps\n\tstatic override migrations = embedShapeMigrations\n\tprivate static embedDefinitions: readonly EmbedDefinition[] = DEFAULT_EMBED_DEFINITIONS\n\n\tstatic setEmbedDefinitions(embedDefinitions: readonly TLEmbedDefinition[]) {\n\t\tEmbedShapeUtil.embedDefinitions = embedDefinitions\n\t}\n\n\tgetEmbedDefinitions(): readonly TLEmbedDefinition[] {\n\t\treturn EmbedShapeUtil.embedDefinitions\n\t}\n\n\tgetEmbedDefinition(url: string): TLEmbedResult {\n\t\treturn getEmbedInfo(EmbedShapeUtil.embedDefinitions, url)\n\t}\n\n\toverride getText(shape: TLEmbedShape) {\n\t\treturn shape.props.url\n\t}\n\n\toverride getAriaDescriptor(shape: TLEmbedShape) {\n\t\tconst embedInfo = this.getEmbedDefinition(shape.props.url)\n\t\treturn embedInfo?.definition.title\n\t}\n\n\toverride hideSelectionBoundsFg(shape: TLEmbedShape) {\n\t\treturn !this.canResize(shape)\n\t}\n\toverride canEdit() {\n\t\treturn true\n\t}\n\toverride canResize(shape: TLEmbedShape) {\n\t\treturn !!this.getEmbedDefinition(shape.props.url)?.definition?.doesResize\n\t}\n\toverride canEditInReadonly() {\n\t\treturn true\n\t}\n\n\toverride getDefaultProps(): TLEmbedShape['props'] {\n\t\treturn {\n\t\t\tw: 300,\n\t\t\th: 300,\n\t\t\turl: '',\n\t\t}\n\t}\n\n\toverride getGeometry(shape: TLEmbedShape) {\n\t\tconst embedInfo = this.getEmbedDefinition(shape.props.url)\n\t\tif (!embedInfo?.definition) {\n\t\t\treturn new Rectangle2d({\n\t\t\t\twidth: BOOKMARK_WIDTH,\n\t\t\t\theight: BOOKMARK_JUST_URL_HEIGHT,\n\t\t\t\tisFilled: true,\n\t\t\t})\n\t\t}\n\t\treturn super.getGeometry(shape)\n\t}\n\n\toverride isAspectRatioLocked(shape: TLEmbedShape) {\n\t\tconst embedInfo = this.getEmbedDefinition(shape.props.url)\n\t\treturn embedInfo?.definition.isAspectRatioLocked ?? false\n\t}\n\n\toverride onResize(shape: TLEmbedShape, info: TLResizeInfo<TLEmbedShape>) {\n\t\tconst isAspectRatioLocked = this.isAspectRatioLocked(shape)\n\t\tconst embedInfo = this.getEmbedDefinition(shape.props.url)\n\t\tlet minWidth = embedInfo?.definition.minWidth ?? 200\n\t\tlet minHeight = embedInfo?.definition.minHeight ?? 200\n\t\tif (isAspectRatioLocked) {\n\t\t\t// Enforce aspect ratio\n\t\t\t// Neither the width or height can be less than 200\n\t\t\tconst aspectRatio = shape.props.w / shape.props.h\n\t\t\tif (aspectRatio > 1) {\n\t\t\t\t// Landscape\n\t\t\t\tminWidth *= aspectRatio\n\t\t\t} else {\n\t\t\t\t// Portrait\n\t\t\t\tminHeight /= aspectRatio\n\t\t\t}\n\t\t}\n\n\t\treturn resizeBox(shape, info, { minWidth, minHeight })\n\t}\n\n\toverride component(shape: TLEmbedShape) {\n\t\tconst svgExport = useSvgExportContext()\n\t\tconst { w, h, url } = shape.props\n\t\tconst isEditing = useIsEditing(shape.id)\n\n\t\tconst embedInfo = this.getEmbedDefinition(url)\n\n\t\tconst isHoveringWhileEditingSameShape = useValue(\n\t\t\t'is hovering',\n\t\t\t() => {\n\t\t\t\tconst { editingShapeId, hoveredShapeId } = this.editor.getCurrentPageState()\n\n\t\t\t\tif (editingShapeId && hoveredShapeId !== editingShapeId) {\n\t\t\t\t\tconst editingShape = this.editor.getShape(editingShapeId)\n\t\t\t\t\tif (editingShape && this.editor.isShapeOfType(editingShape, 'embed')) {\n\t\t\t\t\t\treturn true\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\treturn false\n\t\t\t},\n\t\t\t[]\n\t\t)\n\n\t\tconst pageRotation = this.editor.getShapePageTransform(shape)!.rotation()\n\n\t\tif (svgExport) {\n\t\t\t// for SVG exports, we show a blank embed\n\t\t\treturn (\n\t\t\t\t<HTMLContainer className=\"tl-embed-container\" id={shape.id}>\n\t\t\t\t\t<div\n\t\t\t\t\t\tclassName=\"tl-embed\"\n\t\t\t\t\t\tstyle={{\n\t\t\t\t\t\t\tborder: 0,\n\t\t\t\t\t\t\tboxShadow: getRotatedBoxShadow(pageRotation),\n\t\t\t\t\t\t\tborderRadius: embedInfo?.definition.overrideOutlineRadius ?? 8,\n\t\t\t\t\t\t\tbackground: embedInfo?.definition.backgroundColor ?? 'var(--tl-color-background)',\n\t\t\t\t\t\t\twidth: w,\n\t\t\t\t\t\t\theight: h,\n\t\t\t\t\t\t}}\n\t\t\t\t\t/>\n\t\t\t\t</HTMLContainer>\n\t\t\t)\n\t\t}\n\n\t\tconst isInteractive = isEditing || isHoveringWhileEditingSameShape\n\n\t\t// Prevent nested embedding of tldraw\n\t\tconst isIframe =\n\t\t\ttypeof window !== 'undefined' && (window !== window.top || window.self !== window.parent)\n\t\tif (isIframe && embedInfo?.definition.type === 'tldraw') return null\n\n\t\tif (embedInfo?.definition.type === 'github_gist') {\n\t\t\tconst idFromGistUrl = embedInfo.url.split('/').pop()\n\t\t\tif (!idFromGistUrl) throw Error('No gist id!')\n\n\t\t\treturn (\n\t\t\t\t<HTMLContainer className=\"tl-embed-container\" id={shape.id}>\n\t\t\t\t\t<Gist\n\t\t\t\t\t\tid={idFromGistUrl}\n\t\t\t\t\t\twidth={toDomPrecision(w)!}\n\t\t\t\t\t\theight={toDomPrecision(h)!}\n\t\t\t\t\t\tisInteractive={isInteractive}\n\t\t\t\t\t\tpageRotation={pageRotation}\n\t\t\t\t\t/>\n\t\t\t\t</HTMLContainer>\n\t\t\t)\n\t\t}\n\n\t\tconst sandbox = getSandboxPermissions({\n\t\t\t...embedShapePermissionDefaults,\n\t\t\t...(embedInfo?.definition.overridePermissions ?? {}),\n\t\t})\n\n\t\treturn (\n\t\t\t<HTMLContainer className=\"tl-embed-container\" id={shape.id}>\n\t\t\t\t{embedInfo?.definition ? (\n\t\t\t\t\t<iframe\n\t\t\t\t\t\tclassName=\"tl-embed\"\n\t\t\t\t\t\tsandbox={sandbox}\n\t\t\t\t\t\tsrc={embedInfo.embedUrl}\n\t\t\t\t\t\twidth={toDomPrecision(w)}\n\t\t\t\t\t\theight={toDomPrecision(h)}\n\t\t\t\t\t\tdraggable={false}\n\t\t\t\t\t\t// eslint-disable-next-line @typescript-eslint/no-deprecated\n\t\t\t\t\t\tframeBorder=\"0\"\n\t\t\t\t\t\treferrerPolicy=\"no-referrer-when-downgrade\"\n\t\t\t\t\t\ttabIndex={isEditing ? 0 : -1}\n\t\t\t\t\t\tstyle={{\n\t\t\t\t\t\t\tborder: 0,\n\t\t\t\t\t\t\tpointerEvents: isInteractive ? 'auto' : 'none',\n\t\t\t\t\t\t\t// Fix for safari <https://stackoverflow.com/a/49150908>\n\t\t\t\t\t\t\tzIndex: isInteractive ? '' : '-1',\n\t\t\t\t\t\t\tboxShadow: getRotatedBoxShadow(pageRotation),\n\t\t\t\t\t\t\tborderRadius: embedInfo?.definition.overrideOutlineRadius ?? 8,\n\t\t\t\t\t\t\tbackground: embedInfo?.definition.backgroundColor,\n\t\t\t\t\t\t}}\n\t\t\t\t\t/>\n\t\t\t\t) : (\n\t\t\t\t\t<BookmarkShapeComponent\n\t\t\t\t\t\turl={url}\n\t\t\t\t\t\th={h}\n\t\t\t\t\t\trotation={pageRotation}\n\t\t\t\t\t\tassetId={null}\n\t\t\t\t\t\tshowImageContainer={false}\n\t\t\t\t\t/>\n\t\t\t\t)}\n\t\t\t</HTMLContainer>\n\t\t)\n\t}\n\n\toverride indicator(shape: TLEmbedShape) {\n\t\tconst embedInfo = this.getEmbedDefinition(shape.props.url)\n\n\t\treturn embedInfo?.definition ? (\n\t\t\t<rect\n\t\t\t\twidth={toDomPrecision(shape.props.w)}\n\t\t\t\theight={toDomPrecision(shape.props.h)}\n\t\t\t\trx={embedInfo?.definition.overrideOutlineRadius ?? 8}\n\t\t\t\try={embedInfo?.definition.overrideOutlineRadius ?? 8}\n\t\t\t/>\n\t\t) : (\n\t\t\t<BookmarkIndicatorComponent w={BOOKMARK_WIDTH} h={BOOKMARK_JUST_URL_HEIGHT} />\n\t\t)\n\t}\n\toverride getInterpolatedProps(\n\t\tstartShape: TLEmbedShape,\n\t\tendShape: TLEmbedShape,\n\t\tt: number\n\t): TLEmbedShapeProps {\n\t\treturn {\n\t\t\t...(t > 0.5 ? endShape.props : startShape.props),\n\t\t\tw: lerp(startShape.props.w, endShape.props.w, t),\n\t\t\th: lerp(startShape.props.h, endShape.props.h, t),\n\t\t}\n\t}\n}\n\nfunction Gist({\n\tid,\n\tisInteractive,\n\twidth,\n\theight,\n\tstyle,\n\tpageRotation,\n}: {\n\tid: string\n\tisInteractive: boolean\n\twidth: number\n\theight: number\n\tpageRotation: number\n\tstyle?: React.CSSProperties\n}) {\n\t// Security warning:\n\t// Gists allow adding .json extensions to the URL which return JSONP.\n\t// Furthermore, the JSONP can include callbacks that execute arbitrary JavaScript.\n\t// It _is_ sandboxed by the iframe but we still want to disable it nonetheless.\n\t// We restrict the id to only allow hexdecimal characters to prevent this.\n\t// Read more:\n\t// https://github.com/bhaveshk90/Content-Security-Policy-CSP-Bypass-Techniques\n\t// https://github.com/renniepak/CSPBypass\n\tif (!id.match(/^[0-9a-f]+$/)) throw Error('No gist id!')\n\n\treturn (\n\t\t<iframe\n\t\t\tclassName=\"tl-embed\"\n\t\t\tdraggable={false}\n\t\t\twidth={toDomPrecision(width)}\n\t\t\theight={toDomPrecision(height)}\n\t\t\t// eslint-disable-next-line @typescript-eslint/no-deprecated\n\t\t\tframeBorder=\"0\"\n\t\t\t// eslint-disable-next-line @typescript-eslint/no-deprecated\n\t\t\tscrolling=\"no\"\n\t\t\treferrerPolicy=\"no-referrer-when-downgrade\"\n\t\t\ttabIndex={isInteractive ? 0 : -1}\n\t\t\tstyle={{\n\t\t\t\t...style,\n\t\t\t\tpointerEvents: isInteractive ? 'all' : 'none',\n\t\t\t\t// Fix for safari <https://stackoverflow.com/a/49150908>\n\t\t\t\tzIndex: isInteractive ? '' : '-1',\n\t\t\t\tboxShadow: getRotatedBoxShadow(pageRotation),\n\t\t\t}}\n\t\t\tsrcDoc={`\n\t\t\t<html>\n\t\t\t\t<head>\n\t\t\t\t\t<base target=\"_blank\">\n\t\t\t\t</head>\n\t\t\t\t<body>\n\t\t\t\t\t<script src=${`https://gist.github.com/${id}.js`}></script>\n\t\t\t\t\t<style type=\"text/css\">\n\t\t\t\t\t\t* { margin: 0px; }\n\t\t\t\t\t\ttable { height: 100%; background-color: red; }\n\t\t\t\t\t\t.gist { background-color: none; height: 100%; }\n\t\t\t\t\t\t.gist .gist-file { height: calc(100vh - 2px); padding: 0px; display: grid; grid-template-rows: 1fr auto; }\n\t\t\t\t\t</style>\n\t\t\t\t</body>\n\t\t\t</html>`}\n\t\t/>\n\t)\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../../src/lib/shapes/frame/FrameShapeTool.ts"],
|
|
4
|
-
"sourcesContent": ["import { BaseBoxShapeTool, TLShape, TLShapeId } from '@tldraw/editor'\n\n/** @public */\nexport class FrameShapeTool extends BaseBoxShapeTool {\n\tstatic override id = 'frame'\n\tstatic override initial = 'idle'\n\toverride shapeType = 'frame'\n\n\toverride onCreate(shape: TLShape | null): void {\n\t\tif (!shape) return\n\n\t\tconst bounds = this.editor.getShapePageBounds(shape)!\n\t\tconst shapesToAddToFrame: TLShapeId[] = []\n\t\tconst ancestorIds = this.editor.getShapeAncestors(shape).map((shape) => shape.id)\n\n\t\tthis.editor.getSortedChildIdsForParent(shape.parentId).map((siblingShapeId) => {\n\t\t\tconst siblingShape = this.editor.getShape(siblingShapeId)\n\t\t\tif (!siblingShape) return\n\t\t\t// We don't want to frame the frame itself\n\t\t\tif (siblingShape.id === shape.id) return\n\t\t\tif (siblingShape.isLocked) return\n\n\t\t\tconst pageShapeBounds = this.editor.getShapePageBounds(siblingShape)\n\t\t\tif (!pageShapeBounds) return\n\n\t\t\t// Frame shape encloses page shape\n\t\t\tif (bounds.contains(pageShapeBounds)) {\n\t\t\t\tif (canEnclose(siblingShape, ancestorIds, shape)) {\n\t\t\t\t\tshapesToAddToFrame.push(siblingShape.id)\n\t\t\t\t}\n\t\t\t}\n\t\t})\n\n\t\tthis.editor.reparentShapes(shapesToAddToFrame, shape.id)\n\n\t\tif (this.editor.getInstanceState().isToolLocked) {\n\t\t\tthis.editor.setCurrentTool('frame')\n\t\t} else {\n\t\t\tthis.editor.setCurrentTool('select.idle')\n\t\t}\n\t}\n}\n\n/** @internal */\nfunction canEnclose(shape: TLShape, ancestorIds: TLShapeId[], frame: TLShape): boolean {\n\t// We don't want to pull in shapes that are ancestors of the frame (can create a cycle)\n\tif (ancestorIds.includes(shape.id)) {\n\t\treturn false\n\t}\n\t// We only want to pull in shapes that are siblings of the frame\n\tif (shape.parentId === frame.parentId) {\n\t\treturn true\n\t}\n\treturn false\n}\n"],
|
|
4
|
+
"sourcesContent": ["import { BaseBoxShapeTool, TLShape, TLShapeId } from '@tldraw/editor'\n\n/** @public */\nexport class FrameShapeTool extends BaseBoxShapeTool {\n\tstatic override id = 'frame'\n\tstatic override initial = 'idle'\n\toverride shapeType = 'frame' as const\n\n\toverride onCreate(shape: TLShape | null): void {\n\t\tif (!shape) return\n\n\t\tconst bounds = this.editor.getShapePageBounds(shape)!\n\t\tconst shapesToAddToFrame: TLShapeId[] = []\n\t\tconst ancestorIds = this.editor.getShapeAncestors(shape).map((shape) => shape.id)\n\n\t\tthis.editor.getSortedChildIdsForParent(shape.parentId).map((siblingShapeId) => {\n\t\t\tconst siblingShape = this.editor.getShape(siblingShapeId)\n\t\t\tif (!siblingShape) return\n\t\t\t// We don't want to frame the frame itself\n\t\t\tif (siblingShape.id === shape.id) return\n\t\t\tif (siblingShape.isLocked) return\n\n\t\t\tconst pageShapeBounds = this.editor.getShapePageBounds(siblingShape)\n\t\t\tif (!pageShapeBounds) return\n\n\t\t\t// Frame shape encloses page shape\n\t\t\tif (bounds.contains(pageShapeBounds)) {\n\t\t\t\tif (canEnclose(siblingShape, ancestorIds, shape)) {\n\t\t\t\t\tshapesToAddToFrame.push(siblingShape.id)\n\t\t\t\t}\n\t\t\t}\n\t\t})\n\n\t\tthis.editor.reparentShapes(shapesToAddToFrame, shape.id)\n\n\t\tif (this.editor.getInstanceState().isToolLocked) {\n\t\t\tthis.editor.setCurrentTool('frame')\n\t\t} else {\n\t\t\tthis.editor.setCurrentTool('select.idle')\n\t\t}\n\t}\n}\n\n/** @internal */\nfunction canEnclose(shape: TLShape, ancestorIds: TLShapeId[], frame: TLShape): boolean {\n\t// We don't want to pull in shapes that are ancestors of the frame (can create a cycle)\n\tif (ancestorIds.includes(shape.id)) {\n\t\treturn false\n\t}\n\t// We only want to pull in shapes that are siblings of the frame\n\tif (shape.parentId === frame.parentId) {\n\t\treturn true\n\t}\n\treturn false\n}\n"],
|
|
5
5
|
"mappings": "AAAA,SAAS,wBAA4C;AAG9C,MAAM,uBAAuB,iBAAiB;AAAA,EACpD,OAAgB,KAAK;AAAA,EACrB,OAAgB,UAAU;AAAA,EACjB,YAAY;AAAA,EAEZ,SAAS,OAA6B;AAC9C,QAAI,CAAC,MAAO;AAEZ,UAAM,SAAS,KAAK,OAAO,mBAAmB,KAAK;AACnD,UAAM,qBAAkC,CAAC;AACzC,UAAM,cAAc,KAAK,OAAO,kBAAkB,KAAK,EAAE,IAAI,CAACA,WAAUA,OAAM,EAAE;AAEhF,SAAK,OAAO,2BAA2B,MAAM,QAAQ,EAAE,IAAI,CAAC,mBAAmB;AAC9E,YAAM,eAAe,KAAK,OAAO,SAAS,cAAc;AACxD,UAAI,CAAC,aAAc;AAEnB,UAAI,aAAa,OAAO,MAAM,GAAI;AAClC,UAAI,aAAa,SAAU;AAE3B,YAAM,kBAAkB,KAAK,OAAO,mBAAmB,YAAY;AACnE,UAAI,CAAC,gBAAiB;AAGtB,UAAI,OAAO,SAAS,eAAe,GAAG;AACrC,YAAI,WAAW,cAAc,aAAa,KAAK,GAAG;AACjD,6BAAmB,KAAK,aAAa,EAAE;AAAA,QACxC;AAAA,MACD;AAAA,IACD,CAAC;AAED,SAAK,OAAO,eAAe,oBAAoB,MAAM,EAAE;AAEvD,QAAI,KAAK,OAAO,iBAAiB,EAAE,cAAc;AAChD,WAAK,OAAO,eAAe,OAAO;AAAA,IACnC,OAAO;AACN,WAAK,OAAO,eAAe,aAAa;AAAA,IACzC;AAAA,EACD;AACD;AAGA,SAAS,WAAW,OAAgB,aAA0B,OAAyB;AAEtF,MAAI,YAAY,SAAS,MAAM,EAAE,GAAG;AACnC,WAAO;AAAA,EACR;AAEA,MAAI,MAAM,aAAa,MAAM,UAAU;AACtC,WAAO;AAAA,EACR;AACA,SAAO;AACR;",
|
|
6
6
|
"names": ["shape"]
|
|
7
7
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../../../src/lib/shapes/geo/toolStates/Pointing.ts"],
|
|
4
|
-
"sourcesContent": ["import {\n\tGeoShapeGeoStyle,\n\tStateNode,\n\tTLGeoShape,\n\tTLPointerEventInfo,\n\tVec,\n\tcreateShapeId,\n\tmaybeSnapToGrid,\n} from '@tldraw/editor'\n\nexport class Pointing extends StateNode {\n\tstatic override id = 'pointing'\n\n\toverride onPointerUp() {\n\t\tthis.complete()\n\t}\n\n\toverride onPointerMove(info: TLPointerEventInfo) {\n\t\tif (this.editor.inputs.isDragging) {\n\t\t\tconst { originPagePoint } = this.editor.inputs\n\n\t\t\tconst id = createShapeId()\n\n\t\t\tconst creatingMarkId = this.editor.markHistoryStoppingPoint(`creating_geo:${id}`)\n\t\t\tconst newPoint = maybeSnapToGrid(originPagePoint, this.editor)\n\t\t\tthis.editor\n\t\t\t\t.createShapes
|
|
5
|
-
"mappings": "AAAA;AAAA,EACC;AAAA,EACA;AAAA,EAGA;AAAA,EACA;AAAA,EACA;AAAA,OACM;AAEA,MAAM,iBAAiB,UAAU;AAAA,EACvC,OAAgB,KAAK;AAAA,EAEZ,cAAc;AACtB,SAAK,SAAS;AAAA,EACf;AAAA,EAES,cAAc,MAA0B;AAChD,QAAI,KAAK,OAAO,OAAO,YAAY;AAClC,YAAM,EAAE,gBAAgB,IAAI,KAAK,OAAO;AAExC,YAAM,KAAK,cAAc;AAEzB,YAAM,iBAAiB,KAAK,OAAO,yBAAyB,gBAAgB,EAAE,EAAE;AAChF,YAAM,WAAW,gBAAgB,iBAAiB,KAAK,MAAM;AAC7D,WAAK,OACH,
|
|
4
|
+
"sourcesContent": ["import {\n\tGeoShapeGeoStyle,\n\tStateNode,\n\tTLGeoShape,\n\tTLPointerEventInfo,\n\tVec,\n\tcreateShapeId,\n\tmaybeSnapToGrid,\n} from '@tldraw/editor'\n\nexport class Pointing extends StateNode {\n\tstatic override id = 'pointing'\n\n\toverride onPointerUp() {\n\t\tthis.complete()\n\t}\n\n\toverride onPointerMove(info: TLPointerEventInfo) {\n\t\tif (this.editor.inputs.isDragging) {\n\t\t\tconst { originPagePoint } = this.editor.inputs\n\n\t\t\tconst id = createShapeId()\n\n\t\t\tconst creatingMarkId = this.editor.markHistoryStoppingPoint(`creating_geo:${id}`)\n\t\t\tconst newPoint = maybeSnapToGrid(originPagePoint, this.editor)\n\t\t\tthis.editor\n\t\t\t\t.createShapes([\n\t\t\t\t\t{\n\t\t\t\t\t\tid,\n\t\t\t\t\t\ttype: 'geo',\n\t\t\t\t\t\tx: newPoint.x,\n\t\t\t\t\t\ty: newPoint.y,\n\t\t\t\t\t\tprops: {\n\t\t\t\t\t\t\tw: 1,\n\t\t\t\t\t\t\th: 1,\n\t\t\t\t\t\t\tgeo: this.editor.getStyleForNextShape(GeoShapeGeoStyle),\n\t\t\t\t\t\t\tscale: this.editor.user.getIsDynamicResizeMode() ? 1 / this.editor.getZoomLevel() : 1,\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t])\n\t\t\t\t.select(id)\n\n\t\t\tconst shape = this.editor.getShape(id)\n\t\t\tif (!shape) {\n\t\t\t\tthis.cancel()\n\t\t\t\treturn\n\t\t\t}\n\n\t\t\tthis.editor.setCurrentTool('select.resizing', {\n\t\t\t\t...info,\n\t\t\t\ttarget: 'selection',\n\t\t\t\thandle: 'bottom_right',\n\t\t\t\tisCreating: true,\n\t\t\t\tcreatingMarkId,\n\t\t\t\tcreationCursorOffset: { x: 1, y: 1 },\n\t\t\t\tonInteractionEnd: 'geo',\n\t\t\t})\n\t\t}\n\t}\n\n\toverride onCancel() {\n\t\tthis.cancel()\n\t}\n\n\toverride onComplete() {\n\t\tthis.complete()\n\t}\n\n\toverride onInterrupt() {\n\t\tthis.cancel()\n\t}\n\n\tprivate complete() {\n\t\tconst { originPagePoint } = this.editor.inputs\n\n\t\tconst id = createShapeId()\n\n\t\tthis.editor.markHistoryStoppingPoint(`creating_geo:${id}`)\n\n\t\tconst scale = this.editor.user.getIsDynamicResizeMode() ? 1 / this.editor.getZoomLevel() : 1\n\n\t\tconst geo = this.editor.getStyleForNextShape(GeoShapeGeoStyle)\n\n\t\tconst size =\n\t\t\tgeo === 'star'\n\t\t\t\t? { w: 200, h: 190 }\n\t\t\t\t: geo === 'cloud'\n\t\t\t\t\t? { w: 300, h: 180 }\n\t\t\t\t\t: { w: 200, h: 200 }\n\n\t\tthis.editor.createShapes([\n\t\t\t{\n\t\t\t\tid,\n\t\t\t\ttype: 'geo',\n\t\t\t\tx: originPagePoint.x,\n\t\t\t\ty: originPagePoint.y,\n\t\t\t\tprops: {\n\t\t\t\t\tgeo: this.editor.getStyleForNextShape(GeoShapeGeoStyle),\n\t\t\t\t\tscale,\n\t\t\t\t\t...size,\n\t\t\t\t},\n\t\t\t},\n\t\t])\n\n\t\tconst shape = this.editor.getShape<TLGeoShape>(id)!\n\t\tif (!shape) {\n\t\t\tthis.cancel()\n\t\t\treturn\n\t\t}\n\n\t\tconst { w, h } = shape.props\n\n\t\tconst delta = new Vec(w / 2, h / 2).mul(scale)\n\t\tconst parentTransform = this.editor.getShapeParentTransform(shape)\n\t\tif (parentTransform) delta.rot(-parentTransform.rotation())\n\t\tconst newPoint = maybeSnapToGrid(new Vec(shape.x - delta.x, shape.y - delta.y), this.editor)\n\t\tthis.editor.select(id)\n\t\tthis.editor.updateShape({\n\t\t\tid: shape.id,\n\t\t\ttype: 'geo',\n\t\t\tx: newPoint.x,\n\t\t\ty: newPoint.y,\n\t\t\tprops: {\n\t\t\t\tgeo: this.editor.getStyleForNextShape(GeoShapeGeoStyle),\n\t\t\t\tw: w * scale,\n\t\t\t\th: h * scale,\n\t\t\t},\n\t\t})\n\n\t\tif (this.editor.getInstanceState().isToolLocked) {\n\t\t\tthis.parent.transition('idle')\n\t\t} else {\n\t\t\tthis.editor.setCurrentTool('select', {})\n\t\t}\n\t}\n\n\tprivate cancel() {\n\t\t// we should not have created any shapes yet, so no need to bail\n\t\tthis.parent.transition('idle')\n\t}\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../../../src/lib/shapes/line/toolStates/Pointing.ts"],
|
|
4
|
-
"sourcesContent": ["import {\n\tMat,\n\tStateNode,\n\tTLLineShape,\n\tTLShapeId,\n\tVec,\n\tcreateShapeId,\n\tgetIndexAbove,\n\tlast,\n\tmaybeSnapToGrid,\n\tsortByIndex,\n\tstructuredClone,\n} from '@tldraw/editor'\n\nconst MINIMUM_DISTANCE_BETWEEN_SHIFT_CLICKED_HANDLES = 2\n\nexport class Pointing extends StateNode {\n\tstatic override id = 'pointing'\n\n\tshape = {} as TLLineShape\n\n\tmarkId: string | undefined\n\n\toverride onEnter(info: { shapeId?: TLShapeId }) {\n\t\tconst { inputs } = this.editor\n\t\tconst { currentPagePoint } = inputs\n\n\t\tthis.markId = undefined\n\n\t\t// Previously created line shape that we might be extending\n\t\tconst shape = info.shapeId && this.editor.getShape<TLLineShape>(info.shapeId)\n\n\t\tif (shape && inputs.shiftKey) {\n\t\t\t// Extending a previous shape\n\t\t\tthis.markId = this.editor.markHistoryStoppingPoint(`creating_line:${shape.id}`)\n\t\t\tthis.shape = shape\n\n\t\t\tconst handles = this.editor.getShapeHandles(this.shape)\n\t\t\tif (!handles) return\n\n\t\t\tconst vertexHandles = handles.filter((h) => h.type === 'vertex').sort(sortByIndex)\n\t\t\tconst endHandle = vertexHandles[vertexHandles.length - 1]\n\t\t\tconst prevEndHandle = vertexHandles[vertexHandles.length - 2]\n\n\t\t\tconst shapePagePoint = Mat.applyToPoint(\n\t\t\t\tthis.editor.getShapeParentTransform(this.shape)!,\n\t\t\t\tnew Vec(this.shape.x, this.shape.y)\n\t\t\t)\n\t\t\t// nudge the point slightly to avoid zero-length lines\n\t\t\tconst nudgedPoint = Vec.Sub(currentPagePoint, shapePagePoint).addXY(0.1, 0.1)\n\t\t\tconst nextPoint = maybeSnapToGrid(nudgedPoint, this.editor)\n\t\t\tconst points = structuredClone(this.shape.props.points)\n\n\t\t\tif (\n\t\t\t\tVec.DistMin(endHandle, prevEndHandle, MINIMUM_DISTANCE_BETWEEN_SHIFT_CLICKED_HANDLES) ||\n\t\t\t\tVec.DistMin(nextPoint, endHandle, MINIMUM_DISTANCE_BETWEEN_SHIFT_CLICKED_HANDLES)\n\t\t\t) {\n\t\t\t\t// Don't add a new point if the distance between the last two points is too small\n\t\t\t\tpoints[endHandle.id] = {\n\t\t\t\t\tid: endHandle.id,\n\t\t\t\t\tindex: endHandle.index,\n\t\t\t\t\tx: nextPoint.x,\n\t\t\t\t\ty: nextPoint.y,\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\t// Add a new point\n\t\t\t\tconst nextIndex = getIndexAbove(endHandle.index)\n\t\t\t\tpoints[nextIndex] = {\n\t\t\t\t\tid: nextIndex,\n\t\t\t\t\tindex: nextIndex,\n\t\t\t\t\tx: nextPoint.x,\n\t\t\t\t\ty: nextPoint.y,\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tthis.editor.updateShapes([\n\t\t\t\t{\n\t\t\t\t\tid: this.shape.id,\n\t\t\t\t\ttype: this.shape.type,\n\t\t\t\t\tprops: {\n\t\t\t\t\t\tpoints,\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t])\n\t\t} else {\n\t\t\tconst id = createShapeId()\n\n\t\t\tthis.markId = this.editor.markHistoryStoppingPoint(`creating_line:${id}`)\n\n\t\t\tconst newPoint = maybeSnapToGrid(currentPagePoint, this.editor)\n\n\t\t\tthis.editor.createShapes
|
|
5
|
-
"mappings": "AAAA;AAAA,EACC;AAAA,EACA;AAAA,EAGA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACM;AAEP,MAAM,iDAAiD;AAEhD,MAAM,iBAAiB,UAAU;AAAA,EACvC,OAAgB,KAAK;AAAA,EAErB,QAAQ,CAAC;AAAA,EAET;AAAA,EAES,QAAQ,MAA+B;AAC/C,UAAM,EAAE,OAAO,IAAI,KAAK;AACxB,UAAM,EAAE,iBAAiB,IAAI;AAE7B,SAAK,SAAS;AAGd,UAAM,QAAQ,KAAK,WAAW,KAAK,OAAO,SAAsB,KAAK,OAAO;AAE5E,QAAI,SAAS,OAAO,UAAU;AAE7B,WAAK,SAAS,KAAK,OAAO,yBAAyB,iBAAiB,MAAM,EAAE,EAAE;AAC9E,WAAK,QAAQ;AAEb,YAAM,UAAU,KAAK,OAAO,gBAAgB,KAAK,KAAK;AACtD,UAAI,CAAC,QAAS;AAEd,YAAM,gBAAgB,QAAQ,OAAO,CAAC,MAAM,EAAE,SAAS,QAAQ,EAAE,KAAK,WAAW;AACjF,YAAM,YAAY,cAAc,cAAc,SAAS,CAAC;AACxD,YAAM,gBAAgB,cAAc,cAAc,SAAS,CAAC;AAE5D,YAAM,iBAAiB,IAAI;AAAA,QAC1B,KAAK,OAAO,wBAAwB,KAAK,KAAK;AAAA,QAC9C,IAAI,IAAI,KAAK,MAAM,GAAG,KAAK,MAAM,CAAC;AAAA,MACnC;AAEA,YAAM,cAAc,IAAI,IAAI,kBAAkB,cAAc,EAAE,MAAM,KAAK,GAAG;AAC5E,YAAM,YAAY,gBAAgB,aAAa,KAAK,MAAM;AAC1D,YAAM,SAAS,gBAAgB,KAAK,MAAM,MAAM,MAAM;AAEtD,UACC,IAAI,QAAQ,WAAW,eAAe,8CAA8C,KACpF,IAAI,QAAQ,WAAW,WAAW,8CAA8C,GAC/E;AAED,eAAO,UAAU,EAAE,IAAI;AAAA,UACtB,IAAI,UAAU;AAAA,UACd,OAAO,UAAU;AAAA,UACjB,GAAG,UAAU;AAAA,UACb,GAAG,UAAU;AAAA,QACd;AAAA,MACD,OAAO;AAEN,cAAM,YAAY,cAAc,UAAU,KAAK;AAC/C,eAAO,SAAS,IAAI;AAAA,UACnB,IAAI;AAAA,UACJ,OAAO;AAAA,UACP,GAAG,UAAU;AAAA,UACb,GAAG,UAAU;AAAA,QACd;AAAA,MACD;AAEA,WAAK,OAAO,aAAa;AAAA,QACxB;AAAA,UACC,IAAI,KAAK,MAAM;AAAA,UACf,MAAM,KAAK,MAAM;AAAA,UACjB,OAAO;AAAA,YACN;AAAA,UACD;AAAA,QACD;AAAA,MACD,CAAC;AAAA,IACF,OAAO;AACN,YAAM,KAAK,cAAc;AAEzB,WAAK,SAAS,KAAK,OAAO,yBAAyB,iBAAiB,EAAE,EAAE;AAExE,YAAM,WAAW,gBAAgB,kBAAkB,KAAK,MAAM;AAE9D,WAAK,OAAO,
|
|
4
|
+
"sourcesContent": ["import {\n\tMat,\n\tStateNode,\n\tTLLineShape,\n\tTLShapeId,\n\tVec,\n\tcreateShapeId,\n\tgetIndexAbove,\n\tlast,\n\tmaybeSnapToGrid,\n\tsortByIndex,\n\tstructuredClone,\n} from '@tldraw/editor'\n\nconst MINIMUM_DISTANCE_BETWEEN_SHIFT_CLICKED_HANDLES = 2\n\nexport class Pointing extends StateNode {\n\tstatic override id = 'pointing'\n\n\tshape = {} as TLLineShape\n\n\tmarkId: string | undefined\n\n\toverride onEnter(info: { shapeId?: TLShapeId }) {\n\t\tconst { inputs } = this.editor\n\t\tconst { currentPagePoint } = inputs\n\n\t\tthis.markId = undefined\n\n\t\t// Previously created line shape that we might be extending\n\t\tconst shape = info.shapeId && this.editor.getShape<TLLineShape>(info.shapeId)\n\n\t\tif (shape && inputs.shiftKey) {\n\t\t\t// Extending a previous shape\n\t\t\tthis.markId = this.editor.markHistoryStoppingPoint(`creating_line:${shape.id}`)\n\t\t\tthis.shape = shape\n\n\t\t\tconst handles = this.editor.getShapeHandles(this.shape)\n\t\t\tif (!handles) return\n\n\t\t\tconst vertexHandles = handles.filter((h) => h.type === 'vertex').sort(sortByIndex)\n\t\t\tconst endHandle = vertexHandles[vertexHandles.length - 1]\n\t\t\tconst prevEndHandle = vertexHandles[vertexHandles.length - 2]\n\n\t\t\tconst shapePagePoint = Mat.applyToPoint(\n\t\t\t\tthis.editor.getShapeParentTransform(this.shape)!,\n\t\t\t\tnew Vec(this.shape.x, this.shape.y)\n\t\t\t)\n\t\t\t// nudge the point slightly to avoid zero-length lines\n\t\t\tconst nudgedPoint = Vec.Sub(currentPagePoint, shapePagePoint).addXY(0.1, 0.1)\n\t\t\tconst nextPoint = maybeSnapToGrid(nudgedPoint, this.editor)\n\t\t\tconst points = structuredClone(this.shape.props.points)\n\n\t\t\tif (\n\t\t\t\tVec.DistMin(endHandle, prevEndHandle, MINIMUM_DISTANCE_BETWEEN_SHIFT_CLICKED_HANDLES) ||\n\t\t\t\tVec.DistMin(nextPoint, endHandle, MINIMUM_DISTANCE_BETWEEN_SHIFT_CLICKED_HANDLES)\n\t\t\t) {\n\t\t\t\t// Don't add a new point if the distance between the last two points is too small\n\t\t\t\tpoints[endHandle.id] = {\n\t\t\t\t\tid: endHandle.id,\n\t\t\t\t\tindex: endHandle.index,\n\t\t\t\t\tx: nextPoint.x,\n\t\t\t\t\ty: nextPoint.y,\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\t// Add a new point\n\t\t\t\tconst nextIndex = getIndexAbove(endHandle.index)\n\t\t\t\tpoints[nextIndex] = {\n\t\t\t\t\tid: nextIndex,\n\t\t\t\t\tindex: nextIndex,\n\t\t\t\t\tx: nextPoint.x,\n\t\t\t\t\ty: nextPoint.y,\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tthis.editor.updateShapes([\n\t\t\t\t{\n\t\t\t\t\tid: this.shape.id,\n\t\t\t\t\ttype: this.shape.type,\n\t\t\t\t\tprops: {\n\t\t\t\t\t\tpoints,\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t])\n\t\t} else {\n\t\t\tconst id = createShapeId()\n\n\t\t\tthis.markId = this.editor.markHistoryStoppingPoint(`creating_line:${id}`)\n\n\t\t\tconst newPoint = maybeSnapToGrid(currentPagePoint, this.editor)\n\n\t\t\tthis.editor.createShapes([\n\t\t\t\t{\n\t\t\t\t\tid,\n\t\t\t\t\ttype: 'line',\n\t\t\t\t\tx: newPoint.x,\n\t\t\t\t\ty: newPoint.y,\n\t\t\t\t\tprops: {\n\t\t\t\t\t\tscale: this.editor.user.getIsDynamicResizeMode() ? 1 / this.editor.getZoomLevel() : 1,\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t])\n\n\t\t\tif (!this.editor.getShape(id)) {\n\t\t\t\tthis.cancel()\n\t\t\t\treturn\n\t\t\t}\n\n\t\t\tthis.editor.select(id)\n\t\t\tthis.shape = this.editor.getShape(id)!\n\t\t}\n\t}\n\n\toverride onPointerMove() {\n\t\tif (!this.shape) return\n\n\t\tif (this.editor.inputs.isDragging) {\n\t\t\tconst handles = this.editor.getShapeHandles(this.shape)\n\t\t\tif (!handles) {\n\t\t\t\tif (this.markId) this.editor.bailToMark(this.markId)\n\t\t\t\tthrow Error('No handles found')\n\t\t\t}\n\t\t\tconst lastHandle = last(handles)!\n\t\t\tthis.editor.setCurrentTool('select.dragging_handle', {\n\t\t\t\tshape: this.shape,\n\t\t\t\tisCreating: true,\n\t\t\t\tcreatingMarkId: this.markId,\n\t\t\t\t// remove the offset that we added to the handle when we created it\n\t\t\t\thandle: { ...lastHandle, x: lastHandle.x - 0.1, y: lastHandle.y - 0.1 },\n\t\t\t\tonInteractionEnd: 'line',\n\t\t\t})\n\t\t}\n\t}\n\n\toverride onPointerUp() {\n\t\tthis.complete()\n\t}\n\n\toverride onCancel() {\n\t\tthis.cancel()\n\t}\n\n\toverride onComplete() {\n\t\tthis.complete()\n\t}\n\n\toverride onInterrupt() {\n\t\tthis.parent.transition('idle')\n\t\tif (this.markId) this.editor.bailToMark(this.markId)\n\t\tthis.editor.snaps.clearIndicators()\n\t}\n\n\tcomplete() {\n\t\tthis.parent.transition('idle', { shapeId: this.shape.id })\n\t\tthis.editor.snaps.clearIndicators()\n\t}\n\n\tcancel() {\n\t\tif (this.markId) this.editor.bailToMark(this.markId)\n\t\tthis.parent.transition('idle', { shapeId: this.shape.id })\n\t\tthis.editor.snaps.clearIndicators()\n\t}\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../../src/lib/shapes/note/noteHelpers.ts"],
|
|
4
|
-
"sourcesContent": ["import {\n\tEditor,\n\tIndexKey,\n\tTLNoteShape,\n\tTLShape,\n\tVec,\n\tcompact,\n\tcreateShapeId,\n\ttoRichText,\n} from '@tldraw/editor'\n\n/** @internal */\nexport const CLONE_HANDLE_MARGIN = 0\n/** @internal */\nexport const NOTE_SIZE = 200\n/** @internal */\nexport const NOTE_CENTER_OFFSET = new Vec(NOTE_SIZE / 2, NOTE_SIZE / 2)\n/** @internal */\nexport const NOTE_ADJACENT_POSITION_SNAP_RADIUS = 10\n\nconst BASE_NOTE_POSITIONS = (editor: Editor) =>\n\t[\n\t\t[\n\t\t\t['a1' as IndexKey],\n\t\t\tnew Vec(NOTE_SIZE * 0.5, NOTE_SIZE * -0.5 - editor.options.adjacentShapeMargin),\n\t\t], // t\n\t\t[\n\t\t\t['a2' as IndexKey],\n\t\t\tnew Vec(NOTE_SIZE * 1.5 + editor.options.adjacentShapeMargin, NOTE_SIZE * 0.5),\n\t\t], // r\n\t\t[\n\t\t\t['a3' as IndexKey],\n\t\t\tnew Vec(NOTE_SIZE * 0.5, NOTE_SIZE * 1.5 + editor.options.adjacentShapeMargin),\n\t\t], // b\n\t\t[\n\t\t\t['a4' as IndexKey],\n\t\t\tnew Vec(NOTE_SIZE * -0.5 - editor.options.adjacentShapeMargin, NOTE_SIZE * 0.5),\n\t\t], // l\n\t] as const\n\nfunction getBaseAdjacentNotePositions(editor: Editor, scale: number) {\n\tif (scale === 1) return BASE_NOTE_POSITIONS(editor)\n\tconst s = NOTE_SIZE * scale\n\tconst m = editor.options.adjacentShapeMargin * scale\n\treturn [\n\t\t[['a1' as IndexKey], new Vec(s * 0.5, s * -0.5 - m)], // t\n\t\t[['a2' as IndexKey], new Vec(s * 1.5 + m, s * 0.5)], // r\n\t\t[['a3' as IndexKey], new Vec(s * 0.5, s * 1.5 + m)], // b\n\t\t[['a4' as IndexKey], new Vec(s * -0.5 - m, s * 0.5)], // l\n\t] as const\n}\n\n/**\n * Get the adjacent positions for a particular note shape.\n *\n * @param pagePoint - The point of the note shape on the page.\n * @param pageRotation - The rotation of the note shape on the page.\n * @param growY - The growY of the note shape.\n * @param extraHeight - The extra height to add to the top position above the note shape (ie the growY of the dragging shape).\n *\n * @internal */\nexport function getNoteAdjacentPositions(\n\teditor: Editor,\n\tpagePoint: Vec,\n\tpageRotation: number,\n\tgrowY: number,\n\textraHeight: number,\n\tscale: number\n): Record<IndexKey, Vec> {\n\treturn Object.fromEntries(\n\t\tgetBaseAdjacentNotePositions(editor, scale).map(([id, v], i) => {\n\t\t\tconst point = v.clone()\n\t\t\tif (i === 0 && extraHeight) {\n\t\t\t\t// apply top margin (the growY of the moving note shape)\n\t\t\t\tpoint.y -= extraHeight\n\t\t\t} else if (i === 2 && growY) {\n\t\t\t\t// apply bottom margin (the growY of this note shape)\n\t\t\t\tpoint.y += growY\n\t\t\t}\n\t\t\treturn [id, point.rot(pageRotation).add(pagePoint)]\n\t\t})\n\t)\n}\n\n/**\n * Get all of the available note adjacent positions, excluding the selected shapes.\n *\n * @param editor - The editor instance.\n * @param rotation - The rotation of the note shape.\n * @param extraHeight - The extra height to add to the top position above the note shape (ie the growY of the dragging shape).\n *\n * @internal */\nexport function getAvailableNoteAdjacentPositions(\n\teditor: Editor,\n\trotation: number,\n\tscale: number,\n\textraHeight: number\n) {\n\tconst selectedShapeIds = new Set(editor.getSelectedShapeIds())\n\tconst minSize = (NOTE_SIZE + editor.options.adjacentShapeMargin + extraHeight) ** 2\n\tconst allCenters = new Map<TLNoteShape, Vec>()\n\tconst positions: (Vec | undefined)[] = []\n\n\t// Get all the positions that are adjacent to the selected note shapes\n\tfor (const shape of editor.getCurrentPageShapes()) {\n\t\tif (\n\t\t\t!editor.isShapeOfType
|
|
5
|
-
"mappings": "AAAA;AAAA,EAKC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACM;AAGA,MAAM,sBAAsB;AAE5B,MAAM,YAAY;AAElB,MAAM,qBAAqB,IAAI,IAAI,YAAY,GAAG,YAAY,CAAC;AAE/D,MAAM,qCAAqC;AAElD,MAAM,sBAAsB,CAAC,WAC5B;AAAA,EACC;AAAA,IACC,CAAC,IAAgB;AAAA,IACjB,IAAI,IAAI,YAAY,KAAK,YAAY,OAAO,OAAO,QAAQ,mBAAmB;AAAA,EAC/E;AAAA;AAAA,EACA;AAAA,IACC,CAAC,IAAgB;AAAA,IACjB,IAAI,IAAI,YAAY,MAAM,OAAO,QAAQ,qBAAqB,YAAY,GAAG;AAAA,EAC9E;AAAA;AAAA,EACA;AAAA,IACC,CAAC,IAAgB;AAAA,IACjB,IAAI,IAAI,YAAY,KAAK,YAAY,MAAM,OAAO,QAAQ,mBAAmB;AAAA,EAC9E;AAAA;AAAA,EACA;AAAA,IACC,CAAC,IAAgB;AAAA,IACjB,IAAI,IAAI,YAAY,OAAO,OAAO,QAAQ,qBAAqB,YAAY,GAAG;AAAA,EAC/E;AAAA;AACD;AAED,SAAS,6BAA6B,QAAgB,OAAe;AACpE,MAAI,UAAU,EAAG,QAAO,oBAAoB,MAAM;AAClD,QAAM,IAAI,YAAY;AACtB,QAAM,IAAI,OAAO,QAAQ,sBAAsB;AAC/C,SAAO;AAAA,IACN,CAAC,CAAC,IAAgB,GAAG,IAAI,IAAI,IAAI,KAAK,IAAI,OAAO,CAAC,CAAC;AAAA;AAAA,IACnD,CAAC,CAAC,IAAgB,GAAG,IAAI,IAAI,IAAI,MAAM,GAAG,IAAI,GAAG,CAAC;AAAA;AAAA,IAClD,CAAC,CAAC,IAAgB,GAAG,IAAI,IAAI,IAAI,KAAK,IAAI,MAAM,CAAC,CAAC;AAAA;AAAA,IAClD,CAAC,CAAC,IAAgB,GAAG,IAAI,IAAI,IAAI,OAAO,GAAG,IAAI,GAAG,CAAC;AAAA;AAAA,EACpD;AACD;AAWO,SAAS,yBACf,QACA,WACA,cACA,OACA,aACA,OACwB;AACxB,SAAO,OAAO;AAAA,IACb,6BAA6B,QAAQ,KAAK,EAAE,IAAI,CAAC,CAAC,IAAI,CAAC,GAAG,MAAM;AAC/D,YAAM,QAAQ,EAAE,MAAM;AACtB,UAAI,MAAM,KAAK,aAAa;AAE3B,cAAM,KAAK;AAAA,MACZ,WAAW,MAAM,KAAK,OAAO;AAE5B,cAAM,KAAK;AAAA,MACZ;AACA,aAAO,CAAC,IAAI,MAAM,IAAI,YAAY,EAAE,IAAI,SAAS,CAAC;AAAA,IACnD,CAAC;AAAA,EACF;AACD;AAUO,SAAS,kCACf,QACA,UACA,OACA,aACC;AACD,QAAM,mBAAmB,IAAI,IAAI,OAAO,oBAAoB,CAAC;AAC7D,QAAM,WAAW,YAAY,OAAO,QAAQ,sBAAsB,gBAAgB;AAClF,QAAM,aAAa,oBAAI,IAAsB;AAC7C,QAAM,YAAiC,CAAC;AAGxC,aAAW,SAAS,OAAO,qBAAqB,GAAG;AAClD,QACC,CAAC,OAAO,
|
|
4
|
+
"sourcesContent": ["import {\n\tEditor,\n\tIndexKey,\n\tTLNoteShape,\n\tTLShape,\n\tVec,\n\tcompact,\n\tcreateShapeId,\n\ttoRichText,\n} from '@tldraw/editor'\n\n/** @internal */\nexport const CLONE_HANDLE_MARGIN = 0\n/** @internal */\nexport const NOTE_SIZE = 200\n/** @internal */\nexport const NOTE_CENTER_OFFSET = new Vec(NOTE_SIZE / 2, NOTE_SIZE / 2)\n/** @internal */\nexport const NOTE_ADJACENT_POSITION_SNAP_RADIUS = 10\n\nconst BASE_NOTE_POSITIONS = (editor: Editor) =>\n\t[\n\t\t[\n\t\t\t['a1' as IndexKey],\n\t\t\tnew Vec(NOTE_SIZE * 0.5, NOTE_SIZE * -0.5 - editor.options.adjacentShapeMargin),\n\t\t], // t\n\t\t[\n\t\t\t['a2' as IndexKey],\n\t\t\tnew Vec(NOTE_SIZE * 1.5 + editor.options.adjacentShapeMargin, NOTE_SIZE * 0.5),\n\t\t], // r\n\t\t[\n\t\t\t['a3' as IndexKey],\n\t\t\tnew Vec(NOTE_SIZE * 0.5, NOTE_SIZE * 1.5 + editor.options.adjacentShapeMargin),\n\t\t], // b\n\t\t[\n\t\t\t['a4' as IndexKey],\n\t\t\tnew Vec(NOTE_SIZE * -0.5 - editor.options.adjacentShapeMargin, NOTE_SIZE * 0.5),\n\t\t], // l\n\t] as const\n\nfunction getBaseAdjacentNotePositions(editor: Editor, scale: number) {\n\tif (scale === 1) return BASE_NOTE_POSITIONS(editor)\n\tconst s = NOTE_SIZE * scale\n\tconst m = editor.options.adjacentShapeMargin * scale\n\treturn [\n\t\t[['a1' as IndexKey], new Vec(s * 0.5, s * -0.5 - m)], // t\n\t\t[['a2' as IndexKey], new Vec(s * 1.5 + m, s * 0.5)], // r\n\t\t[['a3' as IndexKey], new Vec(s * 0.5, s * 1.5 + m)], // b\n\t\t[['a4' as IndexKey], new Vec(s * -0.5 - m, s * 0.5)], // l\n\t] as const\n}\n\n/**\n * Get the adjacent positions for a particular note shape.\n *\n * @param pagePoint - The point of the note shape on the page.\n * @param pageRotation - The rotation of the note shape on the page.\n * @param growY - The growY of the note shape.\n * @param extraHeight - The extra height to add to the top position above the note shape (ie the growY of the dragging shape).\n *\n * @internal */\nexport function getNoteAdjacentPositions(\n\teditor: Editor,\n\tpagePoint: Vec,\n\tpageRotation: number,\n\tgrowY: number,\n\textraHeight: number,\n\tscale: number\n): Record<IndexKey, Vec> {\n\treturn Object.fromEntries(\n\t\tgetBaseAdjacentNotePositions(editor, scale).map(([id, v], i) => {\n\t\t\tconst point = v.clone()\n\t\t\tif (i === 0 && extraHeight) {\n\t\t\t\t// apply top margin (the growY of the moving note shape)\n\t\t\t\tpoint.y -= extraHeight\n\t\t\t} else if (i === 2 && growY) {\n\t\t\t\t// apply bottom margin (the growY of this note shape)\n\t\t\t\tpoint.y += growY\n\t\t\t}\n\t\t\treturn [id, point.rot(pageRotation).add(pagePoint)]\n\t\t})\n\t)\n}\n\n/**\n * Get all of the available note adjacent positions, excluding the selected shapes.\n *\n * @param editor - The editor instance.\n * @param rotation - The rotation of the note shape.\n * @param extraHeight - The extra height to add to the top position above the note shape (ie the growY of the dragging shape).\n *\n * @internal */\nexport function getAvailableNoteAdjacentPositions(\n\teditor: Editor,\n\trotation: number,\n\tscale: number,\n\textraHeight: number\n) {\n\tconst selectedShapeIds = new Set(editor.getSelectedShapeIds())\n\tconst minSize = (NOTE_SIZE + editor.options.adjacentShapeMargin + extraHeight) ** 2\n\tconst allCenters = new Map<TLNoteShape, Vec>()\n\tconst positions: (Vec | undefined)[] = []\n\n\t// Get all the positions that are adjacent to the selected note shapes\n\tfor (const shape of editor.getCurrentPageShapes()) {\n\t\tif (\n\t\t\t!editor.isShapeOfType(shape, 'note') ||\n\t\t\tscale !== shape.props.scale ||\n\t\t\tselectedShapeIds.has(shape.id)\n\t\t) {\n\t\t\tcontinue\n\t\t}\n\n\t\tconst transform = editor.getShapePageTransform(shape.id)!\n\n\t\t// If the note has a different rotation, we can't use its adjacent positions\n\t\tif (rotation !== transform.rotation()) continue\n\n\t\t// Save the unselected note shape's center\n\t\tallCenters.set(shape, editor.getShapePageBounds(shape)!.center)\n\n\t\t// And push its position to the positions array\n\t\tpositions.push(\n\t\t\t...Object.values(\n\t\t\t\tgetNoteAdjacentPositions(\n\t\t\t\t\teditor,\n\t\t\t\t\ttransform.point(),\n\t\t\t\t\trotation,\n\t\t\t\t\tshape.props.growY,\n\t\t\t\t\textraHeight,\n\t\t\t\t\tscale\n\t\t\t\t)\n\t\t\t)\n\t\t)\n\t}\n\n\t// Remove positions that are inside of another note shape\n\tconst len = positions.length\n\tlet position: Vec | undefined\n\tfor (const [shape, center] of allCenters) {\n\t\tfor (let i = 0; i < len; i++) {\n\t\t\tposition = positions[i]\n\t\t\tif (!position) continue\n\t\t\tif (Vec.Dist2(center, position) > minSize) continue\n\t\t\tif (editor.isPointInShape(shape, position)) {\n\t\t\t\tpositions[i] = undefined\n\t\t\t}\n\t\t}\n\t}\n\n\treturn compact(positions)\n}\n\n/**\n * For a particular adjacent note position, get the shape in that position or create a new one.\n *\n * @param editor - The editor instance.\n * @param shape - The note shape to create or select.\n * @param center - The center of the note shape.\n * @param pageRotation - The rotation of the note shape on the page.\n * @param forceNew - Whether to force the creation of a new note shape.\n *\n * @internal */\nexport function getNoteShapeForAdjacentPosition(\n\teditor: Editor,\n\tshape: TLNoteShape,\n\tcenter: Vec,\n\tpageRotation: number,\n\tforceNew = false\n) {\n\t// There might already be a note in that position! If there is, we'll\n\t// select the next note and switch focus to it. If there's not, then\n\t// we'll create a new note in that position.\n\n\tlet nextNote: TLShape | undefined\n\n\t// Check the center of where a new note would be\n\t// Start from the top of the stack, and work our way down\n\tconst allShapesOnPage = editor.getCurrentPageShapesSorted()\n\n\tconst minDistance = (NOTE_SIZE + editor.options.adjacentShapeMargin ** 2) ** shape.props.scale\n\n\tfor (let i = allShapesOnPage.length - 1; i >= 0; i--) {\n\t\tconst otherNote = allShapesOnPage[i]\n\t\tif (otherNote.type === 'note' && otherNote.id !== shape.id) {\n\t\t\tconst otherBounds = editor.getShapePageBounds(otherNote)\n\t\t\tif (\n\t\t\t\totherBounds &&\n\t\t\t\tVec.Dist2(otherBounds.center, center) < minDistance &&\n\t\t\t\teditor.isPointInShape(otherNote, center)\n\t\t\t) {\n\t\t\t\tnextNote = otherNote\n\t\t\t\tbreak\n\t\t\t}\n\t\t}\n\t}\n\n\teditor.complete()\n\n\t// If we didn't find any in that position, then create a new one\n\tif (!nextNote || forceNew) {\n\t\teditor.markHistoryStoppingPoint('creating note shape')\n\t\tconst id = createShapeId()\n\n\t\t// We create it at the center first, so that it becomes\n\t\t// the child of whatever parent was at that center\n\t\teditor.createShape({\n\t\t\tid,\n\t\t\ttype: 'note',\n\t\t\tx: center.x,\n\t\t\ty: center.y,\n\t\t\trotation: pageRotation,\n\t\t\topacity: shape.opacity,\n\t\t\tprops: {\n\t\t\t\t// Use the props of the shape we're cloning\n\t\t\t\t...shape.props,\n\t\t\t\trichText: toRichText(''),\n\t\t\t\tgrowY: 0,\n\t\t\t\tfontSizeAdjustment: 0,\n\t\t\t\turl: '',\n\t\t\t},\n\t\t})\n\n\t\t// Now we need to correct its location within its new parent\n\n\t\tconst createdShape = editor.getShape<TLNoteShape>(id)!\n\t\tif (!createdShape) return // may have hit max shapes\n\n\t\t// We need to put the page point in the same coordinate space as the newly created shape (i.e its parent's space)\n\t\tconst topLeft = editor.getPointInParentSpace(\n\t\t\tcreatedShape,\n\t\t\tVec.Sub(\n\t\t\t\tcenter,\n\t\t\t\tVec.Rot(NOTE_CENTER_OFFSET.clone().mul(createdShape.props.scale), pageRotation)\n\t\t\t)\n\t\t)\n\n\t\teditor.updateShape({\n\t\t\tid,\n\t\t\ttype: 'note',\n\t\t\tx: topLeft.x,\n\t\t\ty: topLeft.y,\n\t\t})\n\n\t\tnextNote = editor.getShape(id)!\n\t}\n\n\teditor.zoomToSelectionIfOffscreen(16, {\n\t\tanimation: {\n\t\t\tduration: editor.options.animationMediumMs,\n\t\t},\n\t\tinset: 0,\n\t})\n\treturn nextNote\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../../src/lib/shapes/shared/PlainTextLabel.tsx"],
|
|
4
|
-
"sourcesContent": ["import {\n\tBox,\n\tTLDefaultFillStyle,\n\tTLDefaultFontStyle,\n\tTLDefaultHorizontalAlignStyle,\n\tTLDefaultVerticalAlignStyle,\n\tTLShapeId,\n} from '@tldraw/editor'\nimport React from 'react'\nimport { PlainTextArea } from '../text/PlainTextArea'\nimport { TextHelpers } from './TextHelpers'\nimport { isLegacyAlign } from './legacyProps'\nimport { useEditablePlainText } from './useEditablePlainText'\n\n/** @public */\nexport interface PlainTextLabelProps {\n\tshapeId: TLShapeId\n\ttype: string\n\tfont: TLDefaultFontStyle\n\tfontSize: number\n\tlineHeight: number\n\tfill?: TLDefaultFillStyle\n\talign: TLDefaultHorizontalAlignStyle\n\tverticalAlign: TLDefaultVerticalAlignStyle\n\twrap?: boolean\n\ttext?: string\n\tlabelColor: string\n\tbounds?: Box\n\tisSelected: boolean\n\tonKeyDown?(e: KeyboardEvent): void\n\tclassNamePrefix?: string\n\tstyle?: React.CSSProperties\n\ttextWidth?: number\n\ttextHeight?: number\n\tpadding?: number\n}\n\n/**\n * Renders a text label that can be used inside of shapes.\n * The component has the ability to be edited in place and furthermore\n * supports rich text editing.\n *\n * @public @react\n */\nexport const PlainTextLabel = React.memo(function PlainTextLabel({\n\tshapeId,\n\ttype,\n\ttext: plaintext,\n\tlabelColor,\n\tfont,\n\tfontSize,\n\tlineHeight,\n\talign,\n\tverticalAlign,\n\twrap,\n\tisSelected,\n\tpadding = 0,\n\tonKeyDown: handleKeyDownCustom,\n\tclassNamePrefix,\n\tstyle,\n\ttextWidth,\n\ttextHeight,\n}: PlainTextLabelProps) {\n\tconst { rInput, isEmpty, isEditing, isReadyForEditing, ...editableTextRest } =\n\t\tuseEditablePlainText(shapeId, type, plaintext)\n\n\tconst finalPlainText = TextHelpers.normalizeTextForDom(plaintext || '')\n\tconst hasText = finalPlainText.length > 0\n\n\tconst legacyAlign = isLegacyAlign(align)\n\n\tif (!isEditing && !hasText) {\n\t\treturn null\n\t}\n\n\t// TODO: probably combine tl-text and tl-arrow eventually\n\t// In case you're grepping for this, it breaks down as follows:\n\t// tl-text-label, tl-text-label__inner, tl-text-shape-label, tl-text\n\t// tl-arrow-label, tl-arrow-label__inner, tl-arrow\n\tconst cssPrefix = classNamePrefix || 'tl-text'\n\treturn (\n\t\t<div\n\t\t\tclassName={`${cssPrefix}-label tl-text-wrapper tl-plain-text-wrapper`}\n\t\t\taria-hidden={!isEditing}\n\t\t\tdata-font={font}\n\t\t\tdata-align={align}\n\t\t\tdata-hastext={!isEmpty}\n\t\t\tdata-isediting={isEditing}\n\t\t\tdata-is-ready-for-editing={isReadyForEditing}\n\t\t\tdata-textwrap={!!wrap}\n\t\t\tdata-isselected={isSelected}\n\t\t\tstyle={{\n\t\t\t\tjustifyContent: align === 'middle' || legacyAlign ? 'center' : align,\n\t\t\t\talignItems: verticalAlign === 'middle' ? 'center' : verticalAlign,\n\t\t\t\tpadding,\n\t\t\t\t...style,\n\t\t\t}}\n\t\t>\n\t\t\t<div\n\t\t\t\tclassName={`${cssPrefix}-label__inner tl-text-content__wrapper`}\n\t\t\t\tstyle={{\n\t\t\t\t\tfontSize,\n\t\t\t\t\tlineHeight: lineHeight.toString(),\n\t\t\t\t\tminHeight: Math.floor(fontSize * lineHeight) + 'px',\n\t\t\t\t\tminWidth: Math.ceil(textWidth || 0),\n\t\t\t\t\tcolor: labelColor,\n\t\t\t\t\twidth: textWidth ? Math.ceil(textWidth) : undefined,\n\t\t\t\t\theight: textHeight ? Math.ceil(textHeight) : undefined,\n\t\t\t\t}}\n\t\t\t>\n\t\t\t\t<div className={`${cssPrefix} tl-text tl-text-content`} dir=\"auto\">\n\t\t\t\t\t{finalPlainText.split('\\n').map((lineOfText, index) => (\n\t\t\t\t\t\t<div key={index} dir=\"auto\">\n\t\t\t\t\t\t\t{lineOfText}\n\t\t\t\t\t\t</div>\n\t\t\t\t\t))}\n\t\t\t\t</div>\n\t\t\t\t{(isReadyForEditing || isSelected) && (\n\t\t\t\t\t<PlainTextArea\n\t\t\t\t\t\t// Fudge the ref type because we're using forwardRef and it's not typed correctly.\n\t\t\t\t\t\tref={rInput as any}\n\t\t\t\t\t\ttext={plaintext}\n\t\t\t\t\t\tisEditing={isEditing}\n\t\t\t\t\t\tshapeId={shapeId}\n\t\t\t\t\t\t{...editableTextRest}\n\t\t\t\t\t\thandleKeyDown={handleKeyDownCustom ?? editableTextRest.handleKeyDown}\n\t\t\t\t\t/>\n\t\t\t\t)}\n\t\t\t</div>\n\t\t</div>\n\t)\n})\n"],
|
|
5
|
-
"mappings": "
|
|
4
|
+
"sourcesContent": ["import {\n\tBox,\n\tExtractShapeByProps,\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: ExtractShapeByProps<{ text: string }>['type']\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": "AAmGG,SAcG,KAdH;AA1FH,OAAO,WAAW;AAClB,SAAS,qBAAqB;AAC9B,SAAS,mBAAmB;AAC5B,SAAS,qBAAqB;AAC9B,SAAS,4BAA4B;AAgC9B,MAAM,iBAAiB,MAAM,KAAK,SAASA,gBAAe;AAAA,EAChE;AAAA,EACA;AAAA,EACA,MAAM;AAAA,EACN;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,UAAU;AAAA,EACV,WAAW;AAAA,EACX;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACD,GAAwB;AACvB,QAAM,EAAE,QAAQ,SAAS,WAAW,mBAAmB,GAAG,iBAAiB,IAC1E,qBAAqB,SAAS,MAAM,SAAS;AAE9C,QAAM,iBAAiB,YAAY,oBAAoB,aAAa,EAAE;AACtE,QAAM,UAAU,eAAe,SAAS;AAExC,QAAM,cAAc,cAAc,KAAK;AAEvC,MAAI,CAAC,aAAa,CAAC,SAAS;AAC3B,WAAO;AAAA,EACR;AAMA,QAAM,YAAY,mBAAmB;AACrC,SACC;AAAA,IAAC;AAAA;AAAA,MACA,WAAW,GAAG,SAAS;AAAA,MACvB,eAAa,CAAC;AAAA,MACd,aAAW;AAAA,MACX,cAAY;AAAA,MACZ,gBAAc,CAAC;AAAA,MACf,kBAAgB;AAAA,MAChB,6BAA2B;AAAA,MAC3B,iBAAe,CAAC,CAAC;AAAA,MACjB,mBAAiB;AAAA,MACjB,OAAO;AAAA,QACN,gBAAgB,UAAU,YAAY,cAAc,WAAW;AAAA,QAC/D,YAAY,kBAAkB,WAAW,WAAW;AAAA,QACpD;AAAA,QACA,GAAG;AAAA,MACJ;AAAA,MAEA;AAAA,QAAC;AAAA;AAAA,UACA,WAAW,GAAG,SAAS;AAAA,UACvB,OAAO;AAAA,YACN;AAAA,YACA,YAAY,WAAW,SAAS;AAAA,YAChC,WAAW,KAAK,MAAM,WAAW,UAAU,IAAI;AAAA,YAC/C,UAAU,KAAK,KAAK,aAAa,CAAC;AAAA,YAClC,OAAO;AAAA,YACP,OAAO,YAAY,KAAK,KAAK,SAAS,IAAI;AAAA,YAC1C,QAAQ,aAAa,KAAK,KAAK,UAAU,IAAI;AAAA,UAC9C;AAAA,UAEA;AAAA,gCAAC,SAAI,WAAW,GAAG,SAAS,4BAA4B,KAAI,QAC1D,yBAAe,MAAM,IAAI,EAAE,IAAI,CAAC,YAAY,UAC5C,oBAAC,SAAgB,KAAI,QACnB,wBADQ,KAEV,CACA,GACF;AAAA,aACE,qBAAqB,eACtB;AAAA,cAAC;AAAA;AAAA,gBAEA,KAAK;AAAA,gBACL,MAAM;AAAA,gBACN;AAAA,gBACA;AAAA,gBACC,GAAG;AAAA,gBACJ,eAAe,uBAAuB,iBAAiB;AAAA;AAAA,YACxD;AAAA;AAAA;AAAA,MAEF;AAAA;AAAA,EACD;AAEF,CAAC;",
|
|
6
6
|
"names": ["PlainTextLabel"]
|
|
7
7
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../../src/lib/shapes/shared/RichTextLabel.tsx"],
|
|
4
|
-
"sourcesContent": ["import {\n\tBox,\n\tDefaultFontFamilies,\n\tTLDefaultFillStyle,\n\tTLDefaultFontStyle,\n\tTLDefaultHorizontalAlignStyle,\n\tTLDefaultVerticalAlignStyle,\n\tTLEventInfo,\n\tTLRichText,\n\tTLShapeId,\n\topenWindow,\n\tpreventDefault,\n\tuseEditor,\n\tuseReactor,\n\tuseValue,\n} from '@tldraw/editor'\nimport React, { useMemo } from 'react'\nimport { renderHtmlFromRichText } from '../../utils/text/richText'\nimport { RichTextArea } from '../text/RichTextArea'\nimport { TEXT_PROPS } from './default-shape-constants'\nimport { isLegacyAlign } from './legacyProps'\nimport { useEditableRichText } from './useEditableRichText'\n\n/** @public */\nexport interface RichTextLabelProps {\n\tshapeId: TLShapeId\n\ttype:
|
|
5
|
-
"mappings": "
|
|
4
|
+
"sourcesContent": ["import {\n\tBox,\n\tDefaultFontFamilies,\n\tExtractShapeByProps,\n\tTLDefaultFillStyle,\n\tTLDefaultFontStyle,\n\tTLDefaultHorizontalAlignStyle,\n\tTLDefaultVerticalAlignStyle,\n\tTLEventInfo,\n\tTLRichText,\n\tTLShapeId,\n\topenWindow,\n\tpreventDefault,\n\tuseEditor,\n\tuseReactor,\n\tuseValue,\n} from '@tldraw/editor'\nimport React, { useMemo } from 'react'\nimport { renderHtmlFromRichText } from '../../utils/text/richText'\nimport { RichTextArea } from '../text/RichTextArea'\nimport { TEXT_PROPS } from './default-shape-constants'\nimport { isLegacyAlign } from './legacyProps'\nimport { useEditableRichText } from './useEditableRichText'\n\n/** @public */\nexport interface RichTextLabelProps {\n\tshapeId: TLShapeId\n\ttype: ExtractShapeByProps<{ richText: TLRichText }>['type']\n\tfont: TLDefaultFontStyle\n\tfontSize: number\n\tlineHeight: number\n\tfill?: TLDefaultFillStyle\n\talign: TLDefaultHorizontalAlignStyle\n\tverticalAlign: TLDefaultVerticalAlignStyle\n\twrap?: boolean\n\trichText?: TLRichText\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\thasCustomTabBehavior?: boolean\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 RichTextLabel = React.memo(function RichTextLabel({\n\tshapeId,\n\ttype,\n\trichText,\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\thasCustomTabBehavior,\n}: RichTextLabelProps) {\n\tconst editor = useEditor()\n\tconst isDragging = React.useRef(false)\n\tconst { rInput, isEmpty, isEditing, isReadyForEditing, ...editableTextRest } =\n\t\tuseEditableRichText(shapeId, type, richText)\n\n\tconst html = useMemo(() => {\n\t\tif (richText) {\n\t\t\treturn renderHtmlFromRichText(editor, richText)\n\t\t}\n\t}, [editor, richText])\n\n\tconst selectToolActive = useValue(\n\t\t'isSelectToolActive',\n\t\t() => editor.getCurrentToolId() === 'select',\n\t\t[editor]\n\t)\n\n\tuseReactor(\n\t\t'isDragging',\n\t\t() => {\n\t\t\teditor.getInstanceState()\n\t\t\tisDragging.current = editor.inputs.isDragging\n\t\t},\n\t\t[editor]\n\t)\n\n\tconst legacyAlign = isLegacyAlign(align)\n\n\tconst handlePointerDown = (e: React.MouseEvent<HTMLDivElement>) => {\n\t\tif (e.target instanceof HTMLElement && (e.target.tagName === 'A' || e.target.closest('a'))) {\n\t\t\t// This mousedown prevent default is to let dragging when over a link work.\n\t\t\tpreventDefault(e)\n\n\t\t\tif (!selectToolActive) return\n\t\t\tconst link = e.target.closest('a')?.getAttribute('href') ?? ''\n\t\t\t// We don't get the mouseup event later because we preventDefault\n\t\t\t// so we have to do it manually.\n\t\t\tconst handlePointerUp = (e: TLEventInfo) => {\n\t\t\t\tif (e.name !== 'pointer_up' || !link) return\n\n\t\t\t\tif (!isDragging.current) {\n\t\t\t\t\topenWindow(link, '_blank', false)\n\t\t\t\t}\n\t\t\t\teditor.off('event', handlePointerUp)\n\t\t\t}\n\t\t\teditor.on('event', handlePointerUp)\n\t\t}\n\t}\n\n\t// Should be guarded higher up so that this doesn't render... but repeated here. This should never be true.\n\tif (!isEditing && isEmpty) return null\n\n\t// TODO: probably combine tl-text and tl-arrow eventually\n\tconst cssPrefix = classNamePrefix || 'tl-text'\n\treturn (\n\t\t<div\n\t\t\tclassName={`${cssPrefix}-label tl-text-wrapper tl-rich-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-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{richText && (\n\t\t\t\t\t\t<div\n\t\t\t\t\t\t\tclassName=\"tl-rich-text\"\n\t\t\t\t\t\t\tdata-is-select-tool-active={selectToolActive}\n\t\t\t\t\t\t\t// todo: see if I can abuse this\n\t\t\t\t\t\t\tdangerouslySetInnerHTML={{ __html: html || '' }}\n\t\t\t\t\t\t\tonPointerDown={handlePointerDown}\n\t\t\t\t\t\t\tdata-is-ready-for-editing={isReadyForEditing}\n\t\t\t\t\t\t/>\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<RichTextArea\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\trichText={richText}\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\thasCustomTabBehavior={hasCustomTabBehavior}\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\n/** @public */\nexport interface RichTextSVGProps {\n\tbounds: Box\n\trichText: TLRichText\n\tfontSize: number\n\tfont: TLDefaultFontStyle\n\talign: TLDefaultHorizontalAlignStyle\n\tverticalAlign: TLDefaultVerticalAlignStyle\n\twrap?: boolean\n\tlabelColor: string\n\tpadding: number\n\tshowTextOutline?: boolean\n}\n\n/**\n * Renders a rich text string as SVG given bounds and text properties.\n *\n * @public @react\n */\nexport function RichTextSVG({\n\tbounds,\n\trichText,\n\tfontSize,\n\tfont,\n\talign,\n\tverticalAlign,\n\twrap,\n\tlabelColor,\n\tpadding,\n\tshowTextOutline = true,\n}: RichTextSVGProps) {\n\tconst editor = useEditor()\n\tconst html = renderHtmlFromRichText(editor, richText)\n\tconst textAlign =\n\t\talign === 'middle'\n\t\t\t? ('center' as const)\n\t\t\t: align === 'start'\n\t\t\t\t? ('start' as const)\n\t\t\t\t: ('end' as const)\n\tconst justifyContent =\n\t\talign === 'middle'\n\t\t\t? ('center' as const)\n\t\t\t: align === 'start'\n\t\t\t\t? ('flex-start' as const)\n\t\t\t\t: ('flex-end' as const)\n\tconst alignItems =\n\t\tverticalAlign === 'middle' ? 'center' : verticalAlign === 'start' ? 'flex-start' : 'flex-end'\n\tconst wrapperStyle = {\n\t\tdisplay: 'flex',\n\t\tfontFamily: DefaultFontFamilies[font],\n\t\theight: `100%`,\n\t\tjustifyContent,\n\t\talignItems,\n\t\tpadding: `${padding}px`,\n\t}\n\tconst style = {\n\t\tfontSize: `${fontSize}px`,\n\t\twrap: wrap ? 'wrap' : 'nowrap',\n\t\tcolor: labelColor,\n\t\tlineHeight: TEXT_PROPS.lineHeight,\n\t\ttextAlign,\n\t\twidth: '100%',\n\t\twordWrap: 'break-word' as const,\n\t\toverflowWrap: 'break-word' as const,\n\t\twhiteSpace: 'pre-wrap',\n\t\ttextShadow: showTextOutline ? 'var(--tl-text-outline)' : 'none',\n\t}\n\n\treturn (\n\t\t<foreignObject\n\t\t\tx={bounds.minX}\n\t\t\ty={bounds.minY}\n\t\t\twidth={bounds.w}\n\t\t\theight={bounds.h}\n\t\t\tclassName=\"tl-export-embed-styles tl-rich-text tl-rich-text-svg\"\n\t\t>\n\t\t\t<div style={wrapperStyle}>\n\t\t\t\t<div dangerouslySetInnerHTML={{ __html: html }} style={style} />\n\t\t\t</div>\n\t\t</foreignObject>\n\t)\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": ["RichTextLabel", "e"]
|
|
7
7
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../../src/lib/shapes/shared/crop.ts"],
|
|
4
|
-
"sourcesContent": ["import {\n\tBox,\n\tShapeWithCrop,\n\tTLCropInfo,\n\tTLImageShape,\n\tTLShapeCrop,\n\tTLShapeId,\n\tVec,\n\tclamp,\n\tisEqual,\n} from '@tldraw/editor'\n\n/** @internal */\nexport const MIN_CROP_SIZE = 8\n\n/** @public */\nexport interface CropBoxOptions {\n\tminWidth?: number\n\tminHeight?: number\n}\n\n/** @public */\nexport function getDefaultCrop(): TLShapeCrop {\n\treturn {\n\t\ttopLeft: { x: 0, y: 0 },\n\t\tbottomRight: { x: 1, y: 1 },\n\t}\n}\n\n/** @public */\nexport type ASPECT_RATIO_OPTION =\n\t| 'original'\n\t| 'square'\n\t| 'circle'\n\t| 'landscape'\n\t| 'portrait'\n\t| 'wide'\n\n/** @public */\nexport const ASPECT_RATIO_OPTIONS: ASPECT_RATIO_OPTION[] = [\n\t'original',\n\t'square',\n\t'circle',\n\t'landscape',\n\t'portrait',\n\t'wide',\n]\n\n/** @public */\nexport const ASPECT_RATIO_TO_VALUE: Record<ASPECT_RATIO_OPTION, number> = {\n\toriginal: 0,\n\tsquare: 1,\n\tcircle: 1,\n\tlandscape: 4 / 3,\n\tportrait: 3 / 4,\n\twide: 16 / 9,\n}\n\n/**\n * Original (uncropped) width and height of shape.\n *\n * @public\n */\nexport function getUncroppedSize(\n\tshapeSize: { w: number; h: number },\n\tcrop: TLShapeCrop | null\n): { w: number; h: number } {\n\tif (!crop) return { w: shapeSize.w, h: shapeSize.h }\n\tconst w = shapeSize.w / (crop.bottomRight.x - crop.topLeft.x)\n\tconst h = shapeSize.h / (crop.bottomRight.y - crop.topLeft.y)\n\treturn { w, h }\n}\n\n// Utility function to get crop dimensions\nfunction getCropDimensions(crop: TLShapeCrop) {\n\treturn {\n\t\twidth: crop.bottomRight.x - crop.topLeft.x,\n\t\theight: crop.bottomRight.y - crop.topLeft.y,\n\t}\n}\n\n// Utility function to get crop center\nfunction getCropCenter(crop: TLShapeCrop) {\n\tconst { width, height } = getCropDimensions(crop)\n\treturn {\n\t\tx: crop.topLeft.x + width / 2,\n\t\ty: crop.topLeft.y + height / 2,\n\t}\n}\n\n// Utility function to create crop with specified dimensions centered on given point\nfunction createCropAroundCenter(\n\tcenterX: number,\n\tcenterY: number,\n\twidth: number,\n\theight: number,\n\tisCircle?: boolean\n) {\n\tconst topLeftX = Math.max(0, Math.min(1 - width, centerX - width / 2))\n\tconst topLeftY = Math.max(0, Math.min(1 - height, centerY - height / 2))\n\n\treturn {\n\t\ttopLeft: { x: topLeftX, y: topLeftY },\n\t\tbottomRight: { x: topLeftX + width, y: topLeftY + height },\n\t\tisCircle,\n\t}\n}\n\n/** @public */\nexport function getCropBox<T extends ShapeWithCrop>(\n\tshape: T,\n\tinfo: TLCropInfo<T>,\n\topts = {} as CropBoxOptions\n):\n\t| {\n\t\t\tid: TLShapeId\n\t\t\ttype: T['type']\n\t\t\tx: number\n\t\t\ty: number\n\t\t\tprops: ShapeWithCrop['props']\n\t }\n\t| undefined {\n\tconst { handle, change, crop, aspectRatioLocked } = info\n\tconst { w, h } = info.uncroppedSize\n\tconst { minWidth = MIN_CROP_SIZE, minHeight = MIN_CROP_SIZE } = opts\n\n\tif (w < minWidth || h < minHeight || (change.x === 0 && change.y === 0)) {\n\t\treturn\n\t}\n\n\t// Lets get a box here in pixel space. For simplicity, we'll do all the math in\n\t// pixel space, then convert to normalized space at the end.\n\tconst prevCropBox = new Box(\n\t\tcrop.topLeft.x * w,\n\t\tcrop.topLeft.y * h,\n\t\t(crop.bottomRight.x - crop.topLeft.x) * w,\n\t\t(crop.bottomRight.y - crop.topLeft.y) * h\n\t)\n\n\tconst targetRatio = prevCropBox.aspectRatio\n\tconst tempBox = prevCropBox.clone()\n\n\t// Basic resizing logic based on the handles\n\n\tif (handle === 'top_left' || handle === 'bottom_left' || handle === 'left') {\n\t\ttempBox.x = clamp(tempBox.x + change.x, 0, prevCropBox.maxX - minWidth)\n\t\ttempBox.w = prevCropBox.maxX - tempBox.x\n\t} else if (handle === 'top_right' || handle === 'bottom_right' || handle === 'right') {\n\t\tconst tempRight = clamp(tempBox.maxX + change.x, prevCropBox.x + minWidth, w)\n\t\ttempBox.w = tempRight - tempBox.x\n\t}\n\n\tif (handle === 'top_left' || handle === 'top_right' || handle === 'top') {\n\t\ttempBox.y = clamp(tempBox.y + change.y, 0, prevCropBox.maxY - minHeight)\n\t\ttempBox.h = prevCropBox.maxY - tempBox.y\n\t} else if (handle === 'bottom_left' || handle === 'bottom_right' || handle === 'bottom') {\n\t\tconst tempBottom = clamp(tempBox.maxY + change.y, prevCropBox.y + minHeight, h)\n\t\ttempBox.h = tempBottom - tempBox.y\n\t}\n\n\t// Aspect ratio locked resizing logic\n\n\tif (aspectRatioLocked) {\n\t\tconst isXLimiting = tempBox.aspectRatio > targetRatio\n\n\t\tif (isXLimiting) {\n\t\t\ttempBox.h = tempBox.w / targetRatio\n\t\t} else {\n\t\t\ttempBox.w = tempBox.h * targetRatio\n\t\t}\n\n\t\tswitch (handle) {\n\t\t\tcase 'top_left': {\n\t\t\t\t// preserve the bottom right corner\n\t\t\t\ttempBox.x = prevCropBox.maxX - tempBox.w\n\t\t\t\ttempBox.y = prevCropBox.maxY - tempBox.h\n\n\t\t\t\tif (tempBox.x <= 0) {\n\t\t\t\t\ttempBox.x = 0\n\t\t\t\t\ttempBox.w = prevCropBox.maxX - tempBox.x\n\t\t\t\t\ttempBox.h = tempBox.w / targetRatio\n\t\t\t\t\ttempBox.y = prevCropBox.maxY - tempBox.h\n\t\t\t\t}\n\n\t\t\t\tif (tempBox.y <= 0) {\n\t\t\t\t\ttempBox.y = 0\n\t\t\t\t\ttempBox.h = prevCropBox.maxY - tempBox.y\n\t\t\t\t\ttempBox.w = tempBox.h * targetRatio\n\t\t\t\t\ttempBox.x = prevCropBox.maxX - tempBox.w\n\t\t\t\t}\n\t\t\t\tbreak\n\t\t\t}\n\t\t\tcase 'top_right': {\n\t\t\t\t// preserve the bottom left corner\n\t\t\t\ttempBox.x = prevCropBox.x\n\t\t\t\ttempBox.y = prevCropBox.maxY - tempBox.h\n\n\t\t\t\tif (tempBox.maxX >= w) {\n\t\t\t\t\ttempBox.w = w - prevCropBox.x\n\t\t\t\t\ttempBox.h = tempBox.w / targetRatio\n\t\t\t\t\ttempBox.y = prevCropBox.maxY - tempBox.h\n\t\t\t\t}\n\n\t\t\t\tif (tempBox.y <= 0) {\n\t\t\t\t\ttempBox.y = 0\n\t\t\t\t\ttempBox.h = prevCropBox.maxY - tempBox.y\n\t\t\t\t\ttempBox.w = tempBox.h * targetRatio\n\t\t\t\t}\n\t\t\t\tbreak\n\t\t\t}\n\t\t\tcase 'bottom_left': {\n\t\t\t\t// preserve the top right corner\n\t\t\t\ttempBox.x = prevCropBox.maxX - tempBox.w\n\t\t\t\ttempBox.y = prevCropBox.y\n\n\t\t\t\tif (tempBox.x <= 0) {\n\t\t\t\t\ttempBox.x = 0\n\t\t\t\t\ttempBox.w = prevCropBox.maxX - tempBox.x\n\t\t\t\t\ttempBox.h = tempBox.w / targetRatio\n\t\t\t\t}\n\n\t\t\t\tif (tempBox.maxY >= h) {\n\t\t\t\t\ttempBox.h = h - prevCropBox.y\n\t\t\t\t\ttempBox.w = tempBox.h * targetRatio\n\t\t\t\t\ttempBox.x = prevCropBox.maxX - tempBox.w\n\t\t\t\t}\n\t\t\t\tbreak\n\t\t\t}\n\t\t\tcase 'bottom_right': {\n\t\t\t\t// preserve the top left corner\n\t\t\t\ttempBox.x = prevCropBox.x\n\t\t\t\ttempBox.y = prevCropBox.y\n\n\t\t\t\tif (tempBox.maxX >= w) {\n\t\t\t\t\ttempBox.w = w - prevCropBox.x\n\t\t\t\t\ttempBox.h = tempBox.w / targetRatio\n\t\t\t\t}\n\n\t\t\t\tif (tempBox.maxY >= h) {\n\t\t\t\t\ttempBox.h = h - prevCropBox.y\n\t\t\t\t\ttempBox.w = tempBox.h * targetRatio\n\t\t\t\t}\n\t\t\t\tbreak\n\t\t\t}\n\t\t\tcase 'top': {\n\t\t\t\t// preserve the bottom edge center\n\t\t\t\ttempBox.h = prevCropBox.maxY - tempBox.y\n\t\t\t\ttempBox.w = tempBox.h * targetRatio\n\t\t\t\ttempBox.x -= (tempBox.w - prevCropBox.w) / 2\n\n\t\t\t\tif (tempBox.x <= 0) {\n\t\t\t\t\tconst leftSide = prevCropBox.midX\n\t\t\t\t\ttempBox.w = leftSide * 2\n\t\t\t\t\ttempBox.h = tempBox.w / targetRatio\n\t\t\t\t\ttempBox.x = 0\n\t\t\t\t}\n\n\t\t\t\tif (tempBox.maxX >= w) {\n\t\t\t\t\tconst rightSide = w - prevCropBox.midX\n\t\t\t\t\ttempBox.w = rightSide * 2\n\t\t\t\t\ttempBox.h = tempBox.w / targetRatio\n\t\t\t\t\ttempBox.x = w - tempBox.w\n\t\t\t\t}\n\n\t\t\t\ttempBox.y = prevCropBox.maxY - tempBox.h\n\t\t\t\tbreak\n\t\t\t}\n\t\t\tcase 'right': {\n\t\t\t\t// preserve the left edge center\n\t\t\t\ttempBox.w = tempBox.maxX - prevCropBox.x\n\t\t\t\ttempBox.h = tempBox.w / targetRatio\n\t\t\t\ttempBox.y -= (tempBox.h - prevCropBox.h) / 2\n\n\t\t\t\tif (tempBox.y <= 0) {\n\t\t\t\t\tconst topSide = prevCropBox.midY\n\t\t\t\t\ttempBox.h = topSide * 2\n\t\t\t\t\ttempBox.w = tempBox.h * targetRatio\n\t\t\t\t\ttempBox.y = 0\n\t\t\t\t}\n\n\t\t\t\tif (tempBox.maxY >= h) {\n\t\t\t\t\tconst bottomSide = h - prevCropBox.midY\n\t\t\t\t\ttempBox.h = bottomSide * 2\n\t\t\t\t\ttempBox.w = tempBox.h * targetRatio\n\t\t\t\t\ttempBox.y = h - tempBox.h\n\t\t\t\t}\n\t\t\t\tbreak\n\t\t\t}\n\t\t\tcase 'bottom': {\n\t\t\t\t// preserve the top edge center\n\t\t\t\ttempBox.h = tempBox.maxY - prevCropBox.y\n\t\t\t\ttempBox.w = tempBox.h * targetRatio\n\t\t\t\ttempBox.x -= (tempBox.w - prevCropBox.w) / 2\n\n\t\t\t\tif (tempBox.x <= 0) {\n\t\t\t\t\tconst leftSide = prevCropBox.midX\n\t\t\t\t\ttempBox.w = leftSide * 2\n\t\t\t\t\ttempBox.h = tempBox.w / targetRatio\n\t\t\t\t\ttempBox.x = 0\n\t\t\t\t}\n\n\t\t\t\tif (tempBox.maxX >= w) {\n\t\t\t\t\tconst rightSide = w - prevCropBox.midX\n\t\t\t\t\ttempBox.w = rightSide * 2\n\t\t\t\t\ttempBox.h = tempBox.w / targetRatio\n\t\t\t\t\ttempBox.x = w - tempBox.w\n\t\t\t\t}\n\t\t\t\tbreak\n\t\t\t}\n\t\t\tcase 'left': {\n\t\t\t\t// preserve the right edge center\n\t\t\t\ttempBox.w = prevCropBox.maxX - tempBox.x\n\t\t\t\ttempBox.h = tempBox.w / targetRatio\n\t\t\t\ttempBox.y -= (tempBox.h - prevCropBox.h) / 2\n\n\t\t\t\tif (tempBox.y <= 0) {\n\t\t\t\t\tconst topSide = prevCropBox.midY\n\t\t\t\t\ttempBox.h = topSide * 2\n\t\t\t\t\ttempBox.w = tempBox.h * targetRatio\n\t\t\t\t\ttempBox.y = 0\n\t\t\t\t}\n\n\t\t\t\tif (tempBox.maxY >= h) {\n\t\t\t\t\tconst bottomSide = h - prevCropBox.midY\n\t\t\t\t\ttempBox.h = bottomSide * 2\n\t\t\t\t\ttempBox.w = tempBox.h * targetRatio\n\t\t\t\t\ttempBox.y = h - tempBox.h\n\t\t\t\t}\n\n\t\t\t\ttempBox.x = prevCropBox.maxX - tempBox.w\n\t\t\t\tbreak\n\t\t\t}\n\t\t}\n\t}\n\n\t// Convert the box back to normalized space\n\tconst newCrop: TLShapeCrop = {\n\t\ttopLeft: { x: tempBox.x / w, y: tempBox.y / h },\n\t\tbottomRight: { x: tempBox.maxX / w, y: tempBox.maxY / h },\n\t\tisCircle: crop.isCircle,\n\t}\n\n\t// If the crop hasn't changed, we can return early\n\tif (\n\t\tnewCrop.topLeft.x === crop.topLeft.x &&\n\t\tnewCrop.topLeft.y === crop.topLeft.y &&\n\t\tnewCrop.bottomRight.x === crop.bottomRight.x &&\n\t\tnewCrop.bottomRight.y === crop.bottomRight.y\n\t) {\n\t\treturn\n\t}\n\n\t// Adjust the shape's position to keep the crop's absolute coordinates correct\n\tconst newPoint = new Vec(tempBox.x - crop.topLeft.x * w, tempBox.y - crop.topLeft.y * h)\n\t\t.rot(shape.rotation)\n\t\t.add(shape)\n\n\treturn {\n\t\tid: shape.id,\n\t\ttype: shape.type,\n\t\tx: newPoint.x,\n\t\ty: newPoint.y,\n\t\tprops: {\n\t\t\tw: tempBox.w,\n\t\t\th: tempBox.h,\n\t\t\tcrop: newCrop,\n\t\t},\n\t}\n}\n\ninterface CropChange {\n\tcrop: {\n\t\ttopLeft: { x: number; y: number }\n\t\tbottomRight: { x: number; y: number }\n\t\tisCircle?: boolean\n\t}\n\tw: number\n\th: number\n\tx: number\n\ty: number\n}\n\n// Base function for calculating crop changes\nfunction calculateCropChange(\n\timageShape: TLImageShape,\n\tnewCropWidth: number,\n\tnewCropHeight: number,\n\tcenterOnCurrentCrop: boolean = true,\n\tisCircle: boolean = false\n): CropChange {\n\tconst { w, h } = getUncroppedSize(imageShape.props, imageShape.props.crop ?? getDefaultCrop())\n\tconst currentCrop = imageShape.props.crop || getDefaultCrop()\n\n\t// Calculate image and crop centers\n\tconst imageCenterX = imageShape.x + imageShape.props.w / 2\n\tconst imageCenterY = imageShape.y + imageShape.props.h / 2\n\n\tlet cropCenterX, cropCenterY\n\tif (centerOnCurrentCrop) {\n\t\tconst { x, y } = getCropCenter(currentCrop)\n\t\tcropCenterX = x\n\t\tcropCenterY = y\n\t} else {\n\t\tcropCenterX = 0.5\n\t\tcropCenterY = 0.5\n\t}\n\n\t// Create new crop\n\tconst newCrop = createCropAroundCenter(\n\t\tcropCenterX,\n\t\tcropCenterY,\n\t\tnewCropWidth,\n\t\tnewCropHeight,\n\t\tisCircle\n\t)\n\n\t// Calculate new dimensions\n\tconst croppedW = newCropWidth * w\n\tconst croppedH = newCropHeight * h\n\n\treturn {\n\t\tcrop: newCrop,\n\t\tw: croppedW,\n\t\th: croppedH,\n\t\tx: imageCenterX - croppedW / 2,\n\t\ty: imageCenterY - croppedH / 2,\n\t}\n}\n\n/** @internal */\nexport const MAX_ZOOM = 3\n\n/**\n * Calculate new crop dimensions and position when zooming\n */\nexport function getCroppedImageDataWhenZooming(\n\tzoom: number,\n\timageShape: TLImageShape,\n\tmaxZoom?: number\n): CropChange {\n\tconst oldCrop = imageShape.props.crop || getDefaultCrop()\n\tconst { width: oldWidth, height: oldHeight } = getCropDimensions(oldCrop)\n\tconst aspectRatio = oldWidth / oldHeight\n\n\t// Calculate new crop size with zoom scale\n\tconst derivedMaxZoom = maxZoom ? 1 / (1 - maxZoom) : MAX_ZOOM\n\tconst zoomScale = 1 + zoom * (derivedMaxZoom - 1)\n\tlet newWidth, newHeight\n\n\tif (aspectRatio > 1) {\n\t\tnewWidth = Math.min(1, 1 / zoomScale)\n\t\tnewHeight = newWidth / aspectRatio\n\t} else {\n\t\tnewHeight = Math.min(1, 1 / zoomScale)\n\t\tnewWidth = newHeight * aspectRatio\n\t}\n\n\t// Calculate result with base function\n\tconst result = calculateCropChange(imageShape, newWidth, newHeight, true, oldCrop.isCircle)\n\n\t// Apply zoom factor to display dimensions\n\tconst scaleFactor = Math.min(MAX_ZOOM, oldWidth / newWidth)\n\tresult.w *= scaleFactor\n\tresult.h *= scaleFactor\n\n\t// Recenter\n\tconst imageCenterX = imageShape.x + imageShape.props.w / 2\n\tconst imageCenterY = imageShape.y + imageShape.props.h / 2\n\tresult.x = imageCenterX - result.w / 2\n\tresult.y = imageCenterY - result.h / 2\n\n\treturn result\n}\n\n/**\n * Calculate new crop dimensions and position when replacing an image\n */\nexport function getCroppedImageDataForReplacedImage(\n\timageShape: TLImageShape,\n\tnewImageWidth: number,\n\tnewImageHeight: number\n): CropChange {\n\tconst defaultCrop = getDefaultCrop()\n\tconst currentCrop = imageShape.props.crop || defaultCrop\n\tconst origDisplayW = imageShape.props.w\n\tconst origDisplayH = imageShape.props.h\n\tconst newImageAspectRatio = newImageWidth / newImageHeight\n\n\tlet crop = defaultCrop\n\tlet newDisplayW = origDisplayW\n\tlet newDisplayH = origDisplayH\n\tconst isOriginalCrop = isEqual(imageShape.props.crop, defaultCrop)\n\n\tif (isOriginalCrop) {\n\t\tnewDisplayW = origDisplayW\n\t\tnewDisplayH = (origDisplayW * newImageHeight) / newImageWidth\n\t} else {\n\t\tconst { w: uncroppedW, h: uncroppedH } = getUncroppedSize(\n\t\t\timageShape.props,\n\t\t\timageShape.props.crop || getDefaultCrop() // Use the ACTUAL current crop to correctly infer uncropped size\n\t\t)\n\t\tconst { width: cropW, height: cropH } = getCropDimensions(currentCrop)\n\t\tconst targetRatio = cropW / cropH\n\t\tconst oldImageAspectRatio = uncroppedW / uncroppedH\n\t\tlet newRelativeWidth: number\n\t\tlet newRelativeHeight: number\n\n\t\tconst currentCropCenter = getCropCenter(currentCrop)\n\n\t\t// Adjust the new crop dimensions to match the current crop zoom\n\t\tnewRelativeWidth = cropW\n\t\tconst ratioConversion = newImageAspectRatio / oldImageAspectRatio / targetRatio\n\t\tnewRelativeHeight = newRelativeWidth * ratioConversion\n\n\t\t// Check that our new crop dimensions are within the MAX_ZOOM bounds\n\t\tconst maxRatioConversion = MAX_ZOOM / (MAX_ZOOM - 1)\n\t\tif (ratioConversion > maxRatioConversion) {\n\t\t\tconst minDimension = 1 / MAX_ZOOM\n\t\t\tif (1 / newRelativeHeight < 1 / newRelativeWidth) {\n\t\t\t\tconst scale = newRelativeHeight / minDimension\n\t\t\t\tnewRelativeHeight = newRelativeHeight / scale\n\t\t\t\tnewRelativeWidth = newRelativeWidth / scale\n\t\t\t} else {\n\t\t\t\tconst scale = newRelativeWidth / minDimension\n\t\t\t\tnewRelativeWidth = newRelativeWidth / scale\n\t\t\t\tnewRelativeHeight = newRelativeHeight / scale\n\t\t\t}\n\t\t}\n\n\t\t// Ensure dimensions are within [0, 1] bounds after adjustment\n\t\tnewRelativeWidth = Math.max(0, Math.min(1, newRelativeWidth))\n\t\tnewRelativeHeight = Math.max(0, Math.min(1, newRelativeHeight))\n\n\t\t// Create the new crop object, centered around the CURRENT crop's center\n\t\tcrop = createCropAroundCenter(\n\t\t\tcurrentCropCenter.x,\n\t\t\tcurrentCropCenter.y,\n\t\t\tnewRelativeWidth,\n\t\t\tnewRelativeHeight,\n\t\t\tcurrentCrop.isCircle\n\t\t)\n\t}\n\n\t// Position so visual center stays put\n\tconst pageCenterX = imageShape.x + origDisplayW / 2\n\tconst pageCenterY = imageShape.y + origDisplayH / 2\n\n\tconst newX = pageCenterX - newDisplayW / 2\n\tconst newY = pageCenterY - newDisplayH / 2\n\n\treturn {\n\t\tcrop,\n\t\tw: newDisplayW,\n\t\th: newDisplayH,\n\t\tx: newX,\n\t\ty: newY,\n\t}\n}\n\n/**\n * Calculate new crop dimensions and position when changing aspect ratio\n */\nexport function getCroppedImageDataForAspectRatio(\n\taspectRatioOption: ASPECT_RATIO_OPTION,\n\timageShape: TLImageShape\n): CropChange {\n\t// If original aspect ratio is requested, use default crop\n\tif (aspectRatioOption === 'original') {\n\t\tconst { w, h } = getUncroppedSize(imageShape.props, imageShape.props.crop ?? getDefaultCrop())\n\t\tconst imageCenterX = imageShape.x + imageShape.props.w / 2\n\t\tconst imageCenterY = imageShape.y + imageShape.props.h / 2\n\n\t\treturn {\n\t\t\tcrop: getDefaultCrop(),\n\t\t\tw,\n\t\t\th,\n\t\t\tx: imageCenterX - w / 2,\n\t\t\ty: imageCenterY - h / 2,\n\t\t}\n\t}\n\n\t// Get target ratio and uncropped image properties\n\tconst targetRatio = ASPECT_RATIO_TO_VALUE[aspectRatioOption] // Assume valid option\n\tconst isCircle = aspectRatioOption === 'circle'\n\t// Use default crop to get uncropped size relative to the *original* image bounds\n\tconst { w: uncroppedW, h: uncroppedH } = getUncroppedSize(\n\t\timageShape.props,\n\t\timageShape.props.crop || getDefaultCrop() // Use the ACTUAL current crop to correctly infer uncropped size\n\t)\n\t// Calculate the original image aspect ratio\n\tconst imageAspectRatio = uncroppedW / uncroppedH\n\n\t// Get the current crop and its relative dimensions\n\tconst currentCrop = imageShape.props.crop || getDefaultCrop()\n\tconst { width: cropW, height: cropH } = getCropDimensions(currentCrop)\n\tconst currentCropCenter = getCropCenter(currentCrop)\n\n\t// Calculate the current crop zoom level\n\tconst currentCropZoom = Math.min(1 / cropW, 1 / cropH)\n\n\t// Calculate the relative width and height of the crop rectangle (0-1 scale)\n\t// Try to preserve the longest dimension of the current crop when changing aspect ratios\n\tlet newRelativeWidth: number\n\tlet newRelativeHeight: number\n\n\tif (imageAspectRatio === 0 || !Number.isFinite(imageAspectRatio) || targetRatio === 0) {\n\t\t// Avoid division by zero or NaN issues if image dimensions are invalid or target ratio is 0\n\t\tnewRelativeWidth = 1\n\t\tnewRelativeHeight = 1\n\t} else {\n\t\t// Get current crop dimensions in absolute units\n\t\tconst currentAbsoluteWidth = cropW * uncroppedW\n\t\tconst currentAbsoluteHeight = cropH * uncroppedH\n\n\t\t// Find the longest current dimension to preserve\n\t\tconst longestCurrentDimension = Math.max(currentAbsoluteWidth, currentAbsoluteHeight)\n\t\tconst isWidthLongest = currentAbsoluteWidth >= currentAbsoluteHeight\n\n\t\t// Calculate new dimensions preserving the longest dimension\n\t\tlet newAbsoluteWidth: number\n\t\tlet newAbsoluteHeight: number\n\n\t\tif (isWidthLongest) {\n\t\t\t// Preserve width, calculate height based on target ratio\n\t\t\tnewAbsoluteWidth = longestCurrentDimension\n\t\t\tnewAbsoluteHeight = newAbsoluteWidth / targetRatio\n\t\t} else {\n\t\t\t// Preserve height, calculate width based on target ratio\n\t\t\tnewAbsoluteHeight = longestCurrentDimension\n\t\t\tnewAbsoluteWidth = newAbsoluteHeight * targetRatio\n\t\t}\n\n\t\t// Convert back to relative coordinates\n\t\tnewRelativeWidth = newAbsoluteWidth / uncroppedW\n\t\tnewRelativeHeight = newAbsoluteHeight / uncroppedH\n\n\t\t// Clamp to image bounds and adjust if necessary\n\t\tif (newRelativeWidth > 1) {\n\t\t\t// Width exceeds bounds, clamp and recalculate height\n\t\t\tnewRelativeWidth = 1\n\t\t\tnewRelativeHeight = imageAspectRatio / targetRatio\n\t\t}\n\t\tif (newRelativeHeight > 1) {\n\t\t\t// Height exceeds bounds, clamp and recalculate width\n\t\t\tnewRelativeHeight = 1\n\t\t\tnewRelativeWidth = targetRatio / imageAspectRatio\n\t\t}\n\n\t\t// Final clamp to ensure we stay within bounds\n\t\tnewRelativeWidth = Math.max(0, Math.min(1, newRelativeWidth))\n\t\tnewRelativeHeight = Math.max(0, Math.min(1, newRelativeHeight))\n\t}\n\n\tconst newCropZoom = Math.min(1 / newRelativeWidth, 1 / newRelativeHeight)\n\t// Adjust the new crop dimensions to match the current crop zoom\n\tnewRelativeWidth *= newCropZoom / currentCropZoom\n\tnewRelativeHeight *= newCropZoom / currentCropZoom\n\n\t// Ensure dimensions are within [0, 1] bounds after adjustment\n\tnewRelativeWidth = Math.max(0, Math.min(1, newRelativeWidth))\n\tnewRelativeHeight = Math.max(0, Math.min(1, newRelativeHeight))\n\n\t// Create the new crop object, centered around the CURRENT crop's center\n\tconst newCrop = createCropAroundCenter(\n\t\tcurrentCropCenter.x,\n\t\tcurrentCropCenter.y,\n\t\tnewRelativeWidth,\n\t\tnewRelativeHeight,\n\t\tisCircle\n\t)\n\n\t// Get the actual relative dimensions from the new crop (after potential clamping)\n\tconst finalRelativeWidth = newCrop.bottomRight.x - newCrop.topLeft.x\n\tconst finalRelativeHeight = newCrop.bottomRight.y - newCrop.topLeft.y\n\n\t// Calculate the base dimensions (as if applying the new crop to the uncropped image at scale 1)\n\tconst baseW = finalRelativeWidth * uncroppedW\n\tconst baseH = finalRelativeHeight * uncroppedH\n\n\t// Determine the current effective scale of the shape\n\t// This preserves the visual size when the crop changes\n\tlet currentScale = 1.0\n\tif (cropW > 0) {\n\t\tcurrentScale = imageShape.props.w / (cropW * uncroppedW)\n\t} else if (cropH > 0) {\n\t\t// Fallback to height if width relative dimension is zero\n\t\tcurrentScale = imageShape.props.h / (cropH * uncroppedH)\n\t}\n\n\t// Apply the current scale to the base dimensions to get the final dimensions\n\tconst newW = baseW * currentScale\n\tconst newH = baseH * currentScale\n\n\t// Calculate the new top-left position (x, y) for the shape\n\t// to keep the visual center of the cropped area fixed on the page.\n\tconst currentCenterXPage = imageShape.x + imageShape.props.w / 2\n\tconst currentCenterYPage = imageShape.y + imageShape.props.h / 2\n\tconst newX = currentCenterXPage - newW / 2\n\tconst newY = currentCenterYPage - newH / 2\n\n\treturn {\n\t\tcrop: newCrop,\n\t\tw: newW,\n\t\th: newH,\n\t\tx: newX,\n\t\ty: newY,\n\t}\n}\n"],
|
|
5
|
-
"mappings": "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",
|
|
4
|
+
"sourcesContent": ["import {\n\tBox,\n\tShapeWithCrop,\n\tTLCropInfo,\n\tTLImageShape,\n\tTLShapeCrop,\n\tTLShapeId,\n\tVec,\n\tclamp,\n\tisEqual,\n} from '@tldraw/editor'\n\n/** @internal */\nexport const MIN_CROP_SIZE = 8\n\n/** @public */\nexport interface CropBoxOptions {\n\tminWidth?: number\n\tminHeight?: number\n}\n\n/** @public */\nexport function getDefaultCrop(): TLShapeCrop {\n\treturn {\n\t\ttopLeft: { x: 0, y: 0 },\n\t\tbottomRight: { x: 1, y: 1 },\n\t}\n}\n\n/** @public */\nexport type ASPECT_RATIO_OPTION =\n\t| 'original'\n\t| 'square'\n\t| 'circle'\n\t| 'landscape'\n\t| 'portrait'\n\t| 'wide'\n\n/** @public */\nexport const ASPECT_RATIO_OPTIONS: ASPECT_RATIO_OPTION[] = [\n\t'original',\n\t'square',\n\t'circle',\n\t'landscape',\n\t'portrait',\n\t'wide',\n]\n\n/** @public */\nexport const ASPECT_RATIO_TO_VALUE: Record<ASPECT_RATIO_OPTION, number> = {\n\toriginal: 0,\n\tsquare: 1,\n\tcircle: 1,\n\tlandscape: 4 / 3,\n\tportrait: 3 / 4,\n\twide: 16 / 9,\n}\n\n/**\n * Original (uncropped) width and height of shape.\n *\n * @public\n */\nexport function getUncroppedSize(\n\tshapeSize: { w: number; h: number },\n\tcrop: TLShapeCrop | null\n): { w: number; h: number } {\n\tif (!crop) return { w: shapeSize.w, h: shapeSize.h }\n\tconst w = shapeSize.w / (crop.bottomRight.x - crop.topLeft.x)\n\tconst h = shapeSize.h / (crop.bottomRight.y - crop.topLeft.y)\n\treturn { w, h }\n}\n\n// Utility function to get crop dimensions\nfunction getCropDimensions(crop: TLShapeCrop) {\n\treturn {\n\t\twidth: crop.bottomRight.x - crop.topLeft.x,\n\t\theight: crop.bottomRight.y - crop.topLeft.y,\n\t}\n}\n\n// Utility function to get crop center\nfunction getCropCenter(crop: TLShapeCrop) {\n\tconst { width, height } = getCropDimensions(crop)\n\treturn {\n\t\tx: crop.topLeft.x + width / 2,\n\t\ty: crop.topLeft.y + height / 2,\n\t}\n}\n\n// Utility function to create crop with specified dimensions centered on given point\nfunction createCropAroundCenter(\n\tcenterX: number,\n\tcenterY: number,\n\twidth: number,\n\theight: number,\n\tisCircle?: boolean\n) {\n\tconst topLeftX = Math.max(0, Math.min(1 - width, centerX - width / 2))\n\tconst topLeftY = Math.max(0, Math.min(1 - height, centerY - height / 2))\n\n\treturn {\n\t\ttopLeft: { x: topLeftX, y: topLeftY },\n\t\tbottomRight: { x: topLeftX + width, y: topLeftY + height },\n\t\tisCircle,\n\t}\n}\n\n/** @public */\nexport function getCropBox<T extends ShapeWithCrop>(\n\tshape: T,\n\tinfo: TLCropInfo<T>,\n\topts = {} as CropBoxOptions\n):\n\t| {\n\t\t\tid: TLShapeId\n\t\t\ttype: T['type']\n\t\t\tx: number\n\t\t\ty: number\n\t\t\tprops: ShapeWithCrop['props']\n\t }\n\t| undefined {\n\tconst { handle, change, crop, aspectRatioLocked } = info\n\tconst { w, h } = info.uncroppedSize\n\tconst { minWidth = MIN_CROP_SIZE, minHeight = MIN_CROP_SIZE } = opts\n\n\tif (w < minWidth || h < minHeight || (change.x === 0 && change.y === 0)) {\n\t\treturn\n\t}\n\n\t// Lets get a box here in pixel space. For simplicity, we'll do all the math in\n\t// pixel space, then convert to normalized space at the end.\n\tconst prevCropBox = new Box(\n\t\tcrop.topLeft.x * w,\n\t\tcrop.topLeft.y * h,\n\t\t(crop.bottomRight.x - crop.topLeft.x) * w,\n\t\t(crop.bottomRight.y - crop.topLeft.y) * h\n\t)\n\n\tconst targetRatio = prevCropBox.aspectRatio\n\tconst tempBox = prevCropBox.clone()\n\n\t// Basic resizing logic based on the handles\n\n\tif (handle === 'top_left' || handle === 'bottom_left' || handle === 'left') {\n\t\ttempBox.x = clamp(tempBox.x + change.x, 0, prevCropBox.maxX - minWidth)\n\t\ttempBox.w = prevCropBox.maxX - tempBox.x\n\t} else if (handle === 'top_right' || handle === 'bottom_right' || handle === 'right') {\n\t\tconst tempRight = clamp(tempBox.maxX + change.x, prevCropBox.x + minWidth, w)\n\t\ttempBox.w = tempRight - tempBox.x\n\t}\n\n\tif (handle === 'top_left' || handle === 'top_right' || handle === 'top') {\n\t\ttempBox.y = clamp(tempBox.y + change.y, 0, prevCropBox.maxY - minHeight)\n\t\ttempBox.h = prevCropBox.maxY - tempBox.y\n\t} else if (handle === 'bottom_left' || handle === 'bottom_right' || handle === 'bottom') {\n\t\tconst tempBottom = clamp(tempBox.maxY + change.y, prevCropBox.y + minHeight, h)\n\t\ttempBox.h = tempBottom - tempBox.y\n\t}\n\n\t// Aspect ratio locked resizing logic\n\n\tif (aspectRatioLocked) {\n\t\tconst isXLimiting = tempBox.aspectRatio > targetRatio\n\n\t\tif (isXLimiting) {\n\t\t\ttempBox.h = tempBox.w / targetRatio\n\t\t} else {\n\t\t\ttempBox.w = tempBox.h * targetRatio\n\t\t}\n\n\t\tswitch (handle) {\n\t\t\tcase 'top_left': {\n\t\t\t\t// preserve the bottom right corner\n\t\t\t\ttempBox.x = prevCropBox.maxX - tempBox.w\n\t\t\t\ttempBox.y = prevCropBox.maxY - tempBox.h\n\n\t\t\t\tif (tempBox.x <= 0) {\n\t\t\t\t\ttempBox.x = 0\n\t\t\t\t\ttempBox.w = prevCropBox.maxX - tempBox.x\n\t\t\t\t\ttempBox.h = tempBox.w / targetRatio\n\t\t\t\t\ttempBox.y = prevCropBox.maxY - tempBox.h\n\t\t\t\t}\n\n\t\t\t\tif (tempBox.y <= 0) {\n\t\t\t\t\ttempBox.y = 0\n\t\t\t\t\ttempBox.h = prevCropBox.maxY - tempBox.y\n\t\t\t\t\ttempBox.w = tempBox.h * targetRatio\n\t\t\t\t\ttempBox.x = prevCropBox.maxX - tempBox.w\n\t\t\t\t}\n\t\t\t\tbreak\n\t\t\t}\n\t\t\tcase 'top_right': {\n\t\t\t\t// preserve the bottom left corner\n\t\t\t\ttempBox.x = prevCropBox.x\n\t\t\t\ttempBox.y = prevCropBox.maxY - tempBox.h\n\n\t\t\t\tif (tempBox.maxX >= w) {\n\t\t\t\t\ttempBox.w = w - prevCropBox.x\n\t\t\t\t\ttempBox.h = tempBox.w / targetRatio\n\t\t\t\t\ttempBox.y = prevCropBox.maxY - tempBox.h\n\t\t\t\t}\n\n\t\t\t\tif (tempBox.y <= 0) {\n\t\t\t\t\ttempBox.y = 0\n\t\t\t\t\ttempBox.h = prevCropBox.maxY - tempBox.y\n\t\t\t\t\ttempBox.w = tempBox.h * targetRatio\n\t\t\t\t}\n\t\t\t\tbreak\n\t\t\t}\n\t\t\tcase 'bottom_left': {\n\t\t\t\t// preserve the top right corner\n\t\t\t\ttempBox.x = prevCropBox.maxX - tempBox.w\n\t\t\t\ttempBox.y = prevCropBox.y\n\n\t\t\t\tif (tempBox.x <= 0) {\n\t\t\t\t\ttempBox.x = 0\n\t\t\t\t\ttempBox.w = prevCropBox.maxX - tempBox.x\n\t\t\t\t\ttempBox.h = tempBox.w / targetRatio\n\t\t\t\t}\n\n\t\t\t\tif (tempBox.maxY >= h) {\n\t\t\t\t\ttempBox.h = h - prevCropBox.y\n\t\t\t\t\ttempBox.w = tempBox.h * targetRatio\n\t\t\t\t\ttempBox.x = prevCropBox.maxX - tempBox.w\n\t\t\t\t}\n\t\t\t\tbreak\n\t\t\t}\n\t\t\tcase 'bottom_right': {\n\t\t\t\t// preserve the top left corner\n\t\t\t\ttempBox.x = prevCropBox.x\n\t\t\t\ttempBox.y = prevCropBox.y\n\n\t\t\t\tif (tempBox.maxX >= w) {\n\t\t\t\t\ttempBox.w = w - prevCropBox.x\n\t\t\t\t\ttempBox.h = tempBox.w / targetRatio\n\t\t\t\t}\n\n\t\t\t\tif (tempBox.maxY >= h) {\n\t\t\t\t\ttempBox.h = h - prevCropBox.y\n\t\t\t\t\ttempBox.w = tempBox.h * targetRatio\n\t\t\t\t}\n\t\t\t\tbreak\n\t\t\t}\n\t\t\tcase 'top': {\n\t\t\t\t// preserve the bottom edge center\n\t\t\t\ttempBox.h = prevCropBox.maxY - tempBox.y\n\t\t\t\ttempBox.w = tempBox.h * targetRatio\n\t\t\t\ttempBox.x -= (tempBox.w - prevCropBox.w) / 2\n\n\t\t\t\tif (tempBox.x <= 0) {\n\t\t\t\t\tconst leftSide = prevCropBox.midX\n\t\t\t\t\ttempBox.w = leftSide * 2\n\t\t\t\t\ttempBox.h = tempBox.w / targetRatio\n\t\t\t\t\ttempBox.x = 0\n\t\t\t\t}\n\n\t\t\t\tif (tempBox.maxX >= w) {\n\t\t\t\t\tconst rightSide = w - prevCropBox.midX\n\t\t\t\t\ttempBox.w = rightSide * 2\n\t\t\t\t\ttempBox.h = tempBox.w / targetRatio\n\t\t\t\t\ttempBox.x = w - tempBox.w\n\t\t\t\t}\n\n\t\t\t\ttempBox.y = prevCropBox.maxY - tempBox.h\n\t\t\t\tbreak\n\t\t\t}\n\t\t\tcase 'right': {\n\t\t\t\t// preserve the left edge center\n\t\t\t\ttempBox.w = tempBox.maxX - prevCropBox.x\n\t\t\t\ttempBox.h = tempBox.w / targetRatio\n\t\t\t\ttempBox.y -= (tempBox.h - prevCropBox.h) / 2\n\n\t\t\t\tif (tempBox.y <= 0) {\n\t\t\t\t\tconst topSide = prevCropBox.midY\n\t\t\t\t\ttempBox.h = topSide * 2\n\t\t\t\t\ttempBox.w = tempBox.h * targetRatio\n\t\t\t\t\ttempBox.y = 0\n\t\t\t\t}\n\n\t\t\t\tif (tempBox.maxY >= h) {\n\t\t\t\t\tconst bottomSide = h - prevCropBox.midY\n\t\t\t\t\ttempBox.h = bottomSide * 2\n\t\t\t\t\ttempBox.w = tempBox.h * targetRatio\n\t\t\t\t\ttempBox.y = h - tempBox.h\n\t\t\t\t}\n\t\t\t\tbreak\n\t\t\t}\n\t\t\tcase 'bottom': {\n\t\t\t\t// preserve the top edge center\n\t\t\t\ttempBox.h = tempBox.maxY - prevCropBox.y\n\t\t\t\ttempBox.w = tempBox.h * targetRatio\n\t\t\t\ttempBox.x -= (tempBox.w - prevCropBox.w) / 2\n\n\t\t\t\tif (tempBox.x <= 0) {\n\t\t\t\t\tconst leftSide = prevCropBox.midX\n\t\t\t\t\ttempBox.w = leftSide * 2\n\t\t\t\t\ttempBox.h = tempBox.w / targetRatio\n\t\t\t\t\ttempBox.x = 0\n\t\t\t\t}\n\n\t\t\t\tif (tempBox.maxX >= w) {\n\t\t\t\t\tconst rightSide = w - prevCropBox.midX\n\t\t\t\t\ttempBox.w = rightSide * 2\n\t\t\t\t\ttempBox.h = tempBox.w / targetRatio\n\t\t\t\t\ttempBox.x = w - tempBox.w\n\t\t\t\t}\n\t\t\t\tbreak\n\t\t\t}\n\t\t\tcase 'left': {\n\t\t\t\t// preserve the right edge center\n\t\t\t\ttempBox.w = prevCropBox.maxX - tempBox.x\n\t\t\t\ttempBox.h = tempBox.w / targetRatio\n\t\t\t\ttempBox.y -= (tempBox.h - prevCropBox.h) / 2\n\n\t\t\t\tif (tempBox.y <= 0) {\n\t\t\t\t\tconst topSide = prevCropBox.midY\n\t\t\t\t\ttempBox.h = topSide * 2\n\t\t\t\t\ttempBox.w = tempBox.h * targetRatio\n\t\t\t\t\ttempBox.y = 0\n\t\t\t\t}\n\n\t\t\t\tif (tempBox.maxY >= h) {\n\t\t\t\t\tconst bottomSide = h - prevCropBox.midY\n\t\t\t\t\ttempBox.h = bottomSide * 2\n\t\t\t\t\ttempBox.w = tempBox.h * targetRatio\n\t\t\t\t\ttempBox.y = h - tempBox.h\n\t\t\t\t}\n\n\t\t\t\ttempBox.x = prevCropBox.maxX - tempBox.w\n\t\t\t\tbreak\n\t\t\t}\n\t\t}\n\t}\n\n\t// Convert the box back to normalized space\n\tconst newCrop: TLShapeCrop = {\n\t\ttopLeft: { x: tempBox.x / w, y: tempBox.y / h },\n\t\tbottomRight: { x: tempBox.maxX / w, y: tempBox.maxY / h },\n\t\tisCircle: crop.isCircle,\n\t}\n\n\t// If the crop hasn't changed, we can return early\n\tif (\n\t\tnewCrop.topLeft.x === crop.topLeft.x &&\n\t\tnewCrop.topLeft.y === crop.topLeft.y &&\n\t\tnewCrop.bottomRight.x === crop.bottomRight.x &&\n\t\tnewCrop.bottomRight.y === crop.bottomRight.y\n\t) {\n\t\treturn\n\t}\n\n\t// Adjust the shape's position to keep the crop's absolute coordinates correct\n\tconst newPoint = new Vec(tempBox.x - crop.topLeft.x * w, tempBox.y - crop.topLeft.y * h)\n\t\t.rot(shape.rotation)\n\t\t.add(shape)\n\n\treturn {\n\t\tid: shape.id,\n\t\ttype: shape.type,\n\t\tx: newPoint.x,\n\t\ty: newPoint.y,\n\t\tprops: {\n\t\t\t...shape.props,\n\t\t\tw: tempBox.w,\n\t\t\th: tempBox.h,\n\t\t\tcrop: newCrop,\n\t\t},\n\t}\n}\n\ninterface CropChange {\n\tcrop: {\n\t\ttopLeft: { x: number; y: number }\n\t\tbottomRight: { x: number; y: number }\n\t\tisCircle?: boolean\n\t}\n\tw: number\n\th: number\n\tx: number\n\ty: number\n}\n\n// Base function for calculating crop changes\nfunction calculateCropChange(\n\timageShape: TLImageShape,\n\tnewCropWidth: number,\n\tnewCropHeight: number,\n\tcenterOnCurrentCrop: boolean = true,\n\tisCircle: boolean = false\n): CropChange {\n\tconst { w, h } = getUncroppedSize(imageShape.props, imageShape.props.crop ?? getDefaultCrop())\n\tconst currentCrop = imageShape.props.crop || getDefaultCrop()\n\n\t// Calculate image and crop centers\n\tconst imageCenterX = imageShape.x + imageShape.props.w / 2\n\tconst imageCenterY = imageShape.y + imageShape.props.h / 2\n\n\tlet cropCenterX, cropCenterY\n\tif (centerOnCurrentCrop) {\n\t\tconst { x, y } = getCropCenter(currentCrop)\n\t\tcropCenterX = x\n\t\tcropCenterY = y\n\t} else {\n\t\tcropCenterX = 0.5\n\t\tcropCenterY = 0.5\n\t}\n\n\t// Create new crop\n\tconst newCrop = createCropAroundCenter(\n\t\tcropCenterX,\n\t\tcropCenterY,\n\t\tnewCropWidth,\n\t\tnewCropHeight,\n\t\tisCircle\n\t)\n\n\t// Calculate new dimensions\n\tconst croppedW = newCropWidth * w\n\tconst croppedH = newCropHeight * h\n\n\treturn {\n\t\tcrop: newCrop,\n\t\tw: croppedW,\n\t\th: croppedH,\n\t\tx: imageCenterX - croppedW / 2,\n\t\ty: imageCenterY - croppedH / 2,\n\t}\n}\n\n/** @internal */\nexport const MAX_ZOOM = 3\n\n/**\n * Calculate new crop dimensions and position when zooming\n */\nexport function getCroppedImageDataWhenZooming(\n\tzoom: number,\n\timageShape: TLImageShape,\n\tmaxZoom?: number\n): CropChange {\n\tconst oldCrop = imageShape.props.crop || getDefaultCrop()\n\tconst { width: oldWidth, height: oldHeight } = getCropDimensions(oldCrop)\n\tconst aspectRatio = oldWidth / oldHeight\n\n\t// Calculate new crop size with zoom scale\n\tconst derivedMaxZoom = maxZoom ? 1 / (1 - maxZoom) : MAX_ZOOM\n\tconst zoomScale = 1 + zoom * (derivedMaxZoom - 1)\n\tlet newWidth, newHeight\n\n\tif (aspectRatio > 1) {\n\t\tnewWidth = Math.min(1, 1 / zoomScale)\n\t\tnewHeight = newWidth / aspectRatio\n\t} else {\n\t\tnewHeight = Math.min(1, 1 / zoomScale)\n\t\tnewWidth = newHeight * aspectRatio\n\t}\n\n\t// Calculate result with base function\n\tconst result = calculateCropChange(imageShape, newWidth, newHeight, true, oldCrop.isCircle)\n\n\t// Apply zoom factor to display dimensions\n\tconst scaleFactor = Math.min(MAX_ZOOM, oldWidth / newWidth)\n\tresult.w *= scaleFactor\n\tresult.h *= scaleFactor\n\n\t// Recenter\n\tconst imageCenterX = imageShape.x + imageShape.props.w / 2\n\tconst imageCenterY = imageShape.y + imageShape.props.h / 2\n\tresult.x = imageCenterX - result.w / 2\n\tresult.y = imageCenterY - result.h / 2\n\n\treturn result\n}\n\n/**\n * Calculate new crop dimensions and position when replacing an image\n */\nexport function getCroppedImageDataForReplacedImage(\n\timageShape: TLImageShape,\n\tnewImageWidth: number,\n\tnewImageHeight: number\n): CropChange {\n\tconst defaultCrop = getDefaultCrop()\n\tconst currentCrop = imageShape.props.crop || defaultCrop\n\tconst origDisplayW = imageShape.props.w\n\tconst origDisplayH = imageShape.props.h\n\tconst newImageAspectRatio = newImageWidth / newImageHeight\n\n\tlet crop = defaultCrop\n\tlet newDisplayW = origDisplayW\n\tlet newDisplayH = origDisplayH\n\tconst isOriginalCrop = isEqual(imageShape.props.crop, defaultCrop)\n\n\tif (isOriginalCrop) {\n\t\tnewDisplayW = origDisplayW\n\t\tnewDisplayH = (origDisplayW * newImageHeight) / newImageWidth\n\t} else {\n\t\tconst { w: uncroppedW, h: uncroppedH } = getUncroppedSize(\n\t\t\timageShape.props,\n\t\t\timageShape.props.crop || getDefaultCrop() // Use the ACTUAL current crop to correctly infer uncropped size\n\t\t)\n\t\tconst { width: cropW, height: cropH } = getCropDimensions(currentCrop)\n\t\tconst targetRatio = cropW / cropH\n\t\tconst oldImageAspectRatio = uncroppedW / uncroppedH\n\t\tlet newRelativeWidth: number\n\t\tlet newRelativeHeight: number\n\n\t\tconst currentCropCenter = getCropCenter(currentCrop)\n\n\t\t// Adjust the new crop dimensions to match the current crop zoom\n\t\tnewRelativeWidth = cropW\n\t\tconst ratioConversion = newImageAspectRatio / oldImageAspectRatio / targetRatio\n\t\tnewRelativeHeight = newRelativeWidth * ratioConversion\n\n\t\t// Check that our new crop dimensions are within the MAX_ZOOM bounds\n\t\tconst maxRatioConversion = MAX_ZOOM / (MAX_ZOOM - 1)\n\t\tif (ratioConversion > maxRatioConversion) {\n\t\t\tconst minDimension = 1 / MAX_ZOOM\n\t\t\tif (1 / newRelativeHeight < 1 / newRelativeWidth) {\n\t\t\t\tconst scale = newRelativeHeight / minDimension\n\t\t\t\tnewRelativeHeight = newRelativeHeight / scale\n\t\t\t\tnewRelativeWidth = newRelativeWidth / scale\n\t\t\t} else {\n\t\t\t\tconst scale = newRelativeWidth / minDimension\n\t\t\t\tnewRelativeWidth = newRelativeWidth / scale\n\t\t\t\tnewRelativeHeight = newRelativeHeight / scale\n\t\t\t}\n\t\t}\n\n\t\t// Ensure dimensions are within [0, 1] bounds after adjustment\n\t\tnewRelativeWidth = Math.max(0, Math.min(1, newRelativeWidth))\n\t\tnewRelativeHeight = Math.max(0, Math.min(1, newRelativeHeight))\n\n\t\t// Create the new crop object, centered around the CURRENT crop's center\n\t\tcrop = createCropAroundCenter(\n\t\t\tcurrentCropCenter.x,\n\t\t\tcurrentCropCenter.y,\n\t\t\tnewRelativeWidth,\n\t\t\tnewRelativeHeight,\n\t\t\tcurrentCrop.isCircle\n\t\t)\n\t}\n\n\t// Position so visual center stays put\n\tconst pageCenterX = imageShape.x + origDisplayW / 2\n\tconst pageCenterY = imageShape.y + origDisplayH / 2\n\n\tconst newX = pageCenterX - newDisplayW / 2\n\tconst newY = pageCenterY - newDisplayH / 2\n\n\treturn {\n\t\tcrop,\n\t\tw: newDisplayW,\n\t\th: newDisplayH,\n\t\tx: newX,\n\t\ty: newY,\n\t}\n}\n\n/**\n * Calculate new crop dimensions and position when changing aspect ratio\n */\nexport function getCroppedImageDataForAspectRatio(\n\taspectRatioOption: ASPECT_RATIO_OPTION,\n\timageShape: TLImageShape\n): CropChange {\n\t// If original aspect ratio is requested, use default crop\n\tif (aspectRatioOption === 'original') {\n\t\tconst { w, h } = getUncroppedSize(imageShape.props, imageShape.props.crop ?? getDefaultCrop())\n\t\tconst imageCenterX = imageShape.x + imageShape.props.w / 2\n\t\tconst imageCenterY = imageShape.y + imageShape.props.h / 2\n\n\t\treturn {\n\t\t\tcrop: getDefaultCrop(),\n\t\t\tw,\n\t\t\th,\n\t\t\tx: imageCenterX - w / 2,\n\t\t\ty: imageCenterY - h / 2,\n\t\t}\n\t}\n\n\t// Get target ratio and uncropped image properties\n\tconst targetRatio = ASPECT_RATIO_TO_VALUE[aspectRatioOption] // Assume valid option\n\tconst isCircle = aspectRatioOption === 'circle'\n\t// Use default crop to get uncropped size relative to the *original* image bounds\n\tconst { w: uncroppedW, h: uncroppedH } = getUncroppedSize(\n\t\timageShape.props,\n\t\timageShape.props.crop || getDefaultCrop() // Use the ACTUAL current crop to correctly infer uncropped size\n\t)\n\t// Calculate the original image aspect ratio\n\tconst imageAspectRatio = uncroppedW / uncroppedH\n\n\t// Get the current crop and its relative dimensions\n\tconst currentCrop = imageShape.props.crop || getDefaultCrop()\n\tconst { width: cropW, height: cropH } = getCropDimensions(currentCrop)\n\tconst currentCropCenter = getCropCenter(currentCrop)\n\n\t// Calculate the current crop zoom level\n\tconst currentCropZoom = Math.min(1 / cropW, 1 / cropH)\n\n\t// Calculate the relative width and height of the crop rectangle (0-1 scale)\n\t// Try to preserve the longest dimension of the current crop when changing aspect ratios\n\tlet newRelativeWidth: number\n\tlet newRelativeHeight: number\n\n\tif (imageAspectRatio === 0 || !Number.isFinite(imageAspectRatio) || targetRatio === 0) {\n\t\t// Avoid division by zero or NaN issues if image dimensions are invalid or target ratio is 0\n\t\tnewRelativeWidth = 1\n\t\tnewRelativeHeight = 1\n\t} else {\n\t\t// Get current crop dimensions in absolute units\n\t\tconst currentAbsoluteWidth = cropW * uncroppedW\n\t\tconst currentAbsoluteHeight = cropH * uncroppedH\n\n\t\t// Find the longest current dimension to preserve\n\t\tconst longestCurrentDimension = Math.max(currentAbsoluteWidth, currentAbsoluteHeight)\n\t\tconst isWidthLongest = currentAbsoluteWidth >= currentAbsoluteHeight\n\n\t\t// Calculate new dimensions preserving the longest dimension\n\t\tlet newAbsoluteWidth: number\n\t\tlet newAbsoluteHeight: number\n\n\t\tif (isWidthLongest) {\n\t\t\t// Preserve width, calculate height based on target ratio\n\t\t\tnewAbsoluteWidth = longestCurrentDimension\n\t\t\tnewAbsoluteHeight = newAbsoluteWidth / targetRatio\n\t\t} else {\n\t\t\t// Preserve height, calculate width based on target ratio\n\t\t\tnewAbsoluteHeight = longestCurrentDimension\n\t\t\tnewAbsoluteWidth = newAbsoluteHeight * targetRatio\n\t\t}\n\n\t\t// Convert back to relative coordinates\n\t\tnewRelativeWidth = newAbsoluteWidth / uncroppedW\n\t\tnewRelativeHeight = newAbsoluteHeight / uncroppedH\n\n\t\t// Clamp to image bounds and adjust if necessary\n\t\tif (newRelativeWidth > 1) {\n\t\t\t// Width exceeds bounds, clamp and recalculate height\n\t\t\tnewRelativeWidth = 1\n\t\t\tnewRelativeHeight = imageAspectRatio / targetRatio\n\t\t}\n\t\tif (newRelativeHeight > 1) {\n\t\t\t// Height exceeds bounds, clamp and recalculate width\n\t\t\tnewRelativeHeight = 1\n\t\t\tnewRelativeWidth = targetRatio / imageAspectRatio\n\t\t}\n\n\t\t// Final clamp to ensure we stay within bounds\n\t\tnewRelativeWidth = Math.max(0, Math.min(1, newRelativeWidth))\n\t\tnewRelativeHeight = Math.max(0, Math.min(1, newRelativeHeight))\n\t}\n\n\tconst newCropZoom = Math.min(1 / newRelativeWidth, 1 / newRelativeHeight)\n\t// Adjust the new crop dimensions to match the current crop zoom\n\tnewRelativeWidth *= newCropZoom / currentCropZoom\n\tnewRelativeHeight *= newCropZoom / currentCropZoom\n\n\t// Ensure dimensions are within [0, 1] bounds after adjustment\n\tnewRelativeWidth = Math.max(0, Math.min(1, newRelativeWidth))\n\tnewRelativeHeight = Math.max(0, Math.min(1, newRelativeHeight))\n\n\t// Create the new crop object, centered around the CURRENT crop's center\n\tconst newCrop = createCropAroundCenter(\n\t\tcurrentCropCenter.x,\n\t\tcurrentCropCenter.y,\n\t\tnewRelativeWidth,\n\t\tnewRelativeHeight,\n\t\tisCircle\n\t)\n\n\t// Get the actual relative dimensions from the new crop (after potential clamping)\n\tconst finalRelativeWidth = newCrop.bottomRight.x - newCrop.topLeft.x\n\tconst finalRelativeHeight = newCrop.bottomRight.y - newCrop.topLeft.y\n\n\t// Calculate the base dimensions (as if applying the new crop to the uncropped image at scale 1)\n\tconst baseW = finalRelativeWidth * uncroppedW\n\tconst baseH = finalRelativeHeight * uncroppedH\n\n\t// Determine the current effective scale of the shape\n\t// This preserves the visual size when the crop changes\n\tlet currentScale = 1.0\n\tif (cropW > 0) {\n\t\tcurrentScale = imageShape.props.w / (cropW * uncroppedW)\n\t} else if (cropH > 0) {\n\t\t// Fallback to height if width relative dimension is zero\n\t\tcurrentScale = imageShape.props.h / (cropH * uncroppedH)\n\t}\n\n\t// Apply the current scale to the base dimensions to get the final dimensions\n\tconst newW = baseW * currentScale\n\tconst newH = baseH * currentScale\n\n\t// Calculate the new top-left position (x, y) for the shape\n\t// to keep the visual center of the cropped area fixed on the page.\n\tconst currentCenterXPage = imageShape.x + imageShape.props.w / 2\n\tconst currentCenterYPage = imageShape.y + imageShape.props.h / 2\n\tconst newX = currentCenterXPage - newW / 2\n\tconst newY = currentCenterYPage - newH / 2\n\n\treturn {\n\t\tcrop: newCrop,\n\t\tw: newW,\n\t\th: newH,\n\t\tx: newX,\n\t\ty: newY,\n\t}\n}\n"],
|
|
5
|
+
"mappings": "AAAA;AAAA,EACC;AAAA,EAMA;AAAA,EACA;AAAA,EACA;AAAA,OACM;AAGA,MAAM,gBAAgB;AAStB,SAAS,iBAA8B;AAC7C,SAAO;AAAA,IACN,SAAS,EAAE,GAAG,GAAG,GAAG,EAAE;AAAA,IACtB,aAAa,EAAE,GAAG,GAAG,GAAG,EAAE;AAAA,EAC3B;AACD;AAYO,MAAM,uBAA8C;AAAA,EAC1D;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACD;AAGO,MAAM,wBAA6D;AAAA,EACzE,UAAU;AAAA,EACV,QAAQ;AAAA,EACR,QAAQ;AAAA,EACR,WAAW,IAAI;AAAA,EACf,UAAU,IAAI;AAAA,EACd,MAAM,KAAK;AACZ;AAOO,SAAS,iBACf,WACA,MAC2B;AAC3B,MAAI,CAAC,KAAM,QAAO,EAAE,GAAG,UAAU,GAAG,GAAG,UAAU,EAAE;AACnD,QAAM,IAAI,UAAU,KAAK,KAAK,YAAY,IAAI,KAAK,QAAQ;AAC3D,QAAM,IAAI,UAAU,KAAK,KAAK,YAAY,IAAI,KAAK,QAAQ;AAC3D,SAAO,EAAE,GAAG,EAAE;AACf;AAGA,SAAS,kBAAkB,MAAmB;AAC7C,SAAO;AAAA,IACN,OAAO,KAAK,YAAY,IAAI,KAAK,QAAQ;AAAA,IACzC,QAAQ,KAAK,YAAY,IAAI,KAAK,QAAQ;AAAA,EAC3C;AACD;AAGA,SAAS,cAAc,MAAmB;AACzC,QAAM,EAAE,OAAO,OAAO,IAAI,kBAAkB,IAAI;AAChD,SAAO;AAAA,IACN,GAAG,KAAK,QAAQ,IAAI,QAAQ;AAAA,IAC5B,GAAG,KAAK,QAAQ,IAAI,SAAS;AAAA,EAC9B;AACD;AAGA,SAAS,uBACR,SACA,SACA,OACA,QACA,UACC;AACD,QAAM,WAAW,KAAK,IAAI,GAAG,KAAK,IAAI,IAAI,OAAO,UAAU,QAAQ,CAAC,CAAC;AACrE,QAAM,WAAW,KAAK,IAAI,GAAG,KAAK,IAAI,IAAI,QAAQ,UAAU,SAAS,CAAC,CAAC;AAEvE,SAAO;AAAA,IACN,SAAS,EAAE,GAAG,UAAU,GAAG,SAAS;AAAA,IACpC,aAAa,EAAE,GAAG,WAAW,OAAO,GAAG,WAAW,OAAO;AAAA,IACzD;AAAA,EACD;AACD;AAGO,SAAS,WACf,OACA,MACA,OAAO,CAAC,GASI;AACZ,QAAM,EAAE,QAAQ,QAAQ,MAAM,kBAAkB,IAAI;AACpD,QAAM,EAAE,GAAG,EAAE,IAAI,KAAK;AACtB,QAAM,EAAE,WAAW,eAAe,YAAY,cAAc,IAAI;AAEhE,MAAI,IAAI,YAAY,IAAI,aAAc,OAAO,MAAM,KAAK,OAAO,MAAM,GAAI;AACxE;AAAA,EACD;AAIA,QAAM,cAAc,IAAI;AAAA,IACvB,KAAK,QAAQ,IAAI;AAAA,IACjB,KAAK,QAAQ,IAAI;AAAA,KAChB,KAAK,YAAY,IAAI,KAAK,QAAQ,KAAK;AAAA,KACvC,KAAK,YAAY,IAAI,KAAK,QAAQ,KAAK;AAAA,EACzC;AAEA,QAAM,cAAc,YAAY;AAChC,QAAM,UAAU,YAAY,MAAM;AAIlC,MAAI,WAAW,cAAc,WAAW,iBAAiB,WAAW,QAAQ;AAC3E,YAAQ,IAAI,MAAM,QAAQ,IAAI,OAAO,GAAG,GAAG,YAAY,OAAO,QAAQ;AACtE,YAAQ,IAAI,YAAY,OAAO,QAAQ;AAAA,EACxC,WAAW,WAAW,eAAe,WAAW,kBAAkB,WAAW,SAAS;AACrF,UAAM,YAAY,MAAM,QAAQ,OAAO,OAAO,GAAG,YAAY,IAAI,UAAU,CAAC;AAC5E,YAAQ,IAAI,YAAY,QAAQ;AAAA,EACjC;AAEA,MAAI,WAAW,cAAc,WAAW,eAAe,WAAW,OAAO;AACxE,YAAQ,IAAI,MAAM,QAAQ,IAAI,OAAO,GAAG,GAAG,YAAY,OAAO,SAAS;AACvE,YAAQ,IAAI,YAAY,OAAO,QAAQ;AAAA,EACxC,WAAW,WAAW,iBAAiB,WAAW,kBAAkB,WAAW,UAAU;AACxF,UAAM,aAAa,MAAM,QAAQ,OAAO,OAAO,GAAG,YAAY,IAAI,WAAW,CAAC;AAC9E,YAAQ,IAAI,aAAa,QAAQ;AAAA,EAClC;AAIA,MAAI,mBAAmB;AACtB,UAAM,cAAc,QAAQ,cAAc;AAE1C,QAAI,aAAa;AAChB,cAAQ,IAAI,QAAQ,IAAI;AAAA,IACzB,OAAO;AACN,cAAQ,IAAI,QAAQ,IAAI;AAAA,IACzB;AAEA,YAAQ,QAAQ;AAAA,MACf,KAAK,YAAY;AAEhB,gBAAQ,IAAI,YAAY,OAAO,QAAQ;AACvC,gBAAQ,IAAI,YAAY,OAAO,QAAQ;AAEvC,YAAI,QAAQ,KAAK,GAAG;AACnB,kBAAQ,IAAI;AACZ,kBAAQ,IAAI,YAAY,OAAO,QAAQ;AACvC,kBAAQ,IAAI,QAAQ,IAAI;AACxB,kBAAQ,IAAI,YAAY,OAAO,QAAQ;AAAA,QACxC;AAEA,YAAI,QAAQ,KAAK,GAAG;AACnB,kBAAQ,IAAI;AACZ,kBAAQ,IAAI,YAAY,OAAO,QAAQ;AACvC,kBAAQ,IAAI,QAAQ,IAAI;AACxB,kBAAQ,IAAI,YAAY,OAAO,QAAQ;AAAA,QACxC;AACA;AAAA,MACD;AAAA,MACA,KAAK,aAAa;AAEjB,gBAAQ,IAAI,YAAY;AACxB,gBAAQ,IAAI,YAAY,OAAO,QAAQ;AAEvC,YAAI,QAAQ,QAAQ,GAAG;AACtB,kBAAQ,IAAI,IAAI,YAAY;AAC5B,kBAAQ,IAAI,QAAQ,IAAI;AACxB,kBAAQ,IAAI,YAAY,OAAO,QAAQ;AAAA,QACxC;AAEA,YAAI,QAAQ,KAAK,GAAG;AACnB,kBAAQ,IAAI;AACZ,kBAAQ,IAAI,YAAY,OAAO,QAAQ;AACvC,kBAAQ,IAAI,QAAQ,IAAI;AAAA,QACzB;AACA;AAAA,MACD;AAAA,MACA,KAAK,eAAe;AAEnB,gBAAQ,IAAI,YAAY,OAAO,QAAQ;AACvC,gBAAQ,IAAI,YAAY;AAExB,YAAI,QAAQ,KAAK,GAAG;AACnB,kBAAQ,IAAI;AACZ,kBAAQ,IAAI,YAAY,OAAO,QAAQ;AACvC,kBAAQ,IAAI,QAAQ,IAAI;AAAA,QACzB;AAEA,YAAI,QAAQ,QAAQ,GAAG;AACtB,kBAAQ,IAAI,IAAI,YAAY;AAC5B,kBAAQ,IAAI,QAAQ,IAAI;AACxB,kBAAQ,IAAI,YAAY,OAAO,QAAQ;AAAA,QACxC;AACA;AAAA,MACD;AAAA,MACA,KAAK,gBAAgB;AAEpB,gBAAQ,IAAI,YAAY;AACxB,gBAAQ,IAAI,YAAY;AAExB,YAAI,QAAQ,QAAQ,GAAG;AACtB,kBAAQ,IAAI,IAAI,YAAY;AAC5B,kBAAQ,IAAI,QAAQ,IAAI;AAAA,QACzB;AAEA,YAAI,QAAQ,QAAQ,GAAG;AACtB,kBAAQ,IAAI,IAAI,YAAY;AAC5B,kBAAQ,IAAI,QAAQ,IAAI;AAAA,QACzB;AACA;AAAA,MACD;AAAA,MACA,KAAK,OAAO;AAEX,gBAAQ,IAAI,YAAY,OAAO,QAAQ;AACvC,gBAAQ,IAAI,QAAQ,IAAI;AACxB,gBAAQ,MAAM,QAAQ,IAAI,YAAY,KAAK;AAE3C,YAAI,QAAQ,KAAK,GAAG;AACnB,gBAAM,WAAW,YAAY;AAC7B,kBAAQ,IAAI,WAAW;AACvB,kBAAQ,IAAI,QAAQ,IAAI;AACxB,kBAAQ,IAAI;AAAA,QACb;AAEA,YAAI,QAAQ,QAAQ,GAAG;AACtB,gBAAM,YAAY,IAAI,YAAY;AAClC,kBAAQ,IAAI,YAAY;AACxB,kBAAQ,IAAI,QAAQ,IAAI;AACxB,kBAAQ,IAAI,IAAI,QAAQ;AAAA,QACzB;AAEA,gBAAQ,IAAI,YAAY,OAAO,QAAQ;AACvC;AAAA,MACD;AAAA,MACA,KAAK,SAAS;AAEb,gBAAQ,IAAI,QAAQ,OAAO,YAAY;AACvC,gBAAQ,IAAI,QAAQ,IAAI;AACxB,gBAAQ,MAAM,QAAQ,IAAI,YAAY,KAAK;AAE3C,YAAI,QAAQ,KAAK,GAAG;AACnB,gBAAM,UAAU,YAAY;AAC5B,kBAAQ,IAAI,UAAU;AACtB,kBAAQ,IAAI,QAAQ,IAAI;AACxB,kBAAQ,IAAI;AAAA,QACb;AAEA,YAAI,QAAQ,QAAQ,GAAG;AACtB,gBAAM,aAAa,IAAI,YAAY;AACnC,kBAAQ,IAAI,aAAa;AACzB,kBAAQ,IAAI,QAAQ,IAAI;AACxB,kBAAQ,IAAI,IAAI,QAAQ;AAAA,QACzB;AACA;AAAA,MACD;AAAA,MACA,KAAK,UAAU;AAEd,gBAAQ,IAAI,QAAQ,OAAO,YAAY;AACvC,gBAAQ,IAAI,QAAQ,IAAI;AACxB,gBAAQ,MAAM,QAAQ,IAAI,YAAY,KAAK;AAE3C,YAAI,QAAQ,KAAK,GAAG;AACnB,gBAAM,WAAW,YAAY;AAC7B,kBAAQ,IAAI,WAAW;AACvB,kBAAQ,IAAI,QAAQ,IAAI;AACxB,kBAAQ,IAAI;AAAA,QACb;AAEA,YAAI,QAAQ,QAAQ,GAAG;AACtB,gBAAM,YAAY,IAAI,YAAY;AAClC,kBAAQ,IAAI,YAAY;AACxB,kBAAQ,IAAI,QAAQ,IAAI;AACxB,kBAAQ,IAAI,IAAI,QAAQ;AAAA,QACzB;AACA;AAAA,MACD;AAAA,MACA,KAAK,QAAQ;AAEZ,gBAAQ,IAAI,YAAY,OAAO,QAAQ;AACvC,gBAAQ,IAAI,QAAQ,IAAI;AACxB,gBAAQ,MAAM,QAAQ,IAAI,YAAY,KAAK;AAE3C,YAAI,QAAQ,KAAK,GAAG;AACnB,gBAAM,UAAU,YAAY;AAC5B,kBAAQ,IAAI,UAAU;AACtB,kBAAQ,IAAI,QAAQ,IAAI;AACxB,kBAAQ,IAAI;AAAA,QACb;AAEA,YAAI,QAAQ,QAAQ,GAAG;AACtB,gBAAM,aAAa,IAAI,YAAY;AACnC,kBAAQ,IAAI,aAAa;AACzB,kBAAQ,IAAI,QAAQ,IAAI;AACxB,kBAAQ,IAAI,IAAI,QAAQ;AAAA,QACzB;AAEA,gBAAQ,IAAI,YAAY,OAAO,QAAQ;AACvC;AAAA,MACD;AAAA,IACD;AAAA,EACD;AAGA,QAAM,UAAuB;AAAA,IAC5B,SAAS,EAAE,GAAG,QAAQ,IAAI,GAAG,GAAG,QAAQ,IAAI,EAAE;AAAA,IAC9C,aAAa,EAAE,GAAG,QAAQ,OAAO,GAAG,GAAG,QAAQ,OAAO,EAAE;AAAA,IACxD,UAAU,KAAK;AAAA,EAChB;AAGA,MACC,QAAQ,QAAQ,MAAM,KAAK,QAAQ,KACnC,QAAQ,QAAQ,MAAM,KAAK,QAAQ,KACnC,QAAQ,YAAY,MAAM,KAAK,YAAY,KAC3C,QAAQ,YAAY,MAAM,KAAK,YAAY,GAC1C;AACD;AAAA,EACD;AAGA,QAAM,WAAW,IAAI,IAAI,QAAQ,IAAI,KAAK,QAAQ,IAAI,GAAG,QAAQ,IAAI,KAAK,QAAQ,IAAI,CAAC,EACrF,IAAI,MAAM,QAAQ,EAClB,IAAI,KAAK;AAEX,SAAO;AAAA,IACN,IAAI,MAAM;AAAA,IACV,MAAM,MAAM;AAAA,IACZ,GAAG,SAAS;AAAA,IACZ,GAAG,SAAS;AAAA,IACZ,OAAO;AAAA,MACN,GAAG,MAAM;AAAA,MACT,GAAG,QAAQ;AAAA,MACX,GAAG,QAAQ;AAAA,MACX,MAAM;AAAA,IACP;AAAA,EACD;AACD;AAeA,SAAS,oBACR,YACA,cACA,eACA,sBAA+B,MAC/B,WAAoB,OACP;AACb,QAAM,EAAE,GAAG,EAAE,IAAI,iBAAiB,WAAW,OAAO,WAAW,MAAM,QAAQ,eAAe,CAAC;AAC7F,QAAM,cAAc,WAAW,MAAM,QAAQ,eAAe;AAG5D,QAAM,eAAe,WAAW,IAAI,WAAW,MAAM,IAAI;AACzD,QAAM,eAAe,WAAW,IAAI,WAAW,MAAM,IAAI;AAEzD,MAAI,aAAa;AACjB,MAAI,qBAAqB;AACxB,UAAM,EAAE,GAAG,EAAE,IAAI,cAAc,WAAW;AAC1C,kBAAc;AACd,kBAAc;AAAA,EACf,OAAO;AACN,kBAAc;AACd,kBAAc;AAAA,EACf;AAGA,QAAM,UAAU;AAAA,IACf;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACD;AAGA,QAAM,WAAW,eAAe;AAChC,QAAM,WAAW,gBAAgB;AAEjC,SAAO;AAAA,IACN,MAAM;AAAA,IACN,GAAG;AAAA,IACH,GAAG;AAAA,IACH,GAAG,eAAe,WAAW;AAAA,IAC7B,GAAG,eAAe,WAAW;AAAA,EAC9B;AACD;AAGO,MAAM,WAAW;AAKjB,SAAS,+BACf,MACA,YACA,SACa;AACb,QAAM,UAAU,WAAW,MAAM,QAAQ,eAAe;AACxD,QAAM,EAAE,OAAO,UAAU,QAAQ,UAAU,IAAI,kBAAkB,OAAO;AACxE,QAAM,cAAc,WAAW;AAG/B,QAAM,iBAAiB,UAAU,KAAK,IAAI,WAAW;AACrD,QAAM,YAAY,IAAI,QAAQ,iBAAiB;AAC/C,MAAI,UAAU;AAEd,MAAI,cAAc,GAAG;AACpB,eAAW,KAAK,IAAI,GAAG,IAAI,SAAS;AACpC,gBAAY,WAAW;AAAA,EACxB,OAAO;AACN,gBAAY,KAAK,IAAI,GAAG,IAAI,SAAS;AACrC,eAAW,YAAY;AAAA,EACxB;AAGA,QAAM,SAAS,oBAAoB,YAAY,UAAU,WAAW,MAAM,QAAQ,QAAQ;AAG1F,QAAM,cAAc,KAAK,IAAI,UAAU,WAAW,QAAQ;AAC1D,SAAO,KAAK;AACZ,SAAO,KAAK;AAGZ,QAAM,eAAe,WAAW,IAAI,WAAW,MAAM,IAAI;AACzD,QAAM,eAAe,WAAW,IAAI,WAAW,MAAM,IAAI;AACzD,SAAO,IAAI,eAAe,OAAO,IAAI;AACrC,SAAO,IAAI,eAAe,OAAO,IAAI;AAErC,SAAO;AACR;AAKO,SAAS,oCACf,YACA,eACA,gBACa;AACb,QAAM,cAAc,eAAe;AACnC,QAAM,cAAc,WAAW,MAAM,QAAQ;AAC7C,QAAM,eAAe,WAAW,MAAM;AACtC,QAAM,eAAe,WAAW,MAAM;AACtC,QAAM,sBAAsB,gBAAgB;AAE5C,MAAI,OAAO;AACX,MAAI,cAAc;AAClB,MAAI,cAAc;AAClB,QAAM,iBAAiB,QAAQ,WAAW,MAAM,MAAM,WAAW;AAEjE,MAAI,gBAAgB;AACnB,kBAAc;AACd,kBAAe,eAAe,iBAAkB;AAAA,EACjD,OAAO;AACN,UAAM,EAAE,GAAG,YAAY,GAAG,WAAW,IAAI;AAAA,MACxC,WAAW;AAAA,MACX,WAAW,MAAM,QAAQ,eAAe;AAAA;AAAA,IACzC;AACA,UAAM,EAAE,OAAO,OAAO,QAAQ,MAAM,IAAI,kBAAkB,WAAW;AACrE,UAAM,cAAc,QAAQ;AAC5B,UAAM,sBAAsB,aAAa;AACzC,QAAI;AACJ,QAAI;AAEJ,UAAM,oBAAoB,cAAc,WAAW;AAGnD,uBAAmB;AACnB,UAAM,kBAAkB,sBAAsB,sBAAsB;AACpE,wBAAoB,mBAAmB;AAGvC,UAAM,qBAAqB,YAAY,WAAW;AAClD,QAAI,kBAAkB,oBAAoB;AACzC,YAAM,eAAe,IAAI;AACzB,UAAI,IAAI,oBAAoB,IAAI,kBAAkB;AACjD,cAAM,QAAQ,oBAAoB;AAClC,4BAAoB,oBAAoB;AACxC,2BAAmB,mBAAmB;AAAA,MACvC,OAAO;AACN,cAAM,QAAQ,mBAAmB;AACjC,2BAAmB,mBAAmB;AACtC,4BAAoB,oBAAoB;AAAA,MACzC;AAAA,IACD;AAGA,uBAAmB,KAAK,IAAI,GAAG,KAAK,IAAI,GAAG,gBAAgB,CAAC;AAC5D,wBAAoB,KAAK,IAAI,GAAG,KAAK,IAAI,GAAG,iBAAiB,CAAC;AAG9D,WAAO;AAAA,MACN,kBAAkB;AAAA,MAClB,kBAAkB;AAAA,MAClB;AAAA,MACA;AAAA,MACA,YAAY;AAAA,IACb;AAAA,EACD;AAGA,QAAM,cAAc,WAAW,IAAI,eAAe;AAClD,QAAM,cAAc,WAAW,IAAI,eAAe;AAElD,QAAM,OAAO,cAAc,cAAc;AACzC,QAAM,OAAO,cAAc,cAAc;AAEzC,SAAO;AAAA,IACN;AAAA,IACA,GAAG;AAAA,IACH,GAAG;AAAA,IACH,GAAG;AAAA,IACH,GAAG;AAAA,EACJ;AACD;AAKO,SAAS,kCACf,mBACA,YACa;AAEb,MAAI,sBAAsB,YAAY;AACrC,UAAM,EAAE,GAAG,EAAE,IAAI,iBAAiB,WAAW,OAAO,WAAW,MAAM,QAAQ,eAAe,CAAC;AAC7F,UAAM,eAAe,WAAW,IAAI,WAAW,MAAM,IAAI;AACzD,UAAM,eAAe,WAAW,IAAI,WAAW,MAAM,IAAI;AAEzD,WAAO;AAAA,MACN,MAAM,eAAe;AAAA,MACrB;AAAA,MACA;AAAA,MACA,GAAG,eAAe,IAAI;AAAA,MACtB,GAAG,eAAe,IAAI;AAAA,IACvB;AAAA,EACD;AAGA,QAAM,cAAc,sBAAsB,iBAAiB;AAC3D,QAAM,WAAW,sBAAsB;AAEvC,QAAM,EAAE,GAAG,YAAY,GAAG,WAAW,IAAI;AAAA,IACxC,WAAW;AAAA,IACX,WAAW,MAAM,QAAQ,eAAe;AAAA;AAAA,EACzC;AAEA,QAAM,mBAAmB,aAAa;AAGtC,QAAM,cAAc,WAAW,MAAM,QAAQ,eAAe;AAC5D,QAAM,EAAE,OAAO,OAAO,QAAQ,MAAM,IAAI,kBAAkB,WAAW;AACrE,QAAM,oBAAoB,cAAc,WAAW;AAGnD,QAAM,kBAAkB,KAAK,IAAI,IAAI,OAAO,IAAI,KAAK;AAIrD,MAAI;AACJ,MAAI;AAEJ,MAAI,qBAAqB,KAAK,CAAC,OAAO,SAAS,gBAAgB,KAAK,gBAAgB,GAAG;AAEtF,uBAAmB;AACnB,wBAAoB;AAAA,EACrB,OAAO;AAEN,UAAM,uBAAuB,QAAQ;AACrC,UAAM,wBAAwB,QAAQ;AAGtC,UAAM,0BAA0B,KAAK,IAAI,sBAAsB,qBAAqB;AACpF,UAAM,iBAAiB,wBAAwB;AAG/C,QAAI;AACJ,QAAI;AAEJ,QAAI,gBAAgB;AAEnB,yBAAmB;AACnB,0BAAoB,mBAAmB;AAAA,IACxC,OAAO;AAEN,0BAAoB;AACpB,yBAAmB,oBAAoB;AAAA,IACxC;AAGA,uBAAmB,mBAAmB;AACtC,wBAAoB,oBAAoB;AAGxC,QAAI,mBAAmB,GAAG;AAEzB,yBAAmB;AACnB,0BAAoB,mBAAmB;AAAA,IACxC;AACA,QAAI,oBAAoB,GAAG;AAE1B,0BAAoB;AACpB,yBAAmB,cAAc;AAAA,IAClC;AAGA,uBAAmB,KAAK,IAAI,GAAG,KAAK,IAAI,GAAG,gBAAgB,CAAC;AAC5D,wBAAoB,KAAK,IAAI,GAAG,KAAK,IAAI,GAAG,iBAAiB,CAAC;AAAA,EAC/D;AAEA,QAAM,cAAc,KAAK,IAAI,IAAI,kBAAkB,IAAI,iBAAiB;AAExE,sBAAoB,cAAc;AAClC,uBAAqB,cAAc;AAGnC,qBAAmB,KAAK,IAAI,GAAG,KAAK,IAAI,GAAG,gBAAgB,CAAC;AAC5D,sBAAoB,KAAK,IAAI,GAAG,KAAK,IAAI,GAAG,iBAAiB,CAAC;AAG9D,QAAM,UAAU;AAAA,IACf,kBAAkB;AAAA,IAClB,kBAAkB;AAAA,IAClB;AAAA,IACA;AAAA,IACA;AAAA,EACD;AAGA,QAAM,qBAAqB,QAAQ,YAAY,IAAI,QAAQ,QAAQ;AACnE,QAAM,sBAAsB,QAAQ,YAAY,IAAI,QAAQ,QAAQ;AAGpE,QAAM,QAAQ,qBAAqB;AACnC,QAAM,QAAQ,sBAAsB;AAIpC,MAAI,eAAe;AACnB,MAAI,QAAQ,GAAG;AACd,mBAAe,WAAW,MAAM,KAAK,QAAQ;AAAA,EAC9C,WAAW,QAAQ,GAAG;AAErB,mBAAe,WAAW,MAAM,KAAK,QAAQ;AAAA,EAC9C;AAGA,QAAM,OAAO,QAAQ;AACrB,QAAM,OAAO,QAAQ;AAIrB,QAAM,qBAAqB,WAAW,IAAI,WAAW,MAAM,IAAI;AAC/D,QAAM,qBAAqB,WAAW,IAAI,WAAW,MAAM,IAAI;AAC/D,QAAM,OAAO,qBAAqB,OAAO;AACzC,QAAM,OAAO,qBAAqB,OAAO;AAEzC,SAAO;AAAA,IACN,MAAM;AAAA,IACN,GAAG;AAAA,IACH,GAAG;AAAA,IACH,GAAG;AAAA,IACH,GAAG;AAAA,EACJ;AACD;",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -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\
|
|
5
|
-
"mappings": "AAAA;AAAA,EAIC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACM;AACP,SAAgB,aAAa,WAAW,cAAc;AACtD,SAAS,mBAAmB;AAGrB,SAAS,
|
|
4
|
+
"sourcesContent": ["import {\n\tEditor,\n\tExtractShapeByProps,\n\tTLShapeId,\n\tgetPointerInfo,\n\tnoop,\n\tpreventDefault,\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(\n\tshapeId: TLShapeId,\n\ttype: ExtractShapeByProps<{ text: string }>['type'],\n\ttext?: string\n) {\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({\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(editor, 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\te.stopPropagation() // 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: editor.markEventAsHandled,\n\t\thandlePaste,\n\t\tisEditing,\n\t\tisReadyForEditing,\n\t}\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|