@qwanyx/ai-editor 1.3.6 → 1.3.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
|
@@ -19,6 +19,9 @@ export interface ImagePayload {
|
|
|
19
19
|
captionVerticalAlign?: CaptionVerticalAlignType;
|
|
20
20
|
captionSize?: CaptionSizeType;
|
|
21
21
|
showFileName?: boolean;
|
|
22
|
+
borderWidth?: number;
|
|
23
|
+
borderColor?: string;
|
|
24
|
+
borderRadius?: number;
|
|
22
25
|
}
|
|
23
26
|
export type SerializedImageNode = Spread<{
|
|
24
27
|
src: string;
|
|
@@ -34,6 +37,9 @@ export type SerializedImageNode = Spread<{
|
|
|
34
37
|
captionVerticalAlign?: CaptionVerticalAlignType;
|
|
35
38
|
captionSize?: CaptionSizeType;
|
|
36
39
|
showFileName?: boolean;
|
|
40
|
+
borderWidth?: number;
|
|
41
|
+
borderColor?: string;
|
|
42
|
+
borderRadius?: number;
|
|
37
43
|
}, SerializedLexicalNode>;
|
|
38
44
|
export declare class ImageNode extends DecoratorNode<React.ReactElement> {
|
|
39
45
|
__src: string;
|
|
@@ -49,9 +55,12 @@ export declare class ImageNode extends DecoratorNode<React.ReactElement> {
|
|
|
49
55
|
__captionVerticalAlign?: CaptionVerticalAlignType;
|
|
50
56
|
__captionSize?: CaptionSizeType;
|
|
51
57
|
__showFileName?: boolean;
|
|
58
|
+
__borderWidth?: number;
|
|
59
|
+
__borderColor?: string;
|
|
60
|
+
__borderRadius?: number;
|
|
52
61
|
static getType(): string;
|
|
53
62
|
static clone(node: ImageNode): ImageNode;
|
|
54
|
-
constructor(src: string, altText?: string, width?: number, height?: number, copyright?: string, photographer?: string, comment?: string, float?: ImageFloatType, captionPosition?: CaptionPositionType, captionAlign?: CaptionAlignType, captionVerticalAlign?: CaptionVerticalAlignType, captionSize?: CaptionSizeType, showFileName?: boolean, key?: NodeKey);
|
|
63
|
+
constructor(src: string, altText?: string, width?: number, height?: number, copyright?: string, photographer?: string, comment?: string, float?: ImageFloatType, captionPosition?: CaptionPositionType, captionAlign?: CaptionAlignType, captionVerticalAlign?: CaptionVerticalAlignType, captionSize?: CaptionSizeType, showFileName?: boolean, borderWidth?: number, borderColor?: string, borderRadius?: number, key?: NodeKey);
|
|
55
64
|
createDOM(): HTMLElement;
|
|
56
65
|
updateDOM(): false;
|
|
57
66
|
setSrc(src: string): void;
|
|
@@ -80,6 +89,12 @@ export declare class ImageNode extends DecoratorNode<React.ReactElement> {
|
|
|
80
89
|
getCaptionSize(): CaptionSizeType | undefined;
|
|
81
90
|
setShowFileName(showFileName: boolean | undefined): void;
|
|
82
91
|
getShowFileName(): boolean | undefined;
|
|
92
|
+
setBorderWidth(borderWidth: number | undefined): void;
|
|
93
|
+
getBorderWidth(): number | undefined;
|
|
94
|
+
setBorderColor(borderColor: string | undefined): void;
|
|
95
|
+
getBorderColor(): string | undefined;
|
|
96
|
+
setBorderRadius(borderRadius: number | undefined): void;
|
|
97
|
+
getBorderRadius(): number | undefined;
|
|
83
98
|
static importJSON(serializedNode: SerializedImageNode): ImageNode;
|
|
84
99
|
exportJSON(): SerializedImageNode;
|
|
85
100
|
exportDOM(): DOMExportOutput;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ImageNode.d.ts","sourceRoot":"","sources":["../../src/nodes/ImageNode.tsx"],"names":[],"mappings":"AAEA,OAAO,EACL,aAAa,EACb,gBAAgB,EAChB,eAAe,EACf,WAAW,EACX,OAAO,EACP,qBAAqB,EACrB,MAAM,
|
|
1
|
+
{"version":3,"file":"ImageNode.d.ts","sourceRoot":"","sources":["../../src/nodes/ImageNode.tsx"],"names":[],"mappings":"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"}
|
package/dist/nodes/ImageNode.js
CHANGED
|
@@ -7,6 +7,8 @@ exports.$isImageNode = $isImageNode;
|
|
|
7
7
|
const jsx_runtime_1 = require("react/jsx-runtime");
|
|
8
8
|
const lexical_1 = require("lexical");
|
|
9
9
|
const LexicalComposerContext_1 = require("@lexical/react/LexicalComposerContext");
|
|
10
|
+
const useLexicalNodeSelection_1 = require("@lexical/react/useLexicalNodeSelection");
|
|
11
|
+
const utils_1 = require("@lexical/utils");
|
|
10
12
|
const react_1 = require("react");
|
|
11
13
|
const EditorModeContext_1 = require("../context/EditorModeContext");
|
|
12
14
|
// Font sizes: small=10px, medium=16px, large=24px (alt text gets +2px)
|
|
@@ -15,12 +17,12 @@ const CAPTION_FONT_SIZES = {
|
|
|
15
17
|
medium: { base: 16, alt: 18 },
|
|
16
18
|
large: { base: 24, alt: 26 }
|
|
17
19
|
};
|
|
18
|
-
function ImageComponent({ src, altText, width, height, copyright: initialCopyright, photographer: initialPhotographer, comment: initialComment, float: initialFloat, captionPosition: initialCaptionPosition, captionAlign: initialCaptionAlign, captionVerticalAlign: initialCaptionVerticalAlign, captionSize: initialCaptionSize, showFileName: initialShowFileName, nodeKey, }) {
|
|
20
|
+
function ImageComponent({ src, altText, width, height, copyright: initialCopyright, photographer: initialPhotographer, comment: initialComment, float: initialFloat, captionPosition: initialCaptionPosition, captionAlign: initialCaptionAlign, captionVerticalAlign: initialCaptionVerticalAlign, captionSize: initialCaptionSize, showFileName: initialShowFileName, borderWidth: initialBorderWidth, borderColor: initialBorderColor, borderRadius: initialBorderRadius, nodeKey, }) {
|
|
19
21
|
const [editor] = (0, LexicalComposerContext_1.useLexicalComposerContext)();
|
|
20
22
|
const { isViewer } = (0, EditorModeContext_1.useEditorMode)();
|
|
21
23
|
const containerRef = (0, react_1.useRef)(null);
|
|
22
24
|
const imageRef = (0, react_1.useRef)(null);
|
|
23
|
-
const [isSelected,
|
|
25
|
+
const [isSelected, setSelected, clearSelection] = (0, useLexicalNodeSelection_1.useLexicalNodeSelection)(nodeKey);
|
|
24
26
|
const [isHovered, setIsHovered] = (0, react_1.useState)(false);
|
|
25
27
|
const [isResizing, setIsResizing] = (0, react_1.useState)(false);
|
|
26
28
|
const [showMetadataEditor, setShowMetadataEditor] = (0, react_1.useState)(false);
|
|
@@ -36,6 +38,9 @@ function ImageComponent({ src, altText, width, height, copyright: initialCopyrig
|
|
|
36
38
|
const [displayCaptionVerticalAlign, setDisplayCaptionVerticalAlign] = (0, react_1.useState)(initialCaptionVerticalAlign || 'middle');
|
|
37
39
|
const [displayCaptionSize, setDisplayCaptionSize] = (0, react_1.useState)(initialCaptionSize || 'small');
|
|
38
40
|
const [displayShowFileName, setDisplayShowFileName] = (0, react_1.useState)(initialShowFileName || false);
|
|
41
|
+
const [displayBorderWidth, setDisplayBorderWidth] = (0, react_1.useState)(initialBorderWidth || 0);
|
|
42
|
+
const [displayBorderColor, setDisplayBorderColor] = (0, react_1.useState)(initialBorderColor || '#000000');
|
|
43
|
+
const [displayBorderRadius, setDisplayBorderRadius] = (0, react_1.useState)(initialBorderRadius || 0);
|
|
39
44
|
// Edit form state
|
|
40
45
|
const [editSrc, setEditSrc] = (0, react_1.useState)('');
|
|
41
46
|
const [editAltText, setEditAltText] = (0, react_1.useState)('');
|
|
@@ -48,6 +53,9 @@ function ImageComponent({ src, altText, width, height, copyright: initialCopyrig
|
|
|
48
53
|
const [editCaptionVerticalAlign, setEditCaptionVerticalAlign] = (0, react_1.useState)('middle');
|
|
49
54
|
const [editCaptionSize, setEditCaptionSize] = (0, react_1.useState)('small');
|
|
50
55
|
const [editShowFileName, setEditShowFileName] = (0, react_1.useState)(false);
|
|
56
|
+
const [editBorderWidth, setEditBorderWidth] = (0, react_1.useState)(0);
|
|
57
|
+
const [editBorderColor, setEditBorderColor] = (0, react_1.useState)('#000000');
|
|
58
|
+
const [editBorderRadius, setEditBorderRadius] = (0, react_1.useState)(0);
|
|
51
59
|
// Extract file name from URL
|
|
52
60
|
const getFileName = (url) => {
|
|
53
61
|
try {
|
|
@@ -65,52 +73,42 @@ function ImageComponent({ src, altText, width, height, copyright: initialCopyrig
|
|
|
65
73
|
};
|
|
66
74
|
const startX = (0, react_1.useRef)(0);
|
|
67
75
|
const startWidth = (0, react_1.useRef)(0);
|
|
68
|
-
//
|
|
76
|
+
// Delete handler for when image is selected
|
|
77
|
+
const onDelete = (0, react_1.useCallback)((payload) => {
|
|
78
|
+
if (isSelected && (0, lexical_1.$isNodeSelection)((0, lexical_1.$getSelection)())) {
|
|
79
|
+
const event = payload;
|
|
80
|
+
event.preventDefault();
|
|
81
|
+
const node = (0, lexical_1.$getNodeByKey)(nodeKey);
|
|
82
|
+
if ($isImageNode(node)) {
|
|
83
|
+
node.remove();
|
|
84
|
+
}
|
|
85
|
+
return true;
|
|
86
|
+
}
|
|
87
|
+
return false;
|
|
88
|
+
}, [isSelected, nodeKey]);
|
|
89
|
+
// Register commands for selection and deletion
|
|
90
|
+
(0, react_1.useEffect)(() => {
|
|
91
|
+
if (isViewer)
|
|
92
|
+
return;
|
|
93
|
+
return (0, utils_1.mergeRegister)(editor.registerCommand(lexical_1.CLICK_COMMAND, (payload) => {
|
|
94
|
+
const event = payload;
|
|
95
|
+
if (containerRef.current?.contains(event.target)) {
|
|
96
|
+
if (!event.shiftKey) {
|
|
97
|
+
clearSelection();
|
|
98
|
+
}
|
|
99
|
+
setSelected(true);
|
|
100
|
+
return true;
|
|
101
|
+
}
|
|
102
|
+
return false;
|
|
103
|
+
}, lexical_1.COMMAND_PRIORITY_LOW), editor.registerCommand(lexical_1.KEY_DELETE_COMMAND, onDelete, lexical_1.COMMAND_PRIORITY_LOW), editor.registerCommand(lexical_1.KEY_BACKSPACE_COMMAND, onDelete, lexical_1.COMMAND_PRIORITY_LOW));
|
|
104
|
+
}, [editor, isViewer, clearSelection, setSelected, onDelete]);
|
|
105
|
+
// Handle click in viewer mode (fullscreen)
|
|
69
106
|
const handleClick = (0, react_1.useCallback)((e) => {
|
|
70
|
-
e.stopPropagation();
|
|
71
107
|
if (isViewer) {
|
|
72
|
-
|
|
108
|
+
e.stopPropagation();
|
|
73
109
|
setShowFullscreen(true);
|
|
74
110
|
}
|
|
75
|
-
else {
|
|
76
|
-
setIsSelected(true);
|
|
77
|
-
}
|
|
78
111
|
}, [isViewer]);
|
|
79
|
-
// Click outside to deselect
|
|
80
|
-
(0, react_1.useEffect)(() => {
|
|
81
|
-
const handleClickOutside = (e) => {
|
|
82
|
-
if (containerRef.current && !containerRef.current.contains(e.target)) {
|
|
83
|
-
setIsSelected(false);
|
|
84
|
-
}
|
|
85
|
-
};
|
|
86
|
-
document.addEventListener('mousedown', handleClickOutside);
|
|
87
|
-
return () => document.removeEventListener('mousedown', handleClickOutside);
|
|
88
|
-
}, []);
|
|
89
|
-
// Handle Delete/Backspace to remove image when selected
|
|
90
|
-
(0, react_1.useEffect)(() => {
|
|
91
|
-
if (!isSelected || isViewer)
|
|
92
|
-
return;
|
|
93
|
-
const handleKeyDown = (e) => {
|
|
94
|
-
// Don't delete if modal is open or if user is typing in an input
|
|
95
|
-
if (showMetadataEditor)
|
|
96
|
-
return;
|
|
97
|
-
const target = e.target;
|
|
98
|
-
if (target.tagName === 'INPUT' || target.tagName === 'TEXTAREA')
|
|
99
|
-
return;
|
|
100
|
-
if (e.key === 'Delete' || e.key === 'Backspace') {
|
|
101
|
-
e.preventDefault();
|
|
102
|
-
e.stopPropagation();
|
|
103
|
-
editor.update(() => {
|
|
104
|
-
const node = (0, lexical_1.$getNodeByKey)(nodeKey);
|
|
105
|
-
if (node) {
|
|
106
|
-
node.remove();
|
|
107
|
-
}
|
|
108
|
-
});
|
|
109
|
-
}
|
|
110
|
-
};
|
|
111
|
-
document.addEventListener('keydown', handleKeyDown);
|
|
112
|
-
return () => document.removeEventListener('keydown', handleKeyDown);
|
|
113
|
-
}, [isSelected, isViewer, showMetadataEditor, editor, nodeKey]);
|
|
114
112
|
// Handle resize start
|
|
115
113
|
const handleResizeStart = (0, react_1.useCallback)((e) => {
|
|
116
114
|
e.preventDefault();
|
|
@@ -162,6 +160,9 @@ function ImageComponent({ src, altText, width, height, copyright: initialCopyrig
|
|
|
162
160
|
setEditCaptionVerticalAlign(node.getCaptionVerticalAlign() || 'middle');
|
|
163
161
|
setEditCaptionSize(node.getCaptionSize() || 'small');
|
|
164
162
|
setEditShowFileName(node.getShowFileName() || false);
|
|
163
|
+
setEditBorderWidth(node.getBorderWidth() || 0);
|
|
164
|
+
setEditBorderColor(node.getBorderColor() || '#000000');
|
|
165
|
+
setEditBorderRadius(node.getBorderRadius() || 0);
|
|
165
166
|
}
|
|
166
167
|
});
|
|
167
168
|
setShowMetadataEditor(true);
|
|
@@ -202,6 +203,9 @@ function ImageComponent({ src, altText, width, height, copyright: initialCopyrig
|
|
|
202
203
|
node.setCaptionVerticalAlign(editCaptionVerticalAlign);
|
|
203
204
|
node.setCaptionSize(editCaptionSize);
|
|
204
205
|
node.setShowFileName(editShowFileName);
|
|
206
|
+
node.setBorderWidth(editBorderWidth || undefined);
|
|
207
|
+
node.setBorderColor(editBorderColor || undefined);
|
|
208
|
+
node.setBorderRadius(editBorderRadius || undefined);
|
|
205
209
|
}
|
|
206
210
|
});
|
|
207
211
|
// Update display state
|
|
@@ -214,8 +218,11 @@ function ImageComponent({ src, altText, width, height, copyright: initialCopyrig
|
|
|
214
218
|
setDisplayCaptionVerticalAlign(editCaptionVerticalAlign);
|
|
215
219
|
setDisplayCaptionSize(editCaptionSize);
|
|
216
220
|
setDisplayShowFileName(editShowFileName);
|
|
221
|
+
setDisplayBorderWidth(editBorderWidth);
|
|
222
|
+
setDisplayBorderColor(editBorderColor);
|
|
223
|
+
setDisplayBorderRadius(editBorderRadius);
|
|
217
224
|
setShowMetadataEditor(false);
|
|
218
|
-
}, [editor, nodeKey, editSrc, editAltText, editCopyright, editPhotographer, editComment, editFloat, editCaptionPosition, editCaptionAlign, editCaptionVerticalAlign, editCaptionSize, editShowFileName]);
|
|
225
|
+
}, [editor, nodeKey, editSrc, editAltText, editCopyright, editPhotographer, editComment, editFloat, editCaptionPosition, editCaptionAlign, editCaptionVerticalAlign, editCaptionSize, editShowFileName, editBorderWidth, editBorderColor, editBorderRadius]);
|
|
219
226
|
// Get float styles
|
|
220
227
|
const getFloatStyles = () => {
|
|
221
228
|
if (displayFloat === 'left') {
|
|
@@ -258,19 +265,21 @@ function ImageComponent({ src, altText, width, height, copyright: initialCopyrig
|
|
|
258
265
|
default: return 'center';
|
|
259
266
|
}
|
|
260
267
|
};
|
|
261
|
-
return ((0, jsx_runtime_1.jsxs)("span", { ref: containerRef, style: {
|
|
268
|
+
return ((0, jsx_runtime_1.jsxs)("span", { ref: containerRef, tabIndex: -1, style: {
|
|
262
269
|
display: displayCaptionPosition === 'beside' ? 'inline-flex' : 'inline-block',
|
|
263
270
|
flexDirection: displayCaptionPosition === 'beside' && displayCaptionAlign === 'right' ? 'row-reverse' : 'row',
|
|
264
271
|
gap: displayCaptionPosition === 'beside' ? '12px' : undefined,
|
|
265
272
|
alignItems: displayCaptionPosition === 'beside' ? getVerticalAlign() : undefined,
|
|
266
273
|
position: 'relative',
|
|
274
|
+
outline: 'none',
|
|
267
275
|
...getFloatStyles(),
|
|
268
276
|
}, onClick: handleClick, onMouseEnter: () => setIsHovered(true), onMouseLeave: () => setIsHovered(false), children: [(0, jsx_runtime_1.jsxs)("div", { style: { position: 'relative', flexShrink: 0 }, children: [(0, jsx_runtime_1.jsx)("img", { ref: imageRef, src: src, alt: altText, title: displayComment || undefined, style: {
|
|
269
277
|
maxWidth: '100%',
|
|
270
278
|
height: 'auto',
|
|
271
279
|
width: currentWidth ? `${currentWidth}px` : 'auto',
|
|
272
280
|
display: 'block',
|
|
273
|
-
borderRadius: '4px',
|
|
281
|
+
borderRadius: displayBorderRadius ? `${displayBorderRadius}px` : '4px',
|
|
282
|
+
border: displayBorderWidth ? `${displayBorderWidth}px solid ${displayBorderColor}` : 'none',
|
|
274
283
|
outline: !isViewer && isSelected ? '2px solid #3b82f6' : 'none',
|
|
275
284
|
cursor: 'pointer',
|
|
276
285
|
}, draggable: false }), displayCaptionPosition === 'overlay' && hasMetadata && ((0, jsx_runtime_1.jsx)("div", { style: {
|
|
@@ -631,7 +640,28 @@ function ImageComponent({ src, altText, width, height, copyright: initialCopyrig
|
|
|
631
640
|
width: '18px',
|
|
632
641
|
height: '18px',
|
|
633
642
|
cursor: 'pointer',
|
|
634
|
-
} }), (0, jsx_runtime_1.jsx)("span", { className: "material-icons", style: { fontSize: '18px', color: '#6b7280' }, children: "insert_drive_file" }), "Afficher le nom du fichier"] }) })), (0, jsx_runtime_1.jsxs)("div", { style: { display: 'flex', gap: '
|
|
643
|
+
} }), (0, jsx_runtime_1.jsx)("span", { className: "material-icons", style: { fontSize: '18px', color: '#6b7280' }, children: "insert_drive_file" }), "Afficher le nom du fichier"] }) })), (0, jsx_runtime_1.jsx)("hr", { style: { border: 'none', borderTop: '1px solid #e5e7eb', margin: '20px 0' } }), (0, jsx_runtime_1.jsxs)("div", { style: { marginBottom: '16px' }, children: [(0, jsx_runtime_1.jsxs)("label", { style: { display: 'flex', alignItems: 'center', gap: '8px', marginBottom: '6px', fontSize: '14px', fontWeight: 500, color: '#374151' }, children: [(0, jsx_runtime_1.jsx)("span", { className: "material-icons", style: { fontSize: '18px', color: '#6b7280' }, children: "crop_square" }), "Bordure"] }), (0, jsx_runtime_1.jsxs)("div", { style: { display: 'flex', gap: '12px', alignItems: 'center' }, children: [(0, jsx_runtime_1.jsxs)("div", { style: { flex: 1 }, children: [(0, jsx_runtime_1.jsx)("label", { style: { fontSize: '12px', color: '#6b7280', marginBottom: '4px', display: 'block' }, children: "\u00C9paisseur (px)" }), (0, jsx_runtime_1.jsx)("input", { type: "number", min: "0", max: "20", value: editBorderWidth, onChange: (e) => setEditBorderWidth(parseInt(e.target.value) || 0), style: {
|
|
644
|
+
width: '100%',
|
|
645
|
+
padding: '8px 10px',
|
|
646
|
+
border: '1px solid #d1d5db',
|
|
647
|
+
borderRadius: '6px',
|
|
648
|
+
fontSize: '14px',
|
|
649
|
+
boxSizing: 'border-box',
|
|
650
|
+
} })] }), (0, jsx_runtime_1.jsxs)("div", { style: { flex: 1 }, children: [(0, jsx_runtime_1.jsx)("label", { style: { fontSize: '12px', color: '#6b7280', marginBottom: '4px', display: 'block' }, children: "Couleur" }), (0, jsx_runtime_1.jsx)("input", { type: "color", value: editBorderColor, onChange: (e) => setEditBorderColor(e.target.value), style: {
|
|
651
|
+
width: '100%',
|
|
652
|
+
height: '38px',
|
|
653
|
+
padding: '2px',
|
|
654
|
+
border: '1px solid #d1d5db',
|
|
655
|
+
borderRadius: '6px',
|
|
656
|
+
cursor: 'pointer',
|
|
657
|
+
} })] }), (0, jsx_runtime_1.jsxs)("div", { style: { flex: 1 }, children: [(0, jsx_runtime_1.jsx)("label", { style: { fontSize: '12px', color: '#6b7280', marginBottom: '4px', display: 'block' }, children: "Coins arrondis (px)" }), (0, jsx_runtime_1.jsx)("input", { type: "number", min: "0", max: "100", value: editBorderRadius, onChange: (e) => setEditBorderRadius(parseInt(e.target.value) || 0), style: {
|
|
658
|
+
width: '100%',
|
|
659
|
+
padding: '8px 10px',
|
|
660
|
+
border: '1px solid #d1d5db',
|
|
661
|
+
borderRadius: '6px',
|
|
662
|
+
fontSize: '14px',
|
|
663
|
+
boxSizing: 'border-box',
|
|
664
|
+
} })] })] })] }), (0, jsx_runtime_1.jsxs)("div", { style: { display: 'flex', gap: '12px', justifyContent: 'flex-end' }, children: [(0, jsx_runtime_1.jsx)("button", { onClick: () => setShowMetadataEditor(false), style: {
|
|
635
665
|
padding: '10px 20px',
|
|
636
666
|
border: '1px solid #d1d5db',
|
|
637
667
|
backgroundColor: 'white',
|
|
@@ -701,9 +731,9 @@ class ImageNode extends lexical_1.DecoratorNode {
|
|
|
701
731
|
return 'image';
|
|
702
732
|
}
|
|
703
733
|
static clone(node) {
|
|
704
|
-
return new ImageNode(node.__src, node.__altText, node.__width, node.__height, node.__copyright, node.__photographer, node.__comment, node.__float, node.__captionPosition, node.__captionAlign, node.__captionVerticalAlign, node.__captionSize, node.__showFileName, node.__key);
|
|
734
|
+
return new ImageNode(node.__src, node.__altText, node.__width, node.__height, node.__copyright, node.__photographer, node.__comment, node.__float, node.__captionPosition, node.__captionAlign, node.__captionVerticalAlign, node.__captionSize, node.__showFileName, node.__borderWidth, node.__borderColor, node.__borderRadius, node.__key);
|
|
705
735
|
}
|
|
706
|
-
constructor(src, altText = '', width, height, copyright, photographer, comment, float, captionPosition, captionAlign, captionVerticalAlign, captionSize, showFileName, key) {
|
|
736
|
+
constructor(src, altText = '', width, height, copyright, photographer, comment, float, captionPosition, captionAlign, captionVerticalAlign, captionSize, showFileName, borderWidth, borderColor, borderRadius, key) {
|
|
707
737
|
super(key);
|
|
708
738
|
this.__src = src;
|
|
709
739
|
this.__altText = altText;
|
|
@@ -718,6 +748,9 @@ class ImageNode extends lexical_1.DecoratorNode {
|
|
|
718
748
|
this.__captionVerticalAlign = captionVerticalAlign;
|
|
719
749
|
this.__captionSize = captionSize;
|
|
720
750
|
this.__showFileName = showFileName;
|
|
751
|
+
this.__borderWidth = borderWidth;
|
|
752
|
+
this.__borderColor = borderColor;
|
|
753
|
+
this.__borderRadius = borderRadius;
|
|
721
754
|
}
|
|
722
755
|
createDOM() {
|
|
723
756
|
const span = document.createElement('span');
|
|
@@ -818,9 +851,30 @@ class ImageNode extends lexical_1.DecoratorNode {
|
|
|
818
851
|
getShowFileName() {
|
|
819
852
|
return this.__showFileName;
|
|
820
853
|
}
|
|
854
|
+
setBorderWidth(borderWidth) {
|
|
855
|
+
const writable = this.getWritable();
|
|
856
|
+
writable.__borderWidth = borderWidth;
|
|
857
|
+
}
|
|
858
|
+
getBorderWidth() {
|
|
859
|
+
return this.__borderWidth;
|
|
860
|
+
}
|
|
861
|
+
setBorderColor(borderColor) {
|
|
862
|
+
const writable = this.getWritable();
|
|
863
|
+
writable.__borderColor = borderColor;
|
|
864
|
+
}
|
|
865
|
+
getBorderColor() {
|
|
866
|
+
return this.__borderColor;
|
|
867
|
+
}
|
|
868
|
+
setBorderRadius(borderRadius) {
|
|
869
|
+
const writable = this.getWritable();
|
|
870
|
+
writable.__borderRadius = borderRadius;
|
|
871
|
+
}
|
|
872
|
+
getBorderRadius() {
|
|
873
|
+
return this.__borderRadius;
|
|
874
|
+
}
|
|
821
875
|
static importJSON(serializedNode) {
|
|
822
|
-
const { src, altText, width, height, copyright, photographer, comment, float, captionPosition, captionAlign, captionVerticalAlign, captionSize, showFileName } = serializedNode;
|
|
823
|
-
return $createImageNode({ src, altText, width, height, copyright, photographer, comment, float, captionPosition, captionAlign, captionVerticalAlign, captionSize, showFileName });
|
|
876
|
+
const { src, altText, width, height, copyright, photographer, comment, float, captionPosition, captionAlign, captionVerticalAlign, captionSize, showFileName, borderWidth, borderColor, borderRadius } = serializedNode;
|
|
877
|
+
return $createImageNode({ src, altText, width, height, copyright, photographer, comment, float, captionPosition, captionAlign, captionVerticalAlign, captionSize, showFileName, borderWidth, borderColor, borderRadius });
|
|
824
878
|
}
|
|
825
879
|
exportJSON() {
|
|
826
880
|
return {
|
|
@@ -839,6 +893,9 @@ class ImageNode extends lexical_1.DecoratorNode {
|
|
|
839
893
|
captionVerticalAlign: this.__captionVerticalAlign,
|
|
840
894
|
captionSize: this.__captionSize,
|
|
841
895
|
showFileName: this.__showFileName,
|
|
896
|
+
borderWidth: this.__borderWidth,
|
|
897
|
+
borderColor: this.__borderColor,
|
|
898
|
+
borderRadius: this.__borderRadius,
|
|
842
899
|
};
|
|
843
900
|
}
|
|
844
901
|
exportDOM() {
|
|
@@ -867,12 +924,12 @@ class ImageNode extends lexical_1.DecoratorNode {
|
|
|
867
924
|
};
|
|
868
925
|
}
|
|
869
926
|
decorate() {
|
|
870
|
-
return ((0, jsx_runtime_1.jsx)(ImageComponent, { src: this.__src, altText: this.__altText, width: this.__width, height: this.__height, copyright: this.__copyright, photographer: this.__photographer, comment: this.__comment, float: this.__float, captionPosition: this.__captionPosition, captionAlign: this.__captionAlign, captionVerticalAlign: this.__captionVerticalAlign, captionSize: this.__captionSize, showFileName: this.__showFileName, nodeKey: this.__key }));
|
|
927
|
+
return ((0, jsx_runtime_1.jsx)(ImageComponent, { src: this.__src, altText: this.__altText, width: this.__width, height: this.__height, copyright: this.__copyright, photographer: this.__photographer, comment: this.__comment, float: this.__float, captionPosition: this.__captionPosition, captionAlign: this.__captionAlign, captionVerticalAlign: this.__captionVerticalAlign, captionSize: this.__captionSize, showFileName: this.__showFileName, borderWidth: this.__borderWidth, borderColor: this.__borderColor, borderRadius: this.__borderRadius, nodeKey: this.__key }));
|
|
871
928
|
}
|
|
872
929
|
}
|
|
873
930
|
exports.ImageNode = ImageNode;
|
|
874
931
|
function $createImageNode(payload) {
|
|
875
|
-
return new ImageNode(payload.src, payload.altText || '', payload.width, payload.height, payload.copyright, payload.photographer, payload.comment, payload.float, payload.captionPosition, payload.captionAlign, payload.captionVerticalAlign, payload.captionSize, payload.showFileName);
|
|
932
|
+
return new ImageNode(payload.src, payload.altText || '', payload.width, payload.height, payload.copyright, payload.photographer, payload.comment, payload.float, payload.captionPosition, payload.captionAlign, payload.captionVerticalAlign, payload.captionSize, payload.showFileName, payload.borderWidth, payload.borderColor, payload.borderRadius);
|
|
876
933
|
}
|
|
877
934
|
function $isImageNode(node) {
|
|
878
935
|
return node instanceof ImageNode;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"InsertObjectPlugin.d.ts","sourceRoot":"","sources":["../../src/plugins/InsertObjectPlugin.tsx"],"names":[],"mappings":"AAIA,OAAO,
|
|
1
|
+
{"version":3,"file":"InsertObjectPlugin.d.ts","sourceRoot":"","sources":["../../src/plugins/InsertObjectPlugin.tsx"],"names":[],"mappings":"AAIA,OAAO,EAQL,cAAc,EACf,MAAM,SAAS,CAAA;AAMhB,eAAO,MAAM,qBAAqB,EAAE,cAAc,CAAC,IAAI,CAA0C,CAAA;AA2ZjG,wBAAgB,kBAAkB,4CAuSjC"}
|
|
@@ -425,11 +425,19 @@ function InsertObjectPlugin() {
|
|
|
425
425
|
editor.update(() => {
|
|
426
426
|
const selection = (0, lexical_1.$getSelection)();
|
|
427
427
|
if ((0, lexical_1.$isRangeSelection)(selection)) {
|
|
428
|
+
// Create image in its own paragraph for better control
|
|
428
429
|
const imageNode = (0, ImageNode_1.$createImageNode)({
|
|
429
430
|
src: data.url,
|
|
430
431
|
altText: data.altText || '',
|
|
431
432
|
});
|
|
432
|
-
|
|
433
|
+
const paragraphNode = (0, lexical_1.$createParagraphNode)();
|
|
434
|
+
paragraphNode.append(imageNode);
|
|
435
|
+
// Get the anchor node's parent paragraph and insert after it
|
|
436
|
+
const anchorNode = selection.anchor.getNode();
|
|
437
|
+
const topLevelElement = anchorNode.getTopLevelElementOrThrow();
|
|
438
|
+
topLevelElement.insertAfter(paragraphNode);
|
|
439
|
+
// Select the image
|
|
440
|
+
imageNode.selectEnd();
|
|
433
441
|
}
|
|
434
442
|
});
|
|
435
443
|
}
|