diff --git a/packages/client/components/RetroReflectPhase/PhaseItemEditor.tsx b/packages/client/components/RetroReflectPhase/PhaseItemEditor.tsx index f845732767d..6ab44e95a98 100644 --- a/packages/client/components/RetroReflectPhase/PhaseItemEditor.tsx +++ b/packages/client/components/RetroReflectPhase/PhaseItemEditor.tsx @@ -226,7 +226,7 @@ const PhaseItemEditor = (props: Props) => { >
({ }) export const useBlockResizer = ( width: number, - setWidth: (width: number) => void, updateAttributes: (attrs: Record) => void, - aspectRatioRef: RefObject + aspectRatioRef: RefObject, + maxWidth: number ) => { const dragRef = useRef(makeDrag()) const onMouseUp = useEventCallback((e: MouseEvent | TouchEvent) => { @@ -41,8 +41,8 @@ export const useBlockResizer = ( const sideCoefficient = drag.side === 'left' ? 1 : -1 const delta = (drag.lastX - clientX) * sideCoefficient drag.lastX = clientX - const nextWidth = Math.max(48, width + delta) - setWidth(nextWidth) + const nextWidth = Math.min(maxWidth, Math.max(48, width + delta)) + updateAttributes({width: nextWidth, height: Math.round(nextWidth / aspectRatioRef.current!)}) }) const onMouseDown = useEventCallback( diff --git a/packages/client/hooks/useTipTapReflectionEditor.ts b/packages/client/hooks/useTipTapReflectionEditor.ts index 9a493006083..7a644485328 100644 --- a/packages/client/hooks/useTipTapReflectionEditor.ts +++ b/packages/client/hooks/useTipTapReflectionEditor.ts @@ -70,7 +70,10 @@ export const useTipTapReflectionEditor = ( 'To-do list': false }), Focus, - ImageUpload.configure({editorWidth: ElementWidth.REFLECTION_CARD, editorHeight: 88}), + ImageUpload.configure({ + editorWidth: ElementWidth.REFLECTION_CARD - 16 * 2, + editorHeight: 88 + }), ImageBlock, LoomExtension, Placeholder.configure({ diff --git a/packages/client/tiptap/extensions/imageBlock/ImageBlock.ts b/packages/client/tiptap/extensions/imageBlock/ImageBlock.ts index e574f6ee54d..e0e59746c79 100644 --- a/packages/client/tiptap/extensions/imageBlock/ImageBlock.ts +++ b/packages/client/tiptap/extensions/imageBlock/ImageBlock.ts @@ -13,14 +13,14 @@ export const ImageBlock = ImageBlockBase.extend({ }) }, height: { - default: '100%', + default: undefined, parseHTML: (element) => element.getAttribute('height'), renderHTML: (attributes) => ({ height: attributes.height }) }, width: { - default: '100%', + default: undefined, parseHTML: (element) => element.getAttribute('width'), renderHTML: (attributes) => ({ width: attributes.width diff --git a/packages/client/tiptap/extensions/imageBlock/ImageBlockView.tsx b/packages/client/tiptap/extensions/imageBlock/ImageBlockView.tsx index 19295a9068c..014440f8d9e 100644 --- a/packages/client/tiptap/extensions/imageBlock/ImageBlockView.tsx +++ b/packages/client/tiptap/extensions/imageBlock/ImageBlockView.tsx @@ -1,5 +1,5 @@ import {NodeViewWrapper, type NodeViewProps} from '@tiptap/react' -import {useCallback, useEffect, useRef, useState} from 'react' +import {useCallback, useRef, useState} from 'react' import {useBlockResizer} from '../../../hooks/useBlockResizer' import {cn} from '../../../ui/cn' import {BlockResizer} from './BlockResizer' @@ -7,8 +7,8 @@ import {ImageBlockBubbleMenu} from './ImageBlockBubbleMenu' export const ImageBlockView = (props: NodeViewProps) => { const {editor, getPos, node, updateAttributes} = props const imageWrapperRef = useRef(null) - const {src, align} = node.attrs - + const {attrs} = node + const {src, align, height, width} = attrs const alignClass = align === 'left' ? 'justify-start' : align === 'right' ? 'justify-end' : 'justify-center' @@ -16,19 +16,20 @@ export const ImageBlockView = (props: NodeViewProps) => { editor.commands.setNodeSelection(getPos()) }, [getPos, editor.commands]) - const maxHeightRef = useRef(editor.storage.imageUpload.editorHeight) - const {current: maxHeight} = maxHeightRef - const aspectRatioRef = useRef(0) - const ref = useRef(null) - const [width, setWidth] = useState(node.attrs.width || 0) - const {onMouseDown} = useBlockResizer(width, setWidth, updateAttributes, aspectRatioRef) + const [maxHeight, setMaxHeight] = useState( + // if no height is provided (first load), make sure the image is no taller than the editor + height ? undefined : editor.storage.imageUpload.editorHeight + ) + + const aspectRatioRef = useRef(1) + const {onMouseDown} = useBlockResizer( + width, + updateAttributes, + aspectRatioRef, + editor.storage.imageUpload.editorWidth + ) const onMouseDownLeft = onMouseDown('left') const onMouseDownRight = onMouseDown('right') - useEffect(() => { - if (width === node.attrs.width) return - // the attributes will change if another instance (e.g. a reflection in an expanded stack) edits them - setWidth(node.attrs.width) - }, [node.attrs.width]) return (
@@ -38,15 +39,15 @@ export const ImageBlockView = (props: NodeViewProps) => { src={src} alt='' onClick={onClick} - style={{maxHeight, width: width === 0 ? undefined : width}} - ref={ref} + style={{maxHeight}} + width={width} + height={height} onLoad={(e) => { const img = e.target as HTMLImageElement - console.log('loaded', img.width, img.height, maxHeightRef.current) - maxHeightRef.current = undefined aspectRatioRef.current = img.width / img.height - if (img.width !== node.attrs.width) { - setWidth(img.width) + if (img.width !== width) { + // on initial load, once we grab the h/w/ar, remove the maxH constraint + setMaxHeight(undefined) updateAttributes({width: img.width, height: img.height}) } }}