Commit d232d707 by Яков

update

parent 79263e8a
{ {
"name": "react-ag-qeditor", "name": "react-ag-qeditor",
"version": "1.0.96", "version": "1.0.97",
"description": "WYSIWYG html editor", "description": "WYSIWYG html editor",
"author": "atma", "author": "atma",
"license": "MIT", "license": "MIT",
......
...@@ -11,6 +11,13 @@ const ResizableImageTemplate = ({ node, updateAttributes, editor, getPos, select ...@@ -11,6 +11,13 @@ const ResizableImageTemplate = ({ node, updateAttributes, editor, getPos, select
const wrapperRef = useRef(null); const wrapperRef = useRef(null);
const [showAlignMenu, setShowAlignMenu] = useState(false); const [showAlignMenu, setShowAlignMenu] = useState(false);
const isInitialized = useRef(false); const isInitialized = useRef(false);
const [isResizing, setIsResizing] = useState(false);
// Получаем ширину редактора для масштабирования изображений
const getEditorWidth = () => {
const editorElement = editor?.options?.element?.closest('.atma-editor-content');
return editorElement ? editorElement.clientWidth : null;
};
// Генерация уникального ID при создании // Генерация уникального ID при создании
useEffect(() => { useEffect(() => {
...@@ -36,8 +43,27 @@ const ResizableImageTemplate = ({ node, updateAttributes, editor, getPos, select ...@@ -36,8 +43,27 @@ const ResizableImageTemplate = ({ node, updateAttributes, editor, getPos, select
const initImageSize = () => { const initImageSize = () => {
try { try {
const width = node.attrs.width || imgRef.current.naturalWidth; const editorWidth = getEditorWidth();
const height = node.attrs.height || imgRef.current.naturalHeight; const naturalWidth = imgRef.current.naturalWidth;
const naturalHeight = imgRef.current.naturalHeight;
let width = node.attrs.width || naturalWidth;
let height = node.attrs.height || naturalHeight;
// Масштабируем изображение, если оно шире редактора
if (editorWidth && width > editorWidth) {
const ratio = editorWidth / width;
width = editorWidth;
height = Math.round(height * ratio);
}
// Проверяем минимальный размер
if (width < MIN_WIDTH) {
const ratio = MIN_WIDTH / width;
width = MIN_WIDTH;
height = Math.round(height * ratio);
}
if (width > 0 && height > 0) { if (width > 0 && height > 0) {
updateAttributes({ updateAttributes({
width: Math.round(width), width: Math.round(width),
...@@ -66,7 +92,7 @@ const ResizableImageTemplate = ({ node, updateAttributes, editor, getPos, select ...@@ -66,7 +92,7 @@ const ResizableImageTemplate = ({ node, updateAttributes, editor, getPos, select
e.preventDefault(); e.preventDefault();
e.stopPropagation(); e.stopPropagation();
// Явно устанавливаем выделение перед началом ресайза setIsResizing(true);
editor.commands.setNodeSelection(getPos()); editor.commands.setNodeSelection(getPos());
const startWidth = node.attrs.width || imgRef.current.naturalWidth; const startWidth = node.attrs.width || imgRef.current.naturalWidth;
...@@ -109,7 +135,7 @@ const ResizableImageTemplate = ({ node, updateAttributes, editor, getPos, select ...@@ -109,7 +135,7 @@ const ResizableImageTemplate = ({ node, updateAttributes, editor, getPos, select
const onMouseUp = () => { const onMouseUp = () => {
window.removeEventListener('mousemove', onMouseMove); window.removeEventListener('mousemove', onMouseMove);
window.removeEventListener('mouseup', onMouseUp); window.removeEventListener('mouseup', onMouseUp);
// Явно восстанавливаем выделение после ресайза setIsResizing(false);
editor.commands.setNodeSelection(getPos()); editor.commands.setNodeSelection(getPos());
editor.commands.focus(); editor.commands.focus();
}; };
...@@ -124,38 +150,62 @@ const ResizableImageTemplate = ({ node, updateAttributes, editor, getPos, select ...@@ -124,38 +150,62 @@ const ResizableImageTemplate = ({ node, updateAttributes, editor, getPos, select
editor.commands.focus(); editor.commands.focus();
}; };
const getWrapperStyle = () => ({ const getWrapperStyle = () => {
display: 'inline-block', const baseStyle = {
lineHeight: 0,
margin: '0.5rem 0',
position: 'relative',
outline: selected ? `1px dashed ${BORDER_COLOR}` : 'none',
verticalAlign: 'top',
...(node.attrs.align === 'left' && { float: 'left', marginRight: '1rem' }),
...(node.attrs.align === 'right' && { float: 'right', marginLeft: '1rem' }),
...(node.attrs.align === 'center' && {
display: 'block',
marginLeft: 'auto',
marginRight: 'auto',
textAlign: 'center'
}),
...(node.attrs.align === 'text' && {
display: 'inline-block', display: 'inline-block',
float: 'none', lineHeight: 0,
margin: '0 0.2rem', position: 'relative',
verticalAlign: 'middle' outline: (selected || isResizing) ? `1px dashed ${BORDER_COLOR}` : 'none',
}) verticalAlign: 'top',
}); margin: '0.5rem 0',
};
// Для выравнивания по центру
if (node.attrs.align === 'center') {
return {
...baseStyle,
display: 'block',
marginLeft: 'auto',
marginRight: 'auto',
width: node.attrs.width ? `${node.attrs.width}px` : 'fit-content',
maxWidth: '100%',
textAlign: 'center'
};
}
// Для других вариантов выравнивания
return {
...baseStyle,
...(node.attrs.align === 'left' && {
float: 'left',
marginRight: '1rem',
width: node.attrs.width ? `${node.attrs.width}px` : 'auto',
}),
...(node.attrs.align === 'right' && {
float: 'right',
marginLeft: '1rem',
width: node.attrs.width ? `${node.attrs.width}px` : 'auto',
}),
...(node.attrs.align === 'text' && {
display: 'inline-block',
float: 'none',
margin: '0 0.2rem',
verticalAlign: 'middle',
width: node.attrs.width ? `${node.attrs.width}px` : 'auto',
}),
};
};
const getImageStyle = () => ({ const getImageStyle = () => ({
width: node.attrs.width ? `${node.attrs.width}px` : 'auto', width: node.attrs.width ? `${node.attrs.width}px` : 'auto',
height: node.attrs.height ? `${node.attrs.height}px` : 'auto', height: 'auto', // Автоматическая высота для сохранения пропорций
maxWidth: '100%', maxWidth: '100%',
display: 'block', display: 'block',
cursor: 'default', cursor: 'default',
userSelect: 'none', userSelect: 'none',
margin: node.attrs.align === 'center' ? '0 auto' : '0', margin: node.attrs.align === 'center' ? '0 auto' : '0',
verticalAlign: node.attrs.align === 'text' ? 'middle' : 'top' verticalAlign: node.attrs.align === 'text' ? 'middle' : 'top',
objectFit: 'contain' // Сохраняем пропорции изображения
}); });
return ( return (
...@@ -173,12 +223,31 @@ const ResizableImageTemplate = ({ node, updateAttributes, editor, getPos, select ...@@ -173,12 +223,31 @@ const ResizableImageTemplate = ({ node, updateAttributes, editor, getPos, select
<img <img
{...node.attrs} {...node.attrs}
ref={imgRef} ref={imgRef}
draggable={true} // обязательно true для работы dragstart draggable={true}
style={getImageStyle()} style={getImageStyle()}
onLoad={() => { onLoad={() => {
if (imgRef.current && !isInitialized.current) { if (imgRef.current && !isInitialized.current) {
const width = imgRef.current.naturalWidth; const editorWidth = getEditorWidth();
const height = imgRef.current.naturalHeight; const naturalWidth = imgRef.current.naturalWidth;
const naturalHeight = imgRef.current.naturalHeight;
let width = naturalWidth;
let height = naturalHeight;
// Масштабируем изображение, если оно шире редактора
if (editorWidth && width > editorWidth) {
const ratio = editorWidth / width;
width = editorWidth;
height = Math.round(height * ratio);
}
// Проверяем минимальный размер
if (width < MIN_WIDTH) {
const ratio = MIN_WIDTH / width;
width = MIN_WIDTH;
height = Math.round(height * ratio);
}
updateAttributes({ updateAttributes({
width: Math.round(width), width: Math.round(width),
height: Math.round(height), height: Math.round(height),
...@@ -189,7 +258,7 @@ const ResizableImageTemplate = ({ node, updateAttributes, editor, getPos, select ...@@ -189,7 +258,7 @@ const ResizableImageTemplate = ({ node, updateAttributes, editor, getPos, select
}} }}
/> />
{selected && ( {(selected || isResizing) && (
<Fragment> <Fragment>
{['nw', 'ne', 'sw', 'se'].map(dir => ( {['nw', 'ne', 'sw', 'se'].map(dir => (
<div <div
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment