Delete image button
Signed-off-by: marcin mikołajczak <git@mkljczk.pl>
This commit is contained in:
parent
856dd277f4
commit
eb1feaa182
|
@ -152,7 +152,7 @@ const ComposeEditor = React.forwardRef<string, IComposeEditor>(({
|
||||||
contentEditable={
|
contentEditable={
|
||||||
<div className='editor' ref={onRef} onFocus={onFocus} onPaste={handlePaste}>
|
<div className='editor' ref={onRef} onFocus={onFocus} onPaste={handlePaste}>
|
||||||
<ContentEditable
|
<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-[40px]': condensed,
|
||||||
'min-h-[100px]': !condensed,
|
'min-h-[100px]': !condensed,
|
||||||
})}
|
})}
|
||||||
|
|
|
@ -10,6 +10,7 @@
|
||||||
import { useLexicalComposerContext } from '@lexical/react/LexicalComposerContext';
|
import { useLexicalComposerContext } from '@lexical/react/LexicalComposerContext';
|
||||||
import { useLexicalNodeSelection } from '@lexical/react/useLexicalNodeSelection';
|
import { useLexicalNodeSelection } from '@lexical/react/useLexicalNodeSelection';
|
||||||
import { mergeRegister } from '@lexical/utils';
|
import { mergeRegister } from '@lexical/utils';
|
||||||
|
import clsx from 'clsx';
|
||||||
import {
|
import {
|
||||||
$getNodeByKey,
|
$getNodeByKey,
|
||||||
$getSelection,
|
$getSelection,
|
||||||
|
@ -27,6 +28,8 @@ import {
|
||||||
import * as React from 'react';
|
import * as React from 'react';
|
||||||
import { Suspense, useCallback, useEffect, useRef, useState } from 'react';
|
import { Suspense, useCallback, useEffect, useRef, useState } from 'react';
|
||||||
|
|
||||||
|
import { IconButton } from 'soapbox/components/ui';
|
||||||
|
|
||||||
import { $isImageNode } from './image-node';
|
import { $isImageNode } from './image-node';
|
||||||
|
|
||||||
import type {
|
import type {
|
||||||
|
@ -94,15 +97,24 @@ export default function ImageComponent({
|
||||||
>(null);
|
>(null);
|
||||||
const activeEditorRef = useRef<LexicalEditor | null>(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(
|
const onDelete = useCallback(
|
||||||
(payload: KeyboardEvent) => {
|
(payload: KeyboardEvent) => {
|
||||||
if (isSelected && $isNodeSelection($getSelection())) {
|
if (isSelected && $isNodeSelection($getSelection())) {
|
||||||
const event: KeyboardEvent = payload;
|
const event: KeyboardEvent = payload;
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
const node = $getNodeByKey(nodeKey);
|
deleteNode();
|
||||||
if ($isImageNode(node)) {
|
|
||||||
node.remove();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
},
|
},
|
||||||
|
@ -235,12 +247,20 @@ export default function ImageComponent({
|
||||||
return (
|
return (
|
||||||
<Suspense fallback={null}>
|
<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
|
<LazyImage
|
||||||
className={
|
className={
|
||||||
isFocused
|
clsx('cursor-default', {
|
||||||
? `focused ${$isNodeSelection(selection) ? 'draggable' : ''}`
|
'select-none': isFocused,
|
||||||
: null
|
'cursor-grab active:cursor-grabbing': isFocused && $isNodeSelection(selection),
|
||||||
|
})
|
||||||
}
|
}
|
||||||
src={src}
|
src={src}
|
||||||
altText={altText}
|
altText={altText}
|
||||||
|
|
|
@ -29,14 +29,14 @@ interface ImagePayload {
|
||||||
src: string
|
src: string
|
||||||
}
|
}
|
||||||
|
|
||||||
function convertImageElement(domNode: Node): null | DOMConversionOutput {
|
const convertImageElement = (domNode: Node): null | DOMConversionOutput => {
|
||||||
if (domNode instanceof HTMLImageElement) {
|
if (domNode instanceof HTMLImageElement) {
|
||||||
const { alt: altText, src } = domNode;
|
const { alt: altText, src } = domNode;
|
||||||
const node = $createImageNode({ altText, src });
|
const node = $createImageNode({ altText, src });
|
||||||
return { node };
|
return { node };
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
};
|
||||||
|
|
||||||
type SerializedImageNode = Spread<
|
type SerializedImageNode = Spread<
|
||||||
{
|
{
|
||||||
|
@ -146,11 +146,11 @@ class ImageNode extends DecoratorNode<JSX.Element> {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function $createImageNode({
|
const $createImageNode = ({
|
||||||
altText = '',
|
altText = '',
|
||||||
src,
|
src,
|
||||||
key,
|
key,
|
||||||
}: ImagePayload): ImageNode {
|
}: ImagePayload): ImageNode => {
|
||||||
return $applyNodeReplacement(
|
return $applyNodeReplacement(
|
||||||
new ImageNode(
|
new ImageNode(
|
||||||
src,
|
src,
|
||||||
|
@ -158,7 +158,7 @@ function $createImageNode({
|
||||||
key,
|
key,
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
};
|
||||||
|
|
||||||
const $isImageNode = (
|
const $isImageNode = (
|
||||||
node: LexicalNode | null | undefined,
|
node: LexicalNode | null | undefined,
|
||||||
|
|
|
@ -183,7 +183,7 @@ const BlockTypeFloatingToolbar = ({
|
||||||
const selection = $getSelection();
|
const selection = $getSelection();
|
||||||
if ($isRangeSelection(selection) || DEPRECATED_$isGridSelection(selection)) {
|
if ($isRangeSelection(selection) || DEPRECATED_$isGridSelection(selection)) {
|
||||||
const selectionNode = selection.anchor.getNode();
|
const selectionNode = selection.anchor.getNode();
|
||||||
selectionNode.replace($createImageNode({ src }));
|
selectionNode.replace($createImageNode({ altText: '', src }));
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in New Issue