tldraw 3.16.0-internal.51e99e128bd4 → 3.16.0-next.15f085081fd5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist-cjs/index.d.ts +20 -1
- package/dist-cjs/index.js +5 -1
- package/dist-cjs/index.js.map +2 -2
- package/dist-cjs/lib/Tldraw.js +12 -2
- package/dist-cjs/lib/Tldraw.js.map +2 -2
- package/dist-cjs/lib/defaultExternalContentHandlers.js +5 -4
- package/dist-cjs/lib/defaultExternalContentHandlers.js.map +2 -2
- package/dist-cjs/lib/shapes/frame/FrameShapeUtil.js +3 -0
- package/dist-cjs/lib/shapes/frame/FrameShapeUtil.js.map +2 -2
- package/dist-cjs/lib/shapes/image/ImageShapeUtil.js +3 -0
- package/dist-cjs/lib/shapes/image/ImageShapeUtil.js.map +2 -2
- package/dist-cjs/lib/ui/TldrawUi.js +13 -12
- package/dist-cjs/lib/ui/TldrawUi.js.map +2 -2
- package/dist-cjs/lib/ui/components/{FollowingIndicator.js → DefaultFollowingIndicator.js} +6 -6
- package/dist-cjs/lib/ui/components/DefaultFollowingIndicator.js.map +7 -0
- package/dist-cjs/lib/ui/components/KeyboardShortcutsDialog/DefaultKeyboardShortcutsDialogContent.js +6 -6
- package/dist-cjs/lib/ui/components/KeyboardShortcutsDialog/DefaultKeyboardShortcutsDialogContent.js.map +1 -1
- package/dist-cjs/lib/ui/components/StylePanel/DropdownPicker.js +1 -1
- package/dist-cjs/lib/ui/components/StylePanel/DropdownPicker.js.map +2 -2
- package/dist-cjs/lib/ui/components/primitives/TldrawUiTooltip.js +31 -37
- package/dist-cjs/lib/ui/components/primitives/TldrawUiTooltip.js.map +2 -2
- package/dist-cjs/lib/ui/context/actions.js +16 -2
- package/dist-cjs/lib/ui/context/actions.js.map +2 -2
- package/dist-cjs/lib/ui/context/components.js +2 -0
- package/dist-cjs/lib/ui/context/components.js.map +2 -2
- package/dist-cjs/lib/ui/hooks/useTranslation/TLUiTranslationKey.js.map +1 -1
- package/dist-cjs/lib/ui/hooks/useTranslation/defaultTranslation.js +1 -0
- package/dist-cjs/lib/ui/hooks/useTranslation/defaultTranslation.js.map +2 -2
- package/dist-cjs/lib/ui/kbd-utils.js +9 -3
- package/dist-cjs/lib/ui/kbd-utils.js.map +2 -2
- package/dist-cjs/lib/ui/version.js +3 -3
- package/dist-cjs/lib/ui/version.js.map +1 -1
- package/dist-esm/index.d.mts +20 -1
- package/dist-esm/index.mjs +7 -2
- package/dist-esm/index.mjs.map +2 -2
- package/dist-esm/lib/Tldraw.mjs +14 -4
- package/dist-esm/lib/Tldraw.mjs.map +2 -2
- package/dist-esm/lib/defaultExternalContentHandlers.mjs +5 -4
- package/dist-esm/lib/defaultExternalContentHandlers.mjs.map +2 -2
- package/dist-esm/lib/shapes/frame/FrameShapeUtil.mjs +3 -0
- package/dist-esm/lib/shapes/frame/FrameShapeUtil.mjs.map +2 -2
- package/dist-esm/lib/shapes/image/ImageShapeUtil.mjs +3 -0
- package/dist-esm/lib/shapes/image/ImageShapeUtil.mjs.map +2 -2
- package/dist-esm/lib/ui/TldrawUi.mjs +13 -12
- package/dist-esm/lib/ui/TldrawUi.mjs.map +2 -2
- package/dist-esm/lib/ui/components/{FollowingIndicator.mjs → DefaultFollowingIndicator.mjs} +3 -3
- package/dist-esm/lib/ui/components/DefaultFollowingIndicator.mjs.map +7 -0
- package/dist-esm/lib/ui/components/KeyboardShortcutsDialog/DefaultKeyboardShortcutsDialogContent.mjs +6 -6
- package/dist-esm/lib/ui/components/KeyboardShortcutsDialog/DefaultKeyboardShortcutsDialogContent.mjs.map +1 -1
- package/dist-esm/lib/ui/components/StylePanel/DropdownPicker.mjs +1 -1
- package/dist-esm/lib/ui/components/StylePanel/DropdownPicker.mjs.map +2 -2
- package/dist-esm/lib/ui/components/primitives/TldrawUiTooltip.mjs +31 -37
- package/dist-esm/lib/ui/components/primitives/TldrawUiTooltip.mjs.map +2 -2
- package/dist-esm/lib/ui/context/actions.mjs +16 -2
- package/dist-esm/lib/ui/context/actions.mjs.map +2 -2
- package/dist-esm/lib/ui/context/components.mjs +2 -0
- package/dist-esm/lib/ui/context/components.mjs.map +2 -2
- package/dist-esm/lib/ui/hooks/useTranslation/defaultTranslation.mjs +1 -0
- package/dist-esm/lib/ui/hooks/useTranslation/defaultTranslation.mjs.map +2 -2
- package/dist-esm/lib/ui/kbd-utils.mjs +9 -3
- package/dist-esm/lib/ui/kbd-utils.mjs.map +2 -2
- package/dist-esm/lib/ui/version.mjs +3 -3
- package/dist-esm/lib/ui/version.mjs.map +1 -1
- package/package.json +3 -3
- package/src/index.ts +3 -1
- package/src/lib/Tldraw.tsx +15 -2
- package/src/lib/defaultExternalContentHandlers.ts +12 -4
- package/src/lib/shapes/frame/FrameShapeUtil.tsx +4 -0
- package/src/lib/shapes/image/ImageShapeUtil.tsx +3 -0
- package/src/lib/ui/TldrawUi.tsx +16 -10
- package/src/lib/ui/components/{FollowingIndicator.tsx → DefaultFollowingIndicator.tsx} +2 -1
- package/src/lib/ui/components/KeyboardShortcutsDialog/DefaultKeyboardShortcutsDialogContent.tsx +6 -6
- package/src/lib/ui/components/StylePanel/DropdownPicker.tsx +1 -1
- package/src/lib/ui/components/primitives/TldrawUiTooltip.tsx +20 -22
- package/src/lib/ui/context/actions.tsx +16 -2
- package/src/lib/ui/context/components.tsx +3 -0
- package/src/lib/ui/hooks/useTranslation/TLUiTranslationKey.ts +1 -0
- package/src/lib/ui/hooks/useTranslation/defaultTranslation.ts +1 -0
- package/src/lib/ui/kbd-utils.ts +10 -3
- package/src/lib/ui/version.ts +3 -3
- package/src/lib/ui.css +3 -0
- package/tldraw.css +11 -0
- package/dist-cjs/lib/ui/components/FollowingIndicator.js.map +0 -7
- package/dist-esm/lib/ui/components/FollowingIndicator.mjs.map +0 -7
|
@@ -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 = 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": "
|
|
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 isExportBoundsContainer(): boolean {\n\t\treturn true\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": ["shape"]
|
|
7
7
|
}
|
|
@@ -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(--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
|
-
"mappings": "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",
|
|
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\toverride isExportBoundsContainer(): boolean {\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
|
+
"mappings": "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",
|
|
6
6
|
"names": ["src", "startShape", "endShape", "ImageShape"]
|
|
7
7
|
}
|
|
@@ -3,7 +3,6 @@ import { tlenv, useEditor, useReactor, useValue } from "@tldraw/editor";
|
|
|
3
3
|
import classNames from "classnames";
|
|
4
4
|
import React, { useMemo, useRef, useState } from "react";
|
|
5
5
|
import { SkipToMainContent } from "./components/A11y.mjs";
|
|
6
|
-
import { FollowingIndicator } from "./components/FollowingIndicator.mjs";
|
|
7
6
|
import { TldrawUiButton } from "./components/primitives/Button/TldrawUiButton.mjs";
|
|
8
7
|
import { TldrawUiButtonIcon } from "./components/primitives/Button/TldrawUiButtonIcon.mjs";
|
|
9
8
|
import { PORTRAIT_BREAKPOINT, PORTRAIT_BREAKPOINTS } from "./constants.mjs";
|
|
@@ -54,10 +53,6 @@ const TldrawUiContent = React.memo(function TldrawUI() {
|
|
|
54
53
|
NavigationPanel,
|
|
55
54
|
HelperButtons,
|
|
56
55
|
DebugPanel,
|
|
57
|
-
CursorChatBubble,
|
|
58
|
-
RichTextToolbar,
|
|
59
|
-
ImageToolbar,
|
|
60
|
-
VideoToolbar,
|
|
61
56
|
Toasts,
|
|
62
57
|
Dialogs,
|
|
63
58
|
A11y
|
|
@@ -152,18 +147,24 @@ const TldrawUiContent = React.memo(function TldrawUI() {
|
|
|
152
147
|
A11y && /* @__PURE__ */ jsx(A11y, {})
|
|
153
148
|
] })
|
|
154
149
|
] }),
|
|
155
|
-
RichTextToolbar && /* @__PURE__ */ jsx(RichTextToolbar, {}),
|
|
156
|
-
ImageToolbar && /* @__PURE__ */ jsx(ImageToolbar, {}),
|
|
157
|
-
VideoToolbar && /* @__PURE__ */ jsx(VideoToolbar, {}),
|
|
158
150
|
Toasts && /* @__PURE__ */ jsx(Toasts, {}),
|
|
159
|
-
Dialogs && /* @__PURE__ */ jsx(Dialogs, {})
|
|
160
|
-
/* @__PURE__ */ jsx(FollowingIndicator, {}),
|
|
161
|
-
CursorChatBubble && /* @__PURE__ */ jsx(CursorChatBubble, {})
|
|
151
|
+
Dialogs && /* @__PURE__ */ jsx(Dialogs, {})
|
|
162
152
|
]
|
|
163
153
|
}
|
|
164
154
|
);
|
|
165
155
|
});
|
|
156
|
+
function TldrawUiInFrontOfTheCanvas() {
|
|
157
|
+
const { RichTextToolbar, ImageToolbar, VideoToolbar, CursorChatBubble, FollowingIndicator } = useTldrawUiComponents();
|
|
158
|
+
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
159
|
+
RichTextToolbar && /* @__PURE__ */ jsx(RichTextToolbar, {}),
|
|
160
|
+
ImageToolbar && /* @__PURE__ */ jsx(ImageToolbar, {}),
|
|
161
|
+
VideoToolbar && /* @__PURE__ */ jsx(VideoToolbar, {}),
|
|
162
|
+
FollowingIndicator && /* @__PURE__ */ jsx(FollowingIndicator, {}),
|
|
163
|
+
CursorChatBubble && /* @__PURE__ */ jsx(CursorChatBubble, {})
|
|
164
|
+
] });
|
|
165
|
+
}
|
|
166
166
|
export {
|
|
167
|
-
TldrawUi
|
|
167
|
+
TldrawUi,
|
|
168
|
+
TldrawUiInFrontOfTheCanvas
|
|
168
169
|
};
|
|
169
170
|
//# sourceMappingURL=TldrawUi.mjs.map
|
|
@@ -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, useMemo, useRef, useState } from 'react'\nimport { TLUiAssetUrlOverrides } from './assetUrls'\nimport { SkipToMainContent } from './components/A11y'\nimport {
|
|
5
|
-
"mappings": "
|
|
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 { 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\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{Toasts && <Toasts />}\n\t\t\t{Dialogs && <Dialogs />}\n\t\t</div>\n\t)\n})\n\n/** @public @react */\nexport function TldrawUiInFrontOfTheCanvas() {\n\tconst { RichTextToolbar, ImageToolbar, VideoToolbar, CursorChatBubble, FollowingIndicator } =\n\t\tuseTldrawUiComponents()\n\n\treturn (\n\t\t<>\n\t\t\t{RichTextToolbar && <RichTextToolbar />}\n\t\t\t{ImageToolbar && <ImageToolbar />}\n\t\t\t{VideoToolbar && <VideoToolbar />}\n\t\t\t{FollowingIndicator && <FollowingIndicator />}\n\t\t\t{CursorChatBubble && <CursorChatBubble />}\n\t\t</>\n\t)\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": ["TldrawUi", "TldrawUiInner", "breakpointsAbove", "breakpointsBelow"]
|
|
7
7
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { jsx } from "react/jsx-runtime";
|
|
2
2
|
import { useEditor, usePresence, useValue } from "@tldraw/editor";
|
|
3
|
-
function
|
|
3
|
+
function DefaultFollowingIndicator() {
|
|
4
4
|
const editor = useEditor();
|
|
5
5
|
const followingUserId = useValue("follow", () => editor.getInstanceState().followingUserId, [
|
|
6
6
|
editor
|
|
@@ -14,6 +14,6 @@ function FollowingIndicatorInner({ userId }) {
|
|
|
14
14
|
return /* @__PURE__ */ jsx("div", { className: "tlui-following-indicator", style: { borderColor: presence.color } });
|
|
15
15
|
}
|
|
16
16
|
export {
|
|
17
|
-
|
|
17
|
+
DefaultFollowingIndicator
|
|
18
18
|
};
|
|
19
|
-
//# sourceMappingURL=
|
|
19
|
+
//# sourceMappingURL=DefaultFollowingIndicator.mjs.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../../../src/lib/ui/components/DefaultFollowingIndicator.tsx"],
|
|
4
|
+
"sourcesContent": ["import { useEditor, usePresence, useValue } from '@tldraw/editor'\n\n/** @public @react */\nexport function DefaultFollowingIndicator() {\n\tconst editor = useEditor()\n\tconst followingUserId = useValue('follow', () => editor.getInstanceState().followingUserId, [\n\t\teditor,\n\t])\n\tif (!followingUserId) return null\n\treturn <FollowingIndicatorInner userId={followingUserId} />\n}\n\nfunction FollowingIndicatorInner({ userId }: { userId: string }) {\n\tconst presence = usePresence(userId)\n\tif (!presence) return null\n\treturn <div className=\"tlui-following-indicator\" style={{ borderColor: presence.color }} />\n}\n"],
|
|
5
|
+
"mappings": "AASQ;AATR,SAAS,WAAW,aAAa,gBAAgB;AAG1C,SAAS,4BAA4B;AAC3C,QAAM,SAAS,UAAU;AACzB,QAAM,kBAAkB,SAAS,UAAU,MAAM,OAAO,iBAAiB,EAAE,iBAAiB;AAAA,IAC3F;AAAA,EACD,CAAC;AACD,MAAI,CAAC,gBAAiB,QAAO;AAC7B,SAAO,oBAAC,2BAAwB,QAAQ,iBAAiB;AAC1D;AAEA,SAAS,wBAAwB,EAAE,OAAO,GAAuB;AAChE,QAAM,WAAW,YAAY,MAAM;AACnC,MAAI,CAAC,SAAU,QAAO;AACtB,SAAO,oBAAC,SAAI,WAAU,4BAA2B,OAAO,EAAE,aAAa,SAAS,MAAM,GAAG;AAC1F;",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
package/dist-esm/lib/ui/components/KeyboardShortcutsDialog/DefaultKeyboardShortcutsDialogContent.mjs
CHANGED
|
@@ -137,7 +137,7 @@ function DefaultKeyboardShortcutsDialogContent() {
|
|
|
137
137
|
{
|
|
138
138
|
id: "text-header",
|
|
139
139
|
label: "tool.rich-text-header",
|
|
140
|
-
kbd: "cmd+
|
|
140
|
+
kbd: "cmd+alt+[[1-6]]",
|
|
141
141
|
onSelect: () => {
|
|
142
142
|
}
|
|
143
143
|
}
|
|
@@ -179,7 +179,7 @@ function DefaultKeyboardShortcutsDialogContent() {
|
|
|
179
179
|
{
|
|
180
180
|
id: "a11y-select-next-shape-direction",
|
|
181
181
|
label: "a11y.select-shape-direction",
|
|
182
|
-
kbd: "cmd
|
|
182
|
+
kbd: "cmd+[[\u2191\u2192\u2193\u2190]]",
|
|
183
183
|
onSelect: () => {
|
|
184
184
|
}
|
|
185
185
|
}
|
|
@@ -189,7 +189,7 @@ function DefaultKeyboardShortcutsDialogContent() {
|
|
|
189
189
|
{
|
|
190
190
|
id: "a11y-select-next-shape-container",
|
|
191
191
|
label: "a11y.enter-leave-container",
|
|
192
|
-
kbd: "cmd+shift
|
|
192
|
+
kbd: "cmd+shift+[[\u2191\u2192]]",
|
|
193
193
|
onSelect: () => {
|
|
194
194
|
}
|
|
195
195
|
}
|
|
@@ -199,7 +199,7 @@ function DefaultKeyboardShortcutsDialogContent() {
|
|
|
199
199
|
{
|
|
200
200
|
id: "a11y-pan-camera",
|
|
201
201
|
label: "a11y.pan-camera",
|
|
202
|
-
kbd: "[[Space]]
|
|
202
|
+
kbd: "[[Space]]+[[\u2191\u2192\u2193\u2190]]",
|
|
203
203
|
onSelect: () => {
|
|
204
204
|
}
|
|
205
205
|
}
|
|
@@ -229,7 +229,7 @@ function DefaultKeyboardShortcutsDialogContent() {
|
|
|
229
229
|
{
|
|
230
230
|
id: "a11y-move-shape",
|
|
231
231
|
label: "a11y.move-shape",
|
|
232
|
-
kbd: "\u2191\u2192\u2193\u2190",
|
|
232
|
+
kbd: "[[\u2191\u2192\u2193\u2190]]",
|
|
233
233
|
onSelect: () => {
|
|
234
234
|
}
|
|
235
235
|
}
|
|
@@ -239,7 +239,7 @@ function DefaultKeyboardShortcutsDialogContent() {
|
|
|
239
239
|
{
|
|
240
240
|
id: "a11y-move-shape-faster",
|
|
241
241
|
label: "a11y.move-shape-faster",
|
|
242
|
-
kbd: "shift
|
|
242
|
+
kbd: "shift+[[\u2191\u2192\u2193\u2190]]",
|
|
243
243
|
onSelect: () => {
|
|
244
244
|
}
|
|
245
245
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../../../src/lib/ui/components/KeyboardShortcutsDialog/DefaultKeyboardShortcutsDialogContent.tsx"],
|
|
4
|
-
"sourcesContent": ["import { useShowCollaborationUi } from '../../hooks/useCollaborationStatus'\nimport { TldrawUiMenuActionItem } from '../primitives/menus/TldrawUiMenuActionItem'\nimport { TldrawUiMenuGroup } from '../primitives/menus/TldrawUiMenuGroup'\nimport { TldrawUiMenuItem } from '../primitives/menus/TldrawUiMenuItem'\nimport { TldrawUiMenuToolItem } from '../primitives/menus/TldrawUiMenuToolItem'\n\n/** @public @react */\nexport function DefaultKeyboardShortcutsDialogContent() {\n\tconst showCollaborationUi = useShowCollaborationUi()\n\treturn (\n\t\t<>\n\t\t\t<TldrawUiMenuGroup label=\"shortcuts-dialog.tools\" id=\"tools\">\n\t\t\t\t<TldrawUiMenuActionItem actionId=\"toggle-tool-lock\" />\n\t\t\t\t<TldrawUiMenuActionItem actionId=\"insert-media\" />\n\t\t\t\t<TldrawUiMenuToolItem toolId=\"select\" />\n\t\t\t\t<TldrawUiMenuToolItem toolId=\"draw\" />\n\t\t\t\t<TldrawUiMenuToolItem toolId=\"eraser\" />\n\t\t\t\t<TldrawUiMenuToolItem toolId=\"hand\" />\n\t\t\t\t<TldrawUiMenuToolItem toolId=\"rectangle\" />\n\t\t\t\t<TldrawUiMenuToolItem toolId=\"ellipse\" />\n\t\t\t\t<TldrawUiMenuToolItem toolId=\"arrow\" />\n\t\t\t\t<TldrawUiMenuToolItem toolId=\"line\" />\n\t\t\t\t<TldrawUiMenuToolItem toolId=\"text\" />\n\t\t\t\t<TldrawUiMenuToolItem toolId=\"frame\" />\n\t\t\t\t<TldrawUiMenuToolItem toolId=\"note\" />\n\t\t\t\t<TldrawUiMenuToolItem toolId=\"laser\" />\n\t\t\t\t<TldrawUiMenuItem\n\t\t\t\t\tid=\"pointer-down\"\n\t\t\t\t\tlabel=\"tool.pointer-down\"\n\t\t\t\t\tkbd=\",\"\n\t\t\t\t\tonSelect={() => {\n\t\t\t\t\t\t/* do nothing */\n\t\t\t\t\t}}\n\t\t\t\t/>\n\t\t\t</TldrawUiMenuGroup>\n\t\t\t<TldrawUiMenuGroup label=\"shortcuts-dialog.preferences\" id=\"preferences\">\n\t\t\t\t<TldrawUiMenuActionItem actionId=\"toggle-dark-mode\" />\n\t\t\t\t<TldrawUiMenuActionItem actionId=\"toggle-focus-mode\" />\n\t\t\t\t<TldrawUiMenuActionItem actionId=\"toggle-grid\" />\n\t\t\t</TldrawUiMenuGroup>\n\t\t\t<TldrawUiMenuGroup label=\"shortcuts-dialog.edit\" id=\"edit\">\n\t\t\t\t<TldrawUiMenuActionItem actionId=\"undo\" />\n\t\t\t\t<TldrawUiMenuActionItem actionId=\"redo\" />\n\t\t\t\t<TldrawUiMenuActionItem actionId=\"cut\" />\n\t\t\t\t<TldrawUiMenuActionItem actionId=\"copy\" />\n\t\t\t\t<TldrawUiMenuActionItem actionId=\"paste\" />\n\t\t\t\t<TldrawUiMenuActionItem actionId=\"select-all\" />\n\t\t\t\t<TldrawUiMenuActionItem actionId=\"delete\" />\n\t\t\t\t<TldrawUiMenuActionItem actionId=\"duplicate\" />\n\t\t\t</TldrawUiMenuGroup>\n\t\t\t<TldrawUiMenuGroup label=\"shortcuts-dialog.view\" id=\"view\">\n\t\t\t\t<TldrawUiMenuActionItem actionId=\"zoom-in\" />\n\t\t\t\t<TldrawUiMenuActionItem actionId=\"zoom-out\" />\n\t\t\t\t<TldrawUiMenuActionItem actionId=\"zoom-to-100\" />\n\t\t\t\t<TldrawUiMenuActionItem actionId=\"zoom-to-fit\" />\n\t\t\t\t<TldrawUiMenuActionItem actionId=\"zoom-to-selection\" />\n\t\t\t</TldrawUiMenuGroup>\n\t\t\t<TldrawUiMenuGroup label=\"shortcuts-dialog.transform\" id=\"transform\">\n\t\t\t\t<TldrawUiMenuActionItem actionId=\"bring-to-front\" />\n\t\t\t\t<TldrawUiMenuActionItem actionId=\"bring-forward\" />\n\t\t\t\t<TldrawUiMenuActionItem actionId=\"send-backward\" />\n\t\t\t\t<TldrawUiMenuActionItem actionId=\"send-to-back\" />\n\t\t\t\t<TldrawUiMenuActionItem actionId=\"group\" />\n\t\t\t\t<TldrawUiMenuActionItem actionId=\"ungroup\" />\n\t\t\t\t<TldrawUiMenuActionItem actionId=\"flip-horizontal\" />\n\t\t\t\t<TldrawUiMenuActionItem actionId=\"flip-vertical\" />\n\t\t\t\t<TldrawUiMenuActionItem actionId=\"align-top\" />\n\t\t\t\t<TldrawUiMenuActionItem actionId=\"align-center-vertical\" />\n\t\t\t\t<TldrawUiMenuActionItem actionId=\"align-bottom\" />\n\t\t\t\t<TldrawUiMenuActionItem actionId=\"align-left\" />\n\t\t\t\t<TldrawUiMenuActionItem actionId=\"align-center-horizontal\" />\n\t\t\t\t<TldrawUiMenuActionItem actionId=\"align-right\" />\n\t\t\t</TldrawUiMenuGroup>\n\t\t\t<TldrawUiMenuGroup label=\"shortcuts-dialog.text-formatting\" id=\"text\">\n\t\t\t\t<TldrawUiMenuItem\n\t\t\t\t\tid=\"text-bold\"\n\t\t\t\t\tlabel=\"tool.rich-text-bold\"\n\t\t\t\t\tkbd=\"cmd+b\"\n\t\t\t\t\tonSelect={() => {\n\t\t\t\t\t\t/* do nothing */\n\t\t\t\t\t}}\n\t\t\t\t/>\n\t\t\t\t<TldrawUiMenuItem\n\t\t\t\t\tid=\"text-italic\"\n\t\t\t\t\tlabel=\"tool.rich-text-italic\"\n\t\t\t\t\tkbd=\"cmd+i\"\n\t\t\t\t\tonSelect={() => {\n\t\t\t\t\t\t/* do nothing */\n\t\t\t\t\t}}\n\t\t\t\t/>\n\t\t\t\t<TldrawUiMenuItem\n\t\t\t\t\tid=\"text-code\"\n\t\t\t\t\tlabel=\"tool.rich-text-code\"\n\t\t\t\t\tkbd=\"cmd+e\"\n\t\t\t\t\tonSelect={() => {\n\t\t\t\t\t\t/* do nothing */\n\t\t\t\t\t}}\n\t\t\t\t/>\n\t\t\t\t<TldrawUiMenuItem\n\t\t\t\t\tid=\"text-highlight\"\n\t\t\t\t\tlabel=\"tool.rich-text-highlight\"\n\t\t\t\t\tkbd=\"cmd+shift+h\"\n\t\t\t\t\tonSelect={() => {\n\t\t\t\t\t\t/* do nothing */\n\t\t\t\t\t}}\n\t\t\t\t/>\n\t\t\t\t<TldrawUiMenuItem\n\t\t\t\t\tid=\"text-strikethrough\"\n\t\t\t\t\tlabel=\"tool.rich-text-strikethrough\"\n\t\t\t\t\tkbd=\"cmd+shift+s\"\n\t\t\t\t\tonSelect={() => {\n\t\t\t\t\t\t/* do nothing */\n\t\t\t\t\t}}\n\t\t\t\t/>\n\t\t\t\t<TldrawUiMenuItem\n\t\t\t\t\tid=\"text-link\"\n\t\t\t\t\tlabel=\"tool.rich-text-link\"\n\t\t\t\t\tkbd=\"cmd+shift+k\"\n\t\t\t\t\tonSelect={() => {\n\t\t\t\t\t\t/* do nothing */\n\t\t\t\t\t}}\n\t\t\t\t/>\n\t\t\t\t<TldrawUiMenuItem\n\t\t\t\t\tid=\"text-header\"\n\t\t\t\t\tlabel=\"tool.rich-text-header\"\n\t\t\t\t\tkbd=\"cmd+
|
|
4
|
+
"sourcesContent": ["import { useShowCollaborationUi } from '../../hooks/useCollaborationStatus'\nimport { TldrawUiMenuActionItem } from '../primitives/menus/TldrawUiMenuActionItem'\nimport { TldrawUiMenuGroup } from '../primitives/menus/TldrawUiMenuGroup'\nimport { TldrawUiMenuItem } from '../primitives/menus/TldrawUiMenuItem'\nimport { TldrawUiMenuToolItem } from '../primitives/menus/TldrawUiMenuToolItem'\n\n/** @public @react */\nexport function DefaultKeyboardShortcutsDialogContent() {\n\tconst showCollaborationUi = useShowCollaborationUi()\n\treturn (\n\t\t<>\n\t\t\t<TldrawUiMenuGroup label=\"shortcuts-dialog.tools\" id=\"tools\">\n\t\t\t\t<TldrawUiMenuActionItem actionId=\"toggle-tool-lock\" />\n\t\t\t\t<TldrawUiMenuActionItem actionId=\"insert-media\" />\n\t\t\t\t<TldrawUiMenuToolItem toolId=\"select\" />\n\t\t\t\t<TldrawUiMenuToolItem toolId=\"draw\" />\n\t\t\t\t<TldrawUiMenuToolItem toolId=\"eraser\" />\n\t\t\t\t<TldrawUiMenuToolItem toolId=\"hand\" />\n\t\t\t\t<TldrawUiMenuToolItem toolId=\"rectangle\" />\n\t\t\t\t<TldrawUiMenuToolItem toolId=\"ellipse\" />\n\t\t\t\t<TldrawUiMenuToolItem toolId=\"arrow\" />\n\t\t\t\t<TldrawUiMenuToolItem toolId=\"line\" />\n\t\t\t\t<TldrawUiMenuToolItem toolId=\"text\" />\n\t\t\t\t<TldrawUiMenuToolItem toolId=\"frame\" />\n\t\t\t\t<TldrawUiMenuToolItem toolId=\"note\" />\n\t\t\t\t<TldrawUiMenuToolItem toolId=\"laser\" />\n\t\t\t\t<TldrawUiMenuItem\n\t\t\t\t\tid=\"pointer-down\"\n\t\t\t\t\tlabel=\"tool.pointer-down\"\n\t\t\t\t\tkbd=\",\"\n\t\t\t\t\tonSelect={() => {\n\t\t\t\t\t\t/* do nothing */\n\t\t\t\t\t}}\n\t\t\t\t/>\n\t\t\t</TldrawUiMenuGroup>\n\t\t\t<TldrawUiMenuGroup label=\"shortcuts-dialog.preferences\" id=\"preferences\">\n\t\t\t\t<TldrawUiMenuActionItem actionId=\"toggle-dark-mode\" />\n\t\t\t\t<TldrawUiMenuActionItem actionId=\"toggle-focus-mode\" />\n\t\t\t\t<TldrawUiMenuActionItem actionId=\"toggle-grid\" />\n\t\t\t</TldrawUiMenuGroup>\n\t\t\t<TldrawUiMenuGroup label=\"shortcuts-dialog.edit\" id=\"edit\">\n\t\t\t\t<TldrawUiMenuActionItem actionId=\"undo\" />\n\t\t\t\t<TldrawUiMenuActionItem actionId=\"redo\" />\n\t\t\t\t<TldrawUiMenuActionItem actionId=\"cut\" />\n\t\t\t\t<TldrawUiMenuActionItem actionId=\"copy\" />\n\t\t\t\t<TldrawUiMenuActionItem actionId=\"paste\" />\n\t\t\t\t<TldrawUiMenuActionItem actionId=\"select-all\" />\n\t\t\t\t<TldrawUiMenuActionItem actionId=\"delete\" />\n\t\t\t\t<TldrawUiMenuActionItem actionId=\"duplicate\" />\n\t\t\t</TldrawUiMenuGroup>\n\t\t\t<TldrawUiMenuGroup label=\"shortcuts-dialog.view\" id=\"view\">\n\t\t\t\t<TldrawUiMenuActionItem actionId=\"zoom-in\" />\n\t\t\t\t<TldrawUiMenuActionItem actionId=\"zoom-out\" />\n\t\t\t\t<TldrawUiMenuActionItem actionId=\"zoom-to-100\" />\n\t\t\t\t<TldrawUiMenuActionItem actionId=\"zoom-to-fit\" />\n\t\t\t\t<TldrawUiMenuActionItem actionId=\"zoom-to-selection\" />\n\t\t\t</TldrawUiMenuGroup>\n\t\t\t<TldrawUiMenuGroup label=\"shortcuts-dialog.transform\" id=\"transform\">\n\t\t\t\t<TldrawUiMenuActionItem actionId=\"bring-to-front\" />\n\t\t\t\t<TldrawUiMenuActionItem actionId=\"bring-forward\" />\n\t\t\t\t<TldrawUiMenuActionItem actionId=\"send-backward\" />\n\t\t\t\t<TldrawUiMenuActionItem actionId=\"send-to-back\" />\n\t\t\t\t<TldrawUiMenuActionItem actionId=\"group\" />\n\t\t\t\t<TldrawUiMenuActionItem actionId=\"ungroup\" />\n\t\t\t\t<TldrawUiMenuActionItem actionId=\"flip-horizontal\" />\n\t\t\t\t<TldrawUiMenuActionItem actionId=\"flip-vertical\" />\n\t\t\t\t<TldrawUiMenuActionItem actionId=\"align-top\" />\n\t\t\t\t<TldrawUiMenuActionItem actionId=\"align-center-vertical\" />\n\t\t\t\t<TldrawUiMenuActionItem actionId=\"align-bottom\" />\n\t\t\t\t<TldrawUiMenuActionItem actionId=\"align-left\" />\n\t\t\t\t<TldrawUiMenuActionItem actionId=\"align-center-horizontal\" />\n\t\t\t\t<TldrawUiMenuActionItem actionId=\"align-right\" />\n\t\t\t</TldrawUiMenuGroup>\n\t\t\t<TldrawUiMenuGroup label=\"shortcuts-dialog.text-formatting\" id=\"text\">\n\t\t\t\t<TldrawUiMenuItem\n\t\t\t\t\tid=\"text-bold\"\n\t\t\t\t\tlabel=\"tool.rich-text-bold\"\n\t\t\t\t\tkbd=\"cmd+b\"\n\t\t\t\t\tonSelect={() => {\n\t\t\t\t\t\t/* do nothing */\n\t\t\t\t\t}}\n\t\t\t\t/>\n\t\t\t\t<TldrawUiMenuItem\n\t\t\t\t\tid=\"text-italic\"\n\t\t\t\t\tlabel=\"tool.rich-text-italic\"\n\t\t\t\t\tkbd=\"cmd+i\"\n\t\t\t\t\tonSelect={() => {\n\t\t\t\t\t\t/* do nothing */\n\t\t\t\t\t}}\n\t\t\t\t/>\n\t\t\t\t<TldrawUiMenuItem\n\t\t\t\t\tid=\"text-code\"\n\t\t\t\t\tlabel=\"tool.rich-text-code\"\n\t\t\t\t\tkbd=\"cmd+e\"\n\t\t\t\t\tonSelect={() => {\n\t\t\t\t\t\t/* do nothing */\n\t\t\t\t\t}}\n\t\t\t\t/>\n\t\t\t\t<TldrawUiMenuItem\n\t\t\t\t\tid=\"text-highlight\"\n\t\t\t\t\tlabel=\"tool.rich-text-highlight\"\n\t\t\t\t\tkbd=\"cmd+shift+h\"\n\t\t\t\t\tonSelect={() => {\n\t\t\t\t\t\t/* do nothing */\n\t\t\t\t\t}}\n\t\t\t\t/>\n\t\t\t\t<TldrawUiMenuItem\n\t\t\t\t\tid=\"text-strikethrough\"\n\t\t\t\t\tlabel=\"tool.rich-text-strikethrough\"\n\t\t\t\t\tkbd=\"cmd+shift+s\"\n\t\t\t\t\tonSelect={() => {\n\t\t\t\t\t\t/* do nothing */\n\t\t\t\t\t}}\n\t\t\t\t/>\n\t\t\t\t<TldrawUiMenuItem\n\t\t\t\t\tid=\"text-link\"\n\t\t\t\t\tlabel=\"tool.rich-text-link\"\n\t\t\t\t\tkbd=\"cmd+shift+k\"\n\t\t\t\t\tonSelect={() => {\n\t\t\t\t\t\t/* do nothing */\n\t\t\t\t\t}}\n\t\t\t\t/>\n\t\t\t\t<TldrawUiMenuItem\n\t\t\t\t\tid=\"text-header\"\n\t\t\t\t\tlabel=\"tool.rich-text-header\"\n\t\t\t\t\tkbd=\"cmd+alt+[[1-6]]\"\n\t\t\t\t\tonSelect={() => {\n\t\t\t\t\t\t/* do nothing */\n\t\t\t\t\t}}\n\t\t\t\t/>\n\t\t\t\t<TldrawUiMenuItem\n\t\t\t\t\tid=\"text-orderedList\"\n\t\t\t\t\tlabel=\"tool.rich-text-orderedList\"\n\t\t\t\t\tkbd=\"cmd+shift+7\"\n\t\t\t\t\tonSelect={() => {\n\t\t\t\t\t\t/* do nothing */\n\t\t\t\t\t}}\n\t\t\t\t/>\n\t\t\t\t<TldrawUiMenuItem\n\t\t\t\t\tid=\"text-bulletedlist\"\n\t\t\t\t\tlabel=\"tool.rich-text-bulletList\"\n\t\t\t\t\tkbd=\"cmd+shift+8\"\n\t\t\t\t\tonSelect={() => {\n\t\t\t\t\t\t/* do nothing */\n\t\t\t\t\t}}\n\t\t\t\t/>\n\t\t\t</TldrawUiMenuGroup>\n\t\t\t<TldrawUiMenuGroup label=\"shortcuts-dialog.a11y\" id=\"a11y\">\n\t\t\t\t<TldrawUiMenuItem\n\t\t\t\t\tid=\"a11y-select-next-shape\"\n\t\t\t\t\tlabel=\"a11y.select-shape\"\n\t\t\t\t\tkbd=\"[[Tab]]\"\n\t\t\t\t\tonSelect={() => {\n\t\t\t\t\t\t/* do nothing */\n\t\t\t\t\t}}\n\t\t\t\t/>\n\t\t\t\t<TldrawUiMenuItem\n\t\t\t\t\tid=\"a11y-select-next-shape-direction\"\n\t\t\t\t\tlabel=\"a11y.select-shape-direction\"\n\t\t\t\t\tkbd=\"cmd+[[\u2191\u2192\u2193\u2190]]\"\n\t\t\t\t\tonSelect={() => {\n\t\t\t\t\t\t/* do nothing */\n\t\t\t\t\t}}\n\t\t\t\t/>\n\t\t\t\t<TldrawUiMenuItem\n\t\t\t\t\tid=\"a11y-select-next-shape-container\"\n\t\t\t\t\tlabel=\"a11y.enter-leave-container\"\n\t\t\t\t\tkbd=\"cmd+shift+[[\u2191\u2192]]\"\n\t\t\t\t\tonSelect={() => {\n\t\t\t\t\t\t/* do nothing */\n\t\t\t\t\t}}\n\t\t\t\t/>\n\t\t\t\t<TldrawUiMenuItem\n\t\t\t\t\tid=\"a11y-pan-camera\"\n\t\t\t\t\tlabel=\"a11y.pan-camera\"\n\t\t\t\t\tkbd=\"[[Space]]+[[\u2191\u2192\u2193\u2190]]\"\n\t\t\t\t\tonSelect={() => {\n\t\t\t\t\t\t/* do nothing */\n\t\t\t\t\t}}\n\t\t\t\t/>\n\t\t\t\t<TldrawUiMenuItem\n\t\t\t\t\tid=\"adjust-shape-styles\"\n\t\t\t\t\tlabel=\"a11y.adjust-shape-styles\"\n\t\t\t\t\tkbd=\"cmd+[[Enter]]\"\n\t\t\t\t\tonSelect={() => {\n\t\t\t\t\t\t/* do nothing */\n\t\t\t\t\t}}\n\t\t\t\t/>\n\t\t\t\t<TldrawUiMenuItem\n\t\t\t\t\tid=\"open-context-menu\"\n\t\t\t\t\tlabel=\"a11y.open-context-menu\"\n\t\t\t\t\tkbd=\"cmd+shift+[[Enter]]\"\n\t\t\t\t\tonSelect={() => {\n\t\t\t\t\t\t/* do nothing */\n\t\t\t\t\t}}\n\t\t\t\t/>\n\t\t\t\t<TldrawUiMenuItem\n\t\t\t\t\tid=\"a11y-move-shape\"\n\t\t\t\t\tlabel=\"a11y.move-shape\"\n\t\t\t\t\tkbd=\"[[\u2191\u2192\u2193\u2190]]\"\n\t\t\t\t\tonSelect={() => {\n\t\t\t\t\t\t/* do nothing */\n\t\t\t\t\t}}\n\t\t\t\t/>\n\t\t\t\t<TldrawUiMenuItem\n\t\t\t\t\tid=\"a11y-move-shape-faster\"\n\t\t\t\t\tlabel=\"a11y.move-shape-faster\"\n\t\t\t\t\tkbd=\"shift+[[\u2191\u2192\u2193\u2190]]\"\n\t\t\t\t\tonSelect={() => {\n\t\t\t\t\t\t/* do nothing */\n\t\t\t\t\t}}\n\t\t\t\t/>\n\t\t\t\t<TldrawUiMenuItem\n\t\t\t\t\tid=\"a11y-rotate-shape-cw\"\n\t\t\t\t\tlabel=\"a11y.rotate-shape-cw\"\n\t\t\t\t\tkbd=\"shift+\uFE65\"\n\t\t\t\t\tonSelect={() => {\n\t\t\t\t\t\t/* do nothing */\n\t\t\t\t\t}}\n\t\t\t\t/>\n\t\t\t\t<TldrawUiMenuItem\n\t\t\t\t\tid=\"a11y-rotate-shape-cw-fine\"\n\t\t\t\t\tlabel=\"a11y.rotate-shape-cw-fine\"\n\t\t\t\t\tkbd=\"shift+alt+\uFE65\"\n\t\t\t\t\tonSelect={() => {\n\t\t\t\t\t\t/* do nothing */\n\t\t\t\t\t}}\n\t\t\t\t/>\n\t\t\t\t<TldrawUiMenuItem\n\t\t\t\t\tid=\"a11y-rotate-shape-ccw\"\n\t\t\t\t\tlabel=\"a11y.rotate-shape-ccw\"\n\t\t\t\t\tkbd=\"shift+\uFE64\"\n\t\t\t\t\tonSelect={() => {\n\t\t\t\t\t\t/* do nothing */\n\t\t\t\t\t}}\n\t\t\t\t/>\n\t\t\t\t<TldrawUiMenuItem\n\t\t\t\t\tid=\"a11y-rotate-shape-ccw-fine\"\n\t\t\t\t\tlabel=\"a11y.rotate-shape-ccw-fine\"\n\t\t\t\t\tkbd=\"shift+alt+\uFE64\"\n\t\t\t\t\tonSelect={() => {\n\t\t\t\t\t\t/* do nothing */\n\t\t\t\t\t}}\n\t\t\t\t/>\n\t\t\t\t<TldrawUiMenuActionItem actionId=\"enlarge-shapes\" />\n\t\t\t\t<TldrawUiMenuActionItem actionId=\"shrink-shapes\" />\n\t\t\t\t<TldrawUiMenuActionItem actionId=\"a11y-repeat-shape-announce\" />\n\t\t\t\t<TldrawUiMenuItem\n\t\t\t\t\tid=\"a11y-open-keyboard-shortcuts\"\n\t\t\t\t\tlabel=\"a11y.open-keyboard-shortcuts\"\n\t\t\t\t\tkbd=\"cmd+alt+/\"\n\t\t\t\t\tonSelect={() => {\n\t\t\t\t\t\t/* do nothing */\n\t\t\t\t\t}}\n\t\t\t\t/>\n\t\t\t</TldrawUiMenuGroup>\n\t\t\t{showCollaborationUi && (\n\t\t\t\t<TldrawUiMenuGroup label=\"shortcuts-dialog.collaboration\" id=\"collaboration\">\n\t\t\t\t\t<TldrawUiMenuActionItem actionId=\"open-cursor-chat\" />\n\t\t\t\t</TldrawUiMenuGroup>\n\t\t\t)}\n\t\t</>\n\t)\n}\n"],
|
|
5
5
|
"mappings": "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",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -54,7 +54,7 @@ function DropdownPickerInner({
|
|
|
54
54
|
]
|
|
55
55
|
}
|
|
56
56
|
) }),
|
|
57
|
-
/* @__PURE__ */ jsx(TldrawUiPopoverContent, { side: "left", align: "center", children: /* @__PURE__ */ jsx(TldrawUiToolbar, { orientation: "grid", label: labelStr, children: /* @__PURE__ */ jsx(TldrawUiMenuContextProvider, { type: "icons", sourceId: "style-panel", children: items.map((item) => {
|
|
57
|
+
/* @__PURE__ */ jsx(TldrawUiPopoverContent, { side: "left", align: "center", children: /* @__PURE__ */ jsx(TldrawUiToolbar, { orientation: items.length > 4 ? "grid" : "horizontal", label: labelStr, children: /* @__PURE__ */ jsx(TldrawUiMenuContextProvider, { type: "icons", sourceId: "style-panel", children: items.map((item) => {
|
|
58
58
|
return /* @__PURE__ */ jsx(
|
|
59
59
|
TldrawUiToolbarButton,
|
|
60
60
|
{
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../../../src/lib/ui/components/StylePanel/DropdownPicker.tsx"],
|
|
4
|
-
"sourcesContent": ["import { SharedStyle, StyleProp, tlmenus, useEditor } from '@tldraw/editor'\nimport * as React from 'react'\nimport { StyleValuesForUi } from '../../../styles'\nimport { TLUiTranslationKey } from '../../hooks/useTranslation/TLUiTranslationKey'\nimport { useTranslation } from '../../hooks/useTranslation/useTranslation'\nimport { TLUiIconType } from '../../icon-types'\nimport { TldrawUiButtonIcon } from '../primitives/Button/TldrawUiButtonIcon'\nimport { TldrawUiButtonLabel } from '../primitives/Button/TldrawUiButtonLabel'\nimport {\n\tTldrawUiPopover,\n\tTldrawUiPopoverContent,\n\tTldrawUiPopoverTrigger,\n} from '../primitives/TldrawUiPopover'\nimport { TldrawUiToolbar, TldrawUiToolbarButton } from '../primitives/TldrawUiToolbar'\nimport { TldrawUiMenuContextProvider } from '../primitives/menus/TldrawUiMenuContext'\n\ninterface DropdownPickerProps<T extends string> {\n\tid: string\n\tlabel?: TLUiTranslationKey | Exclude<string, TLUiTranslationKey>\n\tuiType: string\n\tstylePanelType: string\n\tstyle: StyleProp<T>\n\tvalue: SharedStyle<T>\n\titems: StyleValuesForUi<T>\n\ttype: 'icon' | 'tool' | 'menu'\n\tonValueChange(style: StyleProp<T>, value: T): void\n}\n\nfunction DropdownPickerInner<T extends string>({\n\tid,\n\tlabel,\n\tuiType,\n\tstylePanelType,\n\tstyle,\n\titems,\n\ttype,\n\tvalue,\n\tonValueChange,\n}: DropdownPickerProps<T>) {\n\tconst msg = useTranslation()\n\tconst editor = useEditor()\n\tconst [isOpen, setIsOpen] = React.useState(false)\n\n\tconst icon = React.useMemo(\n\t\t() => items.find((item) => value.type === 'shared' && item.value === value.value)?.icon,\n\t\t[items, value]\n\t)\n\n\tconst stylePanelName = msg(`style-panel.${stylePanelType}` as TLUiTranslationKey)\n\n\tconst titleStr =\n\t\tvalue.type === 'mixed'\n\t\t\t? msg('style-panel.mixed')\n\t\t\t: stylePanelName + ' \u2014 ' + msg(`${uiType}-style.${value.value}` as TLUiTranslationKey)\n\tconst labelStr = label ? msg(label) : ''\n\n\tconst popoverId = `style panel ${id}`\n\treturn (\n\t\t<TldrawUiPopover\n\t\t\tid={popoverId}\n\t\t\topen={isOpen}\n\t\t\tonOpenChange={setIsOpen}\n\t\t\tclassName=\"tlui-style-panel__dropdown-picker\"\n\t\t>\n\t\t\t<TldrawUiPopoverTrigger>\n\t\t\t\t<TldrawUiToolbarButton\n\t\t\t\t\ttype={type}\n\t\t\t\t\tdata-testid={`style.${uiType}`}\n\t\t\t\t\tdata-direction=\"left\"\n\t\t\t\t\ttitle={titleStr}\n\t\t\t\t>\n\t\t\t\t\t{labelStr && <TldrawUiButtonLabel>{labelStr}</TldrawUiButtonLabel>}\n\t\t\t\t\t<TldrawUiButtonIcon icon={(icon as TLUiIconType) ?? 'mixed'} />\n\t\t\t\t</TldrawUiToolbarButton>\n\t\t\t</TldrawUiPopoverTrigger>\n\t\t\t<TldrawUiPopoverContent side=\"left\" align=\"center\">\n\t\t\t\t<TldrawUiToolbar orientation
|
|
5
|
-
"mappings": "AAiEI,SAMc,KANd;AAjEJ,SAAiC,SAAS,iBAAiB;AAC3D,YAAY,WAAW;AAGvB,SAAS,sBAAsB;AAE/B,SAAS,0BAA0B;AACnC,SAAS,2BAA2B;AACpC;AAAA,EACC;AAAA,EACA;AAAA,EACA;AAAA,OACM;AACP,SAAS,iBAAiB,6BAA6B;AACvD,SAAS,mCAAmC;AAc5C,SAAS,oBAAsC;AAAA,EAC9C;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACD,GAA2B;AAC1B,QAAM,MAAM,eAAe;AAC3B,QAAM,SAAS,UAAU;AACzB,QAAM,CAAC,QAAQ,SAAS,IAAI,MAAM,SAAS,KAAK;AAEhD,QAAM,OAAO,MAAM;AAAA,IAClB,MAAM,MAAM,KAAK,CAAC,SAAS,MAAM,SAAS,YAAY,KAAK,UAAU,MAAM,KAAK,GAAG;AAAA,IACnF,CAAC,OAAO,KAAK;AAAA,EACd;AAEA,QAAM,iBAAiB,IAAI,eAAe,cAAc,EAAwB;AAEhF,QAAM,WACL,MAAM,SAAS,UACZ,IAAI,mBAAmB,IACvB,iBAAiB,aAAQ,IAAI,GAAG,MAAM,UAAU,MAAM,KAAK,EAAwB;AACvF,QAAM,WAAW,QAAQ,IAAI,KAAK,IAAI;AAEtC,QAAM,YAAY,eAAe,EAAE;AACnC,SACC;AAAA,IAAC;AAAA;AAAA,MACA,IAAI;AAAA,MACJ,MAAM;AAAA,MACN,cAAc;AAAA,MACd,WAAU;AAAA,MAEV;AAAA,4BAAC,0BACA;AAAA,UAAC;AAAA;AAAA,YACA;AAAA,YACA,eAAa,SAAS,MAAM;AAAA,YAC5B,kBAAe;AAAA,YACf,OAAO;AAAA,YAEN;AAAA,0BAAY,oBAAC,uBAAqB,oBAAS;AAAA,cAC5C,oBAAC,sBAAmB,MAAO,QAAyB,SAAS;AAAA;AAAA;AAAA,QAC9D,GACD;AAAA,QACA,oBAAC,0BAAuB,MAAK,QAAO,OAAM,UACzC,8BAAC,mBAAgB,
|
|
4
|
+
"sourcesContent": ["import { SharedStyle, StyleProp, tlmenus, useEditor } from '@tldraw/editor'\nimport * as React from 'react'\nimport { StyleValuesForUi } from '../../../styles'\nimport { TLUiTranslationKey } from '../../hooks/useTranslation/TLUiTranslationKey'\nimport { useTranslation } from '../../hooks/useTranslation/useTranslation'\nimport { TLUiIconType } from '../../icon-types'\nimport { TldrawUiButtonIcon } from '../primitives/Button/TldrawUiButtonIcon'\nimport { TldrawUiButtonLabel } from '../primitives/Button/TldrawUiButtonLabel'\nimport {\n\tTldrawUiPopover,\n\tTldrawUiPopoverContent,\n\tTldrawUiPopoverTrigger,\n} from '../primitives/TldrawUiPopover'\nimport { TldrawUiToolbar, TldrawUiToolbarButton } from '../primitives/TldrawUiToolbar'\nimport { TldrawUiMenuContextProvider } from '../primitives/menus/TldrawUiMenuContext'\n\ninterface DropdownPickerProps<T extends string> {\n\tid: string\n\tlabel?: TLUiTranslationKey | Exclude<string, TLUiTranslationKey>\n\tuiType: string\n\tstylePanelType: string\n\tstyle: StyleProp<T>\n\tvalue: SharedStyle<T>\n\titems: StyleValuesForUi<T>\n\ttype: 'icon' | 'tool' | 'menu'\n\tonValueChange(style: StyleProp<T>, value: T): void\n}\n\nfunction DropdownPickerInner<T extends string>({\n\tid,\n\tlabel,\n\tuiType,\n\tstylePanelType,\n\tstyle,\n\titems,\n\ttype,\n\tvalue,\n\tonValueChange,\n}: DropdownPickerProps<T>) {\n\tconst msg = useTranslation()\n\tconst editor = useEditor()\n\tconst [isOpen, setIsOpen] = React.useState(false)\n\n\tconst icon = React.useMemo(\n\t\t() => items.find((item) => value.type === 'shared' && item.value === value.value)?.icon,\n\t\t[items, value]\n\t)\n\n\tconst stylePanelName = msg(`style-panel.${stylePanelType}` as TLUiTranslationKey)\n\n\tconst titleStr =\n\t\tvalue.type === 'mixed'\n\t\t\t? msg('style-panel.mixed')\n\t\t\t: stylePanelName + ' \u2014 ' + msg(`${uiType}-style.${value.value}` as TLUiTranslationKey)\n\tconst labelStr = label ? msg(label) : ''\n\n\tconst popoverId = `style panel ${id}`\n\treturn (\n\t\t<TldrawUiPopover\n\t\t\tid={popoverId}\n\t\t\topen={isOpen}\n\t\t\tonOpenChange={setIsOpen}\n\t\t\tclassName=\"tlui-style-panel__dropdown-picker\"\n\t\t>\n\t\t\t<TldrawUiPopoverTrigger>\n\t\t\t\t<TldrawUiToolbarButton\n\t\t\t\t\ttype={type}\n\t\t\t\t\tdata-testid={`style.${uiType}`}\n\t\t\t\t\tdata-direction=\"left\"\n\t\t\t\t\ttitle={titleStr}\n\t\t\t\t>\n\t\t\t\t\t{labelStr && <TldrawUiButtonLabel>{labelStr}</TldrawUiButtonLabel>}\n\t\t\t\t\t<TldrawUiButtonIcon icon={(icon as TLUiIconType) ?? 'mixed'} />\n\t\t\t\t</TldrawUiToolbarButton>\n\t\t\t</TldrawUiPopoverTrigger>\n\t\t\t<TldrawUiPopoverContent side=\"left\" align=\"center\">\n\t\t\t\t<TldrawUiToolbar orientation={items.length > 4 ? 'grid' : 'horizontal'} label={labelStr}>\n\t\t\t\t\t<TldrawUiMenuContextProvider type=\"icons\" sourceId=\"style-panel\">\n\t\t\t\t\t\t{items.map((item) => {\n\t\t\t\t\t\t\treturn (\n\t\t\t\t\t\t\t\t<TldrawUiToolbarButton\n\t\t\t\t\t\t\t\t\tkey={item.value}\n\t\t\t\t\t\t\t\t\ttype=\"icon\"\n\t\t\t\t\t\t\t\t\tdata-testid={`style.${uiType}.${item.value}`}\n\t\t\t\t\t\t\t\t\ttitle={\n\t\t\t\t\t\t\t\t\t\tstylePanelName +\n\t\t\t\t\t\t\t\t\t\t' \u2014 ' +\n\t\t\t\t\t\t\t\t\t\tmsg(`${uiType}-style.${item.value}` as TLUiTranslationKey)\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\tisActive={icon === item.icon}\n\t\t\t\t\t\t\t\t\tonClick={() => {\n\t\t\t\t\t\t\t\t\t\teditor.markHistoryStoppingPoint('select style dropdown item')\n\t\t\t\t\t\t\t\t\t\tonValueChange(style, item.value)\n\t\t\t\t\t\t\t\t\t\ttlmenus.deleteOpenMenu(popoverId, editor.contextId)\n\t\t\t\t\t\t\t\t\t\tsetIsOpen(false)\n\t\t\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t<TldrawUiButtonIcon icon={item.icon} />\n\t\t\t\t\t\t\t\t</TldrawUiToolbarButton>\n\t\t\t\t\t\t\t)\n\t\t\t\t\t\t})}\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\n// need to export like this to get generics\nexport const DropdownPicker = React.memo(DropdownPickerInner) as typeof DropdownPickerInner\n"],
|
|
5
|
+
"mappings": "AAiEI,SAMc,KANd;AAjEJ,SAAiC,SAAS,iBAAiB;AAC3D,YAAY,WAAW;AAGvB,SAAS,sBAAsB;AAE/B,SAAS,0BAA0B;AACnC,SAAS,2BAA2B;AACpC;AAAA,EACC;AAAA,EACA;AAAA,EACA;AAAA,OACM;AACP,SAAS,iBAAiB,6BAA6B;AACvD,SAAS,mCAAmC;AAc5C,SAAS,oBAAsC;AAAA,EAC9C;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACD,GAA2B;AAC1B,QAAM,MAAM,eAAe;AAC3B,QAAM,SAAS,UAAU;AACzB,QAAM,CAAC,QAAQ,SAAS,IAAI,MAAM,SAAS,KAAK;AAEhD,QAAM,OAAO,MAAM;AAAA,IAClB,MAAM,MAAM,KAAK,CAAC,SAAS,MAAM,SAAS,YAAY,KAAK,UAAU,MAAM,KAAK,GAAG;AAAA,IACnF,CAAC,OAAO,KAAK;AAAA,EACd;AAEA,QAAM,iBAAiB,IAAI,eAAe,cAAc,EAAwB;AAEhF,QAAM,WACL,MAAM,SAAS,UACZ,IAAI,mBAAmB,IACvB,iBAAiB,aAAQ,IAAI,GAAG,MAAM,UAAU,MAAM,KAAK,EAAwB;AACvF,QAAM,WAAW,QAAQ,IAAI,KAAK,IAAI;AAEtC,QAAM,YAAY,eAAe,EAAE;AACnC,SACC;AAAA,IAAC;AAAA;AAAA,MACA,IAAI;AAAA,MACJ,MAAM;AAAA,MACN,cAAc;AAAA,MACd,WAAU;AAAA,MAEV;AAAA,4BAAC,0BACA;AAAA,UAAC;AAAA;AAAA,YACA;AAAA,YACA,eAAa,SAAS,MAAM;AAAA,YAC5B,kBAAe;AAAA,YACf,OAAO;AAAA,YAEN;AAAA,0BAAY,oBAAC,uBAAqB,oBAAS;AAAA,cAC5C,oBAAC,sBAAmB,MAAO,QAAyB,SAAS;AAAA;AAAA;AAAA,QAC9D,GACD;AAAA,QACA,oBAAC,0BAAuB,MAAK,QAAO,OAAM,UACzC,8BAAC,mBAAgB,aAAa,MAAM,SAAS,IAAI,SAAS,cAAc,OAAO,UAC9E,8BAAC,+BAA4B,MAAK,SAAQ,UAAS,eACjD,gBAAM,IAAI,CAAC,SAAS;AACpB,iBACC;AAAA,YAAC;AAAA;AAAA,cAEA,MAAK;AAAA,cACL,eAAa,SAAS,MAAM,IAAI,KAAK,KAAK;AAAA,cAC1C,OACC,iBACA,aACA,IAAI,GAAG,MAAM,UAAU,KAAK,KAAK,EAAwB;AAAA,cAE1D,UAAU,SAAS,KAAK;AAAA,cACxB,SAAS,MAAM;AACd,uBAAO,yBAAyB,4BAA4B;AAC5D,8BAAc,OAAO,KAAK,KAAK;AAC/B,wBAAQ,eAAe,WAAW,OAAO,SAAS;AAClD,0BAAU,KAAK;AAAA,cAChB;AAAA,cAEA,8BAAC,sBAAmB,MAAM,KAAK,MAAM;AAAA;AAAA,YAhBhC,KAAK;AAAA,UAiBX;AAAA,QAEF,CAAC,GACF,GACD,GACD;AAAA;AAAA;AAAA,EACD;AAEF;AAGO,MAAM,iBAAiB,MAAM,KAAK,mBAAmB;",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|