tldraw 3.16.0-canary.6f3aedaa1c01 → 3.16.0-canary.7cd3b8a5bfd6

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 (123) hide show
  1. package/dist-cjs/index.d.ts +45 -4
  2. package/dist-cjs/index.js +4 -1
  3. package/dist-cjs/index.js.map +2 -2
  4. package/dist-cjs/lib/canvas/TldrawScribble.js +1 -1
  5. package/dist-cjs/lib/canvas/TldrawScribble.js.map +2 -2
  6. package/dist-cjs/lib/shapes/arrow/elbow/ElbowArrowDebug.js +3 -3
  7. package/dist-cjs/lib/shapes/arrow/elbow/ElbowArrowDebug.js.map +1 -1
  8. package/dist-cjs/lib/shapes/embed/EmbedShapeUtil.js +1 -1
  9. package/dist-cjs/lib/shapes/embed/EmbedShapeUtil.js.map +1 -1
  10. package/dist-cjs/lib/shapes/frame/FrameShapeUtil.js +4 -4
  11. package/dist-cjs/lib/shapes/frame/FrameShapeUtil.js.map +2 -2
  12. package/dist-cjs/lib/shapes/frame/components/FrameHeading.js +1 -1
  13. package/dist-cjs/lib/shapes/frame/components/FrameHeading.js.map +2 -2
  14. package/dist-cjs/lib/shapes/image/ImageShapeUtil.js +3 -3
  15. package/dist-cjs/lib/shapes/image/ImageShapeUtil.js.map +1 -1
  16. package/dist-cjs/lib/shapes/shared/ShapeFill.js +1 -1
  17. package/dist-cjs/lib/shapes/shared/ShapeFill.js.map +2 -2
  18. package/dist-cjs/lib/shapes/video/VideoShapeUtil.js +3 -3
  19. package/dist-cjs/lib/shapes/video/VideoShapeUtil.js.map +1 -1
  20. package/dist-cjs/lib/ui/TldrawUi.js +14 -0
  21. package/dist-cjs/lib/ui/TldrawUi.js.map +3 -3
  22. package/dist-cjs/lib/ui/components/ActionsMenu/DefaultActionsMenu.js +10 -2
  23. package/dist-cjs/lib/ui/components/ActionsMenu/DefaultActionsMenu.js.map +2 -2
  24. package/dist-cjs/lib/ui/components/Minimap/MinimapManager.js +4 -4
  25. package/dist-cjs/lib/ui/components/Minimap/MinimapManager.js.map +2 -2
  26. package/dist-cjs/lib/ui/components/MobileStylePanel.js +4 -2
  27. package/dist-cjs/lib/ui/components/MobileStylePanel.js.map +2 -2
  28. package/dist-cjs/lib/ui/components/Toolbar/DefaultImageToolbarContent.js +1 -1
  29. package/dist-cjs/lib/ui/components/Toolbar/DefaultImageToolbarContent.js.map +2 -2
  30. package/dist-cjs/lib/ui/components/Toolbar/DefaultToolbar.js +66 -22
  31. package/dist-cjs/lib/ui/components/Toolbar/DefaultToolbar.js.map +3 -3
  32. package/dist-cjs/lib/ui/components/Toolbar/OverflowingToolbar.js +188 -78
  33. package/dist-cjs/lib/ui/components/Toolbar/OverflowingToolbar.js.map +3 -3
  34. package/dist-cjs/lib/ui/components/primitives/TldrawUiToolbar.js +15 -3
  35. package/dist-cjs/lib/ui/components/primitives/TldrawUiToolbar.js.map +2 -2
  36. package/dist-cjs/lib/ui/components/primitives/TldrawUiTooltip.js +144 -160
  37. package/dist-cjs/lib/ui/components/primitives/TldrawUiTooltip.js.map +2 -2
  38. package/dist-cjs/lib/ui/components/primitives/layout.js +30 -5
  39. package/dist-cjs/lib/ui/components/primitives/layout.js.map +2 -2
  40. package/dist-cjs/lib/ui/components/primitives/menus/TldrawUiMenuContext.js.map +2 -2
  41. package/dist-cjs/lib/ui/components/primitives/menus/TldrawUiMenuGroup.js +25 -12
  42. package/dist-cjs/lib/ui/components/primitives/menus/TldrawUiMenuGroup.js.map +2 -2
  43. package/dist-cjs/lib/ui/components/primitives/menus/TldrawUiMenuItem.js +1 -18
  44. package/dist-cjs/lib/ui/components/primitives/menus/TldrawUiMenuItem.js.map +2 -2
  45. package/dist-cjs/lib/ui/hooks/useTools.js +21 -3
  46. package/dist-cjs/lib/ui/hooks/useTools.js.map +2 -2
  47. package/dist-cjs/lib/ui/version.js +3 -3
  48. package/dist-cjs/lib/ui/version.js.map +1 -1
  49. package/dist-esm/index.d.mts +45 -4
  50. package/dist-esm/index.mjs +8 -2
  51. package/dist-esm/index.mjs.map +2 -2
  52. package/dist-esm/lib/canvas/TldrawScribble.mjs +1 -1
  53. package/dist-esm/lib/canvas/TldrawScribble.mjs.map +2 -2
  54. package/dist-esm/lib/shapes/arrow/elbow/ElbowArrowDebug.mjs +3 -3
  55. package/dist-esm/lib/shapes/arrow/elbow/ElbowArrowDebug.mjs.map +1 -1
  56. package/dist-esm/lib/shapes/embed/EmbedShapeUtil.mjs +1 -1
  57. package/dist-esm/lib/shapes/embed/EmbedShapeUtil.mjs.map +1 -1
  58. package/dist-esm/lib/shapes/frame/FrameShapeUtil.mjs +4 -4
  59. package/dist-esm/lib/shapes/frame/FrameShapeUtil.mjs.map +2 -2
  60. package/dist-esm/lib/shapes/frame/components/FrameHeading.mjs +1 -1
  61. package/dist-esm/lib/shapes/frame/components/FrameHeading.mjs.map +2 -2
  62. package/dist-esm/lib/shapes/image/ImageShapeUtil.mjs +3 -3
  63. package/dist-esm/lib/shapes/image/ImageShapeUtil.mjs.map +1 -1
  64. package/dist-esm/lib/shapes/shared/ShapeFill.mjs +1 -1
  65. package/dist-esm/lib/shapes/shared/ShapeFill.mjs.map +2 -2
  66. package/dist-esm/lib/shapes/video/VideoShapeUtil.mjs +3 -3
  67. package/dist-esm/lib/shapes/video/VideoShapeUtil.mjs.map +1 -1
  68. package/dist-esm/lib/ui/TldrawUi.mjs +16 -2
  69. package/dist-esm/lib/ui/TldrawUi.mjs.map +3 -3
  70. package/dist-esm/lib/ui/components/ActionsMenu/DefaultActionsMenu.mjs +10 -2
  71. package/dist-esm/lib/ui/components/ActionsMenu/DefaultActionsMenu.mjs.map +2 -2
  72. package/dist-esm/lib/ui/components/Minimap/MinimapManager.mjs +4 -4
  73. package/dist-esm/lib/ui/components/Minimap/MinimapManager.mjs.map +2 -2
  74. package/dist-esm/lib/ui/components/MobileStylePanel.mjs +4 -2
  75. package/dist-esm/lib/ui/components/MobileStylePanel.mjs.map +2 -2
  76. package/dist-esm/lib/ui/components/Toolbar/DefaultImageToolbarContent.mjs +1 -1
  77. package/dist-esm/lib/ui/components/Toolbar/DefaultImageToolbarContent.mjs.map +2 -2
  78. package/dist-esm/lib/ui/components/Toolbar/DefaultToolbar.mjs +56 -22
  79. package/dist-esm/lib/ui/components/Toolbar/DefaultToolbar.mjs.map +2 -2
  80. package/dist-esm/lib/ui/components/Toolbar/OverflowingToolbar.mjs +192 -80
  81. package/dist-esm/lib/ui/components/Toolbar/OverflowingToolbar.mjs.map +3 -3
  82. package/dist-esm/lib/ui/components/primitives/TldrawUiToolbar.mjs +16 -4
  83. package/dist-esm/lib/ui/components/primitives/TldrawUiToolbar.mjs.map +2 -2
  84. package/dist-esm/lib/ui/components/primitives/TldrawUiTooltip.mjs +153 -162
  85. package/dist-esm/lib/ui/components/primitives/TldrawUiTooltip.mjs.map +2 -2
  86. package/dist-esm/lib/ui/components/primitives/layout.mjs +31 -6
  87. package/dist-esm/lib/ui/components/primitives/layout.mjs.map +2 -2
  88. package/dist-esm/lib/ui/components/primitives/menus/TldrawUiMenuContext.mjs.map +2 -2
  89. package/dist-esm/lib/ui/components/primitives/menus/TldrawUiMenuGroup.mjs +25 -12
  90. package/dist-esm/lib/ui/components/primitives/menus/TldrawUiMenuGroup.mjs.map +2 -2
  91. package/dist-esm/lib/ui/components/primitives/menus/TldrawUiMenuItem.mjs +1 -18
  92. package/dist-esm/lib/ui/components/primitives/menus/TldrawUiMenuItem.mjs.map +2 -2
  93. package/dist-esm/lib/ui/hooks/useTools.mjs +22 -3
  94. package/dist-esm/lib/ui/hooks/useTools.mjs.map +2 -2
  95. package/dist-esm/lib/ui/version.mjs +3 -3
  96. package/dist-esm/lib/ui/version.mjs.map +1 -1
  97. package/package.json +3 -3
  98. package/src/index.ts +5 -0
  99. package/src/lib/canvas/TldrawScribble.tsx +1 -1
  100. package/src/lib/shapes/arrow/elbow/ElbowArrowDebug.tsx +3 -3
  101. package/src/lib/shapes/embed/EmbedShapeUtil.tsx +1 -1
  102. package/src/lib/shapes/frame/FrameShapeUtil.tsx +12 -4
  103. package/src/lib/shapes/frame/components/FrameHeading.tsx +1 -1
  104. package/src/lib/shapes/image/ImageShapeUtil.tsx +3 -3
  105. package/src/lib/shapes/shared/ShapeFill.tsx +1 -1
  106. package/src/lib/shapes/video/VideoShapeUtil.tsx +3 -3
  107. package/src/lib/ui/TldrawUi.tsx +17 -2
  108. package/src/lib/ui/components/ActionsMenu/DefaultActionsMenu.tsx +13 -2
  109. package/src/lib/ui/components/Minimap/MinimapManager.ts +4 -4
  110. package/src/lib/ui/components/MobileStylePanel.tsx +4 -3
  111. package/src/lib/ui/components/Toolbar/DefaultImageToolbarContent.tsx +1 -1
  112. package/src/lib/ui/components/Toolbar/DefaultToolbar.tsx +55 -24
  113. package/src/lib/ui/components/Toolbar/OverflowingToolbar.tsx +208 -56
  114. package/src/lib/ui/components/primitives/TldrawUiToolbar.tsx +22 -5
  115. package/src/lib/ui/components/primitives/TldrawUiTooltip.tsx +175 -180
  116. package/src/lib/ui/components/primitives/layout.tsx +79 -5
  117. package/src/lib/ui/components/primitives/menus/TldrawUiMenuContext.tsx +0 -1
  118. package/src/lib/ui/components/primitives/menus/TldrawUiMenuGroup.tsx +29 -16
  119. package/src/lib/ui/components/primitives/menus/TldrawUiMenuItem.tsx +2 -16
  120. package/src/lib/ui/hooks/useTools.tsx +25 -3
  121. package/src/lib/ui/version.ts +3 -3
  122. package/src/lib/ui.css +346 -243
  123. package/tldraw.css +639 -533
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../src/lib/shapes/frame/FrameShapeUtil.tsx"],
4
- "sourcesContent": ["import {\n\tBaseBoxShapeUtil,\n\tDefaultColorStyle,\n\tGeometry2d,\n\tGroup2d,\n\tRectangle2d,\n\tSVGContainer,\n\tSvgExportContext,\n\tTLClickEventInfo,\n\tTLDragShapesOutInfo,\n\tTLDragShapesOverInfo,\n\tTLFrameShape,\n\tTLFrameShapeProps,\n\tTLResizeInfo,\n\tTLShape,\n\tTLShapePartial,\n\tTLShapeUtilConstructor,\n\tclamp,\n\tcompact,\n\tframeShapeMigrations,\n\tframeShapeProps,\n\tgetColorValue,\n\tgetDefaultColorTheme,\n\tlerp,\n\tresizeBox,\n\ttoDomPrecision,\n\tuseValue,\n} from '@tldraw/editor'\nimport classNames from 'classnames'\nimport { fitFrameToContent, getFrameChildrenBounds } from '../../utils/frames/frames'\nimport {\n\tTLCreateTextJsxFromSpansOpts,\n\tcreateTextJsxFromSpans,\n} from '../shared/createTextJsxFromSpans'\nimport { useDefaultColorTheme } from '../shared/useDefaultColorTheme'\nimport { FrameHeading } from './components/FrameHeading'\nimport {\n\tgetFrameHeadingOpts,\n\tgetFrameHeadingSide,\n\tgetFrameHeadingSize,\n\tgetFrameHeadingTranslation,\n} from './frameHelpers'\n\n// Some of these values are repeated in CSS and need to match\nconst FRAME_HEADING_EXTRA_WIDTH = 12\nconst FRAME_HEADING_MIN_WIDTH = 32\nconst FRAME_HEADING_NOCOLORS_OFFSET_X = -7\nconst FRAME_HEADING_OFFSET_Y = 4\n\n/** @public */\nexport interface FrameShapeOptions {\n\t/**\n\t * When true, the frame will display colors for the shape's headings and background.\n\t */\n\tshowColors: boolean\n}\n\nexport function defaultEmptyAs(str: string, dflt: string) {\n\tif (str.match(/^\\s*$/)) {\n\t\treturn dflt\n\t}\n\treturn str\n}\n\n/** @public */\nexport class FrameShapeUtil extends BaseBoxShapeUtil<TLFrameShape> {\n\tstatic override type = 'frame' as const\n\tstatic override props = frameShapeProps\n\tstatic override migrations = frameShapeMigrations\n\n\toverride options: FrameShapeOptions = {\n\t\tshowColors: false,\n\t}\n\n\t// evil crimes :)\n\t// By default, showColors is off. Because they use style props, which are picked up\n\t// automatically, we don't have DefaultColorStyle in the props in the schema by default.\n\t// Instead, when someone calls .configure to turn the option on, we manually add in the color\n\t// style here so it plays nicely with the other editor APIs.\n\tstatic override configure<T extends TLShapeUtilConstructor<any, any>>(\n\t\tthis: T,\n\t\toptions: T extends new (...args: any[]) => { options: infer Options } ? Partial<Options> : never\n\t): T {\n\t\tconst withOptions = super.configure.call(this, options) as T\n\t\tif ((options as any).showColors) {\n\t\t\t;(withOptions as any).props = { ...withOptions.props, color: DefaultColorStyle }\n\t\t}\n\t\treturn withOptions\n\t}\n\n\toverride canEdit() {\n\t\treturn true\n\t}\n\n\toverride canResize() {\n\t\treturn true\n\t}\n\n\toverride canResizeChildren() {\n\t\treturn false\n\t}\n\n\toverride getDefaultProps(): TLFrameShape['props'] {\n\t\treturn { w: 160 * 2, h: 90 * 2, name: '', color: 'black' }\n\t}\n\n\toverride getAriaDescriptor(shape: TLFrameShape) {\n\t\treturn shape.props.name\n\t}\n\n\toverride getGeometry(shape: TLFrameShape): Geometry2d {\n\t\tconst { editor } = this\n\n\t\tconst z = editor.getZoomLevel()\n\n\t\t// Which dimension measures the top edge after rotation?\n\t\tconst labelSide = getFrameHeadingSide(editor, shape)\n\t\tconst isVertical = labelSide % 2 === 1\n\t\tconst rotatedTopEdgeWidth = isVertical ? shape.props.h : shape.props.w\n\n\t\t// Get the size of the heading (max width equal to the rotatedTopEdgeWidth)\n\t\tconst opts = getFrameHeadingOpts(rotatedTopEdgeWidth, false)\n\t\tconst headingSize = getFrameHeadingSize(editor, shape, opts)\n\n\t\t// If NOT showing frame colors, we need to offset the label\n\t\t// to the left so that the title is in line with the shape edge\n\t\t// and add that extra width to the right side of the label\n\t\tconst isShowingFrameColors = this.options.showColors\n\n\t\t// Scale everything into **screen space**\n\t\tconst extraWidth = FRAME_HEADING_EXTRA_WIDTH / z\n\t\tconst minWidth = FRAME_HEADING_MIN_WIDTH / z\n\t\tconst maxWidth = rotatedTopEdgeWidth + (isShowingFrameColors ? 1 : extraWidth)\n\n\t\tconst labelWidth = headingSize.w / z\n\t\tconst labelHeight = headingSize.h / z\n\n\t\tconst clampedLabelWidth = clamp(labelWidth + extraWidth, minWidth, maxWidth)\n\n\t\tconst offsetX = (isShowingFrameColors ? -1 : FRAME_HEADING_NOCOLORS_OFFSET_X) / z\n\t\tconst offsetY = FRAME_HEADING_OFFSET_Y / z\n\n\t\t// In page space\n\t\tconst width = isVertical ? labelHeight : clampedLabelWidth\n\t\tconst height = isVertical ? clampedLabelWidth : labelHeight\n\n\t\t// Calculate label position based on side. The position needs to always appear\n\t\t// at the top left of the shape, regardless of rotation. The label must be\n\t\t// between a minimum and maximum. The minimum is arbitrary; the maximum is the\n\t\t// width of the edge of the frame where the label will be shown.\n\n\t\tlet x: number, y: number\n\n\t\tswitch (labelSide) {\n\t\t\tcase 0: {\n\t\t\t\t// top\n\t\t\t\tx = offsetX\n\t\t\t\ty = -(labelHeight + offsetY)\n\t\t\t\tbreak\n\t\t\t}\n\t\t\tcase 1: {\n\t\t\t\t// right\n\t\t\t\tx = -(labelHeight + offsetY)\n\t\t\t\ty = shape.props.h - (offsetX + clampedLabelWidth)\n\t\t\t\tbreak\n\t\t\t}\n\t\t\tcase 2: {\n\t\t\t\t// bottom\n\t\t\t\tx = shape.props.w - (offsetX + clampedLabelWidth)\n\t\t\t\ty = shape.props.h + offsetY\n\t\t\t\tbreak\n\t\t\t}\n\t\t\tcase 3: {\n\t\t\t\t// left\n\t\t\t\tx = shape.props.w + offsetY\n\t\t\t\ty = offsetX\n\t\t\t\tbreak\n\t\t\t}\n\t\t}\n\n\t\treturn new Group2d({\n\t\t\tchildren: [\n\t\t\t\tnew Rectangle2d({\n\t\t\t\t\twidth: shape.props.w,\n\t\t\t\t\theight: shape.props.h,\n\t\t\t\t\tisFilled: false,\n\t\t\t\t}),\n\t\t\t\tnew Rectangle2d({\n\t\t\t\t\tx,\n\t\t\t\t\ty,\n\t\t\t\t\twidth,\n\t\t\t\t\theight,\n\t\t\t\t\tisFilled: true,\n\t\t\t\t\tisLabel: true,\n\t\t\t\t}),\n\t\t\t],\n\t\t})\n\t}\n\n\toverride getText(shape: TLFrameShape): string | undefined {\n\t\treturn shape.props.name\n\t}\n\n\toverride component(shape: TLFrameShape) {\n\t\t// eslint-disable-next-line react-hooks/rules-of-hooks\n\t\tconst theme = useDefaultColorTheme()\n\n\t\t// eslint-disable-next-line react-hooks/rules-of-hooks\n\t\tconst isCreating = useValue(\n\t\t\t'is creating this shape',\n\t\t\t() => {\n\t\t\t\tconst resizingState = this.editor.getStateDescendant('select.resizing')\n\t\t\t\tif (!resizingState) return false\n\t\t\t\tif (!resizingState.getIsActive()) return false\n\t\t\t\tconst info = (resizingState as typeof resizingState & { info: { isCreating: boolean } })\n\t\t\t\t\t?.info\n\t\t\t\tif (!info) return false\n\t\t\t\treturn info.isCreating && this.editor.getOnlySelectedShapeId() === shape.id\n\t\t\t},\n\t\t\t[shape.id]\n\t\t)\n\n\t\tconst showFrameColors = this.options.showColors\n\t\tconst colorToUse = showFrameColors ? shape.props.color : 'black'\n\t\tconst frameFill = getColorValue(theme, colorToUse, 'frameFill')\n\t\tconst frameStroke = getColorValue(theme, colorToUse, 'frameStroke')\n\t\tconst frameHeadingStroke = getColorValue(theme, colorToUse, 'frameHeadingStroke')\n\t\tconst frameHeadingFill = getColorValue(theme, colorToUse, 'frameHeadingFill')\n\t\tconst frameHeadingText = getColorValue(theme, colorToUse, 'frameText')\n\n\t\treturn (\n\t\t\t<>\n\t\t\t\t<SVGContainer>\n\t\t\t\t\t<rect\n\t\t\t\t\t\tclassName={classNames('tl-frame__body', { 'tl-frame__creating': isCreating })}\n\t\t\t\t\t\tfill={frameFill}\n\t\t\t\t\t\tstroke={frameStroke}\n\t\t\t\t\t\tstyle={{\n\t\t\t\t\t\t\twidth: `calc(${shape.props.w}px + 1px / var(--tl-zoom))`,\n\t\t\t\t\t\t\theight: `calc(${shape.props.h}px + 1px / var(--tl-zoom))`,\n\t\t\t\t\t\t\ttransform: `translate(calc(-0.5px / var(--tl-zoom)), calc(-0.5px / var(--tl-zoom)))`,\n\t\t\t\t\t\t}}\n\t\t\t\t\t/>\n\t\t\t\t</SVGContainer>\n\t\t\t\t{isCreating ? null : (\n\t\t\t\t\t<FrameHeading\n\t\t\t\t\t\tid={shape.id}\n\t\t\t\t\t\tname={shape.props.name}\n\t\t\t\t\t\tfill={frameHeadingFill}\n\t\t\t\t\t\tstroke={frameHeadingStroke}\n\t\t\t\t\t\tcolor={frameHeadingText}\n\t\t\t\t\t\twidth={shape.props.w}\n\t\t\t\t\t\theight={shape.props.h}\n\t\t\t\t\t\toffsetX={showFrameColors ? -1 : -7}\n\t\t\t\t\t\tshowColors={this.options.showColors}\n\t\t\t\t\t/>\n\t\t\t\t)}\n\t\t\t</>\n\t\t)\n\t}\n\n\toverride toSvg(shape: TLFrameShape, ctx: SvgExportContext) {\n\t\tconst theme = getDefaultColorTheme({ isDarkMode: ctx.isDarkMode })\n\n\t\t// rotate right 45 deg\n\t\tconst labelSide = getFrameHeadingSide(this.editor, shape)\n\t\tconst isVertical = labelSide % 2 === 1\n\t\tconst rotatedTopEdgeWidth = isVertical ? shape.props.h : shape.props.w\n\t\tconst labelTranslate = getFrameHeadingTranslation(shape, labelSide, true)\n\n\t\t// Truncate with ellipsis\n\t\tconst opts: TLCreateTextJsxFromSpansOpts = getFrameHeadingOpts(rotatedTopEdgeWidth - 12, true)\n\n\t\tconst frameTitle = defaultEmptyAs(shape.props.name, 'Frame') + String.fromCharCode(8203)\n\t\tconst labelBounds = getFrameHeadingSize(this.editor, shape, opts)\n\t\tconst spans = this.editor.textMeasure.measureTextSpans(frameTitle, opts)\n\t\tconst text = createTextJsxFromSpans(this.editor, spans, opts)\n\n\t\tconst showFrameColors = this.options.showColors\n\t\tconst colorToUse = showFrameColors ? shape.props.color : 'black'\n\t\tconst frameFill = getColorValue(theme, colorToUse, 'frameFill')\n\t\tconst frameStroke = getColorValue(theme, colorToUse, 'frameStroke')\n\t\tconst frameHeadingStroke = getColorValue(theme, colorToUse, 'frameHeadingStroke')\n\t\tconst frameHeadingFill = getColorValue(theme, colorToUse, 'frameHeadingFill')\n\t\tconst frameHeadingText = getColorValue(theme, colorToUse, 'frameText')\n\n\t\treturn (\n\t\t\t<>\n\t\t\t\t<rect\n\t\t\t\t\twidth={shape.props.w}\n\t\t\t\t\theight={shape.props.h}\n\t\t\t\t\tfill={frameFill}\n\t\t\t\t\tstroke={frameStroke}\n\t\t\t\t\tstrokeWidth={1}\n\t\t\t\t\tx={0}\n\t\t\t\t\trx={0}\n\t\t\t\t\try={0}\n\t\t\t\t/>\n\t\t\t\t<g fill={frameHeadingText} transform={labelTranslate}>\n\t\t\t\t\t<rect\n\t\t\t\t\t\tx={labelBounds.x - (showFrameColors ? 0 : 6)}\n\t\t\t\t\t\ty={labelBounds.y - 6}\n\t\t\t\t\t\twidth={Math.min(rotatedTopEdgeWidth, labelBounds.width + 12)}\n\t\t\t\t\t\theight={labelBounds.height}\n\t\t\t\t\t\tfill={frameHeadingFill}\n\t\t\t\t\t\tstroke={frameHeadingStroke}\n\t\t\t\t\t\trx={4}\n\t\t\t\t\t\try={4}\n\t\t\t\t\t/>\n\t\t\t\t\t<g transform={`translate(${showFrameColors ? 8 : 0}, 4)`}>{text}</g>\n\t\t\t\t</g>\n\t\t\t</>\n\t\t)\n\t}\n\n\tindicator(shape: TLFrameShape) {\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\tclassName={`tl-frame-indicator`}\n\t\t\t/>\n\t\t)\n\t}\n\n\toverride providesBackgroundForChildren(): boolean {\n\t\treturn true\n\t}\n\n\toverride canReceiveNewChildrenOfType(shape: TLShape) {\n\t\treturn !shape.isLocked\n\t}\n\n\toverride onResize(shape: any, info: TLResizeInfo<any>) {\n\t\treturn resizeBox(shape, info)\n\t}\n\n\toverride getInterpolatedProps(\n\t\tstartShape: TLFrameShape,\n\t\tendShape: TLFrameShape,\n\t\tt: number\n\t): TLFrameShapeProps {\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\toverride onDoubleClickEdge(shape: TLFrameShape, info: TLClickEventInfo) {\n\t\tif (info.target !== 'selection') return\n\t\tconst { handle } = info\n\n\t\t// If handle is missing, we can't determine which edge was clicked\n\t\tif (!handle) return\n\n\t\tconst isHorizontalEdge = handle === 'left' || handle === 'right'\n\t\tconst isVerticalEdge = handle === 'top' || handle === 'bottom'\n\n\t\tconst childIds = this.editor.getSortedChildIdsForParent(shape.id)\n\t\tconst children = compact(childIds.map((id) => this.editor.getShape(id)))\n\t\tif (!children.length) return\n\n\t\tconst { dx, dy, w, h } = getFrameChildrenBounds(children, this.editor, { padding: 10 })\n\n\t\tthis.editor.run(() => {\n\t\t\tconst changes: TLShapePartial[] = childIds.map((childId) => {\n\t\t\t\tconst childShape = this.editor.getShape(childId)!\n\t\t\t\treturn {\n\t\t\t\t\tid: childShape.id,\n\t\t\t\t\ttype: childShape.type,\n\t\t\t\t\tx: isHorizontalEdge ? childShape.x + dx : childShape.x,\n\t\t\t\t\ty: isVerticalEdge ? childShape.y + dy : childShape.y,\n\t\t\t\t}\n\t\t\t})\n\n\t\t\tthis.editor.updateShapes(changes)\n\t\t})\n\n\t\treturn {\n\t\t\tid: shape.id,\n\t\t\ttype: shape.type,\n\t\t\tprops: {\n\t\t\t\tw: isHorizontalEdge ? w : shape.props.w,\n\t\t\t\th: isVerticalEdge ? h : shape.props.h,\n\t\t\t},\n\t\t}\n\t}\n\n\toverride onDoubleClickCorner(shape: TLFrameShape) {\n\t\tfitFrameToContent(this.editor, shape.id, { padding: 10 })\n\t\treturn {\n\t\t\tid: shape.id,\n\t\t\ttype: shape.type,\n\t\t}\n\t}\n\n\toverride onDragShapesIn(\n\t\tshape: TLFrameShape,\n\t\tdraggingShapes: TLShape[],\n\t\t{ initialParentIds, initialIndices }: TLDragShapesOverInfo\n\t) {\n\t\tconst { editor } = this\n\n\t\tif (draggingShapes.every((s) => s.parentId === shape.id)) return\n\n\t\t// Check to see whether any of the shapes can have their old index restored\n\t\tlet canRestoreOriginalIndices = false\n\t\tconst previousChildren = draggingShapes.filter((s) => shape.id === initialParentIds.get(s.id))\n\n\t\tif (previousChildren.length > 0) {\n\t\t\tconst currentChildren = compact(\n\t\t\t\teditor.getSortedChildIdsForParent(shape).map((id) => editor.getShape(id))\n\t\t\t)\n\t\t\tif (previousChildren.every((s) => !currentChildren.find((c) => c.index === s.index))) {\n\t\t\t\tcanRestoreOriginalIndices = true\n\t\t\t}\n\t\t}\n\n\t\t// I can't imagine this happening, but if any of the children are the ancestor of the frame, quit here\n\t\tif (draggingShapes.some((s) => editor.hasAncestor(shape, s.id))) return\n\n\t\t// Reparent the shapes to the new parent\n\t\teditor.reparentShapes(draggingShapes, shape.id)\n\n\t\t// If we can restore the original indices, then do so\n\t\tif (canRestoreOriginalIndices) {\n\t\t\tfor (const shape of previousChildren) {\n\t\t\t\teditor.updateShape({\n\t\t\t\t\tid: shape.id,\n\t\t\t\t\ttype: shape.type,\n\t\t\t\t\tindex: initialIndices.get(shape.id),\n\t\t\t\t})\n\t\t\t}\n\t\t}\n\t}\n\n\toverride onDragShapesOut(\n\t\tshape: TLFrameShape,\n\t\tdraggingShapes: TLShape[],\n\t\tinfo: TLDragShapesOutInfo\n\t): void {\n\t\tconst { editor } = this\n\t\t// When a user drags shapes out of a frame, and if we're not dragging into a new shape, then reparent\n\t\t// the dragging shapes (that are current children of the frame) onto the current page instead\n\t\tif (!info.nextDraggingOverShapeId) {\n\t\t\teditor.reparentShapes(\n\t\t\t\tdraggingShapes.filter(\n\t\t\t\t\t(s) => s.parentId === shape.id && this.canReceiveNewChildrenOfType(s)\n\t\t\t\t),\n\t\t\t\teditor.getCurrentPageId()\n\t\t\t)\n\t\t}\n\t}\n}\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["import {\n\tBaseBoxShapeUtil,\n\tDefaultColorStyle,\n\tGeometry2d,\n\tGroup2d,\n\tRectangle2d,\n\tSVGContainer,\n\tSvgExportContext,\n\tTLClickEventInfo,\n\tTLDragShapesOutInfo,\n\tTLDragShapesOverInfo,\n\tTLFrameShape,\n\tTLFrameShapeProps,\n\tTLResizeInfo,\n\tTLShape,\n\tTLShapePartial,\n\tTLShapeUtilConstructor,\n\tclamp,\n\tcompact,\n\tframeShapeMigrations,\n\tframeShapeProps,\n\tgetColorValue,\n\tgetDefaultColorTheme,\n\tlerp,\n\tresizeBox,\n\ttoDomPrecision,\n\tuseValue,\n} from '@tldraw/editor'\nimport classNames from 'classnames'\nimport { fitFrameToContent, getFrameChildrenBounds } from '../../utils/frames/frames'\nimport {\n\tTLCreateTextJsxFromSpansOpts,\n\tcreateTextJsxFromSpans,\n} from '../shared/createTextJsxFromSpans'\nimport { useDefaultColorTheme } from '../shared/useDefaultColorTheme'\nimport { FrameHeading } from './components/FrameHeading'\nimport {\n\tgetFrameHeadingOpts,\n\tgetFrameHeadingSide,\n\tgetFrameHeadingSize,\n\tgetFrameHeadingTranslation,\n} from './frameHelpers'\n\n// Some of these values are repeated in CSS and need to match\nconst FRAME_HEADING_EXTRA_WIDTH = 12\nconst FRAME_HEADING_MIN_WIDTH = 32\nconst FRAME_HEADING_NOCOLORS_OFFSET_X = -7\nconst FRAME_HEADING_OFFSET_Y = 4\n\n/** @public */\nexport interface FrameShapeOptions {\n\t/**\n\t * When true, the frame will display colors for the shape's headings and background.\n\t */\n\tshowColors: boolean\n}\n\nexport function defaultEmptyAs(str: string, dflt: string) {\n\tif (str.match(/^\\s*$/)) {\n\t\treturn dflt\n\t}\n\treturn str\n}\n\n/** @public */\nexport class FrameShapeUtil extends BaseBoxShapeUtil<TLFrameShape> {\n\tstatic override type = 'frame' as const\n\tstatic override props = frameShapeProps\n\tstatic override migrations = frameShapeMigrations\n\n\toverride options: FrameShapeOptions = {\n\t\tshowColors: false,\n\t}\n\n\t// evil crimes :)\n\t// By default, showColors is off. Because they use style props, which are picked up\n\t// automatically, we don't have DefaultColorStyle in the props in the schema by default.\n\t// Instead, when someone calls .configure to turn the option on, we manually add in the color\n\t// style here so it plays nicely with the other editor APIs.\n\tstatic override configure<T extends TLShapeUtilConstructor<any, any>>(\n\t\tthis: T,\n\t\toptions: T extends new (...args: any[]) => { options: infer Options } ? Partial<Options> : never\n\t): T {\n\t\tconst withOptions = super.configure.call(this, options) as T\n\t\tif ((options as any).showColors) {\n\t\t\t;(withOptions as any).props = { ...withOptions.props, color: DefaultColorStyle }\n\t\t}\n\t\treturn withOptions\n\t}\n\n\toverride canEdit() {\n\t\treturn true\n\t}\n\n\toverride canResize() {\n\t\treturn true\n\t}\n\n\toverride canResizeChildren() {\n\t\treturn false\n\t}\n\n\toverride getDefaultProps(): TLFrameShape['props'] {\n\t\treturn { w: 160 * 2, h: 90 * 2, name: '', color: 'black' }\n\t}\n\n\toverride getAriaDescriptor(shape: TLFrameShape) {\n\t\treturn shape.props.name\n\t}\n\n\toverride getGeometry(shape: TLFrameShape): Geometry2d {\n\t\tconst { editor } = this\n\n\t\tconst z = editor.getZoomLevel()\n\n\t\t// Which dimension measures the top edge after rotation?\n\t\tconst labelSide = getFrameHeadingSide(editor, shape)\n\t\tconst isVertical = labelSide % 2 === 1\n\t\tconst rotatedTopEdgeWidth = isVertical ? shape.props.h : shape.props.w\n\n\t\t// Get the size of the heading (max width equal to the rotatedTopEdgeWidth)\n\t\tconst opts = getFrameHeadingOpts(rotatedTopEdgeWidth, false)\n\t\tconst headingSize = getFrameHeadingSize(editor, shape, opts)\n\n\t\t// If NOT showing frame colors, we need to offset the label\n\t\t// to the left so that the title is in line with the shape edge\n\t\t// and add that extra width to the right side of the label\n\t\tconst isShowingFrameColors = this.options.showColors\n\n\t\t// Scale everything into **screen space**\n\t\tconst extraWidth = FRAME_HEADING_EXTRA_WIDTH / z\n\t\tconst minWidth = FRAME_HEADING_MIN_WIDTH / z\n\t\tconst maxWidth = rotatedTopEdgeWidth + (isShowingFrameColors ? 1 : extraWidth)\n\n\t\tconst labelWidth = headingSize.w / z\n\t\tconst labelHeight = headingSize.h / z\n\n\t\tconst clampedLabelWidth = clamp(labelWidth + extraWidth, minWidth, maxWidth)\n\n\t\tconst offsetX = (isShowingFrameColors ? -1 : FRAME_HEADING_NOCOLORS_OFFSET_X) / z\n\t\tconst offsetY = FRAME_HEADING_OFFSET_Y / z\n\n\t\t// In page space\n\t\tconst width = isVertical ? labelHeight : clampedLabelWidth\n\t\tconst height = isVertical ? clampedLabelWidth : labelHeight\n\n\t\t// Calculate label position based on side. The position needs to always appear\n\t\t// at the top left of the shape, regardless of rotation. The label must be\n\t\t// between a minimum and maximum. The minimum is arbitrary; the maximum is the\n\t\t// width of the edge of the frame where the label will be shown.\n\n\t\tlet x: number, y: number\n\n\t\tswitch (labelSide) {\n\t\t\tcase 0: {\n\t\t\t\t// top\n\t\t\t\tx = offsetX\n\t\t\t\ty = -(labelHeight + offsetY)\n\t\t\t\tbreak\n\t\t\t}\n\t\t\tcase 1: {\n\t\t\t\t// right\n\t\t\t\tx = -(labelHeight + offsetY)\n\t\t\t\ty = shape.props.h - (offsetX + clampedLabelWidth)\n\t\t\t\tbreak\n\t\t\t}\n\t\t\tcase 2: {\n\t\t\t\t// bottom\n\t\t\t\tx = shape.props.w - (offsetX + clampedLabelWidth)\n\t\t\t\ty = shape.props.h + offsetY\n\t\t\t\tbreak\n\t\t\t}\n\t\t\tcase 3: {\n\t\t\t\t// left\n\t\t\t\tx = shape.props.w + offsetY\n\t\t\t\ty = offsetX\n\t\t\t\tbreak\n\t\t\t}\n\t\t}\n\n\t\treturn new Group2d({\n\t\t\tchildren: [\n\t\t\t\tnew Rectangle2d({\n\t\t\t\t\twidth: shape.props.w,\n\t\t\t\t\theight: shape.props.h,\n\t\t\t\t\tisFilled: false,\n\t\t\t\t}),\n\t\t\t\tnew Rectangle2d({\n\t\t\t\t\tx,\n\t\t\t\t\ty,\n\t\t\t\t\twidth,\n\t\t\t\t\theight,\n\t\t\t\t\tisFilled: true,\n\t\t\t\t\tisLabel: true,\n\t\t\t\t}),\n\t\t\t],\n\t\t})\n\t}\n\n\toverride getText(shape: TLFrameShape): string | undefined {\n\t\treturn shape.props.name\n\t}\n\n\toverride component(shape: TLFrameShape) {\n\t\t// eslint-disable-next-line react-hooks/rules-of-hooks\n\t\tconst theme = useDefaultColorTheme()\n\n\t\t// eslint-disable-next-line react-hooks/rules-of-hooks\n\t\tconst isCreating = useValue(\n\t\t\t'is creating this shape',\n\t\t\t() => {\n\t\t\t\tconst resizingState = this.editor.getStateDescendant('select.resizing')\n\t\t\t\tif (!resizingState) return false\n\t\t\t\tif (!resizingState.getIsActive()) return false\n\t\t\t\tconst info = (resizingState as typeof resizingState & { info: { isCreating: boolean } })\n\t\t\t\t\t?.info\n\t\t\t\tif (!info) return false\n\t\t\t\treturn info.isCreating && this.editor.getOnlySelectedShapeId() === shape.id\n\t\t\t},\n\t\t\t[shape.id]\n\t\t)\n\n\t\tconst showFrameColors = this.options.showColors\n\t\tconst colorToUse = showFrameColors ? shape.props.color : 'black'\n\t\tconst frameFill = getColorValue(theme, colorToUse, 'frameFill')\n\t\tconst frameStroke = getColorValue(theme, colorToUse, 'frameStroke')\n\t\tconst frameHeadingStroke = showFrameColors\n\t\t\t? getColorValue(theme, colorToUse, 'frameHeadingStroke')\n\t\t\t: theme.background\n\t\tconst frameHeadingFill = showFrameColors\n\t\t\t? getColorValue(theme, colorToUse, 'frameHeadingFill')\n\t\t\t: theme.background\n\t\tconst frameHeadingText = getColorValue(theme, colorToUse, 'frameText')\n\n\t\treturn (\n\t\t\t<>\n\t\t\t\t<SVGContainer>\n\t\t\t\t\t<rect\n\t\t\t\t\t\tclassName={classNames('tl-frame__body', { 'tl-frame__creating': isCreating })}\n\t\t\t\t\t\tfill={frameFill}\n\t\t\t\t\t\tstroke={frameStroke}\n\t\t\t\t\t\tstyle={{\n\t\t\t\t\t\t\twidth: `calc(${shape.props.w}px + 1px / var(--tl-zoom))`,\n\t\t\t\t\t\t\theight: `calc(${shape.props.h}px + 1px / var(--tl-zoom))`,\n\t\t\t\t\t\t\ttransform: `translate(calc(-0.5px / var(--tl-zoom)), calc(-0.5px / var(--tl-zoom)))`,\n\t\t\t\t\t\t}}\n\t\t\t\t\t/>\n\t\t\t\t</SVGContainer>\n\t\t\t\t{isCreating ? null : (\n\t\t\t\t\t<FrameHeading\n\t\t\t\t\t\tid={shape.id}\n\t\t\t\t\t\tname={shape.props.name}\n\t\t\t\t\t\tfill={frameHeadingFill}\n\t\t\t\t\t\tstroke={frameHeadingStroke}\n\t\t\t\t\t\tcolor={frameHeadingText}\n\t\t\t\t\t\twidth={shape.props.w}\n\t\t\t\t\t\theight={shape.props.h}\n\t\t\t\t\t\toffsetX={showFrameColors ? -1 : -7}\n\t\t\t\t\t\tshowColors={this.options.showColors}\n\t\t\t\t\t/>\n\t\t\t\t)}\n\t\t\t</>\n\t\t)\n\t}\n\n\toverride toSvg(shape: TLFrameShape, ctx: SvgExportContext) {\n\t\tconst theme = getDefaultColorTheme({ isDarkMode: ctx.isDarkMode })\n\n\t\t// rotate right 45 deg\n\t\tconst labelSide = getFrameHeadingSide(this.editor, shape)\n\t\tconst isVertical = labelSide % 2 === 1\n\t\tconst rotatedTopEdgeWidth = isVertical ? shape.props.h : shape.props.w\n\t\tconst labelTranslate = getFrameHeadingTranslation(shape, labelSide, true)\n\n\t\t// Truncate with ellipsis\n\t\tconst opts: TLCreateTextJsxFromSpansOpts = getFrameHeadingOpts(rotatedTopEdgeWidth - 12, true)\n\n\t\tconst frameTitle = defaultEmptyAs(shape.props.name, 'Frame') + String.fromCharCode(8203)\n\t\tconst labelBounds = getFrameHeadingSize(this.editor, shape, opts)\n\t\tconst spans = this.editor.textMeasure.measureTextSpans(frameTitle, opts)\n\t\tconst text = createTextJsxFromSpans(this.editor, spans, opts)\n\n\t\tconst showFrameColors = this.options.showColors\n\t\tconst colorToUse = showFrameColors ? shape.props.color : 'black'\n\t\tconst frameFill = getColorValue(theme, colorToUse, 'frameFill')\n\t\tconst frameStroke = getColorValue(theme, colorToUse, 'frameStroke')\n\t\tconst frameHeadingStroke = showFrameColors\n\t\t\t? getColorValue(theme, colorToUse, 'frameHeadingStroke')\n\t\t\t: theme.background\n\t\tconst frameHeadingFill = showFrameColors\n\t\t\t? getColorValue(theme, colorToUse, 'frameHeadingFill')\n\t\t\t: theme.background\n\t\tconst frameHeadingText = getColorValue(theme, colorToUse, 'frameText')\n\n\t\treturn (\n\t\t\t<>\n\t\t\t\t<rect\n\t\t\t\t\twidth={shape.props.w}\n\t\t\t\t\theight={shape.props.h}\n\t\t\t\t\tfill={frameFill}\n\t\t\t\t\tstroke={frameStroke}\n\t\t\t\t\tstrokeWidth={1}\n\t\t\t\t\tx={0}\n\t\t\t\t\trx={0}\n\t\t\t\t\try={0}\n\t\t\t\t/>\n\t\t\t\t<g fill={frameHeadingText} transform={labelTranslate}>\n\t\t\t\t\t<rect\n\t\t\t\t\t\tx={labelBounds.x - (showFrameColors ? 0 : 6)}\n\t\t\t\t\t\ty={labelBounds.y - 6}\n\t\t\t\t\t\twidth={Math.min(rotatedTopEdgeWidth, labelBounds.width + 12)}\n\t\t\t\t\t\theight={labelBounds.height}\n\t\t\t\t\t\tfill={frameHeadingFill}\n\t\t\t\t\t\tstroke={frameHeadingStroke}\n\t\t\t\t\t\trx={4}\n\t\t\t\t\t\try={4}\n\t\t\t\t\t/>\n\t\t\t\t\t<g transform={`translate(${showFrameColors ? 8 : 0}, 4)`}>{text}</g>\n\t\t\t\t</g>\n\t\t\t</>\n\t\t)\n\t}\n\n\tindicator(shape: TLFrameShape) {\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\tclassName={`tl-frame-indicator`}\n\t\t\t/>\n\t\t)\n\t}\n\n\toverride providesBackgroundForChildren(): boolean {\n\t\treturn true\n\t}\n\n\toverride canReceiveNewChildrenOfType(shape: TLShape) {\n\t\treturn !shape.isLocked\n\t}\n\n\toverride onResize(shape: any, info: TLResizeInfo<any>) {\n\t\treturn resizeBox(shape, info)\n\t}\n\n\toverride getInterpolatedProps(\n\t\tstartShape: TLFrameShape,\n\t\tendShape: TLFrameShape,\n\t\tt: number\n\t): TLFrameShapeProps {\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\toverride onDoubleClickEdge(shape: TLFrameShape, info: TLClickEventInfo) {\n\t\tif (info.target !== 'selection') return\n\t\tconst { handle } = info\n\n\t\t// If handle is missing, we can't determine which edge was clicked\n\t\tif (!handle) return\n\n\t\tconst isHorizontalEdge = handle === 'left' || handle === 'right'\n\t\tconst isVerticalEdge = handle === 'top' || handle === 'bottom'\n\n\t\tconst childIds = this.editor.getSortedChildIdsForParent(shape.id)\n\t\tconst children = compact(childIds.map((id) => this.editor.getShape(id)))\n\t\tif (!children.length) return\n\n\t\tconst { dx, dy, w, h } = getFrameChildrenBounds(children, this.editor, { padding: 10 })\n\n\t\tthis.editor.run(() => {\n\t\t\tconst changes: TLShapePartial[] = childIds.map((childId) => {\n\t\t\t\tconst childShape = this.editor.getShape(childId)!\n\t\t\t\treturn {\n\t\t\t\t\tid: childShape.id,\n\t\t\t\t\ttype: childShape.type,\n\t\t\t\t\tx: isHorizontalEdge ? childShape.x + dx : childShape.x,\n\t\t\t\t\ty: isVerticalEdge ? childShape.y + dy : childShape.y,\n\t\t\t\t}\n\t\t\t})\n\n\t\t\tthis.editor.updateShapes(changes)\n\t\t})\n\n\t\treturn {\n\t\t\tid: shape.id,\n\t\t\ttype: shape.type,\n\t\t\tprops: {\n\t\t\t\tw: isHorizontalEdge ? w : shape.props.w,\n\t\t\t\th: isVerticalEdge ? h : shape.props.h,\n\t\t\t},\n\t\t}\n\t}\n\n\toverride onDoubleClickCorner(shape: TLFrameShape) {\n\t\tfitFrameToContent(this.editor, shape.id, { padding: 10 })\n\t\treturn {\n\t\t\tid: shape.id,\n\t\t\ttype: shape.type,\n\t\t}\n\t}\n\n\toverride onDragShapesIn(\n\t\tshape: TLFrameShape,\n\t\tdraggingShapes: TLShape[],\n\t\t{ initialParentIds, initialIndices }: TLDragShapesOverInfo\n\t) {\n\t\tconst { editor } = this\n\n\t\tif (draggingShapes.every((s) => s.parentId === shape.id)) return\n\n\t\t// Check to see whether any of the shapes can have their old index restored\n\t\tlet canRestoreOriginalIndices = false\n\t\tconst previousChildren = draggingShapes.filter((s) => shape.id === initialParentIds.get(s.id))\n\n\t\tif (previousChildren.length > 0) {\n\t\t\tconst currentChildren = compact(\n\t\t\t\teditor.getSortedChildIdsForParent(shape).map((id) => editor.getShape(id))\n\t\t\t)\n\t\t\tif (previousChildren.every((s) => !currentChildren.find((c) => c.index === s.index))) {\n\t\t\t\tcanRestoreOriginalIndices = true\n\t\t\t}\n\t\t}\n\n\t\t// I can't imagine this happening, but if any of the children are the ancestor of the frame, quit here\n\t\tif (draggingShapes.some((s) => editor.hasAncestor(shape, s.id))) return\n\n\t\t// Reparent the shapes to the new parent\n\t\teditor.reparentShapes(draggingShapes, shape.id)\n\n\t\t// If we can restore the original indices, then do so\n\t\tif (canRestoreOriginalIndices) {\n\t\t\tfor (const shape of previousChildren) {\n\t\t\t\teditor.updateShape({\n\t\t\t\t\tid: shape.id,\n\t\t\t\t\ttype: shape.type,\n\t\t\t\t\tindex: initialIndices.get(shape.id),\n\t\t\t\t})\n\t\t\t}\n\t\t}\n\t}\n\n\toverride onDragShapesOut(\n\t\tshape: TLFrameShape,\n\t\tdraggingShapes: TLShape[],\n\t\tinfo: TLDragShapesOutInfo\n\t): void {\n\t\tconst { editor } = this\n\t\t// When a user drags shapes out of a frame, and if we're not dragging into a new shape, then reparent\n\t\t// the dragging shapes (that are current children of the frame) onto the current page instead\n\t\tif (!info.nextDraggingOverShapeId) {\n\t\t\teditor.reparentShapes(\n\t\t\t\tdraggingShapes.filter(\n\t\t\t\t\t(s) => s.parentId === shape.id && this.canReceiveNewChildrenOfType(s)\n\t\t\t\t),\n\t\t\t\teditor.getCurrentPageId()\n\t\t\t)\n\t\t}\n\t}\n}\n"],
5
+ "mappings": "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",
6
6
  "names": ["classNames", "shape"]
7
7
  }
