@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":"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"}
1
+ {"version":3,"file":"ImageNode.d.ts","sourceRoot":"","sources":["../../src/nodes/ImageNode.tsx"],"names":[],"mappings":"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"}
@@ -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, setIsSelected] = (0, react_1.useState)(false);
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
- // Handle click to select (or open fullscreen in viewer mode)
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
- // In viewer mode, click opens fullscreen directly
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: '12px', justifyContent: 'flex-end' }, children: [(0, jsx_runtime_1.jsx)("button", { onClick: () => setShowMetadataEditor(false), style: {
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,EAML,cAAc,EACf,MAAM,SAAS,CAAA;AAMhB,eAAO,MAAM,qBAAqB,EAAE,cAAc,CAAC,IAAI,CAA0C,CAAA;AA2ZjG,wBAAgB,kBAAkB,4CA6RjC"}
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
- selection.insertNodes([imageNode]);
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
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@qwanyx/ai-editor",
3
- "version": "1.3.6",
3
+ "version": "1.3.8",
4
4
  "description": "AI-powered WYSIWYG rich text editor",
5
5
  "main": "./dist/index.js",
6
6
  "types": "./dist/index.d.ts",