smartrte-react 0.1.3 → 0.1.5

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.
@@ -1,3 +1,4 @@
1
+ import { MediaManagerAdapter } from "./MediaManager";
1
2
  type ClassicEditorProps = {
2
3
  value?: string;
3
4
  onChange?: (html: string) => void;
@@ -5,6 +6,10 @@ type ClassicEditorProps = {
5
6
  minHeight?: number | string;
6
7
  maxHeight?: number | string;
7
8
  readOnly?: boolean;
9
+ table?: boolean;
10
+ media?: boolean;
11
+ formula?: boolean;
12
+ mediaManager?: MediaManagerAdapter;
8
13
  };
9
- export declare function ClassicEditor({ value, onChange, placeholder, minHeight, maxHeight, readOnly, }: ClassicEditorProps): import("react/jsx-runtime").JSX.Element;
14
+ export declare function ClassicEditor({ value, onChange, placeholder, minHeight, maxHeight, readOnly, table, media, formula, mediaManager, }: ClassicEditorProps): import("react/jsx-runtime").JSX.Element;
10
15
  export {};
@@ -1,6 +1,7 @@
1
- import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
1
+ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
2
  import { useEffect, useRef, useState } from "react";
3
- export function ClassicEditor({ value, onChange, placeholder = "Type here…", minHeight = 200, maxHeight = 500, readOnly = false, }) {
3
+ import { MediaManager } from "./MediaManager";
4
+ export function ClassicEditor({ value, onChange, placeholder = "Type here…", minHeight = 200, maxHeight = 500, readOnly = false, table = true, media = true, formula = true, mediaManager, }) {
4
5
  const editableRef = useRef(null);
5
6
  const lastEmittedRef = useRef("");
6
7
  const isComposingRef = useRef(false);
@@ -16,6 +17,7 @@ export function ClassicEditor({ value, onChange, placeholder = "Type here…", m
16
17
  const [tableMenu, setTableMenu] = useState(null);
17
18
  const selectionRef = useRef(null);
18
19
  const selectingRef = useRef(null);
20
+ const [showMediaManager, setShowMediaManager] = useState(false);
19
21
  useEffect(() => {
20
22
  const el = editableRef.current;
21
23
  if (!el)
@@ -62,6 +64,8 @@ export function ClassicEditor({ value, onChange, placeholder = "Type here…", m
62
64
  exec("createLink", url);
63
65
  };
64
66
  const insertImage = () => {
67
+ if (!media)
68
+ return;
65
69
  fileInputRef.current?.click();
66
70
  };
67
71
  const scheduleImageOverlay = () => {
@@ -108,9 +112,7 @@ export function ClassicEditor({ value, onChange, placeholder = "Type here…", m
108
112
  range = document.createRange();
109
113
  range.selectNodeContents(host);
110
114
  range.collapse(false);
111
- sel = window.getSelection();
112
- sel?.removeAllRanges();
113
- sel?.addRange(range);
115
+ safeSelectRange(range);
114
116
  }
115
117
  const img = document.createElement("img");
116
118
  img.src = src;
@@ -127,18 +129,31 @@ export function ClassicEditor({ value, onChange, placeholder = "Type here…", m
127
129
  const r = document.createRange();
128
130
  r.setStartAfter(img);
129
131
  r.collapse(true);
130
- const s = window.getSelection();
131
- s?.removeAllRanges();
132
- s?.addRange(r);
132
+ safeSelectRange(r);
133
133
  setSelectedImage(img);
134
134
  scheduleImageOverlay();
135
135
  handleInput();
136
136
  }
137
137
  catch { }
138
138
  };
139
+ const safeSelectRange = (range) => {
140
+ try {
141
+ if (!range)
142
+ return;
143
+ const start = range.startContainer;
144
+ if (!start || !start.isConnected)
145
+ return;
146
+ const sel = window.getSelection();
147
+ sel?.removeAllRanges();
148
+ sel?.addRange(range);
149
+ }
150
+ catch { }
151
+ };
139
152
  const insertFormulaAtSelection = (tex) => {
140
153
  if (!tex)
141
154
  return;
155
+ if (!formula)
156
+ return;
142
157
  try {
143
158
  const host = editableRef.current;
144
159
  if (!host)
@@ -150,9 +165,7 @@ export function ClassicEditor({ value, onChange, placeholder = "Type here…", m
150
165
  range = document.createRange();
151
166
  range.selectNodeContents(host);
152
167
  range.collapse(false);
153
- sel = window.getSelection();
154
- sel?.removeAllRanges();
155
- sel?.addRange(range);
168
+ safeSelectRange(range);
156
169
  }
157
170
  const span = document.createElement("span");
158
171
  span.setAttribute("data-formula", tex);
@@ -176,9 +189,7 @@ export function ClassicEditor({ value, onChange, placeholder = "Type here…", m
176
189
  const r = document.createRange();
177
190
  r.setStartAfter(span);
178
191
  r.collapse(true);
179
- const s = window.getSelection();
180
- s?.removeAllRanges();
181
- s?.addRange(r);
192
+ safeSelectRange(r);
182
193
  handleInput();
183
194
  }
184
195
  catch { }
@@ -224,6 +235,8 @@ export function ClassicEditor({ value, onChange, placeholder = "Type here…", m
224
235
  return s;
225
236
  };
226
237
  const handleLocalImageFiles = async (files) => {
238
+ if (!media)
239
+ return;
227
240
  const list = Array.from(files).filter((f) => f.type.startsWith("image/"));
228
241
  for (const f of list) {
229
242
  await new Promise((resolve) => {
@@ -643,11 +656,11 @@ export function ClassicEditor({ value, onChange, placeholder = "Type here…", m
643
656
  position: "sticky",
644
657
  top: 0,
645
658
  zIndex: 1,
646
- }, children: [_jsx("input", { ref: fileInputRef, type: "file", accept: "image/*", multiple: true, style: { display: "none" }, onChange: (e) => {
659
+ }, children: [media && (_jsx("input", { ref: fileInputRef, type: "file", accept: "image/*", multiple: true, style: { display: "none" }, onChange: (e) => {
647
660
  if (e.currentTarget.files)
648
661
  handleLocalImageFiles(e.currentTarget.files);
649
662
  e.currentTarget.value = "";
650
- } }), _jsxs("select", { defaultValue: "p", onChange: (e) => {
663
+ } })), _jsxs("select", { defaultValue: "p", onChange: (e) => {
651
664
  const val = e.target.value;
652
665
  if (val === "p")
653
666
  applyFormatBlock("<p>");
@@ -657,39 +670,42 @@ export function ClassicEditor({ value, onChange, placeholder = "Type here…", m
657
670
  applyFormatBlock("<h2>");
658
671
  else if (val === "h3")
659
672
  applyFormatBlock("<h3>");
660
- }, title: "Paragraph/Heading", children: [_jsx("option", { value: "p", children: "Paragraph" }), _jsx("option", { value: "h1", children: "Heading 1" }), _jsx("option", { value: "h2", children: "Heading 2" }), _jsx("option", { value: "h3", children: "Heading 3" })] }), _jsx("button", { onClick: () => exec("bold"), children: "B" }), _jsx("button", { onClick: () => exec("italic"), children: "I" }), _jsx("button", { onClick: () => exec("underline"), children: "U" }), _jsx("button", { onClick: () => exec("strikeThrough"), children: "S" }), _jsx("button", { onClick: () => exec("insertUnorderedList"), children: "\u2022 List" }), _jsx("button", { onClick: () => exec("insertOrderedList"), children: "1. List" }), _jsx("button", { onClick: () => exec("formatBlock", "<blockquote>"), children: "\u275D" }), _jsx("button", { onClick: () => exec("formatBlock", "<pre>"), children: "< />" }), _jsx("button", { title: "Formula", onClick: () => setShowFormulaDialog(true), children: "\u2211" }), _jsx("button", { onClick: insertLink, children: "Link" }), _jsx("button", { onClick: () => exec("unlink"), children: "Unlink" }), _jsx("button", { onClick: insertImage, children: "Image" }), _jsxs("div", { style: {
661
- display: "inline-flex",
662
- gap: 4,
663
- alignItems: "center",
664
- marginLeft: 6,
665
- }, children: [_jsx("span", { style: { fontSize: 12, opacity: 0.7 }, children: "Image align:" }), _jsx("button", { onClick: () => {
666
- const img = selectedImage;
667
- if (!img)
668
- return;
669
- img.style.display = "block";
670
- img.style.margin = "0 auto";
671
- img.style.float = "none";
672
- scheduleImageOverlay();
673
- handleInput();
674
- }, title: "Center", children: "\u2299" }), _jsx("button", { onClick: () => {
675
- const img = selectedImage;
676
- if (!img)
677
- return;
678
- img.style.display = "inline";
679
- img.style.float = "left";
680
- img.style.margin = "0 8px 8px 0";
681
- scheduleImageOverlay();
682
- handleInput();
683
- }, title: "Float left", children: "\u27F8" }), _jsx("button", { onClick: () => {
684
- const img = selectedImage;
685
- if (!img)
686
- return;
687
- img.style.display = "inline";
688
- img.style.float = "right";
689
- img.style.margin = "0 0 8px 8px";
690
- scheduleImageOverlay();
691
- handleInput();
692
- }, title: "Float right", children: "\u27F9" })] }), _jsx("button", { onClick: () => setShowTableDialog(true), children: "+ Table" }), _jsx("button", { onClick: () => exec("undo"), children: "Undo" }), _jsx("button", { onClick: () => exec("redo"), children: "Redo" })] }), showTableDialog && (_jsx("div", { style: {
673
+ }, title: "Paragraph/Heading", children: [_jsx("option", { value: "p", children: "Paragraph" }), _jsx("option", { value: "h1", children: "Heading 1" }), _jsx("option", { value: "h2", children: "Heading 2" }), _jsx("option", { value: "h3", children: "Heading 3" })] }), _jsx("button", { onClick: () => exec("bold"), children: "B" }), _jsx("button", { onClick: () => exec("italic"), children: "I" }), _jsx("button", { onClick: () => exec("underline"), children: "U" }), _jsx("button", { onClick: () => exec("strikeThrough"), children: "S" }), _jsx("button", { onClick: () => exec("insertUnorderedList"), children: "\u2022 List" }), _jsx("button", { onClick: () => exec("insertOrderedList"), children: "1. List" }), _jsx("button", { onClick: () => exec("formatBlock", "<blockquote>"), children: "\u275D" }), _jsx("button", { onClick: () => exec("formatBlock", "<pre>"), children: "< />" }), formula && (_jsx("button", { title: "Formula", onClick: () => setShowFormulaDialog(true), children: "\u2211" })), _jsx("button", { onClick: insertLink, children: "Link" }), _jsx("button", { onClick: () => exec("unlink"), children: "Unlink" }), media && (_jsxs(_Fragment, { children: [_jsx("button", { onClick: insertImage, children: "Image" }), mediaManager && (_jsx("button", { onClick: () => setShowMediaManager(true), children: "Media manager" })), _jsxs("div", { style: {
674
+ display: "inline-flex",
675
+ gap: 4,
676
+ alignItems: "center",
677
+ marginLeft: 6,
678
+ }, children: [_jsx("span", { style: { fontSize: 12, opacity: 0.7 }, children: "Image align:" }), _jsx("button", { onClick: () => {
679
+ const img = selectedImage;
680
+ if (!img)
681
+ return;
682
+ img.style.display = "block";
683
+ img.style.margin = "0 auto";
684
+ img.style.float = "none";
685
+ scheduleImageOverlay();
686
+ handleInput();
687
+ }, title: "Center", children: "\u2299" }), _jsx("button", { onClick: () => {
688
+ const img = selectedImage;
689
+ if (!img)
690
+ return;
691
+ img.style.display = "inline";
692
+ img.style.float = "left";
693
+ img.style.margin = "0 8px 8px 0";
694
+ scheduleImageOverlay();
695
+ handleInput();
696
+ }, title: "Float left", children: "\u27F8" }), _jsx("button", { onClick: () => {
697
+ const img = selectedImage;
698
+ if (!img)
699
+ return;
700
+ img.style.display = "inline";
701
+ img.style.float = "right";
702
+ img.style.margin = "0 0 8px 8px";
703
+ scheduleImageOverlay();
704
+ handleInput();
705
+ }, title: "Float right", children: "\u27F9" })] })] })), table && (_jsx("button", { onClick: () => setShowTableDialog(true), children: "+ Table" })), _jsx("button", { onClick: () => exec("undo"), children: "Undo" }), _jsx("button", { onClick: () => exec("redo"), children: "Redo" })] }), media && mediaManager && (_jsx(MediaManager, { open: showMediaManager, onClose: () => setShowMediaManager(false), adapter: mediaManager, onSelect: (item) => {
706
+ if (item?.url)
707
+ insertImageAtSelection(item.url);
708
+ } })), table && showTableDialog && (_jsx("div", { style: {
693
709
  position: "fixed",
694
710
  inset: 0,
695
711
  background: "rgba(0,0,0,0.35)",
@@ -732,7 +748,7 @@ export function ClassicEditor({ value, onChange, placeholder = "Type here…", m
732
748
  }, children: [_jsx("button", { onClick: () => setShowTableDialog(false), children: "Cancel" }), _jsx("button", { onClick: () => {
733
749
  insertTable();
734
750
  setShowTableDialog(false);
735
- }, children: "Insert" })] })] }) })), showFormulaDialog && (_jsx("div", { style: {
751
+ }, children: "Insert" })] })] }) })), formula && showFormulaDialog && (_jsx("div", { style: {
736
752
  position: "fixed",
737
753
  inset: 0,
738
754
  background: "rgba(0,0,0,0.35)",
@@ -838,7 +854,7 @@ export function ClassicEditor({ value, onChange, placeholder = "Type here…", m
838
854
  handleInput();
839
855
  }, onPaste: (e) => {
840
856
  const items = e.clipboardData?.files;
841
- if (items && items.length) {
857
+ if (media && items && items.length) {
842
858
  const hasImage = Array.from(items).some((f) => f.type.startsWith("image/"));
843
859
  if (hasImage) {
844
860
  e.preventDefault();
@@ -850,7 +866,7 @@ export function ClassicEditor({ value, onChange, placeholder = "Type here…", m
850
866
  e.preventDefault();
851
867
  }
852
868
  }, onDrop: (e) => {
853
- if (e.dataTransfer?.files?.length) {
869
+ if (media && e.dataTransfer?.files?.length) {
854
870
  e.preventDefault();
855
871
  // Try to move caret to drop point
856
872
  const x = e.clientX;
@@ -899,7 +915,9 @@ export function ClassicEditor({ value, onChange, placeholder = "Type here…", m
899
915
  el.innerHTML = "<p><br></p>";
900
916
  }
901
917
  }, onKeyDown: (e) => {
902
- if ((e.metaKey || e.ctrlKey) && String(e.key).toLowerCase() === "m") {
918
+ if (formula &&
919
+ (e.metaKey || e.ctrlKey) &&
920
+ String(e.key).toLowerCase() === "m") {
903
921
  e.preventDefault();
904
922
  setShowFormulaDialog(true);
905
923
  return;
@@ -919,7 +937,8 @@ export function ClassicEditor({ value, onChange, placeholder = "Type here…", m
919
937
  if (["ArrowUp", "ArrowDown", "ArrowLeft", "ArrowRight"].includes(e.key)) {
920
938
  const sel = window.getSelection();
921
939
  const cell = getClosestCell(sel?.anchorNode || null);
922
- if (cell &&
940
+ if (table &&
941
+ cell &&
923
942
  cell.parentElement &&
924
943
  cell.parentElement.parentElement) {
925
944
  const row = cell.parentElement;
@@ -1003,7 +1022,7 @@ export function ClassicEditor({ value, onChange, placeholder = "Type here…", m
1003
1022
  else {
1004
1023
  setTableMenu(null);
1005
1024
  }
1006
- }, dangerouslySetInnerHTML: { __html: value || "" } }), selectedImage && imageOverlay && (_jsxs("div", { style: {
1025
+ } }), selectedImage && imageOverlay && (_jsxs("div", { style: {
1007
1026
  position: "fixed",
1008
1027
  left: imageOverlay.left,
1009
1028
  top: imageOverlay.top,
@@ -0,0 +1,31 @@
1
+ export type MediaItem = {
2
+ id: string;
3
+ url: string;
4
+ width?: number;
5
+ height?: number;
6
+ sizeBytes?: number;
7
+ mimeType?: string;
8
+ hashHex?: string;
9
+ createdAt?: string;
10
+ title?: string;
11
+ alt?: string;
12
+ tags?: string[];
13
+ };
14
+ export type MediaSearchQuery = {
15
+ q?: string;
16
+ tags?: string[];
17
+ mimePrefix?: string;
18
+ hashHex?: string;
19
+ page?: number;
20
+ pageSize?: number;
21
+ };
22
+ export type MediaManagerAdapter = {
23
+ upload: (files: File[]) => Promise<MediaItem[]>;
24
+ search: (query: MediaSearchQuery) => Promise<MediaItem[]>;
25
+ };
26
+ export declare function MediaManager(props: {
27
+ open: boolean;
28
+ onClose: () => void;
29
+ adapter: MediaManagerAdapter;
30
+ onSelect: (item: MediaItem) => void;
31
+ }): import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1,167 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { useEffect, useRef, useState } from "react";
3
+ export function MediaManager(props) {
4
+ const { open, onClose, adapter, onSelect } = props;
5
+ const [activeTab, setActiveTab] = useState("upload");
6
+ const [uploading, setUploading] = useState(false);
7
+ const [error, setError] = useState(null);
8
+ const [query, setQuery] = useState("");
9
+ const [results, setResults] = useState([]);
10
+ const fileInputRef = useRef(null);
11
+ useEffect(() => {
12
+ if (!open)
13
+ return;
14
+ setError(null);
15
+ if (activeTab === "library") {
16
+ performSearch();
17
+ }
18
+ }, [open, activeTab]);
19
+ const performSearch = async () => {
20
+ try {
21
+ const items = await adapter.search({ q: query, mimePrefix: "image/" });
22
+ setResults(items || []);
23
+ }
24
+ catch (e) {
25
+ setError("Failed to search media.");
26
+ }
27
+ };
28
+ const computeSha256Hex = async (file) => {
29
+ const buf = await file.arrayBuffer();
30
+ const digest = await crypto.subtle.digest("SHA-256", buf);
31
+ const bytes = new Uint8Array(digest);
32
+ let hex = "";
33
+ for (let i = 0; i < bytes.length; i++) {
34
+ hex += bytes[i].toString(16).padStart(2, "0");
35
+ }
36
+ return hex;
37
+ };
38
+ const handleUploadFiles = async (files) => {
39
+ if (!files || files.length === 0)
40
+ return;
41
+ const list = Array.from(files).filter((f) => f.type.startsWith("image/"));
42
+ if (list.length === 0)
43
+ return;
44
+ setUploading(true);
45
+ setError(null);
46
+ try {
47
+ // Duplicate detection by content hash (best-effort, server should also verify)
48
+ const duplicates = [];
49
+ const toUpload = [];
50
+ for (const f of list) {
51
+ try {
52
+ const hash = await computeSha256Hex(f);
53
+ const hits = await adapter.search({ hashHex: hash });
54
+ if (hits && hits.length) {
55
+ duplicates.push(hits[0]);
56
+ continue;
57
+ }
58
+ toUpload.push(f);
59
+ }
60
+ catch { }
61
+ }
62
+ if (duplicates.length) {
63
+ // Prefer duplicates immediately
64
+ onSelect(duplicates[0]);
65
+ setUploading(false);
66
+ onClose();
67
+ return;
68
+ }
69
+ if (toUpload.length) {
70
+ const uploaded = await adapter.upload(toUpload);
71
+ if (uploaded && uploaded.length) {
72
+ onSelect(uploaded[0]);
73
+ onClose();
74
+ }
75
+ }
76
+ }
77
+ catch (e) {
78
+ setError("Upload failed. Try again.");
79
+ }
80
+ finally {
81
+ setUploading(false);
82
+ }
83
+ };
84
+ if (!open)
85
+ return null;
86
+ return (_jsx("div", { style: {
87
+ position: "fixed",
88
+ inset: 0,
89
+ background: "rgba(0,0,0,0.35)",
90
+ display: "flex",
91
+ alignItems: "center",
92
+ justifyContent: "center",
93
+ zIndex: 80,
94
+ }, onClick: onClose, children: _jsxs("div", { style: {
95
+ background: "#fff",
96
+ width: 820,
97
+ maxWidth: "90vw",
98
+ maxHeight: "86vh",
99
+ borderRadius: 10,
100
+ boxShadow: "0 12px 32px rgba(0,0,0,0.22)",
101
+ display: "flex",
102
+ flexDirection: "column",
103
+ }, onClick: (e) => e.stopPropagation(), children: [_jsxs("div", { style: {
104
+ display: "flex",
105
+ alignItems: "center",
106
+ justifyContent: "space-between",
107
+ padding: "10px 14px",
108
+ borderBottom: "1px solid #eee",
109
+ }, children: [_jsxs("div", { style: { display: "flex", gap: 8 }, children: [_jsx("button", { onClick: () => setActiveTab("upload"), style: {
110
+ padding: "6px 10px",
111
+ borderRadius: 6,
112
+ border: "1px solid #ddd",
113
+ background: activeTab === "upload" ? "#f2f2f2" : "#fff",
114
+ }, children: "Upload" }), _jsx("button", { onClick: () => setActiveTab("library"), style: {
115
+ padding: "6px 10px",
116
+ borderRadius: 6,
117
+ border: "1px solid #ddd",
118
+ background: activeTab === "library" ? "#f2f2f2" : "#fff",
119
+ }, children: "Library" })] }), _jsx("button", { onClick: onClose, children: "\u2715" })] }), error && (_jsx("div", { style: { color: "#b00020", padding: "8px 14px" }, children: error })), activeTab === "upload" ? (_jsxs("div", { style: { padding: 16 }, children: [_jsx("input", { ref: fileInputRef, type: "file", accept: "image/*", multiple: true, style: { display: "none" }, onChange: (e) => handleUploadFiles(e.currentTarget.files) }), _jsx("div", { onClick: () => fileInputRef.current?.click(), onDragOver: (e) => {
120
+ e.preventDefault();
121
+ }, onDrop: (e) => {
122
+ e.preventDefault();
123
+ handleUploadFiles(e.dataTransfer.files);
124
+ }, style: {
125
+ border: "2px dashed #bbb",
126
+ borderRadius: 10,
127
+ padding: 24,
128
+ textAlign: "center",
129
+ color: "#333",
130
+ background: "#fafafa",
131
+ cursor: uploading ? "default" : "pointer",
132
+ opacity: uploading ? 0.7 : 1,
133
+ }, children: uploading ? "Uploading…" : "Click or drag images to upload" })] })) : (_jsxs("div", { style: {
134
+ padding: 16,
135
+ display: "flex",
136
+ flexDirection: "column",
137
+ gap: 12,
138
+ }, children: [_jsxs("div", { style: { display: "flex", gap: 8 }, children: [_jsx("input", { value: query, onChange: (e) => setQuery(e.target.value), placeholder: "Search images by name, tag, etc.", style: {
139
+ flex: 1,
140
+ padding: "6px 8px",
141
+ border: "1px solid #ddd",
142
+ borderRadius: 6,
143
+ } }), _jsx("button", { onClick: performSearch, children: "Search" })] }), _jsx("div", { style: {
144
+ display: "grid",
145
+ gridTemplateColumns: "repeat(auto-fill, minmax(120px, 1fr))",
146
+ gap: 12,
147
+ overflowY: "auto",
148
+ paddingBottom: 16,
149
+ }, children: results.map((it) => (_jsxs("button", { onClick: () => {
150
+ onSelect(it);
151
+ onClose();
152
+ }, title: it.title || it.url, style: {
153
+ display: "block",
154
+ border: "1px solid #eee",
155
+ borderRadius: 8,
156
+ padding: 6,
157
+ background: "#fff",
158
+ textAlign: "center",
159
+ }, children: [_jsx("img", { src: it.url, alt: it.alt || "", style: {
160
+ maxWidth: "100%",
161
+ maxHeight: 100,
162
+ display: "block",
163
+ margin: "0 auto",
164
+ objectFit: "cover",
165
+ borderRadius: 6,
166
+ } }), _jsx("div", { style: { fontSize: 11, marginTop: 6, color: "#333" }, children: it.width && it.height ? `${it.width}×${it.height}` : "" })] }, it.id || it.url))) })] }))] }) }));
167
+ }
package/dist/index.d.ts CHANGED
@@ -1,2 +1,3 @@
1
1
  import "katex/dist/katex.min.css";
2
2
  export { ClassicEditor } from './components/ClassicEditor';
3
+ export type { MediaManagerAdapter, MediaItem, MediaSearchQuery } from './components/MediaManager';
@@ -37,7 +37,7 @@ function ClassicEditorHost(props, ref) {
37
37
  }
38
38
  }
39
39
  catch { }
40
- }, placeholder: props.placeholder, minHeight: props.minHeight, maxHeight: props.maxHeight, readOnly: props.readOnly }) }));
40
+ }, placeholder: props.placeholder, minHeight: props.minHeight, maxHeight: props.maxHeight, readOnly: props.readOnly, table: props.table, media: props.media, formula: props.formula, mediaManager: props.mediaManager }) }));
41
41
  }
42
42
  const ClassicEditorHostWithRef = React.forwardRef(ClassicEditorHost);
43
43
  function initClassicEditor(opts) {