@@ -71,7 +71,7 @@ const FrameHeading = (0, import_react.memo)(function FrameHeading2({
71
71
  className: "tl-frame-heading",
72
72
  style: {
73
73
  overflow: isEditing ? "visible" : "hidden",
74
- maxWidth: `calc(var(--tl-zoom) * ${side === 0 || side === 2 ? Math.ceil(width) : Math.ceil(height)}px + ${showColors ? "0px" : "var(--frame-offset-width)"})`,
74
+ maxWidth: `calc(var(--tl-zoom) * ${side === 0 || side === 2 ? Math.ceil(width) : Math.ceil(height)}px + ${showColors ? "0px" : "var(--tl-frame-offset-width)"})`,
75
75
  bottom: "100%",
76
76
  transform: `${translation} scale(var(--tl-scale)) translateX(${offsetX}px)`
77
77
  },
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../../src/lib/shapes/frame/components/FrameHeading.tsx"],
4
- "sourcesContent": ["import { TLFrameShape, TLShapeId, useEditor, useIsEditing, useValue } from '@tldraw/editor'\nimport { memo, useEffect, useRef } from 'react'\nimport { getFrameHeadingSide, getFrameHeadingTranslation } from '../frameHelpers'\nimport { FrameLabelInput } from './FrameLabelInput'\n\nexport const FrameHeading = memo(function FrameHeading({\n\tid,\n\tname,\n\twidth,\n\theight,\n\tfill,\n\tstroke,\n\tcolor,\n\toffsetX,\n\tshowColors,\n}: {\n\tid: TLShapeId\n\tname: string\n\twidth: number\n\theight: number\n\tfill: string\n\tstroke: string\n\tcolor: string\n\toffsetX: number\n\tshowColors: boolean\n}) {\n\tconst editor = useEditor()\n\tconst { side, translation } = useValue(\n\t\t'shape rotation',\n\t\t() => {\n\t\t\tconst shape = editor.getShape<TLFrameShape>(id)\n\t\t\tif (!shape) {\n\t\t\t\t// meh\n\t\t\t\treturn {\n\t\t\t\t\tside: 0,\n\t\t\t\t\ttranslation: 'translate(0, 0)',\n\t\t\t\t}\n\t\t\t}\n\t\t\tconst labelSide = getFrameHeadingSide(editor, shape)\n\t\t\treturn {\n\t\t\t\tside: labelSide,\n\t\t\t\ttranslation: getFrameHeadingTranslation(shape, labelSide, false),\n\t\t\t}\n\t\t},\n\t\t[editor, offsetX, id]\n\t)\n\n\tconst rInput = useRef<HTMLInputElement>(null)\n\tconst isEditing = useIsEditing(id)\n\n\tuseEffect(() => {\n\t\tconst el = rInput.current\n\t\tif (el && isEditing) {\n\t\t\t// On iOS, we must focus here\n\t\t\tel.focus()\n\t\t\tel.select()\n\t\t}\n\t}, [rInput, isEditing])\n\n\treturn (\n\t\t<div\n\t\t\tclassName=\"tl-frame-heading\"\n\t\t\tstyle={{\n\t\t\t\toverflow: isEditing ? 'visible' : 'hidden',\n\t\t\t\tmaxWidth: `calc(var(--tl-zoom) * ${\n\t\t\t\t\tside === 0 || side === 2 ? Math.ceil(width) : Math.ceil(height)\n\t\t\t\t}px + ${showColors ? '0px' : 'var(--frame-offset-width)'})`,\n\t\t\t\tbottom: '100%',\n\t\t\t\ttransform: `${translation} scale(var(--tl-scale)) translateX(${offsetX}px)`,\n\t\t\t}}\n\t\t>\n\t\t\t<div\n\t\t\t\tclassName=\"tl-frame-heading-hit-area\"\n\t\t\t\tstyle={{ color, backgroundColor: fill, boxShadow: `inset 0px 0px 0px 1px ${stroke}` }}\n\t\t\t>\n\t\t\t\t<FrameLabelInput ref={rInput} id={id} name={name} isEditing={isEditing} />\n\t\t\t</div>\n\t\t</div>\n\t)\n})\n"],
5
- "mappings": ";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AA2EI;AA3EJ,oBAA2E;AAC3E,mBAAwC;AACxC,0BAAgE;AAChE,6BAAgC;AAEzB,MAAM,mBAAe,mBAAK,SAASA,cAAa;AAAA,EACtD;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACD,GAUG;AACF,QAAM,aAAS,yBAAU;AACzB,QAAM,EAAE,MAAM,YAAY,QAAI;AAAA,IAC7B;AAAA,IACA,MAAM;AACL,YAAM,QAAQ,OAAO,SAAuB,EAAE;AAC9C,UAAI,CAAC,OAAO;AAEX,eAAO;AAAA,UACN,MAAM;AAAA,UACN,aAAa;AAAA,QACd;AAAA,MACD;AACA,YAAM,gBAAY,yCAAoB,QAAQ,KAAK;AACnD,aAAO;AAAA,QACN,MAAM;AAAA,QACN,iBAAa,gDAA2B,OAAO,WAAW,KAAK;AAAA,MAChE;AAAA,IACD;AAAA,IACA,CAAC,QAAQ,SAAS,EAAE;AAAA,EACrB;AAEA,QAAM,aAAS,qBAAyB,IAAI;AAC5C,QAAM,gBAAY,4BAAa,EAAE;AAEjC,8BAAU,MAAM;AACf,UAAM,KAAK,OAAO;AAClB,QAAI,MAAM,WAAW;AAEpB,SAAG,MAAM;AACT,SAAG,OAAO;AAAA,IACX;AAAA,EACD,GAAG,CAAC,QAAQ,SAAS,CAAC;AAEtB,SACC;AAAA,IAAC;AAAA;AAAA,MACA,WAAU;AAAA,MACV,OAAO;AAAA,QACN,UAAU,YAAY,YAAY;AAAA,QAClC,UAAU,yBACT,SAAS,KAAK,SAAS,IAAI,KAAK,KAAK,KAAK,IAAI,KAAK,KAAK,MAAM,CAC/D,QAAQ,aAAa,QAAQ,2BAA2B;AAAA,QACxD,QAAQ;AAAA,QACR,WAAW,GAAG,WAAW,sCAAsC,OAAO;AAAA,MACvE;AAAA,MAEA;AAAA,QAAC;AAAA;AAAA,UACA,WAAU;AAAA,UACV,OAAO,EAAE,OAAO,iBAAiB,MAAM,WAAW,yBAAyB,MAAM,GAAG;AAAA,UAEpF,sDAAC,0CAAgB,KAAK,QAAQ,IAAQ,MAAY,WAAsB;AAAA;AAAA,MACzE;AAAA;AAAA,EACD;AAEF,CAAC;",
4
+ "sourcesContent": ["import { TLFrameShape, TLShapeId, useEditor, useIsEditing, useValue } from '@tldraw/editor'\nimport { memo, useEffect, useRef } from 'react'\nimport { getFrameHeadingSide, getFrameHeadingTranslation } from '../frameHelpers'\nimport { FrameLabelInput } from './FrameLabelInput'\n\nexport const FrameHeading = memo(function FrameHeading({\n\tid,\n\tname,\n\twidth,\n\theight,\n\tfill,\n\tstroke,\n\tcolor,\n\toffsetX,\n\tshowColors,\n}: {\n\tid: TLShapeId\n\tname: string\n\twidth: number\n\theight: number\n\tfill: string\n\tstroke: string\n\tcolor: string\n\toffsetX: number\n\tshowColors: boolean\n}) {\n\tconst editor = useEditor()\n\tconst { side, translation } = useValue(\n\t\t'shape rotation',\n\t\t() => {\n\t\t\tconst shape = editor.getShape<TLFrameShape>(id)\n\t\t\tif (!shape) {\n\t\t\t\t// meh\n\t\t\t\treturn {\n\t\t\t\t\tside: 0,\n\t\t\t\t\ttranslation: 'translate(0, 0)',\n\t\t\t\t}\n\t\t\t}\n\t\t\tconst labelSide = getFrameHeadingSide(editor, shape)\n\t\t\treturn {\n\t\t\t\tside: labelSide,\n\t\t\t\ttranslation: getFrameHeadingTranslation(shape, labelSide, false),\n\t\t\t}\n\t\t},\n\t\t[editor, offsetX, id]\n\t)\n\n\tconst rInput = useRef<HTMLInputElement>(null)\n\tconst isEditing = useIsEditing(id)\n\n\tuseEffect(() => {\n\t\tconst el = rInput.current\n\t\tif (el && isEditing) {\n\t\t\t// On iOS, we must focus here\n\t\t\tel.focus()\n\t\t\tel.select()\n\t\t}\n\t}, [rInput, isEditing])\n\n\treturn (\n\t\t<div\n\t\t\tclassName=\"tl-frame-heading\"\n\t\t\tstyle={{\n\t\t\t\toverflow: isEditing ? 'visible' : 'hidden',\n\t\t\t\tmaxWidth: `calc(var(--tl-zoom) * ${\n\t\t\t\t\tside === 0 || side === 2 ? Math.ceil(width) : Math.ceil(height)\n\t\t\t\t}px + ${showColors ? '0px' : 'var(--tl-frame-offset-width)'})`,\n\t\t\t\tbottom: '100%',\n\t\t\t\ttransform: `${translation} scale(var(--tl-scale)) translateX(${offsetX}px)`,\n\t\t\t}}\n\t\t>\n\t\t\t<div\n\t\t\t\tclassName=\"tl-frame-heading-hit-area\"\n\t\t\t\tstyle={{ color, backgroundColor: fill, boxShadow: `inset 0px 0px 0px 1px ${stroke}` }}\n\t\t\t>\n\t\t\t\t<FrameLabelInput ref={rInput} id={id} name={name} isEditing={isEditing} />\n\t\t\t</div>\n\t\t</div>\n\t)\n})\n"],
5
+ "mappings": ";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AA2EI;AA3EJ,oBAA2E;AAC3E,mBAAwC;AACxC,0BAAgE;AAChE,6BAAgC;AAEzB,MAAM,mBAAe,mBAAK,SAASA,cAAa;AAAA,EACtD;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACD,GAUG;AACF,QAAM,aAAS,yBAAU;AACzB,QAAM,EAAE,MAAM,YAAY,QAAI;AAAA,IAC7B;AAAA,IACA,MAAM;AACL,YAAM,QAAQ,OAAO,SAAuB,EAAE;AAC9C,UAAI,CAAC,OAAO;AAEX,eAAO;AAAA,UACN,MAAM;AAAA,UACN,aAAa;AAAA,QACd;AAAA,MACD;AACA,YAAM,gBAAY,yCAAoB,QAAQ,KAAK;AACnD,aAAO;AAAA,QACN,MAAM;AAAA,QACN,iBAAa,gDAA2B,OAAO,WAAW,KAAK;AAAA,MAChE;AAAA,IACD;AAAA,IACA,CAAC,QAAQ,SAAS,EAAE;AAAA,EACrB;AAEA,QAAM,aAAS,qBAAyB,IAAI;AAC5C,QAAM,gBAAY,4BAAa,EAAE;AAEjC,8BAAU,MAAM;AACf,UAAM,KAAK,OAAO;AAClB,QAAI,MAAM,WAAW;AAEpB,SAAG,MAAM;AACT,SAAG,OAAO;AAAA,IACX;AAAA,EACD,GAAG,CAAC,QAAQ,SAAS,CAAC;AAEtB,SACC;AAAA,IAAC;AAAA;AAAA,MACA,WAAU;AAAA,MACV,OAAO;AAAA,QACN,UAAU,YAAY,YAAY;AAAA,QAClC,UAAU,yBACT,SAAS,KAAK,SAAS,IAAI,KAAK,KAAK,KAAK,IAAI,KAAK,KAAK,MAAM,CAC/D,QAAQ,aAAa,QAAQ,8BAA8B;AAAA,QAC3D,QAAQ;AAAA,QACR,WAAW,GAAG,WAAW,sCAAsC,OAAO;AAAA,MACvE;AAAA,MAEA;AAAA,QAAC;AAAA;AAAA,UACA,WAAU;AAAA,UACV,OAAO,EAAE,OAAO,iBAAiB,MAAM,WAAW,yBAAyB,MAAM,GAAG;AAAA,UAEpF,sDAAC,0CAAgB,KAAK,QAAQ,IAAQ,MAAY,WAAsB;AAAA;AAAA,MACzE;AAAA;AAAA,EACD;AAEF,CAAC;",
6
6
  "names": ["FrameHeading"]
7
7
  }
@@ -253,9 +253,9 @@ const ImageShape = (0, import_react.memo)(function ImageShape2({ shape }) {
253
253
  overflow: "hidden",
254
254
  width: shape.props.w,
255
255
  height: shape.props.h,
256
- color: "var(--color-text-3)",
257
- backgroundColor: "var(--color-low)",
258
- border: "1px solid var(--color-low-border)"
256
+ color: "var(--tl-color-text-3)",
257
+ backgroundColor: "var(--tl-color-low)",
258
+ border: "1px solid var(--tl-color-low-border)"
259
259
  },
260
260
  children: [
261
261
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../src/lib/shapes/image/ImageShapeUtil.tsx"],
4
- "sourcesContent": ["import {\n\tBaseBoxShapeUtil,\n\tEditor,\n\tEllipse2d,\n\tFileHelpers,\n\tGeometry2d,\n\tHTMLContainer,\n\tImage,\n\tMediaHelpers,\n\tRectangle2d,\n\tSvgExportContext,\n\tTLAsset,\n\tTLAssetId,\n\tTLImageShape,\n\tTLImageShapeProps,\n\tTLResizeInfo,\n\tTLShapePartial,\n\tVec,\n\tWeakCache,\n\tfetch,\n\timageShapeMigrations,\n\timageShapeProps,\n\tlerp,\n\tmodulate,\n\tresizeBox,\n\tstructuredClone,\n\ttoDomPrecision,\n\tuseEditor,\n\tuseUniqueSafeId,\n\tuseValue,\n} from '@tldraw/editor'\nimport classNames from 'classnames'\nimport { memo, useEffect, useState } from 'react'\nimport { BrokenAssetIcon } from '../shared/BrokenAssetIcon'\nimport { HyperlinkButton } from '../shared/HyperlinkButton'\nimport { getUncroppedSize } from '../shared/crop'\nimport { useImageOrVideoAsset } from '../shared/useImageOrVideoAsset'\nimport { usePrefersReducedMotion } from '../shared/usePrefersReducedMotion'\n\nasync function getDataURIFromURL(url: string): Promise<string> {\n\tconst response = await fetch(url)\n\tconst blob = await response.blob()\n\treturn FileHelpers.blobToDataUrl(blob)\n}\n\nconst imageSvgExportCache = new WeakCache<TLAsset, Promise<string | null>>()\n\n/** @public */\nexport class ImageShapeUtil extends BaseBoxShapeUtil<TLImageShape> {\n\tstatic override type = 'image' as const\n\tstatic override props = imageShapeProps\n\tstatic override migrations = imageShapeMigrations\n\n\toverride isAspectRatioLocked() {\n\t\treturn true\n\t}\n\toverride canCrop() {\n\t\treturn true\n\t}\n\n\toverride getDefaultProps(): TLImageShape['props'] {\n\t\treturn {\n\t\t\tw: 100,\n\t\t\th: 100,\n\t\t\tassetId: null,\n\t\t\tplaying: true,\n\t\t\turl: '',\n\t\t\tcrop: null,\n\t\t\tflipX: false,\n\t\t\tflipY: false,\n\t\t\taltText: '',\n\t\t}\n\t}\n\n\toverride getGeometry(shape: TLImageShape): Geometry2d {\n\t\tif (shape.props.crop?.isCircle) {\n\t\t\treturn new Ellipse2d({\n\t\t\t\twidth: shape.props.w,\n\t\t\t\theight: shape.props.h,\n\t\t\t\tisFilled: true,\n\t\t\t})\n\t\t}\n\n\t\treturn new Rectangle2d({\n\t\t\twidth: shape.props.w,\n\t\t\theight: shape.props.h,\n\t\t\tisFilled: true,\n\t\t})\n\t}\n\n\toverride getAriaDescriptor(shape: TLImageShape) {\n\t\treturn shape.props.altText\n\t}\n\n\toverride onResize(shape: TLImageShape, info: TLResizeInfo<TLImageShape>) {\n\t\tlet resized: TLImageShape = resizeBox(shape, info)\n\t\tconst { flipX, flipY } = info.initialShape.props\n\t\tconst { scaleX, scaleY, mode } = info\n\n\t\tresized = {\n\t\t\t...resized,\n\t\t\tprops: {\n\t\t\t\t...resized.props,\n\t\t\t\tflipX: scaleX < 0 !== flipX,\n\t\t\t\tflipY: scaleY < 0 !== flipY,\n\t\t\t},\n\t\t}\n\t\tif (!shape.props.crop) return resized\n\n\t\tconst flipCropHorizontally =\n\t\t\t// We used the flip horizontally feature\n\t\t\t(mode === 'scale_shape' && scaleX === -1) ||\n\t\t\t// We resized the shape past it's bounds, so it flipped\n\t\t\t(mode === 'resize_bounds' && flipX !== resized.props.flipX)\n\t\tconst flipCropVertically =\n\t\t\t// We used the flip vertically feature\n\t\t\t(mode === 'scale_shape' && scaleY === -1) ||\n\t\t\t// We resized the shape past it's bounds, so it flipped\n\t\t\t(mode === 'resize_bounds' && flipY !== resized.props.flipY)\n\n\t\tconst { topLeft, bottomRight } = shape.props.crop\n\t\tresized.props.crop = {\n\t\t\ttopLeft: {\n\t\t\t\tx: flipCropHorizontally ? 1 - bottomRight.x : topLeft.x,\n\t\t\t\ty: flipCropVertically ? 1 - bottomRight.y : topLeft.y,\n\t\t\t},\n\t\t\tbottomRight: {\n\t\t\t\tx: flipCropHorizontally ? 1 - topLeft.x : bottomRight.x,\n\t\t\t\ty: flipCropVertically ? 1 - topLeft.y : bottomRight.y,\n\t\t\t},\n\t\t\tisCircle: shape.props.crop.isCircle,\n\t\t}\n\t\treturn resized\n\t}\n\n\tcomponent(shape: TLImageShape) {\n\t\treturn <ImageShape shape={shape} />\n\t}\n\n\tindicator(shape: TLImageShape) {\n\t\tconst isCropping = this.editor.getCroppingShapeId() === shape.id\n\t\tif (isCropping) return null\n\n\t\tif (shape.props.crop?.isCircle) {\n\t\t\treturn (\n\t\t\t\t<ellipse\n\t\t\t\t\tcx={toDomPrecision(shape.props.w / 2)}\n\t\t\t\t\tcy={toDomPrecision(shape.props.h / 2)}\n\t\t\t\t\trx={toDomPrecision(shape.props.w / 2)}\n\t\t\t\t\try={toDomPrecision(shape.props.h / 2)}\n\t\t\t\t/>\n\t\t\t)\n\t\t}\n\n\t\treturn <rect width={toDomPrecision(shape.props.w)} height={toDomPrecision(shape.props.h)} />\n\t}\n\n\toverride async toSvg(shape: TLImageShape, ctx: SvgExportContext) {\n\t\tconst props = shape.props\n\t\tif (!props.assetId) return null\n\n\t\tconst asset = this.editor.getAsset(props.assetId)\n\n\t\tif (!asset) return null\n\n\t\tconst { w } = getUncroppedSize(shape.props, props.crop)\n\n\t\tconst src = await imageSvgExportCache.get(asset, async () => {\n\t\t\tlet src = await ctx.resolveAssetUrl(asset.id, w)\n\t\t\tif (!src) return null\n\t\t\tif (\n\t\t\t\tsrc.startsWith('blob:') ||\n\t\t\t\tsrc.startsWith('http') ||\n\t\t\t\tsrc.startsWith('/') ||\n\t\t\t\tsrc.startsWith('./')\n\t\t\t) {\n\t\t\t\t// If it's a remote image, we need to fetch it and convert it to a data URI\n\t\t\t\tsrc = (await getDataURIFromURL(src)) || ''\n\t\t\t}\n\n\t\t\t// If it's animated then we need to get the first frame\n\t\t\tif (getIsAnimated(this.editor, asset.id)) {\n\t\t\t\tconst { promise } = getFirstFrameOfAnimatedImage(src)\n\t\t\t\tsrc = await promise\n\t\t\t}\n\t\t\treturn src\n\t\t})\n\n\t\tif (!src) return null\n\n\t\treturn <SvgImage shape={shape} src={src} />\n\t}\n\n\toverride onDoubleClickEdge(shape: TLImageShape) {\n\t\tconst props = shape.props\n\t\tif (!props) return\n\n\t\tif (this.editor.getCroppingShapeId() !== shape.id) {\n\t\t\treturn\n\t\t}\n\n\t\tconst crop = structuredClone(props.crop) || {\n\t\t\ttopLeft: { x: 0, y: 0 },\n\t\t\tbottomRight: { x: 1, y: 1 },\n\t\t}\n\n\t\t// The true asset dimensions\n\t\tconst { w, h } = getUncroppedSize(shape.props, crop)\n\n\t\tconst pointDelta = new Vec(crop.topLeft.x * w, crop.topLeft.y * h).rot(shape.rotation)\n\n\t\tconst partial: TLShapePartial<TLImageShape> = {\n\t\t\tid: shape.id,\n\t\t\ttype: shape.type,\n\t\t\tx: shape.x - pointDelta.x,\n\t\t\ty: shape.y - pointDelta.y,\n\t\t\tprops: {\n\t\t\t\tcrop: {\n\t\t\t\t\ttopLeft: { x: 0, y: 0 },\n\t\t\t\t\tbottomRight: { x: 1, y: 1 },\n\t\t\t\t},\n\t\t\t\tw,\n\t\t\t\th,\n\t\t\t},\n\t\t}\n\n\t\tthis.editor.updateShapes([partial])\n\t}\n\toverride getInterpolatedProps(\n\t\tstartShape: TLImageShape,\n\t\tendShape: TLImageShape,\n\t\tt: number\n\t): TLImageShapeProps {\n\t\tfunction interpolateCrop(\n\t\t\tstartShape: TLImageShape,\n\t\t\tendShape: TLImageShape\n\t\t): TLImageShapeProps['crop'] {\n\t\t\tif (startShape.props.crop === null && endShape.props.crop === null) return null\n\n\t\t\tconst startTL = startShape.props.crop?.topLeft || { x: 0, y: 0 }\n\t\t\tconst startBR = startShape.props.crop?.bottomRight || { x: 1, y: 1 }\n\t\t\tconst endTL = endShape.props.crop?.topLeft || { x: 0, y: 0 }\n\t\t\tconst endBR = endShape.props.crop?.bottomRight || { x: 1, y: 1 }\n\n\t\t\treturn {\n\t\t\t\ttopLeft: { x: lerp(startTL.x, endTL.x, t), y: lerp(startTL.y, endTL.y, t) },\n\t\t\t\tbottomRight: { x: lerp(startBR.x, endBR.x, t), y: lerp(startBR.y, endBR.y, t) },\n\t\t\t}\n\t\t}\n\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\tcrop: interpolateCrop(startShape, endShape),\n\t\t}\n\t}\n}\n\nconst ImageShape = memo(function ImageShape({ shape }: { shape: TLImageShape }) {\n\tconst editor = useEditor()\n\n\tconst { w } = getUncroppedSize(shape.props, shape.props.crop)\n\tconst { asset, url } = useImageOrVideoAsset({\n\t\tshapeId: shape.id,\n\t\tassetId: shape.props.assetId,\n\t\twidth: w,\n\t})\n\n\tconst prefersReducedMotion = usePrefersReducedMotion()\n\tconst [staticFrameSrc, setStaticFrameSrc] = useState('')\n\tconst [loadedUrl, setLoadedUrl] = useState<null | string>(null)\n\tconst isAnimated = asset && getIsAnimated(editor, asset.id)\n\n\tuseEffect(() => {\n\t\tif (url && isAnimated) {\n\t\t\tconst { promise, cancel } = getFirstFrameOfAnimatedImage(url)\n\n\t\t\tpromise.then((dataUrl) => {\n\t\t\t\tsetStaticFrameSrc(dataUrl)\n\t\t\t\tsetLoadedUrl(url)\n\t\t\t})\n\n\t\t\treturn () => {\n\t\t\t\tcancel()\n\t\t\t}\n\t\t}\n\t}, [editor, isAnimated, prefersReducedMotion, url])\n\n\tconst showCropPreview = useValue(\n\t\t'show crop preview',\n\t\t() =>\n\t\t\tshape.id === editor.getOnlySelectedShapeId() &&\n\t\t\teditor.getCroppingShapeId() === shape.id &&\n\t\t\teditor.isIn('select.crop'),\n\t\t[editor, shape.id]\n\t)\n\n\t// We only want to reduce motion for mimeTypes that have motion\n\tconst reduceMotion =\n\t\tprefersReducedMotion && (asset?.props.mimeType?.includes('video') || isAnimated)\n\n\tconst containerStyle = getCroppedContainerStyle(shape)\n\n\tconst nextSrc = url === loadedUrl ? null : url\n\tconst loadedSrc = reduceMotion ? staticFrameSrc : loadedUrl\n\n\t// This logic path is for when it's broken/missing asset.\n\tif (!url && !asset?.props.src) {\n\t\treturn (\n\t\t\t<HTMLContainer\n\t\t\t\tid={shape.id}\n\t\t\t\tstyle={{\n\t\t\t\t\toverflow: 'hidden',\n\t\t\t\t\twidth: shape.props.w,\n\t\t\t\t\theight: shape.props.h,\n\t\t\t\t\tcolor: 'var(--color-text-3)',\n\t\t\t\t\tbackgroundColor: 'var(--color-low)',\n\t\t\t\t\tborder: '1px solid var(--color-low-border)',\n\t\t\t\t}}\n\t\t\t>\n\t\t\t\t<div\n\t\t\t\t\tclassName={classNames('tl-image-container', asset && 'tl-image-container-loading')}\n\t\t\t\t\tstyle={containerStyle}\n\t\t\t\t>\n\t\t\t\t\t{asset ? null : <BrokenAssetIcon />}\n\t\t\t\t</div>\n\t\t\t\t{'url' in shape.props && shape.props.url && <HyperlinkButton url={shape.props.url} />}\n\t\t\t</HTMLContainer>\n\t\t)\n\t}\n\n\t// We don't set crossOrigin for non-animated images because for Cloudflare we don't currently\n\t// have that set up.\n\tconst crossOrigin = isAnimated ? 'anonymous' : undefined\n\n\treturn (\n\t\t<>\n\t\t\t{showCropPreview && loadedSrc && (\n\t\t\t\t<div style={containerStyle}>\n\t\t\t\t\t<img\n\t\t\t\t\t\tclassName=\"tl-image\"\n\t\t\t\t\t\tstyle={{ ...getFlipStyle(shape), opacity: 0.1 }}\n\t\t\t\t\t\tcrossOrigin={crossOrigin}\n\t\t\t\t\t\tsrc={loadedSrc}\n\t\t\t\t\t\treferrerPolicy=\"strict-origin-when-cross-origin\"\n\t\t\t\t\t\tdraggable={false}\n\t\t\t\t\t\talt=\"\"\n\t\t\t\t\t/>\n\t\t\t\t</div>\n\t\t\t)}\n\t\t\t<HTMLContainer\n\t\t\t\tid={shape.id}\n\t\t\t\tstyle={{\n\t\t\t\t\toverflow: 'hidden',\n\t\t\t\t\twidth: shape.props.w,\n\t\t\t\t\theight: shape.props.h,\n\t\t\t\t\tborderRadius: shape.props.crop?.isCircle ? '50%' : undefined,\n\t\t\t\t}}\n\t\t\t>\n\t\t\t\t<div className={classNames('tl-image-container')} style={containerStyle}>\n\t\t\t\t\t{/* We have two images: the currently loaded image, and the next image that\n\t\t\t\t\twe're waiting to load. we keep the loaded image mounted while we're waiting\n\t\t\t\t\tfor the next one by storing the loaded URL in state. We use `key` props with\n\t\t\t\t\tthe src of the image so that when the next image is ready, the previous one will\n\t\t\t\t\tbe unmounted and the next will be shown with the browser having to remount a\n\t\t\t\t\tfresh image and decoded it again from the cache. */}\n\t\t\t\t\t{loadedSrc && (\n\t\t\t\t\t\t<img\n\t\t\t\t\t\t\tkey={loadedSrc}\n\t\t\t\t\t\t\tclassName=\"tl-image\"\n\t\t\t\t\t\t\tstyle={getFlipStyle(shape)}\n\t\t\t\t\t\t\tcrossOrigin={crossOrigin}\n\t\t\t\t\t\t\tsrc={loadedSrc}\n\t\t\t\t\t\t\treferrerPolicy=\"strict-origin-when-cross-origin\"\n\t\t\t\t\t\t\tdraggable={false}\n\t\t\t\t\t\t\talt=\"\"\n\t\t\t\t\t\t/>\n\t\t\t\t\t)}\n\t\t\t\t\t{nextSrc && (\n\t\t\t\t\t\t<img\n\t\t\t\t\t\t\tkey={nextSrc}\n\t\t\t\t\t\t\tclassName=\"tl-image\"\n\t\t\t\t\t\t\tstyle={getFlipStyle(shape)}\n\t\t\t\t\t\t\tcrossOrigin={crossOrigin}\n\t\t\t\t\t\t\tsrc={nextSrc}\n\t\t\t\t\t\t\treferrerPolicy=\"strict-origin-when-cross-origin\"\n\t\t\t\t\t\t\tdraggable={false}\n\t\t\t\t\t\t\talt={shape.props.altText}\n\t\t\t\t\t\t\tonLoad={() => setLoadedUrl(nextSrc)}\n\t\t\t\t\t\t/>\n\t\t\t\t\t)}\n\t\t\t\t</div>\n\t\t\t\t{shape.props.url && <HyperlinkButton url={shape.props.url} />}\n\t\t\t</HTMLContainer>\n\t\t</>\n\t)\n})\n\nfunction getIsAnimated(editor: Editor, assetId: TLAssetId) {\n\tconst asset = assetId ? editor.getAsset(assetId) : undefined\n\n\tif (!asset) return false\n\n\treturn (\n\t\t('mimeType' in asset.props && MediaHelpers.isAnimatedImageType(asset?.props.mimeType)) ||\n\t\t('isAnimated' in asset.props && asset.props.isAnimated)\n\t)\n}\n\n/**\n * When an image is cropped we need to translate the image to show the portion withing the cropped\n * area. We do this by translating the image by the negative of the top left corner of the crop\n * area.\n *\n * @param shape - Shape The image shape for which to get the container style\n * @returns - Styles to apply to the image container\n */\nfunction getCroppedContainerStyle(shape: TLImageShape) {\n\tconst crop = shape.props.crop\n\tconst topLeft = crop?.topLeft\n\tif (!topLeft) {\n\t\treturn {\n\t\t\twidth: shape.props.w,\n\t\t\theight: shape.props.h,\n\t\t}\n\t}\n\n\tconst { w, h } = getUncroppedSize(shape.props, crop)\n\tconst offsetX = -topLeft.x * w\n\tconst offsetY = -topLeft.y * h\n\treturn {\n\t\ttransform: `translate(${offsetX}px, ${offsetY}px)`,\n\t\twidth: w,\n\t\theight: h,\n\t}\n}\n\nfunction getFlipStyle(shape: TLImageShape, size?: { width: number; height: number }) {\n\tconst { flipX, flipY, crop } = shape.props\n\tif (!flipX && !flipY) return undefined\n\n\tlet cropOffsetX\n\tlet cropOffsetY\n\tif (crop) {\n\t\t// We have to do all this extra math because of the whole transform origin around 0,0\n\t\t// instead of center in SVG-land, ugh.\n\t\tconst { w, h } = getUncroppedSize(shape.props, crop)\n\n\t\t// Find the resulting w/h of the crop in normalized (0-1) coordinates\n\t\tconst cropWidth = crop.bottomRight.x - crop.topLeft.x\n\t\tconst cropHeight = crop.bottomRight.y - crop.topLeft.y\n\n\t\t// Map from the normalized crop coordinate space to shape pixel space\n\t\tcropOffsetX = modulate(crop.topLeft.x, [0, 1 - cropWidth], [0, w - shape.props.w])\n\t\tcropOffsetY = modulate(crop.topLeft.y, [0, 1 - cropHeight], [0, h - shape.props.h])\n\t}\n\n\tconst scale = `scale(${flipX ? -1 : 1}, ${flipY ? -1 : 1})`\n\tconst translate = size\n\t\t? `translate(${(flipX ? size.width : 0) - (cropOffsetX ? cropOffsetX : 0)}px,\n\t\t ${(flipY ? size.height : 0) - (cropOffsetY ? cropOffsetY : 0)}px)`\n\t\t: ''\n\n\treturn {\n\t\ttransform: `${translate} ${scale}`,\n\t\t// in SVG, flipping around the center doesn't work so we use explicit width/height\n\t\ttransformOrigin: size ? '0 0' : 'center center',\n\t}\n}\n\nfunction SvgImage({ shape, src }: { shape: TLImageShape; src: string }) {\n\tconst cropClipId = useUniqueSafeId()\n\tconst containerStyle = getCroppedContainerStyle(shape)\n\tconst crop = shape.props.crop\n\n\tif (containerStyle.transform && crop) {\n\t\tconst { transform: cropTransform, width, height } = containerStyle\n\t\tconst croppedWidth = (crop.bottomRight.x - crop.topLeft.x) * width\n\t\tconst croppedHeight = (crop.bottomRight.y - crop.topLeft.y) * height\n\n\t\tconst points = [\n\t\t\tnew Vec(0, 0),\n\t\t\tnew Vec(croppedWidth, 0),\n\t\t\tnew Vec(croppedWidth, croppedHeight),\n\t\t\tnew Vec(0, croppedHeight),\n\t\t]\n\n\t\tconst flip = getFlipStyle(shape, { width, height })\n\n\t\treturn (\n\t\t\t<>\n\t\t\t\t<defs>\n\t\t\t\t\t<clipPath id={cropClipId}>\n\t\t\t\t\t\t{crop.isCircle ? (\n\t\t\t\t\t\t\t<ellipse\n\t\t\t\t\t\t\t\tcx={croppedWidth / 2}\n\t\t\t\t\t\t\t\tcy={croppedHeight / 2}\n\t\t\t\t\t\t\t\trx={croppedWidth / 2}\n\t\t\t\t\t\t\t\try={croppedHeight / 2}\n\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t) : (\n\t\t\t\t\t\t\t<polygon points={points.map((p) => `${p.x},${p.y}`).join(' ')} />\n\t\t\t\t\t\t)}\n\t\t\t\t\t</clipPath>\n\t\t\t\t</defs>\n\t\t\t\t<g clipPath={`url(#${cropClipId})`}>\n\t\t\t\t\t<image\n\t\t\t\t\t\thref={src}\n\t\t\t\t\t\twidth={width}\n\t\t\t\t\t\theight={height}\n\t\t\t\t\t\taria-label={shape.props.altText}\n\t\t\t\t\t\tstyle={flip ? { ...flip } : { transform: cropTransform }}\n\t\t\t\t\t/>\n\t\t\t\t</g>\n\t\t\t</>\n\t\t)\n\t} else {\n\t\treturn (\n\t\t\t<image\n\t\t\t\thref={src}\n\t\t\t\twidth={shape.props.w}\n\t\t\t\theight={shape.props.h}\n\t\t\t\taria-label={shape.props.altText}\n\t\t\t\tstyle={getFlipStyle(shape, { width: shape.props.w, height: shape.props.h })}\n\t\t\t/>\n\t\t)\n\t}\n}\n\nfunction getFirstFrameOfAnimatedImage(url: string) {\n\tlet cancelled = false\n\n\tconst promise = new Promise<string>((resolve) => {\n\t\tconst image = Image()\n\t\timage.onload = () => {\n\t\t\tif (cancelled) return\n\n\t\t\tconst canvas = document.createElement('canvas')\n\t\t\tcanvas.width = image.width\n\t\t\tcanvas.height = image.height\n\n\t\t\tconst ctx = canvas.getContext('2d')\n\t\t\tif (!ctx) return\n\n\t\t\tctx.drawImage(image, 0, 0)\n\t\t\tresolve(canvas.toDataURL())\n\t\t}\n\t\timage.crossOrigin = 'anonymous'\n\t\timage.src = url\n\t})\n\n\treturn { promise, cancel: () => (cancelled = true) }\n}\n"],
4
+ "sourcesContent": ["import {\n\tBaseBoxShapeUtil,\n\tEditor,\n\tEllipse2d,\n\tFileHelpers,\n\tGeometry2d,\n\tHTMLContainer,\n\tImage,\n\tMediaHelpers,\n\tRectangle2d,\n\tSvgExportContext,\n\tTLAsset,\n\tTLAssetId,\n\tTLImageShape,\n\tTLImageShapeProps,\n\tTLResizeInfo,\n\tTLShapePartial,\n\tVec,\n\tWeakCache,\n\tfetch,\n\timageShapeMigrations,\n\timageShapeProps,\n\tlerp,\n\tmodulate,\n\tresizeBox,\n\tstructuredClone,\n\ttoDomPrecision,\n\tuseEditor,\n\tuseUniqueSafeId,\n\tuseValue,\n} from '@tldraw/editor'\nimport classNames from 'classnames'\nimport { memo, useEffect, useState } from 'react'\nimport { BrokenAssetIcon } from '../shared/BrokenAssetIcon'\nimport { HyperlinkButton } from '../shared/HyperlinkButton'\nimport { getUncroppedSize } from '../shared/crop'\nimport { useImageOrVideoAsset } from '../shared/useImageOrVideoAsset'\nimport { usePrefersReducedMotion } from '../shared/usePrefersReducedMotion'\n\nasync function getDataURIFromURL(url: string): Promise<string> {\n\tconst response = await fetch(url)\n\tconst blob = await response.blob()\n\treturn FileHelpers.blobToDataUrl(blob)\n}\n\nconst imageSvgExportCache = new WeakCache<TLAsset, Promise<string | null>>()\n\n/** @public */\nexport class ImageShapeUtil extends BaseBoxShapeUtil<TLImageShape> {\n\tstatic override type = 'image' as const\n\tstatic override props = imageShapeProps\n\tstatic override migrations = imageShapeMigrations\n\n\toverride isAspectRatioLocked() {\n\t\treturn true\n\t}\n\toverride canCrop() {\n\t\treturn true\n\t}\n\n\toverride getDefaultProps(): TLImageShape['props'] {\n\t\treturn {\n\t\t\tw: 100,\n\t\t\th: 100,\n\t\t\tassetId: null,\n\t\t\tplaying: true,\n\t\t\turl: '',\n\t\t\tcrop: null,\n\t\t\tflipX: false,\n\t\t\tflipY: false,\n\t\t\taltText: '',\n\t\t}\n\t}\n\n\toverride getGeometry(shape: TLImageShape): Geometry2d {\n\t\tif (shape.props.crop?.isCircle) {\n\t\t\treturn new Ellipse2d({\n\t\t\t\twidth: shape.props.w,\n\t\t\t\theight: shape.props.h,\n\t\t\t\tisFilled: true,\n\t\t\t})\n\t\t}\n\n\t\treturn new Rectangle2d({\n\t\t\twidth: shape.props.w,\n\t\t\theight: shape.props.h,\n\t\t\tisFilled: true,\n\t\t})\n\t}\n\n\toverride getAriaDescriptor(shape: TLImageShape) {\n\t\treturn shape.props.altText\n\t}\n\n\toverride onResize(shape: TLImageShape, info: TLResizeInfo<TLImageShape>) {\n\t\tlet resized: TLImageShape = resizeBox(shape, info)\n\t\tconst { flipX, flipY } = info.initialShape.props\n\t\tconst { scaleX, scaleY, mode } = info\n\n\t\tresized = {\n\t\t\t...resized,\n\t\t\tprops: {\n\t\t\t\t...resized.props,\n\t\t\t\tflipX: scaleX < 0 !== flipX,\n\t\t\t\tflipY: scaleY < 0 !== flipY,\n\t\t\t},\n\t\t}\n\t\tif (!shape.props.crop) return resized\n\n\t\tconst flipCropHorizontally =\n\t\t\t// We used the flip horizontally feature\n\t\t\t(mode === 'scale_shape' && scaleX === -1) ||\n\t\t\t// We resized the shape past it's bounds, so it flipped\n\t\t\t(mode === 'resize_bounds' && flipX !== resized.props.flipX)\n\t\tconst flipCropVertically =\n\t\t\t// We used the flip vertically feature\n\t\t\t(mode === 'scale_shape' && scaleY === -1) ||\n\t\t\t// We resized the shape past it's bounds, so it flipped\n\t\t\t(mode === 'resize_bounds' && flipY !== resized.props.flipY)\n\n\t\tconst { topLeft, bottomRight } = shape.props.crop\n\t\tresized.props.crop = {\n\t\t\ttopLeft: {\n\t\t\t\tx: flipCropHorizontally ? 1 - bottomRight.x : topLeft.x,\n\t\t\t\ty: flipCropVertically ? 1 - bottomRight.y : topLeft.y,\n\t\t\t},\n\t\t\tbottomRight: {\n\t\t\t\tx: flipCropHorizontally ? 1 - topLeft.x : bottomRight.x,\n\t\t\t\ty: flipCropVertically ? 1 - topLeft.y : bottomRight.y,\n\t\t\t},\n\t\t\tisCircle: shape.props.crop.isCircle,\n\t\t}\n\t\treturn resized\n\t}\n\n\tcomponent(shape: TLImageShape) {\n\t\treturn <ImageShape shape={shape} />\n\t}\n\n\tindicator(shape: TLImageShape) {\n\t\tconst isCropping = this.editor.getCroppingShapeId() === shape.id\n\t\tif (isCropping) return null\n\n\t\tif (shape.props.crop?.isCircle) {\n\t\t\treturn (\n\t\t\t\t<ellipse\n\t\t\t\t\tcx={toDomPrecision(shape.props.w / 2)}\n\t\t\t\t\tcy={toDomPrecision(shape.props.h / 2)}\n\t\t\t\t\trx={toDomPrecision(shape.props.w / 2)}\n\t\t\t\t\try={toDomPrecision(shape.props.h / 2)}\n\t\t\t\t/>\n\t\t\t)\n\t\t}\n\n\t\treturn <rect width={toDomPrecision(shape.props.w)} height={toDomPrecision(shape.props.h)} />\n\t}\n\n\toverride async toSvg(shape: TLImageShape, ctx: SvgExportContext) {\n\t\tconst props = shape.props\n\t\tif (!props.assetId) return null\n\n\t\tconst asset = this.editor.getAsset(props.assetId)\n\n\t\tif (!asset) return null\n\n\t\tconst { w } = getUncroppedSize(shape.props, props.crop)\n\n\t\tconst src = await imageSvgExportCache.get(asset, async () => {\n\t\t\tlet src = await ctx.resolveAssetUrl(asset.id, w)\n\t\t\tif (!src) return null\n\t\t\tif (\n\t\t\t\tsrc.startsWith('blob:') ||\n\t\t\t\tsrc.startsWith('http') ||\n\t\t\t\tsrc.startsWith('/') ||\n\t\t\t\tsrc.startsWith('./')\n\t\t\t) {\n\t\t\t\t// If it's a remote image, we need to fetch it and convert it to a data URI\n\t\t\t\tsrc = (await getDataURIFromURL(src)) || ''\n\t\t\t}\n\n\t\t\t// If it's animated then we need to get the first frame\n\t\t\tif (getIsAnimated(this.editor, asset.id)) {\n\t\t\t\tconst { promise } = getFirstFrameOfAnimatedImage(src)\n\t\t\t\tsrc = await promise\n\t\t\t}\n\t\t\treturn src\n\t\t})\n\n\t\tif (!src) return null\n\n\t\treturn <SvgImage shape={shape} src={src} />\n\t}\n\n\toverride onDoubleClickEdge(shape: TLImageShape) {\n\t\tconst props = shape.props\n\t\tif (!props) return\n\n\t\tif (this.editor.getCroppingShapeId() !== shape.id) {\n\t\t\treturn\n\t\t}\n\n\t\tconst crop = structuredClone(props.crop) || {\n\t\t\ttopLeft: { x: 0, y: 0 },\n\t\t\tbottomRight: { x: 1, y: 1 },\n\t\t}\n\n\t\t// The true asset dimensions\n\t\tconst { w, h } = getUncroppedSize(shape.props, crop)\n\n\t\tconst pointDelta = new Vec(crop.topLeft.x * w, crop.topLeft.y * h).rot(shape.rotation)\n\n\t\tconst partial: TLShapePartial<TLImageShape> = {\n\t\t\tid: shape.id,\n\t\t\ttype: shape.type,\n\t\t\tx: shape.x - pointDelta.x,\n\t\t\ty: shape.y - pointDelta.y,\n\t\t\tprops: {\n\t\t\t\tcrop: {\n\t\t\t\t\ttopLeft: { x: 0, y: 0 },\n\t\t\t\t\tbottomRight: { x: 1, y: 1 },\n\t\t\t\t},\n\t\t\t\tw,\n\t\t\t\th,\n\t\t\t},\n\t\t}\n\n\t\tthis.editor.updateShapes([partial])\n\t}\n\toverride getInterpolatedProps(\n\t\tstartShape: TLImageShape,\n\t\tendShape: TLImageShape,\n\t\tt: number\n\t): TLImageShapeProps {\n\t\tfunction interpolateCrop(\n\t\t\tstartShape: TLImageShape,\n\t\t\tendShape: TLImageShape\n\t\t): TLImageShapeProps['crop'] {\n\t\t\tif (startShape.props.crop === null && endShape.props.crop === null) return null\n\n\t\t\tconst startTL = startShape.props.crop?.topLeft || { x: 0, y: 0 }\n\t\t\tconst startBR = startShape.props.crop?.bottomRight || { x: 1, y: 1 }\n\t\t\tconst endTL = endShape.props.crop?.topLeft || { x: 0, y: 0 }\n\t\t\tconst endBR = endShape.props.crop?.bottomRight || { x: 1, y: 1 }\n\n\t\t\treturn {\n\t\t\t\ttopLeft: { x: lerp(startTL.x, endTL.x, t), y: lerp(startTL.y, endTL.y, t) },\n\t\t\t\tbottomRight: { x: lerp(startBR.x, endBR.x, t), y: lerp(startBR.y, endBR.y, t) },\n\t\t\t}\n\t\t}\n\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\tcrop: interpolateCrop(startShape, endShape),\n\t\t}\n\t}\n}\n\nconst ImageShape = memo(function ImageShape({ shape }: { shape: TLImageShape }) {\n\tconst editor = useEditor()\n\n\tconst { w } = getUncroppedSize(shape.props, shape.props.crop)\n\tconst { asset, url } = useImageOrVideoAsset({\n\t\tshapeId: shape.id,\n\t\tassetId: shape.props.assetId,\n\t\twidth: w,\n\t})\n\n\tconst prefersReducedMotion = usePrefersReducedMotion()\n\tconst [staticFrameSrc, setStaticFrameSrc] = useState('')\n\tconst [loadedUrl, setLoadedUrl] = useState<null | string>(null)\n\tconst isAnimated = asset && getIsAnimated(editor, asset.id)\n\n\tuseEffect(() => {\n\t\tif (url && isAnimated) {\n\t\t\tconst { promise, cancel } = getFirstFrameOfAnimatedImage(url)\n\n\t\t\tpromise.then((dataUrl) => {\n\t\t\t\tsetStaticFrameSrc(dataUrl)\n\t\t\t\tsetLoadedUrl(url)\n\t\t\t})\n\n\t\t\treturn () => {\n\t\t\t\tcancel()\n\t\t\t}\n\t\t}\n\t}, [editor, isAnimated, prefersReducedMotion, url])\n\n\tconst showCropPreview = useValue(\n\t\t'show crop preview',\n\t\t() =>\n\t\t\tshape.id === editor.getOnlySelectedShapeId() &&\n\t\t\teditor.getCroppingShapeId() === shape.id &&\n\t\t\teditor.isIn('select.crop'),\n\t\t[editor, shape.id]\n\t)\n\n\t// We only want to reduce motion for mimeTypes that have motion\n\tconst reduceMotion =\n\t\tprefersReducedMotion && (asset?.props.mimeType?.includes('video') || isAnimated)\n\n\tconst containerStyle = getCroppedContainerStyle(shape)\n\n\tconst nextSrc = url === loadedUrl ? null : url\n\tconst loadedSrc = reduceMotion ? staticFrameSrc : loadedUrl\n\n\t// This logic path is for when it's broken/missing asset.\n\tif (!url && !asset?.props.src) {\n\t\treturn (\n\t\t\t<HTMLContainer\n\t\t\t\tid={shape.id}\n\t\t\t\tstyle={{\n\t\t\t\t\toverflow: 'hidden',\n\t\t\t\t\twidth: shape.props.w,\n\t\t\t\t\theight: shape.props.h,\n\t\t\t\t\tcolor: 'var(--tl-color-text-3)',\n\t\t\t\t\tbackgroundColor: 'var(--tl-color-low)',\n\t\t\t\t\tborder: '1px solid var(--tl-color-low-border)',\n\t\t\t\t}}\n\t\t\t>\n\t\t\t\t<div\n\t\t\t\t\tclassName={classNames('tl-image-container', asset && 'tl-image-container-loading')}\n\t\t\t\t\tstyle={containerStyle}\n\t\t\t\t>\n\t\t\t\t\t{asset ? null : <BrokenAssetIcon />}\n\t\t\t\t</div>\n\t\t\t\t{'url' in shape.props && shape.props.url && <HyperlinkButton url={shape.props.url} />}\n\t\t\t</HTMLContainer>\n\t\t)\n\t}\n\n\t// We don't set crossOrigin for non-animated images because for Cloudflare we don't currently\n\t// have that set up.\n\tconst crossOrigin = isAnimated ? 'anonymous' : undefined\n\n\treturn (\n\t\t<>\n\t\t\t{showCropPreview && loadedSrc && (\n\t\t\t\t<div style={containerStyle}>\n\t\t\t\t\t<img\n\t\t\t\t\t\tclassName=\"tl-image\"\n\t\t\t\t\t\tstyle={{ ...getFlipStyle(shape), opacity: 0.1 }}\n\t\t\t\t\t\tcrossOrigin={crossOrigin}\n\t\t\t\t\t\tsrc={loadedSrc}\n\t\t\t\t\t\treferrerPolicy=\"strict-origin-when-cross-origin\"\n\t\t\t\t\t\tdraggable={false}\n\t\t\t\t\t\talt=\"\"\n\t\t\t\t\t/>\n\t\t\t\t</div>\n\t\t\t)}\n\t\t\t<HTMLContainer\n\t\t\t\tid={shape.id}\n\t\t\t\tstyle={{\n\t\t\t\t\toverflow: 'hidden',\n\t\t\t\t\twidth: shape.props.w,\n\t\t\t\t\theight: shape.props.h,\n\t\t\t\t\tborderRadius: shape.props.crop?.isCircle ? '50%' : undefined,\n\t\t\t\t}}\n\t\t\t>\n\t\t\t\t<div className={classNames('tl-image-container')} style={containerStyle}>\n\t\t\t\t\t{/* We have two images: the currently loaded image, and the next image that\n\t\t\t\t\twe're waiting to load. we keep the loaded image mounted while we're waiting\n\t\t\t\t\tfor the next one by storing the loaded URL in state. We use `key` props with\n\t\t\t\t\tthe src of the image so that when the next image is ready, the previous one will\n\t\t\t\t\tbe unmounted and the next will be shown with the browser having to remount a\n\t\t\t\t\tfresh image and decoded it again from the cache. */}\n\t\t\t\t\t{loadedSrc && (\n\t\t\t\t\t\t<img\n\t\t\t\t\t\t\tkey={loadedSrc}\n\t\t\t\t\t\t\tclassName=\"tl-image\"\n\t\t\t\t\t\t\tstyle={getFlipStyle(shape)}\n\t\t\t\t\t\t\tcrossOrigin={crossOrigin}\n\t\t\t\t\t\t\tsrc={loadedSrc}\n\t\t\t\t\t\t\treferrerPolicy=\"strict-origin-when-cross-origin\"\n\t\t\t\t\t\t\tdraggable={false}\n\t\t\t\t\t\t\talt=\"\"\n\t\t\t\t\t\t/>\n\t\t\t\t\t)}\n\t\t\t\t\t{nextSrc && (\n\t\t\t\t\t\t<img\n\t\t\t\t\t\t\tkey={nextSrc}\n\t\t\t\t\t\t\tclassName=\"tl-image\"\n\t\t\t\t\t\t\tstyle={getFlipStyle(shape)}\n\t\t\t\t\t\t\tcrossOrigin={crossOrigin}\n\t\t\t\t\t\t\tsrc={nextSrc}\n\t\t\t\t\t\t\treferrerPolicy=\"strict-origin-when-cross-origin\"\n\t\t\t\t\t\t\tdraggable={false}\n\t\t\t\t\t\t\talt={shape.props.altText}\n\t\t\t\t\t\t\tonLoad={() => setLoadedUrl(nextSrc)}\n\t\t\t\t\t\t/>\n\t\t\t\t\t)}\n\t\t\t\t</div>\n\t\t\t\t{shape.props.url && <HyperlinkButton url={shape.props.url} />}\n\t\t\t</HTMLContainer>\n\t\t</>\n\t)\n})\n\nfunction getIsAnimated(editor: Editor, assetId: TLAssetId) {\n\tconst asset = assetId ? editor.getAsset(assetId) : undefined\n\n\tif (!asset) return false\n\n\treturn (\n\t\t('mimeType' in asset.props && MediaHelpers.isAnimatedImageType(asset?.props.mimeType)) ||\n\t\t('isAnimated' in asset.props && asset.props.isAnimated)\n\t)\n}\n\n/**\n * When an image is cropped we need to translate the image to show the portion withing the cropped\n * area. We do this by translating the image by the negative of the top left corner of the crop\n * area.\n *\n * @param shape - Shape The image shape for which to get the container style\n * @returns - Styles to apply to the image container\n */\nfunction getCroppedContainerStyle(shape: TLImageShape) {\n\tconst crop = shape.props.crop\n\tconst topLeft = crop?.topLeft\n\tif (!topLeft) {\n\t\treturn {\n\t\t\twidth: shape.props.w,\n\t\t\theight: shape.props.h,\n\t\t}\n\t}\n\n\tconst { w, h } = getUncroppedSize(shape.props, crop)\n\tconst offsetX = -topLeft.x * w\n\tconst offsetY = -topLeft.y * h\n\treturn {\n\t\ttransform: `translate(${offsetX}px, ${offsetY}px)`,\n\t\twidth: w,\n\t\theight: h,\n\t}\n}\n\nfunction getFlipStyle(shape: TLImageShape, size?: { width: number; height: number }) {\n\tconst { flipX, flipY, crop } = shape.props\n\tif (!flipX && !flipY) return undefined\n\n\tlet cropOffsetX\n\tlet cropOffsetY\n\tif (crop) {\n\t\t// We have to do all this extra math because of the whole transform origin around 0,0\n\t\t// instead of center in SVG-land, ugh.\n\t\tconst { w, h } = getUncroppedSize(shape.props, crop)\n\n\t\t// Find the resulting w/h of the crop in normalized (0-1) coordinates\n\t\tconst cropWidth = crop.bottomRight.x - crop.topLeft.x\n\t\tconst cropHeight = crop.bottomRight.y - crop.topLeft.y\n\n\t\t// Map from the normalized crop coordinate space to shape pixel space\n\t\tcropOffsetX = modulate(crop.topLeft.x, [0, 1 - cropWidth], [0, w - shape.props.w])\n\t\tcropOffsetY = modulate(crop.topLeft.y, [0, 1 - cropHeight], [0, h - shape.props.h])\n\t}\n\n\tconst scale = `scale(${flipX ? -1 : 1}, ${flipY ? -1 : 1})`\n\tconst translate = size\n\t\t? `translate(${(flipX ? size.width : 0) - (cropOffsetX ? cropOffsetX : 0)}px,\n\t\t ${(flipY ? size.height : 0) - (cropOffsetY ? cropOffsetY : 0)}px)`\n\t\t: ''\n\n\treturn {\n\t\ttransform: `${translate} ${scale}`,\n\t\t// in SVG, flipping around the center doesn't work so we use explicit width/height\n\t\ttransformOrigin: size ? '0 0' : 'center center',\n\t}\n}\n\nfunction SvgImage({ shape, src }: { shape: TLImageShape; src: string }) {\n\tconst cropClipId = useUniqueSafeId()\n\tconst containerStyle = getCroppedContainerStyle(shape)\n\tconst crop = shape.props.crop\n\n\tif (containerStyle.transform && crop) {\n\t\tconst { transform: cropTransform, width, height } = containerStyle\n\t\tconst croppedWidth = (crop.bottomRight.x - crop.topLeft.x) * width\n\t\tconst croppedHeight = (crop.bottomRight.y - crop.topLeft.y) * height\n\n\t\tconst points = [\n\t\t\tnew Vec(0, 0),\n\t\t\tnew Vec(croppedWidth, 0),\n\t\t\tnew Vec(croppedWidth, croppedHeight),\n\t\t\tnew Vec(0, croppedHeight),\n\t\t]\n\n\t\tconst flip = getFlipStyle(shape, { width, height })\n\n\t\treturn (\n\t\t\t<>\n\t\t\t\t<defs>\n\t\t\t\t\t<clipPath id={cropClipId}>\n\t\t\t\t\t\t{crop.isCircle ? (\n\t\t\t\t\t\t\t<ellipse\n\t\t\t\t\t\t\t\tcx={croppedWidth / 2}\n\t\t\t\t\t\t\t\tcy={croppedHeight / 2}\n\t\t\t\t\t\t\t\trx={croppedWidth / 2}\n\t\t\t\t\t\t\t\try={croppedHeight / 2}\n\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t) : (\n\t\t\t\t\t\t\t<polygon points={points.map((p) => `${p.x},${p.y}`).join(' ')} />\n\t\t\t\t\t\t)}\n\t\t\t\t\t</clipPath>\n\t\t\t\t</defs>\n\t\t\t\t<g clipPath={`url(#${cropClipId})`}>\n\t\t\t\t\t<image\n\t\t\t\t\t\thref={src}\n\t\t\t\t\t\twidth={width}\n\t\t\t\t\t\theight={height}\n\t\t\t\t\t\taria-label={shape.props.altText}\n\t\t\t\t\t\tstyle={flip ? { ...flip } : { transform: cropTransform }}\n\t\t\t\t\t/>\n\t\t\t\t</g>\n\t\t\t</>\n\t\t)\n\t} else {\n\t\treturn (\n\t\t\t<image\n\t\t\t\thref={src}\n\t\t\t\twidth={shape.props.w}\n\t\t\t\theight={shape.props.h}\n\t\t\t\taria-label={shape.props.altText}\n\t\t\t\tstyle={getFlipStyle(shape, { width: shape.props.w, height: shape.props.h })}\n\t\t\t/>\n\t\t)\n\t}\n}\n\nfunction getFirstFrameOfAnimatedImage(url: string) {\n\tlet cancelled = false\n\n\tconst promise = new Promise<string>((resolve) => {\n\t\tconst image = Image()\n\t\timage.onload = () => {\n\t\t\tif (cancelled) return\n\n\t\t\tconst canvas = document.createElement('canvas')\n\t\t\tcanvas.width = image.width\n\t\t\tcanvas.height = image.height\n\n\t\t\tconst ctx = canvas.getContext('2d')\n\t\t\tif (!ctx) return\n\n\t\t\tctx.drawImage(image, 0, 0)\n\t\t\tresolve(canvas.toDataURL())\n\t\t}\n\t\timage.crossOrigin = 'anonymous'\n\t\timage.src = url\n\t})\n\n\treturn { promise, cancel: () => (cancelled = true) }\n}\n"],
5
5
  "mappings": "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",
6
6
  "names": ["src", "startShape", "endShape", "ImageShape", "classNames"]
7
7
  }
@@ -51,7 +51,7 @@ const ShapeFill = import_react.default.memo(function ShapeFill2({
51
51
  return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { fill: (0, import_editor.getColorValue)(theme, color, "semi"), d });
52
52
  }
53
53
  case "semi": {
54
- return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { fill: (0, import_editor.getColorValue)(theme, color, "solid"), d });
54
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { fill: theme.solid, d });
55
55
  }
56
56
  case "fill": {
57
57
  return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { fill: (0, import_editor.getColorValue)(theme, color, "fill"), d });
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../src/lib/shapes/shared/ShapeFill.tsx"],
4
- "sourcesContent": ["import {\n\tgetColorValue,\n\tTLDefaultColorStyle,\n\tTLDefaultColorTheme,\n\tTLDefaultFillStyle,\n\tuseEditor,\n\tuseSvgExportContext,\n\tuseValue,\n} from '@tldraw/editor'\nimport React from 'react'\nimport { useGetHashPatternZoomName } from './defaultStyleDefs'\n\ninterface ShapeFillProps {\n\td: string\n\tfill: TLDefaultFillStyle\n\tcolor: TLDefaultColorStyle\n\ttheme: TLDefaultColorTheme\n\tscale: number\n}\n\nexport const ShapeFill = React.memo(function ShapeFill({\n\ttheme,\n\td,\n\tcolor,\n\tfill,\n\tscale,\n}: ShapeFillProps) {\n\tswitch (fill) {\n\t\tcase 'none': {\n\t\t\treturn null\n\t\t}\n\t\tcase 'solid': {\n\t\t\treturn <path fill={getColorValue(theme, color, 'semi')} d={d} />\n\t\t}\n\t\tcase 'semi': {\n\t\t\treturn <path fill={getColorValue(theme, color, 'solid')} d={d} />\n\t\t}\n\t\tcase 'fill': {\n\t\t\treturn <path fill={getColorValue(theme, color, 'fill')} d={d} />\n\t\t}\n\t\tcase 'pattern': {\n\t\t\treturn <PatternFill theme={theme} color={color} fill={fill} d={d} scale={scale} />\n\t\t}\n\t}\n})\n\nexport function PatternFill({ d, color, theme }: ShapeFillProps) {\n\tconst editor = useEditor()\n\tconst svgExport = useSvgExportContext()\n\tconst zoomLevel = useValue('zoomLevel', () => editor.getZoomLevel(), [editor])\n\tconst getHashPatternZoomName = useGetHashPatternZoomName()\n\n\tconst teenyTiny = editor.getZoomLevel() <= 0.18\n\n\treturn (\n\t\t<>\n\t\t\t<path fill={getColorValue(theme, color, 'pattern')} d={d} />\n\t\t\t<path\n\t\t\t\tfill={\n\t\t\t\t\tsvgExport\n\t\t\t\t\t\t? `url(#${getHashPatternZoomName(1, theme.id)})`\n\t\t\t\t\t\t: teenyTiny\n\t\t\t\t\t\t\t? getColorValue(theme, color, 'semi')\n\t\t\t\t\t\t\t: `url(#${getHashPatternZoomName(zoomLevel, theme.id)})`\n\t\t\t\t}\n\t\t\t\td={d}\n\t\t\t/>\n\t\t</>\n\t)\n}\n"],
5
- "mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAgCU;AAhCV,oBAQO;AACP,mBAAkB;AAClB,8BAA0C;AAUnC,MAAM,YAAY,aAAAA,QAAM,KAAK,SAASC,WAAU;AAAA,EACtD;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACD,GAAmB;AAClB,UAAQ,MAAM;AAAA,IACb,KAAK,QAAQ;AACZ,aAAO;AAAA,IACR;AAAA,IACA,KAAK,SAAS;AACb,aAAO,4CAAC,UAAK,UAAM,6BAAc,OAAO,OAAO,MAAM,GAAG,GAAM;AAAA,IAC/D;AAAA,IACA,KAAK,QAAQ;AACZ,aAAO,4CAAC,UAAK,UAAM,6BAAc,OAAO,OAAO,OAAO,GAAG,GAAM;AAAA,IAChE;AAAA,IACA,KAAK,QAAQ;AACZ,aAAO,4CAAC,UAAK,UAAM,6BAAc,OAAO,OAAO,MAAM,GAAG,GAAM;AAAA,IAC/D;AAAA,IACA,KAAK,WAAW;AACf,aAAO,4CAAC,eAAY,OAAc,OAAc,MAAY,GAAM,OAAc;AAAA,IACjF;AAAA,EACD;AACD,CAAC;AAEM,SAAS,YAAY,EAAE,GAAG,OAAO,MAAM,GAAmB;AAChE,QAAM,aAAS,yBAAU;AACzB,QAAM,gBAAY,mCAAoB;AACtC,QAAM,gBAAY,wBAAS,aAAa,MAAM,OAAO,aAAa,GAAG,CAAC,MAAM,CAAC;AAC7E,QAAM,6BAAyB,mDAA0B;AAEzD,QAAM,YAAY,OAAO,aAAa,KAAK;AAE3C,SACC,4EACC;AAAA,gDAAC,UAAK,UAAM,6BAAc,OAAO,OAAO,SAAS,GAAG,GAAM;AAAA,IAC1D;AAAA,MAAC;AAAA;AAAA,QACA,MACC,YACG,QAAQ,uBAAuB,GAAG,MAAM,EAAE,CAAC,MAC3C,gBACC,6BAAc,OAAO,OAAO,MAAM,IAClC,QAAQ,uBAAuB,WAAW,MAAM,EAAE,CAAC;AAAA,QAExD;AAAA;AAAA,IACD;AAAA,KACD;AAEF;",
4
+ "sourcesContent": ["import {\n\tgetColorValue,\n\tTLDefaultColorStyle,\n\tTLDefaultColorTheme,\n\tTLDefaultFillStyle,\n\tuseEditor,\n\tuseSvgExportContext,\n\tuseValue,\n} from '@tldraw/editor'\nimport React from 'react'\nimport { useGetHashPatternZoomName } from './defaultStyleDefs'\n\ninterface ShapeFillProps {\n\td: string\n\tfill: TLDefaultFillStyle\n\tcolor: TLDefaultColorStyle\n\ttheme: TLDefaultColorTheme\n\tscale: number\n}\n\nexport const ShapeFill = React.memo(function ShapeFill({\n\ttheme,\n\td,\n\tcolor,\n\tfill,\n\tscale,\n}: ShapeFillProps) {\n\tswitch (fill) {\n\t\tcase 'none': {\n\t\t\treturn null\n\t\t}\n\t\tcase 'solid': {\n\t\t\treturn <path fill={getColorValue(theme, color, 'semi')} d={d} />\n\t\t}\n\t\tcase 'semi': {\n\t\t\treturn <path fill={theme.solid} d={d} />\n\t\t}\n\t\tcase 'fill': {\n\t\t\treturn <path fill={getColorValue(theme, color, 'fill')} d={d} />\n\t\t}\n\t\tcase 'pattern': {\n\t\t\treturn <PatternFill theme={theme} color={color} fill={fill} d={d} scale={scale} />\n\t\t}\n\t}\n})\n\nexport function PatternFill({ d, color, theme }: ShapeFillProps) {\n\tconst editor = useEditor()\n\tconst svgExport = useSvgExportContext()\n\tconst zoomLevel = useValue('zoomLevel', () => editor.getZoomLevel(), [editor])\n\tconst getHashPatternZoomName = useGetHashPatternZoomName()\n\n\tconst teenyTiny = editor.getZoomLevel() <= 0.18\n\n\treturn (\n\t\t<>\n\t\t\t<path fill={getColorValue(theme, color, 'pattern')} d={d} />\n\t\t\t<path\n\t\t\t\tfill={\n\t\t\t\t\tsvgExport\n\t\t\t\t\t\t? `url(#${getHashPatternZoomName(1, theme.id)})`\n\t\t\t\t\t\t: teenyTiny\n\t\t\t\t\t\t\t? getColorValue(theme, color, 'semi')\n\t\t\t\t\t\t\t: `url(#${getHashPatternZoomName(zoomLevel, theme.id)})`\n\t\t\t\t}\n\t\t\t\td={d}\n\t\t\t/>\n\t\t</>\n\t)\n}\n"],
5
+ "mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAgCU;AAhCV,oBAQO;AACP,mBAAkB;AAClB,8BAA0C;AAUnC,MAAM,YAAY,aAAAA,QAAM,KAAK,SAASC,WAAU;AAAA,EACtD;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACD,GAAmB;AAClB,UAAQ,MAAM;AAAA,IACb,KAAK,QAAQ;AACZ,aAAO;AAAA,IACR;AAAA,IACA,KAAK,SAAS;AACb,aAAO,4CAAC,UAAK,UAAM,6BAAc,OAAO,OAAO,MAAM,GAAG,GAAM;AAAA,IAC/D;AAAA,IACA,KAAK,QAAQ;AACZ,aAAO,4CAAC,UAAK,MAAM,MAAM,OAAO,GAAM;AAAA,IACvC;AAAA,IACA,KAAK,QAAQ;AACZ,aAAO,4CAAC,UAAK,UAAM,6BAAc,OAAO,OAAO,MAAM,GAAG,GAAM;AAAA,IAC/D;AAAA,IACA,KAAK,WAAW;AACf,aAAO,4CAAC,eAAY,OAAc,OAAc,MAAY,GAAM,OAAc;AAAA,IACjF;AAAA,EACD;AACD,CAAC;AAEM,SAAS,YAAY,EAAE,GAAG,OAAO,MAAM,GAAmB;AAChE,QAAM,aAAS,yBAAU;AACzB,QAAM,gBAAY,mCAAoB;AACtC,QAAM,gBAAY,wBAAS,aAAa,MAAM,OAAO,aAAa,GAAG,CAAC,MAAM,CAAC;AAC7E,QAAM,6BAAyB,mDAA0B;AAEzD,QAAM,YAAY,OAAO,aAAa,KAAK;AAE3C,SACC,4EACC;AAAA,gDAAC,UAAK,UAAM,6BAAc,OAAO,OAAO,SAAS,GAAG,GAAM;AAAA,IAC1D;AAAA,MAAC;AAAA;AAAA,QACA,MACC,YACG,QAAQ,uBAAuB,GAAG,MAAM,EAAE,CAAC,MAC3C,gBACC,6BAAc,OAAO,OAAO,MAAM,IAClC,QAAQ,uBAAuB,WAAW,MAAM,EAAE,CAAC;AAAA,QAExD;AAAA;AAAA,IACD;AAAA,KACD;AAEF;",
6
6
  "names": ["React", "ShapeFill"]
7
7
  }
@@ -129,9 +129,9 @@ const VideoShape = (0, import_react.memo)(function VideoShape2({ shape }) {
129
129
  {
130
130
  id: shape.id,
131
131
  style: {
132
- color: "var(--color-text-3)",
133
- backgroundColor: asset ? "transparent" : "var(--color-low)",
134
- border: asset ? "none" : "1px solid var(--color-low-border)"
132
+ color: "var(--tl-color-text-3)",
133
+ backgroundColor: asset ? "transparent" : "var(--tl-color-low)",
134
+ border: asset ? "none" : "1px solid var(--tl-color-low-border)"
135
135
  },
136
136
  children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "tl-counter-scaled", children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "tl-video-container", children: !asset ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_BrokenAssetIcon.BrokenAssetIcon, {}) : Spinner && !asset.props.src ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Spinner, {}) : url ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
137
137
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../src/lib/shapes/video/VideoShapeUtil.tsx"],
4
- "sourcesContent": ["import {\n\tBaseBoxShapeUtil,\n\tHTMLContainer,\n\tMediaHelpers,\n\tSvgExportContext,\n\tTLAsset,\n\tTLVideoShape,\n\tWeakCache,\n\ttoDomPrecision,\n\tuseEditor,\n\tuseEditorComponents,\n\tuseIsEditing,\n\tvideoShapeMigrations,\n\tvideoShapeProps,\n} from '@tldraw/editor'\nimport classNames from 'classnames'\nimport { ReactEventHandler, memo, useCallback, useEffect, useRef, useState } from 'react'\nimport { BrokenAssetIcon } from '../shared/BrokenAssetIcon'\nimport { HyperlinkButton } from '../shared/HyperlinkButton'\nimport { useImageOrVideoAsset } from '../shared/useImageOrVideoAsset'\nimport { usePrefersReducedMotion } from '../shared/usePrefersReducedMotion'\n\nconst videoSvgExportCache = new WeakCache<TLAsset, Promise<string | null>>()\n\n/** @public */\nexport interface VideoShapeOptions {\n\t/**\n\t * Should videos play automatically?\n\t */\n\tautoplay: boolean\n}\n\n/** @public */\nexport class VideoShapeUtil extends BaseBoxShapeUtil<TLVideoShape> {\n\tstatic override type = 'video' as const\n\tstatic override props = videoShapeProps\n\tstatic override migrations = videoShapeMigrations\n\n\toverride options: VideoShapeOptions = {\n\t\tautoplay: true,\n\t}\n\n\toverride canEdit() {\n\t\treturn true\n\t}\n\toverride isAspectRatioLocked() {\n\t\treturn true\n\t}\n\n\toverride getDefaultProps(): TLVideoShape['props'] {\n\t\treturn {\n\t\t\tw: 100,\n\t\t\th: 100,\n\t\t\tassetId: null,\n\t\t\tautoplay: this.options.autoplay,\n\t\t\turl: '',\n\t\t\taltText: '',\n\t\t\t// Not used, but once upon a time were used to sync video state between users\n\t\t\ttime: 0,\n\t\t\tplaying: true,\n\t\t}\n\t}\n\n\toverride getAriaDescriptor(shape: TLVideoShape) {\n\t\treturn shape.props.altText\n\t}\n\n\tcomponent(shape: TLVideoShape) {\n\t\treturn <VideoShape shape={shape} />\n\t}\n\n\tindicator(shape: TLVideoShape) {\n\t\treturn <rect width={toDomPrecision(shape.props.w)} height={toDomPrecision(shape.props.h)} />\n\t}\n\n\toverride async toSvg(shape: TLVideoShape, ctx: SvgExportContext) {\n\t\tconst props = shape.props\n\t\tif (!props.assetId) return null\n\n\t\tconst asset = this.editor.getAsset<TLAsset>(props.assetId)\n\t\tif (!asset) return null\n\n\t\tconst src = await videoSvgExportCache.get(asset, async () => {\n\t\t\tconst assetUrl = await ctx.resolveAssetUrl(asset.id, props.w)\n\t\t\tif (!assetUrl) return null\n\t\t\tconst video = await MediaHelpers.loadVideo(assetUrl)\n\t\t\treturn await MediaHelpers.getVideoFrameAsDataUrl(video, 0)\n\t\t})\n\n\t\tif (!src) return null\n\n\t\treturn <image href={src} width={props.w} height={props.h} aria-label={shape.props.altText} />\n\t}\n}\n\nconst VideoShape = memo(function VideoShape({ shape }: { shape: TLVideoShape }) {\n\tconst editor = useEditor()\n\tconst showControls = editor.getShapeGeometry(shape).bounds.w * editor.getZoomLevel() >= 110\n\tconst isEditing = useIsEditing(shape.id)\n\tconst prefersReducedMotion = usePrefersReducedMotion()\n\tconst { Spinner } = useEditorComponents()\n\n\tconst { asset, url } = useImageOrVideoAsset({\n\t\tshapeId: shape.id,\n\t\tassetId: shape.props.assetId,\n\t\twidth: shape.props.w,\n\t})\n\n\tconst rVideo = useRef<HTMLVideoElement>(null!)\n\n\tconst [isLoaded, setIsLoaded] = useState(false)\n\n\tconst handleLoadedData = useCallback<ReactEventHandler<HTMLVideoElement>>((e) => {\n\t\tconst video = e.currentTarget\n\t\tif (!video) return\n\t\tsetIsLoaded(true)\n\t}, [])\n\n\tconst [isFullscreen, setIsFullscreen] = useState(false)\n\n\tuseEffect(() => {\n\t\tconst fullscreenChange = () => setIsFullscreen(document.fullscreenElement === rVideo.current)\n\t\tdocument.addEventListener('fullscreenchange', fullscreenChange)\n\n\t\treturn () => document.removeEventListener('fullscreenchange', fullscreenChange)\n\t})\n\n\t// Focus the video when editing\n\tuseEffect(() => {\n\t\tconst video = rVideo.current\n\t\tif (!video) return\n\n\t\tif (isEditing) {\n\t\t\tif (document.activeElement !== video) {\n\t\t\t\tvideo.focus()\n\t\t\t}\n\t\t}\n\t}, [isEditing, isLoaded])\n\n\treturn (\n\t\t<>\n\t\t\t<HTMLContainer\n\t\t\t\tid={shape.id}\n\t\t\t\tstyle={{\n\t\t\t\t\tcolor: 'var(--color-text-3)',\n\t\t\t\t\tbackgroundColor: asset ? 'transparent' : 'var(--color-low)',\n\t\t\t\t\tborder: asset ? 'none' : '1px solid var(--color-low-border)',\n\t\t\t\t}}\n\t\t\t>\n\t\t\t\t<div className=\"tl-counter-scaled\">\n\t\t\t\t\t<div className=\"tl-video-container\">\n\t\t\t\t\t\t{!asset ? (\n\t\t\t\t\t\t\t<BrokenAssetIcon />\n\t\t\t\t\t\t) : Spinner && !asset.props.src ? (\n\t\t\t\t\t\t\t<Spinner />\n\t\t\t\t\t\t) : url ? (\n\t\t\t\t\t\t\t<>\n\t\t\t\t\t\t\t\t<video\n\t\t\t\t\t\t\t\t\tkey={url}\n\t\t\t\t\t\t\t\t\tref={rVideo}\n\t\t\t\t\t\t\t\t\tstyle={\n\t\t\t\t\t\t\t\t\t\tisEditing\n\t\t\t\t\t\t\t\t\t\t\t? { pointerEvents: 'all' }\n\t\t\t\t\t\t\t\t\t\t\t: !isLoaded\n\t\t\t\t\t\t\t\t\t\t\t\t? { display: 'none' }\n\t\t\t\t\t\t\t\t\t\t\t\t: undefined\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\tclassName={classNames('tl-video', `tl-video-shape-${shape.id.split(':')[1]}`, {\n\t\t\t\t\t\t\t\t\t\t'tl-video-is-fullscreen': isFullscreen,\n\t\t\t\t\t\t\t\t\t})}\n\t\t\t\t\t\t\t\t\twidth=\"100%\"\n\t\t\t\t\t\t\t\t\theight=\"100%\"\n\t\t\t\t\t\t\t\t\tdraggable={false}\n\t\t\t\t\t\t\t\t\tplaysInline\n\t\t\t\t\t\t\t\t\tautoPlay={shape.props.autoplay && !prefersReducedMotion}\n\t\t\t\t\t\t\t\t\tmuted\n\t\t\t\t\t\t\t\t\tloop\n\t\t\t\t\t\t\t\t\tdisableRemotePlayback\n\t\t\t\t\t\t\t\t\tdisablePictureInPicture\n\t\t\t\t\t\t\t\t\tcontrols={isEditing && showControls}\n\t\t\t\t\t\t\t\t\tonLoadedData={handleLoadedData}\n\t\t\t\t\t\t\t\t\thidden={!isLoaded}\n\t\t\t\t\t\t\t\t\taria-label={shape.props.altText}\n\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t<source src={url} />\n\t\t\t\t\t\t\t\t</video>\n\t\t\t\t\t\t\t\t{!isLoaded && Spinner && <Spinner />}\n\t\t\t\t\t\t\t</>\n\t\t\t\t\t\t) : null}\n\t\t\t\t\t</div>\n\t\t\t\t</div>\n\t\t\t</HTMLContainer>\n\t\t\t{'url' in shape.props && shape.props.url && <HyperlinkButton url={shape.props.url} />}\n\t\t</>\n\t)\n})\n"],
4
+ "sourcesContent": ["import {\n\tBaseBoxShapeUtil,\n\tHTMLContainer,\n\tMediaHelpers,\n\tSvgExportContext,\n\tTLAsset,\n\tTLVideoShape,\n\tWeakCache,\n\ttoDomPrecision,\n\tuseEditor,\n\tuseEditorComponents,\n\tuseIsEditing,\n\tvideoShapeMigrations,\n\tvideoShapeProps,\n} from '@tldraw/editor'\nimport classNames from 'classnames'\nimport { ReactEventHandler, memo, useCallback, useEffect, useRef, useState } from 'react'\nimport { BrokenAssetIcon } from '../shared/BrokenAssetIcon'\nimport { HyperlinkButton } from '../shared/HyperlinkButton'\nimport { useImageOrVideoAsset } from '../shared/useImageOrVideoAsset'\nimport { usePrefersReducedMotion } from '../shared/usePrefersReducedMotion'\n\nconst videoSvgExportCache = new WeakCache<TLAsset, Promise<string | null>>()\n\n/** @public */\nexport interface VideoShapeOptions {\n\t/**\n\t * Should videos play automatically?\n\t */\n\tautoplay: boolean\n}\n\n/** @public */\nexport class VideoShapeUtil extends BaseBoxShapeUtil<TLVideoShape> {\n\tstatic override type = 'video' as const\n\tstatic override props = videoShapeProps\n\tstatic override migrations = videoShapeMigrations\n\n\toverride options: VideoShapeOptions = {\n\t\tautoplay: true,\n\t}\n\n\toverride canEdit() {\n\t\treturn true\n\t}\n\toverride isAspectRatioLocked() {\n\t\treturn true\n\t}\n\n\toverride getDefaultProps(): TLVideoShape['props'] {\n\t\treturn {\n\t\t\tw: 100,\n\t\t\th: 100,\n\t\t\tassetId: null,\n\t\t\tautoplay: this.options.autoplay,\n\t\t\turl: '',\n\t\t\taltText: '',\n\t\t\t// Not used, but once upon a time were used to sync video state between users\n\t\t\ttime: 0,\n\t\t\tplaying: true,\n\t\t}\n\t}\n\n\toverride getAriaDescriptor(shape: TLVideoShape) {\n\t\treturn shape.props.altText\n\t}\n\n\tcomponent(shape: TLVideoShape) {\n\t\treturn <VideoShape shape={shape} />\n\t}\n\n\tindicator(shape: TLVideoShape) {\n\t\treturn <rect width={toDomPrecision(shape.props.w)} height={toDomPrecision(shape.props.h)} />\n\t}\n\n\toverride async toSvg(shape: TLVideoShape, ctx: SvgExportContext) {\n\t\tconst props = shape.props\n\t\tif (!props.assetId) return null\n\n\t\tconst asset = this.editor.getAsset<TLAsset>(props.assetId)\n\t\tif (!asset) return null\n\n\t\tconst src = await videoSvgExportCache.get(asset, async () => {\n\t\t\tconst assetUrl = await ctx.resolveAssetUrl(asset.id, props.w)\n\t\t\tif (!assetUrl) return null\n\t\t\tconst video = await MediaHelpers.loadVideo(assetUrl)\n\t\t\treturn await MediaHelpers.getVideoFrameAsDataUrl(video, 0)\n\t\t})\n\n\t\tif (!src) return null\n\n\t\treturn <image href={src} width={props.w} height={props.h} aria-label={shape.props.altText} />\n\t}\n}\n\nconst VideoShape = memo(function VideoShape({ shape }: { shape: TLVideoShape }) {\n\tconst editor = useEditor()\n\tconst showControls = editor.getShapeGeometry(shape).bounds.w * editor.getZoomLevel() >= 110\n\tconst isEditing = useIsEditing(shape.id)\n\tconst prefersReducedMotion = usePrefersReducedMotion()\n\tconst { Spinner } = useEditorComponents()\n\n\tconst { asset, url } = useImageOrVideoAsset({\n\t\tshapeId: shape.id,\n\t\tassetId: shape.props.assetId,\n\t\twidth: shape.props.w,\n\t})\n\n\tconst rVideo = useRef<HTMLVideoElement>(null!)\n\n\tconst [isLoaded, setIsLoaded] = useState(false)\n\n\tconst handleLoadedData = useCallback<ReactEventHandler<HTMLVideoElement>>((e) => {\n\t\tconst video = e.currentTarget\n\t\tif (!video) return\n\t\tsetIsLoaded(true)\n\t}, [])\n\n\tconst [isFullscreen, setIsFullscreen] = useState(false)\n\n\tuseEffect(() => {\n\t\tconst fullscreenChange = () => setIsFullscreen(document.fullscreenElement === rVideo.current)\n\t\tdocument.addEventListener('fullscreenchange', fullscreenChange)\n\n\t\treturn () => document.removeEventListener('fullscreenchange', fullscreenChange)\n\t})\n\n\t// Focus the video when editing\n\tuseEffect(() => {\n\t\tconst video = rVideo.current\n\t\tif (!video) return\n\n\t\tif (isEditing) {\n\t\t\tif (document.activeElement !== video) {\n\t\t\t\tvideo.focus()\n\t\t\t}\n\t\t}\n\t}, [isEditing, isLoaded])\n\n\treturn (\n\t\t<>\n\t\t\t<HTMLContainer\n\t\t\t\tid={shape.id}\n\t\t\t\tstyle={{\n\t\t\t\t\tcolor: 'var(--tl-color-text-3)',\n\t\t\t\t\tbackgroundColor: asset ? 'transparent' : 'var(--tl-color-low)',\n\t\t\t\t\tborder: asset ? 'none' : '1px solid var(--tl-color-low-border)',\n\t\t\t\t}}\n\t\t\t>\n\t\t\t\t<div className=\"tl-counter-scaled\">\n\t\t\t\t\t<div className=\"tl-video-container\">\n\t\t\t\t\t\t{!asset ? (\n\t\t\t\t\t\t\t<BrokenAssetIcon />\n\t\t\t\t\t\t) : Spinner && !asset.props.src ? (\n\t\t\t\t\t\t\t<Spinner />\n\t\t\t\t\t\t) : url ? (\n\t\t\t\t\t\t\t<>\n\t\t\t\t\t\t\t\t<video\n\t\t\t\t\t\t\t\t\tkey={url}\n\t\t\t\t\t\t\t\t\tref={rVideo}\n\t\t\t\t\t\t\t\t\tstyle={\n\t\t\t\t\t\t\t\t\t\tisEditing\n\t\t\t\t\t\t\t\t\t\t\t? { pointerEvents: 'all' }\n\t\t\t\t\t\t\t\t\t\t\t: !isLoaded\n\t\t\t\t\t\t\t\t\t\t\t\t? { display: 'none' }\n\t\t\t\t\t\t\t\t\t\t\t\t: undefined\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\tclassName={classNames('tl-video', `tl-video-shape-${shape.id.split(':')[1]}`, {\n\t\t\t\t\t\t\t\t\t\t'tl-video-is-fullscreen': isFullscreen,\n\t\t\t\t\t\t\t\t\t})}\n\t\t\t\t\t\t\t\t\twidth=\"100%\"\n\t\t\t\t\t\t\t\t\theight=\"100%\"\n\t\t\t\t\t\t\t\t\tdraggable={false}\n\t\t\t\t\t\t\t\t\tplaysInline\n\t\t\t\t\t\t\t\t\tautoPlay={shape.props.autoplay && !prefersReducedMotion}\n\t\t\t\t\t\t\t\t\tmuted\n\t\t\t\t\t\t\t\t\tloop\n\t\t\t\t\t\t\t\t\tdisableRemotePlayback\n\t\t\t\t\t\t\t\t\tdisablePictureInPicture\n\t\t\t\t\t\t\t\t\tcontrols={isEditing && showControls}\n\t\t\t\t\t\t\t\t\tonLoadedData={handleLoadedData}\n\t\t\t\t\t\t\t\t\thidden={!isLoaded}\n\t\t\t\t\t\t\t\t\taria-label={shape.props.altText}\n\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t<source src={url} />\n\t\t\t\t\t\t\t\t</video>\n\t\t\t\t\t\t\t\t{!isLoaded && Spinner && <Spinner />}\n\t\t\t\t\t\t\t</>\n\t\t\t\t\t\t) : null}\n\t\t\t\t\t</div>\n\t\t\t\t</div>\n\t\t\t</HTMLContainer>\n\t\t\t{'url' in shape.props && shape.props.url && <HyperlinkButton url={shape.props.url} />}\n\t\t</>\n\t)\n})\n"],
5
5
  "mappings": "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",
6
6
  "names": ["VideoShape", "classNames"]
7
7
  }
@@ -128,6 +128,18 @@ const TldrawUiContent = import_react.default.memo(function TldrawUI() {
128
128
  []
129
129
  );
130
130
  const { "toggle-focus-mode": toggleFocus } = (0, import_actions.useActions)();
131
+ const { breakpointsAbove, breakpointsBelow } = (0, import_react.useMemo)(() => {
132
+ const breakpointsAbove2 = [];
133
+ const breakpointsBelow2 = [];
134
+ for (let bp = 0; bp < import_constants.PORTRAIT_BREAKPOINTS.length; bp++) {
135
+ if (bp <= breakpoint) {
136
+ breakpointsAbove2.push(bp);
137
+ } else {
138
+ breakpointsBelow2.push(bp);
139
+ }
140
+ }
141
+ return { breakpointsAbove: breakpointsAbove2, breakpointsBelow: breakpointsBelow2 };
142
+ }, [breakpoint]);
131
143
  return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
132
144
  "div",
133
145
  {
@@ -136,6 +148,8 @@ const TldrawUiContent = import_react.default.memo(function TldrawUI() {
136
148
  }),
137
149
  "data-iseditinganything": hideToolbarWhileEditing,
138
150
  "data-breakpoint": breakpoint,
151
+ "data-breakpoints-above": breakpointsAbove.join(" "),
152
+ "data-breakpoints-below": breakpointsBelow.join(" "),
139
153
  children: [
140
154
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_A11y.SkipToMainContent, {}),
141
155
  isFocusMode ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "tlui-layout__top", children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../src/lib/ui/TldrawUi.tsx"],
4
- "sourcesContent": ["import { tlenv, useEditor, useReactor, useValue } from '@tldraw/editor'\nimport classNames from 'classnames'\nimport React, { ReactNode, useRef, useState } from 'react'\nimport { TLUiAssetUrlOverrides } from './assetUrls'\nimport { SkipToMainContent } from './components/A11y'\nimport { FollowingIndicator } from './components/FollowingIndicator'\nimport { TldrawUiButton } from './components/primitives/Button/TldrawUiButton'\nimport { TldrawUiButtonIcon } from './components/primitives/Button/TldrawUiButtonIcon'\nimport { PORTRAIT_BREAKPOINT } from './constants'\nimport {\n\tTLUiContextProviderProps,\n\tTldrawUiContextProvider,\n} from './context/TldrawUiContextProvider'\nimport { useActions } from './context/actions'\nimport { useBreakpoint } from './context/breakpoints'\nimport { TLUiComponents, useTldrawUiComponents } from './context/components'\nimport { useNativeClipboardEvents } from './hooks/useClipboardEvents'\nimport { useEditorEvents } from './hooks/useEditorEvents'\nimport { useKeyboardShortcuts } from './hooks/useKeyboardShortcuts'\nimport { useReadonly } from './hooks/useReadonly'\nimport { useTranslation } from './hooks/useTranslation/useTranslation'\n\n/** @public */\nexport interface TldrawUiProps extends TLUiContextProviderProps {\n\t/**\n\t * The component's children.\n\t */\n\tchildren?: ReactNode\n\n\t/**\n\t * Whether to hide the user interface and only display the canvas.\n\t */\n\thideUi?: boolean\n\n\t/**\n\t * Overrides for the UI components.\n\t */\n\tcomponents?: TLUiComponents\n\n\t/**\n\t * Additional items to add to the debug menu (will be deprecated)\n\t */\n\trenderDebugMenuItems?(): React.ReactNode\n\n\t/** Asset URL override. */\n\tassetUrls?: TLUiAssetUrlOverrides\n}\n\n/**\n * @public\n * @react\n */\nexport const TldrawUi = React.memo(function TldrawUi({\n\trenderDebugMenuItems,\n\tchildren,\n\thideUi,\n\tcomponents,\n\t...rest\n}: TldrawUiProps) {\n\treturn (\n\t\t<TldrawUiContextProvider {...rest} components={components}>\n\t\t\t<TldrawUiInner hideUi={hideUi} renderDebugMenuItems={renderDebugMenuItems}>\n\t\t\t\t{children}\n\t\t\t</TldrawUiInner>\n\t\t</TldrawUiContextProvider>\n\t)\n})\n\ninterface TldrawUiContentProps {\n\thideUi?: boolean\n\tshareZone?: ReactNode\n\ttopZone?: ReactNode\n\trenderDebugMenuItems?(): React.ReactNode\n}\n\nconst TldrawUiInner = React.memo(function TldrawUiInner({\n\tchildren,\n\thideUi,\n\t...rest\n}: TldrawUiContentProps & { children: ReactNode }) {\n\t// The hideUi prop should prevent the UI from mounting.\n\t// If we ever need want the UI to mount and preserve state, then\n\t// we should change this behavior and hide the UI via CSS instead.\n\n\treturn (\n\t\t<>\n\t\t\t{children}\n\t\t\t{hideUi ? null : <TldrawUiContent {...rest} />}\n\t\t</>\n\t)\n})\n\nconst TldrawUiContent = React.memo(function TldrawUI() {\n\tconst editor = useEditor()\n\tconst msg = useTranslation()\n\tconst breakpoint = useBreakpoint()\n\tconst isReadonlyMode = useReadonly()\n\tconst isFocusMode = useValue('focus', () => editor.getInstanceState().isFocusMode, [editor])\n\tconst isDebugMode = useValue('debug', () => editor.getInstanceState().isDebugMode, [editor])\n\n\tconst {\n\t\tSharePanel,\n\t\tTopPanel,\n\t\tMenuPanel,\n\t\tStylePanel,\n\t\tToolbar,\n\t\tHelpMenu,\n\t\tNavigationPanel,\n\t\tHelperButtons,\n\t\tDebugPanel,\n\t\tCursorChatBubble,\n\t\tRichTextToolbar,\n\t\tImageToolbar,\n\t\tVideoToolbar,\n\t\tToasts,\n\t\tDialogs,\n\t\tA11y,\n\t} = useTldrawUiComponents()\n\n\tuseKeyboardShortcuts()\n\tuseNativeClipboardEvents()\n\tuseEditorEvents()\n\n\tconst rIsEditingAnything = useRef(false)\n\tconst rHidingTimeout = useRef(-1 as any)\n\tconst [hideToolbarWhileEditing, setHideToolbarWhileEditing] = useState(false)\n\n\tuseReactor(\n\t\t'update hide toolbar while delayed',\n\t\t() => {\n\t\t\tconst isMobileEnvironment = tlenv.isIos || tlenv.isAndroid\n\t\t\tif (!isMobileEnvironment) return\n\n\t\t\tconst editingShape = editor.getEditingShapeId()\n\t\t\tif (editingShape === null) {\n\t\t\t\tif (rIsEditingAnything.current) {\n\t\t\t\t\trIsEditingAnything.current = false\n\t\t\t\t\tclearTimeout(rHidingTimeout.current)\n\t\t\t\t\tif (tlenv.isAndroid) {\n\t\t\t\t\t\t// On Android, hide it after 150ms\n\t\t\t\t\t\trHidingTimeout.current = editor.timers.setTimeout(() => {\n\t\t\t\t\t\t\tsetHideToolbarWhileEditing(false)\n\t\t\t\t\t\t}, 150)\n\t\t\t\t\t} else {\n\t\t\t\t\t\t// On iOS, just hide it immediately\n\t\t\t\t\t\tsetHideToolbarWhileEditing(false)\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn\n\t\t\t}\n\n\t\t\tif (!rIsEditingAnything.current) {\n\t\t\t\trIsEditingAnything.current = true\n\t\t\t\tclearTimeout(rHidingTimeout.current)\n\t\t\t\tsetHideToolbarWhileEditing(true)\n\t\t\t}\n\t\t},\n\t\t[]\n\t)\n\n\tconst { 'toggle-focus-mode': toggleFocus } = useActions()\n\n\treturn (\n\t\t<div\n\t\t\tclassName={classNames('tlui-layout', {\n\t\t\t\t'tlui-layout__mobile': breakpoint < PORTRAIT_BREAKPOINT.TABLET_SM,\n\t\t\t})}\n\t\t\t// When the virtual keyboard is opening we want it to hide immediately.\n\t\t\t// But when the virtual keyboard is closing we want to wait a bit before showing it again.\n\t\t\tdata-iseditinganything={hideToolbarWhileEditing}\n\t\t\tdata-breakpoint={breakpoint}\n\t\t>\n\t\t\t<SkipToMainContent />\n\t\t\t{isFocusMode ? (\n\t\t\t\t<div className=\"tlui-layout__top\">\n\t\t\t\t\t<TldrawUiButton\n\t\t\t\t\t\ttype=\"icon\"\n\t\t\t\t\t\tclassName=\"tlui-focus-button\"\n\t\t\t\t\t\ttitle={msg('focus-mode.toggle-focus-mode')}\n\t\t\t\t\t\tonClick={() => toggleFocus.onSelect('menu')}\n\t\t\t\t\t>\n\t\t\t\t\t\t<TldrawUiButtonIcon icon=\"dot\" />\n\t\t\t\t\t</TldrawUiButton>\n\t\t\t\t</div>\n\t\t\t) : (\n\t\t\t\t<>\n\t\t\t\t\t<div className=\"tlui-layout__top\">\n\t\t\t\t\t\t<div className=\"tlui-layout__top__left\">\n\t\t\t\t\t\t\t{MenuPanel && <MenuPanel />}\n\t\t\t\t\t\t\t{HelperButtons && <HelperButtons />}\n\t\t\t\t\t\t</div>\n\t\t\t\t\t\t<div className=\"tlui-layout__top__center\">{TopPanel && <TopPanel />}</div>\n\t\t\t\t\t\t<div className=\"tlui-layout__top__right\">\n\t\t\t\t\t\t\t{SharePanel && <SharePanel />}\n\t\t\t\t\t\t\t{StylePanel && breakpoint >= PORTRAIT_BREAKPOINT.TABLET_SM && !isReadonlyMode && (\n\t\t\t\t\t\t\t\t<StylePanel />\n\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t</div>\n\t\t\t\t\t</div>\n\t\t\t\t\t<div className=\"tlui-layout__bottom\">\n\t\t\t\t\t\t<div className=\"tlui-layout__bottom__main\">\n\t\t\t\t\t\t\t{NavigationPanel && <NavigationPanel />}\n\t\t\t\t\t\t\t{Toolbar && <Toolbar />}\n\t\t\t\t\t\t\t{HelpMenu && <HelpMenu />}\n\t\t\t\t\t\t</div>\n\t\t\t\t\t\t{isDebugMode && DebugPanel && <DebugPanel />}\n\t\t\t\t\t\t{A11y && <A11y />}\n\t\t\t\t\t</div>\n\t\t\t\t</>\n\t\t\t)}\n\t\t\t{RichTextToolbar && <RichTextToolbar />}\n\t\t\t{ImageToolbar && <ImageToolbar />}\n\t\t\t{VideoToolbar && <VideoToolbar />}\n\t\t\t{Toasts && <Toasts />}\n\t\t\t{Dialogs && <Dialogs />}\n\t\t\t<FollowingIndicator />\n\t\t\t{CursorChatBubble && <CursorChatBubble />}\n\t\t</div>\n\t)\n})\n"],
5
- "mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AA6DG;AA7DH,oBAAuD;AACvD,wBAAuB;AACvB,mBAAmD;AAEnD,kBAAkC;AAClC,gCAAmC;AACnC,4BAA+B;AAC/B,gCAAmC;AACnC,uBAAoC;AACpC,qCAGO;AACP,qBAA2B;AAC3B,yBAA8B;AAC9B,wBAAsD;AACtD,gCAAyC;AACzC,6BAAgC;AAChC,kCAAqC;AACrC,yBAA4B;AAC5B,4BAA+B;AAgCxB,MAAM,WAAW,aAAAA,QAAM,KAAK,SAASC,UAAS;AAAA,EACpD;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,GAAG;AACJ,GAAkB;AACjB,SACC,4CAAC,0DAAyB,GAAG,MAAM,YAClC,sDAAC,iBAAc,QAAgB,sBAC7B,UACF,GACD;AAEF,CAAC;AASD,MAAM,gBAAgB,aAAAD,QAAM,KAAK,SAASE,eAAc;AAAA,EACvD;AAAA,EACA;AAAA,EACA,GAAG;AACJ,GAAmD;AAKlD,SACC,4EACE;AAAA;AAAA,IACA,SAAS,OAAO,4CAAC,mBAAiB,GAAG,MAAM;AAAA,KAC7C;AAEF,CAAC;AAED,MAAM,kBAAkB,aAAAF,QAAM,KAAK,SAAS,WAAW;AACtD,QAAM,aAAS,yBAAU;AACzB,QAAM,UAAM,sCAAe;AAC3B,QAAM,iBAAa,kCAAc;AACjC,QAAM,qBAAiB,gCAAY;AACnC,QAAM,kBAAc,wBAAS,SAAS,MAAM,OAAO,iBAAiB,EAAE,aAAa,CAAC,MAAM,CAAC;AAC3F,QAAM,kBAAc,wBAAS,SAAS,MAAM,OAAO,iBAAiB,EAAE,aAAa,CAAC,MAAM,CAAC;AAE3F,QAAM;AAAA,IACL;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACD,QAAI,yCAAsB;AAE1B,wDAAqB;AACrB,0DAAyB;AACzB,8CAAgB;AAEhB,QAAM,yBAAqB,qBAAO,KAAK;AACvC,QAAM,qBAAiB,qBAAO,EAAS;AACvC,QAAM,CAAC,yBAAyB,0BAA0B,QAAI,uBAAS,KAAK;AAE5E;AAAA,IACC;AAAA,IACA,MAAM;AACL,YAAM,sBAAsB,oBAAM,SAAS,oBAAM;AACjD,UAAI,CAAC,oBAAqB;AAE1B,YAAM,eAAe,OAAO,kBAAkB;AAC9C,UAAI,iBAAiB,MAAM;AAC1B,YAAI,mBAAmB,SAAS;AAC/B,6BAAmB,UAAU;AAC7B,uBAAa,eAAe,OAAO;AACnC,cAAI,oBAAM,WAAW;AAEpB,2BAAe,UAAU,OAAO,OAAO,WAAW,MAAM;AACvD,yCAA2B,KAAK;AAAA,YACjC,GAAG,GAAG;AAAA,UACP,OAAO;AAEN,uCAA2B,KAAK;AAAA,UACjC;AAAA,QACD;AACA;AAAA,MACD;AAEA,UAAI,CAAC,mBAAmB,SAAS;AAChC,2BAAmB,UAAU;AAC7B,qBAAa,eAAe,OAAO;AACnC,mCAA2B,IAAI;AAAA,MAChC;AAAA,IACD;AAAA,IACA,CAAC;AAAA,EACF;AAEA,QAAM,EAAE,qBAAqB,YAAY,QAAI,2BAAW;AAExD,SACC;AAAA,IAAC;AAAA;AAAA,MACA,eAAW,kBAAAG,SAAW,eAAe;AAAA,QACpC,uBAAuB,aAAa,qCAAoB;AAAA,MACzD,CAAC;AAAA,MAGD,0BAAwB;AAAA,MACxB,mBAAiB;AAAA,MAEjB;AAAA,oDAAC,iCAAkB;AAAA,QAClB,cACA,4CAAC,SAAI,WAAU,oBACd;AAAA,UAAC;AAAA;AAAA,YACA,MAAK;AAAA,YACL,WAAU;AAAA,YACV,OAAO,IAAI,8BAA8B;AAAA,YACzC,SAAS,MAAM,YAAY,SAAS,MAAM;AAAA,YAE1C,sDAAC,gDAAmB,MAAK,OAAM;AAAA;AAAA,QAChC,GACD,IAEA,4EACC;AAAA,uDAAC,SAAI,WAAU,oBACd;AAAA,yDAAC,SAAI,WAAU,0BACb;AAAA,2BAAa,4CAAC,aAAU;AAAA,cACxB,iBAAiB,4CAAC,iBAAc;AAAA,eAClC;AAAA,YACA,4CAAC,SAAI,WAAU,4BAA4B,sBAAY,4CAAC,YAAS,GAAG;AAAA,YACpE,6CAAC,SAAI,WAAU,2BACb;AAAA,4BAAc,4CAAC,cAAW;AAAA,cAC1B,cAAc,cAAc,qCAAoB,aAAa,CAAC,kBAC9D,4CAAC,cAAW;AAAA,eAEd;AAAA,aACD;AAAA,UACA,6CAAC,SAAI,WAAU,uBACd;AAAA,yDAAC,SAAI,WAAU,6BACb;AAAA,iCAAmB,4CAAC,mBAAgB;AAAA,cACpC,WAAW,4CAAC,WAAQ;AAAA,cACpB,YAAY,4CAAC,YAAS;AAAA,eACxB;AAAA,YACC,eAAe,cAAc,4CAAC,cAAW;AAAA,YACzC,QAAQ,4CAAC,QAAK;AAAA,aAChB;AAAA,WACD;AAAA,QAEA,mBAAmB,4CAAC,mBAAgB;AAAA,QACpC,gBAAgB,4CAAC,gBAAa;AAAA,QAC9B,gBAAgB,4CAAC,gBAAa;AAAA,QAC9B,UAAU,4CAAC,UAAO;AAAA,QAClB,WAAW,4CAAC,WAAQ;AAAA,QACrB,4CAAC,gDAAmB;AAAA,QACnB,oBAAoB,4CAAC,oBAAiB;AAAA;AAAA;AAAA,EACxC;AAEF,CAAC;",
6
- "names": ["React", "TldrawUi", "TldrawUiInner", "classNames"]
4
+ "sourcesContent": ["import { tlenv, useEditor, useReactor, useValue } from '@tldraw/editor'\nimport classNames from 'classnames'\nimport React, { ReactNode, useMemo, useRef, useState } from 'react'\nimport { TLUiAssetUrlOverrides } from './assetUrls'\nimport { SkipToMainContent } from './components/A11y'\nimport { FollowingIndicator } from './components/FollowingIndicator'\nimport { TldrawUiButton } from './components/primitives/Button/TldrawUiButton'\nimport { TldrawUiButtonIcon } from './components/primitives/Button/TldrawUiButtonIcon'\nimport { PORTRAIT_BREAKPOINT, PORTRAIT_BREAKPOINTS } from './constants'\nimport {\n\tTLUiContextProviderProps,\n\tTldrawUiContextProvider,\n} from './context/TldrawUiContextProvider'\nimport { useActions } from './context/actions'\nimport { useBreakpoint } from './context/breakpoints'\nimport { TLUiComponents, useTldrawUiComponents } from './context/components'\nimport { useNativeClipboardEvents } from './hooks/useClipboardEvents'\nimport { useEditorEvents } from './hooks/useEditorEvents'\nimport { useKeyboardShortcuts } from './hooks/useKeyboardShortcuts'\nimport { useReadonly } from './hooks/useReadonly'\nimport { useTranslation } from './hooks/useTranslation/useTranslation'\n\n/** @public */\nexport interface TldrawUiProps extends TLUiContextProviderProps {\n\t/**\n\t * The component's children.\n\t */\n\tchildren?: ReactNode\n\n\t/**\n\t * Whether to hide the user interface and only display the canvas.\n\t */\n\thideUi?: boolean\n\n\t/**\n\t * Overrides for the UI components.\n\t */\n\tcomponents?: TLUiComponents\n\n\t/**\n\t * Additional items to add to the debug menu (will be deprecated)\n\t */\n\trenderDebugMenuItems?(): React.ReactNode\n\n\t/** Asset URL override. */\n\tassetUrls?: TLUiAssetUrlOverrides\n}\n\n/**\n * @public\n * @react\n */\nexport const TldrawUi = React.memo(function TldrawUi({\n\trenderDebugMenuItems,\n\tchildren,\n\thideUi,\n\tcomponents,\n\t...rest\n}: TldrawUiProps) {\n\treturn (\n\t\t<TldrawUiContextProvider {...rest} components={components}>\n\t\t\t<TldrawUiInner hideUi={hideUi} renderDebugMenuItems={renderDebugMenuItems}>\n\t\t\t\t{children}\n\t\t\t</TldrawUiInner>\n\t\t</TldrawUiContextProvider>\n\t)\n})\n\ninterface TldrawUiContentProps {\n\thideUi?: boolean\n\tshareZone?: ReactNode\n\ttopZone?: ReactNode\n\trenderDebugMenuItems?(): React.ReactNode\n}\n\nconst TldrawUiInner = React.memo(function TldrawUiInner({\n\tchildren,\n\thideUi,\n\t...rest\n}: TldrawUiContentProps & { children: ReactNode }) {\n\t// The hideUi prop should prevent the UI from mounting.\n\t// If we ever need want the UI to mount and preserve state, then\n\t// we should change this behavior and hide the UI via CSS instead.\n\n\treturn (\n\t\t<>\n\t\t\t{children}\n\t\t\t{hideUi ? null : <TldrawUiContent {...rest} />}\n\t\t</>\n\t)\n})\n\nconst TldrawUiContent = React.memo(function TldrawUI() {\n\tconst editor = useEditor()\n\tconst msg = useTranslation()\n\tconst breakpoint = useBreakpoint()\n\tconst isReadonlyMode = useReadonly()\n\tconst isFocusMode = useValue('focus', () => editor.getInstanceState().isFocusMode, [editor])\n\tconst isDebugMode = useValue('debug', () => editor.getInstanceState().isDebugMode, [editor])\n\n\tconst {\n\t\tSharePanel,\n\t\tTopPanel,\n\t\tMenuPanel,\n\t\tStylePanel,\n\t\tToolbar,\n\t\tHelpMenu,\n\t\tNavigationPanel,\n\t\tHelperButtons,\n\t\tDebugPanel,\n\t\tCursorChatBubble,\n\t\tRichTextToolbar,\n\t\tImageToolbar,\n\t\tVideoToolbar,\n\t\tToasts,\n\t\tDialogs,\n\t\tA11y,\n\t} = useTldrawUiComponents()\n\n\tuseKeyboardShortcuts()\n\tuseNativeClipboardEvents()\n\tuseEditorEvents()\n\n\tconst rIsEditingAnything = useRef(false)\n\tconst rHidingTimeout = useRef(-1 as any)\n\tconst [hideToolbarWhileEditing, setHideToolbarWhileEditing] = useState(false)\n\n\tuseReactor(\n\t\t'update hide toolbar while delayed',\n\t\t() => {\n\t\t\tconst isMobileEnvironment = tlenv.isIos || tlenv.isAndroid\n\t\t\tif (!isMobileEnvironment) return\n\n\t\t\tconst editingShape = editor.getEditingShapeId()\n\t\t\tif (editingShape === null) {\n\t\t\t\tif (rIsEditingAnything.current) {\n\t\t\t\t\trIsEditingAnything.current = false\n\t\t\t\t\tclearTimeout(rHidingTimeout.current)\n\t\t\t\t\tif (tlenv.isAndroid) {\n\t\t\t\t\t\t// On Android, hide it after 150ms\n\t\t\t\t\t\trHidingTimeout.current = editor.timers.setTimeout(() => {\n\t\t\t\t\t\t\tsetHideToolbarWhileEditing(false)\n\t\t\t\t\t\t}, 150)\n\t\t\t\t\t} else {\n\t\t\t\t\t\t// On iOS, just hide it immediately\n\t\t\t\t\t\tsetHideToolbarWhileEditing(false)\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn\n\t\t\t}\n\n\t\t\tif (!rIsEditingAnything.current) {\n\t\t\t\trIsEditingAnything.current = true\n\t\t\t\tclearTimeout(rHidingTimeout.current)\n\t\t\t\tsetHideToolbarWhileEditing(true)\n\t\t\t}\n\t\t},\n\t\t[]\n\t)\n\n\tconst { 'toggle-focus-mode': toggleFocus } = useActions()\n\n\tconst { breakpointsAbove, breakpointsBelow } = useMemo(() => {\n\t\tconst breakpointsAbove = []\n\t\tconst breakpointsBelow = []\n\t\tfor (let bp = 0; bp < PORTRAIT_BREAKPOINTS.length; bp++) {\n\t\t\tif (bp <= breakpoint) {\n\t\t\t\tbreakpointsAbove.push(bp)\n\t\t\t} else {\n\t\t\t\tbreakpointsBelow.push(bp)\n\t\t\t}\n\t\t}\n\t\treturn { breakpointsAbove, breakpointsBelow }\n\t}, [breakpoint])\n\n\treturn (\n\t\t<div\n\t\t\tclassName={classNames('tlui-layout', {\n\t\t\t\t'tlui-layout__mobile': breakpoint < PORTRAIT_BREAKPOINT.TABLET_SM,\n\t\t\t})}\n\t\t\t// When the virtual keyboard is opening we want it to hide immediately.\n\t\t\t// But when the virtual keyboard is closing we want to wait a bit before showing it again.\n\t\t\tdata-iseditinganything={hideToolbarWhileEditing}\n\t\t\tdata-breakpoint={breakpoint}\n\t\t\tdata-breakpoints-above={breakpointsAbove.join(' ')}\n\t\t\tdata-breakpoints-below={breakpointsBelow.join(' ')}\n\t\t>\n\t\t\t<SkipToMainContent />\n\t\t\t{isFocusMode ? (\n\t\t\t\t<div className=\"tlui-layout__top\">\n\t\t\t\t\t<TldrawUiButton\n\t\t\t\t\t\ttype=\"icon\"\n\t\t\t\t\t\tclassName=\"tlui-focus-button\"\n\t\t\t\t\t\ttitle={msg('focus-mode.toggle-focus-mode')}\n\t\t\t\t\t\tonClick={() => toggleFocus.onSelect('menu')}\n\t\t\t\t\t>\n\t\t\t\t\t\t<TldrawUiButtonIcon icon=\"dot\" />\n\t\t\t\t\t</TldrawUiButton>\n\t\t\t\t</div>\n\t\t\t) : (\n\t\t\t\t<>\n\t\t\t\t\t<div className=\"tlui-layout__top\">\n\t\t\t\t\t\t<div className=\"tlui-layout__top__left\">\n\t\t\t\t\t\t\t{MenuPanel && <MenuPanel />}\n\t\t\t\t\t\t\t{HelperButtons && <HelperButtons />}\n\t\t\t\t\t\t</div>\n\t\t\t\t\t\t<div className=\"tlui-layout__top__center\">{TopPanel && <TopPanel />}</div>\n\t\t\t\t\t\t<div className=\"tlui-layout__top__right\">\n\t\t\t\t\t\t\t{SharePanel && <SharePanel />}\n\t\t\t\t\t\t\t{StylePanel && breakpoint >= PORTRAIT_BREAKPOINT.TABLET_SM && !isReadonlyMode && (\n\t\t\t\t\t\t\t\t<StylePanel />\n\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t</div>\n\t\t\t\t\t</div>\n\t\t\t\t\t<div className=\"tlui-layout__bottom\">\n\t\t\t\t\t\t<div className=\"tlui-layout__bottom__main\">\n\t\t\t\t\t\t\t{NavigationPanel && <NavigationPanel />}\n\t\t\t\t\t\t\t{Toolbar && <Toolbar />}\n\t\t\t\t\t\t\t{HelpMenu && <HelpMenu />}\n\t\t\t\t\t\t</div>\n\t\t\t\t\t\t{isDebugMode && DebugPanel && <DebugPanel />}\n\t\t\t\t\t\t{A11y && <A11y />}\n\t\t\t\t\t</div>\n\t\t\t\t</>\n\t\t\t)}\n\t\t\t{RichTextToolbar && <RichTextToolbar />}\n\t\t\t{ImageToolbar && <ImageToolbar />}\n\t\t\t{VideoToolbar && <VideoToolbar />}\n\t\t\t{Toasts && <Toasts />}\n\t\t\t{Dialogs && <Dialogs />}\n\t\t\t<FollowingIndicator />\n\t\t\t{CursorChatBubble && <CursorChatBubble />}\n\t\t</div>\n\t)\n})\n"],
5
+ "mappings": "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",
6
+ "names": ["React", "TldrawUi", "TldrawUiInner", "breakpointsAbove", "breakpointsBelow", "classNames"]
7
7
  }
@@ -31,6 +31,7 @@ var import_useTranslation = require("../../hooks/useTranslation/useTranslation")
31
31
  var import_TldrawUiButtonIcon = require("../primitives/Button/TldrawUiButtonIcon");
32
32
  var import_TldrawUiPopover = require("../primitives/TldrawUiPopover");
33
33
  var import_TldrawUiToolbar = require("../primitives/TldrawUiToolbar");
34
+ var import_layout = require("../primitives/layout");
34
35
  var import_TldrawUiMenuContext = require("../primitives/menus/TldrawUiMenuContext");
35
36
  var import_DefaultActionsMenuContent = require("./DefaultActionsMenuContent");
36
37
  const DefaultActionsMenu = (0, import_react.memo)(function DefaultActionsMenu2({
@@ -39,6 +40,7 @@ const DefaultActionsMenu = (0, import_react.memo)(function DefaultActionsMenu2({
39
40
  const msg = (0, import_useTranslation.useTranslation)();
40
41
  const breakpoint = (0, import_breakpoints.useBreakpoint)();
41
42
  const isReadonlyMode = (0, import_useReadonly.useReadonly)();
43
+ const { orientation } = (0, import_layout.useTldrawUiOrientation)();
42
44
  const ref = (0, import_react.useRef)(null);
43
45
  (0, import_editor.usePassThroughWheelEvents)(ref);
44
46
  const editor = (0, import_editor.useEditor)();
@@ -56,13 +58,19 @@ const DefaultActionsMenu = (0, import_react.memo)(function DefaultActionsMenu2({
56
58
  type: "icon",
57
59
  "data-testid": "actions-menu.button",
58
60
  title: msg("actions-menu.title"),
59
- children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_TldrawUiButtonIcon.TldrawUiButtonIcon, { icon: "dots-vertical", small: true })
61
+ children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
62
+ import_TldrawUiButtonIcon.TldrawUiButtonIcon,
63
+ {
64
+ icon: orientation === "horizontal" ? "dots-vertical" : "dots-horizontal",
65
+ small: true
66
+ }
67
+ )
60
68
  }
61
69
  ) }),
62
70
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
63
71
  import_TldrawUiPopover.TldrawUiPopoverContent,
64
72
  {
65
- side: breakpoint >= import_constants.PORTRAIT_BREAKPOINT.TABLET ? "bottom" : "top",
73
+ side: orientation === "horizontal" ? breakpoint >= import_constants.PORTRAIT_BREAKPOINT.TABLET ? "bottom" : "top" : "right",
66
74
  sideOffset: 6,
67
75
  children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
68
76
  import_TldrawUiToolbar.TldrawUiToolbar,
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../../src/lib/ui/components/ActionsMenu/DefaultActionsMenu.tsx"],
4
- "sourcesContent": ["import { useEditor, usePassThroughWheelEvents, useValue } from '@tldraw/editor'\nimport { ReactNode, memo, useRef } from 'react'\nimport { PORTRAIT_BREAKPOINT } from '../../constants'\nimport { useBreakpoint } from '../../context/breakpoints'\nimport { useReadonly } from '../../hooks/useReadonly'\nimport { useTranslation } from '../../hooks/useTranslation/useTranslation'\nimport { TldrawUiButtonIcon } from '../primitives/Button/TldrawUiButtonIcon'\nimport {\n\tTldrawUiPopover,\n\tTldrawUiPopoverContent,\n\tTldrawUiPopoverTrigger,\n} from '../primitives/TldrawUiPopover'\nimport { TldrawUiToolbar, TldrawUiToolbarButton } from '../primitives/TldrawUiToolbar'\nimport { TldrawUiMenuContextProvider } from '../primitives/menus/TldrawUiMenuContext'\nimport { DefaultActionsMenuContent } from './DefaultActionsMenuContent'\n\n/** @public */\nexport interface TLUiActionsMenuProps {\n\tchildren?: ReactNode\n}\n\n/** @public @react */\nexport const DefaultActionsMenu = memo(function DefaultActionsMenu({\n\tchildren,\n}: TLUiActionsMenuProps) {\n\tconst msg = useTranslation()\n\tconst breakpoint = useBreakpoint()\n\tconst isReadonlyMode = useReadonly()\n\n\tconst ref = useRef<HTMLDivElement>(null)\n\tusePassThroughWheelEvents(ref)\n\n\tconst editor = useEditor()\n\tconst isInAcceptableReadonlyState = useValue(\n\t\t'should display quick actions when in readonly',\n\t\t() => editor.isInAny('hand', 'zoom'),\n\t\t[editor]\n\t)\n\n\t// Get the actions menu content, either the default component or the user's\n\t// override. If there's no menu content, then the user has set it to null,\n\t// so skip rendering the menu.\n\n\tconst content = children ?? <DefaultActionsMenuContent />\n\tif (isReadonlyMode && !isInAcceptableReadonlyState) return\n\n\treturn (\n\t\t<TldrawUiPopover id=\"actions-menu\">\n\t\t\t<TldrawUiPopoverTrigger>\n\t\t\t\t<TldrawUiToolbarButton\n\t\t\t\t\ttype=\"icon\"\n\t\t\t\t\tdata-testid=\"actions-menu.button\"\n\t\t\t\t\ttitle={msg('actions-menu.title')}\n\t\t\t\t>\n\t\t\t\t\t<TldrawUiButtonIcon icon=\"dots-vertical\" small />\n\t\t\t\t</TldrawUiToolbarButton>\n\t\t\t</TldrawUiPopoverTrigger>\n\t\t\t<TldrawUiPopoverContent\n\t\t\t\tside={breakpoint >= PORTRAIT_BREAKPOINT.TABLET ? 'bottom' : 'top'}\n\t\t\t\tsideOffset={6}\n\t\t\t>\n\t\t\t\t<TldrawUiToolbar\n\t\t\t\t\tref={ref}\n\t\t\t\t\tlabel={msg('actions-menu.title')}\n\t\t\t\t\tclassName=\"tlui-actions-menu\"\n\t\t\t\t\tdata-testid=\"actions-menu.content\"\n\t\t\t\t\torientation=\"grid\"\n\t\t\t\t>\n\t\t\t\t\t<TldrawUiMenuContextProvider type=\"icons\" sourceId=\"actions-menu\">\n\t\t\t\t\t\t{content}\n\t\t\t\t\t</TldrawUiMenuContextProvider>\n\t\t\t\t</TldrawUiToolbar>\n\t\t\t</TldrawUiPopoverContent>\n\t\t</TldrawUiPopover>\n\t)\n})\n"],
5
- "mappings": ";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AA2C6B;AA3C7B,oBAA+D;AAC/D,mBAAwC;AACxC,uBAAoC;AACpC,yBAA8B;AAC9B,yBAA4B;AAC5B,4BAA+B;AAC/B,gCAAmC;AACnC,6BAIO;AACP,6BAAuD;AACvD,iCAA4C;AAC5C,uCAA0C;AAQnC,MAAM,yBAAqB,mBAAK,SAASA,oBAAmB;AAAA,EAClE;AACD,GAAyB;AACxB,QAAM,UAAM,sCAAe;AAC3B,QAAM,iBAAa,kCAAc;AACjC,QAAM,qBAAiB,gCAAY;AAEnC,QAAM,UAAM,qBAAuB,IAAI;AACvC,+CAA0B,GAAG;AAE7B,QAAM,aAAS,yBAAU;AACzB,QAAM,kCAA8B;AAAA,IACnC;AAAA,IACA,MAAM,OAAO,QAAQ,QAAQ,MAAM;AAAA,IACnC,CAAC,MAAM;AAAA,EACR;AAMA,QAAM,UAAU,YAAY,4CAAC,8DAA0B;AACvD,MAAI,kBAAkB,CAAC,4BAA6B;AAEpD,SACC,6CAAC,0CAAgB,IAAG,gBACnB;AAAA,gDAAC,iDACA;AAAA,MAAC;AAAA;AAAA,QACA,MAAK;AAAA,QACL,eAAY;AAAA,QACZ,OAAO,IAAI,oBAAoB;AAAA,QAE/B,sDAAC,gDAAmB,MAAK,iBAAgB,OAAK,MAAC;AAAA;AAAA,IAChD,GACD;AAAA,IACA;AAAA,MAAC;AAAA;AAAA,QACA,MAAM,cAAc,qCAAoB,SAAS,WAAW;AAAA,QAC5D,YAAY;AAAA,QAEZ;AAAA,UAAC;AAAA;AAAA,YACA;AAAA,YACA,OAAO,IAAI,oBAAoB;AAAA,YAC/B,WAAU;AAAA,YACV,eAAY;AAAA,YACZ,aAAY;AAAA,YAEZ,sDAAC,0DAA4B,MAAK,SAAQ,UAAS,gBACjD,mBACF;AAAA;AAAA,QACD;AAAA;AAAA,IACD;AAAA,KACD;AAEF,CAAC;",
4
+ "sourcesContent": ["import { useEditor, usePassThroughWheelEvents, useValue } from '@tldraw/editor'\nimport { ReactNode, memo, useRef } from 'react'\nimport { PORTRAIT_BREAKPOINT } from '../../constants'\nimport { useBreakpoint } from '../../context/breakpoints'\nimport { useReadonly } from '../../hooks/useReadonly'\nimport { useTranslation } from '../../hooks/useTranslation/useTranslation'\nimport { TldrawUiButtonIcon } from '../primitives/Button/TldrawUiButtonIcon'\nimport {\n\tTldrawUiPopover,\n\tTldrawUiPopoverContent,\n\tTldrawUiPopoverTrigger,\n} from '../primitives/TldrawUiPopover'\nimport { TldrawUiToolbar, TldrawUiToolbarButton } from '../primitives/TldrawUiToolbar'\nimport { useTldrawUiOrientation } from '../primitives/layout'\nimport { TldrawUiMenuContextProvider } from '../primitives/menus/TldrawUiMenuContext'\nimport { DefaultActionsMenuContent } from './DefaultActionsMenuContent'\n\n/** @public */\nexport interface TLUiActionsMenuProps {\n\tchildren?: ReactNode\n}\n\n/** @public @react */\nexport const DefaultActionsMenu = memo(function DefaultActionsMenu({\n\tchildren,\n}: TLUiActionsMenuProps) {\n\tconst msg = useTranslation()\n\tconst breakpoint = useBreakpoint()\n\tconst isReadonlyMode = useReadonly()\n\tconst { orientation } = useTldrawUiOrientation()\n\n\tconst ref = useRef<HTMLDivElement>(null)\n\tusePassThroughWheelEvents(ref)\n\n\tconst editor = useEditor()\n\tconst isInAcceptableReadonlyState = useValue(\n\t\t'should display quick actions when in readonly',\n\t\t() => editor.isInAny('hand', 'zoom'),\n\t\t[editor]\n\t)\n\n\t// Get the actions menu content, either the default component or the user's\n\t// override. If there's no menu content, then the user has set it to null,\n\t// so skip rendering the menu.\n\n\tconst content = children ?? <DefaultActionsMenuContent />\n\tif (isReadonlyMode && !isInAcceptableReadonlyState) return\n\n\treturn (\n\t\t<TldrawUiPopover id=\"actions-menu\">\n\t\t\t<TldrawUiPopoverTrigger>\n\t\t\t\t<TldrawUiToolbarButton\n\t\t\t\t\ttype=\"icon\"\n\t\t\t\t\tdata-testid=\"actions-menu.button\"\n\t\t\t\t\ttitle={msg('actions-menu.title')}\n\t\t\t\t>\n\t\t\t\t\t<TldrawUiButtonIcon\n\t\t\t\t\t\ticon={orientation === 'horizontal' ? 'dots-vertical' : 'dots-horizontal'}\n\t\t\t\t\t\tsmall\n\t\t\t\t\t/>\n\t\t\t\t</TldrawUiToolbarButton>\n\t\t\t</TldrawUiPopoverTrigger>\n\t\t\t<TldrawUiPopoverContent\n\t\t\t\tside={\n\t\t\t\t\torientation === 'horizontal'\n\t\t\t\t\t\t? breakpoint >= PORTRAIT_BREAKPOINT.TABLET\n\t\t\t\t\t\t\t? 'bottom'\n\t\t\t\t\t\t\t: 'top'\n\t\t\t\t\t\t: 'right'\n\t\t\t\t}\n\t\t\t\tsideOffset={6}\n\t\t\t>\n\t\t\t\t<TldrawUiToolbar\n\t\t\t\t\tref={ref}\n\t\t\t\t\tlabel={msg('actions-menu.title')}\n\t\t\t\t\tclassName=\"tlui-actions-menu\"\n\t\t\t\t\tdata-testid=\"actions-menu.content\"\n\t\t\t\t\torientation=\"grid\"\n\t\t\t\t>\n\t\t\t\t\t<TldrawUiMenuContextProvider type=\"icons\" sourceId=\"actions-menu\">\n\t\t\t\t\t\t{content}\n\t\t\t\t\t</TldrawUiMenuContextProvider>\n\t\t\t\t</TldrawUiToolbar>\n\t\t\t</TldrawUiPopoverContent>\n\t\t</TldrawUiPopover>\n\t)\n})\n"],
5
+ "mappings": ";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AA6C6B;AA7C7B,oBAA+D;AAC/D,mBAAwC;AACxC,uBAAoC;AACpC,yBAA8B;AAC9B,yBAA4B;AAC5B,4BAA+B;AAC/B,gCAAmC;AACnC,6BAIO;AACP,6BAAuD;AACvD,oBAAuC;AACvC,iCAA4C;AAC5C,uCAA0C;AAQnC,MAAM,yBAAqB,mBAAK,SAASA,oBAAmB;AAAA,EAClE;AACD,GAAyB;AACxB,QAAM,UAAM,sCAAe;AAC3B,QAAM,iBAAa,kCAAc;AACjC,QAAM,qBAAiB,gCAAY;AACnC,QAAM,EAAE,YAAY,QAAI,sCAAuB;AAE/C,QAAM,UAAM,qBAAuB,IAAI;AACvC,+CAA0B,GAAG;AAE7B,QAAM,aAAS,yBAAU;AACzB,QAAM,kCAA8B;AAAA,IACnC;AAAA,IACA,MAAM,OAAO,QAAQ,QAAQ,MAAM;AAAA,IACnC,CAAC,MAAM;AAAA,EACR;AAMA,QAAM,UAAU,YAAY,4CAAC,8DAA0B;AACvD,MAAI,kBAAkB,CAAC,4BAA6B;AAEpD,SACC,6CAAC,0CAAgB,IAAG,gBACnB;AAAA,gDAAC,iDACA;AAAA,MAAC;AAAA;AAAA,QACA,MAAK;AAAA,QACL,eAAY;AAAA,QACZ,OAAO,IAAI,oBAAoB;AAAA,QAE/B;AAAA,UAAC;AAAA;AAAA,YACA,MAAM,gBAAgB,eAAe,kBAAkB;AAAA,YACvD,OAAK;AAAA;AAAA,QACN;AAAA;AAAA,IACD,GACD;AAAA,IACA;AAAA,MAAC;AAAA;AAAA,QACA,MACC,gBAAgB,eACb,cAAc,qCAAoB,SACjC,WACA,QACD;AAAA,QAEJ,YAAY;AAAA,QAEZ;AAAA,UAAC;AAAA;AAAA,YACA;AAAA,YACA,OAAO,IAAI,oBAAoB;AAAA,YAC/B,WAAU;AAAA,YACV,eAAY;AAAA,YACZ,aAAY;AAAA,YAEZ,sDAAC,0DAA4B,MAAK,SAAQ,UAAS,gBACjD,mBACF;AAAA;AAAA,QACD;AAAA;AAAA,IACD;AAAA,KACD;AAEF,CAAC;",
6
6
  "names": ["DefaultActionsMenu"]
7
7
  }
@@ -105,10 +105,10 @@ class MinimapManager {
105
105
  _getColors() {
106
106
  const style = getComputedStyle(this.editor.getContainer());
107
107
  return {
108
- shapeFill: (0, import_getRgba.getRgba)(style.getPropertyValue("--color-text-3").trim()),
109
- selectFill: (0, import_getRgba.getRgba)(style.getPropertyValue("--color-selected").trim()),
110
- viewportFill: (0, import_getRgba.getRgba)(style.getPropertyValue("--color-muted-1").trim()),
111
- background: (0, import_getRgba.getRgba)(style.getPropertyValue("--color-low").trim())
108
+ shapeFill: (0, import_getRgba.getRgba)(style.getPropertyValue("--tl-color-text-3").trim()),
109
+ selectFill: (0, import_getRgba.getRgba)(style.getPropertyValue("--tl-color-selected").trim()),
110
+ viewportFill: (0, import_getRgba.getRgba)(style.getPropertyValue("--tl-color-muted-1").trim()),
111
+ background: (0, import_getRgba.getRgba)(style.getPropertyValue("--tl-color-low").trim())
112
112
  };
113
113
  }
114
114
  // this should be called after dark/light mode changes have propagated to the dom