smartrte-react 0.1.2

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.
Files changed (42) hide show
  1. package/dist/QuillEditor.d.ts +8 -0
  2. package/dist/QuillEditor.js +34 -0
  3. package/dist/app.d.ts +6 -0
  4. package/dist/app.js +6 -0
  5. package/dist/blots/CommentBlot.d.ts +8 -0
  6. package/dist/blots/CommentBlot.js +17 -0
  7. package/dist/blots/FormulaBlot.d.ts +12 -0
  8. package/dist/blots/FormulaBlot.js +36 -0
  9. package/dist/blots/MediaBlot.d.ts +11 -0
  10. package/dist/blots/MediaBlot.js +37 -0
  11. package/dist/blots/TableBlot.d.ts +10 -0
  12. package/dist/blots/TableBlot.js +54 -0
  13. package/dist/blots/index.d.ts +5 -0
  14. package/dist/blots/index.js +12 -0
  15. package/dist/components/ClassicEditor.d.ts +10 -0
  16. package/dist/components/ClassicEditor.js +1066 -0
  17. package/dist/components/DiagramEditor.d.ts +5 -0
  18. package/dist/components/DiagramEditor.js +73 -0
  19. package/dist/components/FormulaEditor.d.ts +6 -0
  20. package/dist/components/FormulaEditor.js +86 -0
  21. package/dist/components/InfoBox.d.ts +7 -0
  22. package/dist/components/InfoBox.js +18 -0
  23. package/dist/components/MCQBlock.d.ts +13 -0
  24. package/dist/components/MCQBlock.js +29 -0
  25. package/dist/components/SmartEditor.d.ts +0 -0
  26. package/dist/components/SmartEditor.js +1 -0
  27. package/dist/components/SmartTable.d.ts +22 -0
  28. package/dist/components/SmartTable.js +629 -0
  29. package/dist/components/TableContextMenu.d.ts +11 -0
  30. package/dist/components/TableContextMenu.js +15 -0
  31. package/dist/components/TableInsertDialog.d.ts +7 -0
  32. package/dist/components/TableInsertDialog.js +42 -0
  33. package/dist/hooks/useEditorSync.d.ts +5 -0
  34. package/dist/hooks/useEditorSync.js +53 -0
  35. package/dist/index.d.ts +1 -0
  36. package/dist/index.js +1 -0
  37. package/dist/smart-editor.d.ts +0 -0
  38. package/dist/smart-editor.js +1 -0
  39. package/dist/standalone/classic-editor-embed.d.ts +12 -0
  40. package/dist/standalone/classic-editor-embed.js +108 -0
  41. package/dist/standalone/editor.js +241 -0
  42. package/package.json +46 -0
