Skip to content

Commit 4180438

Browse files
committed
Fix image selection overlay sizing and dragging
1 parent b565a1b commit 4180438

1 file changed

Lines changed: 32 additions & 6 deletions

File tree

components/rich-text/ImageNode.tsx

Lines changed: 32 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,10 @@ const ImageComponent: React.FC<ImageComponentProps> = ({ src, altText, width, he
7373
const pointerStateRef = useRef<PointerState | null>(null);
7474
const [currentWidth, setCurrentWidth] = useState<number | 'inherit'>(width ?? 'inherit');
7575
const [currentHeight, setCurrentHeight] = useState<number | 'inherit'>(height ?? 'inherit');
76+
const [naturalSize, setNaturalSize] = useState({
77+
width: typeof width === 'number' ? width : 0,
78+
height: typeof height === 'number' ? height : 0,
79+
});
7680

7781
useEffect(() => {
7882
setCurrentWidth(width ?? 'inherit');
@@ -141,12 +145,15 @@ const ImageComponent: React.FC<ImageComponentProps> = ({ src, altText, width, he
141145
if (!isEditable || !event.dataTransfer || !imageRef.current) {
142146
return false;
143147
}
148+
clearSelection();
149+
setSelected(true);
144150
event.dataTransfer.setData('text/plain', '_lexical_image');
151+
event.dataTransfer.setData('application/x-lexical-dragged-nodes', JSON.stringify([nodeKey]));
145152
event.dataTransfer.setDragImage(imageRef.current, imageRef.current.clientWidth / 2, imageRef.current.clientHeight / 2);
146153
event.dataTransfer.effectAllowed = 'move';
147154
return true;
148155
},
149-
[isEditable],
156+
[clearSelection, isEditable, nodeKey, setSelected],
150157
);
151158

152159
const onDragEnd = useCallback(() => {
@@ -190,6 +197,20 @@ const ImageComponent: React.FC<ImageComponentProps> = ({ src, altText, width, he
190197
[currentHeight],
191198
);
192199

200+
const measuredWidth = useMemo(() => {
201+
if (typeof currentWidth === 'number') return currentWidth;
202+
if (imageRef.current?.width) return imageRef.current.width;
203+
if (naturalSize.width) return naturalSize.width;
204+
return undefined;
205+
}, [currentWidth, naturalSize.width]);
206+
207+
const measuredHeight = useMemo(() => {
208+
if (typeof currentHeight === 'number') return currentHeight;
209+
if (imageRef.current?.height) return imageRef.current.height;
210+
if (naturalSize.height) return naturalSize.height;
211+
return undefined;
212+
}, [currentHeight, naturalSize.height]);
213+
193214
const handlePointerMove = useCallback((event: PointerEvent) => {
194215
const state = pointerStateRef.current;
195216
if (!state) {
@@ -312,8 +333,12 @@ const ImageComponent: React.FC<ImageComponentProps> = ({ src, altText, width, he
312333

313334
return (
314335
<span
315-
className={`group relative my-3 block w-full max-w-full ${isSelected ? 'cursor-move' : ''}`}
336+
className={`group relative my-3 inline-block max-w-full align-top ${isSelected ? 'cursor-move' : ''}`}
316337
draggable={isEditable}
338+
style={{
339+
width: measuredWidth ? `${measuredWidth}px` : undefined,
340+
height: measuredHeight ? `${measuredHeight}px` : undefined,
341+
}}
317342
>
318343
<img
319344
ref={imageRef}
@@ -322,6 +347,9 @@ const ImageComponent: React.FC<ImageComponentProps> = ({ src, altText, width, he
322347
style={{ width: resolvedWidth, height: resolvedHeight, maxWidth: '100%', borderRadius: '0.5rem', objectFit: 'contain' }}
323348
className={`block border border-border-color/60 bg-secondary transition-shadow duration-150 ${showHandles ? 'ring-2 ring-primary shadow-lg' : 'shadow-sm'}`}
324349
draggable={isEditable}
350+
onLoad={(event) => {
351+
setNaturalSize({ width: event.currentTarget.naturalWidth, height: event.currentTarget.naturalHeight });
352+
}}
325353
onDragStart={(event) => {
326354
onDragStart(event.nativeEvent);
327355
}}
@@ -353,9 +381,7 @@ const ImageComponent: React.FC<ImageComponentProps> = ({ src, altText, width, he
353381
/>
354382
))}
355383
<div className="pointer-events-none absolute left-2 top-2 rounded bg-background/90 px-2 py-1 text-xs font-medium text-foreground shadow-sm">
356-
{`${Math.round(typeof currentWidth === 'number' ? currentWidth : imageRef.current?.width ?? 0)} × ${Math.round(
357-
typeof currentHeight === 'number' ? currentHeight : imageRef.current?.height ?? 0,
358-
)} px`}
384+
{`${Math.round(measuredWidth ?? 0)} × ${Math.round(measuredHeight ?? 0)} px`}
359385
</div>
360386
</div>
361387
) : null}
@@ -388,7 +414,7 @@ export class ImageNode extends DecoratorNode<JSX.Element> {
388414

389415
createDOM(): HTMLElement {
390416
const dom = document.createElement('span');
391-
dom.className = 'inline-block my-3 w-full';
417+
dom.className = 'inline-block my-3 max-w-full';
392418
dom.style.maxWidth = '100%';
393419
return dom;
394420
}

0 commit comments

Comments
 (0)