tldraw 5.1.0 → 5.2.0-canary.4a316fdfb2bb
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 +6 -8
- package/dist-cjs/index.js +1 -1
- package/dist-cjs/lib/defaultExternalContentHandlers.js +16 -2
- package/dist-cjs/lib/defaultExternalContentHandlers.js.map +2 -2
- package/dist-cjs/lib/shapes/bookmark/bookmarks.js +2 -2
- package/dist-cjs/lib/shapes/bookmark/bookmarks.js.map +2 -2
- package/dist-cjs/lib/shapes/note/NoteShapeUtil.js +4 -0
- package/dist-cjs/lib/shapes/note/NoteShapeUtil.js.map +2 -2
- package/dist-cjs/lib/shapes/shared/interpolate-props.js +2 -2
- package/dist-cjs/lib/shapes/shared/interpolate-props.js.map +2 -2
- package/dist-cjs/lib/shapes/shared/useEditablePlainText.js +4 -2
- package/dist-cjs/lib/shapes/shared/useEditablePlainText.js.map +2 -2
- package/dist-cjs/lib/shapes/text/RichTextArea.js +2 -2
- package/dist-cjs/lib/shapes/text/RichTextArea.js.map +2 -2
- package/dist-cjs/lib/tools/HandTool/HandTool.js +1 -22
- package/dist-cjs/lib/tools/HandTool/HandTool.js.map +2 -2
- package/dist-cjs/lib/tools/SelectTool/childStates/Crop/Crop.js +3 -1
- package/dist-cjs/lib/tools/SelectTool/childStates/Crop/Crop.js.map +2 -2
- package/dist-cjs/lib/tools/SelectTool/childStates/Crop/children/Idle.js +1 -1
- package/dist-cjs/lib/tools/SelectTool/childStates/Crop/children/Idle.js.map +2 -2
- package/dist-cjs/lib/tools/SelectTool/childStates/Crop/children/PointingCrop.js +7 -0
- package/dist-cjs/lib/tools/SelectTool/childStates/Crop/children/PointingCrop.js.map +2 -2
- package/dist-cjs/lib/tools/SelectTool/childStates/Crop/children/PointingCropHandle.js +7 -0
- package/dist-cjs/lib/tools/SelectTool/childStates/Crop/children/PointingCropHandle.js.map +2 -2
- package/dist-cjs/lib/tools/SelectTool/childStates/Idle.js +1 -1
- package/dist-cjs/lib/tools/SelectTool/childStates/Idle.js.map +2 -2
- package/dist-cjs/lib/tools/SelectTool/childStates/PointingCanvas.js +7 -0
- package/dist-cjs/lib/tools/SelectTool/childStates/PointingCanvas.js.map +2 -2
- package/dist-cjs/lib/tools/SelectTool/childStates/PointingHandle.js +7 -0
- package/dist-cjs/lib/tools/SelectTool/childStates/PointingHandle.js.map +2 -2
- package/dist-cjs/lib/tools/SelectTool/childStates/PointingResizeHandle.js +7 -0
- package/dist-cjs/lib/tools/SelectTool/childStates/PointingResizeHandle.js.map +2 -2
- package/dist-cjs/lib/tools/SelectTool/childStates/PointingRotateHandle.js +7 -0
- package/dist-cjs/lib/tools/SelectTool/childStates/PointingRotateHandle.js.map +2 -2
- package/dist-cjs/lib/tools/SelectTool/childStates/PointingSelection.js +4 -1
- package/dist-cjs/lib/tools/SelectTool/childStates/PointingSelection.js.map +2 -2
- package/dist-cjs/lib/tools/SelectTool/childStates/PointingShape.js +10 -1
- package/dist-cjs/lib/tools/SelectTool/childStates/PointingShape.js.map +2 -2
- package/dist-cjs/lib/ui/components/A11y.js +2 -2
- package/dist-cjs/lib/ui/components/A11y.js.map +2 -2
- package/dist-cjs/lib/ui/components/LoadingScreen.js +2 -2
- package/dist-cjs/lib/ui/components/LoadingScreen.js.map +2 -2
- package/dist-cjs/lib/ui/components/PageMenu/edit-pages-shared.js +2 -2
- package/dist-cjs/lib/ui/components/PageMenu/edit-pages-shared.js.map +2 -2
- package/dist-cjs/lib/ui/components/StylePanel/StylePanelDropdownPicker.js +2 -1
- package/dist-cjs/lib/ui/components/StylePanel/StylePanelDropdownPicker.js.map +2 -2
- package/dist-cjs/lib/ui/components/Toolbar/OverflowingToolbar.js +2 -2
- package/dist-cjs/lib/ui/components/Toolbar/OverflowingToolbar.js.map +2 -2
- package/dist-cjs/lib/ui/components/primitives/TldrawUiContextualToolbar.js +3 -3
- package/dist-cjs/lib/ui/components/primitives/TldrawUiContextualToolbar.js.map +2 -2
- package/dist-cjs/lib/ui/components/primitives/TldrawUiToolbar.js +6 -6
- package/dist-cjs/lib/ui/components/primitives/TldrawUiToolbar.js.map +2 -2
- package/dist-cjs/lib/ui/hooks/menu-hooks.js +8 -8
- package/dist-cjs/lib/ui/hooks/menu-hooks.js.map +2 -2
- package/dist-cjs/lib/ui/hooks/useClipboardEvents.js +4 -4
- package/dist-cjs/lib/ui/hooks/useClipboardEvents.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/text/richText.js +5 -0
- package/dist-cjs/lib/utils/text/richText.js.map +2 -2
- package/dist-cjs/lib/utils/text/text.js +2 -2
- package/dist-cjs/lib/utils/text/text.js.map +2 -2
- package/dist-esm/index.d.mts +6 -8
- package/dist-esm/index.mjs +1 -1
- package/dist-esm/lib/defaultExternalContentHandlers.mjs +16 -2
- package/dist-esm/lib/defaultExternalContentHandlers.mjs.map +2 -2
- package/dist-esm/lib/shapes/bookmark/bookmarks.mjs +2 -2
- package/dist-esm/lib/shapes/bookmark/bookmarks.mjs.map +2 -2
- package/dist-esm/lib/shapes/note/NoteShapeUtil.mjs +5 -0
- package/dist-esm/lib/shapes/note/NoteShapeUtil.mjs.map +2 -2
- package/dist-esm/lib/shapes/shared/interpolate-props.mjs +2 -2
- package/dist-esm/lib/shapes/shared/interpolate-props.mjs.map +2 -2
- package/dist-esm/lib/shapes/shared/useEditablePlainText.mjs +4 -3
- package/dist-esm/lib/shapes/shared/useEditablePlainText.mjs.map +2 -2
- package/dist-esm/lib/shapes/text/RichTextArea.mjs +2 -2
- package/dist-esm/lib/shapes/text/RichTextArea.mjs.map +2 -2
- package/dist-esm/lib/tools/HandTool/HandTool.mjs +1 -22
- package/dist-esm/lib/tools/HandTool/HandTool.mjs.map +2 -2
- package/dist-esm/lib/tools/SelectTool/childStates/Crop/Crop.mjs +3 -1
- package/dist-esm/lib/tools/SelectTool/childStates/Crop/Crop.mjs.map +2 -2
- package/dist-esm/lib/tools/SelectTool/childStates/Crop/children/Idle.mjs +1 -1
- package/dist-esm/lib/tools/SelectTool/childStates/Crop/children/Idle.mjs.map +2 -2
- package/dist-esm/lib/tools/SelectTool/childStates/Crop/children/PointingCrop.mjs +7 -0
- package/dist-esm/lib/tools/SelectTool/childStates/Crop/children/PointingCrop.mjs.map +2 -2
- package/dist-esm/lib/tools/SelectTool/childStates/Crop/children/PointingCropHandle.mjs +7 -0
- package/dist-esm/lib/tools/SelectTool/childStates/Crop/children/PointingCropHandle.mjs.map +2 -2
- package/dist-esm/lib/tools/SelectTool/childStates/Idle.mjs +1 -1
- package/dist-esm/lib/tools/SelectTool/childStates/Idle.mjs.map +2 -2
- package/dist-esm/lib/tools/SelectTool/childStates/PointingCanvas.mjs +7 -0
- package/dist-esm/lib/tools/SelectTool/childStates/PointingCanvas.mjs.map +2 -2
- package/dist-esm/lib/tools/SelectTool/childStates/PointingHandle.mjs +11 -1
- package/dist-esm/lib/tools/SelectTool/childStates/PointingHandle.mjs.map +2 -2
- package/dist-esm/lib/tools/SelectTool/childStates/PointingResizeHandle.mjs +10 -1
- package/dist-esm/lib/tools/SelectTool/childStates/PointingResizeHandle.mjs.map +2 -2
- package/dist-esm/lib/tools/SelectTool/childStates/PointingRotateHandle.mjs +7 -0
- package/dist-esm/lib/tools/SelectTool/childStates/PointingRotateHandle.mjs.map +2 -2
- package/dist-esm/lib/tools/SelectTool/childStates/PointingSelection.mjs +4 -1
- package/dist-esm/lib/tools/SelectTool/childStates/PointingSelection.mjs.map +2 -2
- package/dist-esm/lib/tools/SelectTool/childStates/PointingShape.mjs +10 -1
- package/dist-esm/lib/tools/SelectTool/childStates/PointingShape.mjs.map +2 -2
- package/dist-esm/lib/ui/components/A11y.mjs +2 -2
- package/dist-esm/lib/ui/components/A11y.mjs.map +2 -2
- package/dist-esm/lib/ui/components/LoadingScreen.mjs +2 -2
- package/dist-esm/lib/ui/components/LoadingScreen.mjs.map +2 -2
- package/dist-esm/lib/ui/components/PageMenu/edit-pages-shared.mjs +2 -2
- package/dist-esm/lib/ui/components/PageMenu/edit-pages-shared.mjs.map +2 -2
- package/dist-esm/lib/ui/components/StylePanel/StylePanelDropdownPicker.mjs +2 -1
- package/dist-esm/lib/ui/components/StylePanel/StylePanelDropdownPicker.mjs.map +2 -2
- package/dist-esm/lib/ui/components/Toolbar/OverflowingToolbar.mjs +2 -2
- package/dist-esm/lib/ui/components/Toolbar/OverflowingToolbar.mjs.map +2 -2
- package/dist-esm/lib/ui/components/primitives/TldrawUiContextualToolbar.mjs +3 -3
- package/dist-esm/lib/ui/components/primitives/TldrawUiContextualToolbar.mjs.map +2 -2
- package/dist-esm/lib/ui/components/primitives/TldrawUiToolbar.mjs +6 -6
- package/dist-esm/lib/ui/components/primitives/TldrawUiToolbar.mjs.map +2 -2
- package/dist-esm/lib/ui/hooks/menu-hooks.mjs +8 -8
- package/dist-esm/lib/ui/hooks/menu-hooks.mjs.map +2 -2
- package/dist-esm/lib/ui/hooks/useClipboardEvents.mjs +4 -4
- package/dist-esm/lib/ui/hooks/useClipboardEvents.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/text/richText.mjs +5 -0
- package/dist-esm/lib/utils/text/richText.mjs.map +2 -2
- package/dist-esm/lib/utils/text/text.mjs +2 -2
- package/dist-esm/lib/utils/text/text.mjs.map +2 -2
- package/package.json +4 -4
- package/src/lib/defaultExternalContentHandlers.ts +20 -1
- package/src/lib/shapes/bookmark/bookmarks.ts +1 -1
- package/src/lib/shapes/note/NoteShapeUtil.tsx +10 -0
- package/src/lib/shapes/shared/interpolate-props.ts +2 -2
- package/src/lib/shapes/shared/useEditablePlainText.ts +2 -3
- package/src/lib/shapes/text/RichTextArea.tsx +2 -2
- package/src/lib/tools/HandTool/HandTool.ts +1 -25
- package/src/lib/tools/SelectTool/childStates/Crop/Crop.ts +3 -1
- package/src/lib/tools/SelectTool/childStates/Crop/children/Idle.ts +2 -2
- package/src/lib/tools/SelectTool/childStates/Crop/children/PointingCrop.ts +15 -1
- package/src/lib/tools/SelectTool/childStates/Crop/children/PointingCropHandle.ts +15 -1
- package/src/lib/tools/SelectTool/childStates/Idle.ts +1 -1
- package/src/lib/tools/SelectTool/childStates/PointingCanvas.ts +15 -1
- package/src/lib/tools/SelectTool/childStates/PointingHandle.ts +23 -1
- package/src/lib/tools/SelectTool/childStates/PointingResizeHandle.ts +21 -1
- package/src/lib/tools/SelectTool/childStates/PointingRotateHandle.ts +15 -1
- package/src/lib/tools/SelectTool/childStates/PointingSelection.ts +11 -2
- package/src/lib/tools/SelectTool/childStates/PointingShape.ts +18 -2
- package/src/lib/ui/components/A11y.tsx +1 -1
- package/src/lib/ui/components/LoadingScreen.tsx +1 -1
- package/src/lib/ui/components/PageMenu/edit-pages-shared.ts +2 -2
- package/src/lib/ui/components/StylePanel/StylePanelDropdownPicker.tsx +8 -1
- package/src/lib/ui/components/Toolbar/OverflowingToolbar.tsx +2 -2
- package/src/lib/ui/components/primitives/TldrawUiContextualToolbar.tsx +2 -2
- package/src/lib/ui/components/primitives/TldrawUiToolbar.tsx +4 -4
- package/src/lib/ui/hooks/menu-hooks.ts +4 -4
- package/src/lib/ui/hooks/useClipboardEvents.ts +3 -3
- package/src/lib/ui/version.ts +3 -3
- package/src/lib/utils/text/richText.ts +9 -0
- package/src/lib/utils/text/text.ts +1 -1
- package/src/test/ClickManager.test.ts +33 -28
- package/src/test/HandTool.test.ts +5 -34
- package/src/test/SelectTool.test.ts +135 -0
- package/src/test/TestEditor.ts +44 -42
- package/src/test/commands/__snapshots__/getSvgString.test.ts.snap +4 -6
- package/src/test/cropping.test.ts +7 -0
- package/src/test/getSnapLines.ts +1 -1
- package/src/test/pinch-dom.test.tsx +170 -0
- package/src/test/pinch.test.ts +139 -0
- package/src/test/roundedBox.ts +1 -1
- package/src/test/selection-omnibus.test.ts +4 -4
package/dist-cjs/index.d.ts
CHANGED
|
@@ -2562,7 +2562,7 @@ export declare function GroupOrUngroupMenuItem(): JSX.Element;
|
|
|
2562
2562
|
*
|
|
2563
2563
|
* @public
|
|
2564
2564
|
*/
|
|
2565
|
-
export declare
|
|
2565
|
+
export declare function handleNativeOrMenuCopy(editor: Editor, context?: TLClipboardWriteInfo): Promise<boolean>;
|
|
2566
2566
|
|
|
2567
2567
|
/** @public */
|
|
2568
2568
|
export declare class HandTool extends StateNode {
|
|
@@ -2571,8 +2571,6 @@ export declare class HandTool extends StateNode {
|
|
|
2571
2571
|
static isLockable: boolean;
|
|
2572
2572
|
static children(): TLStateNodeConstructor[];
|
|
2573
2573
|
onDoubleClick(info: TLClickEventInfo): void;
|
|
2574
|
-
onTripleClick(info: TLClickEventInfo): void;
|
|
2575
|
-
onQuadrupleClick(info: TLClickEventInfo): void;
|
|
2576
2574
|
}
|
|
2577
2575
|
|
|
2578
2576
|
/** @public @react */
|
|
@@ -4237,7 +4235,7 @@ export declare const TldrawUiContextProvider: NamedExoticComponent<TLUiContextPr
|
|
|
4237
4235
|
*
|
|
4238
4236
|
* @public @react
|
|
4239
4237
|
*/
|
|
4240
|
-
export declare
|
|
4238
|
+
export declare function TldrawUiContextualToolbar({ children, className, isMousingDown, getSelectionBounds, changeOnlyWhenYChanges, label }: TLUiContextualToolbarProps): JSX.Element;
|
|
4241
4239
|
|
|
4242
4240
|
/** @public @react */
|
|
4243
4241
|
export declare function TldrawUiDialogBody({ className, children, style }: TLUiDialogBodyProps): JSX.Element;
|
|
@@ -4453,10 +4451,10 @@ export declare const TldrawUiToolbar: React_3.ForwardRefExoticComponent<TLUiTool
|
|
|
4453
4451
|
export declare const TldrawUiToolbarButton: React_3.ForwardRefExoticComponent<TLUiToolbarButtonProps & React_3.RefAttributes<HTMLButtonElement>>;
|
|
4454
4452
|
|
|
4455
4453
|
/** @public @react */
|
|
4456
|
-
export declare
|
|
4454
|
+
export declare function TldrawUiToolbarToggleGroup({ children, className, type, asChild, ...props }: TLUiToolbarToggleGroupProps): JSX.Element;
|
|
4457
4455
|
|
|
4458
4456
|
/** @public @react */
|
|
4459
|
-
export declare
|
|
4457
|
+
export declare function TldrawUiToolbarToggleItem({ children, className, type, value, tooltip, ...props }: TLUiToolbarToggleItemProps): JSX.Element;
|
|
4460
4458
|
|
|
4461
4459
|
/** @public @react */
|
|
4462
4460
|
export declare const TldrawUiTooltip: React_3.ForwardRefExoticComponent<TldrawUiTooltipProps & React_3.RefAttributes<HTMLButtonElement>>;
|
|
@@ -5709,7 +5707,7 @@ export declare function TrapezoidToolbarItem(): JSX.Element;
|
|
|
5709
5707
|
export declare function TriangleToolbarItem(): JSX.Element;
|
|
5710
5708
|
|
|
5711
5709
|
/** @public */
|
|
5712
|
-
export declare
|
|
5710
|
+
export declare function truncateStringWithEllipsis(str: string, maxLength: number): string;
|
|
5713
5711
|
|
|
5714
5712
|
/** @public @react */
|
|
5715
5713
|
export declare function UndoRedoGroup(): JSX.Element;
|
|
@@ -5951,7 +5949,7 @@ export declare function useReadonly(): boolean;
|
|
|
5951
5949
|
export declare function useRelevantStyles(stylesToCheck?: readonly StyleProp<any>[]): null | ReadonlySharedStyleMap;
|
|
5952
5950
|
|
|
5953
5951
|
/** @public */
|
|
5954
|
-
export declare
|
|
5952
|
+
export declare function useSelectedShapesAnnouncer(): void;
|
|
5955
5953
|
|
|
5956
5954
|
/** @public */
|
|
5957
5955
|
export declare function useShowCollaborationUi(): boolean;
|
package/dist-cjs/index.js
CHANGED
|
@@ -648,7 +648,7 @@ var import_buildFromV1Document = require("./lib/utils/tldr/buildFromV1Document")
|
|
|
648
648
|
var import_file = require("./lib/utils/tldr/file");
|
|
649
649
|
(0, import_editor.registerTldrawLibraryVersion)(
|
|
650
650
|
"tldraw",
|
|
651
|
-
"5.
|
|
651
|
+
"5.2.0-canary.4a316fdfb2bb",
|
|
652
652
|
"cjs"
|
|
653
653
|
);
|
|
654
654
|
//# sourceMappingURL=index.js.map
|
|
@@ -409,12 +409,26 @@ async function defaultHandleExternalTldrawContent(editor, { point, content }) {
|
|
|
409
409
|
shape.isLocked = false;
|
|
410
410
|
}
|
|
411
411
|
}
|
|
412
|
+
const isMidInteraction = editor.isInAny(
|
|
413
|
+
"select.dragging_handle",
|
|
414
|
+
"select.translating",
|
|
415
|
+
"select.resizing",
|
|
416
|
+
"select.rotating"
|
|
417
|
+
);
|
|
412
418
|
editor.putContentOntoCurrentPage(content, {
|
|
413
419
|
point,
|
|
414
|
-
select:
|
|
420
|
+
select: !isMidInteraction
|
|
415
421
|
});
|
|
416
422
|
const selectedBoundsAfter = editor.getSelectionPageBounds();
|
|
417
|
-
if (
|
|
423
|
+
if (
|
|
424
|
+
// When mid-interaction we don't select the pasted content, so the
|
|
425
|
+
// selection is unchanged and the before/after bounds are identical —
|
|
426
|
+
// the overlap check would always pass. The selection flash below
|
|
427
|
+
// signals that the newly-selected pasted content landed on the old
|
|
428
|
+
// selection, which is meaningless when we didn't change the
|
|
429
|
+
// selection, so skip it.
|
|
430
|
+
!isMidInteraction && selectionBoundsBefore && selectedBoundsAfter && selectionBoundsBefore?.collides(selectedBoundsAfter)
|
|
431
|
+
) {
|
|
418
432
|
editor.updateInstanceState({ isChangingStyle: true });
|
|
419
433
|
editor.timers.setTimeout(() => {
|
|
420
434
|
editor.updateInstanceState({ isChangingStyle: false });
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../src/lib/defaultExternalContentHandlers.ts"],
|
|
4
|
-
"sourcesContent": ["import {\n\tAssetRecordType,\n\tEditor,\n\tTLAsset,\n\tTLAssetId,\n\tTLBookmarkAsset,\n\tTLBookmarkShape,\n\tTLContent,\n\tTLFileExternalAsset,\n\tTLFileReplaceExternalContent,\n\tTLImageAsset,\n\tTLImageShape,\n\tTLShapeId,\n\tTLShapePartial,\n\tTLTextShape,\n\tTLTextShapeProps,\n\tTLUrlExternalAsset,\n\tTLVideoAsset,\n\tVec,\n\tVecLike,\n\tassert,\n\tcreateShapeId,\n\tfetch,\n\tgetHashForBuffer,\n\tgetHashForString,\n\tmaybeSnapToGrid,\n\ttoRichText,\n} from '@tldraw/editor'\nimport { EmbedDefinition } from './defaultEmbedDefinitions'\nimport { createBookmarkFromUrl } from './shapes/bookmark/bookmarks'\nimport { EmbedShapeUtil } from './shapes/embed/EmbedShapeUtil'\nimport { getCroppedImageDataForReplacedImage } from './shapes/shared/crop'\nimport { FONT_SIZES, TEXT_PROPS, getFontFamily } from './shapes/shared/default-shape-constants'\nimport { TLUiToastsContextType } from './ui/context/toasts'\nimport { useTranslation } from './ui/hooks/useTranslation/useTranslation'\nimport { putExcalidrawContent } from './utils/excalidraw/putExcalidrawContent'\nimport { renderHtmlFromRichTextForMeasurement, renderRichTextFromHTML } from './utils/text/richText'\nimport { cleanupText, isRightToLeftLanguage } from './utils/text/text'\n\n/**\n * 5000px\n * @public\n */\nexport const DEFAULT_MAX_IMAGE_DIMENSION = 5000\n/**\n * 10mb\n * @public\n */\nexport const DEFAULT_MAX_ASSET_SIZE = 10 * 1024 * 1024\n\n/** @public */\nexport interface TLExternalContentProps {\n\t/**\n\t * The maximum dimension (width or height) of an image. Images larger than this will be rescaled\n\t * to fit. Defaults to infinity.\n\t */\n\tmaxImageDimension?: number\n\t/**\n\t * The maximum size (in bytes) of an asset. Assets larger than this will be rejected. Defaults\n\t * to 10mb (10 * 1024 * 1024).\n\t */\n\tmaxAssetSize?: number\n\t/**\n\t * The mime types of images that are allowed to be handled. When passed to\n\t * the `Tldraw` component, this also reconfigures the default `ImageAssetUtil`\n\t * to only accept files matching these types. If you only want to accept a\n\t * subset of image types and want to additionally block videos, pass\n\t * `acceptedVideoMimeTypes={[]}`. A file is accepted if its MIME type is in\n\t * this list, in `acceptedVideoMimeTypes`, or if any registered asset util\n\t * accepts it.\n\t */\n\tacceptedImageMimeTypes?: readonly string[]\n\t/**\n\t * The mime types of videos that are allowed to be handled. When passed to\n\t * the `Tldraw` component, this also reconfigures the default `VideoAssetUtil`\n\t * to only accept files matching these types. A file is accepted if its MIME\n\t * type is in this list, in `acceptedImageMimeTypes`, or if any registered\n\t * asset util accepts it.\n\t */\n\tacceptedVideoMimeTypes?: readonly string[]\n}\n\n/** @public */\nexport interface TLDefaultExternalContentHandlerOpts extends TLExternalContentProps {\n\ttoasts: TLUiToastsContextType\n\tmsg: ReturnType<typeof useTranslation>\n}\n\n/** @public */\nexport function registerDefaultExternalContentHandlers(\n\teditor: Editor,\n\toptions: TLDefaultExternalContentHandlerOpts\n) {\n\t// files -> asset\n\teditor.registerExternalAssetHandler('file', async (externalAsset) => {\n\t\treturn defaultHandleExternalFileAsset(editor, externalAsset, options)\n\t})\n\n\t// urls -> bookmark asset\n\teditor.registerExternalAssetHandler('url', async (externalAsset) => {\n\t\treturn defaultHandleExternalUrlAsset(editor, externalAsset, options)\n\t})\n\n\t// svg text\n\teditor.registerExternalContentHandler('svg-text', async (externalContent) => {\n\t\treturn defaultHandleExternalSvgTextContent(editor, externalContent)\n\t})\n\n\t// embeds\n\teditor.registerExternalContentHandler<'embed', EmbedDefinition>('embed', (externalContent) => {\n\t\treturn defaultHandleExternalEmbedContent(editor, externalContent)\n\t})\n\n\t// files\n\teditor.registerExternalContentHandler('files', async (externalContent) => {\n\t\treturn defaultHandleExternalFileContent(editor, externalContent, options)\n\t})\n\n\t// file-replace -> asset\n\teditor.registerExternalContentHandler('file-replace', async (externalContent) => {\n\t\treturn defaultHandleExternalFileReplaceContent(editor, externalContent, options)\n\t})\n\n\t// text\n\teditor.registerExternalContentHandler('text', async (externalContent) => {\n\t\treturn defaultHandleExternalTextContent(editor, externalContent)\n\t})\n\n\t// url\n\teditor.registerExternalContentHandler('url', async (externalContent) => {\n\t\treturn defaultHandleExternalUrlContent(editor, externalContent, options)\n\t})\n\n\t// tldraw\n\teditor.registerExternalContentHandler('tldraw', async (externalContent) => {\n\t\treturn defaultHandleExternalTldrawContent(editor, externalContent)\n\t})\n\n\t// excalidraw\n\teditor.registerExternalContentHandler('excalidraw', async (externalContent) => {\n\t\treturn defaultHandleExternalExcalidrawContent(editor, externalContent)\n\t})\n}\n\n/** @public */\nexport async function defaultHandleExternalFileAsset(\n\teditor: Editor,\n\t{ file, assetId }: TLFileExternalAsset,\n\toptions: TLDefaultExternalContentHandlerOpts\n) {\n\tconst isSuccess = notifyIfFileNotAllowed(editor, file, options)\n\tif (!isSuccess) assert(false, 'File checks failed')\n\n\tconst sanitizedFile = await maybeSanitizeSvgFile(file)\n\tif (!sanitizedFile) assert(false, 'SVG file contained no safe content')\n\tconst assetInfo = await getAssetInfo(editor, sanitizedFile, assetId)\n\tif (!assetInfo) assert(false, `No asset util found for MIME type \"${file.type}\"`)\n\tconst result = await editor.uploadAsset(assetInfo, sanitizedFile)\n\tassetInfo.props.src = result.src\n\tif (result.meta) assetInfo.meta = { ...assetInfo.meta, ...result.meta }\n\n\treturn AssetRecordType.create(assetInfo)\n}\n\n/** @public */\nexport async function defaultHandleExternalFileReplaceContent(\n\teditor: Editor,\n\t{ file, shapeId }: TLFileReplaceExternalContent,\n\toptions: TLDefaultExternalContentHandlerOpts\n) {\n\tconst isSuccess = notifyIfFileNotAllowed(editor, file, options)\n\tif (!isSuccess) assert(false, 'File checks failed')\n\n\tconst sanitizedFile = await maybeSanitizeSvgFile(file)\n\tif (!sanitizedFile) return\n\tconst shape = editor.getShape(shapeId)\n\tif (!shape) assert(false, 'Shape not found')\n\n\tconst hash = getHashForBuffer(await sanitizedFile.arrayBuffer())\n\tconst assetId = AssetRecordType.createId(hash)\n\teditor.createTemporaryAssetPreview(assetId, sanitizedFile)\n\tconst assetInfoPartial = (await getAssetInfo(editor, sanitizedFile, assetId)) as\n\t\t| TLImageAsset\n\t\t| TLVideoAsset\n\t\t| null\n\tif (!assetInfoPartial) return\n\teditor.createAssets([assetInfoPartial])\n\n\t// And update the shape\n\tif (shape.type === 'image') {\n\t\tconst imageShape = shape as TLImageShape\n\t\tconst currentCrop = imageShape.props.crop\n\n\t\t// Calculate new dimensions that preserve the current visual size of the cropped area\n\t\tlet newWidth = assetInfoPartial.props.w\n\t\tlet newHeight = assetInfoPartial.props.h\n\t\tlet newX = imageShape.x\n\t\tlet newY = imageShape.y\n\t\tlet finalCrop = currentCrop\n\n\t\tif (currentCrop) {\n\t\t\t// Use the dedicated function to calculate the new crop and dimensions\n\t\t\tconst result = getCroppedImageDataForReplacedImage(\n\t\t\t\timageShape,\n\t\t\t\tassetInfoPartial.props.w,\n\t\t\t\tassetInfoPartial.props.h\n\t\t\t)\n\n\t\t\tfinalCrop = result.crop\n\t\t\tnewWidth = result.w\n\t\t\tnewHeight = result.h\n\t\t\tnewX = result.x\n\t\t\tnewY = result.y\n\t\t}\n\n\t\teditor.updateShapes([\n\t\t\t{\n\t\t\t\tid: imageShape.id,\n\t\t\t\ttype: imageShape.type,\n\t\t\t\tprops: {\n\t\t\t\t\tassetId: assetId,\n\t\t\t\t\tcrop: finalCrop,\n\t\t\t\t\tw: newWidth,\n\t\t\t\t\th: newHeight,\n\t\t\t\t},\n\t\t\t\tx: newX,\n\t\t\t\ty: newY,\n\t\t\t},\n\t\t])\n\t} else if (shape.type === 'video') {\n\t\teditor.updateShapes([\n\t\t\t{\n\t\t\t\tid: shape.id,\n\t\t\t\ttype: shape.type,\n\t\t\t\tprops: {\n\t\t\t\t\tassetId: assetId,\n\t\t\t\t\tw: assetInfoPartial.props.w,\n\t\t\t\t\th: assetInfoPartial.props.h,\n\t\t\t\t},\n\t\t\t},\n\t\t])\n\t}\n\n\tconst asset = (await editor.getAssetForExternalContent({\n\t\ttype: 'file',\n\t\tfile: sanitizedFile,\n\t\tassetId,\n\t})) as TLAsset\n\n\teditor.updateAssets([{ ...asset, id: assetId }])\n\n\treturn asset\n}\n\n/** @public */\nexport async function defaultHandleExternalUrlAsset(\n\teditor: Editor,\n\t{ url }: TLUrlExternalAsset,\n\t{ toasts, msg }: TLDefaultExternalContentHandlerOpts\n): Promise<TLBookmarkAsset> {\n\tlet meta: { image: string; favicon: string; title: string; description: string }\n\n\ttry {\n\t\tconst resp = await fetch(url, {\n\t\t\tmethod: 'GET',\n\t\t\tmode: 'no-cors',\n\t\t})\n\t\tconst html = await resp.text()\n\t\tconst doc = new DOMParser().parseFromString(html, 'text/html')\n\t\tmeta = {\n\t\t\timage: doc.head.querySelector('meta[property=\"og:image\"]')?.getAttribute('content') ?? '',\n\t\t\tfavicon:\n\t\t\t\tdoc.head.querySelector('link[rel=\"apple-touch-icon\"]')?.getAttribute('href') ??\n\t\t\t\tdoc.head.querySelector('link[rel=\"icon\"]')?.getAttribute('href') ??\n\t\t\t\t'',\n\t\t\ttitle: doc.head.querySelector('meta[property=\"og:title\"]')?.getAttribute('content') ?? url,\n\t\t\tdescription:\n\t\t\t\tdoc.head.querySelector('meta[property=\"og:description\"]')?.getAttribute('content') ?? '',\n\t\t}\n\t\tif (!meta.image.startsWith('http')) {\n\t\t\tmeta.image = new URL(meta.image, url).href\n\t\t}\n\t\tif (!meta.favicon.startsWith('http')) {\n\t\t\tmeta.favicon = new URL(meta.favicon, url).href\n\t\t}\n\t} catch (error) {\n\t\tconsole.error(error)\n\t\ttoasts.addToast({\n\t\t\ttitle: msg('assets.url.failed'),\n\t\t\tseverity: 'error',\n\t\t})\n\t\tmeta = { image: '', favicon: '', title: '', description: '' }\n\t}\n\n\t// Create the bookmark asset from the meta\n\treturn {\n\t\tid: AssetRecordType.createId(getHashForString(url)),\n\t\ttypeName: 'asset',\n\t\ttype: 'bookmark',\n\t\tprops: {\n\t\t\tsrc: url,\n\t\t\tdescription: meta.description,\n\t\t\timage: meta.image,\n\t\t\tfavicon: meta.favicon,\n\t\t\ttitle: meta.title,\n\t\t},\n\t\tmeta: {},\n\t} as TLBookmarkAsset\n}\n\n/** @public */\nexport async function defaultHandleExternalSvgTextContent(\n\teditor: Editor,\n\t{ point, text }: { point?: VecLike; text: string }\n) {\n\tconst { sanitizeSvg } = await import('./utils/svg/sanitizeSvg')\n\ttext = sanitizeSvg(text)\n\tif (!text) return\n\n\tconst position =\n\t\tpoint ??\n\t\t(editor.inputs.getShiftKey()\n\t\t\t? editor.inputs.getCurrentPagePoint()\n\t\t\t: editor.getViewportPageBounds().center)\n\n\tconst svg = new DOMParser().parseFromString(text, 'image/svg+xml').querySelector('svg')\n\tif (!svg) {\n\t\tthrow new Error('No <svg/> element present')\n\t}\n\n\tlet width = parseFloat(svg.getAttribute('width') || '0')\n\tlet height = parseFloat(svg.getAttribute('height') || '0')\n\n\tif (!(width && height)) {\n\t\tconst doc = editor.getContainerDocument()\n\t\tdoc.body.appendChild(svg)\n\t\tconst box = svg.getBoundingClientRect()\n\t\tdoc.body.removeChild(svg)\n\n\t\twidth = box.width\n\t\theight = box.height\n\t}\n\n\tconst asset = await editor.getAssetForExternalContent({\n\t\ttype: 'file',\n\t\tfile: new File([text], 'asset.svg', { type: 'image/svg+xml' }),\n\t})\n\n\tif (!asset) throw Error('Could not create an asset')\n\n\tcreateShapesForAssets(editor, [asset], position)\n}\n\n/** @public */\nexport function defaultHandleExternalEmbedContent<T>(\n\teditor: Editor,\n\t{ point, url, embed }: { point?: VecLike; url: string; embed: T }\n) {\n\tconst position =\n\t\tpoint ??\n\t\t(editor.inputs.getShiftKey()\n\t\t\t? editor.inputs.getCurrentPagePoint()\n\t\t\t: editor.getViewportPageBounds().center)\n\n\tconst { width, height } = embed as { width: number; height: number }\n\n\tconst id = createShapeId()\n\n\tconst newPoint = maybeSnapToGrid(\n\t\tnew Vec(position.x - (width || 450) / 2, position.y - (height || 450) / 2),\n\t\teditor\n\t)\n\tconst shapePartial: TLShapePartial = {\n\t\tid,\n\t\ttype: 'embed',\n\t\tx: newPoint.x,\n\t\ty: newPoint.y,\n\t\tprops: {\n\t\t\tw: width,\n\t\t\th: height,\n\t\t\turl,\n\t\t},\n\t}\n\n\tif (editor.canCreateShape(shapePartial)) {\n\t\teditor.createShape(shapePartial).select(id)\n\t}\n}\n\n/** @public */\nexport async function defaultHandleExternalFileContent(\n\teditor: Editor,\n\t{ point, files }: { point?: VecLike; files: File[] },\n\toptions: TLDefaultExternalContentHandlerOpts\n) {\n\tconst { toasts, msg } = options\n\tif (files.length > editor.options.maxFilesAtOnce) {\n\t\ttoasts.addToast({ title: msg('assets.files.amount-too-many'), severity: 'error' })\n\t\treturn\n\t}\n\n\tconst position =\n\t\tpoint ??\n\t\t(editor.inputs.getShiftKey()\n\t\t\t? editor.inputs.getCurrentPagePoint()\n\t\t\t: editor.getViewportPageBounds().center)\n\n\tconst pagePoint = new Vec(position.x, position.y)\n\tconst assetPartials: TLAsset[] = []\n\tconst assetsToUpdate: {\n\t\tasset: TLAsset\n\t\tfile: File\n\t}[] = []\n\tfor (const file of files) {\n\t\tconst isSuccess = notifyIfFileNotAllowed(editor, file, options)\n\t\tif (!isSuccess) continue\n\n\t\tconst sanitizedFile = await maybeSanitizeSvgFile(file)\n\t\tif (!sanitizedFile) {\n\t\t\ttoasts.addToast({\n\t\t\t\ttitle: msg('assets.files.upload-failed'),\n\t\t\t\tseverity: 'error',\n\t\t\t})\n\t\t\tcontinue\n\t\t}\n\t\tconst assetInfo = await getAssetInfo(editor, sanitizedFile)\n\t\tif (!assetInfo) continue\n\t\tif (assetInfo.type === 'image') {\n\t\t\teditor.createTemporaryAssetPreview(assetInfo.id, sanitizedFile)\n\t\t}\n\t\tassetPartials.push(assetInfo)\n\t\tassetsToUpdate.push({ asset: assetInfo, file: sanitizedFile })\n\t}\n\n\tPromise.allSettled(\n\t\tassetsToUpdate.map(async (assetAndFile) => {\n\t\t\ttry {\n\t\t\t\tconst newAsset = await editor.getAssetForExternalContent({\n\t\t\t\t\ttype: 'file',\n\t\t\t\t\tfile: assetAndFile.file,\n\t\t\t\t})\n\n\t\t\t\tif (!newAsset) {\n\t\t\t\t\tthrow Error('Could not create an asset')\n\t\t\t\t}\n\n\t\t\t\t// Save the new asset under the old asset's id\n\t\t\t\teditor.updateAssets([{ ...newAsset, id: assetAndFile.asset.id }])\n\t\t\t} catch (error) {\n\t\t\t\ttoasts.addToast({\n\t\t\t\t\ttitle: msg('assets.files.upload-failed'),\n\t\t\t\t\tseverity: 'error',\n\t\t\t\t})\n\t\t\t\tconsole.error(error)\n\t\t\t\teditor.deleteAssets([assetAndFile.asset.id])\n\t\t\t\treturn\n\t\t\t}\n\t\t})\n\t)\n\n\tcreateShapesForAssets(editor, assetPartials, pagePoint)\n}\n\n/** @public */\nexport async function defaultHandleExternalTextContent(\n\teditor: Editor,\n\t{ point, text, html }: { point?: VecLike; text: string; html?: string }\n) {\n\tconst p =\n\t\tpoint ??\n\t\t(editor.inputs.getShiftKey()\n\t\t\t? editor.inputs.getCurrentPagePoint()\n\t\t\t: editor.getViewportPageBounds().center)\n\n\tconst defaultProps = editor.getShapeUtil<TLTextShape>('text').getDefaultProps()\n\n\tconst cleanedUpPlaintext = cleanupText(text)\n\tconst richTextToPaste = html\n\t\t? renderRichTextFromHTML(editor, html)\n\t\t: toRichText(cleanedUpPlaintext)\n\n\t// todo: discuss\n\t// If we have one shape with rich text selected, update the shape's text.\n\t// const onlySelectedShape = editor.getOnlySelectedShape()\n\t// if (onlySelectedShape && 'richText' in onlySelectedShape.props) {\n\t// \teditor.updateShapes([\n\t// \t\t{\n\t// \t\t\tid: onlySelectedShape.id,\n\t// \t\t\ttype: onlySelectedShape.type,\n\t// \t\t\tprops: {\n\t// \t\t\t\trichText: richTextToPaste,\n\t// \t\t\t},\n\t// \t\t},\n\t// \t])\n\n\t// \treturn\n\t// }\n\n\t// Measure the text with default values\n\tlet w: number\n\tlet h: number\n\tlet autoSize: boolean\n\tlet align = 'middle' as TLTextShapeProps['textAlign']\n\n\tconst htmlToMeasure = renderHtmlFromRichTextForMeasurement(editor, richTextToPaste)\n\tconst isMultiLine = richTextToPaste.content.length > 1\n\n\t// check whether the text contains the most common characters in RTL languages\n\tconst isRtl = isRightToLeftLanguage(cleanedUpPlaintext)\n\n\tif (isMultiLine) {\n\t\talign = isMultiLine ? (isRtl ? 'end' : 'start') : 'middle'\n\t}\n\n\tconst theme = editor.getCurrentTheme()\n\n\tconst rawSize = editor.textMeasure.measureHtml(htmlToMeasure, {\n\t\t...TEXT_PROPS,\n\t\tlineHeight: theme.lineHeight,\n\t\tfontFamily: getFontFamily(theme, defaultProps.font),\n\t\tfontSize: theme.fontSize * FONT_SIZES[defaultProps.size],\n\t\tmaxWidth: null,\n\t})\n\n\tconst minWidth = Math.min(\n\t\tisMultiLine ? editor.getViewportPageBounds().width * 0.9 : 920,\n\t\tMath.max(200, editor.getViewportPageBounds().width * 0.9)\n\t)\n\n\tif (rawSize.w > minWidth) {\n\t\tconst shrunkSize = editor.textMeasure.measureHtml(htmlToMeasure, {\n\t\t\t...TEXT_PROPS,\n\t\t\tlineHeight: theme.lineHeight,\n\t\t\tfontFamily: getFontFamily(theme, defaultProps.font),\n\t\t\tfontSize: theme.fontSize * FONT_SIZES[defaultProps.size],\n\t\t\tmaxWidth: minWidth,\n\t\t})\n\t\tw = shrunkSize.w\n\t\th = shrunkSize.h\n\t\tautoSize = false\n\t\talign = isRtl ? 'end' : 'start'\n\t} else {\n\t\t// autosize is fine\n\t\tw = Math.max(rawSize.w, 10)\n\t\th = Math.max(rawSize.h, 10)\n\t\tautoSize = true\n\t}\n\n\tif (p.y - h / 2 < editor.getViewportPageBounds().minY + 40) {\n\t\tp.y = editor.getViewportPageBounds().minY + 40 + h / 2\n\t}\n\n\tconst newPoint = maybeSnapToGrid(new Vec(p.x - w / 2, p.y - h / 2), editor)\n\tconst shapeId = createShapeId()\n\n\t// Allow this to trigger the max shapes reached alert\n\teditor.createShapes([\n\t\t{\n\t\t\tid: shapeId,\n\t\t\ttype: 'text',\n\t\t\tx: newPoint.x,\n\t\t\ty: newPoint.y,\n\t\t\tprops: {\n\t\t\t\trichText: richTextToPaste,\n\t\t\t\t// if the text has more than one line, align it to the left\n\t\t\t\ttextAlign: align,\n\t\t\t\tautoSize,\n\t\t\t\tw,\n\t\t\t},\n\t\t},\n\t])\n}\n\n/** @public */\nexport async function defaultHandleExternalUrlContent(\n\teditor: Editor,\n\t{ point, url }: { point?: VecLike; url: string },\n\t{ toasts, msg }: TLDefaultExternalContentHandlerOpts\n) {\n\t// try to paste as an embed first\n\tconst embedUtil = editor.getShapeUtil('embed') as EmbedShapeUtil | undefined\n\tconst embedInfo = embedUtil?.getEmbedDefinition(url)\n\n\tif (embedInfo && embedInfo.definition.embedOnPaste !== false) {\n\t\treturn editor.putExternalContent({\n\t\t\ttype: 'embed',\n\t\t\turl: embedInfo.url,\n\t\t\tpoint,\n\t\t\tembed: embedInfo.definition,\n\t\t})\n\t}\n\n\tconst position =\n\t\tpoint ??\n\t\t(editor.inputs.getShiftKey()\n\t\t\t? editor.inputs.getCurrentPagePoint()\n\t\t\t: editor.getViewportPageBounds().center)\n\n\t// Use the new function to create the bookmark\n\tconst result = await createBookmarkFromUrl(editor, { url, center: position })\n\n\tif (!result.ok) {\n\t\ttoasts.addToast({\n\t\t\ttitle: msg('assets.url.failed'),\n\t\t\tseverity: 'error',\n\t\t})\n\t\treturn\n\t}\n}\n\n/** @public */\nexport async function defaultHandleExternalTldrawContent(\n\teditor: Editor,\n\t{ point, content }: { point?: VecLike; content: TLContent }\n) {\n\teditor.run(() => {\n\t\tconst selectionBoundsBefore = editor.getSelectionPageBounds()\n\t\teditor.markHistoryStoppingPoint('paste')\n\n\t\t// Unlock any locked root shapes on paste\n\t\tfor (const shape of content.shapes) {\n\t\t\tif (content.rootShapeIds.includes(shape.id)) {\n\t\t\t\tshape.isLocked = false\n\t\t\t}\n\t\t}\n\n\t\teditor.putContentOntoCurrentPage(content, {\n\t\t\tpoint: point,\n\t\t\tselect: true,\n\t\t})\n\t\tconst selectedBoundsAfter = editor.getSelectionPageBounds()\n\t\tif (\n\t\t\tselectionBoundsBefore &&\n\t\t\tselectedBoundsAfter &&\n\t\t\tselectionBoundsBefore?.collides(selectedBoundsAfter)\n\t\t) {\n\t\t\t// Creates a 'puff' to show content has been pasted\n\t\t\teditor.updateInstanceState({ isChangingStyle: true })\n\t\t\teditor.timers.setTimeout(() => {\n\t\t\t\teditor.updateInstanceState({ isChangingStyle: false })\n\t\t\t}, 150)\n\t\t}\n\t})\n}\n\n/** @public */\nexport async function defaultHandleExternalExcalidrawContent(\n\teditor: Editor,\n\t{ point, content }: { point?: VecLike; content: any }\n) {\n\teditor.run(() => {\n\t\tputExcalidrawContent(editor, content, point)\n\t})\n}\n\n/**\n * A helper function for an external content handler. It creates bookmarks,\n * images or video shapes corresponding to the type of assets provided.\n *\n * @param editor - The editor instance\n *\n * @param assets - An array of asset Ids\n *\n * @param position - the position at which to create the shapes\n *\n * @public\n */\nexport async function createShapesForAssets(\n\teditor: Editor,\n\tassets: TLAsset[],\n\tposition: VecLike\n): Promise<TLShapeId[]> {\n\tif (!assets.length) return []\n\n\tconst currentPoint = Vec.From(position)\n\tconst partials: TLShapePartial[] = []\n\n\tfor (let i = 0; i < assets.length; i++) {\n\t\tconst asset = assets[i]\n\t\tconst shapeUtil = editor.getShapeUtilForAssetType(asset.type)\n\t\tconst partial = shapeUtil?.createShapeForAsset?.(asset, currentPoint) ?? null\n\t\tif (partial) {\n\t\t\tpartials.push(partial)\n\t\t\tif ('w' in asset.props && typeof asset.props.w === 'number') {\n\t\t\t\tcurrentPoint.x += asset.props.w\n\t\t\t}\n\t\t}\n\t}\n\n\teditor.run(() => {\n\t\t// Create any assets\n\t\tconst assetsToCreate = assets.filter((asset) => !editor.getAsset(asset.id))\n\n\t\teditor.store.atomic(() => {\n\t\t\tif (editor.canCreateShapes(partials)) {\n\t\t\t\tif (assetsToCreate.length) {\n\t\t\t\t\teditor.createAssets(assetsToCreate)\n\t\t\t\t}\n\n\t\t\t\t// Create the shapes\n\t\t\t\teditor.createShapes(partials).select(...partials.map((p) => p.id))\n\n\t\t\t\t// Re-position shapes so that the center of the group is at the provided point\n\t\t\t\tcenterSelectionAroundPoint(editor, position)\n\t\t\t}\n\t\t})\n\t})\n\n\treturn partials.map((p) => p.id)\n}\n\n/**\n * Repositions selected shapes do that the center of the group is\n * at the provided position\n *\n * @param editor - The editor instance\n *\n * @param position - the point to center the shapes around\n *\n * @public\n */\nexport function centerSelectionAroundPoint(editor: Editor, position: VecLike) {\n\t// Re-position shapes so that the center of the group is at the provided point\n\tconst viewportPageBounds = editor.getViewportPageBounds()\n\tlet selectionPageBounds = editor.getSelectionPageBounds()\n\n\tif (selectionPageBounds) {\n\t\tconst offset = selectionPageBounds!.center.sub(position)\n\n\t\teditor.updateShapes(\n\t\t\teditor.getSelectedShapes().map((shape) => {\n\t\t\t\tconst localRotation = editor.getShapeParentTransform(shape).decompose().rotation\n\t\t\t\tconst localDelta = Vec.Rot(offset, -localRotation)\n\t\t\t\treturn {\n\t\t\t\t\tid: shape.id,\n\t\t\t\t\ttype: shape.type,\n\t\t\t\t\tx: shape.x! - localDelta.x,\n\t\t\t\t\ty: shape.y! - localDelta.y,\n\t\t\t\t}\n\t\t\t})\n\t\t)\n\t}\n\tselectionPageBounds = editor.getSelectionPageBounds()\n\t// align selection with the grid if necessary\n\tif (selectionPageBounds && editor.getInstanceState().isGridMode) {\n\t\tconst gridSize = editor.getDocumentSettings().gridSize\n\t\tconst topLeft = new Vec(selectionPageBounds.minX, selectionPageBounds.minY)\n\t\tconst gridSnappedPoint = topLeft.clone().snapToGrid(gridSize)\n\t\tconst delta = Vec.Sub(topLeft, gridSnappedPoint)\n\t\teditor.updateShapes(\n\t\t\teditor.getSelectedShapes().map((shape) => {\n\t\t\t\tconst newPoint = { x: shape.x! - delta.x, y: shape.y! - delta.y }\n\t\t\t\treturn {\n\t\t\t\t\tid: shape.id,\n\t\t\t\t\ttype: shape.type,\n\t\t\t\t\tx: newPoint.x,\n\t\t\t\t\ty: newPoint.y,\n\t\t\t\t}\n\t\t\t})\n\t\t)\n\t}\n\t// Zoom out to fit the shapes, if necessary\n\tselectionPageBounds = editor.getSelectionPageBounds()\n\tif (selectionPageBounds && !viewportPageBounds.contains(selectionPageBounds)) {\n\t\teditor.zoomToSelection({ animation: { duration: editor.options.animationMediumMs } })\n\t}\n}\n\n/** @public */\nexport function createEmptyBookmarkShape(\n\teditor: Editor,\n\turl: string,\n\tposition: VecLike\n): TLBookmarkShape {\n\tconst partial: TLShapePartial = {\n\t\tid: createShapeId(),\n\t\ttype: 'bookmark',\n\t\tx: position.x - 150,\n\t\ty: position.y - 160,\n\t\topacity: 1,\n\t\tprops: {\n\t\t\tassetId: null,\n\t\t\turl,\n\t\t},\n\t}\n\n\teditor.run(() => {\n\t\t// Allow this to trigger the max shapes reached alert\n\t\teditor.createShape(partial)\n\t\tif (!editor.getShape(partial.id)) return\n\t\teditor.select(partial.id)\n\t\tcenterSelectionAroundPoint(editor, position)\n\t})\n\n\treturn editor.getShape(partial.id) as TLBookmarkShape\n}\n\nasync function maybeSanitizeSvgFile(file: File): Promise<File | null> {\n\tif (file.type !== 'image/svg+xml') return file\n\ttry {\n\t\tconst text = await file.text()\n\t\tconst { sanitizeSvg } = await import('./utils/svg/sanitizeSvg')\n\t\tconst sanitized = sanitizeSvg(text)\n\t\tif (!sanitized) return null\n\t\treturn new File([sanitized], file.name, { type: file.type, lastModified: file.lastModified })\n\t} catch {\n\t\treturn null\n\t}\n}\n\n/**\n * Checks if a file is allowed to be uploaded. If it is not, it will show a toast explaining why to the user.\n *\n * @param editor - The editor instance\n * @param file - The file to check\n * @param options - The options for the external content handler\n * @returns True if the file is allowed, false otherwise\n * @public\n */\nexport function notifyIfFileNotAllowed(\n\teditor: Editor,\n\tfile: File,\n\toptions: TLDefaultExternalContentHandlerOpts\n) {\n\tconst {\n\t\tmaxAssetSize = DEFAULT_MAX_ASSET_SIZE,\n\t\tacceptedImageMimeTypes,\n\t\tacceptedVideoMimeTypes,\n\t\ttoasts,\n\t\tmsg,\n\t} = options\n\n\t// Allow if any registered asset util accepts the MIME type, or if it matches\n\t// an explicit allow-list. The asset-util branch lets custom AssetUtils\n\t// (e.g. for PDFs) extend the default media handling \u2014 without it, files\n\t// registered via `assetUtils` would be rejected because <Tldraw> forwards\n\t// `DEFAULT_SUPPORTED_IMAGE_TYPES` / `DEFAULT_SUPPORT_VIDEO_TYPES` here, and\n\t// custom MIME types aren't in those lists. The explicit-list branch supports\n\t// callers that pass these props directly to restrict allowed types.\n\tconst isFileTypeAllowed =\n\t\t!!editor.getAssetUtilForMimeType(file.type) ||\n\t\t(acceptedImageMimeTypes?.includes(file.type) ?? false) ||\n\t\t(acceptedVideoMimeTypes?.includes(file.type) ?? false)\n\tif (!isFileTypeAllowed) {\n\t\ttoasts.addToast({\n\t\t\ttitle: msg('assets.files.type-not-allowed'),\n\t\t\tseverity: 'error',\n\t\t})\n\t\treturn false\n\t}\n\n\tif (file.size > maxAssetSize) {\n\t\tconst formatBytes = (bytes: number): string => {\n\t\t\tif (bytes === 0) return '0 bytes'\n\n\t\t\tconst units = ['bytes', 'KB', 'MB', 'GB', 'TB', 'PB']\n\t\t\tconst base = 1024\n\t\t\tconst unitIndex = Math.floor(Math.log(bytes) / Math.log(base))\n\n\t\t\tconst value = bytes / Math.pow(base, unitIndex)\n\t\t\tconst formatted = value % 1 === 0 ? value.toString() : value.toFixed(1)\n\n\t\t\treturn `${formatted} ${units[unitIndex]}`\n\t\t}\n\n\t\ttoasts.addToast({\n\t\t\ttitle: msg('assets.files.size-too-big'),\n\t\t\tdescription: msg('assets.files.maximum-size').replace('{size}', formatBytes(maxAssetSize)),\n\t\t\tseverity: 'error',\n\t\t})\n\t\treturn false\n\t}\n\n\t// Use mime type instead of file ext, this is because\n\t// window.navigator.clipboard does not preserve file names\n\t// of copied files.\n\tif (!file.type) {\n\t\ttoasts.addToast({\n\t\t\ttitle: msg('assets.files.upload-failed'),\n\t\t\tseverity: 'error',\n\t\t})\n\t\tconsole.error('No mime type')\n\t\treturn false\n\t}\n\n\treturn true\n}\n\n/** @public */\nexport async function getAssetInfo(editor: Editor, file: File, assetId?: TLAssetId) {\n\tif (!assetId) {\n\t\tconst hash = getHashForBuffer(await file.arrayBuffer())\n\t\tassetId = AssetRecordType.createId(hash)\n\t}\n\n\tconst assetUtil = editor.getAssetUtilForMimeType(file.type)\n\tif (!assetUtil) return null\n\n\treturn await assetUtil.getAssetFromFile(file, assetId)\n}\n"],
|
|
5
|
-
"mappings": "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",
|
|
4
|
+
"sourcesContent": ["import {\n\tAssetRecordType,\n\tEditor,\n\tTLAsset,\n\tTLAssetId,\n\tTLBookmarkAsset,\n\tTLBookmarkShape,\n\tTLContent,\n\tTLFileExternalAsset,\n\tTLFileReplaceExternalContent,\n\tTLImageAsset,\n\tTLImageShape,\n\tTLShapeId,\n\tTLShapePartial,\n\tTLTextShape,\n\tTLTextShapeProps,\n\tTLUrlExternalAsset,\n\tTLVideoAsset,\n\tVec,\n\tVecLike,\n\tassert,\n\tcreateShapeId,\n\tfetch,\n\tgetHashForBuffer,\n\tgetHashForString,\n\tmaybeSnapToGrid,\n\ttoRichText,\n} from '@tldraw/editor'\nimport { EmbedDefinition } from './defaultEmbedDefinitions'\nimport { createBookmarkFromUrl } from './shapes/bookmark/bookmarks'\nimport { EmbedShapeUtil } from './shapes/embed/EmbedShapeUtil'\nimport { getCroppedImageDataForReplacedImage } from './shapes/shared/crop'\nimport { FONT_SIZES, TEXT_PROPS, getFontFamily } from './shapes/shared/default-shape-constants'\nimport { TLUiToastsContextType } from './ui/context/toasts'\nimport { useTranslation } from './ui/hooks/useTranslation/useTranslation'\nimport { putExcalidrawContent } from './utils/excalidraw/putExcalidrawContent'\nimport { renderHtmlFromRichTextForMeasurement, renderRichTextFromHTML } from './utils/text/richText'\nimport { cleanupText, isRightToLeftLanguage } from './utils/text/text'\n\n/**\n * 5000px\n * @public\n */\nexport const DEFAULT_MAX_IMAGE_DIMENSION = 5000\n/**\n * 10mb\n * @public\n */\nexport const DEFAULT_MAX_ASSET_SIZE = 10 * 1024 * 1024\n\n/** @public */\nexport interface TLExternalContentProps {\n\t/**\n\t * The maximum dimension (width or height) of an image. Images larger than this will be rescaled\n\t * to fit. Defaults to infinity.\n\t */\n\tmaxImageDimension?: number\n\t/**\n\t * The maximum size (in bytes) of an asset. Assets larger than this will be rejected. Defaults\n\t * to 10mb (10 * 1024 * 1024).\n\t */\n\tmaxAssetSize?: number\n\t/**\n\t * The mime types of images that are allowed to be handled. When passed to\n\t * the `Tldraw` component, this also reconfigures the default `ImageAssetUtil`\n\t * to only accept files matching these types. If you only want to accept a\n\t * subset of image types and want to additionally block videos, pass\n\t * `acceptedVideoMimeTypes={[]}`. A file is accepted if its MIME type is in\n\t * this list, in `acceptedVideoMimeTypes`, or if any registered asset util\n\t * accepts it.\n\t */\n\tacceptedImageMimeTypes?: readonly string[]\n\t/**\n\t * The mime types of videos that are allowed to be handled. When passed to\n\t * the `Tldraw` component, this also reconfigures the default `VideoAssetUtil`\n\t * to only accept files matching these types. A file is accepted if its MIME\n\t * type is in this list, in `acceptedImageMimeTypes`, or if any registered\n\t * asset util accepts it.\n\t */\n\tacceptedVideoMimeTypes?: readonly string[]\n}\n\n/** @public */\nexport interface TLDefaultExternalContentHandlerOpts extends TLExternalContentProps {\n\ttoasts: TLUiToastsContextType\n\tmsg: ReturnType<typeof useTranslation>\n}\n\n/** @public */\nexport function registerDefaultExternalContentHandlers(\n\teditor: Editor,\n\toptions: TLDefaultExternalContentHandlerOpts\n) {\n\t// files -> asset\n\teditor.registerExternalAssetHandler('file', async (externalAsset) => {\n\t\treturn defaultHandleExternalFileAsset(editor, externalAsset, options)\n\t})\n\n\t// urls -> bookmark asset\n\teditor.registerExternalAssetHandler('url', async (externalAsset) => {\n\t\treturn defaultHandleExternalUrlAsset(editor, externalAsset, options)\n\t})\n\n\t// svg text\n\teditor.registerExternalContentHandler('svg-text', async (externalContent) => {\n\t\treturn defaultHandleExternalSvgTextContent(editor, externalContent)\n\t})\n\n\t// embeds\n\teditor.registerExternalContentHandler<'embed', EmbedDefinition>('embed', (externalContent) => {\n\t\treturn defaultHandleExternalEmbedContent(editor, externalContent)\n\t})\n\n\t// files\n\teditor.registerExternalContentHandler('files', async (externalContent) => {\n\t\treturn defaultHandleExternalFileContent(editor, externalContent, options)\n\t})\n\n\t// file-replace -> asset\n\teditor.registerExternalContentHandler('file-replace', async (externalContent) => {\n\t\treturn defaultHandleExternalFileReplaceContent(editor, externalContent, options)\n\t})\n\n\t// text\n\teditor.registerExternalContentHandler('text', async (externalContent) => {\n\t\treturn defaultHandleExternalTextContent(editor, externalContent)\n\t})\n\n\t// url\n\teditor.registerExternalContentHandler('url', async (externalContent) => {\n\t\treturn defaultHandleExternalUrlContent(editor, externalContent, options)\n\t})\n\n\t// tldraw\n\teditor.registerExternalContentHandler('tldraw', async (externalContent) => {\n\t\treturn defaultHandleExternalTldrawContent(editor, externalContent)\n\t})\n\n\t// excalidraw\n\teditor.registerExternalContentHandler('excalidraw', async (externalContent) => {\n\t\treturn defaultHandleExternalExcalidrawContent(editor, externalContent)\n\t})\n}\n\n/** @public */\nexport async function defaultHandleExternalFileAsset(\n\teditor: Editor,\n\t{ file, assetId }: TLFileExternalAsset,\n\toptions: TLDefaultExternalContentHandlerOpts\n) {\n\tconst isSuccess = notifyIfFileNotAllowed(editor, file, options)\n\tif (!isSuccess) assert(false, 'File checks failed')\n\n\tconst sanitizedFile = await maybeSanitizeSvgFile(file)\n\tif (!sanitizedFile) assert(false, 'SVG file contained no safe content')\n\tconst assetInfo = await getAssetInfo(editor, sanitizedFile, assetId)\n\tif (!assetInfo) assert(false, `No asset util found for MIME type \"${file.type}\"`)\n\tconst result = await editor.uploadAsset(assetInfo, sanitizedFile)\n\tassetInfo.props.src = result.src\n\tif (result.meta) assetInfo.meta = { ...assetInfo.meta, ...result.meta }\n\n\treturn AssetRecordType.create(assetInfo)\n}\n\n/** @public */\nexport async function defaultHandleExternalFileReplaceContent(\n\teditor: Editor,\n\t{ file, shapeId }: TLFileReplaceExternalContent,\n\toptions: TLDefaultExternalContentHandlerOpts\n) {\n\tconst isSuccess = notifyIfFileNotAllowed(editor, file, options)\n\tif (!isSuccess) assert(false, 'File checks failed')\n\n\tconst sanitizedFile = await maybeSanitizeSvgFile(file)\n\tif (!sanitizedFile) return\n\tconst shape = editor.getShape(shapeId)\n\tif (!shape) assert(false, 'Shape not found')\n\n\tconst hash = getHashForBuffer(await sanitizedFile.arrayBuffer())\n\tconst assetId = AssetRecordType.createId(hash)\n\teditor.createTemporaryAssetPreview(assetId, sanitizedFile)\n\tconst assetInfoPartial = (await getAssetInfo(editor, sanitizedFile, assetId)) as\n\t\t| TLImageAsset\n\t\t| TLVideoAsset\n\t\t| null\n\tif (!assetInfoPartial) return\n\teditor.createAssets([assetInfoPartial])\n\n\t// And update the shape\n\tif (shape.type === 'image') {\n\t\tconst imageShape = shape as TLImageShape\n\t\tconst currentCrop = imageShape.props.crop\n\n\t\t// Calculate new dimensions that preserve the current visual size of the cropped area\n\t\tlet newWidth = assetInfoPartial.props.w\n\t\tlet newHeight = assetInfoPartial.props.h\n\t\tlet newX = imageShape.x\n\t\tlet newY = imageShape.y\n\t\tlet finalCrop = currentCrop\n\n\t\tif (currentCrop) {\n\t\t\t// Use the dedicated function to calculate the new crop and dimensions\n\t\t\tconst result = getCroppedImageDataForReplacedImage(\n\t\t\t\timageShape,\n\t\t\t\tassetInfoPartial.props.w,\n\t\t\t\tassetInfoPartial.props.h\n\t\t\t)\n\n\t\t\tfinalCrop = result.crop\n\t\t\tnewWidth = result.w\n\t\t\tnewHeight = result.h\n\t\t\tnewX = result.x\n\t\t\tnewY = result.y\n\t\t}\n\n\t\teditor.updateShapes([\n\t\t\t{\n\t\t\t\tid: imageShape.id,\n\t\t\t\ttype: imageShape.type,\n\t\t\t\tprops: {\n\t\t\t\t\tassetId: assetId,\n\t\t\t\t\tcrop: finalCrop,\n\t\t\t\t\tw: newWidth,\n\t\t\t\t\th: newHeight,\n\t\t\t\t},\n\t\t\t\tx: newX,\n\t\t\t\ty: newY,\n\t\t\t},\n\t\t])\n\t} else if (shape.type === 'video') {\n\t\teditor.updateShapes([\n\t\t\t{\n\t\t\t\tid: shape.id,\n\t\t\t\ttype: shape.type,\n\t\t\t\tprops: {\n\t\t\t\t\tassetId: assetId,\n\t\t\t\t\tw: assetInfoPartial.props.w,\n\t\t\t\t\th: assetInfoPartial.props.h,\n\t\t\t\t},\n\t\t\t},\n\t\t])\n\t}\n\n\tconst asset = (await editor.getAssetForExternalContent({\n\t\ttype: 'file',\n\t\tfile: sanitizedFile,\n\t\tassetId,\n\t})) as TLAsset\n\n\teditor.updateAssets([{ ...asset, id: assetId }])\n\n\treturn asset\n}\n\n/** @public */\nexport async function defaultHandleExternalUrlAsset(\n\teditor: Editor,\n\t{ url }: TLUrlExternalAsset,\n\t{ toasts, msg }: TLDefaultExternalContentHandlerOpts\n): Promise<TLBookmarkAsset> {\n\tlet meta: { image: string; favicon: string; title: string; description: string }\n\n\ttry {\n\t\tconst resp = await fetch(url, {\n\t\t\tmethod: 'GET',\n\t\t\tmode: 'no-cors',\n\t\t})\n\t\tconst html = await resp.text()\n\t\tconst doc = new DOMParser().parseFromString(html, 'text/html')\n\t\tmeta = {\n\t\t\timage: doc.head.querySelector('meta[property=\"og:image\"]')?.getAttribute('content') ?? '',\n\t\t\tfavicon:\n\t\t\t\tdoc.head.querySelector('link[rel=\"apple-touch-icon\"]')?.getAttribute('href') ??\n\t\t\t\tdoc.head.querySelector('link[rel=\"icon\"]')?.getAttribute('href') ??\n\t\t\t\t'',\n\t\t\ttitle: doc.head.querySelector('meta[property=\"og:title\"]')?.getAttribute('content') ?? url,\n\t\t\tdescription:\n\t\t\t\tdoc.head.querySelector('meta[property=\"og:description\"]')?.getAttribute('content') ?? '',\n\t\t}\n\t\tif (!meta.image.startsWith('http')) {\n\t\t\tmeta.image = new URL(meta.image, url).href\n\t\t}\n\t\tif (!meta.favicon.startsWith('http')) {\n\t\t\tmeta.favicon = new URL(meta.favicon, url).href\n\t\t}\n\t} catch (error) {\n\t\tconsole.error(error)\n\t\ttoasts.addToast({\n\t\t\ttitle: msg('assets.url.failed'),\n\t\t\tseverity: 'error',\n\t\t})\n\t\tmeta = { image: '', favicon: '', title: '', description: '' }\n\t}\n\n\t// Create the bookmark asset from the meta\n\treturn {\n\t\tid: AssetRecordType.createId(getHashForString(url)),\n\t\ttypeName: 'asset',\n\t\ttype: 'bookmark',\n\t\tprops: {\n\t\t\tsrc: url,\n\t\t\tdescription: meta.description,\n\t\t\timage: meta.image,\n\t\t\tfavicon: meta.favicon,\n\t\t\ttitle: meta.title,\n\t\t},\n\t\tmeta: {},\n\t} as TLBookmarkAsset\n}\n\n/** @public */\nexport async function defaultHandleExternalSvgTextContent(\n\teditor: Editor,\n\t{ point, text }: { point?: VecLike; text: string }\n) {\n\tconst { sanitizeSvg } = await import('./utils/svg/sanitizeSvg')\n\ttext = sanitizeSvg(text)\n\tif (!text) return\n\n\tconst position =\n\t\tpoint ??\n\t\t(editor.inputs.getShiftKey()\n\t\t\t? editor.inputs.getCurrentPagePoint()\n\t\t\t: editor.getViewportPageBounds().center)\n\n\tconst svg = new DOMParser().parseFromString(text, 'image/svg+xml').querySelector('svg')\n\tif (!svg) {\n\t\tthrow new Error('No <svg/> element present')\n\t}\n\n\tlet width = parseFloat(svg.getAttribute('width') || '0')\n\tlet height = parseFloat(svg.getAttribute('height') || '0')\n\n\tif (!(width && height)) {\n\t\tconst doc = editor.getContainerDocument()\n\t\tdoc.body.appendChild(svg)\n\t\tconst box = svg.getBoundingClientRect()\n\t\tdoc.body.removeChild(svg)\n\n\t\twidth = box.width\n\t\theight = box.height\n\t}\n\n\tconst asset = await editor.getAssetForExternalContent({\n\t\ttype: 'file',\n\t\tfile: new File([text], 'asset.svg', { type: 'image/svg+xml' }),\n\t})\n\n\tif (!asset) throw Error('Could not create an asset')\n\n\tcreateShapesForAssets(editor, [asset], position)\n}\n\n/** @public */\nexport function defaultHandleExternalEmbedContent<T>(\n\teditor: Editor,\n\t{ point, url, embed }: { point?: VecLike; url: string; embed: T }\n) {\n\tconst position =\n\t\tpoint ??\n\t\t(editor.inputs.getShiftKey()\n\t\t\t? editor.inputs.getCurrentPagePoint()\n\t\t\t: editor.getViewportPageBounds().center)\n\n\tconst { width, height } = embed as { width: number; height: number }\n\n\tconst id = createShapeId()\n\n\tconst newPoint = maybeSnapToGrid(\n\t\tnew Vec(position.x - (width || 450) / 2, position.y - (height || 450) / 2),\n\t\teditor\n\t)\n\tconst shapePartial: TLShapePartial = {\n\t\tid,\n\t\ttype: 'embed',\n\t\tx: newPoint.x,\n\t\ty: newPoint.y,\n\t\tprops: {\n\t\t\tw: width,\n\t\t\th: height,\n\t\t\turl,\n\t\t},\n\t}\n\n\tif (editor.canCreateShape(shapePartial)) {\n\t\teditor.createShape(shapePartial).select(id)\n\t}\n}\n\n/** @public */\nexport async function defaultHandleExternalFileContent(\n\teditor: Editor,\n\t{ point, files }: { point?: VecLike; files: File[] },\n\toptions: TLDefaultExternalContentHandlerOpts\n) {\n\tconst { toasts, msg } = options\n\tif (files.length > editor.options.maxFilesAtOnce) {\n\t\ttoasts.addToast({ title: msg('assets.files.amount-too-many'), severity: 'error' })\n\t\treturn\n\t}\n\n\tconst position =\n\t\tpoint ??\n\t\t(editor.inputs.getShiftKey()\n\t\t\t? editor.inputs.getCurrentPagePoint()\n\t\t\t: editor.getViewportPageBounds().center)\n\n\tconst pagePoint = new Vec(position.x, position.y)\n\tconst assetPartials: TLAsset[] = []\n\tconst assetsToUpdate: {\n\t\tasset: TLAsset\n\t\tfile: File\n\t}[] = []\n\tfor (const file of files) {\n\t\tconst isSuccess = notifyIfFileNotAllowed(editor, file, options)\n\t\tif (!isSuccess) continue\n\n\t\tconst sanitizedFile = await maybeSanitizeSvgFile(file)\n\t\tif (!sanitizedFile) {\n\t\t\ttoasts.addToast({\n\t\t\t\ttitle: msg('assets.files.upload-failed'),\n\t\t\t\tseverity: 'error',\n\t\t\t})\n\t\t\tcontinue\n\t\t}\n\t\tconst assetInfo = await getAssetInfo(editor, sanitizedFile)\n\t\tif (!assetInfo) continue\n\t\tif (assetInfo.type === 'image') {\n\t\t\teditor.createTemporaryAssetPreview(assetInfo.id, sanitizedFile)\n\t\t}\n\t\tassetPartials.push(assetInfo)\n\t\tassetsToUpdate.push({ asset: assetInfo, file: sanitizedFile })\n\t}\n\n\tPromise.allSettled(\n\t\tassetsToUpdate.map(async (assetAndFile) => {\n\t\t\ttry {\n\t\t\t\tconst newAsset = await editor.getAssetForExternalContent({\n\t\t\t\t\ttype: 'file',\n\t\t\t\t\tfile: assetAndFile.file,\n\t\t\t\t})\n\n\t\t\t\tif (!newAsset) {\n\t\t\t\t\tthrow Error('Could not create an asset')\n\t\t\t\t}\n\n\t\t\t\t// Save the new asset under the old asset's id\n\t\t\t\teditor.updateAssets([{ ...newAsset, id: assetAndFile.asset.id }])\n\t\t\t} catch (error) {\n\t\t\t\ttoasts.addToast({\n\t\t\t\t\ttitle: msg('assets.files.upload-failed'),\n\t\t\t\t\tseverity: 'error',\n\t\t\t\t})\n\t\t\t\tconsole.error(error)\n\t\t\t\teditor.deleteAssets([assetAndFile.asset.id])\n\t\t\t\treturn\n\t\t\t}\n\t\t})\n\t)\n\n\tcreateShapesForAssets(editor, assetPartials, pagePoint)\n}\n\n/** @public */\nexport async function defaultHandleExternalTextContent(\n\teditor: Editor,\n\t{ point, text, html }: { point?: VecLike; text: string; html?: string }\n) {\n\tconst p =\n\t\tpoint ??\n\t\t(editor.inputs.getShiftKey()\n\t\t\t? editor.inputs.getCurrentPagePoint()\n\t\t\t: editor.getViewportPageBounds().center)\n\n\tconst defaultProps = editor.getShapeUtil<TLTextShape>('text').getDefaultProps()\n\n\tconst cleanedUpPlaintext = cleanupText(text)\n\tconst richTextToPaste = html\n\t\t? renderRichTextFromHTML(editor, html)\n\t\t: toRichText(cleanedUpPlaintext)\n\n\t// todo: discuss\n\t// If we have one shape with rich text selected, update the shape's text.\n\t// const onlySelectedShape = editor.getOnlySelectedShape()\n\t// if (onlySelectedShape && 'richText' in onlySelectedShape.props) {\n\t// \teditor.updateShapes([\n\t// \t\t{\n\t// \t\t\tid: onlySelectedShape.id,\n\t// \t\t\ttype: onlySelectedShape.type,\n\t// \t\t\tprops: {\n\t// \t\t\t\trichText: richTextToPaste,\n\t// \t\t\t},\n\t// \t\t},\n\t// \t])\n\n\t// \treturn\n\t// }\n\n\t// Measure the text with default values\n\tlet w: number\n\tlet h: number\n\tlet autoSize: boolean\n\tlet align = 'middle' as TLTextShapeProps['textAlign']\n\n\tconst htmlToMeasure = renderHtmlFromRichTextForMeasurement(editor, richTextToPaste)\n\tconst isMultiLine = richTextToPaste.content.length > 1\n\n\t// check whether the text contains the most common characters in RTL languages\n\tconst isRtl = isRightToLeftLanguage(cleanedUpPlaintext)\n\n\tif (isMultiLine) {\n\t\talign = isMultiLine ? (isRtl ? 'end' : 'start') : 'middle'\n\t}\n\n\tconst theme = editor.getCurrentTheme()\n\n\tconst rawSize = editor.textMeasure.measureHtml(htmlToMeasure, {\n\t\t...TEXT_PROPS,\n\t\tlineHeight: theme.lineHeight,\n\t\tfontFamily: getFontFamily(theme, defaultProps.font),\n\t\tfontSize: theme.fontSize * FONT_SIZES[defaultProps.size],\n\t\tmaxWidth: null,\n\t})\n\n\tconst minWidth = Math.min(\n\t\tisMultiLine ? editor.getViewportPageBounds().width * 0.9 : 920,\n\t\tMath.max(200, editor.getViewportPageBounds().width * 0.9)\n\t)\n\n\tif (rawSize.w > minWidth) {\n\t\tconst shrunkSize = editor.textMeasure.measureHtml(htmlToMeasure, {\n\t\t\t...TEXT_PROPS,\n\t\t\tlineHeight: theme.lineHeight,\n\t\t\tfontFamily: getFontFamily(theme, defaultProps.font),\n\t\t\tfontSize: theme.fontSize * FONT_SIZES[defaultProps.size],\n\t\t\tmaxWidth: minWidth,\n\t\t})\n\t\tw = shrunkSize.w\n\t\th = shrunkSize.h\n\t\tautoSize = false\n\t\talign = isRtl ? 'end' : 'start'\n\t} else {\n\t\t// autosize is fine\n\t\tw = Math.max(rawSize.w, 10)\n\t\th = Math.max(rawSize.h, 10)\n\t\tautoSize = true\n\t}\n\n\tif (p.y - h / 2 < editor.getViewportPageBounds().minY + 40) {\n\t\tp.y = editor.getViewportPageBounds().minY + 40 + h / 2\n\t}\n\n\tconst newPoint = maybeSnapToGrid(new Vec(p.x - w / 2, p.y - h / 2), editor)\n\tconst shapeId = createShapeId()\n\n\t// Allow this to trigger the max shapes reached alert\n\teditor.createShapes([\n\t\t{\n\t\t\tid: shapeId,\n\t\t\ttype: 'text',\n\t\t\tx: newPoint.x,\n\t\t\ty: newPoint.y,\n\t\t\tprops: {\n\t\t\t\trichText: richTextToPaste,\n\t\t\t\t// if the text has more than one line, align it to the left\n\t\t\t\ttextAlign: align,\n\t\t\t\tautoSize,\n\t\t\t\tw,\n\t\t\t},\n\t\t},\n\t])\n}\n\n/** @public */\nexport async function defaultHandleExternalUrlContent(\n\teditor: Editor,\n\t{ point, url }: { point?: VecLike; url: string },\n\t{ toasts, msg }: TLDefaultExternalContentHandlerOpts\n) {\n\t// try to paste as an embed first\n\tconst embedUtil = editor.getShapeUtil('embed') as EmbedShapeUtil | undefined\n\tconst embedInfo = embedUtil?.getEmbedDefinition(url)\n\n\tif (embedInfo && embedInfo.definition.embedOnPaste !== false) {\n\t\treturn editor.putExternalContent({\n\t\t\ttype: 'embed',\n\t\t\turl: embedInfo.url,\n\t\t\tpoint,\n\t\t\tembed: embedInfo.definition,\n\t\t})\n\t}\n\n\tconst position =\n\t\tpoint ??\n\t\t(editor.inputs.getShiftKey()\n\t\t\t? editor.inputs.getCurrentPagePoint()\n\t\t\t: editor.getViewportPageBounds().center)\n\n\t// Use the new function to create the bookmark\n\tconst result = await createBookmarkFromUrl(editor, { url, center: position })\n\n\tif (!result.ok) {\n\t\ttoasts.addToast({\n\t\t\ttitle: msg('assets.url.failed'),\n\t\t\tseverity: 'error',\n\t\t})\n\t\treturn\n\t}\n}\n\n/** @public */\nexport async function defaultHandleExternalTldrawContent(\n\teditor: Editor,\n\t{ point, content }: { point?: VecLike; content: TLContent }\n) {\n\teditor.run(() => {\n\t\tconst selectionBoundsBefore = editor.getSelectionPageBounds()\n\t\teditor.markHistoryStoppingPoint('paste')\n\n\t\t// Unlock any locked root shapes on paste\n\t\tfor (const shape of content.shapes) {\n\t\t\tif (content.rootShapeIds.includes(shape.id)) {\n\t\t\t\tshape.isLocked = false\n\t\t\t}\n\t\t}\n\n\t\t// While the user is mid-interaction (dragging a handle, translating,\n\t\t// resizing, or rotating), selecting the pasted content would steal the\n\t\t// selection from the shape being manipulated and interrupt the\n\t\t// interaction \u2014 e.g. an arrow's in-progress binding hint disappears\n\t\t// until the drag ends. Leave the selection alone in those cases.\n\t\tconst isMidInteraction = editor.isInAny(\n\t\t\t'select.dragging_handle',\n\t\t\t'select.translating',\n\t\t\t'select.resizing',\n\t\t\t'select.rotating'\n\t\t)\n\n\t\teditor.putContentOntoCurrentPage(content, {\n\t\t\tpoint: point,\n\t\t\tselect: !isMidInteraction,\n\t\t})\n\t\tconst selectedBoundsAfter = editor.getSelectionPageBounds()\n\t\tif (\n\t\t\t// When mid-interaction we don't select the pasted content, so the\n\t\t\t// selection is unchanged and the before/after bounds are identical \u2014\n\t\t\t// the overlap check would always pass. The selection flash below\n\t\t\t// signals that the newly-selected pasted content landed on the old\n\t\t\t// selection, which is meaningless when we didn't change the\n\t\t\t// selection, so skip it.\n\t\t\t!isMidInteraction &&\n\t\t\tselectionBoundsBefore &&\n\t\t\tselectedBoundsAfter &&\n\t\t\tselectionBoundsBefore?.collides(selectedBoundsAfter)\n\t\t) {\n\t\t\t// Creates a 'puff' to show content has been pasted\n\t\t\teditor.updateInstanceState({ isChangingStyle: true })\n\t\t\teditor.timers.setTimeout(() => {\n\t\t\t\teditor.updateInstanceState({ isChangingStyle: false })\n\t\t\t}, 150)\n\t\t}\n\t})\n}\n\n/** @public */\nexport async function defaultHandleExternalExcalidrawContent(\n\teditor: Editor,\n\t{ point, content }: { point?: VecLike; content: any }\n) {\n\teditor.run(() => {\n\t\tputExcalidrawContent(editor, content, point)\n\t})\n}\n\n/**\n * A helper function for an external content handler. It creates bookmarks,\n * images or video shapes corresponding to the type of assets provided.\n *\n * @param editor - The editor instance\n *\n * @param assets - An array of asset Ids\n *\n * @param position - the position at which to create the shapes\n *\n * @public\n */\nexport async function createShapesForAssets(\n\teditor: Editor,\n\tassets: TLAsset[],\n\tposition: VecLike\n): Promise<TLShapeId[]> {\n\tif (!assets.length) return []\n\n\tconst currentPoint = Vec.From(position)\n\tconst partials: TLShapePartial[] = []\n\n\tfor (let i = 0; i < assets.length; i++) {\n\t\tconst asset = assets[i]\n\t\tconst shapeUtil = editor.getShapeUtilForAssetType(asset.type)\n\t\tconst partial = shapeUtil?.createShapeForAsset?.(asset, currentPoint) ?? null\n\t\tif (partial) {\n\t\t\tpartials.push(partial)\n\t\t\tif ('w' in asset.props && typeof asset.props.w === 'number') {\n\t\t\t\tcurrentPoint.x += asset.props.w\n\t\t\t}\n\t\t}\n\t}\n\n\teditor.run(() => {\n\t\t// Create any assets\n\t\tconst assetsToCreate = assets.filter((asset) => !editor.getAsset(asset.id))\n\n\t\teditor.store.atomic(() => {\n\t\t\tif (editor.canCreateShapes(partials)) {\n\t\t\t\tif (assetsToCreate.length) {\n\t\t\t\t\teditor.createAssets(assetsToCreate)\n\t\t\t\t}\n\n\t\t\t\t// Create the shapes\n\t\t\t\teditor.createShapes(partials).select(...partials.map((p) => p.id))\n\n\t\t\t\t// Re-position shapes so that the center of the group is at the provided point\n\t\t\t\tcenterSelectionAroundPoint(editor, position)\n\t\t\t}\n\t\t})\n\t})\n\n\treturn partials.map((p) => p.id)\n}\n\n/**\n * Repositions selected shapes do that the center of the group is\n * at the provided position\n *\n * @param editor - The editor instance\n *\n * @param position - the point to center the shapes around\n *\n * @public\n */\nexport function centerSelectionAroundPoint(editor: Editor, position: VecLike) {\n\t// Re-position shapes so that the center of the group is at the provided point\n\tconst viewportPageBounds = editor.getViewportPageBounds()\n\tlet selectionPageBounds = editor.getSelectionPageBounds()\n\n\tif (selectionPageBounds) {\n\t\tconst offset = selectionPageBounds!.center.sub(position)\n\n\t\teditor.updateShapes(\n\t\t\teditor.getSelectedShapes().map((shape) => {\n\t\t\t\tconst localRotation = editor.getShapeParentTransform(shape).decompose().rotation\n\t\t\t\tconst localDelta = Vec.Rot(offset, -localRotation)\n\t\t\t\treturn {\n\t\t\t\t\tid: shape.id,\n\t\t\t\t\ttype: shape.type,\n\t\t\t\t\tx: shape.x! - localDelta.x,\n\t\t\t\t\ty: shape.y! - localDelta.y,\n\t\t\t\t}\n\t\t\t})\n\t\t)\n\t}\n\tselectionPageBounds = editor.getSelectionPageBounds()\n\t// align selection with the grid if necessary\n\tif (selectionPageBounds && editor.getInstanceState().isGridMode) {\n\t\tconst gridSize = editor.getDocumentSettings().gridSize\n\t\tconst topLeft = new Vec(selectionPageBounds.minX, selectionPageBounds.minY)\n\t\tconst gridSnappedPoint = topLeft.clone().snapToGrid(gridSize)\n\t\tconst delta = Vec.Sub(topLeft, gridSnappedPoint)\n\t\teditor.updateShapes(\n\t\t\teditor.getSelectedShapes().map((shape) => {\n\t\t\t\tconst newPoint = { x: shape.x! - delta.x, y: shape.y! - delta.y }\n\t\t\t\treturn {\n\t\t\t\t\tid: shape.id,\n\t\t\t\t\ttype: shape.type,\n\t\t\t\t\tx: newPoint.x,\n\t\t\t\t\ty: newPoint.y,\n\t\t\t\t}\n\t\t\t})\n\t\t)\n\t}\n\t// Zoom out to fit the shapes, if necessary\n\tselectionPageBounds = editor.getSelectionPageBounds()\n\tif (selectionPageBounds && !viewportPageBounds.contains(selectionPageBounds)) {\n\t\teditor.zoomToSelection({ animation: { duration: editor.options.animationMediumMs } })\n\t}\n}\n\n/** @public */\nexport function createEmptyBookmarkShape(\n\teditor: Editor,\n\turl: string,\n\tposition: VecLike\n): TLBookmarkShape {\n\tconst partial: TLShapePartial = {\n\t\tid: createShapeId(),\n\t\ttype: 'bookmark',\n\t\tx: position.x - 150,\n\t\ty: position.y - 160,\n\t\topacity: 1,\n\t\tprops: {\n\t\t\tassetId: null,\n\t\t\turl,\n\t\t},\n\t}\n\n\teditor.run(() => {\n\t\t// Allow this to trigger the max shapes reached alert\n\t\teditor.createShape(partial)\n\t\tif (!editor.getShape(partial.id)) return\n\t\teditor.select(partial.id)\n\t\tcenterSelectionAroundPoint(editor, position)\n\t})\n\n\treturn editor.getShape(partial.id) as TLBookmarkShape\n}\n\nasync function maybeSanitizeSvgFile(file: File): Promise<File | null> {\n\tif (file.type !== 'image/svg+xml') return file\n\ttry {\n\t\tconst text = await file.text()\n\t\tconst { sanitizeSvg } = await import('./utils/svg/sanitizeSvg')\n\t\tconst sanitized = sanitizeSvg(text)\n\t\tif (!sanitized) return null\n\t\treturn new File([sanitized], file.name, { type: file.type, lastModified: file.lastModified })\n\t} catch {\n\t\treturn null\n\t}\n}\n\n/**\n * Checks if a file is allowed to be uploaded. If it is not, it will show a toast explaining why to the user.\n *\n * @param editor - The editor instance\n * @param file - The file to check\n * @param options - The options for the external content handler\n * @returns True if the file is allowed, false otherwise\n * @public\n */\nexport function notifyIfFileNotAllowed(\n\teditor: Editor,\n\tfile: File,\n\toptions: TLDefaultExternalContentHandlerOpts\n) {\n\tconst {\n\t\tmaxAssetSize = DEFAULT_MAX_ASSET_SIZE,\n\t\tacceptedImageMimeTypes,\n\t\tacceptedVideoMimeTypes,\n\t\ttoasts,\n\t\tmsg,\n\t} = options\n\n\t// Allow if any registered asset util accepts the MIME type, or if it matches\n\t// an explicit allow-list. The asset-util branch lets custom AssetUtils\n\t// (e.g. for PDFs) extend the default media handling \u2014 without it, files\n\t// registered via `assetUtils` would be rejected because <Tldraw> forwards\n\t// `DEFAULT_SUPPORTED_IMAGE_TYPES` / `DEFAULT_SUPPORT_VIDEO_TYPES` here, and\n\t// custom MIME types aren't in those lists. The explicit-list branch supports\n\t// callers that pass these props directly to restrict allowed types.\n\tconst isFileTypeAllowed =\n\t\t!!editor.getAssetUtilForMimeType(file.type) ||\n\t\t(acceptedImageMimeTypes?.includes(file.type) ?? false) ||\n\t\t(acceptedVideoMimeTypes?.includes(file.type) ?? false)\n\tif (!isFileTypeAllowed) {\n\t\ttoasts.addToast({\n\t\t\ttitle: msg('assets.files.type-not-allowed'),\n\t\t\tseverity: 'error',\n\t\t})\n\t\treturn false\n\t}\n\n\tif (file.size > maxAssetSize) {\n\t\tconst formatBytes = (bytes: number): string => {\n\t\t\tif (bytes === 0) return '0 bytes'\n\n\t\t\tconst units = ['bytes', 'KB', 'MB', 'GB', 'TB', 'PB']\n\t\t\tconst base = 1024\n\t\t\tconst unitIndex = Math.floor(Math.log(bytes) / Math.log(base))\n\n\t\t\tconst value = bytes / Math.pow(base, unitIndex)\n\t\t\tconst formatted = value % 1 === 0 ? value.toString() : value.toFixed(1)\n\n\t\t\treturn `${formatted} ${units[unitIndex]}`\n\t\t}\n\n\t\ttoasts.addToast({\n\t\t\ttitle: msg('assets.files.size-too-big'),\n\t\t\tdescription: msg('assets.files.maximum-size').replace('{size}', formatBytes(maxAssetSize)),\n\t\t\tseverity: 'error',\n\t\t})\n\t\treturn false\n\t}\n\n\t// Use mime type instead of file ext, this is because\n\t// window.navigator.clipboard does not preserve file names\n\t// of copied files.\n\tif (!file.type) {\n\t\ttoasts.addToast({\n\t\t\ttitle: msg('assets.files.upload-failed'),\n\t\t\tseverity: 'error',\n\t\t})\n\t\tconsole.error('No mime type')\n\t\treturn false\n\t}\n\n\treturn true\n}\n\n/** @public */\nexport async function getAssetInfo(editor: Editor, file: File, assetId?: TLAssetId) {\n\tif (!assetId) {\n\t\tconst hash = getHashForBuffer(await file.arrayBuffer())\n\t\tassetId = AssetRecordType.createId(hash)\n\t}\n\n\tconst assetUtil = editor.getAssetUtilForMimeType(file.type)\n\tif (!assetUtil) return null\n\n\treturn await assetUtil.getAssetFromFile(file, assetId)\n}\n"],
|
|
5
|
+
"mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,oBA2BO;AAEP,uBAAsC;AAEtC,kBAAoD;AACpD,qCAAsD;AAGtD,kCAAqC;AACrC,sBAA6E;AAC7E,kBAAmD;AAM5C,MAAM,8BAA8B;AAKpC,MAAM,yBAAyB,KAAK,OAAO;AAyC3C,SAAS,uCACf,QACA,SACC;AAED,SAAO,6BAA6B,QAAQ,OAAO,kBAAkB;AACpE,WAAO,+BAA+B,QAAQ,eAAe,OAAO;AAAA,EACrE,CAAC;AAGD,SAAO,6BAA6B,OAAO,OAAO,kBAAkB;AACnE,WAAO,8BAA8B,QAAQ,eAAe,OAAO;AAAA,EACpE,CAAC;AAGD,SAAO,+BAA+B,YAAY,OAAO,oBAAoB;AAC5E,WAAO,oCAAoC,QAAQ,eAAe;AAAA,EACnE,CAAC;AAGD,SAAO,+BAAyD,SAAS,CAAC,oBAAoB;AAC7F,WAAO,kCAAkC,QAAQ,eAAe;AAAA,EACjE,CAAC;AAGD,SAAO,+BAA+B,SAAS,OAAO,oBAAoB;AACzE,WAAO,iCAAiC,QAAQ,iBAAiB,OAAO;AAAA,EACzE,CAAC;AAGD,SAAO,+BAA+B,gBAAgB,OAAO,oBAAoB;AAChF,WAAO,wCAAwC,QAAQ,iBAAiB,OAAO;AAAA,EAChF,CAAC;AAGD,SAAO,+BAA+B,QAAQ,OAAO,oBAAoB;AACxE,WAAO,iCAAiC,QAAQ,eAAe;AAAA,EAChE,CAAC;AAGD,SAAO,+BAA+B,OAAO,OAAO,oBAAoB;AACvE,WAAO,gCAAgC,QAAQ,iBAAiB,OAAO;AAAA,EACxE,CAAC;AAGD,SAAO,+BAA+B,UAAU,OAAO,oBAAoB;AAC1E,WAAO,mCAAmC,QAAQ,eAAe;AAAA,EAClE,CAAC;AAGD,SAAO,+BAA+B,cAAc,OAAO,oBAAoB;AAC9E,WAAO,uCAAuC,QAAQ,eAAe;AAAA,EACtE,CAAC;AACF;AAGA,eAAsB,+BACrB,QACA,EAAE,MAAM,QAAQ,GAChB,SACC;AACD,QAAM,YAAY,uBAAuB,QAAQ,MAAM,OAAO;AAC9D,MAAI,CAAC,UAAW,2BAAO,OAAO,oBAAoB;AAElD,QAAM,gBAAgB,MAAM,qBAAqB,IAAI;AACrD,MAAI,CAAC,cAAe,2BAAO,OAAO,oCAAoC;AACtE,QAAM,YAAY,MAAM,aAAa,QAAQ,eAAe,OAAO;AACnE,MAAI,CAAC,UAAW,2BAAO,OAAO,sCAAsC,KAAK,IAAI,GAAG;AAChF,QAAM,SAAS,MAAM,OAAO,YAAY,WAAW,aAAa;AAChE,YAAU,MAAM,MAAM,OAAO;AAC7B,MAAI,OAAO,KAAM,WAAU,OAAO,EAAE,GAAG,UAAU,MAAM,GAAG,OAAO,KAAK;AAEtE,SAAO,8BAAgB,OAAO,SAAS;AACxC;AAGA,eAAsB,wCACrB,QACA,EAAE,MAAM,QAAQ,GAChB,SACC;AACD,QAAM,YAAY,uBAAuB,QAAQ,MAAM,OAAO;AAC9D,MAAI,CAAC,UAAW,2BAAO,OAAO,oBAAoB;AAElD,QAAM,gBAAgB,MAAM,qBAAqB,IAAI;AACrD,MAAI,CAAC,cAAe;AACpB,QAAM,QAAQ,OAAO,SAAS,OAAO;AACrC,MAAI,CAAC,MAAO,2BAAO,OAAO,iBAAiB;AAE3C,QAAM,WAAO,gCAAiB,MAAM,cAAc,YAAY,CAAC;AAC/D,QAAM,UAAU,8BAAgB,SAAS,IAAI;AAC7C,SAAO,4BAA4B,SAAS,aAAa;AACzD,QAAM,mBAAoB,MAAM,aAAa,QAAQ,eAAe,OAAO;AAI3E,MAAI,CAAC,iBAAkB;AACvB,SAAO,aAAa,CAAC,gBAAgB,CAAC;AAGtC,MAAI,MAAM,SAAS,SAAS;AAC3B,UAAM,aAAa;AACnB,UAAM,cAAc,WAAW,MAAM;AAGrC,QAAI,WAAW,iBAAiB,MAAM;AACtC,QAAI,YAAY,iBAAiB,MAAM;AACvC,QAAI,OAAO,WAAW;AACtB,QAAI,OAAO,WAAW;AACtB,QAAI,YAAY;AAEhB,QAAI,aAAa;AAEhB,YAAM,aAAS;AAAA,QACd;AAAA,QACA,iBAAiB,MAAM;AAAA,QACvB,iBAAiB,MAAM;AAAA,MACxB;AAEA,kBAAY,OAAO;AACnB,iBAAW,OAAO;AAClB,kBAAY,OAAO;AACnB,aAAO,OAAO;AACd,aAAO,OAAO;AAAA,IACf;AAEA,WAAO,aAAa;AAAA,MACnB;AAAA,QACC,IAAI,WAAW;AAAA,QACf,MAAM,WAAW;AAAA,QACjB,OAAO;AAAA,UACN;AAAA,UACA,MAAM;AAAA,UACN,GAAG;AAAA,UACH,GAAG;AAAA,QACJ;AAAA,QACA,GAAG;AAAA,QACH,GAAG;AAAA,MACJ;AAAA,IACD,CAAC;AAAA,EACF,WAAW,MAAM,SAAS,SAAS;AAClC,WAAO,aAAa;AAAA,MACnB;AAAA,QACC,IAAI,MAAM;AAAA,QACV,MAAM,MAAM;AAAA,QACZ,OAAO;AAAA,UACN;AAAA,UACA,GAAG,iBAAiB,MAAM;AAAA,UAC1B,GAAG,iBAAiB,MAAM;AAAA,QAC3B;AAAA,MACD;AAAA,IACD,CAAC;AAAA,EACF;AAEA,QAAM,QAAS,MAAM,OAAO,2BAA2B;AAAA,IACtD,MAAM;AAAA,IACN,MAAM;AAAA,IACN;AAAA,EACD,CAAC;AAED,SAAO,aAAa,CAAC,EAAE,GAAG,OAAO,IAAI,QAAQ,CAAC,CAAC;AAE/C,SAAO;AACR;AAGA,eAAsB,8BACrB,QACA,EAAE,IAAI,GACN,EAAE,QAAQ,IAAI,GACa;AAC3B,MAAI;AAEJ,MAAI;AACH,UAAM,OAAO,UAAM,qBAAM,KAAK;AAAA,MAC7B,QAAQ;AAAA,MACR,MAAM;AAAA,IACP,CAAC;AACD,UAAM,OAAO,MAAM,KAAK,KAAK;AAC7B,UAAM,MAAM,IAAI,UAAU,EAAE,gBAAgB,MAAM,WAAW;AAC7D,WAAO;AAAA,MACN,OAAO,IAAI,KAAK,cAAc,2BAA2B,GAAG,aAAa,SAAS,KAAK;AAAA,MACvF,SACC,IAAI,KAAK,cAAc,8BAA8B,GAAG,aAAa,MAAM,KAC3E,IAAI,KAAK,cAAc,kBAAkB,GAAG,aAAa,MAAM,KAC/D;AAAA,MACD,OAAO,IAAI,KAAK,cAAc,2BAA2B,GAAG,aAAa,SAAS,KAAK;AAAA,MACvF,aACC,IAAI,KAAK,cAAc,iCAAiC,GAAG,aAAa,SAAS,KAAK;AAAA,IACxF;AACA,QAAI,CAAC,KAAK,MAAM,WAAW,MAAM,GAAG;AACnC,WAAK,QAAQ,IAAI,IAAI,KAAK,OAAO,GAAG,EAAE;AAAA,IACvC;AACA,QAAI,CAAC,KAAK,QAAQ,WAAW,MAAM,GAAG;AACrC,WAAK,UAAU,IAAI,IAAI,KAAK,SAAS,GAAG,EAAE;AAAA,IAC3C;AAAA,EACD,SAAS,OAAO;AACf,YAAQ,MAAM,KAAK;AACnB,WAAO,SAAS;AAAA,MACf,OAAO,IAAI,mBAAmB;AAAA,MAC9B,UAAU;AAAA,IACX,CAAC;AACD,WAAO,EAAE,OAAO,IAAI,SAAS,IAAI,OAAO,IAAI,aAAa,GAAG;AAAA,EAC7D;AAGA,SAAO;AAAA,IACN,IAAI,8BAAgB,aAAS,gCAAiB,GAAG,CAAC;AAAA,IAClD,UAAU;AAAA,IACV,MAAM;AAAA,IACN,OAAO;AAAA,MACN,KAAK;AAAA,MACL,aAAa,KAAK;AAAA,MAClB,OAAO,KAAK;AAAA,MACZ,SAAS,KAAK;AAAA,MACd,OAAO,KAAK;AAAA,IACb;AAAA,IACA,MAAM,CAAC;AAAA,EACR;AACD;AAGA,eAAsB,oCACrB,QACA,EAAE,OAAO,KAAK,GACb;AACD,QAAM,EAAE,YAAY,IAAI,MAAM,OAAO,yBAAyB;AAC9D,SAAO,YAAY,IAAI;AACvB,MAAI,CAAC,KAAM;AAEX,QAAM,WACL,UACC,OAAO,OAAO,YAAY,IACxB,OAAO,OAAO,oBAAoB,IAClC,OAAO,sBAAsB,EAAE;AAEnC,QAAM,MAAM,IAAI,UAAU,EAAE,gBAAgB,MAAM,eAAe,EAAE,cAAc,KAAK;AACtF,MAAI,CAAC,KAAK;AACT,UAAM,IAAI,MAAM,2BAA2B;AAAA,EAC5C;AAEA,MAAI,QAAQ,WAAW,IAAI,aAAa,OAAO,KAAK,GAAG;AACvD,MAAI,SAAS,WAAW,IAAI,aAAa,QAAQ,KAAK,GAAG;AAEzD,MAAI,EAAE,SAAS,SAAS;AACvB,UAAM,MAAM,OAAO,qBAAqB;AACxC,QAAI,KAAK,YAAY,GAAG;AACxB,UAAM,MAAM,IAAI,sBAAsB;AACtC,QAAI,KAAK,YAAY,GAAG;AAExB,YAAQ,IAAI;AACZ,aAAS,IAAI;AAAA,EACd;AAEA,QAAM,QAAQ,MAAM,OAAO,2BAA2B;AAAA,IACrD,MAAM;AAAA,IACN,MAAM,IAAI,KAAK,CAAC,IAAI,GAAG,aAAa,EAAE,MAAM,gBAAgB,CAAC;AAAA,EAC9D,CAAC;AAED,MAAI,CAAC,MAAO,OAAM,MAAM,2BAA2B;AAEnD,wBAAsB,QAAQ,CAAC,KAAK,GAAG,QAAQ;AAChD;AAGO,SAAS,kCACf,QACA,EAAE,OAAO,KAAK,MAAM,GACnB;AACD,QAAM,WACL,UACC,OAAO,OAAO,YAAY,IACxB,OAAO,OAAO,oBAAoB,IAClC,OAAO,sBAAsB,EAAE;AAEnC,QAAM,EAAE,OAAO,OAAO,IAAI;AAE1B,QAAM,SAAK,6BAAc;AAEzB,QAAM,eAAW;AAAA,IAChB,IAAI,kBAAI,SAAS,KAAK,SAAS,OAAO,GAAG,SAAS,KAAK,UAAU,OAAO,CAAC;AAAA,IACzE;AAAA,EACD;AACA,QAAM,eAA+B;AAAA,IACpC;AAAA,IACA,MAAM;AAAA,IACN,GAAG,SAAS;AAAA,IACZ,GAAG,SAAS;AAAA,IACZ,OAAO;AAAA,MACN,GAAG;AAAA,MACH,GAAG;AAAA,MACH;AAAA,IACD;AAAA,EACD;AAEA,MAAI,OAAO,eAAe,YAAY,GAAG;AACxC,WAAO,YAAY,YAAY,EAAE,OAAO,EAAE;AAAA,EAC3C;AACD;AAGA,eAAsB,iCACrB,QACA,EAAE,OAAO,MAAM,GACf,SACC;AACD,QAAM,EAAE,QAAQ,IAAI,IAAI;AACxB,MAAI,MAAM,SAAS,OAAO,QAAQ,gBAAgB;AACjD,WAAO,SAAS,EAAE,OAAO,IAAI,8BAA8B,GAAG,UAAU,QAAQ,CAAC;AACjF;AAAA,EACD;AAEA,QAAM,WACL,UACC,OAAO,OAAO,YAAY,IACxB,OAAO,OAAO,oBAAoB,IAClC,OAAO,sBAAsB,EAAE;AAEnC,QAAM,YAAY,IAAI,kBAAI,SAAS,GAAG,SAAS,CAAC;AAChD,QAAM,gBAA2B,CAAC;AAClC,QAAM,iBAGA,CAAC;AACP,aAAW,QAAQ,OAAO;AACzB,UAAM,YAAY,uBAAuB,QAAQ,MAAM,OAAO;AAC9D,QAAI,CAAC,UAAW;AAEhB,UAAM,gBAAgB,MAAM,qBAAqB,IAAI;AACrD,QAAI,CAAC,eAAe;AACnB,aAAO,SAAS;AAAA,QACf,OAAO,IAAI,4BAA4B;AAAA,QACvC,UAAU;AAAA,MACX,CAAC;AACD;AAAA,IACD;AACA,UAAM,YAAY,MAAM,aAAa,QAAQ,aAAa;AAC1D,QAAI,CAAC,UAAW;AAChB,QAAI,UAAU,SAAS,SAAS;AAC/B,aAAO,4BAA4B,UAAU,IAAI,aAAa;AAAA,IAC/D;AACA,kBAAc,KAAK,SAAS;AAC5B,mBAAe,KAAK,EAAE,OAAO,WAAW,MAAM,cAAc,CAAC;AAAA,EAC9D;AAEA,UAAQ;AAAA,IACP,eAAe,IAAI,OAAO,iBAAiB;AAC1C,UAAI;AACH,cAAM,WAAW,MAAM,OAAO,2BAA2B;AAAA,UACxD,MAAM;AAAA,UACN,MAAM,aAAa;AAAA,QACpB,CAAC;AAED,YAAI,CAAC,UAAU;AACd,gBAAM,MAAM,2BAA2B;AAAA,QACxC;AAGA,eAAO,aAAa,CAAC,EAAE,GAAG,UAAU,IAAI,aAAa,MAAM,GAAG,CAAC,CAAC;AAAA,MACjE,SAAS,OAAO;AACf,eAAO,SAAS;AAAA,UACf,OAAO,IAAI,4BAA4B;AAAA,UACvC,UAAU;AAAA,QACX,CAAC;AACD,gBAAQ,MAAM,KAAK;AACnB,eAAO,aAAa,CAAC,aAAa,MAAM,EAAE,CAAC;AAC3C;AAAA,MACD;AAAA,IACD,CAAC;AAAA,EACF;AAEA,wBAAsB,QAAQ,eAAe,SAAS;AACvD;AAGA,eAAsB,iCACrB,QACA,EAAE,OAAO,MAAM,KAAK,GACnB;AACD,QAAM,IACL,UACC,OAAO,OAAO,YAAY,IACxB,OAAO,OAAO,oBAAoB,IAClC,OAAO,sBAAsB,EAAE;AAEnC,QAAM,eAAe,OAAO,aAA0B,MAAM,EAAE,gBAAgB;AAE9E,QAAM,yBAAqB,yBAAY,IAAI;AAC3C,QAAM,kBAAkB,WACrB,wCAAuB,QAAQ,IAAI,QACnC,0BAAW,kBAAkB;AAoBhC,MAAI;AACJ,MAAI;AACJ,MAAI;AACJ,MAAI,QAAQ;AAEZ,QAAM,oBAAgB,sDAAqC,QAAQ,eAAe;AAClF,QAAM,cAAc,gBAAgB,QAAQ,SAAS;AAGrD,QAAM,YAAQ,mCAAsB,kBAAkB;AAEtD,MAAI,aAAa;AAChB,YAAQ,cAAe,QAAQ,QAAQ,UAAW;AAAA,EACnD;AAEA,QAAM,QAAQ,OAAO,gBAAgB;AAErC,QAAM,UAAU,OAAO,YAAY,YAAY,eAAe;AAAA,IAC7D,GAAG;AAAA,IACH,YAAY,MAAM;AAAA,IAClB,gBAAY,8CAAc,OAAO,aAAa,IAAI;AAAA,IAClD,UAAU,MAAM,WAAW,0CAAW,aAAa,IAAI;AAAA,IACvD,UAAU;AAAA,EACX,CAAC;AAED,QAAM,WAAW,KAAK;AAAA,IACrB,cAAc,OAAO,sBAAsB,EAAE,QAAQ,MAAM;AAAA,IAC3D,KAAK,IAAI,KAAK,OAAO,sBAAsB,EAAE,QAAQ,GAAG;AAAA,EACzD;AAEA,MAAI,QAAQ,IAAI,UAAU;AACzB,UAAM,aAAa,OAAO,YAAY,YAAY,eAAe;AAAA,MAChE,GAAG;AAAA,MACH,YAAY,MAAM;AAAA,MAClB,gBAAY,8CAAc,OAAO,aAAa,IAAI;AAAA,MAClD,UAAU,MAAM,WAAW,0CAAW,aAAa,IAAI;AAAA,MACvD,UAAU;AAAA,IACX,CAAC;AACD,QAAI,WAAW;AACf,QAAI,WAAW;AACf,eAAW;AACX,YAAQ,QAAQ,QAAQ;AAAA,EACzB,OAAO;AAEN,QAAI,KAAK,IAAI,QAAQ,GAAG,EAAE;AAC1B,QAAI,KAAK,IAAI,QAAQ,GAAG,EAAE;AAC1B,eAAW;AAAA,EACZ;AAEA,MAAI,EAAE,IAAI,IAAI,IAAI,OAAO,sBAAsB,EAAE,OAAO,IAAI;AAC3D,MAAE,IAAI,OAAO,sBAAsB,EAAE,OAAO,KAAK,IAAI;AAAA,EACtD;AAEA,QAAM,eAAW,+BAAgB,IAAI,kBAAI,EAAE,IAAI,IAAI,GAAG,EAAE,IAAI,IAAI,CAAC,GAAG,MAAM;AAC1E,QAAM,cAAU,6BAAc;AAG9B,SAAO,aAAa;AAAA,IACnB;AAAA,MACC,IAAI;AAAA,MACJ,MAAM;AAAA,MACN,GAAG,SAAS;AAAA,MACZ,GAAG,SAAS;AAAA,MACZ,OAAO;AAAA,QACN,UAAU;AAAA;AAAA,QAEV,WAAW;AAAA,QACX;AAAA,QACA;AAAA,MACD;AAAA,IACD;AAAA,EACD,CAAC;AACF;AAGA,eAAsB,gCACrB,QACA,EAAE,OAAO,IAAI,GACb,EAAE,QAAQ,IAAI,GACb;AAED,QAAM,YAAY,OAAO,aAAa,OAAO;AAC7C,QAAM,YAAY,WAAW,mBAAmB,GAAG;AAEnD,MAAI,aAAa,UAAU,WAAW,iBAAiB,OAAO;AAC7D,WAAO,OAAO,mBAAmB;AAAA,MAChC,MAAM;AAAA,MACN,KAAK,UAAU;AAAA,MACf;AAAA,MACA,OAAO,UAAU;AAAA,IAClB,CAAC;AAAA,EACF;AAEA,QAAM,WACL,UACC,OAAO,OAAO,YAAY,IACxB,OAAO,OAAO,oBAAoB,IAClC,OAAO,sBAAsB,EAAE;AAGnC,QAAM,SAAS,UAAM,wCAAsB,QAAQ,EAAE,KAAK,QAAQ,SAAS,CAAC;AAE5E,MAAI,CAAC,OAAO,IAAI;AACf,WAAO,SAAS;AAAA,MACf,OAAO,IAAI,mBAAmB;AAAA,MAC9B,UAAU;AAAA,IACX,CAAC;AACD;AAAA,EACD;AACD;AAGA,eAAsB,mCACrB,QACA,EAAE,OAAO,QAAQ,GAChB;AACD,SAAO,IAAI,MAAM;AAChB,UAAM,wBAAwB,OAAO,uBAAuB;AAC5D,WAAO,yBAAyB,OAAO;AAGvC,eAAW,SAAS,QAAQ,QAAQ;AACnC,UAAI,QAAQ,aAAa,SAAS,MAAM,EAAE,GAAG;AAC5C,cAAM,WAAW;AAAA,MAClB;AAAA,IACD;AAOA,UAAM,mBAAmB,OAAO;AAAA,MAC/B;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACD;AAEA,WAAO,0BAA0B,SAAS;AAAA,MACzC;AAAA,MACA,QAAQ,CAAC;AAAA,IACV,CAAC;AACD,UAAM,sBAAsB,OAAO,uBAAuB;AAC1D;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,MAOC,CAAC,oBACD,yBACA,uBACA,uBAAuB,SAAS,mBAAmB;AAAA,MAClD;AAED,aAAO,oBAAoB,EAAE,iBAAiB,KAAK,CAAC;AACpD,aAAO,OAAO,WAAW,MAAM;AAC9B,eAAO,oBAAoB,EAAE,iBAAiB,MAAM,CAAC;AAAA,MACtD,GAAG,GAAG;AAAA,IACP;AAAA,EACD,CAAC;AACF;AAGA,eAAsB,uCACrB,QACA,EAAE,OAAO,QAAQ,GAChB;AACD,SAAO,IAAI,MAAM;AAChB,0DAAqB,QAAQ,SAAS,KAAK;AAAA,EAC5C,CAAC;AACF;AAcA,eAAsB,sBACrB,QACA,QACA,UACuB;AACvB,MAAI,CAAC,OAAO,OAAQ,QAAO,CAAC;AAE5B,QAAM,eAAe,kBAAI,KAAK,QAAQ;AACtC,QAAM,WAA6B,CAAC;AAEpC,WAAS,IAAI,GAAG,IAAI,OAAO,QAAQ,KAAK;AACvC,UAAM,QAAQ,OAAO,CAAC;AACtB,UAAM,YAAY,OAAO,yBAAyB,MAAM,IAAI;AAC5D,UAAM,UAAU,WAAW,sBAAsB,OAAO,YAAY,KAAK;AACzE,QAAI,SAAS;AACZ,eAAS,KAAK,OAAO;AACrB,UAAI,OAAO,MAAM,SAAS,OAAO,MAAM,MAAM,MAAM,UAAU;AAC5D,qBAAa,KAAK,MAAM,MAAM;AAAA,MAC/B;AAAA,IACD;AAAA,EACD;AAEA,SAAO,IAAI,MAAM;AAEhB,UAAM,iBAAiB,OAAO,OAAO,CAAC,UAAU,CAAC,OAAO,SAAS,MAAM,EAAE,CAAC;AAE1E,WAAO,MAAM,OAAO,MAAM;AACzB,UAAI,OAAO,gBAAgB,QAAQ,GAAG;AACrC,YAAI,eAAe,QAAQ;AAC1B,iBAAO,aAAa,cAAc;AAAA,QACnC;AAGA,eAAO,aAAa,QAAQ,EAAE,OAAO,GAAG,SAAS,IAAI,CAAC,MAAM,EAAE,EAAE,CAAC;AAGjE,mCAA2B,QAAQ,QAAQ;AAAA,MAC5C;AAAA,IACD,CAAC;AAAA,EACF,CAAC;AAED,SAAO,SAAS,IAAI,CAAC,MAAM,EAAE,EAAE;AAChC;AAYO,SAAS,2BAA2B,QAAgB,UAAmB;AAE7E,QAAM,qBAAqB,OAAO,sBAAsB;AACxD,MAAI,sBAAsB,OAAO,uBAAuB;AAExD,MAAI,qBAAqB;AACxB,UAAM,SAAS,oBAAqB,OAAO,IAAI,QAAQ;AAEvD,WAAO;AAAA,MACN,OAAO,kBAAkB,EAAE,IAAI,CAAC,UAAU;AACzC,cAAM,gBAAgB,OAAO,wBAAwB,KAAK,EAAE,UAAU,EAAE;AACxE,cAAM,aAAa,kBAAI,IAAI,QAAQ,CAAC,aAAa;AACjD,eAAO;AAAA,UACN,IAAI,MAAM;AAAA,UACV,MAAM,MAAM;AAAA,UACZ,GAAG,MAAM,IAAK,WAAW;AAAA,UACzB,GAAG,MAAM,IAAK,WAAW;AAAA,QAC1B;AAAA,MACD,CAAC;AAAA,IACF;AAAA,EACD;AACA,wBAAsB,OAAO,uBAAuB;AAEpD,MAAI,uBAAuB,OAAO,iBAAiB,EAAE,YAAY;AAChE,UAAM,WAAW,OAAO,oBAAoB,EAAE;AAC9C,UAAM,UAAU,IAAI,kBAAI,oBAAoB,MAAM,oBAAoB,IAAI;AAC1E,UAAM,mBAAmB,QAAQ,MAAM,EAAE,WAAW,QAAQ;AAC5D,UAAM,QAAQ,kBAAI,IAAI,SAAS,gBAAgB;AAC/C,WAAO;AAAA,MACN,OAAO,kBAAkB,EAAE,IAAI,CAAC,UAAU;AACzC,cAAM,WAAW,EAAE,GAAG,MAAM,IAAK,MAAM,GAAG,GAAG,MAAM,IAAK,MAAM,EAAE;AAChE,eAAO;AAAA,UACN,IAAI,MAAM;AAAA,UACV,MAAM,MAAM;AAAA,UACZ,GAAG,SAAS;AAAA,UACZ,GAAG,SAAS;AAAA,QACb;AAAA,MACD,CAAC;AAAA,IACF;AAAA,EACD;AAEA,wBAAsB,OAAO,uBAAuB;AACpD,MAAI,uBAAuB,CAAC,mBAAmB,SAAS,mBAAmB,GAAG;AAC7E,WAAO,gBAAgB,EAAE,WAAW,EAAE,UAAU,OAAO,QAAQ,kBAAkB,EAAE,CAAC;AAAA,EACrF;AACD;AAGO,SAAS,yBACf,QACA,KACA,UACkB;AAClB,QAAM,UAA0B;AAAA,IAC/B,QAAI,6BAAc;AAAA,IAClB,MAAM;AAAA,IACN,GAAG,SAAS,IAAI;AAAA,IAChB,GAAG,SAAS,IAAI;AAAA,IAChB,SAAS;AAAA,IACT,OAAO;AAAA,MACN,SAAS;AAAA,MACT;AAAA,IACD;AAAA,EACD;AAEA,SAAO,IAAI,MAAM;AAEhB,WAAO,YAAY,OAAO;AAC1B,QAAI,CAAC,OAAO,SAAS,QAAQ,EAAE,EAAG;AAClC,WAAO,OAAO,QAAQ,EAAE;AACxB,+BAA2B,QAAQ,QAAQ;AAAA,EAC5C,CAAC;AAED,SAAO,OAAO,SAAS,QAAQ,EAAE;AAClC;AAEA,eAAe,qBAAqB,MAAkC;AACrE,MAAI,KAAK,SAAS,gBAAiB,QAAO;AAC1C,MAAI;AACH,UAAM,OAAO,MAAM,KAAK,KAAK;AAC7B,UAAM,EAAE,YAAY,IAAI,MAAM,OAAO,yBAAyB;AAC9D,UAAM,YAAY,YAAY,IAAI;AAClC,QAAI,CAAC,UAAW,QAAO;AACvB,WAAO,IAAI,KAAK,CAAC,SAAS,GAAG,KAAK,MAAM,EAAE,MAAM,KAAK,MAAM,cAAc,KAAK,aAAa,CAAC;AAAA,EAC7F,QAAQ;AACP,WAAO;AAAA,EACR;AACD;AAWO,SAAS,uBACf,QACA,MACA,SACC;AACD,QAAM;AAAA,IACL,eAAe;AAAA,IACf;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACD,IAAI;AASJ,QAAM,oBACL,CAAC,CAAC,OAAO,wBAAwB,KAAK,IAAI,MACzC,wBAAwB,SAAS,KAAK,IAAI,KAAK,WAC/C,wBAAwB,SAAS,KAAK,IAAI,KAAK;AACjD,MAAI,CAAC,mBAAmB;AACvB,WAAO,SAAS;AAAA,MACf,OAAO,IAAI,+BAA+B;AAAA,MAC1C,UAAU;AAAA,IACX,CAAC;AACD,WAAO;AAAA,EACR;AAEA,MAAI,KAAK,OAAO,cAAc;AAC7B,UAAM,cAAc,CAAC,UAA0B;AAC9C,UAAI,UAAU,EAAG,QAAO;AAExB,YAAM,QAAQ,CAAC,SAAS,MAAM,MAAM,MAAM,MAAM,IAAI;AACpD,YAAM,OAAO;AACb,YAAM,YAAY,KAAK,MAAM,KAAK,IAAI,KAAK,IAAI,KAAK,IAAI,IAAI,CAAC;AAE7D,YAAM,QAAQ,QAAQ,KAAK,IAAI,MAAM,SAAS;AAC9C,YAAM,YAAY,QAAQ,MAAM,IAAI,MAAM,SAAS,IAAI,MAAM,QAAQ,CAAC;AAEtE,aAAO,GAAG,SAAS,IAAI,MAAM,SAAS,CAAC;AAAA,IACxC;AAEA,WAAO,SAAS;AAAA,MACf,OAAO,IAAI,2BAA2B;AAAA,MACtC,aAAa,IAAI,2BAA2B,EAAE,QAAQ,UAAU,YAAY,YAAY,CAAC;AAAA,MACzF,UAAU;AAAA,IACX,CAAC;AACD,WAAO;AAAA,EACR;AAKA,MAAI,CAAC,KAAK,MAAM;AACf,WAAO,SAAS;AAAA,MACf,OAAO,IAAI,4BAA4B;AAAA,MACvC,UAAU;AAAA,IACX,CAAC;AACD,YAAQ,MAAM,cAAc;AAC5B,WAAO;AAAA,EACR;AAEA,SAAO;AACR;AAGA,eAAsB,aAAa,QAAgB,MAAY,SAAqB;AACnF,MAAI,CAAC,SAAS;AACb,UAAM,WAAO,gCAAiB,MAAM,KAAK,YAAY,CAAC;AACtD,cAAU,8BAAgB,SAAS,IAAI;AAAA,EACxC;AAEA,QAAM,YAAY,OAAO,wBAAwB,KAAK,IAAI;AAC1D,MAAI,CAAC,UAAW,QAAO;AAEvB,SAAO,MAAM,UAAU,iBAAiB,MAAM,OAAO;AACtD;",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -52,14 +52,14 @@ function setBookmarkHeight(editor, shape) {
|
|
|
52
52
|
props: { ...shape.props, h: getBookmarkHeight(editor, shape.props.assetId) }
|
|
53
53
|
};
|
|
54
54
|
}
|
|
55
|
-
|
|
55
|
+
function getHumanReadableAddress(url) {
|
|
56
56
|
try {
|
|
57
57
|
const objUrl = new URL(url);
|
|
58
58
|
return objUrl.hostname.replace(/^www\./, "");
|
|
59
59
|
} catch {
|
|
60
60
|
return url;
|
|
61
61
|
}
|
|
62
|
-
}
|
|
62
|
+
}
|
|
63
63
|
function updateBookmarkAssetOnUrlChange(editor, shape) {
|
|
64
64
|
const { url } = shape.props;
|
|
65
65
|
const assetId = import_editor.AssetRecordType.createId((0, import_editor.getHashForString)(url));
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../../src/lib/shapes/bookmark/bookmarks.ts"],
|
|
4
|
-
"sourcesContent": ["import {\n\tAssetRecordType,\n\tEditor,\n\tResult,\n\tTLAssetId,\n\tTLBookmarkAsset,\n\tTLBookmarkShape,\n\tTLShapePartial,\n\tcreateShapeId,\n\tdebounce,\n\tgetHashForString,\n} from '@tldraw/editor'\n\nexport const BOOKMARK_WIDTH = 300\nexport const BOOKMARK_HEIGHT = 320\nexport const BOOKMARK_JUST_URL_HEIGHT = 46\nconst SHORT_BOOKMARK_HEIGHT = 101\n\nexport function getBookmarkHeight(editor: Editor, assetId?: TLAssetId | null) {\n\tconst asset = (assetId ? editor.getAsset(assetId) : null) as TLBookmarkAsset | null\n\n\tif (asset) {\n\t\tif (!asset.props.image) {\n\t\t\tif (!asset.props.title) {\n\t\t\t\treturn BOOKMARK_JUST_URL_HEIGHT\n\t\t\t} else {\n\t\t\t\treturn SHORT_BOOKMARK_HEIGHT\n\t\t\t}\n\t\t}\n\t}\n\n\treturn BOOKMARK_HEIGHT\n}\n\nexport function setBookmarkHeight(editor: Editor, shape: TLBookmarkShape) {\n\treturn {\n\t\t...shape,\n\t\tprops: { ...shape.props, h: getBookmarkHeight(editor, shape.props.assetId) },\n\t}\n}\n\n/** @internal */\nexport
|
|
5
|
-
"mappings": ";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,oBAWO;AAEA,MAAM,iBAAiB;AACvB,MAAM,kBAAkB;AACxB,MAAM,2BAA2B;AACxC,MAAM,wBAAwB;AAEvB,SAAS,kBAAkB,QAAgB,SAA4B;AAC7E,QAAM,QAAS,UAAU,OAAO,SAAS,OAAO,IAAI;AAEpD,MAAI,OAAO;AACV,QAAI,CAAC,MAAM,MAAM,OAAO;AACvB,UAAI,CAAC,MAAM,MAAM,OAAO;AACvB,eAAO;AAAA,MACR,OAAO;AACN,eAAO;AAAA,MACR;AAAA,IACD;AAAA,EACD;AAEA,SAAO;AACR;AAEO,SAAS,kBAAkB,QAAgB,OAAwB;AACzE,SAAO;AAAA,IACN,GAAG;AAAA,IACH,OAAO,EAAE,GAAG,MAAM,OAAO,GAAG,kBAAkB,QAAQ,MAAM,MAAM,OAAO,EAAE;AAAA,EAC5E;AACD;AAGO,
|
|
4
|
+
"sourcesContent": ["import {\n\tAssetRecordType,\n\tEditor,\n\tResult,\n\tTLAssetId,\n\tTLBookmarkAsset,\n\tTLBookmarkShape,\n\tTLShapePartial,\n\tcreateShapeId,\n\tdebounce,\n\tgetHashForString,\n} from '@tldraw/editor'\n\nexport const BOOKMARK_WIDTH = 300\nexport const BOOKMARK_HEIGHT = 320\nexport const BOOKMARK_JUST_URL_HEIGHT = 46\nconst SHORT_BOOKMARK_HEIGHT = 101\n\nexport function getBookmarkHeight(editor: Editor, assetId?: TLAssetId | null) {\n\tconst asset = (assetId ? editor.getAsset(assetId) : null) as TLBookmarkAsset | null\n\n\tif (asset) {\n\t\tif (!asset.props.image) {\n\t\t\tif (!asset.props.title) {\n\t\t\t\treturn BOOKMARK_JUST_URL_HEIGHT\n\t\t\t} else {\n\t\t\t\treturn SHORT_BOOKMARK_HEIGHT\n\t\t\t}\n\t\t}\n\t}\n\n\treturn BOOKMARK_HEIGHT\n}\n\nexport function setBookmarkHeight(editor: Editor, shape: TLBookmarkShape) {\n\treturn {\n\t\t...shape,\n\t\tprops: { ...shape.props, h: getBookmarkHeight(editor, shape.props.assetId) },\n\t}\n}\n\n/** @internal */\nexport function getHumanReadableAddress(url: string) {\n\ttry {\n\t\tconst objUrl = new URL(url)\n\t\t// we want the hostname without any www\n\t\treturn objUrl.hostname.replace(/^www\\./, '')\n\t} catch {\n\t\treturn url\n\t}\n}\n\nexport function updateBookmarkAssetOnUrlChange(editor: Editor, shape: TLBookmarkShape) {\n\tconst { url } = shape.props\n\n\t// Derive the asset id from the URL\n\tconst assetId: TLAssetId = AssetRecordType.createId(getHashForString(url))\n\n\tif (editor.getAsset(assetId)) {\n\t\t// Existing asset for this URL?\n\t\tif (shape.props.assetId !== assetId) {\n\t\t\teditor.updateShapes([\n\t\t\t\t{\n\t\t\t\t\tid: shape.id,\n\t\t\t\t\ttype: shape.type,\n\t\t\t\t\tprops: { assetId },\n\t\t\t\t},\n\t\t\t])\n\t\t}\n\t} else {\n\t\t// No asset for this URL?\n\n\t\t// First, clear out the existing asset reference\n\t\teditor.updateShapes([\n\t\t\t{\n\t\t\t\tid: shape.id,\n\t\t\t\ttype: shape.type,\n\t\t\t\tprops: { assetId: null },\n\t\t\t},\n\t\t])\n\n\t\t// Then try to asyncronously create a new one\n\t\tcreateBookmarkAssetOnUrlChange(editor, shape)\n\t}\n}\n\nasync function _createBookmarkAssetOnUrlChange(editor: Editor, shape: TLBookmarkShape) {\n\tif (editor.isDisposed) return\n\n\tconst { url } = shape.props\n\n\t// Create the asset using the external content manager's createAssetFromUrl method.\n\t// This may be overwritten by the user (for example, we overwrite it on tldraw.com)\n\tconst asset = await editor.getAssetForExternalContent({ type: 'url', url })\n\n\tif (!asset) {\n\t\t// No asset? Just leave the bookmark as a null assetId.\n\t\treturn\n\t}\n\n\teditor.run(() => {\n\t\t// Create the new asset\n\t\teditor.createAssets([asset])\n\n\t\t// And update the shape\n\t\teditor.updateShapes([\n\t\t\t{\n\t\t\t\tid: shape.id,\n\t\t\t\ttype: shape.type,\n\t\t\t\tprops: { assetId: asset.id },\n\t\t\t},\n\t\t])\n\t})\n}\n\nconst bookmarkDebouncers = new WeakMap<\n\tEditor,\n\tReturnType<typeof debounce<[Editor, TLBookmarkShape], void>>\n>()\n\nfunction createBookmarkAssetOnUrlChange(editor: Editor, shape: TLBookmarkShape) {\n\tlet fn = bookmarkDebouncers.get(editor)\n\tif (!fn) {\n\t\tfn = debounce(_createBookmarkAssetOnUrlChange, 500)\n\t\tbookmarkDebouncers.set(editor, fn)\n\t}\n\tfn(editor, shape)\n}\n\n/**\n * Creates a bookmark shape from a URL with unfurled metadata.\n *\n * @returns A Result containing the created bookmark shape or an error\n * @public\n */\n\nexport async function createBookmarkFromUrl(\n\teditor: Editor,\n\t{\n\t\turl,\n\t\tcenter = editor.getViewportPageBounds().center,\n\t}: {\n\t\turl: string\n\t\tcenter?: { x: number; y: number }\n\t}\n): Promise<Result<TLBookmarkShape, string>> {\n\ttry {\n\t\t// Create the bookmark asset with unfurled metadata\n\t\tconst asset = await editor.getAssetForExternalContent({ type: 'url', url })\n\n\t\t// Create the bookmark shape\n\t\tconst shapeId = createShapeId()\n\t\tconst shapePartial: TLShapePartial<TLBookmarkShape> = {\n\t\t\tid: shapeId,\n\t\t\ttype: 'bookmark',\n\t\t\tx: center.x - BOOKMARK_WIDTH / 2,\n\t\t\ty: center.y - BOOKMARK_HEIGHT / 2,\n\t\t\trotation: 0,\n\t\t\topacity: 1,\n\t\t\tprops: {\n\t\t\t\turl,\n\t\t\t\tassetId: asset?.id || null,\n\t\t\t\tw: BOOKMARK_WIDTH,\n\t\t\t\th: getBookmarkHeight(editor, asset?.id),\n\t\t\t},\n\t\t}\n\n\t\teditor.run(() => {\n\t\t\t// Create the asset if we have one\n\t\t\tif (asset) {\n\t\t\t\teditor.createAssets([asset])\n\t\t\t}\n\n\t\t\t// Create the shape\n\t\t\teditor.createShapes([shapePartial])\n\t\t})\n\n\t\t// Get the created shape\n\t\tconst createdShape = editor.getShape(shapeId) as TLBookmarkShape\n\t\treturn Result.ok(createdShape)\n\t} catch (error) {\n\t\treturn Result.err(error instanceof Error ? error.message : 'Failed to create bookmark')\n\t}\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -507,6 +507,10 @@ function useNoteKeydownHandler(id) {
|
|
|
507
507
|
if (!shape) return;
|
|
508
508
|
const isTab = e.key === "Tab";
|
|
509
509
|
const isCmdEnter = (e.metaKey || e.ctrlKey) && e.key === "Enter";
|
|
510
|
+
if (isTab && (0, import_richText.isEditingRichTextList)(editor)) {
|
|
511
|
+
e.preventDefault();
|
|
512
|
+
return;
|
|
513
|
+
}
|
|
510
514
|
if (isTab || isCmdEnter) {
|
|
511
515
|
e.preventDefault();
|
|
512
516
|
const pageTransform = editor.getShapePageTransform(id);
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../../src/lib/shapes/note/NoteShapeUtil.tsx"],
|
|
4
|
-
"sourcesContent": ["/* eslint-disable react-hooks/rules-of-hooks */\nimport {\n\tBox,\n\tDefaultFontFamilies,\n\tEMPTY_ARRAY,\n\tEditor,\n\tGroup2d,\n\tIndexKey,\n\tRectangle2d,\n\tSafeId,\n\tShapeUtil,\n\tSvgExportContext,\n\tTLHandle,\n\tTLNoteShape,\n\tTLNoteShapeProps,\n\tTLResizeInfo,\n\tTLShape,\n\tTLShapeId,\n\tVec,\n\tWeakCache,\n\texhaustiveSwitchError,\n\tgetColorValue,\n\tgetFontsFromRichText,\n\tisEqual,\n\tlerp,\n\tnoteShapeMigrations,\n\tnoteShapeProps,\n\tresizeScaled,\n\trng,\n\ttoRichText,\n\tuseColorMode,\n\tuseEditor,\n\tuseValue,\n} from '@tldraw/editor'\nimport { useCallback, useContext } from 'react'\nimport { startEditingShapeWithRichText } from '../../tools/SelectTool/selectHelpers'\nimport { TldrawUiTooltip } from '../../ui/components/primitives/TldrawUiTooltip'\nimport { TranslationsContext } from '../../ui/hooks/useTranslation/useTranslation'\nimport {\n\tisEmptyRichText,\n\trenderHtmlFromRichTextForMeasurement,\n\trenderPlaintextFromRichText,\n} from '../../utils/text/richText'\nimport { isRightToLeftLanguage } from '../../utils/text/text'\nimport {\n\tLABEL_FONT_SIZES,\n\tLABEL_PADDING,\n\tTEXT_PROPS,\n\tgetFontFamily,\n} from '../shared/default-shape-constants'\nimport { DefaultFontFaces, getThemeFontFaces } from '../shared/defaultFonts'\nimport { ShapeOptionsWithDisplayValues, getDisplayValues } from '../shared/getDisplayValues'\nimport { HyperlinkButton } from '../shared/HyperlinkButton'\nimport { RichTextLabel, RichTextSVG } from '../shared/RichTextLabel'\nimport { useIsReadyForEditing } from '../shared/useEditablePlainText'\nimport { useEfficientZoomThreshold } from '../shared/useEfficientZoomThreshold'\nimport { CLONE_HANDLE_MARGIN, getNoteShapeForAdjacentPosition } from './noteHelpers'\n\nconst NOTE_SHAPE_HORIZONTAL_ALIGNS = Object.freeze({\n\tstart: 'start',\n\tmiddle: 'center',\n\tend: 'end',\n\t'start-legacy': 'start',\n\t'end-legacy': 'end',\n\t'middle-legacy': 'center',\n} as const)\n\nconst NOTE_SHAPE_VERTICAL_ALIGNS = Object.freeze({\n\tstart: 'start',\n\tmiddle: 'middle',\n\tend: 'end',\n} as const)\n\n/** @public */\nexport interface NoteShapeUtilDisplayValues {\n\tnoteWidth: number\n\tnoteHeight: number\n\tnoteBackgroundColor: string\n\tborderColor: string\n\tborderWidth: number\n\tlabelColor: string\n\tlabelFontFamily: string\n\tlabelFontSize: number\n\tlabelLineHeight: number\n\tlabelFontWeight: string\n\tlabelFontVariant: string\n\tlabelFontStyle: string\n\tlabelPadding: number\n\tlabelHorizontalAlign: 'start' | 'center' | 'end'\n\tlabelVerticalAlign: 'start' | 'middle' | 'end'\n}\n\n/** @public */\nexport interface NoteShapeOptions extends ShapeOptionsWithDisplayValues<\n\tTLNoteShape,\n\tNoteShapeUtilDisplayValues\n> {\n\t/**\n\t * How should the note shape resize? By default it does not resize (except automatically based on its text content),\n\t * but you can set it to be user-resizable using scale.\n\t */\n\tresizeMode: 'none' | 'scale'\n}\n\n/** @public */\nexport class NoteShapeUtil extends ShapeUtil<TLNoteShape> {\n\tstatic override type = 'note' as const\n\tstatic override props = noteShapeProps\n\tstatic override migrations = noteShapeMigrations\n\n\toverride options: NoteShapeOptions = {\n\t\tresizeMode: 'none',\n\t\tgetDefaultDisplayValues(_editor, shape, theme, colorMode): NoteShapeUtilDisplayValues {\n\t\t\tconst { color, labelColor, font, size, align, verticalAlign } = shape.props\n\t\t\tconst colors = theme.colors[colorMode]\n\t\t\treturn {\n\t\t\t\tnoteWidth: 200,\n\t\t\t\tnoteHeight: 200,\n\t\t\t\tnoteBackgroundColor: getColorValue(colors, color, 'noteFill'),\n\t\t\t\tborderColor: colors.noteBorder,\n\t\t\t\tborderWidth: 2,\n\t\t\t\tlabelColor:\n\t\t\t\t\tlabelColor === 'black'\n\t\t\t\t\t\t? getColorValue(colors, color, 'noteText')\n\t\t\t\t\t\t: getColorValue(colors, labelColor, 'fill'),\n\t\t\t\tlabelFontFamily: getFontFamily(theme, font),\n\t\t\t\tlabelFontSize: theme.fontSize * LABEL_FONT_SIZES[size],\n\t\t\t\tlabelLineHeight: theme.lineHeight,\n\t\t\t\tlabelFontWeight: TEXT_PROPS.fontWeight,\n\t\t\t\tlabelFontVariant: TEXT_PROPS.fontVariant,\n\t\t\t\tlabelFontStyle: TEXT_PROPS.fontStyle,\n\t\t\t\tlabelPadding: LABEL_PADDING,\n\t\t\t\tlabelHorizontalAlign: NOTE_SHAPE_HORIZONTAL_ALIGNS[align],\n\t\t\t\tlabelVerticalAlign: NOTE_SHAPE_VERTICAL_ALIGNS[verticalAlign],\n\t\t\t}\n\t\t},\n\t\tgetCustomDisplayValues(): Partial<NoteShapeUtilDisplayValues> {\n\t\t\treturn {}\n\t\t},\n\t}\n\n\toverride canEdit(shape: TLNoteShape) {\n\t\treturn true\n\t}\n\toverride hideResizeHandles(shape: TLNoteShape) {\n\t\tconst { resizeMode } = this.options\n\t\tswitch (resizeMode) {\n\t\t\tcase 'none': {\n\t\t\t\treturn true\n\t\t\t}\n\t\t\tcase 'scale': {\n\t\t\t\treturn false\n\t\t\t}\n\t\t\tdefault: {\n\t\t\t\tthrow exhaustiveSwitchError(resizeMode)\n\t\t\t}\n\t\t}\n\t}\n\n\toverride isAspectRatioLocked(shape: TLNoteShape) {\n\t\treturn this.options.resizeMode === 'scale'\n\t}\n\n\toverride hideSelectionBoundsFg(shape: TLNoteShape) {\n\t\treturn false\n\t}\n\n\tgetDefaultProps(): TLNoteShape['props'] {\n\t\treturn {\n\t\t\tcolor: 'black',\n\t\t\trichText: toRichText(''),\n\t\t\tsize: 'm',\n\t\t\tfont: 'draw',\n\t\t\talign: 'middle',\n\t\t\tverticalAlign: 'middle',\n\t\t\tlabelColor: 'black',\n\t\t\tgrowY: 0,\n\t\t\tfontSizeAdjustment: 1,\n\t\t\turl: '',\n\t\t\tscale: 1,\n\t\t\ttextFirstEditedBy: null,\n\t\t}\n\t}\n\n\tgetGeometry(shape: TLNoteShape) {\n\t\tconst { labelHeight, labelWidth } = this.getLabelSize(shape)\n\t\tconst { scale } = shape.props\n\n\t\tconst dv = getDisplayValues(this, shape)\n\n\t\tconst lh = labelHeight * scale\n\t\tconst lw = labelWidth * scale\n\t\tconst nw = dv.noteWidth * scale\n\t\tconst nh = getNoteHeight(shape, dv.noteHeight)\n\n\t\treturn new Group2d({\n\t\t\tchildren: [\n\t\t\t\tnew Rectangle2d({ width: nw, height: nh, isFilled: true }),\n\t\t\t\tnew Rectangle2d({\n\t\t\t\t\tx:\n\t\t\t\t\t\tdv.labelHorizontalAlign === 'start'\n\t\t\t\t\t\t\t? 0\n\t\t\t\t\t\t\t: dv.labelHorizontalAlign === 'end'\n\t\t\t\t\t\t\t\t? nw - lw\n\t\t\t\t\t\t\t\t: (nw - lw) / 2,\n\t\t\t\t\ty:\n\t\t\t\t\t\tdv.labelVerticalAlign === 'start'\n\t\t\t\t\t\t\t? 0\n\t\t\t\t\t\t\t: dv.labelVerticalAlign === 'end'\n\t\t\t\t\t\t\t\t? nh - lh\n\t\t\t\t\t\t\t\t: (nh - lh) / 2,\n\t\t\t\t\twidth: lw,\n\t\t\t\t\theight: lh,\n\t\t\t\t\tisFilled: true,\n\t\t\t\t\tisLabel: true,\n\t\t\t\t\texcludeFromShapeBounds: true,\n\t\t\t\t}),\n\t\t\t],\n\t\t})\n\t}\n\n\toverride getHandles(shape: TLNoteShape): TLHandle[] {\n\t\tconst { scale } = shape.props\n\t\tconst isCoarsePointer = this.editor.getInstanceState().isCoarsePointer\n\t\tif (isCoarsePointer) return []\n\n\t\tconst zoom = this.editor.getEfficientZoomLevel()\n\t\tif (zoom * scale < 0.25) return []\n\n\t\tconst dv = getDisplayValues(this, shape)\n\t\tconst nh = getNoteHeight(shape, dv.noteHeight)\n\t\tconst nw = dv.noteWidth * scale\n\t\tconst offset = (CLONE_HANDLE_MARGIN / zoom) * scale\n\n\t\tif (zoom * scale < 0.5) {\n\t\t\treturn [\n\t\t\t\t{\n\t\t\t\t\tid: 'bottom',\n\t\t\t\t\tindex: 'a3' as IndexKey,\n\t\t\t\t\ttype: 'clone',\n\t\t\t\t\tx: nw / 2,\n\t\t\t\t\ty: nh + offset,\n\t\t\t\t},\n\t\t\t]\n\t\t}\n\n\t\treturn [\n\t\t\t{\n\t\t\t\tid: 'top',\n\t\t\t\tindex: 'a1' as IndexKey,\n\t\t\t\ttype: 'clone',\n\t\t\t\tx: nw / 2,\n\t\t\t\ty: -offset,\n\t\t\t},\n\t\t\t{\n\t\t\t\tid: 'right',\n\t\t\t\tindex: 'a2' as IndexKey,\n\t\t\t\ttype: 'clone',\n\t\t\t\tx: nw + offset,\n\t\t\t\ty: nh / 2,\n\t\t\t},\n\t\t\t{\n\t\t\t\tid: 'bottom',\n\t\t\t\tindex: 'a3' as IndexKey,\n\t\t\t\ttype: 'clone',\n\t\t\t\tx: nw / 2,\n\t\t\t\ty: nh + offset,\n\t\t\t},\n\t\t\t{\n\t\t\t\tid: 'left',\n\t\t\t\tindex: 'a4' as IndexKey,\n\t\t\t\ttype: 'clone',\n\t\t\t\tx: -offset,\n\t\t\t\ty: nh / 2,\n\t\t\t},\n\t\t]\n\t}\n\n\toverride onResize(shape: any, info: TLResizeInfo<any>) {\n\t\tconst { resizeMode } = this.options\n\t\tswitch (resizeMode) {\n\t\t\tcase 'none': {\n\t\t\t\treturn undefined\n\t\t\t}\n\t\t\tcase 'scale': {\n\t\t\t\treturn resizeScaled(shape, info)\n\t\t\t}\n\t\t\tdefault: {\n\t\t\t\tthrow exhaustiveSwitchError(resizeMode)\n\t\t\t}\n\t\t}\n\t}\n\n\toverride getText(shape: TLNoteShape) {\n\t\treturn renderPlaintextFromRichText(this.editor, shape.props.richText)\n\t}\n\n\toverride getReferencedUserIds(shape: TLNoteShape) {\n\t\treturn shape.props.textFirstEditedBy ? [shape.props.textFirstEditedBy] : []\n\t}\n\n\toverride getFontFaces(shape: TLNoteShape) {\n\t\tconst fonts = isEmptyRichText(shape.props.richText)\n\t\t\t? []\n\t\t\t: getFontsFromRichText(this.editor, shape.props.richText, {\n\t\t\t\t\tfamily: `tldraw_${shape.props.font}`,\n\t\t\t\t\tweight: 'normal',\n\t\t\t\t\tstyle: 'normal',\n\t\t\t\t})\n\n\t\tif (shape.props.textFirstEditedBy && !isEmptyRichText(shape.props.richText)) {\n\t\t\treturn [...fonts, DefaultFontFaces.tldraw_sans.normal.normal]\n\t\t}\n\t\tconst themeFaces = getThemeFontFaces(this.editor.getCurrentTheme(), shape.props.font)\n\t\tif (themeFaces) return [...themeFaces, ...fonts]\n\n\t\treturn fonts.length ? fonts : EMPTY_ARRAY\n\t}\n\n\tcomponent(shape: TLNoteShape) {\n\t\tconst { id, type, props } = shape\n\t\tconst { scale, richText, fontSizeAdjustment, textFirstEditedBy } = props\n\n\t\tconst handleKeyDown = useNoteKeydownHandler(id)\n\n\t\tconst rotation = useValue(\n\t\t\t'shape rotation',\n\t\t\t() => this.editor.getShapePageTransform(id)?.rotation() ?? 0,\n\t\t\t[this.editor]\n\t\t)\n\n\t\tconst colorMode = useColorMode()\n\t\tconst dv = getDisplayValues(this, shape, colorMode)\n\n\t\tconst nw = dv.noteWidth * scale\n\t\tconst nh = getNoteHeight(shape, dv.noteHeight)\n\n\t\t// Shadows are hidden when zoomed out far enough; the cheap borderBottom takes over.\n\t\tconst hideShadows = useEfficientZoomThreshold(0.25 / scale)\n\n\t\tconst isSelected = shape.id === this.editor.getOnlySelectedShapeId()\n\n\t\tconst isReadyForEditing = useIsReadyForEditing(this.editor, shape.id)\n\t\tconst isEmpty = isEmptyRichText(richText)\n\n\t\tconst attribution = useValue(\n\t\t\t'attribution',\n\t\t\t() => {\n\t\t\t\tif (!textFirstEditedBy || isEmpty) return null\n\t\t\t\tconst name = this.editor.getAttributionDisplayName(textFirstEditedBy)\n\t\t\t\tif (!name) return null\n\t\t\t\treturn { short: name.split(' ')[0], full: name }\n\t\t\t},\n\t\t\t[textFirstEditedBy, isEmpty, this.editor]\n\t\t)\n\n\t\treturn (\n\t\t\t<>\n\t\t\t\t<div\n\t\t\t\t\tid={id}\n\t\t\t\t\tclassName=\"tl-note__container\"\n\t\t\t\t\tstyle={{\n\t\t\t\t\t\twidth: nw,\n\t\t\t\t\t\theight: nh,\n\t\t\t\t\t\tbackgroundColor: dv.noteBackgroundColor,\n\t\t\t\t\t\tborderBottom: hideShadows\n\t\t\t\t\t\t\t? `${dv.borderWidth * scale}px solid ${dv.borderColor}`\n\t\t\t\t\t\t\t: 'none',\n\t\t\t\t\t\tboxShadow: hideShadows ? 'none' : getNoteShadow(shape.id, rotation, scale),\n\t\t\t\t\t}}\n\t\t\t\t>\n\t\t\t\t\t{attribution && (\n\t\t\t\t\t\t<TldrawUiTooltip content={attribution.full} side=\"bottom\">\n\t\t\t\t\t\t\t<div\n\t\t\t\t\t\t\t\tclassName=\"tl-note__attribution\"\n\t\t\t\t\t\t\t\tstyle={{\n\t\t\t\t\t\t\t\t\t['--note-attribution-scale' as string]: scale,\n\t\t\t\t\t\t\t\t\tfontSize: 11 * scale,\n\t\t\t\t\t\t\t\t\tcolor: dv.labelColor,\n\t\t\t\t\t\t\t\t\topacity: 0.6,\n\t\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t{attribution.short}\n\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t</TldrawUiTooltip>\n\t\t\t\t\t)}\n\t\t\t\t\t{(isSelected || isReadyForEditing || !isEmpty) && (\n\t\t\t\t\t\t<RichTextLabel\n\t\t\t\t\t\t\tshapeId={id}\n\t\t\t\t\t\t\ttype={type}\n\t\t\t\t\t\t\tfontFamily={dv.labelFontFamily}\n\t\t\t\t\t\t\tfontSize={(fontSizeAdjustment ?? 1) * dv.labelFontSize}\n\t\t\t\t\t\t\tlineHeight={dv.labelLineHeight}\n\t\t\t\t\t\t\ttextAlign={dv.labelHorizontalAlign}\n\t\t\t\t\t\t\tverticalAlign={dv.labelVerticalAlign}\n\t\t\t\t\t\t\trichText={richText}\n\t\t\t\t\t\t\tisSelected={isSelected}\n\t\t\t\t\t\t\tlabelColor={dv.labelColor}\n\t\t\t\t\t\t\twrap\n\t\t\t\t\t\t\tpadding={dv.labelPadding}\n\t\t\t\t\t\t\thasCustomTabBehavior\n\t\t\t\t\t\t\tshowTextOutline={false}\n\t\t\t\t\t\t\tonKeyDown={handleKeyDown}\n\t\t\t\t\t\t\tstyle={\n\t\t\t\t\t\t\t\tscale !== 1\n\t\t\t\t\t\t\t\t\t? {\n\t\t\t\t\t\t\t\t\t\t\ttransform: `scale(${scale})`,\n\t\t\t\t\t\t\t\t\t\t\ttransformOrigin: 'top left',\n\t\t\t\t\t\t\t\t\t\t\twidth: dv.noteWidth,\n\t\t\t\t\t\t\t\t\t\t\theight: dv.noteHeight + shape.props.growY,\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t: undefined\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t/>\n\t\t\t\t\t)}\n\t\t\t\t</div>\n\t\t\t\t{'url' in shape.props && shape.props.url && <HyperlinkButton url={shape.props.url} />}\n\t\t\t</>\n\t\t)\n\t}\n\n\toverride getIndicatorPath(shape: TLNoteShape): Path2D {\n\t\tconst { scale } = shape.props\n\t\tconst dv = getDisplayValues(this, shape)\n\t\tconst path = new Path2D()\n\t\tpath.rect(0, 0, dv.noteWidth * scale, getNoteHeight(shape, dv.noteHeight))\n\t\treturn path\n\t}\n\n\toverride toSvg(shape: TLNoteShape, ctx: SvgExportContext) {\n\t\tconst dv = getDisplayValues(this, shape, ctx.colorMode)\n\t\tconst bounds = new Box(0, 0, dv.noteWidth, dv.noteHeight + shape.props.growY)\n\n\t\tconst filterId = `note-shadow-${shape.id.replace(/:/g, '_')}` as SafeId\n\n\t\tctx.addExportDef({\n\t\t\tkey: filterId,\n\t\t\tgetElement: () => (\n\t\t\t\t<filter id={filterId} x=\"-10%\" y=\"-10%\" width=\"130%\" height=\"150%\">\n\t\t\t\t\t<feMorphology in=\"SourceAlpha\" operator=\"erode\" radius=\"3\" result=\"erode1\" />\n\t\t\t\t\t<feGaussianBlur in=\"erode1\" stdDeviation=\"3\" result=\"blur1\" />\n\t\t\t\t\t<feOffset in=\"blur1\" dy=\"3\" result=\"offsetBlur1\" />\n\t\t\t\t\t<feComponentTransfer in=\"offsetBlur1\" result=\"shadow1\">\n\t\t\t\t\t\t<feFuncA type=\"linear\" slope=\"0.5\" />\n\t\t\t\t\t</feComponentTransfer>\n\t\t\t\t\t<feMorphology in=\"SourceAlpha\" operator=\"erode\" radius=\"10\" result=\"erode2\" />\n\t\t\t\t\t<feGaussianBlur in=\"erode2\" stdDeviation=\"6\" result=\"blur2\" />\n\t\t\t\t\t<feOffset in=\"blur2\" dy=\"6\" result=\"offsetBlur2\" />\n\t\t\t\t\t<feComponentTransfer in=\"offsetBlur2\" result=\"shadow2\">\n\t\t\t\t\t\t<feFuncA type=\"linear\" slope=\"0.5\" />\n\t\t\t\t\t</feComponentTransfer>\n\t\t\t\t\t<feMerge>\n\t\t\t\t\t\t<feMergeNode in=\"shadow1\" />\n\t\t\t\t\t\t<feMergeNode in=\"shadow2\" />\n\t\t\t\t\t\t<feMergeNode in=\"SourceGraphic\" />\n\t\t\t\t\t</feMerge>\n\t\t\t\t</filter>\n\t\t\t),\n\t\t})\n\n\t\tconst { textFirstEditedBy } = shape.props\n\t\tconst attributionFirstName =\n\t\t\ttextFirstEditedBy && !isEmptyRichText(shape.props.richText)\n\t\t\t\t? this.editor.getAttributionDisplayName(textFirstEditedBy)?.split(' ')[0]\n\t\t\t\t: null\n\t\tconst attributionName = attributionFirstName\n\t\t\t? truncateAttributionForSvg(this.editor, attributionFirstName, dv.noteWidth)\n\t\t\t: null\n\n\t\treturn (\n\t\t\t<>\n\t\t\t\t{ctx.isDarkMode ? null : (\n\t\t\t\t\t<rect\n\t\t\t\t\t\trx={1}\n\t\t\t\t\t\twidth={dv.noteWidth}\n\t\t\t\t\t\theight={bounds.h}\n\t\t\t\t\t\tfill={dv.noteBackgroundColor}\n\t\t\t\t\t\tfilter={`url(#${filterId})`}\n\t\t\t\t\t/>\n\t\t\t\t)}\n\t\t\t\t<rect rx={1} width={dv.noteWidth} height={bounds.h} fill={dv.noteBackgroundColor} />\n\t\t\t\t<RichTextSVG\n\t\t\t\t\tfontSize={(shape.props.fontSizeAdjustment ?? 1) * dv.labelFontSize}\n\t\t\t\t\tfontFamily={dv.labelFontFamily}\n\t\t\t\t\tlineHeight={dv.labelLineHeight}\n\t\t\t\t\ttextAlign={dv.labelHorizontalAlign}\n\t\t\t\t\tverticalAlign={dv.labelVerticalAlign}\n\t\t\t\t\trichText={shape.props.richText}\n\t\t\t\t\tlabelColor={dv.labelColor}\n\t\t\t\t\tbounds={bounds}\n\t\t\t\t\tpadding={dv.labelPadding}\n\t\t\t\t\tshowTextOutline={false}\n\t\t\t\t/>\n\t\t\t\t{attributionName && (\n\t\t\t\t\t<text\n\t\t\t\t\t\tx={dv.noteWidth - 8}\n\t\t\t\t\t\ty={bounds.h - 6}\n\t\t\t\t\t\ttextAnchor=\"end\"\n\t\t\t\t\t\tfontFamily={DefaultFontFamilies['sans']}\n\t\t\t\t\t\tfontSize={11}\n\t\t\t\t\t\tfill={dv.labelColor}\n\t\t\t\t\t\topacity={0.6}\n\t\t\t\t\t>\n\t\t\t\t\t\t{attributionName}\n\t\t\t\t\t</text>\n\t\t\t\t)}\n\t\t\t</>\n\t\t)\n\t}\n\n\toverride onBeforeCreate(next: TLNoteShape) {\n\t\treturn this.getNoteSizeAdjustments(next)\n\t}\n\n\toverride onBeforeUpdate(prev: TLNoteShape, next: TLNoteShape) {\n\t\tconst richTextChanged = !isEqual(prev.props.richText, next.props.richText)\n\n\t\tif (\n\t\t\t!richTextChanged &&\n\t\t\tprev.props.font === next.props.font &&\n\t\t\tprev.props.size === next.props.size\n\t\t) {\n\t\t\treturn\n\t\t}\n\n\t\tlet shape = next\n\t\tif (richTextChanged) {\n\t\t\tif (isEmptyRichText(next.props.richText)) {\n\t\t\t\tshape = {\n\t\t\t\t\t...shape,\n\t\t\t\t\tprops: { ...shape.props, textFirstEditedBy: null },\n\t\t\t\t}\n\t\t\t} else if (!prev.props.textFirstEditedBy) {\n\t\t\t\tshape = {\n\t\t\t\t\t...shape,\n\t\t\t\t\tprops: { ...shape.props, textFirstEditedBy: this.editor.getAttributionUserId() },\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn this.getNoteSizeAdjustments(shape) ?? (richTextChanged ? shape : undefined)\n\t}\n\n\toverride getInterpolatedProps(\n\t\tstartShape: TLNoteShape,\n\t\tendShape: TLNoteShape,\n\t\tt: number\n\t): TLNoteShapeProps {\n\t\treturn {\n\t\t\t...(t > 0.5 ? endShape.props : startShape.props),\n\t\t\tscale: lerp(startShape.props.scale, endShape.props.scale, t),\n\t\t}\n\t}\n\n\t/**\n\t * Get the growY and fontSizeAdjustment for a shape.\n\t */\n\tprivate getNoteSizeAdjustments(shape: TLNoteShape) {\n\t\tconst dv = getDisplayValues(this, shape)\n\t\tconst { labelHeight, fontSizeAdjustment } = this.getLabelSize(shape)\n\t\t// When the label height is more than the height of the shape, we add extra height to it\n\t\tconst growY = Math.max(0, labelHeight - dv.noteHeight)\n\n\t\tif (growY !== shape.props.growY || fontSizeAdjustment !== shape.props.fontSizeAdjustment) {\n\t\t\treturn {\n\t\t\t\t...shape,\n\t\t\t\tprops: {\n\t\t\t\t\t...shape.props,\n\t\t\t\t\tgrowY,\n\t\t\t\t\tfontSizeAdjustment,\n\t\t\t\t},\n\t\t\t}\n\t\t}\n\n\t\treturn undefined\n\t}\n\n\tprivate _labelSizesForNoteCache = new WeakCache<\n\t\tTLShape,\n\t\t{ labelHeight: number; labelWidth: number; fontSizeAdjustment: number }\n\t>()\n\n\t/**\n\t * Get the cached label size for the shape.\n\t */\n\tprivate getLabelSize(shape: TLNoteShape) {\n\t\treturn this._labelSizesForNoteCache.get(shape, () => this.measureNoteLabelSize(shape))\n\t}\n\n\t/**\n\t * Expensively measure the label size for a note shape.\n\t */\n\tprivate measureNoteLabelSize(shape: TLNoteShape) {\n\t\tconst dv = getDisplayValues(this, shape)\n\t\tconst { richText } = shape.props\n\n\t\tif (isEmptyRichText(richText)) {\n\t\t\tconst minHeight = dv.labelFontSize * dv.labelLineHeight + dv.labelPadding * 2\n\t\t\treturn { labelHeight: minHeight, labelWidth: 100, fontSizeAdjustment: 1 }\n\t\t}\n\n\t\tconst unadjustedFontSize = dv.labelFontSize\n\n\t\tlet fontSizeAdjustment = unadjustedFontSize\n\t\tlet iterations = 0\n\t\tlet labelHeight = dv.noteHeight\n\t\tlet labelWidth = dv.noteWidth\n\n\t\t// N.B. For some note shapes with text like 'hjhjhjhjhjhjhjhj', you'll run into\n\t\t// some text measurement fuzziness where the browser swears there's no overflow (scrollWidth === width)\n\t\t// but really there is when you enable overflow-wrap again. This helps account for that little bit\n\t\t// of give.\n\t\tconst FUZZ = 1\n\n\t\t// We slightly make the font smaller if the text is too big for the note, width-wise.\n\t\tdo {\n\t\t\tfontSizeAdjustment = Math.min(unadjustedFontSize, unadjustedFontSize - iterations)\n\t\t\tconst html = renderHtmlFromRichTextForMeasurement(this.editor, richText)\n\t\t\tconst nextTextSize = this.editor.textMeasure.measureHtml(html, {\n\t\t\t\t...TEXT_PROPS,\n\t\t\t\tlineHeight: dv.labelLineHeight,\n\t\t\t\tfontFamily: dv.labelFontFamily,\n\t\t\t\tfontSize: fontSizeAdjustment,\n\t\t\t\tmaxWidth: dv.noteWidth - dv.labelPadding * 2 - FUZZ,\n\t\t\t\tdisableOverflowWrapBreaking: true,\n\t\t\t\tmeasureScrollWidth: true,\n\t\t\t})\n\n\t\t\tlabelHeight = nextTextSize.h + dv.labelPadding * 2\n\t\t\tlabelWidth = nextTextSize.w + dv.labelPadding * 2\n\n\t\t\tif (fontSizeAdjustment <= 14) {\n\t\t\t\t// Too small, just rely now on CSS `overflow-wrap: break-word`\n\t\t\t\t// We need to recalculate the text measurement here with break-word enabled.\n\t\t\t\tconst html = renderHtmlFromRichTextForMeasurement(this.editor, richText)\n\t\t\t\tconst nextTextSizeWithOverflowBreak = this.editor.textMeasure.measureHtml(html, {\n\t\t\t\t\t...TEXT_PROPS,\n\t\t\t\t\tlineHeight: dv.labelLineHeight,\n\t\t\t\t\tfontFamily: dv.labelFontFamily,\n\t\t\t\t\tfontSize: fontSizeAdjustment,\n\t\t\t\t\tmaxWidth: dv.noteWidth - dv.labelPadding * 2 - FUZZ,\n\t\t\t\t})\n\t\t\t\tlabelHeight = nextTextSizeWithOverflowBreak.h + dv.labelPadding * 2\n\t\t\t\tlabelWidth = nextTextSizeWithOverflowBreak.w + dv.labelPadding * 2\n\t\t\t\tbreak\n\t\t\t}\n\n\t\t\tif (nextTextSize.scrollWidth.toFixed(0) === nextTextSize.w.toFixed(0)) {\n\t\t\t\tbreak\n\t\t\t}\n\t\t} while (iterations++ < 50)\n\n\t\treturn {\n\t\t\tlabelHeight: labelHeight,\n\t\t\tlabelWidth: labelWidth,\n\t\t\tfontSizeAdjustment:\n\t\t\t\tfontSizeAdjustment === unadjustedFontSize ? 1 : fontSizeAdjustment / unadjustedFontSize,\n\t\t}\n\t}\n}\n\nfunction useNoteKeydownHandler(id: TLShapeId) {\n\tconst editor = useEditor()\n\t// Try to get the translation context, but fallback to ltr if it doesn't exist\n\tconst translation = useContext(TranslationsContext)\n\n\treturn useCallback(\n\t\t(e: KeyboardEvent) => {\n\t\t\tconst shape = editor.getShape<TLNoteShape>(id)\n\t\t\tif (!shape) return\n\n\t\t\tconst isTab = e.key === 'Tab'\n\t\t\tconst isCmdEnter = (e.metaKey || e.ctrlKey) && e.key === 'Enter'\n\t\t\tif (isTab || isCmdEnter) {\n\t\t\t\te.preventDefault()\n\n\t\t\t\tconst pageTransform = editor.getShapePageTransform(id)\n\t\t\t\tconst pageRotation = pageTransform.rotation()\n\n\t\t\t\t// Based on the inputs, calculate the offset to the next note\n\t\t\t\t// tab controls x axis (shift inverts direction set by RTL)\n\t\t\t\t// cmd enter is the y axis (shift inverts direction)\n\t\t\t\tconst isRTL = !!(\n\t\t\t\t\ttranslation?.dir === 'rtl' ||\n\t\t\t\t\t// todo: can we check a partial of the text, so that we don't have to render the whole thing?\n\t\t\t\t\tisRightToLeftLanguage(renderPlaintextFromRichText(editor, shape.props.richText))\n\t\t\t\t)\n\n\t\t\t\tconst noteUtil = editor.getShapeUtil(shape) as NoteShapeUtil\n\t\t\t\tconst dv = getDisplayValues(noteUtil, shape)\n\n\t\t\t\tconst noteOffset = isTab\n\t\t\t\t\t? dv.noteWidth + editor.options.adjacentShapeMargin\n\t\t\t\t\t: dv.noteHeight +\n\t\t\t\t\t\teditor.options.adjacentShapeMargin +\n\t\t\t\t\t\t// If we're growing down, we need to account for the current shape's growY\n\t\t\t\t\t\t(isCmdEnter && !e.shiftKey ? shape.props.growY : 0)\n\t\t\t\tconst offsetLength = noteOffset * shape.props.scale\n\n\t\t\t\tconst adjacentCenter = new Vec(\n\t\t\t\t\tisTab ? (e.shiftKey != isRTL ? -1 : 1) : 0,\n\t\t\t\t\tisCmdEnter ? (e.shiftKey ? -1 : 1) : 0\n\t\t\t\t)\n\t\t\t\t\t.mul(offsetLength)\n\t\t\t\t\t.add(new Vec(dv.noteWidth / 2, dv.noteHeight / 2).mul(shape.props.scale))\n\t\t\t\t\t.rot(pageRotation)\n\t\t\t\t\t.add(pageTransform.point())\n\n\t\t\t\tconst newNote = getNoteShapeForAdjacentPosition(editor, {\n\t\t\t\t\tshape,\n\t\t\t\t\tcenter: adjacentCenter,\n\t\t\t\t\tpageRotation,\n\t\t\t\t\tnoteWidth: dv.noteWidth,\n\t\t\t\t\tnoteHeight: dv.noteHeight,\n\t\t\t\t})\n\n\t\t\t\tif (newNote) {\n\t\t\t\t\tstartEditingShapeWithRichText(editor, newNote, { selectAll: true })\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\t\t[id, editor, translation?.dir]\n\t)\n}\n\nfunction getNoteHeight(shape: TLNoteShape, noteHeight: number) {\n\treturn (noteHeight + shape.props.growY) * shape.props.scale\n}\n\n// Matches `.tl-note__attribution { max-width: 60% }` so SVG export truncates the same way.\nconst ATTRIBUTION_MAX_WIDTH_RATIO = 0.6\n\nfunction truncateAttributionForSvg(editor: Editor, name: string, noteWidth: number) {\n\tif (process.env.NODE_ENV === 'test') return name\n\tconst spans = editor.textMeasure.measureTextSpans(name, {\n\t\tfontSize: 11,\n\t\tfontFamily: DefaultFontFamilies['sans'],\n\t\ttextAlign: 'end',\n\t\twidth: noteWidth * ATTRIBUTION_MAX_WIDTH_RATIO,\n\t\theight: 16,\n\t\tpadding: 0,\n\t\tlineHeight: 1,\n\t\tfontStyle: 'normal',\n\t\tfontWeight: 'normal',\n\t\toverflow: 'truncate-ellipsis',\n\t})\n\tif (spans.length === 0) return name\n\treturn spans.map((s) => s.text).join('')\n}\n\nfunction getNoteShadow(id: string, rotation: number, scale: number) {\n\tconst random = rng(id) // seeded based on id\n\tconst lift = Math.abs(random()) + 0.5 // 0 to 1.5\n\tconst oy = Math.cos(rotation)\n\tconst a = 5 * scale\n\tconst b = 4 * scale\n\tconst c = 6 * scale\n\tconst d = 7 * scale\n\t// Clamped so shadow never goes above the note at small scales (e.g. dynamic size mode at high zoom)\n\treturn `0px ${Math.max(0, a - lift)}px ${a}px -${a}px rgba(15, 23, 31, .6),\n\t0px ${(b + lift * d) * Math.max(0, oy)}px ${c + lift * d}px -${b + lift * c}px rgba(15, 23, 31, ${(0.3 + lift * 0.1).toFixed(2)}),\n\t0px ${48 * scale}px ${10 * scale}px -${10 * scale}px inset rgba(15, 23, 44, ${((0.022 + random() * 0.005) * ((1 + oy) / 2)).toFixed(2)})`\n}\n"],
|
|
5
|
-
"mappings": "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",
|
|
4
|
+
"sourcesContent": ["/* eslint-disable react-hooks/rules-of-hooks */\nimport {\n\tBox,\n\tDefaultFontFamilies,\n\tEMPTY_ARRAY,\n\tEditor,\n\tGroup2d,\n\tIndexKey,\n\tRectangle2d,\n\tSafeId,\n\tShapeUtil,\n\tSvgExportContext,\n\tTLHandle,\n\tTLNoteShape,\n\tTLNoteShapeProps,\n\tTLResizeInfo,\n\tTLShape,\n\tTLShapeId,\n\tVec,\n\tWeakCache,\n\texhaustiveSwitchError,\n\tgetColorValue,\n\tgetFontsFromRichText,\n\tisEqual,\n\tlerp,\n\tnoteShapeMigrations,\n\tnoteShapeProps,\n\tresizeScaled,\n\trng,\n\ttoRichText,\n\tuseColorMode,\n\tuseEditor,\n\tuseValue,\n} from '@tldraw/editor'\nimport { useCallback, useContext } from 'react'\nimport { startEditingShapeWithRichText } from '../../tools/SelectTool/selectHelpers'\nimport { TldrawUiTooltip } from '../../ui/components/primitives/TldrawUiTooltip'\nimport { TranslationsContext } from '../../ui/hooks/useTranslation/useTranslation'\nimport {\n\tisEditingRichTextList,\n\tisEmptyRichText,\n\trenderHtmlFromRichTextForMeasurement,\n\trenderPlaintextFromRichText,\n} from '../../utils/text/richText'\nimport { isRightToLeftLanguage } from '../../utils/text/text'\nimport {\n\tLABEL_FONT_SIZES,\n\tLABEL_PADDING,\n\tTEXT_PROPS,\n\tgetFontFamily,\n} from '../shared/default-shape-constants'\nimport { DefaultFontFaces, getThemeFontFaces } from '../shared/defaultFonts'\nimport { ShapeOptionsWithDisplayValues, getDisplayValues } from '../shared/getDisplayValues'\nimport { HyperlinkButton } from '../shared/HyperlinkButton'\nimport { RichTextLabel, RichTextSVG } from '../shared/RichTextLabel'\nimport { useIsReadyForEditing } from '../shared/useEditablePlainText'\nimport { useEfficientZoomThreshold } from '../shared/useEfficientZoomThreshold'\nimport { CLONE_HANDLE_MARGIN, getNoteShapeForAdjacentPosition } from './noteHelpers'\n\nconst NOTE_SHAPE_HORIZONTAL_ALIGNS = Object.freeze({\n\tstart: 'start',\n\tmiddle: 'center',\n\tend: 'end',\n\t'start-legacy': 'start',\n\t'end-legacy': 'end',\n\t'middle-legacy': 'center',\n} as const)\n\nconst NOTE_SHAPE_VERTICAL_ALIGNS = Object.freeze({\n\tstart: 'start',\n\tmiddle: 'middle',\n\tend: 'end',\n} as const)\n\n/** @public */\nexport interface NoteShapeUtilDisplayValues {\n\tnoteWidth: number\n\tnoteHeight: number\n\tnoteBackgroundColor: string\n\tborderColor: string\n\tborderWidth: number\n\tlabelColor: string\n\tlabelFontFamily: string\n\tlabelFontSize: number\n\tlabelLineHeight: number\n\tlabelFontWeight: string\n\tlabelFontVariant: string\n\tlabelFontStyle: string\n\tlabelPadding: number\n\tlabelHorizontalAlign: 'start' | 'center' | 'end'\n\tlabelVerticalAlign: 'start' | 'middle' | 'end'\n}\n\n/** @public */\nexport interface NoteShapeOptions extends ShapeOptionsWithDisplayValues<\n\tTLNoteShape,\n\tNoteShapeUtilDisplayValues\n> {\n\t/**\n\t * How should the note shape resize? By default it does not resize (except automatically based on its text content),\n\t * but you can set it to be user-resizable using scale.\n\t */\n\tresizeMode: 'none' | 'scale'\n}\n\n/** @public */\nexport class NoteShapeUtil extends ShapeUtil<TLNoteShape> {\n\tstatic override type = 'note' as const\n\tstatic override props = noteShapeProps\n\tstatic override migrations = noteShapeMigrations\n\n\toverride options: NoteShapeOptions = {\n\t\tresizeMode: 'none',\n\t\tgetDefaultDisplayValues(_editor, shape, theme, colorMode): NoteShapeUtilDisplayValues {\n\t\t\tconst { color, labelColor, font, size, align, verticalAlign } = shape.props\n\t\t\tconst colors = theme.colors[colorMode]\n\t\t\treturn {\n\t\t\t\tnoteWidth: 200,\n\t\t\t\tnoteHeight: 200,\n\t\t\t\tnoteBackgroundColor: getColorValue(colors, color, 'noteFill'),\n\t\t\t\tborderColor: colors.noteBorder,\n\t\t\t\tborderWidth: 2,\n\t\t\t\tlabelColor:\n\t\t\t\t\tlabelColor === 'black'\n\t\t\t\t\t\t? getColorValue(colors, color, 'noteText')\n\t\t\t\t\t\t: getColorValue(colors, labelColor, 'fill'),\n\t\t\t\tlabelFontFamily: getFontFamily(theme, font),\n\t\t\t\tlabelFontSize: theme.fontSize * LABEL_FONT_SIZES[size],\n\t\t\t\tlabelLineHeight: theme.lineHeight,\n\t\t\t\tlabelFontWeight: TEXT_PROPS.fontWeight,\n\t\t\t\tlabelFontVariant: TEXT_PROPS.fontVariant,\n\t\t\t\tlabelFontStyle: TEXT_PROPS.fontStyle,\n\t\t\t\tlabelPadding: LABEL_PADDING,\n\t\t\t\tlabelHorizontalAlign: NOTE_SHAPE_HORIZONTAL_ALIGNS[align],\n\t\t\t\tlabelVerticalAlign: NOTE_SHAPE_VERTICAL_ALIGNS[verticalAlign],\n\t\t\t}\n\t\t},\n\t\tgetCustomDisplayValues(): Partial<NoteShapeUtilDisplayValues> {\n\t\t\treturn {}\n\t\t},\n\t}\n\n\toverride canEdit(shape: TLNoteShape) {\n\t\treturn true\n\t}\n\toverride hideResizeHandles(shape: TLNoteShape) {\n\t\tconst { resizeMode } = this.options\n\t\tswitch (resizeMode) {\n\t\t\tcase 'none': {\n\t\t\t\treturn true\n\t\t\t}\n\t\t\tcase 'scale': {\n\t\t\t\treturn false\n\t\t\t}\n\t\t\tdefault: {\n\t\t\t\tthrow exhaustiveSwitchError(resizeMode)\n\t\t\t}\n\t\t}\n\t}\n\n\toverride isAspectRatioLocked(shape: TLNoteShape) {\n\t\treturn this.options.resizeMode === 'scale'\n\t}\n\n\toverride hideSelectionBoundsFg(shape: TLNoteShape) {\n\t\treturn false\n\t}\n\n\tgetDefaultProps(): TLNoteShape['props'] {\n\t\treturn {\n\t\t\tcolor: 'black',\n\t\t\trichText: toRichText(''),\n\t\t\tsize: 'm',\n\t\t\tfont: 'draw',\n\t\t\talign: 'middle',\n\t\t\tverticalAlign: 'middle',\n\t\t\tlabelColor: 'black',\n\t\t\tgrowY: 0,\n\t\t\tfontSizeAdjustment: 1,\n\t\t\turl: '',\n\t\t\tscale: 1,\n\t\t\ttextFirstEditedBy: null,\n\t\t}\n\t}\n\n\tgetGeometry(shape: TLNoteShape) {\n\t\tconst { labelHeight, labelWidth } = this.getLabelSize(shape)\n\t\tconst { scale } = shape.props\n\n\t\tconst dv = getDisplayValues(this, shape)\n\n\t\tconst lh = labelHeight * scale\n\t\tconst lw = labelWidth * scale\n\t\tconst nw = dv.noteWidth * scale\n\t\tconst nh = getNoteHeight(shape, dv.noteHeight)\n\n\t\treturn new Group2d({\n\t\t\tchildren: [\n\t\t\t\tnew Rectangle2d({ width: nw, height: nh, isFilled: true }),\n\t\t\t\tnew Rectangle2d({\n\t\t\t\t\tx:\n\t\t\t\t\t\tdv.labelHorizontalAlign === 'start'\n\t\t\t\t\t\t\t? 0\n\t\t\t\t\t\t\t: dv.labelHorizontalAlign === 'end'\n\t\t\t\t\t\t\t\t? nw - lw\n\t\t\t\t\t\t\t\t: (nw - lw) / 2,\n\t\t\t\t\ty:\n\t\t\t\t\t\tdv.labelVerticalAlign === 'start'\n\t\t\t\t\t\t\t? 0\n\t\t\t\t\t\t\t: dv.labelVerticalAlign === 'end'\n\t\t\t\t\t\t\t\t? nh - lh\n\t\t\t\t\t\t\t\t: (nh - lh) / 2,\n\t\t\t\t\twidth: lw,\n\t\t\t\t\theight: lh,\n\t\t\t\t\tisFilled: true,\n\t\t\t\t\tisLabel: true,\n\t\t\t\t\texcludeFromShapeBounds: true,\n\t\t\t\t}),\n\t\t\t],\n\t\t})\n\t}\n\n\toverride getHandles(shape: TLNoteShape): TLHandle[] {\n\t\tconst { scale } = shape.props\n\t\tconst isCoarsePointer = this.editor.getInstanceState().isCoarsePointer\n\t\tif (isCoarsePointer) return []\n\n\t\tconst zoom = this.editor.getEfficientZoomLevel()\n\t\tif (zoom * scale < 0.25) return []\n\n\t\tconst dv = getDisplayValues(this, shape)\n\t\tconst nh = getNoteHeight(shape, dv.noteHeight)\n\t\tconst nw = dv.noteWidth * scale\n\t\tconst offset = (CLONE_HANDLE_MARGIN / zoom) * scale\n\n\t\tif (zoom * scale < 0.5) {\n\t\t\treturn [\n\t\t\t\t{\n\t\t\t\t\tid: 'bottom',\n\t\t\t\t\tindex: 'a3' as IndexKey,\n\t\t\t\t\ttype: 'clone',\n\t\t\t\t\tx: nw / 2,\n\t\t\t\t\ty: nh + offset,\n\t\t\t\t},\n\t\t\t]\n\t\t}\n\n\t\treturn [\n\t\t\t{\n\t\t\t\tid: 'top',\n\t\t\t\tindex: 'a1' as IndexKey,\n\t\t\t\ttype: 'clone',\n\t\t\t\tx: nw / 2,\n\t\t\t\ty: -offset,\n\t\t\t},\n\t\t\t{\n\t\t\t\tid: 'right',\n\t\t\t\tindex: 'a2' as IndexKey,\n\t\t\t\ttype: 'clone',\n\t\t\t\tx: nw + offset,\n\t\t\t\ty: nh / 2,\n\t\t\t},\n\t\t\t{\n\t\t\t\tid: 'bottom',\n\t\t\t\tindex: 'a3' as IndexKey,\n\t\t\t\ttype: 'clone',\n\t\t\t\tx: nw / 2,\n\t\t\t\ty: nh + offset,\n\t\t\t},\n\t\t\t{\n\t\t\t\tid: 'left',\n\t\t\t\tindex: 'a4' as IndexKey,\n\t\t\t\ttype: 'clone',\n\t\t\t\tx: -offset,\n\t\t\t\ty: nh / 2,\n\t\t\t},\n\t\t]\n\t}\n\n\toverride onResize(shape: any, info: TLResizeInfo<any>) {\n\t\tconst { resizeMode } = this.options\n\t\tswitch (resizeMode) {\n\t\t\tcase 'none': {\n\t\t\t\treturn undefined\n\t\t\t}\n\t\t\tcase 'scale': {\n\t\t\t\treturn resizeScaled(shape, info)\n\t\t\t}\n\t\t\tdefault: {\n\t\t\t\tthrow exhaustiveSwitchError(resizeMode)\n\t\t\t}\n\t\t}\n\t}\n\n\toverride getText(shape: TLNoteShape) {\n\t\treturn renderPlaintextFromRichText(this.editor, shape.props.richText)\n\t}\n\n\toverride getReferencedUserIds(shape: TLNoteShape) {\n\t\treturn shape.props.textFirstEditedBy ? [shape.props.textFirstEditedBy] : []\n\t}\n\n\toverride getFontFaces(shape: TLNoteShape) {\n\t\tconst fonts = isEmptyRichText(shape.props.richText)\n\t\t\t? []\n\t\t\t: getFontsFromRichText(this.editor, shape.props.richText, {\n\t\t\t\t\tfamily: `tldraw_${shape.props.font}`,\n\t\t\t\t\tweight: 'normal',\n\t\t\t\t\tstyle: 'normal',\n\t\t\t\t})\n\n\t\tif (shape.props.textFirstEditedBy && !isEmptyRichText(shape.props.richText)) {\n\t\t\treturn [...fonts, DefaultFontFaces.tldraw_sans.normal.normal]\n\t\t}\n\t\tconst themeFaces = getThemeFontFaces(this.editor.getCurrentTheme(), shape.props.font)\n\t\tif (themeFaces) return [...themeFaces, ...fonts]\n\n\t\treturn fonts.length ? fonts : EMPTY_ARRAY\n\t}\n\n\tcomponent(shape: TLNoteShape) {\n\t\tconst { id, type, props } = shape\n\t\tconst { scale, richText, fontSizeAdjustment, textFirstEditedBy } = props\n\n\t\tconst handleKeyDown = useNoteKeydownHandler(id)\n\n\t\tconst rotation = useValue(\n\t\t\t'shape rotation',\n\t\t\t() => this.editor.getShapePageTransform(id)?.rotation() ?? 0,\n\t\t\t[this.editor]\n\t\t)\n\n\t\tconst colorMode = useColorMode()\n\t\tconst dv = getDisplayValues(this, shape, colorMode)\n\n\t\tconst nw = dv.noteWidth * scale\n\t\tconst nh = getNoteHeight(shape, dv.noteHeight)\n\n\t\t// Shadows are hidden when zoomed out far enough; the cheap borderBottom takes over.\n\t\tconst hideShadows = useEfficientZoomThreshold(0.25 / scale)\n\n\t\tconst isSelected = shape.id === this.editor.getOnlySelectedShapeId()\n\n\t\tconst isReadyForEditing = useIsReadyForEditing(this.editor, shape.id)\n\t\tconst isEmpty = isEmptyRichText(richText)\n\n\t\tconst attribution = useValue(\n\t\t\t'attribution',\n\t\t\t() => {\n\t\t\t\tif (!textFirstEditedBy || isEmpty) return null\n\t\t\t\tconst name = this.editor.getAttributionDisplayName(textFirstEditedBy)\n\t\t\t\tif (!name) return null\n\t\t\t\treturn { short: name.split(' ')[0], full: name }\n\t\t\t},\n\t\t\t[textFirstEditedBy, isEmpty, this.editor]\n\t\t)\n\n\t\treturn (\n\t\t\t<>\n\t\t\t\t<div\n\t\t\t\t\tid={id}\n\t\t\t\t\tclassName=\"tl-note__container\"\n\t\t\t\t\tstyle={{\n\t\t\t\t\t\twidth: nw,\n\t\t\t\t\t\theight: nh,\n\t\t\t\t\t\tbackgroundColor: dv.noteBackgroundColor,\n\t\t\t\t\t\tborderBottom: hideShadows\n\t\t\t\t\t\t\t? `${dv.borderWidth * scale}px solid ${dv.borderColor}`\n\t\t\t\t\t\t\t: 'none',\n\t\t\t\t\t\tboxShadow: hideShadows ? 'none' : getNoteShadow(shape.id, rotation, scale),\n\t\t\t\t\t}}\n\t\t\t\t>\n\t\t\t\t\t{attribution && (\n\t\t\t\t\t\t<TldrawUiTooltip content={attribution.full} side=\"bottom\">\n\t\t\t\t\t\t\t<div\n\t\t\t\t\t\t\t\tclassName=\"tl-note__attribution\"\n\t\t\t\t\t\t\t\tstyle={{\n\t\t\t\t\t\t\t\t\t['--note-attribution-scale' as string]: scale,\n\t\t\t\t\t\t\t\t\tfontSize: 11 * scale,\n\t\t\t\t\t\t\t\t\tcolor: dv.labelColor,\n\t\t\t\t\t\t\t\t\topacity: 0.6,\n\t\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t{attribution.short}\n\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t</TldrawUiTooltip>\n\t\t\t\t\t)}\n\t\t\t\t\t{(isSelected || isReadyForEditing || !isEmpty) && (\n\t\t\t\t\t\t<RichTextLabel\n\t\t\t\t\t\t\tshapeId={id}\n\t\t\t\t\t\t\ttype={type}\n\t\t\t\t\t\t\tfontFamily={dv.labelFontFamily}\n\t\t\t\t\t\t\tfontSize={(fontSizeAdjustment ?? 1) * dv.labelFontSize}\n\t\t\t\t\t\t\tlineHeight={dv.labelLineHeight}\n\t\t\t\t\t\t\ttextAlign={dv.labelHorizontalAlign}\n\t\t\t\t\t\t\tverticalAlign={dv.labelVerticalAlign}\n\t\t\t\t\t\t\trichText={richText}\n\t\t\t\t\t\t\tisSelected={isSelected}\n\t\t\t\t\t\t\tlabelColor={dv.labelColor}\n\t\t\t\t\t\t\twrap\n\t\t\t\t\t\t\tpadding={dv.labelPadding}\n\t\t\t\t\t\t\thasCustomTabBehavior\n\t\t\t\t\t\t\tshowTextOutline={false}\n\t\t\t\t\t\t\tonKeyDown={handleKeyDown}\n\t\t\t\t\t\t\tstyle={\n\t\t\t\t\t\t\t\tscale !== 1\n\t\t\t\t\t\t\t\t\t? {\n\t\t\t\t\t\t\t\t\t\t\ttransform: `scale(${scale})`,\n\t\t\t\t\t\t\t\t\t\t\ttransformOrigin: 'top left',\n\t\t\t\t\t\t\t\t\t\t\twidth: dv.noteWidth,\n\t\t\t\t\t\t\t\t\t\t\theight: dv.noteHeight + shape.props.growY,\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t: undefined\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t/>\n\t\t\t\t\t)}\n\t\t\t\t</div>\n\t\t\t\t{'url' in shape.props && shape.props.url && <HyperlinkButton url={shape.props.url} />}\n\t\t\t</>\n\t\t)\n\t}\n\n\toverride getIndicatorPath(shape: TLNoteShape): Path2D {\n\t\tconst { scale } = shape.props\n\t\tconst dv = getDisplayValues(this, shape)\n\t\tconst path = new Path2D()\n\t\tpath.rect(0, 0, dv.noteWidth * scale, getNoteHeight(shape, dv.noteHeight))\n\t\treturn path\n\t}\n\n\toverride toSvg(shape: TLNoteShape, ctx: SvgExportContext) {\n\t\tconst dv = getDisplayValues(this, shape, ctx.colorMode)\n\t\tconst bounds = new Box(0, 0, dv.noteWidth, dv.noteHeight + shape.props.growY)\n\n\t\tconst filterId = `note-shadow-${shape.id.replace(/:/g, '_')}` as SafeId\n\n\t\tctx.addExportDef({\n\t\t\tkey: filterId,\n\t\t\tgetElement: () => (\n\t\t\t\t<filter id={filterId} x=\"-10%\" y=\"-10%\" width=\"130%\" height=\"150%\">\n\t\t\t\t\t<feMorphology in=\"SourceAlpha\" operator=\"erode\" radius=\"3\" result=\"erode1\" />\n\t\t\t\t\t<feGaussianBlur in=\"erode1\" stdDeviation=\"3\" result=\"blur1\" />\n\t\t\t\t\t<feOffset in=\"blur1\" dy=\"3\" result=\"offsetBlur1\" />\n\t\t\t\t\t<feComponentTransfer in=\"offsetBlur1\" result=\"shadow1\">\n\t\t\t\t\t\t<feFuncA type=\"linear\" slope=\"0.5\" />\n\t\t\t\t\t</feComponentTransfer>\n\t\t\t\t\t<feMorphology in=\"SourceAlpha\" operator=\"erode\" radius=\"10\" result=\"erode2\" />\n\t\t\t\t\t<feGaussianBlur in=\"erode2\" stdDeviation=\"6\" result=\"blur2\" />\n\t\t\t\t\t<feOffset in=\"blur2\" dy=\"6\" result=\"offsetBlur2\" />\n\t\t\t\t\t<feComponentTransfer in=\"offsetBlur2\" result=\"shadow2\">\n\t\t\t\t\t\t<feFuncA type=\"linear\" slope=\"0.5\" />\n\t\t\t\t\t</feComponentTransfer>\n\t\t\t\t\t<feMerge>\n\t\t\t\t\t\t<feMergeNode in=\"shadow1\" />\n\t\t\t\t\t\t<feMergeNode in=\"shadow2\" />\n\t\t\t\t\t\t<feMergeNode in=\"SourceGraphic\" />\n\t\t\t\t\t</feMerge>\n\t\t\t\t</filter>\n\t\t\t),\n\t\t})\n\n\t\tconst { textFirstEditedBy } = shape.props\n\t\tconst attributionFirstName =\n\t\t\ttextFirstEditedBy && !isEmptyRichText(shape.props.richText)\n\t\t\t\t? this.editor.getAttributionDisplayName(textFirstEditedBy)?.split(' ')[0]\n\t\t\t\t: null\n\t\tconst attributionName = attributionFirstName\n\t\t\t? truncateAttributionForSvg(this.editor, attributionFirstName, dv.noteWidth)\n\t\t\t: null\n\n\t\treturn (\n\t\t\t<>\n\t\t\t\t{ctx.isDarkMode ? null : (\n\t\t\t\t\t<rect\n\t\t\t\t\t\trx={1}\n\t\t\t\t\t\twidth={dv.noteWidth}\n\t\t\t\t\t\theight={bounds.h}\n\t\t\t\t\t\tfill={dv.noteBackgroundColor}\n\t\t\t\t\t\tfilter={`url(#${filterId})`}\n\t\t\t\t\t/>\n\t\t\t\t)}\n\t\t\t\t<rect rx={1} width={dv.noteWidth} height={bounds.h} fill={dv.noteBackgroundColor} />\n\t\t\t\t<RichTextSVG\n\t\t\t\t\tfontSize={(shape.props.fontSizeAdjustment ?? 1) * dv.labelFontSize}\n\t\t\t\t\tfontFamily={dv.labelFontFamily}\n\t\t\t\t\tlineHeight={dv.labelLineHeight}\n\t\t\t\t\ttextAlign={dv.labelHorizontalAlign}\n\t\t\t\t\tverticalAlign={dv.labelVerticalAlign}\n\t\t\t\t\trichText={shape.props.richText}\n\t\t\t\t\tlabelColor={dv.labelColor}\n\t\t\t\t\tbounds={bounds}\n\t\t\t\t\tpadding={dv.labelPadding}\n\t\t\t\t\tshowTextOutline={false}\n\t\t\t\t/>\n\t\t\t\t{attributionName && (\n\t\t\t\t\t<text\n\t\t\t\t\t\tx={dv.noteWidth - 8}\n\t\t\t\t\t\ty={bounds.h - 6}\n\t\t\t\t\t\ttextAnchor=\"end\"\n\t\t\t\t\t\tfontFamily={DefaultFontFamilies['sans']}\n\t\t\t\t\t\tfontSize={11}\n\t\t\t\t\t\tfill={dv.labelColor}\n\t\t\t\t\t\topacity={0.6}\n\t\t\t\t\t>\n\t\t\t\t\t\t{attributionName}\n\t\t\t\t\t</text>\n\t\t\t\t)}\n\t\t\t</>\n\t\t)\n\t}\n\n\toverride onBeforeCreate(next: TLNoteShape) {\n\t\treturn this.getNoteSizeAdjustments(next)\n\t}\n\n\toverride onBeforeUpdate(prev: TLNoteShape, next: TLNoteShape) {\n\t\tconst richTextChanged = !isEqual(prev.props.richText, next.props.richText)\n\n\t\tif (\n\t\t\t!richTextChanged &&\n\t\t\tprev.props.font === next.props.font &&\n\t\t\tprev.props.size === next.props.size\n\t\t) {\n\t\t\treturn\n\t\t}\n\n\t\tlet shape = next\n\t\tif (richTextChanged) {\n\t\t\tif (isEmptyRichText(next.props.richText)) {\n\t\t\t\tshape = {\n\t\t\t\t\t...shape,\n\t\t\t\t\tprops: { ...shape.props, textFirstEditedBy: null },\n\t\t\t\t}\n\t\t\t} else if (!prev.props.textFirstEditedBy) {\n\t\t\t\tshape = {\n\t\t\t\t\t...shape,\n\t\t\t\t\tprops: { ...shape.props, textFirstEditedBy: this.editor.getAttributionUserId() },\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn this.getNoteSizeAdjustments(shape) ?? (richTextChanged ? shape : undefined)\n\t}\n\n\toverride getInterpolatedProps(\n\t\tstartShape: TLNoteShape,\n\t\tendShape: TLNoteShape,\n\t\tt: number\n\t): TLNoteShapeProps {\n\t\treturn {\n\t\t\t...(t > 0.5 ? endShape.props : startShape.props),\n\t\t\tscale: lerp(startShape.props.scale, endShape.props.scale, t),\n\t\t}\n\t}\n\n\t/**\n\t * Get the growY and fontSizeAdjustment for a shape.\n\t */\n\tprivate getNoteSizeAdjustments(shape: TLNoteShape) {\n\t\tconst dv = getDisplayValues(this, shape)\n\t\tconst { labelHeight, fontSizeAdjustment } = this.getLabelSize(shape)\n\t\t// When the label height is more than the height of the shape, we add extra height to it\n\t\tconst growY = Math.max(0, labelHeight - dv.noteHeight)\n\n\t\tif (growY !== shape.props.growY || fontSizeAdjustment !== shape.props.fontSizeAdjustment) {\n\t\t\treturn {\n\t\t\t\t...shape,\n\t\t\t\tprops: {\n\t\t\t\t\t...shape.props,\n\t\t\t\t\tgrowY,\n\t\t\t\t\tfontSizeAdjustment,\n\t\t\t\t},\n\t\t\t}\n\t\t}\n\n\t\treturn undefined\n\t}\n\n\tprivate _labelSizesForNoteCache = new WeakCache<\n\t\tTLShape,\n\t\t{ labelHeight: number; labelWidth: number; fontSizeAdjustment: number }\n\t>()\n\n\t/**\n\t * Get the cached label size for the shape.\n\t */\n\tprivate getLabelSize(shape: TLNoteShape) {\n\t\treturn this._labelSizesForNoteCache.get(shape, () => this.measureNoteLabelSize(shape))\n\t}\n\n\t/**\n\t * Expensively measure the label size for a note shape.\n\t */\n\tprivate measureNoteLabelSize(shape: TLNoteShape) {\n\t\tconst dv = getDisplayValues(this, shape)\n\t\tconst { richText } = shape.props\n\n\t\tif (isEmptyRichText(richText)) {\n\t\t\tconst minHeight = dv.labelFontSize * dv.labelLineHeight + dv.labelPadding * 2\n\t\t\treturn { labelHeight: minHeight, labelWidth: 100, fontSizeAdjustment: 1 }\n\t\t}\n\n\t\tconst unadjustedFontSize = dv.labelFontSize\n\n\t\tlet fontSizeAdjustment = unadjustedFontSize\n\t\tlet iterations = 0\n\t\tlet labelHeight = dv.noteHeight\n\t\tlet labelWidth = dv.noteWidth\n\n\t\t// N.B. For some note shapes with text like 'hjhjhjhjhjhjhjhj', you'll run into\n\t\t// some text measurement fuzziness where the browser swears there's no overflow (scrollWidth === width)\n\t\t// but really there is when you enable overflow-wrap again. This helps account for that little bit\n\t\t// of give.\n\t\tconst FUZZ = 1\n\n\t\t// We slightly make the font smaller if the text is too big for the note, width-wise.\n\t\tdo {\n\t\t\tfontSizeAdjustment = Math.min(unadjustedFontSize, unadjustedFontSize - iterations)\n\t\t\tconst html = renderHtmlFromRichTextForMeasurement(this.editor, richText)\n\t\t\tconst nextTextSize = this.editor.textMeasure.measureHtml(html, {\n\t\t\t\t...TEXT_PROPS,\n\t\t\t\tlineHeight: dv.labelLineHeight,\n\t\t\t\tfontFamily: dv.labelFontFamily,\n\t\t\t\tfontSize: fontSizeAdjustment,\n\t\t\t\tmaxWidth: dv.noteWidth - dv.labelPadding * 2 - FUZZ,\n\t\t\t\tdisableOverflowWrapBreaking: true,\n\t\t\t\tmeasureScrollWidth: true,\n\t\t\t})\n\n\t\t\tlabelHeight = nextTextSize.h + dv.labelPadding * 2\n\t\t\tlabelWidth = nextTextSize.w + dv.labelPadding * 2\n\n\t\t\tif (fontSizeAdjustment <= 14) {\n\t\t\t\t// Too small, just rely now on CSS `overflow-wrap: break-word`\n\t\t\t\t// We need to recalculate the text measurement here with break-word enabled.\n\t\t\t\tconst html = renderHtmlFromRichTextForMeasurement(this.editor, richText)\n\t\t\t\tconst nextTextSizeWithOverflowBreak = this.editor.textMeasure.measureHtml(html, {\n\t\t\t\t\t...TEXT_PROPS,\n\t\t\t\t\tlineHeight: dv.labelLineHeight,\n\t\t\t\t\tfontFamily: dv.labelFontFamily,\n\t\t\t\t\tfontSize: fontSizeAdjustment,\n\t\t\t\t\tmaxWidth: dv.noteWidth - dv.labelPadding * 2 - FUZZ,\n\t\t\t\t})\n\t\t\t\tlabelHeight = nextTextSizeWithOverflowBreak.h + dv.labelPadding * 2\n\t\t\t\tlabelWidth = nextTextSizeWithOverflowBreak.w + dv.labelPadding * 2\n\t\t\t\tbreak\n\t\t\t}\n\n\t\t\tif (nextTextSize.scrollWidth.toFixed(0) === nextTextSize.w.toFixed(0)) {\n\t\t\t\tbreak\n\t\t\t}\n\t\t} while (iterations++ < 50)\n\n\t\treturn {\n\t\t\tlabelHeight: labelHeight,\n\t\t\tlabelWidth: labelWidth,\n\t\t\tfontSizeAdjustment:\n\t\t\t\tfontSizeAdjustment === unadjustedFontSize ? 1 : fontSizeAdjustment / unadjustedFontSize,\n\t\t}\n\t}\n}\n\nfunction useNoteKeydownHandler(id: TLShapeId) {\n\tconst editor = useEditor()\n\t// Try to get the translation context, but fallback to ltr if it doesn't exist\n\tconst translation = useContext(TranslationsContext)\n\n\treturn useCallback(\n\t\t(e: KeyboardEvent) => {\n\t\t\tconst shape = editor.getShape<TLNoteShape>(id)\n\t\t\tif (!shape) return\n\n\t\t\tconst isTab = e.key === 'Tab'\n\t\t\tconst isCmdEnter = (e.metaKey || e.ctrlKey) && e.key === 'Enter'\n\n\t\t\tif (isTab && isEditingRichTextList(editor)) {\n\t\t\t\t// In a list, let the rich text editor indent the item instead of\n\t\t\t\t// creating a new note. Prevent default so Tab doesn't move focus out\n\t\t\t\t// of the editor when the item can't be indented (e.g. the first item).\n\t\t\t\te.preventDefault()\n\t\t\t\treturn\n\t\t\t}\n\n\t\t\tif (isTab || isCmdEnter) {\n\t\t\t\te.preventDefault()\n\n\t\t\t\tconst pageTransform = editor.getShapePageTransform(id)\n\t\t\t\tconst pageRotation = pageTransform.rotation()\n\n\t\t\t\t// Based on the inputs, calculate the offset to the next note\n\t\t\t\t// tab controls x axis (shift inverts direction set by RTL)\n\t\t\t\t// cmd enter is the y axis (shift inverts direction)\n\t\t\t\tconst isRTL = !!(\n\t\t\t\t\ttranslation?.dir === 'rtl' ||\n\t\t\t\t\t// todo: can we check a partial of the text, so that we don't have to render the whole thing?\n\t\t\t\t\tisRightToLeftLanguage(renderPlaintextFromRichText(editor, shape.props.richText))\n\t\t\t\t)\n\n\t\t\t\tconst noteUtil = editor.getShapeUtil(shape) as NoteShapeUtil\n\t\t\t\tconst dv = getDisplayValues(noteUtil, shape)\n\n\t\t\t\tconst noteOffset = isTab\n\t\t\t\t\t? dv.noteWidth + editor.options.adjacentShapeMargin\n\t\t\t\t\t: dv.noteHeight +\n\t\t\t\t\t\teditor.options.adjacentShapeMargin +\n\t\t\t\t\t\t// If we're growing down, we need to account for the current shape's growY\n\t\t\t\t\t\t(isCmdEnter && !e.shiftKey ? shape.props.growY : 0)\n\t\t\t\tconst offsetLength = noteOffset * shape.props.scale\n\n\t\t\t\tconst adjacentCenter = new Vec(\n\t\t\t\t\tisTab ? (e.shiftKey != isRTL ? -1 : 1) : 0,\n\t\t\t\t\tisCmdEnter ? (e.shiftKey ? -1 : 1) : 0\n\t\t\t\t)\n\t\t\t\t\t.mul(offsetLength)\n\t\t\t\t\t.add(new Vec(dv.noteWidth / 2, dv.noteHeight / 2).mul(shape.props.scale))\n\t\t\t\t\t.rot(pageRotation)\n\t\t\t\t\t.add(pageTransform.point())\n\n\t\t\t\tconst newNote = getNoteShapeForAdjacentPosition(editor, {\n\t\t\t\t\tshape,\n\t\t\t\t\tcenter: adjacentCenter,\n\t\t\t\t\tpageRotation,\n\t\t\t\t\tnoteWidth: dv.noteWidth,\n\t\t\t\t\tnoteHeight: dv.noteHeight,\n\t\t\t\t})\n\n\t\t\t\tif (newNote) {\n\t\t\t\t\tstartEditingShapeWithRichText(editor, newNote, { selectAll: true })\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\t\t[id, editor, translation?.dir]\n\t)\n}\n\nfunction getNoteHeight(shape: TLNoteShape, noteHeight: number) {\n\treturn (noteHeight + shape.props.growY) * shape.props.scale\n}\n\n// Matches `.tl-note__attribution { max-width: 60% }` so SVG export truncates the same way.\nconst ATTRIBUTION_MAX_WIDTH_RATIO = 0.6\n\nfunction truncateAttributionForSvg(editor: Editor, name: string, noteWidth: number) {\n\tif (process.env.NODE_ENV === 'test') return name\n\tconst spans = editor.textMeasure.measureTextSpans(name, {\n\t\tfontSize: 11,\n\t\tfontFamily: DefaultFontFamilies['sans'],\n\t\ttextAlign: 'end',\n\t\twidth: noteWidth * ATTRIBUTION_MAX_WIDTH_RATIO,\n\t\theight: 16,\n\t\tpadding: 0,\n\t\tlineHeight: 1,\n\t\tfontStyle: 'normal',\n\t\tfontWeight: 'normal',\n\t\toverflow: 'truncate-ellipsis',\n\t})\n\tif (spans.length === 0) return name\n\treturn spans.map((s) => s.text).join('')\n}\n\nfunction getNoteShadow(id: string, rotation: number, scale: number) {\n\tconst random = rng(id) // seeded based on id\n\tconst lift = Math.abs(random()) + 0.5 // 0 to 1.5\n\tconst oy = Math.cos(rotation)\n\tconst a = 5 * scale\n\tconst b = 4 * scale\n\tconst c = 6 * scale\n\tconst d = 7 * scale\n\t// Clamped so shadow never goes above the note at small scales (e.g. dynamic size mode at high zoom)\n\treturn `0px ${Math.max(0, a - lift)}px ${a}px -${a}px rgba(15, 23, 31, .6),\n\t0px ${(b + lift * d) * Math.max(0, oy)}px ${c + lift * d}px -${b + lift * c}px rgba(15, 23, 31, ${(0.3 + lift * 0.1).toFixed(2)}),\n\t0px ${48 * scale}px ${10 * scale}px -${10 * scale}px inset rgba(15, 23, 44, ${((0.022 + random() * 0.005) * ((1 + oy) / 2)).toFixed(2)})`\n}\n"],
|
|
5
|
+
"mappings": ";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAsWG;AArWH,oBAgCO;AACP,mBAAwC;AACxC,2BAA8C;AAC9C,6BAAgC;AAChC,4BAAoC;AACpC,sBAKO;AACP,kBAAsC;AACtC,qCAKO;AACP,0BAAoD;AACpD,8BAAgE;AAChE,6BAAgC;AAChC,2BAA2C;AAC3C,kCAAqC;AACrC,uCAA0C;AAC1C,yBAAqE;AAErE,MAAM,+BAA+B,OAAO,OAAO;AAAA,EAClD,OAAO;AAAA,EACP,QAAQ;AAAA,EACR,KAAK;AAAA,EACL,gBAAgB;AAAA,EAChB,cAAc;AAAA,EACd,iBAAiB;AAClB,CAAU;AAEV,MAAM,6BAA6B,OAAO,OAAO;AAAA,EAChD,OAAO;AAAA,EACP,QAAQ;AAAA,EACR,KAAK;AACN,CAAU;AAkCH,MAAM,sBAAsB,wBAAuB;AAAA,EACzD,OAAgB,OAAO;AAAA,EACvB,OAAgB,QAAQ;AAAA,EACxB,OAAgB,aAAa;AAAA,EAEpB,UAA4B;AAAA,IACpC,YAAY;AAAA,IACZ,wBAAwB,SAAS,OAAO,OAAO,WAAuC;AACrF,YAAM,EAAE,OAAO,YAAY,MAAM,MAAM,OAAO,cAAc,IAAI,MAAM;AACtE,YAAM,SAAS,MAAM,OAAO,SAAS;AACrC,aAAO;AAAA,QACN,WAAW;AAAA,QACX,YAAY;AAAA,QACZ,yBAAqB,6BAAc,QAAQ,OAAO,UAAU;AAAA,QAC5D,aAAa,OAAO;AAAA,QACpB,aAAa;AAAA,QACb,YACC,eAAe,cACZ,6BAAc,QAAQ,OAAO,UAAU,QACvC,6BAAc,QAAQ,YAAY,MAAM;AAAA,QAC5C,qBAAiB,8CAAc,OAAO,IAAI;AAAA,QAC1C,eAAe,MAAM,WAAW,gDAAiB,IAAI;AAAA,QACrD,iBAAiB,MAAM;AAAA,QACvB,iBAAiB,0CAAW;AAAA,QAC5B,kBAAkB,0CAAW;AAAA,QAC7B,gBAAgB,0CAAW;AAAA,QAC3B,cAAc;AAAA,QACd,sBAAsB,6BAA6B,KAAK;AAAA,QACxD,oBAAoB,2BAA2B,aAAa;AAAA,MAC7D;AAAA,IACD;AAAA,IACA,yBAA8D;AAC7D,aAAO,CAAC;AAAA,IACT;AAAA,EACD;AAAA,EAES,QAAQ,OAAoB;AACpC,WAAO;AAAA,EACR;AAAA,EACS,kBAAkB,OAAoB;AAC9C,UAAM,EAAE,WAAW,IAAI,KAAK;AAC5B,YAAQ,YAAY;AAAA,MACnB,KAAK,QAAQ;AACZ,eAAO;AAAA,MACR;AAAA,MACA,KAAK,SAAS;AACb,eAAO;AAAA,MACR;AAAA,MACA,SAAS;AACR,kBAAM,qCAAsB,UAAU;AAAA,MACvC;AAAA,IACD;AAAA,EACD;AAAA,EAES,oBAAoB,OAAoB;AAChD,WAAO,KAAK,QAAQ,eAAe;AAAA,EACpC;AAAA,EAES,sBAAsB,OAAoB;AAClD,WAAO;AAAA,EACR;AAAA,EAEA,kBAAwC;AACvC,WAAO;AAAA,MACN,OAAO;AAAA,MACP,cAAU,0BAAW,EAAE;AAAA,MACvB,MAAM;AAAA,MACN,MAAM;AAAA,MACN,OAAO;AAAA,MACP,eAAe;AAAA,MACf,YAAY;AAAA,MACZ,OAAO;AAAA,MACP,oBAAoB;AAAA,MACpB,KAAK;AAAA,MACL,OAAO;AAAA,MACP,mBAAmB;AAAA,IACpB;AAAA,EACD;AAAA,EAEA,YAAY,OAAoB;AAC/B,UAAM,EAAE,aAAa,WAAW,IAAI,KAAK,aAAa,KAAK;AAC3D,UAAM,EAAE,MAAM,IAAI,MAAM;AAExB,UAAM,SAAK,0CAAiB,MAAM,KAAK;AAEvC,UAAM,KAAK,cAAc;AACzB,UAAM,KAAK,aAAa;AACxB,UAAM,KAAK,GAAG,YAAY;AAC1B,UAAM,KAAK,cAAc,OAAO,GAAG,UAAU;AAE7C,WAAO,IAAI,sBAAQ;AAAA,MAClB,UAAU;AAAA,QACT,IAAI,0BAAY,EAAE,OAAO,IAAI,QAAQ,IAAI,UAAU,KAAK,CAAC;AAAA,QACzD,IAAI,0BAAY;AAAA,UACf,GACC,GAAG,yBAAyB,UACzB,IACA,GAAG,yBAAyB,QAC3B,KAAK,MACJ,KAAK,MAAM;AAAA,UACjB,GACC,GAAG,uBAAuB,UACvB,IACA,GAAG,uBAAuB,QACzB,KAAK,MACJ,KAAK,MAAM;AAAA,UACjB,OAAO;AAAA,UACP,QAAQ;AAAA,UACR,UAAU;AAAA,UACV,SAAS;AAAA,UACT,wBAAwB;AAAA,QACzB,CAAC;AAAA,MACF;AAAA,IACD,CAAC;AAAA,EACF;AAAA,EAES,WAAW,OAAgC;AACnD,UAAM,EAAE,MAAM,IAAI,MAAM;AACxB,UAAM,kBAAkB,KAAK,OAAO,iBAAiB,EAAE;AACvD,QAAI,gBAAiB,QAAO,CAAC;AAE7B,UAAM,OAAO,KAAK,OAAO,sBAAsB;AAC/C,QAAI,OAAO,QAAQ,KAAM,QAAO,CAAC;AAEjC,UAAM,SAAK,0CAAiB,MAAM,KAAK;AACvC,UAAM,KAAK,cAAc,OAAO,GAAG,UAAU;AAC7C,UAAM,KAAK,GAAG,YAAY;AAC1B,UAAM,SAAU,yCAAsB,OAAQ;AAE9C,QAAI,OAAO,QAAQ,KAAK;AACvB,aAAO;AAAA,QACN;AAAA,UACC,IAAI;AAAA,UACJ,OAAO;AAAA,UACP,MAAM;AAAA,UACN,GAAG,KAAK;AAAA,UACR,GAAG,KAAK;AAAA,QACT;AAAA,MACD;AAAA,IACD;AAEA,WAAO;AAAA,MACN;AAAA,QACC,IAAI;AAAA,QACJ,OAAO;AAAA,QACP,MAAM;AAAA,QACN,GAAG,KAAK;AAAA,QACR,GAAG,CAAC;AAAA,MACL;AAAA,MACA;AAAA,QACC,IAAI;AAAA,QACJ,OAAO;AAAA,QACP,MAAM;AAAA,QACN,GAAG,KAAK;AAAA,QACR,GAAG,KAAK;AAAA,MACT;AAAA,MACA;AAAA,QACC,IAAI;AAAA,QACJ,OAAO;AAAA,QACP,MAAM;AAAA,QACN,GAAG,KAAK;AAAA,QACR,GAAG,KAAK;AAAA,MACT;AAAA,MACA;AAAA,QACC,IAAI;AAAA,QACJ,OAAO;AAAA,QACP,MAAM;AAAA,QACN,GAAG,CAAC;AAAA,QACJ,GAAG,KAAK;AAAA,MACT;AAAA,IACD;AAAA,EACD;AAAA,EAES,SAAS,OAAY,MAAyB;AACtD,UAAM,EAAE,WAAW,IAAI,KAAK;AAC5B,YAAQ,YAAY;AAAA,MACnB,KAAK,QAAQ;AACZ,eAAO;AAAA,MACR;AAAA,MACA,KAAK,SAAS;AACb,mBAAO,4BAAa,OAAO,IAAI;AAAA,MAChC;AAAA,MACA,SAAS;AACR,kBAAM,qCAAsB,UAAU;AAAA,MACvC;AAAA,IACD;AAAA,EACD;AAAA,EAES,QAAQ,OAAoB;AACpC,eAAO,6CAA4B,KAAK,QAAQ,MAAM,MAAM,QAAQ;AAAA,EACrE;AAAA,EAES,qBAAqB,OAAoB;AACjD,WAAO,MAAM,MAAM,oBAAoB,CAAC,MAAM,MAAM,iBAAiB,IAAI,CAAC;AAAA,EAC3E;AAAA,EAES,aAAa,OAAoB;AACzC,UAAM,YAAQ,iCAAgB,MAAM,MAAM,QAAQ,IAC/C,CAAC,QACD,oCAAqB,KAAK,QAAQ,MAAM,MAAM,UAAU;AAAA,MACxD,QAAQ,UAAU,MAAM,MAAM,IAAI;AAAA,MAClC,QAAQ;AAAA,MACR,OAAO;AAAA,IACR,CAAC;AAEH,QAAI,MAAM,MAAM,qBAAqB,KAAC,iCAAgB,MAAM,MAAM,QAAQ,GAAG;AAC5E,aAAO,CAAC,GAAG,OAAO,qCAAiB,YAAY,OAAO,MAAM;AAAA,IAC7D;AACA,UAAM,iBAAa,uCAAkB,KAAK,OAAO,gBAAgB,GAAG,MAAM,MAAM,IAAI;AACpF,QAAI,WAAY,QAAO,CAAC,GAAG,YAAY,GAAG,KAAK;AAE/C,WAAO,MAAM,SAAS,QAAQ;AAAA,EAC/B;AAAA,EAEA,UAAU,OAAoB;AAC7B,UAAM,EAAE,IAAI,MAAM,MAAM,IAAI;AAC5B,UAAM,EAAE,OAAO,UAAU,oBAAoB,kBAAkB,IAAI;AAEnE,UAAM,gBAAgB,sBAAsB,EAAE;AAE9C,UAAM,eAAW;AAAA,MAChB;AAAA,MACA,MAAM,KAAK,OAAO,sBAAsB,EAAE,GAAG,SAAS,KAAK;AAAA,MAC3D,CAAC,KAAK,MAAM;AAAA,IACb;AAEA,UAAM,gBAAY,4BAAa;AAC/B,UAAM,SAAK,0CAAiB,MAAM,OAAO,SAAS;AAElD,UAAM,KAAK,GAAG,YAAY;AAC1B,UAAM,KAAK,cAAc,OAAO,GAAG,UAAU;AAG7C,UAAM,kBAAc,4DAA0B,OAAO,KAAK;AAE1D,UAAM,aAAa,MAAM,OAAO,KAAK,OAAO,uBAAuB;AAEnE,UAAM,wBAAoB,kDAAqB,KAAK,QAAQ,MAAM,EAAE;AACpE,UAAM,cAAU,iCAAgB,QAAQ;AAExC,UAAM,kBAAc;AAAA,MACnB;AAAA,MACA,MAAM;AACL,YAAI,CAAC,qBAAqB,QAAS,QAAO;AAC1C,cAAM,OAAO,KAAK,OAAO,0BAA0B,iBAAiB;AACpE,YAAI,CAAC,KAAM,QAAO;AAClB,eAAO,EAAE,OAAO,KAAK,MAAM,GAAG,EAAE,CAAC,GAAG,MAAM,KAAK;AAAA,MAChD;AAAA,MACA,CAAC,mBAAmB,SAAS,KAAK,MAAM;AAAA,IACzC;AAEA,WACC,4EACC;AAAA;AAAA,QAAC;AAAA;AAAA,UACA;AAAA,UACA,WAAU;AAAA,UACV,OAAO;AAAA,YACN,OAAO;AAAA,YACP,QAAQ;AAAA,YACR,iBAAiB,GAAG;AAAA,YACpB,cAAc,cACX,GAAG,GAAG,cAAc,KAAK,YAAY,GAAG,WAAW,KACnD;AAAA,YACH,WAAW,cAAc,SAAS,cAAc,MAAM,IAAI,UAAU,KAAK;AAAA,UAC1E;AAAA,UAEC;AAAA,2BACA,4CAAC,0CAAgB,SAAS,YAAY,MAAM,MAAK,UAChD;AAAA,cAAC;AAAA;AAAA,gBACA,WAAU;AAAA,gBACV,OAAO;AAAA,kBACN,CAAC,0BAAoC,GAAG;AAAA,kBACxC,UAAU,KAAK;AAAA,kBACf,OAAO,GAAG;AAAA,kBACV,SAAS;AAAA,gBACV;AAAA,gBAEC,sBAAY;AAAA;AAAA,YACd,GACD;AAAA,aAEC,cAAc,qBAAqB,CAAC,YACrC;AAAA,cAAC;AAAA;AAAA,gBACA,SAAS;AAAA,gBACT;AAAA,gBACA,YAAY,GAAG;AAAA,gBACf,WAAW,sBAAsB,KAAK,GAAG;AAAA,gBACzC,YAAY,GAAG;AAAA,gBACf,WAAW,GAAG;AAAA,gBACd,eAAe,GAAG;AAAA,gBAClB;AAAA,gBACA;AAAA,gBACA,YAAY,GAAG;AAAA,gBACf,MAAI;AAAA,gBACJ,SAAS,GAAG;AAAA,gBACZ,sBAAoB;AAAA,gBACpB,iBAAiB;AAAA,gBACjB,WAAW;AAAA,gBACX,OACC,UAAU,IACP;AAAA,kBACA,WAAW,SAAS,KAAK;AAAA,kBACzB,iBAAiB;AAAA,kBACjB,OAAO,GAAG;AAAA,kBACV,QAAQ,GAAG,aAAa,MAAM,MAAM;AAAA,gBACrC,IACC;AAAA;AAAA,YAEL;AAAA;AAAA;AAAA,MAEF;AAAA,MACC,SAAS,MAAM,SAAS,MAAM,MAAM,OAAO,4CAAC,0CAAgB,KAAK,MAAM,MAAM,KAAK;AAAA,OACpF;AAAA,EAEF;AAAA,EAES,iBAAiB,OAA4B;AACrD,UAAM,EAAE,MAAM,IAAI,MAAM;AACxB,UAAM,SAAK,0CAAiB,MAAM,KAAK;AACvC,UAAM,OAAO,IAAI,OAAO;AACxB,SAAK,KAAK,GAAG,GAAG,GAAG,YAAY,OAAO,cAAc,OAAO,GAAG,UAAU,CAAC;AACzE,WAAO;AAAA,EACR;AAAA,EAES,MAAM,OAAoB,KAAuB;AACzD,UAAM,SAAK,0CAAiB,MAAM,OAAO,IAAI,SAAS;AACtD,UAAM,SAAS,IAAI,kBAAI,GAAG,GAAG,GAAG,WAAW,GAAG,aAAa,MAAM,MAAM,KAAK;AAE5E,UAAM,WAAW,eAAe,MAAM,GAAG,QAAQ,MAAM,GAAG,CAAC;AAE3D,QAAI,aAAa;AAAA,MAChB,KAAK;AAAA,MACL,YAAY,MACX,6CAAC,YAAO,IAAI,UAAU,GAAE,QAAO,GAAE,QAAO,OAAM,QAAO,QAAO,QAC3D;AAAA,oDAAC,kBAAa,IAAG,eAAc,UAAS,SAAQ,QAAO,KAAI,QAAO,UAAS;AAAA,QAC3E,4CAAC,oBAAe,IAAG,UAAS,cAAa,KAAI,QAAO,SAAQ;AAAA,QAC5D,4CAAC,cAAS,IAAG,SAAQ,IAAG,KAAI,QAAO,eAAc;AAAA,QACjD,4CAAC,yBAAoB,IAAG,eAAc,QAAO,WAC5C,sDAAC,aAAQ,MAAK,UAAS,OAAM,OAAM,GACpC;AAAA,QACA,4CAAC,kBAAa,IAAG,eAAc,UAAS,SAAQ,QAAO,MAAK,QAAO,UAAS;AAAA,QAC5E,4CAAC,oBAAe,IAAG,UAAS,cAAa,KAAI,QAAO,SAAQ;AAAA,QAC5D,4CAAC,cAAS,IAAG,SAAQ,IAAG,KAAI,QAAO,eAAc;AAAA,QACjD,4CAAC,yBAAoB,IAAG,eAAc,QAAO,WAC5C,sDAAC,aAAQ,MAAK,UAAS,OAAM,OAAM,GACpC;AAAA,QACA,6CAAC,aACA;AAAA,sDAAC,iBAAY,IAAG,WAAU;AAAA,UAC1B,4CAAC,iBAAY,IAAG,WAAU;AAAA,UAC1B,4CAAC,iBAAY,IAAG,iBAAgB;AAAA,WACjC;AAAA,SACD;AAAA,IAEF,CAAC;AAED,UAAM,EAAE,kBAAkB,IAAI,MAAM;AACpC,UAAM,uBACL,qBAAqB,KAAC,iCAAgB,MAAM,MAAM,QAAQ,IACvD,KAAK,OAAO,0BAA0B,iBAAiB,GAAG,MAAM,GAAG,EAAE,CAAC,IACtE;AACJ,UAAM,kBAAkB,uBACrB,0BAA0B,KAAK,QAAQ,sBAAsB,GAAG,SAAS,IACzE;AAEH,WACC,4EACE;AAAA,UAAI,aAAa,OACjB;AAAA,QAAC;AAAA;AAAA,UACA,IAAI;AAAA,UACJ,OAAO,GAAG;AAAA,UACV,QAAQ,OAAO;AAAA,UACf,MAAM,GAAG;AAAA,UACT,QAAQ,QAAQ,QAAQ;AAAA;AAAA,MACzB;AAAA,MAED,4CAAC,UAAK,IAAI,GAAG,OAAO,GAAG,WAAW,QAAQ,OAAO,GAAG,MAAM,GAAG,qBAAqB;AAAA,MAClF;AAAA,QAAC;AAAA;AAAA,UACA,WAAW,MAAM,MAAM,sBAAsB,KAAK,GAAG;AAAA,UACrD,YAAY,GAAG;AAAA,UACf,YAAY,GAAG;AAAA,UACf,WAAW,GAAG;AAAA,UACd,eAAe,GAAG;AAAA,UAClB,UAAU,MAAM,MAAM;AAAA,UACtB,YAAY,GAAG;AAAA,UACf;AAAA,UACA,SAAS,GAAG;AAAA,UACZ,iBAAiB;AAAA;AAAA,MAClB;AAAA,MACC,mBACA;AAAA,QAAC;AAAA;AAAA,UACA,GAAG,GAAG,YAAY;AAAA,UAClB,GAAG,OAAO,IAAI;AAAA,UACd,YAAW;AAAA,UACX,YAAY,kCAAoB,MAAM;AAAA,UACtC,UAAU;AAAA,UACV,MAAM,GAAG;AAAA,UACT,SAAS;AAAA,UAER;AAAA;AAAA,MACF;AAAA,OAEF;AAAA,EAEF;AAAA,EAES,eAAe,MAAmB;AAC1C,WAAO,KAAK,uBAAuB,IAAI;AAAA,EACxC;AAAA,EAES,eAAe,MAAmB,MAAmB;AAC7D,UAAM,kBAAkB,KAAC,uBAAQ,KAAK,MAAM,UAAU,KAAK,MAAM,QAAQ;AAEzE,QACC,CAAC,mBACD,KAAK,MAAM,SAAS,KAAK,MAAM,QAC/B,KAAK,MAAM,SAAS,KAAK,MAAM,MAC9B;AACD;AAAA,IACD;AAEA,QAAI,QAAQ;AACZ,QAAI,iBAAiB;AACpB,cAAI,iCAAgB,KAAK,MAAM,QAAQ,GAAG;AACzC,gBAAQ;AAAA,UACP,GAAG;AAAA,UACH,OAAO,EAAE,GAAG,MAAM,OAAO,mBAAmB,KAAK;AAAA,QAClD;AAAA,MACD,WAAW,CAAC,KAAK,MAAM,mBAAmB;AACzC,gBAAQ;AAAA,UACP,GAAG;AAAA,UACH,OAAO,EAAE,GAAG,MAAM,OAAO,mBAAmB,KAAK,OAAO,qBAAqB,EAAE;AAAA,QAChF;AAAA,MACD;AAAA,IACD;AAEA,WAAO,KAAK,uBAAuB,KAAK,MAAM,kBAAkB,QAAQ;AAAA,EACzE;AAAA,EAES,qBACR,YACA,UACA,GACmB;AACnB,WAAO;AAAA,MACN,GAAI,IAAI,MAAM,SAAS,QAAQ,WAAW;AAAA,MAC1C,WAAO,oBAAK,WAAW,MAAM,OAAO,SAAS,MAAM,OAAO,CAAC;AAAA,IAC5D;AAAA,EACD;AAAA;AAAA;AAAA;AAAA,EAKQ,uBAAuB,OAAoB;AAClD,UAAM,SAAK,0CAAiB,MAAM,KAAK;AACvC,UAAM,EAAE,aAAa,mBAAmB,IAAI,KAAK,aAAa,KAAK;AAEnE,UAAM,QAAQ,KAAK,IAAI,GAAG,cAAc,GAAG,UAAU;AAErD,QAAI,UAAU,MAAM,MAAM,SAAS,uBAAuB,MAAM,MAAM,oBAAoB;AACzF,aAAO;AAAA,QACN,GAAG;AAAA,QACH,OAAO;AAAA,UACN,GAAG,MAAM;AAAA,UACT;AAAA,UACA;AAAA,QACD;AAAA,MACD;AAAA,IACD;AAEA,WAAO;AAAA,EACR;AAAA,EAEQ,0BAA0B,IAAI,wBAGpC;AAAA;AAAA;AAAA;AAAA,EAKM,aAAa,OAAoB;AACxC,WAAO,KAAK,wBAAwB,IAAI,OAAO,MAAM,KAAK,qBAAqB,KAAK,CAAC;AAAA,EACtF;AAAA;AAAA;AAAA;AAAA,EAKQ,qBAAqB,OAAoB;AAChD,UAAM,SAAK,0CAAiB,MAAM,KAAK;AACvC,UAAM,EAAE,SAAS,IAAI,MAAM;AAE3B,YAAI,iCAAgB,QAAQ,GAAG;AAC9B,YAAM,YAAY,GAAG,gBAAgB,GAAG,kBAAkB,GAAG,eAAe;AAC5E,aAAO,EAAE,aAAa,WAAW,YAAY,KAAK,oBAAoB,EAAE;AAAA,IACzE;AAEA,UAAM,qBAAqB,GAAG;AAE9B,QAAI,qBAAqB;AACzB,QAAI,aAAa;AACjB,QAAI,cAAc,GAAG;AACrB,QAAI,aAAa,GAAG;AAMpB,UAAM,OAAO;AAGb,OAAG;AACF,2BAAqB,KAAK,IAAI,oBAAoB,qBAAqB,UAAU;AACjF,YAAM,WAAO,sDAAqC,KAAK,QAAQ,QAAQ;AACvE,YAAM,eAAe,KAAK,OAAO,YAAY,YAAY,MAAM;AAAA,QAC9D,GAAG;AAAA,QACH,YAAY,GAAG;AAAA,QACf,YAAY,GAAG;AAAA,QACf,UAAU;AAAA,QACV,UAAU,GAAG,YAAY,GAAG,eAAe,IAAI;AAAA,QAC/C,6BAA6B;AAAA,QAC7B,oBAAoB;AAAA,MACrB,CAAC;AAED,oBAAc,aAAa,IAAI,GAAG,eAAe;AACjD,mBAAa,aAAa,IAAI,GAAG,eAAe;AAEhD,UAAI,sBAAsB,IAAI;AAG7B,cAAMA,YAAO,sDAAqC,KAAK,QAAQ,QAAQ;AACvE,cAAM,gCAAgC,KAAK,OAAO,YAAY,YAAYA,OAAM;AAAA,UAC/E,GAAG;AAAA,UACH,YAAY,GAAG;AAAA,UACf,YAAY,GAAG;AAAA,UACf,UAAU;AAAA,UACV,UAAU,GAAG,YAAY,GAAG,eAAe,IAAI;AAAA,QAChD,CAAC;AACD,sBAAc,8BAA8B,IAAI,GAAG,eAAe;AAClE,qBAAa,8BAA8B,IAAI,GAAG,eAAe;AACjE;AAAA,MACD;AAEA,UAAI,aAAa,YAAY,QAAQ,CAAC,MAAM,aAAa,EAAE,QAAQ,CAAC,GAAG;AACtE;AAAA,MACD;AAAA,IACD,SAAS,eAAe;AAExB,WAAO;AAAA,MACN;AAAA,MACA;AAAA,MACA,oBACC,uBAAuB,qBAAqB,IAAI,qBAAqB;AAAA,IACvE;AAAA,EACD;AACD;AAEA,SAAS,sBAAsB,IAAe;AAC7C,QAAM,aAAS,yBAAU;AAEzB,QAAM,kBAAc,yBAAW,yCAAmB;AAElD,aAAO;AAAA,IACN,CAAC,MAAqB;AACrB,YAAM,QAAQ,OAAO,SAAsB,EAAE;AAC7C,UAAI,CAAC,MAAO;AAEZ,YAAM,QAAQ,EAAE,QAAQ;AACxB,YAAM,cAAc,EAAE,WAAW,EAAE,YAAY,EAAE,QAAQ;AAEzD,UAAI,aAAS,uCAAsB,MAAM,GAAG;AAI3C,UAAE,eAAe;AACjB;AAAA,MACD;AAEA,UAAI,SAAS,YAAY;AACxB,UAAE,eAAe;AAEjB,cAAM,gBAAgB,OAAO,sBAAsB,EAAE;AACrD,cAAM,eAAe,cAAc,SAAS;AAK5C,cAAM,QAAQ,CAAC,EACd,aAAa,QAAQ;AAAA,YAErB,uCAAsB,6CAA4B,QAAQ,MAAM,MAAM,QAAQ,CAAC;AAGhF,cAAM,WAAW,OAAO,aAAa,KAAK;AAC1C,cAAM,SAAK,0CAAiB,UAAU,KAAK;AAE3C,cAAM,aAAa,QAChB,GAAG,YAAY,OAAO,QAAQ,sBAC9B,GAAG,aACJ,OAAO,QAAQ;AAAA,SAEd,cAAc,CAAC,EAAE,WAAW,MAAM,MAAM,QAAQ;AACnD,cAAM,eAAe,aAAa,MAAM,MAAM;AAE9C,cAAM,iBAAiB,IAAI;AAAA,UAC1B,QAAS,EAAE,YAAY,QAAQ,KAAK,IAAK;AAAA,UACzC,aAAc,EAAE,WAAW,KAAK,IAAK;AAAA,QACtC,EACE,IAAI,YAAY,EAChB,IAAI,IAAI,kBAAI,GAAG,YAAY,GAAG,GAAG,aAAa,CAAC,EAAE,IAAI,MAAM,MAAM,KAAK,CAAC,EACvE,IAAI,YAAY,EAChB,IAAI,cAAc,MAAM,CAAC;AAE3B,cAAM,cAAU,oDAAgC,QAAQ;AAAA,UACvD;AAAA,UACA,QAAQ;AAAA,UACR;AAAA,UACA,WAAW,GAAG;AAAA,UACd,YAAY,GAAG;AAAA,QAChB,CAAC;AAED,YAAI,SAAS;AACZ,kEAA8B,QAAQ,SAAS,EAAE,WAAW,KAAK,CAAC;AAAA,QACnE;AAAA,MACD;AAAA,IACD;AAAA,IACA,CAAC,IAAI,QAAQ,aAAa,GAAG;AAAA,EAC9B;AACD;AAEA,SAAS,cAAc,OAAoB,YAAoB;AAC9D,UAAQ,aAAa,MAAM,MAAM,SAAS,MAAM,MAAM;AACvD;AAGA,MAAM,8BAA8B;AAEpC,SAAS,0BAA0B,QAAgB,MAAc,WAAmB;AACnF,MAAI,QAAQ,IAAI,aAAa,OAAQ,QAAO;AAC5C,QAAM,QAAQ,OAAO,YAAY,iBAAiB,MAAM;AAAA,IACvD,UAAU;AAAA,IACV,YAAY,kCAAoB,MAAM;AAAA,IACtC,WAAW;AAAA,IACX,OAAO,YAAY;AAAA,IACnB,QAAQ;AAAA,IACR,SAAS;AAAA,IACT,YAAY;AAAA,IACZ,WAAW;AAAA,IACX,YAAY;AAAA,IACZ,UAAU;AAAA,EACX,CAAC;AACD,MAAI,MAAM,WAAW,EAAG,QAAO;AAC/B,SAAO,MAAM,IAAI,CAAC,MAAM,EAAE,IAAI,EAAE,KAAK,EAAE;AACxC;AAEA,SAAS,cAAc,IAAY,UAAkB,OAAe;AACnE,QAAM,aAAS,mBAAI,EAAE;AACrB,QAAM,OAAO,KAAK,IAAI,OAAO,CAAC,IAAI;AAClC,QAAM,KAAK,KAAK,IAAI,QAAQ;AAC5B,QAAM,IAAI,IAAI;AACd,QAAM,IAAI,IAAI;AACd,QAAM,IAAI,IAAI;AACd,QAAM,IAAI,IAAI;AAEd,SAAO,OAAO,KAAK,IAAI,GAAG,IAAI,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC;AAAA,QAC3C,IAAI,OAAO,KAAK,KAAK,IAAI,GAAG,EAAE,CAAC,MAAM,IAAI,OAAO,CAAC,OAAO,IAAI,OAAO,CAAC,wBAAwB,MAAM,OAAO,KAAK,QAAQ,CAAC,CAAC;AAAA,OACzH,KAAK,KAAK,MAAM,KAAK,KAAK,OAAO,KAAK,KAAK,+BAA+B,QAAQ,OAAO,IAAI,UAAW,IAAI,MAAM,IAAI,QAAQ,CAAC,CAAC;AACvI;",
|
|
6
6
|
"names": ["html"]
|
|
7
7
|
}
|
|
@@ -22,7 +22,7 @@ __export(interpolate_props_exports, {
|
|
|
22
22
|
});
|
|
23
23
|
module.exports = __toCommonJS(interpolate_props_exports);
|
|
24
24
|
var import_editor = require("@tldraw/editor");
|
|
25
|
-
|
|
25
|
+
function interpolateSegments(startSegments, endSegments, progress) {
|
|
26
26
|
const startPoints = [];
|
|
27
27
|
const endPoints = [];
|
|
28
28
|
startSegments.forEach((segment) => startPoints.push(...import_editor.b64Vecs.decodePoints(segment.path)));
|
|
@@ -51,5 +51,5 @@ const interpolateSegments = (startSegments, endSegments, progress) => {
|
|
|
51
51
|
path: import_editor.b64Vecs.encodePoints(interpolatedPoints)
|
|
52
52
|
}
|
|
53
53
|
];
|
|
54
|
-
}
|
|
54
|
+
}
|
|
55
55
|
//# sourceMappingURL=interpolate-props.js.map
|