@@ -0,0 +1,5 @@
1
+ export declare function DiagramEditor({ open, onClose, onInsert, }: {
2
+ open: boolean;
3
+ onClose: () => void;
4
+ onInsert: (dataUrl: string) => void;
5
+ }): import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1,73 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { useEffect, useRef, useState } from "react";
3
+ export function DiagramEditor({ open, onClose, onInsert, }) {
4
+ const [code, setCode] = useState("graph TD\nA[Start] --> B{Decision}\nB -- Yes --> C[Do thing]\nB -- No --> D[Stop]");
5
+ const [svg, setSvg] = useState("");
6
+ const mounted = useRef(false);
7
+ useEffect(() => {
8
+ mounted.current = true;
9
+ return () => {
10
+ mounted.current = false;
11
+ };
12
+ }, []);
13
+ useEffect(() => {
14
+ if (!open)
15
+ return;
16
+ (async () => {
17
+ const loadMermaid = async () => {
18
+ // Use existing global if present
19
+ if (window.mermaid)
20
+ return window.mermaid;
21
+ // Load from CDN lazily to avoid bundler resolution
22
+ await new Promise((resolve) => {
23
+ const s = document.createElement("script");
24
+ s.src = "https://cdn.jsdelivr.net/npm/mermaid@10/dist/mermaid.min.js";
25
+ s.async = true;
26
+ s.onload = () => resolve();
27
+ s.onerror = () => resolve();
28
+ document.head.appendChild(s);
29
+ });
30
+ return window.mermaid;
31
+ };
32
+ try {
33
+ const mermaid = await loadMermaid();
34
+ if (mermaid && mermaid.initialize) {
35
+ mermaid.initialize({ startOnLoad: false });
36
+ const { svg } = await mermaid.render("diagram-preview", code);
37
+ if (mounted.current)
38
+ setSvg(svg);
39
+ }
40
+ else {
41
+ setSvg(`<svg xmlns='http://www.w3.org/2000/svg' width='400' height='80'><text x='10' y='40' font-family='monospace'>Mermaid not available</text></svg>`);
42
+ }
43
+ }
44
+ catch {
45
+ setSvg(`<svg xmlns='http://www.w3.org/2000/svg' width='400' height='80'><text x='10' y='40' font-family='monospace'>Mermaid not available</text></svg>`);
46
+ }
47
+ })();
48
+ }, [open, code]);
49
+ if (!open)
50
+ return null;
51
+ const toDataUrl = (svgText) => `data:image/svg+xml;utf8,${encodeURIComponent(svgText)}`;
52
+ return (_jsx("div", { style: {
53
+ position: "fixed",
54
+ inset: 0,
55
+ background: "rgba(0,0,0,0.4)",
56
+ display: "flex",
57
+ alignItems: "center",
58
+ justifyContent: "center",
59
+ zIndex: 100,
60
+ }, onClick: onClose, children: _jsxs("div", { style: {
61
+ background: "#fff",
62
+ padding: 16,
63
+ borderRadius: 8,
64
+ minWidth: 520,
65
+ maxWidth: 820,
66
+ width: "90%",
67
+ }, onClick: (e) => e.stopPropagation(), children: [_jsx("div", { style: { fontWeight: 600, marginBottom: 8 }, children: "Insert diagram (Mermaid)" }), _jsxs("div", { style: { display: "grid", gridTemplateColumns: "1fr 1fr", gap: 12 }, children: [_jsx("textarea", { value: code, onChange: (e) => setCode(e.target.value), rows: 12, style: { width: "100%", fontFamily: "monospace" } }), _jsx("div", { style: { border: "1px solid #eee", padding: 8, overflow: "auto" }, dangerouslySetInnerHTML: { __html: svg } })] }), _jsxs("div", { style: {
68
+ display: "flex",
69
+ gap: 8,
70
+ justifyContent: "flex-end",
71
+ marginTop: 12,
72
+ }, children: [_jsx("button", { onClick: onClose, children: "Cancel" }), _jsx("button", { onClick: () => onInsert(toDataUrl(svg || "")), children: "Insert" })] })] }) }));
73
+ }
@@ -0,0 +1,6 @@
1
+ import "katex/dist/katex.min.css";
2
+ export declare function FormulaEditor({ open, onClose, onInsert, }: {
3
+ open: boolean;
4
+ onClose: () => void;
5
+ onInsert: (tex: string, block: boolean) => void;
6
+ }): import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1,86 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { useEffect, useState } from "react";
3
+ import katex from "katex";
4
+ import "katex/dist/katex.min.css";
5
+ export function FormulaEditor({ open, onClose, onInsert, }) {
6
+ const [tex, setTex] = useState("a^2 + b^2 = c^2");
7
+ const [block, setBlock] = useState(false);
8
+ const presets = [
9
+ {
10
+ label: "Quadratic Formula",
11
+ tex: "x = \\frac{-b \\pm \\sqrt{b^2-4ac}}{2a}",
12
+ },
13
+ {
14
+ label: "Binomial Theorem",
15
+ tex: "(a+b)^n = \\sum_{k=0}^n \\binom{n}{k} a^{n-k} b^k",
16
+ },
17
+ { label: "Euler's Identity", tex: "e^{i\\pi}+1=0" },
18
+ { label: "Pythagoras", tex: "a^2 + b^2 = c^2" },
19
+ { label: "Derivative", tex: "\\frac{d}{dx} x^n = n x^{n-1}" },
20
+ { label: "Integral", tex: "\\int_a^b f(x)\\,dx" },
21
+ { label: "Limit", tex: "\\lim_{x\\to 0} \\frac{\\sin x}{x} = 1" },
22
+ {
23
+ label: "Matrix 2x2",
24
+ tex: "\\begin{pmatrix} a & b \\ \\ c & d \\end{pmatrix}",
25
+ },
26
+ { label: "Chem: Water", tex: "\\ce{H2O}" },
27
+ { label: "Chem: Combustion", tex: "\\ce{CH4 + 2 O2 -> CO2 + 2 H2O}" },
28
+ ];
29
+ const palette = [
30
+ "\\frac{a}{b}",
31
+ "\\sqrt{x}",
32
+ "\\int_a^b",
33
+ "\\sum_{i=1}^n",
34
+ "\\prod_{i=1}^n",
35
+ "\\lim_{x\\to 0}",
36
+ "x^{2}",
37
+ "x_{i}",
38
+ "\\alpha",
39
+ "\\beta",
40
+ "\\gamma",
41
+ "\\Delta",
42
+ "\\ce{H2O}",
43
+ "\\ce{CO2}",
44
+ ];
45
+ useEffect(() => {
46
+ if (!open)
47
+ return;
48
+ try {
49
+ const el = document.getElementById("katex-preview");
50
+ if (el)
51
+ katex.render(tex, el, {
52
+ throwOnError: false,
53
+ displayMode: block,
54
+ macros: { "\\ce": "\\mhchem" },
55
+ });
56
+ }
57
+ catch { }
58
+ }, [open, tex, block]);
59
+ if (!open)
60
+ return null;
61
+ return (_jsx("div", { style: {
62
+ position: "fixed",
63
+ inset: 0,
64
+ background: "rgba(0,0,0,0.4)",
65
+ display: "flex",
66
+ alignItems: "center",
67
+ justifyContent: "center",
68
+ zIndex: 100,
69
+ }, onClick: onClose, children: _jsxs("div", { style: {
70
+ background: "#fff",
71
+ color: "black",
72
+ padding: 16,
73
+ borderRadius: 8,
74
+ minWidth: 420,
75
+ }, onClick: (e) => e.stopPropagation(), children: [_jsx("div", { style: { fontWeight: 600, marginBottom: 8 }, children: "Insert formula" }), _jsx("div", { style: { display: "flex", flexWrap: "wrap", gap: 6, marginBottom: 8 }, children: palette.map((t) => (_jsx("button", { onClick: () => setTex((prev) => (prev ? prev + " " + t : t)), title: t, children: t }, t))) }), _jsx("div", { style: { display: "flex", flexWrap: "wrap", gap: 8, marginBottom: 8 }, children: presets.map((p) => (_jsx("button", { onClick: () => setTex(p.tex), title: p.tex, style: { fontSize: 12 }, children: p.label }, p.label))) }), _jsx("textarea", { value: tex, onChange: (e) => setTex(e.target.value), rows: 4, style: { width: "100%", fontFamily: "monospace", marginBottom: 8 } }), _jsxs("label", { style: {
76
+ display: "flex",
77
+ alignItems: "center",
78
+ gap: 8,
79
+ marginBottom: 8,
80
+ }, children: [_jsx("input", { type: "checkbox", checked: block, onChange: (e) => setBlock(e.target.checked) }), " ", "Block"] }), _jsx("div", { id: "katex-preview", style: {
81
+ padding: 12,
82
+ border: "1px solid #eee",
83
+ minHeight: 40,
84
+ marginBottom: 12,
85
+ } }), _jsxs("div", { style: { display: "flex", gap: 8, justifyContent: "flex-end" }, children: [_jsx("button", { onClick: onClose, children: "Cancel" }), _jsx("button", { onClick: () => onInsert(tex, block), children: "Insert" })] })] }) }));
86
+ }
@@ -0,0 +1,7 @@
1
+ export declare function InfoBox({ box, onChange, }: {
2
+ box: {
3
+ kind: string;
4
+ text: string;
5
+ };
6
+ onChange?: (next: any) => void;
7
+ }): import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1,18 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ const COLORS = {
3
+ info: "#e3f2fd",
4
+ warning: "#fff8e1",
5
+ success: "#e8f5e9",
6
+ danger: "#ffebee",
7
+ };
8
+ export function InfoBox({ box, onChange, }) {
9
+ const bg = COLORS[box.kind] || COLORS.info;
10
+ return (_jsxs("div", { style: {
11
+ background: bg,
12
+ border: "1px solid #e5e7eb",
13
+ padding: 12,
14
+ borderRadius: 8,
15
+ margin: "8px 0",
16
+ }, children: [_jsxs("select", { value: box.kind, onChange: (e) => onChange && onChange({ ...box, kind: e.target.value }), style: { marginBottom: 8 }, children: [_jsx("option", { value: "info", children: "Blue" }), _jsx("option", { value: "warning", children: "Yellow" }), _jsx("option", { value: "success", children: "Green" }), _jsx("option", { value: "danger", children: "Red" })] }), _jsx("div", { contentEditable: true, suppressContentEditableWarning: true, onInput: (e) => onChange &&
17
+ onChange({ ...box, text: e.target.innerText }), children: box.text })] }));
18
+ }
@@ -0,0 +1,13 @@
1
+ type MCQOption = {
2
+ text: string;
3
+ correct?: boolean;
4
+ };
5
+ export declare function MCQBlock({ block, onChange, }: {
6
+ block: {
7
+ question: string;
8
+ options: MCQOption[];
9
+ multiple?: boolean;
10
+ };
11
+ onChange?: (next: any) => void;
12
+ }): import("react/jsx-runtime").JSX.Element;
13
+ export {};
@@ -0,0 +1,29 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ export function MCQBlock({ block, onChange, }) {
3
+ return (_jsxs("div", { style: {
4
+ border: "1px solid #e5e7eb",
5
+ padding: 12,
6
+ borderRadius: 8,
7
+ margin: "8px 0",
8
+ }, children: [_jsx("div", { contentEditable: true, suppressContentEditableWarning: true, style: { fontWeight: 600, marginBottom: 8 }, onInput: (e) => onChange &&
9
+ onChange({ ...block, question: e.target.innerText }), children: block.question }), _jsx("ul", { style: { listStyle: "none", padding: 0, margin: 0 }, children: block.options.map((opt, i) => (_jsxs("li", { style: {
10
+ display: "flex",
11
+ alignItems: "center",
12
+ gap: 8,
13
+ marginBottom: 6,
14
+ }, children: [_jsx("input", { type: block.multiple ? "checkbox" : "radio", checked: !!opt.correct, onChange: (e) => onChange &&
15
+ onChange({
16
+ ...block,
17
+ options: block.options.map((o, idx) => idx === i
18
+ ? { ...o, correct: e.target.checked }
19
+ : block.multiple
20
+ ? o
21
+ : { ...o, correct: false }),
22
+ }) }), _jsx("div", { contentEditable: true, suppressContentEditableWarning: true, style: { flex: 1, borderBottom: "1px dashed #ddd" }, onInput: (e) => onChange &&
23
+ onChange({
24
+ ...block,
25
+ options: block.options.map((o, idx) => idx === i
26
+ ? { ...o, text: e.target.innerText }
27
+ : o),
28
+ }), children: opt.text })] }, i))) })] }));
29
+ }
File without changes
@@ -0,0 +1 @@
1
+ // Removed: SmartEditor component is not part of the public API.
@@ -0,0 +1,22 @@
1
+ type TableNode = {
2
+ rows: Array<{
3
+ cells: Array<any>;
4
+ }>;
5
+ column_widths?: number[];
6
+ freeze_header?: boolean;
7
+ freeze_first_col?: boolean;
8
+ };
9
+ type Props = {
10
+ editor: any;
11
+ tableNode: TableNode;
12
+ tableIdx: number;
13
+ onChange?: () => void;
14
+ onCaretUpdate?: (ctx: {
15
+ tableIdx: number;
16
+ r: number;
17
+ c: number;
18
+ offset: number;
19
+ }) => void;
20
+ };
21
+ export declare function SmartTable({ editor, tableNode, tableIdx, onChange, onCaretUpdate, }: Props): import("react/jsx-runtime").JSX.Element;
22
+ export {};