@qwanyx/ai-editor 1.7.3 → 1.7.4
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.
- package/dist/components/MarkdownEditor.d.ts +10 -0
- package/dist/components/MarkdownEditor.d.ts.map +1 -0
- package/dist/components/MarkdownEditor.js +179 -0
- package/dist/components/MarkdownToolbar.d.ts +2 -0
- package/dist/components/MarkdownToolbar.d.ts.map +1 -0
- package/dist/components/MarkdownToolbar.js +132 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +5 -2
- package/package.json +2 -1
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export interface MarkdownEditorProps {
|
|
2
|
+
value: string;
|
|
3
|
+
onChange: (markdown: string) => void;
|
|
4
|
+
placeholder?: string;
|
|
5
|
+
minHeight?: string;
|
|
6
|
+
className?: string;
|
|
7
|
+
externalUpdate?: string | number;
|
|
8
|
+
}
|
|
9
|
+
export declare function MarkdownEditor({ value, onChange, placeholder, minHeight, className, externalUpdate, }: MarkdownEditorProps): import("react/jsx-runtime").JSX.Element;
|
|
10
|
+
//# sourceMappingURL=MarkdownEditor.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"MarkdownEditor.d.ts","sourceRoot":"","sources":["../../src/components/MarkdownEditor.tsx"],"names":[],"mappings":"AAwBA,MAAM,WAAW,mBAAmB;IAClC,KAAK,EAAE,MAAM,CAAA;IACb,QAAQ,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,IAAI,CAAA;IACpC,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,cAAc,CAAC,EAAE,MAAM,GAAG,MAAM,CAAA;CACjC;AAuKD,wBAAgB,cAAc,CAAC,EAC7B,KAAK,EACL,QAAQ,EACR,WAAqC,EACrC,SAAmB,EACnB,SAAc,EACd,cAAc,GACf,EAAE,mBAAmB,2CA8CrB"}
|
|
@@ -0,0 +1,179 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
'use client';
|
|
3
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
4
|
+
exports.MarkdownEditor = MarkdownEditor;
|
|
5
|
+
const jsx_runtime_1 = require("react/jsx-runtime");
|
|
6
|
+
const react_1 = require("react");
|
|
7
|
+
const LexicalComposer_1 = require("@lexical/react/LexicalComposer");
|
|
8
|
+
const LexicalRichTextPlugin_1 = require("@lexical/react/LexicalRichTextPlugin");
|
|
9
|
+
const LexicalContentEditable_1 = require("@lexical/react/LexicalContentEditable");
|
|
10
|
+
const LexicalHistoryPlugin_1 = require("@lexical/react/LexicalHistoryPlugin");
|
|
11
|
+
const LexicalComposerContext_1 = require("@lexical/react/LexicalComposerContext");
|
|
12
|
+
const LexicalErrorBoundary_1 = require("@lexical/react/LexicalErrorBoundary");
|
|
13
|
+
const rich_text_1 = require("@lexical/rich-text");
|
|
14
|
+
const list_1 = require("@lexical/list");
|
|
15
|
+
const link_1 = require("@lexical/link");
|
|
16
|
+
const LexicalListPlugin_1 = require("@lexical/react/LexicalListPlugin");
|
|
17
|
+
const LexicalLinkPlugin_1 = require("@lexical/react/LexicalLinkPlugin");
|
|
18
|
+
const LexicalMarkdownShortcutPlugin_1 = require("@lexical/react/LexicalMarkdownShortcutPlugin");
|
|
19
|
+
const markdown_1 = require("@lexical/markdown");
|
|
20
|
+
const MarkdownToolbar_1 = require("./MarkdownToolbar");
|
|
21
|
+
// Dark theme for Markdown editor
|
|
22
|
+
const mdEditorTheme = {
|
|
23
|
+
paragraph: 'md-editor-paragraph',
|
|
24
|
+
heading: {
|
|
25
|
+
h1: 'md-editor-heading-h1',
|
|
26
|
+
h2: 'md-editor-heading-h2',
|
|
27
|
+
h3: 'md-editor-heading-h3',
|
|
28
|
+
},
|
|
29
|
+
text: {
|
|
30
|
+
bold: 'md-editor-text-bold',
|
|
31
|
+
italic: 'md-editor-text-italic',
|
|
32
|
+
},
|
|
33
|
+
list: {
|
|
34
|
+
ul: 'md-editor-list-ul',
|
|
35
|
+
ol: 'md-editor-list-ol',
|
|
36
|
+
listitem: 'md-editor-listitem',
|
|
37
|
+
nested: {
|
|
38
|
+
listitem: 'md-editor-nested-listitem',
|
|
39
|
+
},
|
|
40
|
+
},
|
|
41
|
+
quote: 'md-editor-quote',
|
|
42
|
+
link: 'md-editor-link',
|
|
43
|
+
};
|
|
44
|
+
const mdEditorStyles = `
|
|
45
|
+
.md-editor-paragraph {
|
|
46
|
+
margin-bottom: 8px;
|
|
47
|
+
color: #e5e7eb;
|
|
48
|
+
line-height: 1.6;
|
|
49
|
+
}
|
|
50
|
+
.md-editor-heading-h1 {
|
|
51
|
+
font-size: 1.875rem;
|
|
52
|
+
font-weight: bold;
|
|
53
|
+
margin-bottom: 16px;
|
|
54
|
+
margin-top: 24px;
|
|
55
|
+
color: #f9fafb;
|
|
56
|
+
}
|
|
57
|
+
.md-editor-heading-h2 {
|
|
58
|
+
font-size: 1.5rem;
|
|
59
|
+
font-weight: bold;
|
|
60
|
+
margin-bottom: 12px;
|
|
61
|
+
margin-top: 20px;
|
|
62
|
+
color: #f3f4f6;
|
|
63
|
+
}
|
|
64
|
+
.md-editor-heading-h3 {
|
|
65
|
+
font-size: 1.25rem;
|
|
66
|
+
font-weight: 600;
|
|
67
|
+
margin-bottom: 8px;
|
|
68
|
+
margin-top: 16px;
|
|
69
|
+
color: #e5e7eb;
|
|
70
|
+
}
|
|
71
|
+
.md-editor-text-bold {
|
|
72
|
+
font-weight: bold;
|
|
73
|
+
}
|
|
74
|
+
.md-editor-text-italic {
|
|
75
|
+
font-style: italic;
|
|
76
|
+
}
|
|
77
|
+
.md-editor-list-ul {
|
|
78
|
+
list-style-type: disc;
|
|
79
|
+
margin-left: 24px;
|
|
80
|
+
margin-bottom: 8px;
|
|
81
|
+
padding-left: 0;
|
|
82
|
+
color: #e5e7eb;
|
|
83
|
+
}
|
|
84
|
+
.md-editor-list-ol {
|
|
85
|
+
list-style-type: decimal;
|
|
86
|
+
margin-left: 24px;
|
|
87
|
+
margin-bottom: 8px;
|
|
88
|
+
padding-left: 0;
|
|
89
|
+
color: #e5e7eb;
|
|
90
|
+
}
|
|
91
|
+
.md-editor-listitem {
|
|
92
|
+
margin-bottom: 4px;
|
|
93
|
+
}
|
|
94
|
+
.md-editor-nested-listitem {
|
|
95
|
+
list-style-type: none;
|
|
96
|
+
}
|
|
97
|
+
.md-editor-quote {
|
|
98
|
+
border-left: 4px solid #4b5563;
|
|
99
|
+
padding-left: 16px;
|
|
100
|
+
font-style: italic;
|
|
101
|
+
color: #9ca3af;
|
|
102
|
+
margin: 16px 0;
|
|
103
|
+
}
|
|
104
|
+
.md-editor-link {
|
|
105
|
+
color: #60a5fa;
|
|
106
|
+
text-decoration: underline;
|
|
107
|
+
}
|
|
108
|
+
.md-editor-link:hover {
|
|
109
|
+
color: #93bbfc;
|
|
110
|
+
}
|
|
111
|
+
`;
|
|
112
|
+
function getEditorConfig() {
|
|
113
|
+
return {
|
|
114
|
+
namespace: 'MarkdownEditor',
|
|
115
|
+
theme: mdEditorTheme,
|
|
116
|
+
onError: (error) => {
|
|
117
|
+
console.error('MarkdownEditor error:', error);
|
|
118
|
+
},
|
|
119
|
+
nodes: [
|
|
120
|
+
rich_text_1.HeadingNode,
|
|
121
|
+
rich_text_1.QuoteNode,
|
|
122
|
+
list_1.ListNode,
|
|
123
|
+
list_1.ListItemNode,
|
|
124
|
+
link_1.LinkNode,
|
|
125
|
+
],
|
|
126
|
+
};
|
|
127
|
+
}
|
|
128
|
+
// Plugin to initialize from markdown on mount
|
|
129
|
+
function InitialMarkdownPlugin({ value }) {
|
|
130
|
+
const [editor] = (0, LexicalComposerContext_1.useLexicalComposerContext)();
|
|
131
|
+
const isFirstRender = (0, react_1.useRef)(true);
|
|
132
|
+
(0, react_1.useEffect)(() => {
|
|
133
|
+
if (isFirstRender.current) {
|
|
134
|
+
isFirstRender.current = false;
|
|
135
|
+
if (value) {
|
|
136
|
+
editor.update(() => {
|
|
137
|
+
(0, markdown_1.$convertFromMarkdownString)(value, markdown_1.TRANSFORMERS);
|
|
138
|
+
});
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
}, [editor, value]);
|
|
142
|
+
return null;
|
|
143
|
+
}
|
|
144
|
+
// Plugin to reload from value when externalUpdate changes
|
|
145
|
+
function ExternalUpdatePlugin({ value, externalUpdate }) {
|
|
146
|
+
const [editor] = (0, LexicalComposerContext_1.useLexicalComposerContext)();
|
|
147
|
+
const prevUpdate = (0, react_1.useRef)(externalUpdate);
|
|
148
|
+
(0, react_1.useEffect)(() => {
|
|
149
|
+
if (externalUpdate !== undefined && externalUpdate !== prevUpdate.current) {
|
|
150
|
+
prevUpdate.current = externalUpdate;
|
|
151
|
+
editor.update(() => {
|
|
152
|
+
(0, markdown_1.$convertFromMarkdownString)(value, markdown_1.TRANSFORMERS);
|
|
153
|
+
});
|
|
154
|
+
}
|
|
155
|
+
}, [editor, value, externalUpdate]);
|
|
156
|
+
return null;
|
|
157
|
+
}
|
|
158
|
+
// Plugin to emit markdown on every change
|
|
159
|
+
function MarkdownOnChangePlugin({ onChange }) {
|
|
160
|
+
const [editor] = (0, LexicalComposerContext_1.useLexicalComposerContext)();
|
|
161
|
+
(0, react_1.useEffect)(() => {
|
|
162
|
+
return editor.registerUpdateListener(({ editorState, dirtyElements, dirtyLeaves }) => {
|
|
163
|
+
// Only fire if something actually changed
|
|
164
|
+
if (dirtyElements.size === 0 && dirtyLeaves.size === 0)
|
|
165
|
+
return;
|
|
166
|
+
editorState.read(() => {
|
|
167
|
+
const md = (0, markdown_1.$convertToMarkdownString)(markdown_1.TRANSFORMERS);
|
|
168
|
+
onChange(md);
|
|
169
|
+
});
|
|
170
|
+
});
|
|
171
|
+
}, [editor, onChange]);
|
|
172
|
+
return null;
|
|
173
|
+
}
|
|
174
|
+
function MarkdownEditor({ value, onChange, placeholder = 'Commencez à écrire...', minHeight = '300px', className = '', externalUpdate, }) {
|
|
175
|
+
const handleChange = (0, react_1.useCallback)((md) => {
|
|
176
|
+
onChange(md);
|
|
177
|
+
}, [onChange]);
|
|
178
|
+
return ((0, jsx_runtime_1.jsxs)("div", { className: `border border-gray-700 rounded-xl bg-[#1A1A1A] flex flex-col overflow-hidden ${className}`, style: { minHeight }, children: [(0, jsx_runtime_1.jsx)("style", { dangerouslySetInnerHTML: { __html: mdEditorStyles } }), (0, jsx_runtime_1.jsxs)(LexicalComposer_1.LexicalComposer, { initialConfig: getEditorConfig(), children: [(0, jsx_runtime_1.jsx)("div", { className: "flex-shrink-0", children: (0, jsx_runtime_1.jsx)(MarkdownToolbar_1.MarkdownToolbar, {}) }), (0, jsx_runtime_1.jsxs)("div", { className: "relative flex-1 overflow-y-auto", children: [(0, jsx_runtime_1.jsx)(LexicalRichTextPlugin_1.RichTextPlugin, { contentEditable: (0, jsx_runtime_1.jsx)(LexicalContentEditable_1.ContentEditable, { className: "outline-none p-4 text-gray-200 min-h-[200px]", style: { minHeight: `calc(${minHeight} - 50px)` } }), placeholder: (0, jsx_runtime_1.jsx)("div", { className: "absolute top-4 left-4 text-gray-500 pointer-events-none", children: placeholder }), ErrorBoundary: LexicalErrorBoundary_1.LexicalErrorBoundary }), (0, jsx_runtime_1.jsx)(LexicalHistoryPlugin_1.HistoryPlugin, {}), (0, jsx_runtime_1.jsx)(LexicalListPlugin_1.ListPlugin, {}), (0, jsx_runtime_1.jsx)(LexicalLinkPlugin_1.LinkPlugin, {}), (0, jsx_runtime_1.jsx)(LexicalMarkdownShortcutPlugin_1.MarkdownShortcutPlugin, { transformers: markdown_1.TRANSFORMERS }), (0, jsx_runtime_1.jsx)(InitialMarkdownPlugin, { value: value }), (0, jsx_runtime_1.jsx)(ExternalUpdatePlugin, { value: value, externalUpdate: externalUpdate }), (0, jsx_runtime_1.jsx)(MarkdownOnChangePlugin, { onChange: handleChange })] })] })] }));
|
|
179
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"MarkdownToolbar.d.ts","sourceRoot":"","sources":["../../src/components/MarkdownToolbar.tsx"],"names":[],"mappings":"AAwEA,wBAAgB,eAAe,4CAoN9B"}
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
'use client';
|
|
3
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
4
|
+
exports.MarkdownToolbar = MarkdownToolbar;
|
|
5
|
+
const jsx_runtime_1 = require("react/jsx-runtime");
|
|
6
|
+
const react_1 = require("react");
|
|
7
|
+
const LexicalComposerContext_1 = require("@lexical/react/LexicalComposerContext");
|
|
8
|
+
const lexical_1 = require("lexical");
|
|
9
|
+
const list_1 = require("@lexical/list");
|
|
10
|
+
const rich_text_1 = require("@lexical/rich-text");
|
|
11
|
+
const selection_1 = require("@lexical/selection");
|
|
12
|
+
const link_1 = require("@lexical/link");
|
|
13
|
+
// Dropdown component using fixed positioning to escape overflow containers
|
|
14
|
+
function FixedDropdown({ show, buttonRef, children }) {
|
|
15
|
+
const [position, setPosition] = (0, react_1.useState)({ top: 0, left: 0 });
|
|
16
|
+
(0, react_1.useEffect)(() => {
|
|
17
|
+
if (show && buttonRef.current) {
|
|
18
|
+
const rect = buttonRef.current.getBoundingClientRect();
|
|
19
|
+
setPosition({
|
|
20
|
+
top: rect.bottom + 4,
|
|
21
|
+
left: rect.left
|
|
22
|
+
});
|
|
23
|
+
}
|
|
24
|
+
}, [show, buttonRef]);
|
|
25
|
+
if (!show)
|
|
26
|
+
return null;
|
|
27
|
+
return ((0, jsx_runtime_1.jsx)("div", { style: {
|
|
28
|
+
position: 'fixed',
|
|
29
|
+
top: position.top,
|
|
30
|
+
left: position.left,
|
|
31
|
+
zIndex: 99999,
|
|
32
|
+
backgroundColor: '#1f2937',
|
|
33
|
+
border: '1px solid #374151',
|
|
34
|
+
borderRadius: '8px',
|
|
35
|
+
boxShadow: '0 10px 15px -3px rgba(0, 0, 0, 0.3)',
|
|
36
|
+
padding: '4px 0',
|
|
37
|
+
minWidth: '160px'
|
|
38
|
+
}, onClick: (e) => e.stopPropagation(), children: children }));
|
|
39
|
+
}
|
|
40
|
+
function MarkdownToolbar() {
|
|
41
|
+
const [editor] = (0, LexicalComposerContext_1.useLexicalComposerContext)();
|
|
42
|
+
const [canUndo, setCanUndo] = (0, react_1.useState)(false);
|
|
43
|
+
const [canRedo, setCanRedo] = (0, react_1.useState)(false);
|
|
44
|
+
const [isBold, setIsBold] = (0, react_1.useState)(false);
|
|
45
|
+
const [isItalic, setIsItalic] = (0, react_1.useState)(false);
|
|
46
|
+
const [showHeadingMenu, setShowHeadingMenu] = (0, react_1.useState)(false);
|
|
47
|
+
const headingButtonRef = (0, react_1.useRef)(null);
|
|
48
|
+
const toolbarRef = (0, react_1.useRef)(null);
|
|
49
|
+
// Update toolbar state based on selection
|
|
50
|
+
const updateToolbar = (0, react_1.useCallback)(() => {
|
|
51
|
+
const selection = (0, lexical_1.$getSelection)();
|
|
52
|
+
if ((0, lexical_1.$isRangeSelection)(selection)) {
|
|
53
|
+
setIsBold(selection.hasFormat('bold'));
|
|
54
|
+
setIsItalic(selection.hasFormat('italic'));
|
|
55
|
+
}
|
|
56
|
+
}, []);
|
|
57
|
+
(0, react_1.useEffect)(() => {
|
|
58
|
+
return editor.registerUpdateListener(({ editorState }) => {
|
|
59
|
+
editorState.read(() => {
|
|
60
|
+
updateToolbar();
|
|
61
|
+
});
|
|
62
|
+
});
|
|
63
|
+
}, [editor, updateToolbar]);
|
|
64
|
+
(0, react_1.useEffect)(() => {
|
|
65
|
+
return editor.registerCommand(lexical_1.CAN_UNDO_COMMAND, (payload) => { setCanUndo(payload); return false; }, lexical_1.COMMAND_PRIORITY_CRITICAL);
|
|
66
|
+
}, [editor]);
|
|
67
|
+
(0, react_1.useEffect)(() => {
|
|
68
|
+
return editor.registerCommand(lexical_1.CAN_REDO_COMMAND, (payload) => { setCanRedo(payload); return false; }, lexical_1.COMMAND_PRIORITY_CRITICAL);
|
|
69
|
+
}, [editor]);
|
|
70
|
+
const formatBold = () => editor.dispatchCommand(lexical_1.FORMAT_TEXT_COMMAND, 'bold');
|
|
71
|
+
const formatItalic = () => editor.dispatchCommand(lexical_1.FORMAT_TEXT_COMMAND, 'italic');
|
|
72
|
+
const formatHeading = (headingTag) => {
|
|
73
|
+
editor.update(() => {
|
|
74
|
+
const selection = (0, lexical_1.$getSelection)();
|
|
75
|
+
if ((0, lexical_1.$isRangeSelection)(selection)) {
|
|
76
|
+
(0, selection_1.$setBlocksType)(selection, () => (0, rich_text_1.$createHeadingNode)(headingTag));
|
|
77
|
+
}
|
|
78
|
+
});
|
|
79
|
+
setShowHeadingMenu(false);
|
|
80
|
+
};
|
|
81
|
+
const formatParagraph = () => {
|
|
82
|
+
editor.update(() => {
|
|
83
|
+
const selection = (0, lexical_1.$getSelection)();
|
|
84
|
+
if ((0, lexical_1.$isRangeSelection)(selection)) {
|
|
85
|
+
(0, selection_1.$setBlocksType)(selection, () => (0, lexical_1.$createParagraphNode)());
|
|
86
|
+
}
|
|
87
|
+
});
|
|
88
|
+
setShowHeadingMenu(false);
|
|
89
|
+
};
|
|
90
|
+
const formatQuote = () => {
|
|
91
|
+
editor.update(() => {
|
|
92
|
+
const selection = (0, lexical_1.$getSelection)();
|
|
93
|
+
if ((0, lexical_1.$isRangeSelection)(selection)) {
|
|
94
|
+
(0, selection_1.$setBlocksType)(selection, () => (0, rich_text_1.$createQuoteNode)());
|
|
95
|
+
}
|
|
96
|
+
});
|
|
97
|
+
};
|
|
98
|
+
const formatBulletList = () => {
|
|
99
|
+
editor.dispatchCommand(list_1.INSERT_UNORDERED_LIST_COMMAND, undefined);
|
|
100
|
+
};
|
|
101
|
+
const formatNumberedList = () => {
|
|
102
|
+
editor.dispatchCommand(list_1.INSERT_ORDERED_LIST_COMMAND, undefined);
|
|
103
|
+
};
|
|
104
|
+
const insertLink = () => {
|
|
105
|
+
const url = window.prompt('URL du lien:');
|
|
106
|
+
if (url) {
|
|
107
|
+
editor.dispatchCommand(link_1.TOGGLE_LINK_COMMAND, url);
|
|
108
|
+
}
|
|
109
|
+
};
|
|
110
|
+
const undo = () => editor.dispatchCommand(lexical_1.UNDO_COMMAND, undefined);
|
|
111
|
+
const redo = () => editor.dispatchCommand(lexical_1.REDO_COMMAND, undefined);
|
|
112
|
+
// Close menus when clicking outside
|
|
113
|
+
(0, react_1.useEffect)(() => {
|
|
114
|
+
const handleClickOutside = (e) => {
|
|
115
|
+
if (toolbarRef.current && !toolbarRef.current.contains(e.target)) {
|
|
116
|
+
setShowHeadingMenu(false);
|
|
117
|
+
}
|
|
118
|
+
};
|
|
119
|
+
document.addEventListener('mousedown', handleClickOutside);
|
|
120
|
+
return () => document.removeEventListener('mousedown', handleClickOutside);
|
|
121
|
+
}, []);
|
|
122
|
+
const btnClass = (active = false) => `p-1.5 rounded transition-colors ${active
|
|
123
|
+
? 'bg-gray-600 text-white'
|
|
124
|
+
: 'text-gray-400 hover:text-white hover:bg-gray-700'}`;
|
|
125
|
+
const disabledBtnClass = (enabled) => `p-1.5 rounded transition-colors ${enabled
|
|
126
|
+
? 'text-gray-400 hover:text-white hover:bg-gray-700'
|
|
127
|
+
: 'text-gray-600 cursor-not-allowed opacity-30'}`;
|
|
128
|
+
return ((0, jsx_runtime_1.jsxs)("div", { ref: toolbarRef, className: "flex flex-wrap items-center gap-1 p-2 bg-[#1e1e1e] border-b border-gray-700 flex-shrink-0", children: [(0, jsx_runtime_1.jsx)("button", { onClick: undo, disabled: !canUndo, className: disabledBtnClass(canUndo), title: "Annuler (Ctrl+Z)", children: (0, jsx_runtime_1.jsx)("span", { className: "material-icons text-lg", children: "undo" }) }), (0, jsx_runtime_1.jsx)("button", { onClick: redo, disabled: !canRedo, className: disabledBtnClass(canRedo), title: "Refaire (Ctrl+Y)", children: (0, jsx_runtime_1.jsx)("span", { className: "material-icons text-lg", children: "redo" }) }), (0, jsx_runtime_1.jsx)("div", { className: "w-px h-6 bg-gray-700 mx-1" }), (0, jsx_runtime_1.jsx)("button", { onClick: formatBold, className: btnClass(isBold), title: "Gras (Ctrl+B)", children: (0, jsx_runtime_1.jsx)("span", { className: "material-icons text-lg", children: "format_bold" }) }), (0, jsx_runtime_1.jsx)("button", { onClick: formatItalic, className: btnClass(isItalic), title: "Italique (Ctrl+I)", children: (0, jsx_runtime_1.jsx)("span", { className: "material-icons text-lg", children: "format_italic" }) }), (0, jsx_runtime_1.jsx)("div", { className: "w-px h-6 bg-gray-700 mx-1" }), (0, jsx_runtime_1.jsxs)("div", { style: { position: 'relative' }, children: [(0, jsx_runtime_1.jsxs)("button", { ref: headingButtonRef, onClick: (e) => {
|
|
129
|
+
e.stopPropagation();
|
|
130
|
+
setShowHeadingMenu(!showHeadingMenu);
|
|
131
|
+
}, className: "p-1.5 text-gray-400 hover:text-white hover:bg-gray-700 rounded transition-colors flex items-center", title: "Titres", children: [(0, jsx_runtime_1.jsx)("span", { className: "material-icons text-lg", children: "title" }), (0, jsx_runtime_1.jsx)("span", { className: "material-icons text-sm", children: "arrow_drop_down" })] }), (0, jsx_runtime_1.jsxs)(FixedDropdown, { show: showHeadingMenu, buttonRef: headingButtonRef, children: [(0, jsx_runtime_1.jsx)("button", { onClick: formatParagraph, style: { display: 'block', width: '100%', padding: '6px 16px', textAlign: 'left', fontSize: '14px', backgroundColor: 'transparent', border: 'none', cursor: 'pointer', color: '#d1d5db' }, onMouseEnter: (e) => e.currentTarget.style.backgroundColor = '#374151', onMouseLeave: (e) => e.currentTarget.style.backgroundColor = 'transparent', children: "Paragraphe" }), (0, jsx_runtime_1.jsx)("button", { onClick: () => formatHeading('h1'), style: { display: 'block', width: '100%', padding: '6px 16px', textAlign: 'left', fontSize: '20px', fontWeight: 'bold', backgroundColor: 'transparent', border: 'none', cursor: 'pointer', color: '#d1d5db' }, onMouseEnter: (e) => e.currentTarget.style.backgroundColor = '#374151', onMouseLeave: (e) => e.currentTarget.style.backgroundColor = 'transparent', children: "Titre 1" }), (0, jsx_runtime_1.jsx)("button", { onClick: () => formatHeading('h2'), style: { display: 'block', width: '100%', padding: '6px 16px', textAlign: 'left', fontSize: '18px', fontWeight: 'bold', backgroundColor: 'transparent', border: 'none', cursor: 'pointer', color: '#d1d5db' }, onMouseEnter: (e) => e.currentTarget.style.backgroundColor = '#374151', onMouseLeave: (e) => e.currentTarget.style.backgroundColor = 'transparent', children: "Titre 2" }), (0, jsx_runtime_1.jsx)("button", { onClick: () => formatHeading('h3'), style: { display: 'block', width: '100%', padding: '6px 16px', textAlign: 'left', fontSize: '16px', fontWeight: '600', backgroundColor: 'transparent', border: 'none', cursor: 'pointer', color: '#d1d5db' }, onMouseEnter: (e) => e.currentTarget.style.backgroundColor = '#374151', onMouseLeave: (e) => e.currentTarget.style.backgroundColor = 'transparent', children: "Titre 3" })] })] }), (0, jsx_runtime_1.jsx)("div", { className: "w-px h-6 bg-gray-700 mx-1" }), (0, jsx_runtime_1.jsx)("button", { onClick: formatBulletList, className: btnClass(), title: "Liste \u00E0 puces", children: (0, jsx_runtime_1.jsx)("span", { className: "material-icons text-lg", children: "format_list_bulleted" }) }), (0, jsx_runtime_1.jsx)("button", { onClick: formatNumberedList, className: btnClass(), title: "Liste num\u00E9rot\u00E9e", children: (0, jsx_runtime_1.jsx)("span", { className: "material-icons text-lg", children: "format_list_numbered" }) }), (0, jsx_runtime_1.jsx)("button", { onClick: formatQuote, className: btnClass(), title: "Citation", children: (0, jsx_runtime_1.jsx)("span", { className: "material-icons text-lg", children: "format_quote" }) }), (0, jsx_runtime_1.jsx)("div", { className: "w-px h-6 bg-gray-700 mx-1" }), (0, jsx_runtime_1.jsx)("button", { onClick: insertLink, className: btnClass(), title: "Ins\u00E9rer un lien", children: (0, jsx_runtime_1.jsx)("span", { className: "material-icons text-lg", children: "link" }) })] }));
|
|
132
|
+
}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
export { RichTextEditor } from './components/RichTextEditor';
|
|
2
2
|
export type { RichTextEditorProps } from './components/RichTextEditor';
|
|
3
|
+
export { MarkdownEditor } from './components/MarkdownEditor';
|
|
4
|
+
export type { MarkdownEditorProps } from './components/MarkdownEditor';
|
|
3
5
|
export { RichTextViewer } from './components/RichTextViewer';
|
|
4
6
|
export type { RichTextViewerProps } from './components/RichTextViewer';
|
|
5
7
|
export { EditorToolbar } from './components/EditorToolbar';
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
package/dist/index.js
CHANGED
|
@@ -1,10 +1,13 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.
|
|
4
|
-
exports.AIEditor = exports.createEmptyPage = exports.createSection = exports.generateId = exports.DEFAULT_SEPARATOR = exports.DEFAULT_DROP_CAP = exports.VIDEO_PRESETS = exports.PRINT_PRESETS = exports.prepareForSave = exports.isSimpleDocument = exports.ensurePageDocument = exports.pageDocumentToLexical = void 0;
|
|
3
|
+
exports.isLexicalState = exports.isPageDocument = exports.detectFormat = exports.createDefaultGalleryContent = exports.GalleryLayout = exports.createDefaultRichTextContent = exports.RichTextLayout = exports.createDefaultOgilvyContent = exports.OgilvyLayout = exports.initializeLayouts = exports.getLayoutDefaultContent = exports.getLayoutComponent = exports.getLayoutsByCategory = exports.getAllLayouts = exports.getLayout = exports.registerLayout = exports.PaddingEditor = exports.SectionOptionsModal = exports.ImageMetadataDialog = exports.SmartViewer = exports.SmartEditor = exports.SectionComponent = exports.PageViewer = exports.PageEditor = exports.usePageContextSafe = exports.usePageContext = exports.PageProvider = exports.PageContext = exports.useEditorMode = exports.EditorModeProvider = exports.EditorModeContext = exports.SimpleLinkPlugin = exports.ImageLinkPlugin = exports.INSERT_OBJECT_COMMAND = exports.InsertObjectPlugin = exports.$wrapSelectionInSimpleLink = exports.$isSimpleLinkNode = exports.$createSimpleLinkNode = exports.SimpleLinkNode = exports.$wrapSelectionInImageLink = exports.$isImageLinkNode = exports.$createImageLinkNode = exports.ImageLinkNode = exports.$isImageNode = exports.$createImageNode = exports.ImageNode = exports.EditorToolbar = exports.RichTextViewer = exports.MarkdownEditor = exports.RichTextEditor = void 0;
|
|
4
|
+
exports.AIEditor = exports.createEmptyPage = exports.createSection = exports.generateId = exports.DEFAULT_SEPARATOR = exports.DEFAULT_DROP_CAP = exports.VIDEO_PRESETS = exports.PRINT_PRESETS = exports.prepareForSave = exports.isSimpleDocument = exports.ensurePageDocument = exports.pageDocumentToLexical = exports.lexicalToPageDocument = void 0;
|
|
5
5
|
// Main WYSIWYG editor component
|
|
6
6
|
var RichTextEditor_1 = require("./components/RichTextEditor");
|
|
7
7
|
Object.defineProperty(exports, "RichTextEditor", { enumerable: true, get: function () { return RichTextEditor_1.RichTextEditor; } });
|
|
8
|
+
// Markdown WYSIWYG editor (reads/writes Markdown)
|
|
9
|
+
var MarkdownEditor_1 = require("./components/MarkdownEditor");
|
|
10
|
+
Object.defineProperty(exports, "MarkdownEditor", { enumerable: true, get: function () { return MarkdownEditor_1.MarkdownEditor; } });
|
|
8
11
|
// Read-only viewer component
|
|
9
12
|
var RichTextViewer_1 = require("./components/RichTextViewer");
|
|
10
13
|
Object.defineProperty(exports, "RichTextViewer", { enumerable: true, get: function () { return RichTextViewer_1.RichTextViewer; } });
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@qwanyx/ai-editor",
|
|
3
|
-
"version": "1.7.
|
|
3
|
+
"version": "1.7.4",
|
|
4
4
|
"description": "AI-powered WYSIWYG rich text editor",
|
|
5
5
|
"main": "./dist/index.js",
|
|
6
6
|
"types": "./dist/index.d.ts",
|
|
@@ -26,6 +26,7 @@
|
|
|
26
26
|
"@lexical/history": "^0.17.0",
|
|
27
27
|
"@lexical/list": "^0.17.0",
|
|
28
28
|
"@lexical/link": "^0.17.0",
|
|
29
|
+
"@lexical/markdown": "^0.17.0",
|
|
29
30
|
"@lexical/selection": "^0.17.0",
|
|
30
31
|
"lexical": "^0.17.0",
|
|
31
32
|
"react": "^18.3.1",
|