Delete image button

Signed-off-by: marcin mikołajczak <git@mkljczk.pl>
This commit is contained in:
marcin mikołajczak 2023-07-21 23:04:27 +02:00
parent 856dd277f4
commit eb1feaa182
4 changed files with 35 additions and 15 deletions

View file

@ -152,7 +152,7 @@ const ComposeEditor = React.forwardRef<string, IComposeEditor>(({
contentEditable={
<div className='editor' ref={onRef} onFocus={onFocus} onPaste={handlePaste}>
<ContentEditable
className={clsx('mr-4 outline-none transition-[min-height] motion-reduce:transition-none', {
className={clsx('mr-4 pb-8 outline-none transition-[min-height] motion-reduce:transition-none', {
'min-h-[40px]': condensed,
'min-h-[100px]': !condensed,
})}

View file

@ -10,6 +10,7 @@
import { useLexicalComposerContext } from '@lexical/react/LexicalComposerContext';
import { useLexicalNodeSelection } from '@lexical/react/useLexicalNodeSelection';
import { mergeRegister } from '@lexical/utils';
import clsx from 'clsx';
import {
$getNodeByKey,
$getSelection,
@ -27,6 +28,8 @@ import {
import * as React from 'react';
import { Suspense, useCallback, useEffect, useRef, useState } from 'react';
import { IconButton } from 'soapbox/components/ui';
import { $isImageNode } from './image-node';
import type {
@ -94,15 +97,24 @@ export default function ImageComponent({
>(null);
const activeEditorRef = useRef<LexicalEditor | null>(null);
const deleteNode = useCallback(
() => {
editor.update(() => {
const node = $getNodeByKey(nodeKey);
if ($isImageNode(node)) {
node.remove();
}
});
},
[nodeKey],
);
const onDelete = useCallback(
(payload: KeyboardEvent) => {
if (isSelected && $isNodeSelection($getSelection())) {
const event: KeyboardEvent = payload;
event.preventDefault();
const node = $getNodeByKey(nodeKey);
if ($isImageNode(node)) {
node.remove();
}
deleteNode();
}
return false;
},
@ -235,12 +247,20 @@ export default function ImageComponent({
return (
<Suspense fallback={null}>
<>
<div draggable={draggable}>
<div className='relative' draggable={draggable}>
<IconButton
onClick={deleteNode}
src={require('@tabler/icons/x.svg')}
theme='dark'
className='absolute right-2 top-2 z-10 hover:scale-105 hover:bg-gray-900'
iconClassName='h-5 w-5'
/>
<LazyImage
className={
isFocused
? `focused ${$isNodeSelection(selection) ? 'draggable' : ''}`
: null
clsx('cursor-default', {
'select-none': isFocused,
'cursor-grab active:cursor-grabbing': isFocused && $isNodeSelection(selection),
})
}
src={src}
altText={altText}

View file

@ -29,14 +29,14 @@ interface ImagePayload {
src: string
}
function convertImageElement(domNode: Node): null | DOMConversionOutput {
const convertImageElement = (domNode: Node): null | DOMConversionOutput => {
if (domNode instanceof HTMLImageElement) {
const { alt: altText, src } = domNode;
const node = $createImageNode({ altText, src });
return { node };
}
return null;
}
};
type SerializedImageNode = Spread<
{
@ -146,11 +146,11 @@ class ImageNode extends DecoratorNode<JSX.Element> {
}
function $createImageNode({
const $createImageNode = ({
altText = '',
src,
key,
}: ImagePayload): ImageNode {
}: ImagePayload): ImageNode => {
return $applyNodeReplacement(
new ImageNode(
src,
@ -158,7 +158,7 @@ function $createImageNode({
key,
),
);
}
};
const $isImageNode = (
node: LexicalNode | null | undefined,

View file

@ -183,7 +183,7 @@ const BlockTypeFloatingToolbar = ({
const selection = $getSelection();
if ($isRangeSelection(selection) || DEPRECATED_$isGridSelection(selection)) {
const selectionNode = selection.anchor.getNode();
selectionNode.replace($createImageNode({ src }));
selectionNode.replace($createImageNode({ altText: '', src }));
}
});
};