tldraw 3.16.0-canary.faec5de49906 → 3.16.0-canary.fe4babe9c1ad

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.
Files changed (135) hide show
  1. package/dist-cjs/index.d.ts +7 -5
  2. package/dist-cjs/index.js +1 -1
  3. package/dist-cjs/lib/defaultExternalContentHandlers.js +10 -0
  4. package/dist-cjs/lib/defaultExternalContentHandlers.js.map +2 -2
  5. package/dist-cjs/lib/shapes/bookmark/BookmarkShapeUtil.js +4 -4
  6. package/dist-cjs/lib/shapes/bookmark/BookmarkShapeUtil.js.map +2 -2
  7. package/dist-cjs/lib/shapes/frame/components/FrameLabelInput.js +2 -2
  8. package/dist-cjs/lib/shapes/frame/components/FrameLabelInput.js.map +2 -2
  9. package/dist-cjs/lib/shapes/shared/HyperlinkButton.js +4 -4
  10. package/dist-cjs/lib/shapes/shared/HyperlinkButton.js.map +2 -2
  11. package/dist-cjs/lib/shapes/shared/useEditablePlainText.js +3 -2
  12. package/dist-cjs/lib/shapes/shared/useEditablePlainText.js.map +2 -2
  13. package/dist-cjs/lib/shapes/text/PlainTextArea.js +2 -2
  14. package/dist-cjs/lib/shapes/text/PlainTextArea.js.map +2 -2
  15. package/dist-cjs/lib/shapes/text/RichTextArea.js +3 -3
  16. package/dist-cjs/lib/shapes/text/RichTextArea.js.map +2 -2
  17. package/dist-cjs/lib/ui/components/A11y.js +1 -1
  18. package/dist-cjs/lib/ui/components/A11y.js.map +2 -2
  19. package/dist-cjs/lib/ui/components/LanguageMenu.js +1 -0
  20. package/dist-cjs/lib/ui/components/LanguageMenu.js.map +2 -2
  21. package/dist-cjs/lib/ui/components/Minimap/DefaultMinimap.js +1 -0
  22. package/dist-cjs/lib/ui/components/Minimap/DefaultMinimap.js.map +2 -2
  23. package/dist-cjs/lib/ui/components/PageMenu/DefaultPageMenu.js +1 -1
  24. package/dist-cjs/lib/ui/components/PageMenu/DefaultPageMenu.js.map +2 -2
  25. package/dist-cjs/lib/ui/components/StylePanel/StylePanelButtonPicker.js +11 -2
  26. package/dist-cjs/lib/ui/components/StylePanel/StylePanelButtonPicker.js.map +2 -2
  27. package/dist-cjs/lib/ui/components/Toolbar/AltTextEditor.js +3 -2
  28. package/dist-cjs/lib/ui/components/Toolbar/AltTextEditor.js.map +2 -2
  29. package/dist-cjs/lib/ui/components/Toolbar/LinkEditor.js +5 -4
  30. package/dist-cjs/lib/ui/components/Toolbar/LinkEditor.js.map +2 -2
  31. package/dist-cjs/lib/ui/components/Toolbar/OverflowingToolbar.js +1 -1
  32. package/dist-cjs/lib/ui/components/Toolbar/OverflowingToolbar.js.map +2 -2
  33. package/dist-cjs/lib/ui/components/Toolbar/ToggleToolLockedButton.js +6 -2
  34. package/dist-cjs/lib/ui/components/Toolbar/ToggleToolLockedButton.js.map +2 -2
  35. package/dist-cjs/lib/ui/components/primitives/TldrawUiContextualToolbar.js +1 -1
  36. package/dist-cjs/lib/ui/components/primitives/TldrawUiContextualToolbar.js.map +1 -1
  37. package/dist-cjs/lib/ui/components/primitives/TldrawUiInput.js +5 -3
  38. package/dist-cjs/lib/ui/components/primitives/TldrawUiInput.js.map +2 -2
  39. package/dist-cjs/lib/ui/components/primitives/TldrawUiToolbar.js +1 -0
  40. package/dist-cjs/lib/ui/components/primitives/TldrawUiToolbar.js.map +2 -2
  41. package/dist-cjs/lib/ui/components/primitives/TldrawUiTooltip.js +14 -2
  42. package/dist-cjs/lib/ui/components/primitives/TldrawUiTooltip.js.map +2 -2
  43. package/dist-cjs/lib/ui/components/primitives/menus/TldrawUiMenuCheckboxItem.js +3 -0
  44. package/dist-cjs/lib/ui/components/primitives/menus/TldrawUiMenuCheckboxItem.js.map +2 -2
  45. package/dist-cjs/lib/ui/context/actions.js +6 -0
  46. package/dist-cjs/lib/ui/context/actions.js.map +2 -2
  47. package/dist-cjs/lib/ui/hooks/useClipboardEvents.js +1 -1
  48. package/dist-cjs/lib/ui/hooks/useClipboardEvents.js.map +2 -2
  49. package/dist-cjs/lib/ui/hooks/useTranslation/TLUiTranslationKey.js.map +1 -1
  50. package/dist-cjs/lib/ui/hooks/useTranslation/defaultTranslation.js +2 -0
  51. package/dist-cjs/lib/ui/hooks/useTranslation/defaultTranslation.js.map +2 -2
  52. package/dist-cjs/lib/ui/version.js +3 -3
  53. package/dist-cjs/lib/ui/version.js.map +1 -1
  54. package/dist-esm/index.d.mts +7 -5
  55. package/dist-esm/index.mjs +1 -1
  56. package/dist-esm/lib/defaultExternalContentHandlers.mjs +10 -0
  57. package/dist-esm/lib/defaultExternalContentHandlers.mjs.map +2 -2
  58. package/dist-esm/lib/shapes/bookmark/BookmarkShapeUtil.mjs +5 -5
  59. package/dist-esm/lib/shapes/bookmark/BookmarkShapeUtil.mjs.map +2 -2
  60. package/dist-esm/lib/shapes/frame/components/FrameLabelInput.mjs +3 -3
  61. package/dist-esm/lib/shapes/frame/components/FrameLabelInput.mjs.map +2 -2
  62. package/dist-esm/lib/shapes/shared/HyperlinkButton.mjs +5 -5
  63. package/dist-esm/lib/shapes/shared/HyperlinkButton.mjs.map +2 -2
  64. package/dist-esm/lib/shapes/shared/useEditablePlainText.mjs +4 -3
  65. package/dist-esm/lib/shapes/shared/useEditablePlainText.mjs.map +2 -2
  66. package/dist-esm/lib/shapes/text/PlainTextArea.mjs +3 -3
  67. package/dist-esm/lib/shapes/text/PlainTextArea.mjs.map +2 -2
  68. package/dist-esm/lib/shapes/text/RichTextArea.mjs +3 -4
  69. package/dist-esm/lib/shapes/text/RichTextArea.mjs.map +2 -2
  70. package/dist-esm/lib/ui/components/A11y.mjs +2 -2
  71. package/dist-esm/lib/ui/components/A11y.mjs.map +2 -2
  72. package/dist-esm/lib/ui/components/LanguageMenu.mjs +1 -0
  73. package/dist-esm/lib/ui/components/LanguageMenu.mjs.map +2 -2
  74. package/dist-esm/lib/ui/components/Minimap/DefaultMinimap.mjs +1 -0
  75. package/dist-esm/lib/ui/components/Minimap/DefaultMinimap.mjs.map +2 -2
  76. package/dist-esm/lib/ui/components/PageMenu/DefaultPageMenu.mjs +2 -2
  77. package/dist-esm/lib/ui/components/PageMenu/DefaultPageMenu.mjs.map +2 -2
  78. package/dist-esm/lib/ui/components/StylePanel/StylePanelButtonPicker.mjs +11 -2
  79. package/dist-esm/lib/ui/components/StylePanel/StylePanelButtonPicker.mjs.map +2 -2
  80. package/dist-esm/lib/ui/components/Toolbar/AltTextEditor.mjs +3 -2
  81. package/dist-esm/lib/ui/components/Toolbar/AltTextEditor.mjs.map +2 -2
  82. package/dist-esm/lib/ui/components/Toolbar/LinkEditor.mjs +5 -4
  83. package/dist-esm/lib/ui/components/Toolbar/LinkEditor.mjs.map +2 -2
  84. package/dist-esm/lib/ui/components/Toolbar/OverflowingToolbar.mjs +1 -1
  85. package/dist-esm/lib/ui/components/Toolbar/OverflowingToolbar.mjs.map +2 -2
  86. package/dist-esm/lib/ui/components/Toolbar/ToggleToolLockedButton.mjs +6 -2
  87. package/dist-esm/lib/ui/components/Toolbar/ToggleToolLockedButton.mjs.map +2 -2
  88. package/dist-esm/lib/ui/components/primitives/TldrawUiContextualToolbar.mjs +2 -2
  89. package/dist-esm/lib/ui/components/primitives/TldrawUiContextualToolbar.mjs.map +1 -1
  90. package/dist-esm/lib/ui/components/primitives/TldrawUiInput.mjs +6 -4
  91. package/dist-esm/lib/ui/components/primitives/TldrawUiInput.mjs.map +2 -2
  92. package/dist-esm/lib/ui/components/primitives/TldrawUiToolbar.mjs +1 -0
  93. package/dist-esm/lib/ui/components/primitives/TldrawUiToolbar.mjs.map +2 -2
  94. package/dist-esm/lib/ui/components/primitives/TldrawUiTooltip.mjs +14 -2
  95. package/dist-esm/lib/ui/components/primitives/TldrawUiTooltip.mjs.map +2 -2
  96. package/dist-esm/lib/ui/components/primitives/menus/TldrawUiMenuCheckboxItem.mjs +3 -0
  97. package/dist-esm/lib/ui/components/primitives/menus/TldrawUiMenuCheckboxItem.mjs.map +2 -2
  98. package/dist-esm/lib/ui/context/actions.mjs +6 -0
  99. package/dist-esm/lib/ui/context/actions.mjs.map +2 -2
  100. package/dist-esm/lib/ui/hooks/useClipboardEvents.mjs +2 -2
  101. package/dist-esm/lib/ui/hooks/useClipboardEvents.mjs.map +2 -2
  102. package/dist-esm/lib/ui/hooks/useTranslation/defaultTranslation.mjs +2 -0
  103. package/dist-esm/lib/ui/hooks/useTranslation/defaultTranslation.mjs.map +2 -2
  104. package/dist-esm/lib/ui/version.mjs +3 -3
  105. package/dist-esm/lib/ui/version.mjs.map +1 -1
  106. package/package.json +3 -3
  107. package/src/lib/defaultExternalContentHandlers.ts +14 -0
  108. package/src/lib/shapes/arrow/ArrowShapeTool.test.ts +2 -2
  109. package/src/lib/shapes/bookmark/BookmarkShapeUtil.tsx +5 -5
  110. package/src/lib/shapes/frame/components/FrameLabelInput.tsx +3 -3
  111. package/src/lib/shapes/shared/HyperlinkButton.tsx +5 -5
  112. package/src/lib/shapes/shared/useEditablePlainText.ts +5 -3
  113. package/src/lib/shapes/text/PlainTextArea.tsx +3 -3
  114. package/src/lib/shapes/text/RichTextArea.tsx +3 -4
  115. package/src/lib/ui/components/A11y.tsx +2 -2
  116. package/src/lib/ui/components/LanguageMenu.tsx +1 -0
  117. package/src/lib/ui/components/Minimap/DefaultMinimap.tsx +1 -0
  118. package/src/lib/ui/components/PageMenu/DefaultPageMenu.tsx +2 -2
  119. package/src/lib/ui/components/StylePanel/StylePanelButtonPicker.tsx +9 -2
  120. package/src/lib/ui/components/Toolbar/AltTextEditor.tsx +4 -3
  121. package/src/lib/ui/components/Toolbar/LinkEditor.tsx +6 -5
  122. package/src/lib/ui/components/Toolbar/OverflowingToolbar.tsx +1 -1
  123. package/src/lib/ui/components/Toolbar/ToggleToolLockedButton.tsx +9 -2
  124. package/src/lib/ui/components/primitives/TldrawUiContextualToolbar.tsx +2 -2
  125. package/src/lib/ui/components/primitives/TldrawUiInput.tsx +6 -3
  126. package/src/lib/ui/components/primitives/TldrawUiToolbar.tsx +2 -1
  127. package/src/lib/ui/components/primitives/TldrawUiTooltip.tsx +16 -2
  128. package/src/lib/ui/components/primitives/menus/TldrawUiMenuCheckboxItem.tsx +4 -0
  129. package/src/lib/ui/context/actions.tsx +13 -0
  130. package/src/lib/ui/hooks/useClipboardEvents.ts +2 -2
  131. package/src/lib/ui/hooks/useTranslation/TLUiTranslationKey.ts +2 -0
  132. package/src/lib/ui/hooks/useTranslation/defaultTranslation.ts +2 -0
  133. package/src/lib/ui/version.ts +3 -3
  134. package/src/lib/ui.css +10 -0
  135. package/tldraw.css +10 -0
@@ -3185,7 +3185,7 @@ export declare function TldrawUiMenuActionCheckboxItem({ actionId, ...rest }: TL
3185
3185
  export declare function TldrawUiMenuActionItem({ actionId, ...rest }: TLUiMenuActionItemProps): JSX_2.Element | null;
3186
3186
 
3187
3187
  /** @public @react */
3188
- export declare function TldrawUiMenuCheckboxItem<TranslationKey extends string = string, IconType extends string = string>({ id, kbd, label, readonlyOk, onSelect, toggle, disabled, checked, }: TLUiMenuCheckboxItemProps<TranslationKey, IconType>): JSX_2.Element | null;
3188
+ export declare function TldrawUiMenuCheckboxItem<TranslationKey extends string = string, IconType extends string = string>({ id, kbd, label, lang, readonlyOk, onSelect, toggle, disabled, checked, }: TLUiMenuCheckboxItemProps<TranslationKey, IconType>): JSX_2.Element | null;
3189
3189
 
3190
3190
  /** @public @react */
3191
3191
  export declare function TldrawUiMenuContextProvider({ type, sourceId, children, }: TLUiMenuContextProviderProps): JSX_2.Element;
@@ -3897,6 +3897,7 @@ export declare interface TLUiInputProps {
3897
3897
  shouldManuallyMaintainScrollPositionWhenFocused?: boolean;
3898
3898
  value?: string;
3899
3899
  'data-testid'?: string;
3900
+ 'aria-label'?: string;
3900
3901
  }
3901
3902
 
3902
3903
  /** @public */
@@ -3941,6 +3942,7 @@ export declare interface TLUiMenuCheckboxItemProps<TranslationKey extends string
3941
3942
  label?: {
3942
3943
  [key: string]: TranslationKey;
3943
3944
  } | TranslationKey;
3945
+ lang?: string;
3944
3946
  readonlyOk?: boolean;
3945
3947
  onSelect(source: TLUiEventSource): Promise<void> | void;
3946
3948
  toggle?: boolean;
@@ -4177,7 +4179,7 @@ export declare interface TLUiToolbarToggleItemProps extends React_3.HTMLAttribut
4177
4179
  className?: string;
4178
4180
  type: 'icon' | 'tool';
4179
4181
  value: string;
4180
- tooltip?: string;
4182
+ tooltip?: React_3.ReactNode;
4181
4183
  }
4182
4184
 
4183
4185
  /** @public */
@@ -4223,7 +4225,7 @@ export declare interface TLUiTranslation {
4223
4225
  export declare type TLUiTranslationContextType = TLUiTranslation;
4224
4226
 
4225
4227
  /** @public */
4226
- export declare type TLUiTranslationKey = 'a11y.adjust-shape-styles' | 'a11y.enlarge-shape' | 'a11y.enter-leave-container' | 'a11y.move-shape-faster' | 'a11y.move-shape' | 'a11y.multiple-shapes' | 'a11y.open-context-menu' | 'a11y.open-keyboard-shortcuts' | 'a11y.pan-camera' | 'a11y.repeat-shape' | 'a11y.rotate-shape-ccw-fine' | 'a11y.rotate-shape-ccw' | 'a11y.rotate-shape-cw-fine' | 'a11y.rotate-shape-cw' | 'a11y.select-shape-direction' | 'a11y.select-shape' | 'a11y.shape-image' | 'a11y.shape-index' | 'a11y.shape-video' | 'a11y.shrink-shape' | 'a11y.skip-to-main-content' | 'a11y.status' | 'action.align-bottom' | 'action.align-center-horizontal.short' | 'action.align-center-horizontal' | 'action.align-center-vertical.short' | 'action.align-center-vertical' | 'action.align-left' | 'action.align-right' | 'action.align-top' | 'action.back-to-content' | 'action.bring-forward' | 'action.bring-to-front' | 'action.convert-to-bookmark' | 'action.convert-to-embed' | 'action.copy-as-png.short' | 'action.copy-as-png' | 'action.copy-as-svg.short' | 'action.copy-as-svg' | 'action.copy' | 'action.cut' | 'action.delete' | 'action.distribute-horizontal.short' | 'action.distribute-horizontal' | 'action.distribute-vertical.short' | 'action.distribute-vertical' | 'action.download-original' | 'action.duplicate' | 'action.edit-link' | 'action.exit-pen-mode' | 'action.export-all-as-png.short' | 'action.export-all-as-png' | 'action.export-all-as-svg.short' | 'action.export-all-as-svg' | 'action.export-as-png.short' | 'action.export-as-png' | 'action.export-as-svg.short' | 'action.export-as-svg' | 'action.fit-frame-to-content' | 'action.flatten-to-image' | 'action.flip-horizontal.short' | 'action.flip-horizontal' | 'action.flip-vertical.short' | 'action.flip-vertical' | 'action.fork-project-on-tldraw' | 'action.fork-project' | 'action.group' | 'action.insert-embed' | 'action.insert-media' | 'action.leave-shared-project' | 'action.new-project' | 'action.new-shared-project' | 'action.open-cursor-chat' | 'action.open-embed-link' | 'action.open-file' | 'action.open-kbd-shortcuts' | 'action.pack' | 'action.paste-error-description' | 'action.paste-error-title' | 'action.paste' | 'action.print' | 'action.redo' | 'action.remove-frame' | 'action.rename' | 'action.rotate-ccw' | 'action.rotate-cw' | 'action.save-copy' | 'action.select-all' | 'action.select-none' | 'action.send-backward' | 'action.send-to-back' | 'action.share-project' | 'action.stack-horizontal.short' | 'action.stack-horizontal' | 'action.stack-vertical.short' | 'action.stack-vertical' | 'action.stop-following' | 'action.stretch-horizontal.short' | 'action.stretch-horizontal' | 'action.stretch-vertical.short' | 'action.stretch-vertical' | 'action.toggle-auto-size' | 'action.toggle-dark-mode.menu' | 'action.toggle-dark-mode' | 'action.toggle-debug-mode.menu' | 'action.toggle-debug-mode' | 'action.toggle-dynamic-size-mode.menu' | 'action.toggle-dynamic-size-mode' | 'action.toggle-edge-scrolling.menu' | 'action.toggle-edge-scrolling' | 'action.toggle-focus-mode.menu' | 'action.toggle-focus-mode' | 'action.toggle-grid.menu' | 'action.toggle-grid' | 'action.toggle-keyboard-shortcuts.menu' | 'action.toggle-keyboard-shortcuts' | 'action.toggle-lock' | 'action.toggle-paste-at-cursor.menu' | 'action.toggle-paste-at-cursor' | 'action.toggle-reduce-motion.menu' | 'action.toggle-reduce-motion' | 'action.toggle-snap-mode.menu' | 'action.toggle-snap-mode' | 'action.toggle-tool-lock.menu' | 'action.toggle-tool-lock' | 'action.toggle-transparent.context-menu' | 'action.toggle-transparent.menu' | 'action.toggle-transparent' | 'action.toggle-ui-labels.menu' | 'action.toggle-ui-labels' | 'action.toggle-wrap-mode.menu' | 'action.toggle-wrap-mode' | 'action.undo' | 'action.ungroup' | 'action.unlock-all' | 'action.zoom-in' | 'action.zoom-out' | 'action.zoom-to-100' | 'action.zoom-to-fit' | 'action.zoom-to-selection' | 'actions-menu.title' | 'align-style.end' | 'align-style.justify' | 'align-style.middle' | 'align-style.start' | 'app.loading' | 'arrow-kind-style.arc' | 'arrow-kind-style.elbow' | 'arrowheadEnd-style.arrow' | 'arrowheadEnd-style.bar' | 'arrowheadEnd-style.diamond' | 'arrowheadEnd-style.dot' | 'arrowheadEnd-style.inverted' | 'arrowheadEnd-style.none' | 'arrowheadEnd-style.pipe' | 'arrowheadEnd-style.square' | 'arrowheadEnd-style.triangle' | 'arrowheadStart-style.arrow' | 'arrowheadStart-style.bar' | 'arrowheadStart-style.diamond' | 'arrowheadStart-style.dot' | 'arrowheadStart-style.inverted' | 'arrowheadStart-style.none' | 'arrowheadStart-style.pipe' | 'arrowheadStart-style.square' | 'arrowheadStart-style.triangle' | 'assets.files.amount-too-many' | 'assets.files.size-too-big' | 'assets.files.type-not-allowed' | 'assets.files.upload-failed' | 'assets.url.failed' | 'color-style.black' | 'color-style.blue' | 'color-style.green' | 'color-style.grey' | 'color-style.light-blue' | 'color-style.light-green' | 'color-style.light-red' | 'color-style.light-violet' | 'color-style.orange' | 'color-style.red' | 'color-style.violet' | 'color-style.white' | 'color-style.yellow' | 'context-menu.arrange' | 'context-menu.copy-as' | 'context-menu.edit' | 'context-menu.export-all-as' | 'context-menu.export-as' | 'context-menu.move-to-page' | 'context-menu.reorder' | 'context-menu.title' | 'context.pages.new-page' | 'cursor-chat.type-to-chat' | 'dash-style.dashed' | 'dash-style.dotted' | 'dash-style.draw' | 'dash-style.solid' | 'document-name-menu.copy-link' | 'document.default-name' | 'edit-link-dialog.cancel' | 'edit-link-dialog.clear' | 'edit-link-dialog.detail' | 'edit-link-dialog.external-link' | 'edit-link-dialog.invalid-url' | 'edit-link-dialog.save' | 'edit-link-dialog.title' | 'edit-link-dialog.url' | 'embed-dialog.back' | 'embed-dialog.cancel' | 'embed-dialog.create' | 'embed-dialog.instruction' | 'embed-dialog.invalid-url' | 'embed-dialog.title' | 'embed-dialog.url' | 'file-system.confirm-clear.cancel' | 'file-system.confirm-clear.continue' | 'file-system.confirm-clear.description' | 'file-system.confirm-clear.dont-show-again' | 'file-system.confirm-clear.title' | 'file-system.confirm-open.cancel' | 'file-system.confirm-open.description' | 'file-system.confirm-open.dont-show-again' | 'file-system.confirm-open.open' | 'file-system.confirm-open.title' | 'file-system.file-open-error.file-format-version-too-new' | 'file-system.file-open-error.generic-corrupted-file' | 'file-system.file-open-error.not-a-tldraw-file' | 'file-system.file-open-error.title' | 'file-system.shared-document-file-open-error.description' | 'file-system.shared-document-file-open-error.title' | 'fill-style.fill' | 'fill-style.none' | 'fill-style.pattern' | 'fill-style.semi' | 'fill-style.solid' | 'focus-mode.toggle-focus-mode' | 'font-style.draw' | 'font-style.mono' | 'font-style.sans' | 'font-style.serif' | 'geo-style.arrow-down' | 'geo-style.arrow-left' | 'geo-style.arrow-right' | 'geo-style.arrow-up' | 'geo-style.check-box' | 'geo-style.cloud' | 'geo-style.diamond' | 'geo-style.ellipse' | 'geo-style.heart' | 'geo-style.hexagon' | 'geo-style.octagon' | 'geo-style.oval' | 'geo-style.pentagon' | 'geo-style.rectangle' | 'geo-style.rhombus-2' | 'geo-style.rhombus' | 'geo-style.star' | 'geo-style.trapezoid' | 'geo-style.triangle' | 'geo-style.x-box' | 'handle.crop.bottom-left' | 'handle.crop.bottom-right' | 'handle.crop.bottom' | 'handle.crop.left' | 'handle.crop.right' | 'handle.crop.top-left' | 'handle.crop.top-right' | 'handle.crop.top' | 'handle.resize-bottom-left' | 'handle.resize-bottom-right' | 'handle.resize-bottom' | 'handle.resize-left' | 'handle.resize-right' | 'handle.resize-top-left' | 'handle.resize-top-right' | 'handle.resize-top' | 'handle.rotate.bottom_left_rotate' | 'handle.rotate.bottom_right_rotate' | 'handle.rotate.mobile_rotate' | 'handle.rotate.top_left_rotate' | 'handle.rotate.top_right_rotate' | 'help-menu.about' | 'help-menu.discord' | 'help-menu.github' | 'help-menu.import-tldr-file' | 'help-menu.keyboard-shortcuts' | 'help-menu.privacy' | 'help-menu.terms' | 'help-menu.title' | 'help-menu.twitter' | 'menu.accessibility' | 'menu.copy-as' | 'menu.edit' | 'menu.export-as' | 'menu.file' | 'menu.language' | 'menu.preferences' | 'menu.theme' | 'menu.title' | 'menu.view' | 'navigation-zone.minimap' | 'navigation-zone.title' | 'navigation-zone.toggle-minimap' | 'navigation-zone.zoom' | 'opacity-style.0.1' | 'opacity-style.0.25' | 'opacity-style.0.5' | 'opacity-style.0.75' | 'opacity-style.1' | 'page-menu.create-new-page' | 'page-menu.edit-done' | 'page-menu.edit-start' | 'page-menu.go-to-page' | 'page-menu.max-page-count-reached' | 'page-menu.new-page-initial-name' | 'page-menu.submenu.delete' | 'page-menu.submenu.duplicate-page' | 'page-menu.submenu.move-down' | 'page-menu.submenu.move-up' | 'page-menu.submenu.rename' | 'page-menu.submenu.title' | 'page-menu.title' | 'people-menu.anonymous-user' | 'people-menu.avatar-color' | 'people-menu.change-color' | 'people-menu.change-name' | 'people-menu.follow' | 'people-menu.following' | 'people-menu.invite' | 'people-menu.leading' | 'people-menu.title' | 'people-menu.user' | 'share-menu.copied' | 'share-menu.copy-link-note' | 'share-menu.copy-link' | 'share-menu.copy-readonly-link-note' | 'share-menu.copy-readonly-link' | 'share-menu.create-snapshot-link' | 'share-menu.creating-project' | 'share-menu.fork-note' | 'share-menu.offline-note' | 'share-menu.project-too-large' | 'share-menu.save-note' | 'share-menu.share-project' | 'share-menu.snapshot-link-note' | 'share-menu.title' | 'share-menu.upload-failed' | 'sharing.confirm-leave.cancel' | 'sharing.confirm-leave.description' | 'sharing.confirm-leave.dont-show-again' | 'sharing.confirm-leave.leave' | 'sharing.confirm-leave.title' | 'shortcuts-dialog.a11y' | 'shortcuts-dialog.collaboration' | 'shortcuts-dialog.edit' | 'shortcuts-dialog.file' | 'shortcuts-dialog.preferences' | 'shortcuts-dialog.text-formatting' | 'shortcuts-dialog.title' | 'shortcuts-dialog.tools' | 'shortcuts-dialog.transform' | 'shortcuts-dialog.view' | 'size-style.l' | 'size-style.m' | 'size-style.s' | 'size-style.xl' | 'spline-style.cubic' | 'spline-style.line' | 'status.offline' | 'style-panel.align' | 'style-panel.arrow-kind' | 'style-panel.arrowhead-end' | 'style-panel.arrowhead-start' | 'style-panel.arrowheads' | 'style-panel.color' | 'style-panel.dash' | 'style-panel.fill' | 'style-panel.font' | 'style-panel.geo' | 'style-panel.label-align' | 'style-panel.mixed' | 'style-panel.opacity' | 'style-panel.position' | 'style-panel.size' | 'style-panel.spline' | 'style-panel.title' | 'style-panel.vertical-align' | 'theme.dark' | 'theme.light' | 'theme.system' | 'toast.close' | 'toast.error.copy-fail.desc' | 'toast.error.copy-fail.title' | 'toast.error.export-fail.desc' | 'toast.error.export-fail.title' | 'toast.error' | 'toast.info' | 'toast.success' | 'toast.warning' | 'tool-panel.more' | 'tool-panel.title' | 'tool.arrow-down' | 'tool.arrow-left' | 'tool.arrow-right' | 'tool.arrow-up' | 'tool.arrow' | 'tool.aspect-ratio.circle' | 'tool.aspect-ratio.landscape' | 'tool.aspect-ratio.original' | 'tool.aspect-ratio.portrait' | 'tool.aspect-ratio.square' | 'tool.aspect-ratio.wide' | 'tool.aspect-ratio' | 'tool.bookmark' | 'tool.check-box' | 'tool.cloud' | 'tool.diamond' | 'tool.draw' | 'tool.ellipse' | 'tool.embed' | 'tool.eraser' | 'tool.flip-horz' | 'tool.flip-vert' | 'tool.frame' | 'tool.hand' | 'tool.heart' | 'tool.hexagon' | 'tool.highlight' | 'tool.image-crop-confirm' | 'tool.image-crop' | 'tool.image-toolbar-title' | 'tool.image-zoom' | 'tool.laser' | 'tool.line' | 'tool.media-alt-text-confirm' | 'tool.media-alt-text-desc' | 'tool.media-alt-text' | 'tool.media' | 'tool.note' | 'tool.octagon' | 'tool.oval' | 'tool.pentagon' | 'tool.pointer-down' | 'tool.rectangle' | 'tool.replace-media' | 'tool.rhombus' | 'tool.rich-text-bold' | 'tool.rich-text-bulletList' | 'tool.rich-text-code' | 'tool.rich-text-header' | 'tool.rich-text-highlight' | 'tool.rich-text-italic' | 'tool.rich-text-link-remove' | 'tool.rich-text-link-visit' | 'tool.rich-text-link' | 'tool.rich-text-orderedList' | 'tool.rich-text-strikethrough' | 'tool.rich-text-toolbar-title' | 'tool.rotate-cw' | 'tool.select' | 'tool.star' | 'tool.text' | 'tool.trapezoid' | 'tool.triangle' | 'tool.x-box' | 'ui.checked' | 'ui.close' | 'ui.unchecked' | 'verticalAlign-style.end' | 'verticalAlign-style.middle' | 'verticalAlign-style.start' | 'vscode.file-open.backup-failed' | 'vscode.file-open.backup-saved' | 'vscode.file-open.backup' | 'vscode.file-open.desc' | 'vscode.file-open.dont-show-again' | 'vscode.file-open.open';
4228
+ export declare type TLUiTranslationKey = 'a11y.adjust-shape-styles' | 'a11y.enlarge-shape' | 'a11y.enter-leave-container' | 'a11y.move-shape-faster' | 'a11y.move-shape' | 'a11y.multiple-shapes' | 'a11y.open-context-menu' | 'a11y.open-keyboard-shortcuts' | 'a11y.pan-camera' | 'a11y.repeat-shape' | 'a11y.rotate-shape-ccw-fine' | 'a11y.rotate-shape-ccw' | 'a11y.rotate-shape-cw-fine' | 'a11y.rotate-shape-cw' | 'a11y.select-shape-direction' | 'a11y.select-shape' | 'a11y.shape-image' | 'a11y.shape-index' | 'a11y.shape-video' | 'a11y.shrink-shape' | 'a11y.skip-to-main-content' | 'a11y.status' | 'action.align-bottom' | 'action.align-center-horizontal.short' | 'action.align-center-horizontal' | 'action.align-center-vertical.short' | 'action.align-center-vertical' | 'action.align-left' | 'action.align-right' | 'action.align-top' | 'action.back-to-content' | 'action.bring-forward' | 'action.bring-to-front' | 'action.convert-to-bookmark' | 'action.convert-to-embed' | 'action.copy-as-png.short' | 'action.copy-as-png' | 'action.copy-as-svg.short' | 'action.copy-as-svg' | 'action.copy' | 'action.cut' | 'action.delete' | 'action.distribute-horizontal.short' | 'action.distribute-horizontal' | 'action.distribute-vertical.short' | 'action.distribute-vertical' | 'action.download-original' | 'action.duplicate' | 'action.edit-link' | 'action.exit-pen-mode' | 'action.export-all-as-png.short' | 'action.export-all-as-png' | 'action.export-all-as-svg.short' | 'action.export-all-as-svg' | 'action.export-as-png.short' | 'action.export-as-png' | 'action.export-as-svg.short' | 'action.export-as-svg' | 'action.fit-frame-to-content' | 'action.flatten-to-image' | 'action.flip-horizontal.short' | 'action.flip-horizontal' | 'action.flip-vertical.short' | 'action.flip-vertical' | 'action.fork-project-on-tldraw' | 'action.fork-project' | 'action.group' | 'action.insert-embed' | 'action.insert-media' | 'action.leave-shared-project' | 'action.new-project' | 'action.new-shared-project' | 'action.open-cursor-chat' | 'action.open-embed-link' | 'action.open-file' | 'action.open-kbd-shortcuts' | 'action.pack' | 'action.paste-error-description' | 'action.paste-error-title' | 'action.paste' | 'action.print' | 'action.redo' | 'action.remove-frame' | 'action.rename' | 'action.rotate-ccw' | 'action.rotate-cw' | 'action.save-copy' | 'action.select-all' | 'action.select-none' | 'action.send-backward' | 'action.send-to-back' | 'action.share-project' | 'action.stack-horizontal.short' | 'action.stack-horizontal' | 'action.stack-vertical.short' | 'action.stack-vertical' | 'action.stop-following' | 'action.stretch-horizontal.short' | 'action.stretch-horizontal' | 'action.stretch-vertical.short' | 'action.stretch-vertical' | 'action.toggle-auto-size' | 'action.toggle-dark-mode.menu' | 'action.toggle-dark-mode' | 'action.toggle-debug-mode.menu' | 'action.toggle-debug-mode' | 'action.toggle-dynamic-size-mode.menu' | 'action.toggle-dynamic-size-mode' | 'action.toggle-edge-scrolling.menu' | 'action.toggle-edge-scrolling' | 'action.toggle-focus-mode.menu' | 'action.toggle-focus-mode' | 'action.toggle-grid.menu' | 'action.toggle-grid' | 'action.toggle-keyboard-shortcuts.menu' | 'action.toggle-keyboard-shortcuts' | 'action.toggle-lock' | 'action.toggle-paste-at-cursor.menu' | 'action.toggle-paste-at-cursor' | 'action.toggle-reduce-motion.menu' | 'action.toggle-reduce-motion' | 'action.toggle-snap-mode.menu' | 'action.toggle-snap-mode' | 'action.toggle-tool-lock.menu' | 'action.toggle-tool-lock' | 'action.toggle-transparent.context-menu' | 'action.toggle-transparent.menu' | 'action.toggle-transparent' | 'action.toggle-ui-labels.menu' | 'action.toggle-ui-labels' | 'action.toggle-wrap-mode.menu' | 'action.toggle-wrap-mode' | 'action.undo' | 'action.ungroup' | 'action.unlock-all' | 'action.zoom-in' | 'action.zoom-out' | 'action.zoom-to-100' | 'action.zoom-to-fit' | 'action.zoom-to-selection' | 'actions-menu.title' | 'align-style.end' | 'align-style.justify' | 'align-style.middle' | 'align-style.start' | 'app.loading' | 'arrow-kind-style.arc' | 'arrow-kind-style.elbow' | 'arrowheadEnd-style.arrow' | 'arrowheadEnd-style.bar' | 'arrowheadEnd-style.diamond' | 'arrowheadEnd-style.dot' | 'arrowheadEnd-style.inverted' | 'arrowheadEnd-style.none' | 'arrowheadEnd-style.pipe' | 'arrowheadEnd-style.square' | 'arrowheadEnd-style.triangle' | 'arrowheadStart-style.arrow' | 'arrowheadStart-style.bar' | 'arrowheadStart-style.diamond' | 'arrowheadStart-style.dot' | 'arrowheadStart-style.inverted' | 'arrowheadStart-style.none' | 'arrowheadStart-style.pipe' | 'arrowheadStart-style.square' | 'arrowheadStart-style.triangle' | 'assets.files.amount-too-many' | 'assets.files.maximum-size' | 'assets.files.size-too-big' | 'assets.files.type-not-allowed' | 'assets.files.upload-failed' | 'assets.url.failed' | 'color-style.black' | 'color-style.blue' | 'color-style.green' | 'color-style.grey' | 'color-style.light-blue' | 'color-style.light-green' | 'color-style.light-red' | 'color-style.light-violet' | 'color-style.orange' | 'color-style.red' | 'color-style.violet' | 'color-style.white' | 'color-style.yellow' | 'context-menu.arrange' | 'context-menu.copy-as' | 'context-menu.edit' | 'context-menu.export-all-as' | 'context-menu.export-as' | 'context-menu.move-to-page' | 'context-menu.reorder' | 'context-menu.title' | 'context.pages.new-page' | 'cursor-chat.type-to-chat' | 'dash-style.dashed' | 'dash-style.dotted' | 'dash-style.draw' | 'dash-style.solid' | 'document-name-menu.copy-link' | 'document.default-name' | 'edit-link-dialog.cancel' | 'edit-link-dialog.clear' | 'edit-link-dialog.detail' | 'edit-link-dialog.external-link' | 'edit-link-dialog.invalid-url' | 'edit-link-dialog.save' | 'edit-link-dialog.title' | 'edit-link-dialog.url' | 'embed-dialog.back' | 'embed-dialog.cancel' | 'embed-dialog.create' | 'embed-dialog.instruction' | 'embed-dialog.invalid-url' | 'embed-dialog.title' | 'embed-dialog.url' | 'file-system.confirm-clear.cancel' | 'file-system.confirm-clear.continue' | 'file-system.confirm-clear.description' | 'file-system.confirm-clear.dont-show-again' | 'file-system.confirm-clear.title' | 'file-system.confirm-open.cancel' | 'file-system.confirm-open.description' | 'file-system.confirm-open.dont-show-again' | 'file-system.confirm-open.open' | 'file-system.confirm-open.title' | 'file-system.file-open-error.file-format-version-too-new' | 'file-system.file-open-error.generic-corrupted-file' | 'file-system.file-open-error.not-a-tldraw-file' | 'file-system.file-open-error.title' | 'file-system.shared-document-file-open-error.description' | 'file-system.shared-document-file-open-error.title' | 'fill-style.fill' | 'fill-style.none' | 'fill-style.pattern' | 'fill-style.semi' | 'fill-style.solid' | 'focus-mode.toggle-focus-mode' | 'font-style.draw' | 'font-style.mono' | 'font-style.sans' | 'font-style.serif' | 'geo-style.arrow-down' | 'geo-style.arrow-left' | 'geo-style.arrow-right' | 'geo-style.arrow-up' | 'geo-style.check-box' | 'geo-style.cloud' | 'geo-style.diamond' | 'geo-style.ellipse' | 'geo-style.heart' | 'geo-style.hexagon' | 'geo-style.octagon' | 'geo-style.oval' | 'geo-style.pentagon' | 'geo-style.rectangle' | 'geo-style.rhombus-2' | 'geo-style.rhombus' | 'geo-style.star' | 'geo-style.trapezoid' | 'geo-style.triangle' | 'geo-style.x-box' | 'handle.crop.bottom-left' | 'handle.crop.bottom-right' | 'handle.crop.bottom' | 'handle.crop.left' | 'handle.crop.right' | 'handle.crop.top-left' | 'handle.crop.top-right' | 'handle.crop.top' | 'handle.resize-bottom-left' | 'handle.resize-bottom-right' | 'handle.resize-bottom' | 'handle.resize-left' | 'handle.resize-right' | 'handle.resize-top-left' | 'handle.resize-top-right' | 'handle.resize-top' | 'handle.rotate.bottom_left_rotate' | 'handle.rotate.bottom_right_rotate' | 'handle.rotate.mobile_rotate' | 'handle.rotate.top_left_rotate' | 'handle.rotate.top_right_rotate' | 'help-menu.about' | 'help-menu.discord' | 'help-menu.github' | 'help-menu.import-tldr-file' | 'help-menu.keyboard-shortcuts' | 'help-menu.privacy' | 'help-menu.terms' | 'help-menu.title' | 'help-menu.twitter' | 'menu.accessibility' | 'menu.copy-as' | 'menu.edit' | 'menu.export-as' | 'menu.file' | 'menu.language' | 'menu.preferences' | 'menu.theme' | 'menu.title' | 'menu.view' | 'navigation-zone.minimap' | 'navigation-zone.title' | 'navigation-zone.toggle-minimap' | 'navigation-zone.zoom' | 'opacity-style.0.1' | 'opacity-style.0.25' | 'opacity-style.0.5' | 'opacity-style.0.75' | 'opacity-style.1' | 'page-menu.create-new-page' | 'page-menu.edit-done' | 'page-menu.edit-start' | 'page-menu.go-to-page' | 'page-menu.max-page-count-reached' | 'page-menu.new-page-initial-name' | 'page-menu.submenu.delete' | 'page-menu.submenu.duplicate-page' | 'page-menu.submenu.move-down' | 'page-menu.submenu.move-up' | 'page-menu.submenu.rename' | 'page-menu.submenu.title' | 'page-menu.title' | 'people-menu.anonymous-user' | 'people-menu.avatar-color' | 'people-menu.change-color' | 'people-menu.change-name' | 'people-menu.follow' | 'people-menu.following' | 'people-menu.invite' | 'people-menu.leading' | 'people-menu.title' | 'people-menu.user' | 'share-menu.copied' | 'share-menu.copy-link-note' | 'share-menu.copy-link' | 'share-menu.copy-readonly-link-note' | 'share-menu.copy-readonly-link' | 'share-menu.create-snapshot-link' | 'share-menu.creating-project' | 'share-menu.fork-note' | 'share-menu.offline-note' | 'share-menu.project-too-large' | 'share-menu.save-note' | 'share-menu.share-project' | 'share-menu.snapshot-link-note' | 'share-menu.title' | 'share-menu.upload-failed' | 'sharing.confirm-leave.cancel' | 'sharing.confirm-leave.description' | 'sharing.confirm-leave.dont-show-again' | 'sharing.confirm-leave.leave' | 'sharing.confirm-leave.title' | 'shortcuts-dialog.a11y' | 'shortcuts-dialog.collaboration' | 'shortcuts-dialog.edit' | 'shortcuts-dialog.file' | 'shortcuts-dialog.preferences' | 'shortcuts-dialog.text-formatting' | 'shortcuts-dialog.title' | 'shortcuts-dialog.tools' | 'shortcuts-dialog.transform' | 'shortcuts-dialog.view' | 'size-style.l' | 'size-style.m' | 'size-style.s' | 'size-style.xl' | 'spline-style.cubic' | 'spline-style.line' | 'status.offline' | 'style-panel.align' | 'style-panel.arrow-kind' | 'style-panel.arrowhead-end' | 'style-panel.arrowhead-start' | 'style-panel.arrowheads' | 'style-panel.color' | 'style-panel.dash' | 'style-panel.fill' | 'style-panel.font' | 'style-panel.geo' | 'style-panel.label-align' | 'style-panel.mixed' | 'style-panel.opacity' | 'style-panel.position' | 'style-panel.selected' | 'style-panel.size' | 'style-panel.spline' | 'style-panel.title' | 'style-panel.vertical-align' | 'theme.dark' | 'theme.light' | 'theme.system' | 'toast.close' | 'toast.error.copy-fail.desc' | 'toast.error.copy-fail.title' | 'toast.error.export-fail.desc' | 'toast.error.export-fail.title' | 'toast.error' | 'toast.info' | 'toast.success' | 'toast.warning' | 'tool-panel.more' | 'tool-panel.title' | 'tool.arrow-down' | 'tool.arrow-left' | 'tool.arrow-right' | 'tool.arrow-up' | 'tool.arrow' | 'tool.aspect-ratio.circle' | 'tool.aspect-ratio.landscape' | 'tool.aspect-ratio.original' | 'tool.aspect-ratio.portrait' | 'tool.aspect-ratio.square' | 'tool.aspect-ratio.wide' | 'tool.aspect-ratio' | 'tool.bookmark' | 'tool.check-box' | 'tool.cloud' | 'tool.diamond' | 'tool.draw' | 'tool.ellipse' | 'tool.embed' | 'tool.eraser' | 'tool.flip-horz' | 'tool.flip-vert' | 'tool.frame' | 'tool.hand' | 'tool.heart' | 'tool.hexagon' | 'tool.highlight' | 'tool.image-crop-confirm' | 'tool.image-crop' | 'tool.image-toolbar-title' | 'tool.image-zoom' | 'tool.laser' | 'tool.line' | 'tool.media-alt-text-confirm' | 'tool.media-alt-text-desc' | 'tool.media-alt-text' | 'tool.media' | 'tool.note' | 'tool.octagon' | 'tool.oval' | 'tool.pentagon' | 'tool.pointer-down' | 'tool.rectangle' | 'tool.replace-media' | 'tool.rhombus' | 'tool.rich-text-bold' | 'tool.rich-text-bulletList' | 'tool.rich-text-code' | 'tool.rich-text-header' | 'tool.rich-text-highlight' | 'tool.rich-text-italic' | 'tool.rich-text-link-remove' | 'tool.rich-text-link-visit' | 'tool.rich-text-link' | 'tool.rich-text-orderedList' | 'tool.rich-text-strikethrough' | 'tool.rich-text-toolbar-title' | 'tool.rotate-cw' | 'tool.select' | 'tool.star' | 'tool.text' | 'tool.trapezoid' | 'tool.triangle' | 'tool.x-box' | 'ui.checked' | 'ui.close' | 'ui.unchecked' | 'verticalAlign-style.end' | 'verticalAlign-style.middle' | 'verticalAlign-style.start' | 'vscode.file-open.backup-failed' | 'vscode.file-open.backup-saved' | 'vscode.file-open.backup' | 'vscode.file-open.desc' | 'vscode.file-open.dont-show-again' | 'vscode.file-open.open';
4227
4229
 
4228
4230
  /** @public */
4229
4231
  export declare interface TLUiTranslationProviderProps {
@@ -4485,7 +4487,7 @@ export declare function useEditablePlainText(shapeId: TLShapeId, type: string, t
4485
4487
  handleChange: ({ plaintext }: {
4486
4488
  plaintext: string;
4487
4489
  }) => void;
4488
- handleDoubleClick: (e: any) => any;
4490
+ handleDoubleClick: (e: React_3.MouseEvent) => void;
4489
4491
  handleFocus: () => void;
4490
4492
  handleInputPointerDown: (e: React_3.PointerEvent) => void;
4491
4493
  handleKeyDown: (e: KeyboardEvent) => void;
@@ -4502,7 +4504,7 @@ export declare function useEditableRichText(shapeId: TLShapeId, type: string, ri
4502
4504
  handleChange: ({ richText }: {
4503
4505
  richText: TLRichText;
4504
4506
  }) => void;
4505
- handleDoubleClick: (e: any) => any;
4507
+ handleDoubleClick: (e: React.MouseEvent) => void;
4506
4508
  handleFocus: () => void;
4507
4509
  handleInputPointerDown: (e: React.PointerEvent) => void;
4508
4510
  handleKeyDown: (e: KeyboardEvent) => void;
@@ -524,7 +524,7 @@ import {
524
524
  } from "./lib/utils/tldr/file.mjs";
525
525
  registerTldrawLibraryVersion(
526
526
  "tldraw",
527
- "3.16.0-canary.faec5de49906",
527
+ "3.16.0-canary.fe4babe9c1ad",
528
528
  "esm"
529
529
  );
530
530
  export {
@@ -563,8 +563,18 @@ function notifyIfFileNotAllowed(file, options) {
563
563
  return false;
564
564
  }
565
565
  if (file.size > maxAssetSize) {
566
+ const formatBytes = (bytes) => {
567
+ if (bytes === 0) return "0 bytes";
568
+ const units = ["bytes", "KB", "MB", "GB", "TB", "PB"];
569
+ const base = 1024;
570
+ const unitIndex = Math.floor(Math.log(bytes) / Math.log(base));
571
+ const value = bytes / Math.pow(base, unitIndex);
572
+ const formatted = value % 1 === 0 ? value.toString() : value.toFixed(1);
573
+ return `${formatted} ${units[unitIndex]}`;
574
+ };
566
575
  toasts.addToast({
567
576
  title: msg("assets.files.size-too-big"),
577
+ description: msg("assets.files.maximum-size").replace("{size}", formatBytes(maxAssetSize)),
568
578
  severity: "error"
569
579
  });
570
580
  return false;
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../src/lib/defaultExternalContentHandlers.ts"],
4
- "sourcesContent": ["import {\n\tAssetRecordType,\n\tDEFAULT_SUPPORTED_IMAGE_TYPES,\n\tDEFAULT_SUPPORT_VIDEO_TYPES,\n\tEditor,\n\tMediaHelpers,\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\tTLVideoShape,\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 { EmbedShapeUtil } from './shapes/embed/EmbedShapeUtil'\nimport { getCroppedImageDataForReplacedImage } from './shapes/shared/crop'\nimport { FONT_FAMILIES, FONT_SIZES, TEXT_PROPS } from './shapes/shared/default-shape-constants'\nimport { TLUiToastsContextType } from './ui/context/toasts'\nimport { useTranslation } from './ui/hooks/useTranslation/useTranslation'\nimport { containBoxSize } from './utils/assets/assets'\nimport { putExcalidrawContent } from './utils/excalidraw/putExcalidrawContent'\nimport { 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. Defaults to\n\t * DEFAULT_SUPPORTED_IMAGE_TYPES.\n\t */\n\tacceptedImageMimeTypes?: readonly string[]\n\t/**\n\t * The mime types of videos that are allowed to be handled. Defaults to\n\t * DEFAULT_SUPPORT_VIDEO_TYPES.\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(file, options)\n\tif (!isSuccess) assert(false, 'File checks failed')\n\n\tconst assetInfo = await getAssetInfo(file, options, assetId)\n\tconst result = await editor.uploadAsset(assetInfo, file)\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, isImage }: TLFileReplaceExternalContent,\n\toptions: TLDefaultExternalContentHandlerOpts\n) {\n\tconst isSuccess = notifyIfFileNotAllowed(file, options)\n\tif (!isSuccess) assert(false, 'File checks failed')\n\n\tconst shape = editor.getShape(shapeId)\n\tif (!shape) assert(false, 'Shape not found')\n\n\tconst hash = getHashForBuffer(await file.arrayBuffer())\n\tconst assetId = AssetRecordType.createId(hash)\n\teditor.createTemporaryAssetPreview(assetId, file)\n\tconst assetInfoPartial = await getMediaAssetInfoPartial(\n\t\tfile,\n\t\tassetId,\n\t\tisImage /* isImage */,\n\t\t!isImage /* isVideo */\n\t)\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<TLImageShape>([\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<TLVideoShape>([\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,\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 position =\n\t\tpoint ??\n\t\t(editor.inputs.shiftKey\n\t\t\t? editor.inputs.currentPagePoint\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\tdocument.body.appendChild(svg)\n\t\tconst box = svg.getBoundingClientRect()\n\t\tdocument.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.shiftKey\n\t\t\t? editor.inputs.currentPagePoint\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 { acceptedImageMimeTypes = DEFAULT_SUPPORTED_IMAGE_TYPES, toasts, msg } = options\n\tif (files.length > editor.options.maxFilesAtOnce) {\n\t\ttoasts.addToast({ title: msg('assets.files.amount-too-big'), severity: 'error' })\n\t\treturn\n\t}\n\n\tconst position =\n\t\tpoint ??\n\t\t(editor.inputs.shiftKey\n\t\t\t? editor.inputs.currentPagePoint\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(file, options)\n\t\tif (!isSuccess) continue\n\n\t\tconst assetInfo = await getAssetInfo(file, options)\n\t\tif (acceptedImageMimeTypes.includes(file.type)) {\n\t\t\teditor.createTemporaryAssetPreview(assetInfo.id, file)\n\t\t}\n\t\tassetPartials.push(assetInfo)\n\t\tassetsToUpdate.push({ asset: assetInfo, file })\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.shiftKey\n\t\t\t? editor.inputs.currentPagePoint\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 = html ?? cleanedUpPlaintext.replace(/\\n/g, '<br>')\n\tconst isMultiLine = html\n\t\t? richTextToPaste.content.length > 1\n\t\t: cleanedUpPlaintext.split('\\n').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 rawSize = editor.textMeasure.measureHtml(htmlToMeasure, {\n\t\t...TEXT_PROPS,\n\t\tfontFamily: FONT_FAMILIES[defaultProps.font],\n\t\tfontSize: 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\tfontFamily: FONT_FAMILIES[defaultProps.font],\n\t\t\tfontSize: 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<TLTextShape>([\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) {\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.shiftKey\n\t\t\t? editor.inputs.currentPagePoint\n\t\t\t: editor.getViewportPageBounds().center)\n\n\tconst assetId: TLAssetId = AssetRecordType.createId(getHashForString(url))\n\tconst shape = createEmptyBookmarkShape(editor, url, position)\n\n\t// Use an existing asset if we have one, or else else create a new one\n\tlet asset = editor.getAsset(assetId) as TLAsset\n\tlet shouldAlsoCreateAsset = false\n\tif (!asset) {\n\t\tshouldAlsoCreateAsset = true\n\t\ttry {\n\t\t\tconst bookmarkAsset = await editor.getAssetForExternalContent({ type: 'url', url })\n\t\t\tif (!bookmarkAsset) throw Error('Could not create an asset')\n\t\t\tasset = bookmarkAsset\n\t\t} catch {\n\t\t\ttoasts.addToast({\n\t\t\t\ttitle: msg('assets.url.failed'),\n\t\t\t\tseverity: 'error',\n\t\t\t})\n\t\t\treturn\n\t\t}\n\t}\n\n\teditor.run(() => {\n\t\tif (shouldAlsoCreateAsset) {\n\t\t\teditor.createAssets([asset])\n\t\t}\n\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: asset.id,\n\t\t\t\t},\n\t\t\t},\n\t\t])\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/** @public */\nexport async function getMediaAssetInfoPartial(\n\tfile: File,\n\tassetId: TLAssetId,\n\tisImageType: boolean,\n\tisVideoType: boolean,\n\tmaxImageDimension?: number\n) {\n\tlet fileType = file.type\n\n\tif (file.type === 'video/quicktime') {\n\t\t// hack to make .mov videos work\n\t\tfileType = 'video/mp4'\n\t}\n\n\tconst size = isImageType\n\t\t? await MediaHelpers.getImageSize(file)\n\t\t: await MediaHelpers.getVideoSize(file)\n\n\tconst isAnimated = (await MediaHelpers.isAnimated(file)) || isVideoType\n\n\tconst assetInfo = {\n\t\tid: assetId,\n\t\ttype: isImageType ? 'image' : 'video',\n\t\ttypeName: 'asset',\n\t\tprops: {\n\t\t\tname: file.name,\n\t\t\tsrc: '',\n\t\t\tw: size.w,\n\t\t\th: size.h,\n\t\t\tfileSize: file.size,\n\t\t\tmimeType: fileType,\n\t\t\tisAnimated,\n\t\t},\n\t\tmeta: {},\n\t} as TLImageAsset | TLVideoAsset\n\n\tif (maxImageDimension && isFinite(maxImageDimension)) {\n\t\tconst size = { w: assetInfo.props.w, h: assetInfo.props.h }\n\t\tconst resizedSize = containBoxSize(size, { w: maxImageDimension, h: maxImageDimension })\n\t\tif (size !== resizedSize && MediaHelpers.isStaticImageType(file.type)) {\n\t\t\tassetInfo.props.w = resizedSize.w\n\t\t\tassetInfo.props.h = resizedSize.h\n\t\t}\n\t}\n\n\treturn assetInfo\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\tswitch (asset.type) {\n\t\t\tcase 'image': {\n\t\t\t\tpartials.push({\n\t\t\t\t\tid: createShapeId(),\n\t\t\t\t\ttype: 'image',\n\t\t\t\t\tx: currentPoint.x,\n\t\t\t\t\ty: currentPoint.y,\n\t\t\t\t\topacity: 1,\n\t\t\t\t\tprops: {\n\t\t\t\t\t\tassetId: asset.id,\n\t\t\t\t\t\tw: asset.props.w,\n\t\t\t\t\t\th: asset.props.h,\n\t\t\t\t\t},\n\t\t\t\t})\n\n\t\t\t\tcurrentPoint.x += asset.props.w\n\t\t\t\tbreak\n\t\t\t}\n\t\t\tcase 'video': {\n\t\t\t\tpartials.push({\n\t\t\t\t\tid: createShapeId(),\n\t\t\t\t\ttype: 'video',\n\t\t\t\t\tx: currentPoint.x,\n\t\t\t\t\ty: currentPoint.y,\n\t\t\t\t\topacity: 1,\n\t\t\t\t\tprops: {\n\t\t\t\t\t\tassetId: asset.id,\n\t\t\t\t\t\tw: asset.props.w,\n\t\t\t\t\t\th: asset.props.h,\n\t\t\t\t\t},\n\t\t\t\t})\n\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\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 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(file: File, options: TLDefaultExternalContentHandlerOpts) {\n\tconst {\n\t\tacceptedImageMimeTypes = DEFAULT_SUPPORTED_IMAGE_TYPES,\n\t\tacceptedVideoMimeTypes = DEFAULT_SUPPORT_VIDEO_TYPES,\n\t\tmaxAssetSize = DEFAULT_MAX_ASSET_SIZE,\n\t\ttoasts,\n\t\tmsg,\n\t} = options\n\tconst isImageType = acceptedImageMimeTypes.includes(file.type)\n\tconst isVideoType = acceptedVideoMimeTypes.includes(file.type)\n\n\tif (!isImageType && !isVideoType) {\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\ttoasts.addToast({\n\t\t\ttitle: msg('assets.files.size-too-big'),\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(\n\tfile: File,\n\toptions: TLDefaultExternalContentHandlerOpts,\n\tassetId?: TLAssetId\n) {\n\tconst {\n\t\tacceptedImageMimeTypes = DEFAULT_SUPPORTED_IMAGE_TYPES,\n\t\tacceptedVideoMimeTypes = DEFAULT_SUPPORT_VIDEO_TYPES,\n\t\tmaxImageDimension = DEFAULT_MAX_IMAGE_DIMENSION,\n\t} = options\n\n\tconst isImageType = acceptedImageMimeTypes.includes(file.type)\n\tconst isVideoType = acceptedVideoMimeTypes.includes(file.type)\n\tconst hash = getHashForBuffer(await file.arrayBuffer())\n\tassetId ??= AssetRecordType.createId(hash)\n\tconst assetInfo = await getMediaAssetInfoPartial(\n\t\tfile,\n\t\tassetId,\n\t\tisImageType,\n\t\tisVideoType,\n\t\tmaxImageDimension\n\t)\n\treturn assetInfo\n}\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["import {\n\tAssetRecordType,\n\tDEFAULT_SUPPORTED_IMAGE_TYPES,\n\tDEFAULT_SUPPORT_VIDEO_TYPES,\n\tEditor,\n\tMediaHelpers,\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\tTLVideoShape,\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 { EmbedShapeUtil } from './shapes/embed/EmbedShapeUtil'\nimport { getCroppedImageDataForReplacedImage } from './shapes/shared/crop'\nimport { FONT_FAMILIES, FONT_SIZES, TEXT_PROPS } from './shapes/shared/default-shape-constants'\nimport { TLUiToastsContextType } from './ui/context/toasts'\nimport { useTranslation } from './ui/hooks/useTranslation/useTranslation'\nimport { containBoxSize } from './utils/assets/assets'\nimport { putExcalidrawContent } from './utils/excalidraw/putExcalidrawContent'\nimport { 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. Defaults to\n\t * DEFAULT_SUPPORTED_IMAGE_TYPES.\n\t */\n\tacceptedImageMimeTypes?: readonly string[]\n\t/**\n\t * The mime types of videos that are allowed to be handled. Defaults to\n\t * DEFAULT_SUPPORT_VIDEO_TYPES.\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(file, options)\n\tif (!isSuccess) assert(false, 'File checks failed')\n\n\tconst assetInfo = await getAssetInfo(file, options, assetId)\n\tconst result = await editor.uploadAsset(assetInfo, file)\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, isImage }: TLFileReplaceExternalContent,\n\toptions: TLDefaultExternalContentHandlerOpts\n) {\n\tconst isSuccess = notifyIfFileNotAllowed(file, options)\n\tif (!isSuccess) assert(false, 'File checks failed')\n\n\tconst shape = editor.getShape(shapeId)\n\tif (!shape) assert(false, 'Shape not found')\n\n\tconst hash = getHashForBuffer(await file.arrayBuffer())\n\tconst assetId = AssetRecordType.createId(hash)\n\teditor.createTemporaryAssetPreview(assetId, file)\n\tconst assetInfoPartial = await getMediaAssetInfoPartial(\n\t\tfile,\n\t\tassetId,\n\t\tisImage /* isImage */,\n\t\t!isImage /* isVideo */\n\t)\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<TLImageShape>([\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<TLVideoShape>([\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,\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 position =\n\t\tpoint ??\n\t\t(editor.inputs.shiftKey\n\t\t\t? editor.inputs.currentPagePoint\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\tdocument.body.appendChild(svg)\n\t\tconst box = svg.getBoundingClientRect()\n\t\tdocument.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.shiftKey\n\t\t\t? editor.inputs.currentPagePoint\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 { acceptedImageMimeTypes = DEFAULT_SUPPORTED_IMAGE_TYPES, toasts, msg } = options\n\tif (files.length > editor.options.maxFilesAtOnce) {\n\t\ttoasts.addToast({ title: msg('assets.files.amount-too-big'), severity: 'error' })\n\t\treturn\n\t}\n\n\tconst position =\n\t\tpoint ??\n\t\t(editor.inputs.shiftKey\n\t\t\t? editor.inputs.currentPagePoint\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(file, options)\n\t\tif (!isSuccess) continue\n\n\t\tconst assetInfo = await getAssetInfo(file, options)\n\t\tif (acceptedImageMimeTypes.includes(file.type)) {\n\t\t\teditor.createTemporaryAssetPreview(assetInfo.id, file)\n\t\t}\n\t\tassetPartials.push(assetInfo)\n\t\tassetsToUpdate.push({ asset: assetInfo, file })\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.shiftKey\n\t\t\t? editor.inputs.currentPagePoint\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 = html ?? cleanedUpPlaintext.replace(/\\n/g, '<br>')\n\tconst isMultiLine = html\n\t\t? richTextToPaste.content.length > 1\n\t\t: cleanedUpPlaintext.split('\\n').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 rawSize = editor.textMeasure.measureHtml(htmlToMeasure, {\n\t\t...TEXT_PROPS,\n\t\tfontFamily: FONT_FAMILIES[defaultProps.font],\n\t\tfontSize: 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\tfontFamily: FONT_FAMILIES[defaultProps.font],\n\t\t\tfontSize: 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<TLTextShape>([\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) {\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.shiftKey\n\t\t\t? editor.inputs.currentPagePoint\n\t\t\t: editor.getViewportPageBounds().center)\n\n\tconst assetId: TLAssetId = AssetRecordType.createId(getHashForString(url))\n\tconst shape = createEmptyBookmarkShape(editor, url, position)\n\n\t// Use an existing asset if we have one, or else else create a new one\n\tlet asset = editor.getAsset(assetId) as TLAsset\n\tlet shouldAlsoCreateAsset = false\n\tif (!asset) {\n\t\tshouldAlsoCreateAsset = true\n\t\ttry {\n\t\t\tconst bookmarkAsset = await editor.getAssetForExternalContent({ type: 'url', url })\n\t\t\tif (!bookmarkAsset) throw Error('Could not create an asset')\n\t\t\tasset = bookmarkAsset\n\t\t} catch {\n\t\t\ttoasts.addToast({\n\t\t\t\ttitle: msg('assets.url.failed'),\n\t\t\t\tseverity: 'error',\n\t\t\t})\n\t\t\treturn\n\t\t}\n\t}\n\n\teditor.run(() => {\n\t\tif (shouldAlsoCreateAsset) {\n\t\t\teditor.createAssets([asset])\n\t\t}\n\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: asset.id,\n\t\t\t\t},\n\t\t\t},\n\t\t])\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/** @public */\nexport async function getMediaAssetInfoPartial(\n\tfile: File,\n\tassetId: TLAssetId,\n\tisImageType: boolean,\n\tisVideoType: boolean,\n\tmaxImageDimension?: number\n) {\n\tlet fileType = file.type\n\n\tif (file.type === 'video/quicktime') {\n\t\t// hack to make .mov videos work\n\t\tfileType = 'video/mp4'\n\t}\n\n\tconst size = isImageType\n\t\t? await MediaHelpers.getImageSize(file)\n\t\t: await MediaHelpers.getVideoSize(file)\n\n\tconst isAnimated = (await MediaHelpers.isAnimated(file)) || isVideoType\n\n\tconst assetInfo = {\n\t\tid: assetId,\n\t\ttype: isImageType ? 'image' : 'video',\n\t\ttypeName: 'asset',\n\t\tprops: {\n\t\t\tname: file.name,\n\t\t\tsrc: '',\n\t\t\tw: size.w,\n\t\t\th: size.h,\n\t\t\tfileSize: file.size,\n\t\t\tmimeType: fileType,\n\t\t\tisAnimated,\n\t\t},\n\t\tmeta: {},\n\t} as TLImageAsset | TLVideoAsset\n\n\tif (maxImageDimension && isFinite(maxImageDimension)) {\n\t\tconst size = { w: assetInfo.props.w, h: assetInfo.props.h }\n\t\tconst resizedSize = containBoxSize(size, { w: maxImageDimension, h: maxImageDimension })\n\t\tif (size !== resizedSize && MediaHelpers.isStaticImageType(file.type)) {\n\t\t\tassetInfo.props.w = resizedSize.w\n\t\t\tassetInfo.props.h = resizedSize.h\n\t\t}\n\t}\n\n\treturn assetInfo\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\tswitch (asset.type) {\n\t\t\tcase 'image': {\n\t\t\t\tpartials.push({\n\t\t\t\t\tid: createShapeId(),\n\t\t\t\t\ttype: 'image',\n\t\t\t\t\tx: currentPoint.x,\n\t\t\t\t\ty: currentPoint.y,\n\t\t\t\t\topacity: 1,\n\t\t\t\t\tprops: {\n\t\t\t\t\t\tassetId: asset.id,\n\t\t\t\t\t\tw: asset.props.w,\n\t\t\t\t\t\th: asset.props.h,\n\t\t\t\t\t},\n\t\t\t\t})\n\n\t\t\t\tcurrentPoint.x += asset.props.w\n\t\t\t\tbreak\n\t\t\t}\n\t\t\tcase 'video': {\n\t\t\t\tpartials.push({\n\t\t\t\t\tid: createShapeId(),\n\t\t\t\t\ttype: 'video',\n\t\t\t\t\tx: currentPoint.x,\n\t\t\t\t\ty: currentPoint.y,\n\t\t\t\t\topacity: 1,\n\t\t\t\t\tprops: {\n\t\t\t\t\t\tassetId: asset.id,\n\t\t\t\t\t\tw: asset.props.w,\n\t\t\t\t\t\th: asset.props.h,\n\t\t\t\t\t},\n\t\t\t\t})\n\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\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 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(file: File, options: TLDefaultExternalContentHandlerOpts) {\n\tconst {\n\t\tacceptedImageMimeTypes = DEFAULT_SUPPORTED_IMAGE_TYPES,\n\t\tacceptedVideoMimeTypes = DEFAULT_SUPPORT_VIDEO_TYPES,\n\t\tmaxAssetSize = DEFAULT_MAX_ASSET_SIZE,\n\t\ttoasts,\n\t\tmsg,\n\t} = options\n\tconst isImageType = acceptedImageMimeTypes.includes(file.type)\n\tconst isVideoType = acceptedVideoMimeTypes.includes(file.type)\n\n\tif (!isImageType && !isVideoType) {\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(\n\tfile: File,\n\toptions: TLDefaultExternalContentHandlerOpts,\n\tassetId?: TLAssetId\n) {\n\tconst {\n\t\tacceptedImageMimeTypes = DEFAULT_SUPPORTED_IMAGE_TYPES,\n\t\tacceptedVideoMimeTypes = DEFAULT_SUPPORT_VIDEO_TYPES,\n\t\tmaxImageDimension = DEFAULT_MAX_IMAGE_DIMENSION,\n\t} = options\n\n\tconst isImageType = acceptedImageMimeTypes.includes(file.type)\n\tconst isVideoType = acceptedVideoMimeTypes.includes(file.type)\n\tconst hash = getHashForBuffer(await file.arrayBuffer())\n\tassetId ??= AssetRecordType.createId(hash)\n\tconst assetInfo = await getMediaAssetInfoPartial(\n\t\tfile,\n\t\tassetId,\n\t\tisImageType,\n\t\tisVideoType,\n\t\tmaxImageDimension\n\t)\n\treturn assetInfo\n}\n"],
5
+ "mappings": "AAAA;AAAA,EACC;AAAA,EACA;AAAA,EACA;AAAA,EAEA;AAAA,EAiBA;AAAA,EAEA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACM;AAGP,SAAS,2CAA2C;AACpD,SAAS,eAAe,YAAY,kBAAkB;AAGtD,SAAS,sBAAsB;AAC/B,SAAS,4BAA4B;AACrC,SAAS,8BAA8B;AACvC,SAAS,aAAa,6BAA6B;AAM5C,MAAM,8BAA8B;AAKpC,MAAM,yBAAyB,KAAK,OAAO;AAiC3C,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,MAAM,OAAO;AACtD,MAAI,CAAC,UAAW,QAAO,OAAO,oBAAoB;AAElD,QAAM,YAAY,MAAM,aAAa,MAAM,SAAS,OAAO;AAC3D,QAAM,SAAS,MAAM,OAAO,YAAY,WAAW,IAAI;AACvD,YAAU,MAAM,MAAM,OAAO;AAC7B,MAAI,OAAO,KAAM,WAAU,OAAO,EAAE,GAAG,UAAU,MAAM,GAAG,OAAO,KAAK;AAEtE,SAAO,gBAAgB,OAAO,SAAS;AACxC;AAGA,eAAsB,wCACrB,QACA,EAAE,MAAM,SAAS,QAAQ,GACzB,SACC;AACD,QAAM,YAAY,uBAAuB,MAAM,OAAO;AACtD,MAAI,CAAC,UAAW,QAAO,OAAO,oBAAoB;AAElD,QAAM,QAAQ,OAAO,SAAS,OAAO;AACrC,MAAI,CAAC,MAAO,QAAO,OAAO,iBAAiB;AAE3C,QAAM,OAAO,iBAAiB,MAAM,KAAK,YAAY,CAAC;AACtD,QAAM,UAAU,gBAAgB,SAAS,IAAI;AAC7C,SAAO,4BAA4B,SAAS,IAAI;AAChD,QAAM,mBAAmB,MAAM;AAAA,IAC9B;AAAA,IACA;AAAA,IACA;AAAA,IACA,CAAC;AAAA;AAAA,EACF;AACA,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,SAAS;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,aAA2B;AAAA,MACjC;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,aAA2B;AAAA,MACjC;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;AAAA,IACA;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,MAAM,MAAM,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,gBAAgB,SAAS,iBAAiB,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,WACL,UACC,OAAO,OAAO,WACZ,OAAO,OAAO,mBACd,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,aAAS,KAAK,YAAY,GAAG;AAC7B,UAAM,MAAM,IAAI,sBAAsB;AACtC,aAAS,KAAK,YAAY,GAAG;AAE7B,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,WACZ,OAAO,OAAO,mBACd,OAAO,sBAAsB,EAAE;AAEnC,QAAM,EAAE,OAAO,OAAO,IAAI;AAE1B,QAAM,KAAK,cAAc;AAEzB,QAAM,WAAW;AAAA,IAChB,IAAI,IAAI,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,yBAAyB,+BAA+B,QAAQ,IAAI,IAAI;AAChF,MAAI,MAAM,SAAS,OAAO,QAAQ,gBAAgB;AACjD,WAAO,SAAS,EAAE,OAAO,IAAI,6BAA6B,GAAG,UAAU,QAAQ,CAAC;AAChF;AAAA,EACD;AAEA,QAAM,WACL,UACC,OAAO,OAAO,WACZ,OAAO,OAAO,mBACd,OAAO,sBAAsB,EAAE;AAEnC,QAAM,YAAY,IAAI,IAAI,SAAS,GAAG,SAAS,CAAC;AAChD,QAAM,gBAA2B,CAAC;AAClC,QAAM,iBAGA,CAAC;AACP,aAAW,QAAQ,OAAO;AACzB,UAAM,YAAY,uBAAuB,MAAM,OAAO;AACtD,QAAI,CAAC,UAAW;AAEhB,UAAM,YAAY,MAAM,aAAa,MAAM,OAAO;AAClD,QAAI,uBAAuB,SAAS,KAAK,IAAI,GAAG;AAC/C,aAAO,4BAA4B,UAAU,IAAI,IAAI;AAAA,IACtD;AACA,kBAAc,KAAK,SAAS;AAC5B,mBAAe,KAAK,EAAE,OAAO,WAAW,KAAK,CAAC;AAAA,EAC/C;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,WACZ,OAAO,OAAO,mBACd,OAAO,sBAAsB,EAAE;AAEnC,QAAM,eAAe,OAAO,aAA0B,MAAM,EAAE,gBAAgB;AAE9E,QAAM,qBAAqB,YAAY,IAAI;AAC3C,QAAM,kBAAkB,OACrB,uBAAuB,QAAQ,IAAI,IACnC,WAAW,kBAAkB;AAoBhC,MAAI;AACJ,MAAI;AACJ,MAAI;AACJ,MAAI,QAAQ;AAEZ,QAAM,gBAAgB,QAAQ,mBAAmB,QAAQ,OAAO,MAAM;AACtE,QAAM,cAAc,OACjB,gBAAgB,QAAQ,SAAS,IACjC,mBAAmB,MAAM,IAAI,EAAE,SAAS;AAG3C,QAAM,QAAQ,sBAAsB,kBAAkB;AAEtD,MAAI,aAAa;AAChB,YAAQ,cAAe,QAAQ,QAAQ,UAAW;AAAA,EACnD;AAEA,QAAM,UAAU,OAAO,YAAY,YAAY,eAAe;AAAA,IAC7D,GAAG;AAAA,IACH,YAAY,cAAc,aAAa,IAAI;AAAA,IAC3C,UAAU,WAAW,aAAa,IAAI;AAAA,IACtC,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,cAAc,aAAa,IAAI;AAAA,MAC3C,UAAU,WAAW,aAAa,IAAI;AAAA,MACtC,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,WAAW,gBAAgB,IAAI,IAAI,EAAE,IAAI,IAAI,GAAG,EAAE,IAAI,IAAI,CAAC,GAAG,MAAM;AAC1E,QAAM,UAAU,cAAc;AAG9B,SAAO,aAA0B;AAAA,IAChC;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,WAAW;AACd,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,WACZ,OAAO,OAAO,mBACd,OAAO,sBAAsB,EAAE;AAEnC,QAAM,UAAqB,gBAAgB,SAAS,iBAAiB,GAAG,CAAC;AACzE,QAAM,QAAQ,yBAAyB,QAAQ,KAAK,QAAQ;AAG5D,MAAI,QAAQ,OAAO,SAAS,OAAO;AACnC,MAAI,wBAAwB;AAC5B,MAAI,CAAC,OAAO;AACX,4BAAwB;AACxB,QAAI;AACH,YAAM,gBAAgB,MAAM,OAAO,2BAA2B,EAAE,MAAM,OAAO,IAAI,CAAC;AAClF,UAAI,CAAC,cAAe,OAAM,MAAM,2BAA2B;AAC3D,cAAQ;AAAA,IACT,QAAQ;AACP,aAAO,SAAS;AAAA,QACf,OAAO,IAAI,mBAAmB;AAAA,QAC9B,UAAU;AAAA,MACX,CAAC;AACD;AAAA,IACD;AAAA,EACD;AAEA,SAAO,IAAI,MAAM;AAChB,QAAI,uBAAuB;AAC1B,aAAO,aAAa,CAAC,KAAK,CAAC;AAAA,IAC5B;AAEA,WAAO,aAAa;AAAA,MACnB;AAAA,QACC,IAAI,MAAM;AAAA,QACV,MAAM,MAAM;AAAA,QACZ,OAAO;AAAA,UACN,SAAS,MAAM;AAAA,QAChB;AAAA,MACD;AAAA,IACD,CAAC;AAAA,EACF,CAAC;AACF;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;AAEA,WAAO,0BAA0B,SAAS;AAAA,MACzC;AAAA,MACA,QAAQ;AAAA,IACT,CAAC;AACD,UAAM,sBAAsB,OAAO,uBAAuB;AAC1D,QACC,yBACA,uBACA,uBAAuB,SAAS,mBAAmB,GAClD;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,yBAAqB,QAAQ,SAAS,KAAK;AAAA,EAC5C,CAAC;AACF;AAGA,eAAsB,yBACrB,MACA,SACA,aACA,aACA,mBACC;AACD,MAAI,WAAW,KAAK;AAEpB,MAAI,KAAK,SAAS,mBAAmB;AAEpC,eAAW;AAAA,EACZ;AAEA,QAAM,OAAO,cACV,MAAM,aAAa,aAAa,IAAI,IACpC,MAAM,aAAa,aAAa,IAAI;AAEvC,QAAM,aAAc,MAAM,aAAa,WAAW,IAAI,KAAM;AAE5D,QAAM,YAAY;AAAA,IACjB,IAAI;AAAA,IACJ,MAAM,cAAc,UAAU;AAAA,IAC9B,UAAU;AAAA,IACV,OAAO;AAAA,MACN,MAAM,KAAK;AAAA,MACX,KAAK;AAAA,MACL,GAAG,KAAK;AAAA,MACR,GAAG,KAAK;AAAA,MACR,UAAU,KAAK;AAAA,MACf,UAAU;AAAA,MACV;AAAA,IACD;AAAA,IACA,MAAM,CAAC;AAAA,EACR;AAEA,MAAI,qBAAqB,SAAS,iBAAiB,GAAG;AACrD,UAAMA,QAAO,EAAE,GAAG,UAAU,MAAM,GAAG,GAAG,UAAU,MAAM,EAAE;AAC1D,UAAM,cAAc,eAAeA,OAAM,EAAE,GAAG,mBAAmB,GAAG,kBAAkB,CAAC;AACvF,QAAIA,UAAS,eAAe,aAAa,kBAAkB,KAAK,IAAI,GAAG;AACtE,gBAAU,MAAM,IAAI,YAAY;AAChC,gBAAU,MAAM,IAAI,YAAY;AAAA,IACjC;AAAA,EACD;AAEA,SAAO;AACR;AAcA,eAAsB,sBACrB,QACA,QACA,UACuB;AACvB,MAAI,CAAC,OAAO,OAAQ,QAAO,CAAC;AAE5B,QAAM,eAAe,IAAI,KAAK,QAAQ;AACtC,QAAM,WAA6B,CAAC;AAEpC,WAAS,IAAI,GAAG,IAAI,OAAO,QAAQ,KAAK;AACvC,UAAM,QAAQ,OAAO,CAAC;AACtB,YAAQ,MAAM,MAAM;AAAA,MACnB,KAAK,SAAS;AACb,iBAAS,KAAK;AAAA,UACb,IAAI,cAAc;AAAA,UAClB,MAAM;AAAA,UACN,GAAG,aAAa;AAAA,UAChB,GAAG,aAAa;AAAA,UAChB,SAAS;AAAA,UACT,OAAO;AAAA,YACN,SAAS,MAAM;AAAA,YACf,GAAG,MAAM,MAAM;AAAA,YACf,GAAG,MAAM,MAAM;AAAA,UAChB;AAAA,QACD,CAAC;AAED,qBAAa,KAAK,MAAM,MAAM;AAC9B;AAAA,MACD;AAAA,MACA,KAAK,SAAS;AACb,iBAAS,KAAK;AAAA,UACb,IAAI,cAAc;AAAA,UAClB,MAAM;AAAA,UACN,GAAG,aAAa;AAAA,UAChB,GAAG,aAAa;AAAA,UAChB,SAAS;AAAA,UACT,OAAO;AAAA,YACN,SAAS,MAAM;AAAA,YACf,GAAG,MAAM,MAAM;AAAA,YACf,GAAG,MAAM,MAAM;AAAA,UAChB;AAAA,QACD,CAAC;AAED,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,IAAI,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,IAAI,oBAAoB,MAAM,oBAAoB,IAAI;AAC1E,UAAM,mBAAmB,QAAQ,MAAM,EAAE,WAAW,QAAQ;AAC5D,UAAM,QAAQ,IAAI,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,IAAI,cAAc;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;AAUO,SAAS,uBAAuB,MAAY,SAA8C;AAChG,QAAM;AAAA,IACL,yBAAyB;AAAA,IACzB,yBAAyB;AAAA,IACzB,eAAe;AAAA,IACf;AAAA,IACA;AAAA,EACD,IAAI;AACJ,QAAM,cAAc,uBAAuB,SAAS,KAAK,IAAI;AAC7D,QAAM,cAAc,uBAAuB,SAAS,KAAK,IAAI;AAE7D,MAAI,CAAC,eAAe,CAAC,aAAa;AACjC,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,aACrB,MACA,SACA,SACC;AACD,QAAM;AAAA,IACL,yBAAyB;AAAA,IACzB,yBAAyB;AAAA,IACzB,oBAAoB;AAAA,EACrB,IAAI;AAEJ,QAAM,cAAc,uBAAuB,SAAS,KAAK,IAAI;AAC7D,QAAM,cAAc,uBAAuB,SAAS,KAAK,IAAI;AAC7D,QAAM,OAAO,iBAAiB,MAAM,KAAK,YAAY,CAAC;AACtD,cAAY,gBAAgB,SAAS,IAAI;AACzC,QAAM,YAAY,MAAM;AAAA,IACvB;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACD;AACA,SAAO;AACR;",
6
6
  "names": ["size"]
7
7
  }
@@ -9,7 +9,7 @@ import {
9
9
  debounce,
10
10
  getHashForString,
11
11
  lerp,
12
- stopEventPropagation,
12
+ markEventAsHandled,
13
13
  tlenv,
14
14
  toDomPrecision,
15
15
  useEditor,
@@ -96,9 +96,9 @@ function BookmarkShapeComponent({ shape }) {
96
96
  const address = getHumanReadableAddress(shape);
97
97
  const [isFaviconValid, setIsFaviconValid] = useState(true);
98
98
  const onFaviconError = () => setIsFaviconValid(false);
99
- const useStopPropagationOnShiftKey = useCallback(
99
+ const markAsHandledOnShiftKey = useCallback(
100
100
  (e) => {
101
- if (!editor.inputs.shiftKey) stopEventPropagation(e);
101
+ if (!editor.inputs.shiftKey) markEventAsHandled(e);
102
102
  },
103
103
  [editor]
104
104
  );
@@ -138,8 +138,8 @@ function BookmarkShapeComponent({ shape }) {
138
138
  target: "_blank",
139
139
  rel: "noopener noreferrer",
140
140
  draggable: false,
141
- onPointerDown: useStopPropagationOnShiftKey,
142
- onPointerUp: useStopPropagationOnShiftKey,
141
+ onPointerDown: markAsHandledOnShiftKey,
142
+ onPointerUp: markAsHandledOnShiftKey,
143
143
  children: [
144
144
  isFaviconValid && asset?.props.favicon ? /* @__PURE__ */ jsx(
145
145
  "img",
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../src/lib/shapes/bookmark/BookmarkShapeUtil.tsx"],
4
- "sourcesContent": ["import {\n\tAssetRecordType,\n\tBaseBoxShapeUtil,\n\tEditor,\n\tHTMLContainer,\n\tT,\n\tTLAssetId,\n\tTLBookmarkAsset,\n\tTLBookmarkShape,\n\tTLBookmarkShapeProps,\n\tbookmarkShapeMigrations,\n\tbookmarkShapeProps,\n\tdebounce,\n\tgetHashForString,\n\tlerp,\n\tstopEventPropagation,\n\ttlenv,\n\ttoDomPrecision,\n\tuseEditor,\n\tuseSvgExportContext,\n} from '@tldraw/editor'\nimport classNames from 'classnames'\nimport { PointerEventHandler, useCallback, useState } from 'react'\nimport { convertCommonTitleHTMLEntities } from '../../utils/text/text'\nimport { HyperlinkButton } from '../shared/HyperlinkButton'\nimport { LINK_ICON } from '../shared/icons-editor'\nimport { getRotatedBoxShadow } from '../shared/rotated-box-shadow'\n\nconst BOOKMARK_WIDTH = 300\nconst BOOKMARK_HEIGHT = 320\nconst BOOKMARK_JUST_URL_HEIGHT = 46\nconst SHORT_BOOKMARK_HEIGHT = 101\n\n/** @public */\nexport class BookmarkShapeUtil extends BaseBoxShapeUtil<TLBookmarkShape> {\n\tstatic override type = 'bookmark' as const\n\tstatic override props = bookmarkShapeProps\n\tstatic override migrations = bookmarkShapeMigrations\n\n\toverride canResize() {\n\t\treturn false\n\t}\n\n\toverride hideSelectionBoundsFg() {\n\t\treturn true\n\t}\n\n\toverride getText(shape: TLBookmarkShape) {\n\t\treturn shape.props.url\n\t}\n\n\toverride getAriaDescriptor(shape: TLBookmarkShape) {\n\t\tconst asset = (\n\t\t\tshape.props.assetId ? this.editor.getAsset(shape.props.assetId) : null\n\t\t) as TLBookmarkAsset | null\n\n\t\tif (!asset?.props.title) return undefined\n\n\t\treturn (\n\t\t\tconvertCommonTitleHTMLEntities(asset.props.title) +\n\t\t\t(asset.props.description ? ', ' + asset.props.description : '')\n\t\t)\n\t}\n\n\toverride getDefaultProps(): TLBookmarkShape['props'] {\n\t\treturn {\n\t\t\turl: '',\n\t\t\tw: BOOKMARK_WIDTH,\n\t\t\th: BOOKMARK_HEIGHT,\n\t\t\tassetId: null,\n\t\t}\n\t}\n\n\toverride component(shape: TLBookmarkShape) {\n\t\treturn <BookmarkShapeComponent shape={shape} />\n\t}\n\n\toverride indicator(shape: TLBookmarkShape) {\n\t\treturn (\n\t\t\t<rect\n\t\t\t\twidth={toDomPrecision(shape.props.w)}\n\t\t\t\theight={toDomPrecision(shape.props.h)}\n\t\t\t\trx=\"6\"\n\t\t\t\try=\"6\"\n\t\t\t/>\n\t\t)\n\t}\n\n\toverride onBeforeCreate(next: TLBookmarkShape) {\n\t\treturn getBookmarkSize(this.editor, next)\n\t}\n\n\toverride onBeforeUpdate(prev: TLBookmarkShape, shape: TLBookmarkShape) {\n\t\tif (prev.props.url !== shape.props.url) {\n\t\t\tif (!T.linkUrl.isValid(shape.props.url)) {\n\t\t\t\treturn { ...shape, props: { ...shape.props, url: prev.props.url } }\n\t\t\t} else {\n\t\t\t\tupdateBookmarkAssetOnUrlChange(this.editor, shape)\n\t\t\t}\n\t\t}\n\n\t\tif (prev.props.assetId !== shape.props.assetId) {\n\t\t\treturn getBookmarkSize(this.editor, shape)\n\t\t}\n\t}\n\toverride getInterpolatedProps(\n\t\tstartShape: TLBookmarkShape,\n\t\tendShape: TLBookmarkShape,\n\t\tt: number\n\t): TLBookmarkShapeProps {\n\t\treturn {\n\t\t\t...(t > 0.5 ? endShape.props : startShape.props),\n\t\t\tw: lerp(startShape.props.w, endShape.props.w, t),\n\t\t\th: lerp(startShape.props.h, endShape.props.h, t),\n\t\t}\n\t}\n}\n\nfunction BookmarkShapeComponent({ shape }: { shape: TLBookmarkShape }) {\n\tconst editor = useEditor()\n\n\tconst asset = (\n\t\tshape.props.assetId ? editor.getAsset(shape.props.assetId) : null\n\t) as TLBookmarkAsset\n\n\tconst isSafariExport = !!useSvgExportContext() && tlenv.isSafari\n\n\tconst pageRotation = editor.getShapePageTransform(shape)!.rotation()\n\n\tconst address = getHumanReadableAddress(shape)\n\n\tconst [isFaviconValid, setIsFaviconValid] = useState(true)\n\tconst onFaviconError = () => setIsFaviconValid(false)\n\n\tconst useStopPropagationOnShiftKey = useCallback<PointerEventHandler>(\n\t\t(e) => {\n\t\t\tif (!editor.inputs.shiftKey) stopEventPropagation(e)\n\t\t},\n\t\t[editor]\n\t)\n\n\treturn (\n\t\t<HTMLContainer>\n\t\t\t<div\n\t\t\t\tclassName={classNames(\n\t\t\t\t\t'tl-bookmark__container',\n\t\t\t\t\tisSafariExport && 'tl-bookmark__container--safariExport'\n\t\t\t\t)}\n\t\t\t\tstyle={{\n\t\t\t\t\tboxShadow: isSafariExport ? undefined : getRotatedBoxShadow(pageRotation),\n\t\t\t\t\tmaxHeight: shape.props.h,\n\t\t\t\t}}\n\t\t\t>\n\t\t\t\t{(!asset || asset.props.image) && (\n\t\t\t\t\t<div className=\"tl-bookmark__image_container\">\n\t\t\t\t\t\t{asset ? (\n\t\t\t\t\t\t\t<img\n\t\t\t\t\t\t\t\tclassName=\"tl-bookmark__image\"\n\t\t\t\t\t\t\t\tdraggable={false}\n\t\t\t\t\t\t\t\treferrerPolicy=\"strict-origin-when-cross-origin\"\n\t\t\t\t\t\t\t\tsrc={asset?.props.image}\n\t\t\t\t\t\t\t\talt={asset?.props.title || ''}\n\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t) : (\n\t\t\t\t\t\t\t<div className=\"tl-bookmark__placeholder\" />\n\t\t\t\t\t\t)}\n\t\t\t\t\t\t{asset?.props.image && <HyperlinkButton url={shape.props.url} />}\n\t\t\t\t\t</div>\n\t\t\t\t)}\n\t\t\t\t<div className=\"tl-bookmark__copy_container\">\n\t\t\t\t\t{asset?.props.title ? (\n\t\t\t\t\t\t<h2 className=\"tl-bookmark__heading\">\n\t\t\t\t\t\t\t{convertCommonTitleHTMLEntities(asset.props.title)}\n\t\t\t\t\t\t</h2>\n\t\t\t\t\t) : null}\n\t\t\t\t\t{asset?.props.description && asset?.props.image ? (\n\t\t\t\t\t\t<p className=\"tl-bookmark__description\">{asset.props.description}</p>\n\t\t\t\t\t) : null}\n\t\t\t\t\t<a\n\t\t\t\t\t\tclassName=\"tl-bookmark__link\"\n\t\t\t\t\t\thref={shape.props.url || ''}\n\t\t\t\t\t\ttarget=\"_blank\"\n\t\t\t\t\t\trel=\"noopener noreferrer\"\n\t\t\t\t\t\tdraggable={false}\n\t\t\t\t\t\tonPointerDown={useStopPropagationOnShiftKey}\n\t\t\t\t\t\tonPointerUp={useStopPropagationOnShiftKey}\n\t\t\t\t\t>\n\t\t\t\t\t\t{isFaviconValid && asset?.props.favicon ? (\n\t\t\t\t\t\t\t<img\n\t\t\t\t\t\t\t\tclassName=\"tl-bookmark__favicon\"\n\t\t\t\t\t\t\t\tsrc={asset?.props.favicon}\n\t\t\t\t\t\t\t\treferrerPolicy=\"strict-origin-when-cross-origin\"\n\t\t\t\t\t\t\t\tonError={onFaviconError}\n\t\t\t\t\t\t\t\talt={`favicon of ${address}`}\n\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t) : (\n\t\t\t\t\t\t\t<div\n\t\t\t\t\t\t\t\tclassName=\"tl-hyperlink__icon\"\n\t\t\t\t\t\t\t\tstyle={{\n\t\t\t\t\t\t\t\t\tmask: `url(\"${LINK_ICON}\") center 100% / 100% no-repeat`,\n\t\t\t\t\t\t\t\t\tWebkitMask: `url(\"${LINK_ICON}\") center 100% / 100% no-repeat`,\n\t\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t)}\n\t\t\t\t\t\t<span>{address}</span>\n\t\t\t\t\t</a>\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t</HTMLContainer>\n\t)\n}\n\nfunction getBookmarkSize(editor: Editor, shape: TLBookmarkShape) {\n\tconst asset = (\n\t\tshape.props.assetId ? editor.getAsset(shape.props.assetId) : null\n\t) as TLBookmarkAsset\n\n\tlet h = BOOKMARK_HEIGHT\n\n\tif (asset) {\n\t\tif (!asset.props.image) {\n\t\t\tif (!asset.props.title) {\n\t\t\t\th = BOOKMARK_JUST_URL_HEIGHT\n\t\t\t} else {\n\t\t\t\th = SHORT_BOOKMARK_HEIGHT\n\t\t\t}\n\t\t}\n\t}\n\n\treturn {\n\t\t...shape,\n\t\tprops: {\n\t\t\t...shape.props,\n\t\t\th,\n\t\t},\n\t}\n}\n\n/** @internal */\nexport const getHumanReadableAddress = (shape: TLBookmarkShape) => {\n\ttry {\n\t\tconst url = new URL(shape.props.url)\n\t\t// we want the hostname without any www\n\t\treturn url.hostname.replace(/^www\\./, '')\n\t} catch {\n\t\treturn shape.props.url\n\t}\n}\n\nfunction 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<TLBookmarkShape>([\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<TLBookmarkShape>([\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\nconst createBookmarkAssetOnUrlChange = debounce(async (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<TLBookmarkShape>([\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}, 500)\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["import {\n\tAssetRecordType,\n\tBaseBoxShapeUtil,\n\tEditor,\n\tHTMLContainer,\n\tT,\n\tTLAssetId,\n\tTLBookmarkAsset,\n\tTLBookmarkShape,\n\tTLBookmarkShapeProps,\n\tbookmarkShapeMigrations,\n\tbookmarkShapeProps,\n\tdebounce,\n\tgetHashForString,\n\tlerp,\n\tmarkEventAsHandled,\n\ttlenv,\n\ttoDomPrecision,\n\tuseEditor,\n\tuseSvgExportContext,\n} from '@tldraw/editor'\nimport classNames from 'classnames'\nimport { PointerEventHandler, useCallback, useState } from 'react'\nimport { convertCommonTitleHTMLEntities } from '../../utils/text/text'\nimport { HyperlinkButton } from '../shared/HyperlinkButton'\nimport { LINK_ICON } from '../shared/icons-editor'\nimport { getRotatedBoxShadow } from '../shared/rotated-box-shadow'\n\nconst BOOKMARK_WIDTH = 300\nconst BOOKMARK_HEIGHT = 320\nconst BOOKMARK_JUST_URL_HEIGHT = 46\nconst SHORT_BOOKMARK_HEIGHT = 101\n\n/** @public */\nexport class BookmarkShapeUtil extends BaseBoxShapeUtil<TLBookmarkShape> {\n\tstatic override type = 'bookmark' as const\n\tstatic override props = bookmarkShapeProps\n\tstatic override migrations = bookmarkShapeMigrations\n\n\toverride canResize() {\n\t\treturn false\n\t}\n\n\toverride hideSelectionBoundsFg() {\n\t\treturn true\n\t}\n\n\toverride getText(shape: TLBookmarkShape) {\n\t\treturn shape.props.url\n\t}\n\n\toverride getAriaDescriptor(shape: TLBookmarkShape) {\n\t\tconst asset = (\n\t\t\tshape.props.assetId ? this.editor.getAsset(shape.props.assetId) : null\n\t\t) as TLBookmarkAsset | null\n\n\t\tif (!asset?.props.title) return undefined\n\n\t\treturn (\n\t\t\tconvertCommonTitleHTMLEntities(asset.props.title) +\n\t\t\t(asset.props.description ? ', ' + asset.props.description : '')\n\t\t)\n\t}\n\n\toverride getDefaultProps(): TLBookmarkShape['props'] {\n\t\treturn {\n\t\t\turl: '',\n\t\t\tw: BOOKMARK_WIDTH,\n\t\t\th: BOOKMARK_HEIGHT,\n\t\t\tassetId: null,\n\t\t}\n\t}\n\n\toverride component(shape: TLBookmarkShape) {\n\t\treturn <BookmarkShapeComponent shape={shape} />\n\t}\n\n\toverride indicator(shape: TLBookmarkShape) {\n\t\treturn (\n\t\t\t<rect\n\t\t\t\twidth={toDomPrecision(shape.props.w)}\n\t\t\t\theight={toDomPrecision(shape.props.h)}\n\t\t\t\trx=\"6\"\n\t\t\t\try=\"6\"\n\t\t\t/>\n\t\t)\n\t}\n\n\toverride onBeforeCreate(next: TLBookmarkShape) {\n\t\treturn getBookmarkSize(this.editor, next)\n\t}\n\n\toverride onBeforeUpdate(prev: TLBookmarkShape, shape: TLBookmarkShape) {\n\t\tif (prev.props.url !== shape.props.url) {\n\t\t\tif (!T.linkUrl.isValid(shape.props.url)) {\n\t\t\t\treturn { ...shape, props: { ...shape.props, url: prev.props.url } }\n\t\t\t} else {\n\t\t\t\tupdateBookmarkAssetOnUrlChange(this.editor, shape)\n\t\t\t}\n\t\t}\n\n\t\tif (prev.props.assetId !== shape.props.assetId) {\n\t\t\treturn getBookmarkSize(this.editor, shape)\n\t\t}\n\t}\n\toverride getInterpolatedProps(\n\t\tstartShape: TLBookmarkShape,\n\t\tendShape: TLBookmarkShape,\n\t\tt: number\n\t): TLBookmarkShapeProps {\n\t\treturn {\n\t\t\t...(t > 0.5 ? endShape.props : startShape.props),\n\t\t\tw: lerp(startShape.props.w, endShape.props.w, t),\n\t\t\th: lerp(startShape.props.h, endShape.props.h, t),\n\t\t}\n\t}\n}\n\nfunction BookmarkShapeComponent({ shape }: { shape: TLBookmarkShape }) {\n\tconst editor = useEditor()\n\n\tconst asset = (\n\t\tshape.props.assetId ? editor.getAsset(shape.props.assetId) : null\n\t) as TLBookmarkAsset\n\n\tconst isSafariExport = !!useSvgExportContext() && tlenv.isSafari\n\n\tconst pageRotation = editor.getShapePageTransform(shape)!.rotation()\n\n\tconst address = getHumanReadableAddress(shape)\n\n\tconst [isFaviconValid, setIsFaviconValid] = useState(true)\n\tconst onFaviconError = () => setIsFaviconValid(false)\n\n\tconst markAsHandledOnShiftKey = useCallback<PointerEventHandler>(\n\t\t(e) => {\n\t\t\tif (!editor.inputs.shiftKey) markEventAsHandled(e)\n\t\t},\n\t\t[editor]\n\t)\n\n\treturn (\n\t\t<HTMLContainer>\n\t\t\t<div\n\t\t\t\tclassName={classNames(\n\t\t\t\t\t'tl-bookmark__container',\n\t\t\t\t\tisSafariExport && 'tl-bookmark__container--safariExport'\n\t\t\t\t)}\n\t\t\t\tstyle={{\n\t\t\t\t\tboxShadow: isSafariExport ? undefined : getRotatedBoxShadow(pageRotation),\n\t\t\t\t\tmaxHeight: shape.props.h,\n\t\t\t\t}}\n\t\t\t>\n\t\t\t\t{(!asset || asset.props.image) && (\n\t\t\t\t\t<div className=\"tl-bookmark__image_container\">\n\t\t\t\t\t\t{asset ? (\n\t\t\t\t\t\t\t<img\n\t\t\t\t\t\t\t\tclassName=\"tl-bookmark__image\"\n\t\t\t\t\t\t\t\tdraggable={false}\n\t\t\t\t\t\t\t\treferrerPolicy=\"strict-origin-when-cross-origin\"\n\t\t\t\t\t\t\t\tsrc={asset?.props.image}\n\t\t\t\t\t\t\t\talt={asset?.props.title || ''}\n\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t) : (\n\t\t\t\t\t\t\t<div className=\"tl-bookmark__placeholder\" />\n\t\t\t\t\t\t)}\n\t\t\t\t\t\t{asset?.props.image && <HyperlinkButton url={shape.props.url} />}\n\t\t\t\t\t</div>\n\t\t\t\t)}\n\t\t\t\t<div className=\"tl-bookmark__copy_container\">\n\t\t\t\t\t{asset?.props.title ? (\n\t\t\t\t\t\t<h2 className=\"tl-bookmark__heading\">\n\t\t\t\t\t\t\t{convertCommonTitleHTMLEntities(asset.props.title)}\n\t\t\t\t\t\t</h2>\n\t\t\t\t\t) : null}\n\t\t\t\t\t{asset?.props.description && asset?.props.image ? (\n\t\t\t\t\t\t<p className=\"tl-bookmark__description\">{asset.props.description}</p>\n\t\t\t\t\t) : null}\n\t\t\t\t\t<a\n\t\t\t\t\t\tclassName=\"tl-bookmark__link\"\n\t\t\t\t\t\thref={shape.props.url || ''}\n\t\t\t\t\t\ttarget=\"_blank\"\n\t\t\t\t\t\trel=\"noopener noreferrer\"\n\t\t\t\t\t\tdraggable={false}\n\t\t\t\t\t\tonPointerDown={markAsHandledOnShiftKey}\n\t\t\t\t\t\tonPointerUp={markAsHandledOnShiftKey}\n\t\t\t\t\t>\n\t\t\t\t\t\t{isFaviconValid && asset?.props.favicon ? (\n\t\t\t\t\t\t\t<img\n\t\t\t\t\t\t\t\tclassName=\"tl-bookmark__favicon\"\n\t\t\t\t\t\t\t\tsrc={asset?.props.favicon}\n\t\t\t\t\t\t\t\treferrerPolicy=\"strict-origin-when-cross-origin\"\n\t\t\t\t\t\t\t\tonError={onFaviconError}\n\t\t\t\t\t\t\t\talt={`favicon of ${address}`}\n\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t) : (\n\t\t\t\t\t\t\t<div\n\t\t\t\t\t\t\t\tclassName=\"tl-hyperlink__icon\"\n\t\t\t\t\t\t\t\tstyle={{\n\t\t\t\t\t\t\t\t\tmask: `url(\"${LINK_ICON}\") center 100% / 100% no-repeat`,\n\t\t\t\t\t\t\t\t\tWebkitMask: `url(\"${LINK_ICON}\") center 100% / 100% no-repeat`,\n\t\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t)}\n\t\t\t\t\t\t<span>{address}</span>\n\t\t\t\t\t</a>\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t</HTMLContainer>\n\t)\n}\n\nfunction getBookmarkSize(editor: Editor, shape: TLBookmarkShape) {\n\tconst asset = (\n\t\tshape.props.assetId ? editor.getAsset(shape.props.assetId) : null\n\t) as TLBookmarkAsset\n\n\tlet h = BOOKMARK_HEIGHT\n\n\tif (asset) {\n\t\tif (!asset.props.image) {\n\t\t\tif (!asset.props.title) {\n\t\t\t\th = BOOKMARK_JUST_URL_HEIGHT\n\t\t\t} else {\n\t\t\t\th = SHORT_BOOKMARK_HEIGHT\n\t\t\t}\n\t\t}\n\t}\n\n\treturn {\n\t\t...shape,\n\t\tprops: {\n\t\t\t...shape.props,\n\t\t\th,\n\t\t},\n\t}\n}\n\n/** @internal */\nexport const getHumanReadableAddress = (shape: TLBookmarkShape) => {\n\ttry {\n\t\tconst url = new URL(shape.props.url)\n\t\t// we want the hostname without any www\n\t\treturn url.hostname.replace(/^www\\./, '')\n\t} catch {\n\t\treturn shape.props.url\n\t}\n}\n\nfunction 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<TLBookmarkShape>([\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<TLBookmarkShape>([\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\nconst createBookmarkAssetOnUrlChange = debounce(async (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<TLBookmarkShape>([\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}, 500)\n"],
5
+ "mappings": "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",
6
6
  "names": []
7
7
  }
@@ -1,5 +1,5 @@
1
1
  import { jsx, jsxs } from "react/jsx-runtime";
2
- import { stopEventPropagation, useEditor } from "@tldraw/editor";
2
+ import { markEventAsHandled, useEditor } from "@tldraw/editor";
3
3
  import { forwardRef, useCallback } from "react";
4
4
  import { defaultEmptyAs } from "../FrameShapeUtil.mjs";
5
5
  const FrameLabelInput = forwardRef(({ id, name, isEditing }, ref) => {
@@ -7,7 +7,7 @@ const FrameLabelInput = forwardRef(({ id, name, isEditing }, ref) => {
7
7
  const handleKeyDown = useCallback(
8
8
  (e) => {
9
9
  if (e.key === "Enter" && !e.nativeEvent.isComposing) {
10
- stopEventPropagation(e);
10
+ markEventAsHandled(e);
11
11
  e.currentTarget.blur();
12
12
  editor.setEditingShape(null);
13
13
  }
@@ -62,7 +62,7 @@ const FrameLabelInput = forwardRef(({ id, name, isEditing }, ref) => {
62
62
  onKeyDown: handleKeyDown,
63
63
  onBlur: handleBlur,
64
64
  onChange: handleChange,
65
- onPointerDown: isEditing ? stopEventPropagation : void 0,
65
+ onPointerDown: isEditing ? markEventAsHandled : void 0,
66
66
  draggable: false
67
67
  }
68
68
  ),
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../../src/lib/shapes/frame/components/FrameLabelInput.tsx"],
4
- "sourcesContent": ["import { TLFrameShape, TLShapeId, stopEventPropagation, useEditor } from '@tldraw/editor'\nimport { forwardRef, useCallback } from 'react'\nimport { defaultEmptyAs } from '../FrameShapeUtil'\n\nexport const FrameLabelInput = forwardRef<\n\tHTMLInputElement,\n\t{ id: TLShapeId; name: string; isEditing: boolean }\n>(({ id, name, isEditing }, ref) => {\n\tconst editor = useEditor()\n\n\tconst handleKeyDown = useCallback(\n\t\t(e: React.KeyboardEvent<HTMLInputElement>) => {\n\t\t\tif (e.key === 'Enter' && !e.nativeEvent.isComposing) {\n\t\t\t\t// need to prevent the enter keydown making it's way up to the Idle state\n\t\t\t\t// and sending us back into edit mode\n\t\t\t\tstopEventPropagation(e)\n\t\t\t\te.currentTarget.blur()\n\t\t\t\teditor.setEditingShape(null)\n\t\t\t}\n\t\t},\n\t\t[editor]\n\t)\n\n\tconst handleBlur = useCallback(\n\t\t(e: React.FocusEvent<HTMLInputElement>) => {\n\t\t\tconst shape = editor.getShape<TLFrameShape>(id)\n\t\t\tif (!shape) return\n\n\t\t\tconst name = shape.props.name\n\t\t\tconst value = e.currentTarget.value.trim()\n\t\t\tif (name === value) return\n\n\t\t\teditor.updateShapes([\n\t\t\t\t{\n\t\t\t\t\tid,\n\t\t\t\t\ttype: 'frame',\n\t\t\t\t\tprops: { name: value },\n\t\t\t\t},\n\t\t\t])\n\t\t},\n\t\t[id, editor]\n\t)\n\n\tconst handleChange = useCallback(\n\t\t(e: React.ChangeEvent<HTMLInputElement>) => {\n\t\t\tconst shape = editor.getShape<TLFrameShape>(id)\n\t\t\tif (!shape) return\n\n\t\t\tconst name = shape.props.name\n\t\t\tconst value = e.currentTarget.value\n\t\t\tif (name === value) return\n\n\t\t\teditor.updateShapes([\n\t\t\t\t{\n\t\t\t\t\tid,\n\t\t\t\t\ttype: 'frame',\n\t\t\t\t\tprops: { name: value },\n\t\t\t\t},\n\t\t\t])\n\t\t},\n\t\t[id, editor]\n\t)\n\n\treturn (\n\t\t<div className={`tl-frame-label ${isEditing ? 'tl-frame-label__editing' : ''}`}>\n\t\t\t<input\n\t\t\t\tclassName=\"tl-frame-name-input\"\n\t\t\t\tref={ref}\n\t\t\t\tdisabled={!isEditing}\n\t\t\t\treadOnly={!isEditing}\n\t\t\t\tstyle={{ display: isEditing ? undefined : 'none' }}\n\t\t\t\tvalue={name}\n\t\t\t\tautoFocus\n\t\t\t\tonKeyDown={handleKeyDown}\n\t\t\t\tonBlur={handleBlur}\n\t\t\t\tonChange={handleChange}\n\t\t\t\tonPointerDown={isEditing ? stopEventPropagation : undefined}\n\t\t\t\tdraggable={false}\n\t\t\t/>\n\t\t\t{defaultEmptyAs(name, 'Frame') + String.fromCharCode(8203)}\n\t\t</div>\n\t)\n})\n"],
5
- "mappings": "AAgEE,SACC,KADD;AAhEF,SAAkC,sBAAsB,iBAAiB;AACzE,SAAS,YAAY,mBAAmB;AACxC,SAAS,sBAAsB;AAExB,MAAM,kBAAkB,WAG7B,CAAC,EAAE,IAAI,MAAM,UAAU,GAAG,QAAQ;AACnC,QAAM,SAAS,UAAU;AAEzB,QAAM,gBAAgB;AAAA,IACrB,CAAC,MAA6C;AAC7C,UAAI,EAAE,QAAQ,WAAW,CAAC,EAAE,YAAY,aAAa;AAGpD,6BAAqB,CAAC;AACtB,UAAE,cAAc,KAAK;AACrB,eAAO,gBAAgB,IAAI;AAAA,MAC5B;AAAA,IACD;AAAA,IACA,CAAC,MAAM;AAAA,EACR;AAEA,QAAM,aAAa;AAAA,IAClB,CAAC,MAA0C;AAC1C,YAAM,QAAQ,OAAO,SAAuB,EAAE;AAC9C,UAAI,CAAC,MAAO;AAEZ,YAAMA,QAAO,MAAM,MAAM;AACzB,YAAM,QAAQ,EAAE,cAAc,MAAM,KAAK;AACzC,UAAIA,UAAS,MAAO;AAEpB,aAAO,aAAa;AAAA,QACnB;AAAA,UACC;AAAA,UACA,MAAM;AAAA,UACN,OAAO,EAAE,MAAM,MAAM;AAAA,QACtB;AAAA,MACD,CAAC;AAAA,IACF;AAAA,IACA,CAAC,IAAI,MAAM;AAAA,EACZ;AAEA,QAAM,eAAe;AAAA,IACpB,CAAC,MAA2C;AAC3C,YAAM,QAAQ,OAAO,SAAuB,EAAE;AAC9C,UAAI,CAAC,MAAO;AAEZ,YAAMA,QAAO,MAAM,MAAM;AACzB,YAAM,QAAQ,EAAE,cAAc;AAC9B,UAAIA,UAAS,MAAO;AAEpB,aAAO,aAAa;AAAA,QACnB;AAAA,UACC;AAAA,UACA,MAAM;AAAA,UACN,OAAO,EAAE,MAAM,MAAM;AAAA,QACtB;AAAA,MACD,CAAC;AAAA,IACF;AAAA,IACA,CAAC,IAAI,MAAM;AAAA,EACZ;AAEA,SACC,qBAAC,SAAI,WAAW,kBAAkB,YAAY,4BAA4B,EAAE,IAC3E;AAAA;AAAA,MAAC;AAAA;AAAA,QACA,WAAU;AAAA,QACV;AAAA,QACA,UAAU,CAAC;AAAA,QACX,UAAU,CAAC;AAAA,QACX,OAAO,EAAE,SAAS,YAAY,SAAY,OAAO;AAAA,QACjD,OAAO;AAAA,QACP,WAAS;AAAA,QACT,WAAW;AAAA,QACX,QAAQ;AAAA,QACR,UAAU;AAAA,QACV,eAAe,YAAY,uBAAuB;AAAA,QAClD,WAAW;AAAA;AAAA,IACZ;AAAA,IACC,eAAe,MAAM,OAAO,IAAI,OAAO,aAAa,IAAI;AAAA,KAC1D;AAEF,CAAC;",
4
+ "sourcesContent": ["import { TLFrameShape, TLShapeId, markEventAsHandled, useEditor } from '@tldraw/editor'\nimport { forwardRef, useCallback } from 'react'\nimport { defaultEmptyAs } from '../FrameShapeUtil'\n\nexport const FrameLabelInput = forwardRef<\n\tHTMLInputElement,\n\t{ id: TLShapeId; name: string; isEditing: boolean }\n>(({ id, name, isEditing }, ref) => {\n\tconst editor = useEditor()\n\n\tconst handleKeyDown = useCallback(\n\t\t(e: React.KeyboardEvent<HTMLInputElement>) => {\n\t\t\tif (e.key === 'Enter' && !e.nativeEvent.isComposing) {\n\t\t\t\t// need to prevent the enter keydown making it's way up to the Idle state\n\t\t\t\t// and sending us back into edit mode\n\t\t\t\tmarkEventAsHandled(e)\n\t\t\t\te.currentTarget.blur()\n\t\t\t\teditor.setEditingShape(null)\n\t\t\t}\n\t\t},\n\t\t[editor]\n\t)\n\n\tconst handleBlur = useCallback(\n\t\t(e: React.FocusEvent<HTMLInputElement>) => {\n\t\t\tconst shape = editor.getShape<TLFrameShape>(id)\n\t\t\tif (!shape) return\n\n\t\t\tconst name = shape.props.name\n\t\t\tconst value = e.currentTarget.value.trim()\n\t\t\tif (name === value) return\n\n\t\t\teditor.updateShapes([\n\t\t\t\t{\n\t\t\t\t\tid,\n\t\t\t\t\ttype: 'frame',\n\t\t\t\t\tprops: { name: value },\n\t\t\t\t},\n\t\t\t])\n\t\t},\n\t\t[id, editor]\n\t)\n\n\tconst handleChange = useCallback(\n\t\t(e: React.ChangeEvent<HTMLInputElement>) => {\n\t\t\tconst shape = editor.getShape<TLFrameShape>(id)\n\t\t\tif (!shape) return\n\n\t\t\tconst name = shape.props.name\n\t\t\tconst value = e.currentTarget.value\n\t\t\tif (name === value) return\n\n\t\t\teditor.updateShapes([\n\t\t\t\t{\n\t\t\t\t\tid,\n\t\t\t\t\ttype: 'frame',\n\t\t\t\t\tprops: { name: value },\n\t\t\t\t},\n\t\t\t])\n\t\t},\n\t\t[id, editor]\n\t)\n\n\treturn (\n\t\t<div className={`tl-frame-label ${isEditing ? 'tl-frame-label__editing' : ''}`}>\n\t\t\t<input\n\t\t\t\tclassName=\"tl-frame-name-input\"\n\t\t\t\tref={ref}\n\t\t\t\tdisabled={!isEditing}\n\t\t\t\treadOnly={!isEditing}\n\t\t\t\tstyle={{ display: isEditing ? undefined : 'none' }}\n\t\t\t\tvalue={name}\n\t\t\t\tautoFocus\n\t\t\t\tonKeyDown={handleKeyDown}\n\t\t\t\tonBlur={handleBlur}\n\t\t\t\tonChange={handleChange}\n\t\t\t\tonPointerDown={isEditing ? markEventAsHandled : undefined}\n\t\t\t\tdraggable={false}\n\t\t\t/>\n\t\t\t{defaultEmptyAs(name, 'Frame') + String.fromCharCode(8203)}\n\t\t</div>\n\t)\n})\n"],
5
+ "mappings": "AAgEE,SACC,KADD;AAhEF,SAAkC,oBAAoB,iBAAiB;AACvE,SAAS,YAAY,mBAAmB;AACxC,SAAS,sBAAsB;AAExB,MAAM,kBAAkB,WAG7B,CAAC,EAAE,IAAI,MAAM,UAAU,GAAG,QAAQ;AACnC,QAAM,SAAS,UAAU;AAEzB,QAAM,gBAAgB;AAAA,IACrB,CAAC,MAA6C;AAC7C,UAAI,EAAE,QAAQ,WAAW,CAAC,EAAE,YAAY,aAAa;AAGpD,2BAAmB,CAAC;AACpB,UAAE,cAAc,KAAK;AACrB,eAAO,gBAAgB,IAAI;AAAA,MAC5B;AAAA,IACD;AAAA,IACA,CAAC,MAAM;AAAA,EACR;AAEA,QAAM,aAAa;AAAA,IAClB,CAAC,MAA0C;AAC1C,YAAM,QAAQ,OAAO,SAAuB,EAAE;AAC9C,UAAI,CAAC,MAAO;AAEZ,YAAMA,QAAO,MAAM,MAAM;AACzB,YAAM,QAAQ,EAAE,cAAc,MAAM,KAAK;AACzC,UAAIA,UAAS,MAAO;AAEpB,aAAO,aAAa;AAAA,QACnB;AAAA,UACC;AAAA,UACA,MAAM;AAAA,UACN,OAAO,EAAE,MAAM,MAAM;AAAA,QACtB;AAAA,MACD,CAAC;AAAA,IACF;AAAA,IACA,CAAC,IAAI,MAAM;AAAA,EACZ;AAEA,QAAM,eAAe;AAAA,IACpB,CAAC,MAA2C;AAC3C,YAAM,QAAQ,OAAO,SAAuB,EAAE;AAC9C,UAAI,CAAC,MAAO;AAEZ,YAAMA,QAAO,MAAM,MAAM;AACzB,YAAM,QAAQ,EAAE,cAAc;AAC9B,UAAIA,UAAS,MAAO;AAEpB,aAAO,aAAa;AAAA,QACnB;AAAA,UACC;AAAA,UACA,MAAM;AAAA,UACN,OAAO,EAAE,MAAM,MAAM;AAAA,QACtB;AAAA,MACD,CAAC;AAAA,IACF;AAAA,IACA,CAAC,IAAI,MAAM;AAAA,EACZ;AAEA,SACC,qBAAC,SAAI,WAAW,kBAAkB,YAAY,4BAA4B,EAAE,IAC3E;AAAA;AAAA,MAAC;AAAA;AAAA,QACA,WAAU;AAAA,QACV;AAAA,QACA,UAAU,CAAC;AAAA,QACX,UAAU,CAAC;AAAA,QACX,OAAO,EAAE,SAAS,YAAY,SAAY,OAAO;AAAA,QACjD,OAAO;AAAA,QACP,WAAS;AAAA,QACT,WAAW;AAAA,QACX,QAAQ;AAAA,QACR,UAAU;AAAA,QACV,eAAe,YAAY,qBAAqB;AAAA,QAChD,WAAW;AAAA;AAAA,IACZ;AAAA,IACC,eAAe,MAAM,OAAO,IAAI,OAAO,aAAa,IAAI;AAAA,KAC1D;AAEF,CAAC;",
6
6
  "names": ["name"]
7
7
  }
@@ -1,14 +1,14 @@
1
1
  import { jsx } from "react/jsx-runtime";
2
- import { stopEventPropagation, useEditor, useValue } from "@tldraw/editor";
2
+ import { markEventAsHandled, useEditor, useValue } from "@tldraw/editor";
3
3
  import classNames from "classnames";
4
4
  import { useCallback } from "react";
5
5
  const LINK_ICON = "data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='30' height='30' fill='none'%3E%3Cpath stroke='%23000' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' d='M13 5H7a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h16a2 2 0 0 0 2-2v-6M19 5h6m0 0v6m0-6L13 17'/%3E%3C/svg%3E";
6
6
  function HyperlinkButton({ url }) {
7
7
  const editor = useEditor();
8
8
  const hideButton = useValue("zoomLevel", () => editor.getZoomLevel() < 0.32, [editor]);
9
- const useStopPropagationOnShiftKey = useCallback(
9
+ const markAsHandledOnShiftKey = useCallback(
10
10
  (e) => {
11
- if (!editor.inputs.shiftKey) stopEventPropagation(e);
11
+ if (!editor.inputs.shiftKey) markEventAsHandled(e);
12
12
  },
13
13
  [editor]
14
14
  );
@@ -21,8 +21,8 @@ function HyperlinkButton({ url }) {
21
21
  href: url,
22
22
  target: "_blank",
23
23
  rel: "noopener noreferrer",
24
- onPointerDown: useStopPropagationOnShiftKey,
25
- onPointerUp: useStopPropagationOnShiftKey,
24
+ onPointerDown: markAsHandledOnShiftKey,
25
+ onPointerUp: markAsHandledOnShiftKey,
26
26
  title: url,
27
27
  draggable: false,
28
28
  children: /* @__PURE__ */ jsx(
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../src/lib/shapes/shared/HyperlinkButton.tsx"],
4
- "sourcesContent": ["import { stopEventPropagation, useEditor, useValue } from '@tldraw/editor'\nimport classNames from 'classnames'\nimport { PointerEventHandler, useCallback } from 'react'\n\nconst LINK_ICON =\n\t\"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='30' height='30' fill='none'%3E%3Cpath stroke='%23000' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' d='M13 5H7a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h16a2 2 0 0 0 2-2v-6M19 5h6m0 0v6m0-6L13 17'/%3E%3C/svg%3E\"\n\nexport function HyperlinkButton({ url }: { url: string }) {\n\tconst editor = useEditor()\n\tconst hideButton = useValue('zoomLevel', () => editor.getZoomLevel() < 0.32, [editor])\n\tconst useStopPropagationOnShiftKey = useCallback<PointerEventHandler>(\n\t\t(e) => {\n\t\t\tif (!editor.inputs.shiftKey) stopEventPropagation(e)\n\t\t},\n\t\t[editor]\n\t)\n\treturn (\n\t\t<a\n\t\t\tclassName={classNames('tl-hyperlink-button', {\n\t\t\t\t'tl-hyperlink-button__hidden': hideButton,\n\t\t\t})}\n\t\t\thref={url}\n\t\t\ttarget=\"_blank\"\n\t\t\trel=\"noopener noreferrer\"\n\t\t\tonPointerDown={useStopPropagationOnShiftKey}\n\t\t\tonPointerUp={useStopPropagationOnShiftKey}\n\t\t\ttitle={url}\n\t\t\tdraggable={false}\n\t\t>\n\t\t\t<div\n\t\t\t\tclassName=\"tl-hyperlink__icon\"\n\t\t\t\tstyle={{\n\t\t\t\t\tmask: `url(\"${LINK_ICON}\") center 100% / 100% no-repeat`,\n\t\t\t\t\tWebkitMask: `url(\"${LINK_ICON}\") center 100% / 100% no-repeat`,\n\t\t\t\t}}\n\t\t\t/>\n\t\t</a>\n\t)\n}\n"],
5
- "mappings": "AA6BG;AA7BH,SAAS,sBAAsB,WAAW,gBAAgB;AAC1D,OAAO,gBAAgB;AACvB,SAA8B,mBAAmB;AAEjD,MAAM,YACL;AAEM,SAAS,gBAAgB,EAAE,IAAI,GAAoB;AACzD,QAAM,SAAS,UAAU;AACzB,QAAM,aAAa,SAAS,aAAa,MAAM,OAAO,aAAa,IAAI,MAAM,CAAC,MAAM,CAAC;AACrF,QAAM,+BAA+B;AAAA,IACpC,CAAC,MAAM;AACN,UAAI,CAAC,OAAO,OAAO,SAAU,sBAAqB,CAAC;AAAA,IACpD;AAAA,IACA,CAAC,MAAM;AAAA,EACR;AACA,SACC;AAAA,IAAC;AAAA;AAAA,MACA,WAAW,WAAW,uBAAuB;AAAA,QAC5C,+BAA+B;AAAA,MAChC,CAAC;AAAA,MACD,MAAM;AAAA,MACN,QAAO;AAAA,MACP,KAAI;AAAA,MACJ,eAAe;AAAA,MACf,aAAa;AAAA,MACb,OAAO;AAAA,MACP,WAAW;AAAA,MAEX;AAAA,QAAC;AAAA;AAAA,UACA,WAAU;AAAA,UACV,OAAO;AAAA,YACN,MAAM,QAAQ,SAAS;AAAA,YACvB,YAAY,QAAQ,SAAS;AAAA,UAC9B;AAAA;AAAA,MACD;AAAA;AAAA,EACD;AAEF;",
4
+ "sourcesContent": ["import { markEventAsHandled, useEditor, useValue } from '@tldraw/editor'\nimport classNames from 'classnames'\nimport { PointerEventHandler, useCallback } from 'react'\n\nconst LINK_ICON =\n\t\"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='30' height='30' fill='none'%3E%3Cpath stroke='%23000' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' d='M13 5H7a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h16a2 2 0 0 0 2-2v-6M19 5h6m0 0v6m0-6L13 17'/%3E%3C/svg%3E\"\n\nexport function HyperlinkButton({ url }: { url: string }) {\n\tconst editor = useEditor()\n\tconst hideButton = useValue('zoomLevel', () => editor.getZoomLevel() < 0.32, [editor])\n\tconst markAsHandledOnShiftKey = useCallback<PointerEventHandler>(\n\t\t(e) => {\n\t\t\tif (!editor.inputs.shiftKey) markEventAsHandled(e)\n\t\t},\n\t\t[editor]\n\t)\n\treturn (\n\t\t<a\n\t\t\tclassName={classNames('tl-hyperlink-button', {\n\t\t\t\t'tl-hyperlink-button__hidden': hideButton,\n\t\t\t})}\n\t\t\thref={url}\n\t\t\ttarget=\"_blank\"\n\t\t\trel=\"noopener noreferrer\"\n\t\t\tonPointerDown={markAsHandledOnShiftKey}\n\t\t\tonPointerUp={markAsHandledOnShiftKey}\n\t\t\ttitle={url}\n\t\t\tdraggable={false}\n\t\t>\n\t\t\t<div\n\t\t\t\tclassName=\"tl-hyperlink__icon\"\n\t\t\t\tstyle={{\n\t\t\t\t\tmask: `url(\"${LINK_ICON}\") center 100% / 100% no-repeat`,\n\t\t\t\t\tWebkitMask: `url(\"${LINK_ICON}\") center 100% / 100% no-repeat`,\n\t\t\t\t}}\n\t\t\t/>\n\t\t</a>\n\t)\n}\n"],
5
+ "mappings": "AA6BG;AA7BH,SAAS,oBAAoB,WAAW,gBAAgB;AACxD,OAAO,gBAAgB;AACvB,SAA8B,mBAAmB;AAEjD,MAAM,YACL;AAEM,SAAS,gBAAgB,EAAE,IAAI,GAAoB;AACzD,QAAM,SAAS,UAAU;AACzB,QAAM,aAAa,SAAS,aAAa,MAAM,OAAO,aAAa,IAAI,MAAM,CAAC,MAAM,CAAC;AACrF,QAAM,0BAA0B;AAAA,IAC/B,CAAC,MAAM;AACN,UAAI,CAAC,OAAO,OAAO,SAAU,oBAAmB,CAAC;AAAA,IAClD;AAAA,IACA,CAAC,MAAM;AAAA,EACR;AACA,SACC;AAAA,IAAC;AAAA;AAAA,MACA,WAAW,WAAW,uBAAuB;AAAA,QAC5C,+BAA+B;AAAA,MAChC,CAAC;AAAA,MACD,MAAM;AAAA,MACN,QAAO;AAAA,MACP,KAAI;AAAA,MACJ,eAAe;AAAA,MACf,aAAa;AAAA,MACb,OAAO;AAAA,MACP,WAAW;AAAA,MAEX;AAAA,QAAC;AAAA;AAAA,UACA,WAAU;AAAA,UACV,OAAO;AAAA,YACN,MAAM,QAAQ,SAAS;AAAA,YACvB,YAAY,QAAQ,SAAS;AAAA,UAC9B;AAAA;AAAA,MACD;AAAA;AAAA,EACD;AAEF;",
6
6
  "names": []
7
7
  }