react-next-editor-js 0.1.0

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 (102) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +877 -0
  3. package/dist/chunk-3QWXTDLY.cjs +486 -0
  4. package/dist/chunk-3QWXTDLY.cjs.map +1 -0
  5. package/dist/chunk-5F6SPYCN.cjs +180 -0
  6. package/dist/chunk-5F6SPYCN.cjs.map +1 -0
  7. package/dist/chunk-6NTSXJX4.js +174 -0
  8. package/dist/chunk-6NTSXJX4.js.map +1 -0
  9. package/dist/chunk-7VYJDBH7.js +261 -0
  10. package/dist/chunk-7VYJDBH7.js.map +1 -0
  11. package/dist/chunk-DBSFCCBG.cjs +1712 -0
  12. package/dist/chunk-DBSFCCBG.cjs.map +1 -0
  13. package/dist/chunk-EFE6RHDL.cjs +4 -0
  14. package/dist/chunk-EFE6RHDL.cjs.map +1 -0
  15. package/dist/chunk-G6YRIEK4.js +3 -0
  16. package/dist/chunk-G6YRIEK4.js.map +1 -0
  17. package/dist/chunk-GFNFJ3FL.cjs +119 -0
  18. package/dist/chunk-GFNFJ3FL.cjs.map +1 -0
  19. package/dist/chunk-IG2YLUFW.js +114 -0
  20. package/dist/chunk-IG2YLUFW.js.map +1 -0
  21. package/dist/chunk-JQXTWLHL.js +176 -0
  22. package/dist/chunk-JQXTWLHL.js.map +1 -0
  23. package/dist/chunk-NJCEHQV3.cjs +454 -0
  24. package/dist/chunk-NJCEHQV3.cjs.map +1 -0
  25. package/dist/chunk-O4GTLC3T.js +478 -0
  26. package/dist/chunk-O4GTLC3T.js.map +1 -0
  27. package/dist/chunk-ODHABIIC.cjs +82 -0
  28. package/dist/chunk-ODHABIIC.cjs.map +1 -0
  29. package/dist/chunk-PZ5AY32C.js +9 -0
  30. package/dist/chunk-PZ5AY32C.js.map +1 -0
  31. package/dist/chunk-Q7SFCCGT.cjs +11 -0
  32. package/dist/chunk-Q7SFCCGT.cjs.map +1 -0
  33. package/dist/chunk-QIUIYBCZ.js +80 -0
  34. package/dist/chunk-QIUIYBCZ.js.map +1 -0
  35. package/dist/chunk-QROUNVQK.js +450 -0
  36. package/dist/chunk-QROUNVQK.js.map +1 -0
  37. package/dist/chunk-T6FR37IC.js +41 -0
  38. package/dist/chunk-T6FR37IC.js.map +1 -0
  39. package/dist/chunk-TI44I654.cjs +265 -0
  40. package/dist/chunk-TI44I654.cjs.map +1 -0
  41. package/dist/chunk-TXPLBAH5.cjs +47 -0
  42. package/dist/chunk-TXPLBAH5.cjs.map +1 -0
  43. package/dist/chunk-U3O54IYI.cjs +187 -0
  44. package/dist/chunk-U3O54IYI.cjs.map +1 -0
  45. package/dist/chunk-VLC7SZMT.js +1669 -0
  46. package/dist/chunk-VLC7SZMT.js.map +1 -0
  47. package/dist/core/index.cjs +232 -0
  48. package/dist/core/index.cjs.map +1 -0
  49. package/dist/core/index.d.cts +122 -0
  50. package/dist/core/index.d.ts +122 -0
  51. package/dist/core/index.js +7 -0
  52. package/dist/core/index.js.map +1 -0
  53. package/dist/defaults-EQD5QKCU.js +4 -0
  54. package/dist/defaults-EQD5QKCU.js.map +1 -0
  55. package/dist/defaults-MLYXD2BG.cjs +49 -0
  56. package/dist/defaults-MLYXD2BG.cjs.map +1 -0
  57. package/dist/docx-BUrf4PFj.d.ts +49 -0
  58. package/dist/docx-DLfSdvXm.d.cts +49 -0
  59. package/dist/docx-LDETXV3L.js +5 -0
  60. package/dist/docx-LDETXV3L.js.map +1 -0
  61. package/dist/docx-N2LKIOK3.cjs +14 -0
  62. package/dist/docx-N2LKIOK3.cjs.map +1 -0
  63. package/dist/export/index.cjs +54 -0
  64. package/dist/export/index.cjs.map +1 -0
  65. package/dist/export/index.d.cts +60 -0
  66. package/dist/export/index.d.ts +60 -0
  67. package/dist/export/index.js +9 -0
  68. package/dist/export/index.js.map +1 -0
  69. package/dist/html-5BXJPQU3.js +7 -0
  70. package/dist/html-5BXJPQU3.js.map +1 -0
  71. package/dist/html-KU2KHLRF.cjs +24 -0
  72. package/dist/html-KU2KHLRF.cjs.map +1 -0
  73. package/dist/import/index.cjs +15 -0
  74. package/dist/import/index.cjs.map +1 -0
  75. package/dist/import/index.d.cts +37 -0
  76. package/dist/import/index.d.ts +37 -0
  77. package/dist/import/index.js +6 -0
  78. package/dist/import/index.js.map +1 -0
  79. package/dist/index.cjs +1035 -0
  80. package/dist/index.cjs.map +1 -0
  81. package/dist/index.d.cts +248 -0
  82. package/dist/index.d.ts +248 -0
  83. package/dist/index.js +885 -0
  84. package/dist/index.js.map +1 -0
  85. package/dist/persistence/index.cjs +37 -0
  86. package/dist/persistence/index.cjs.map +1 -0
  87. package/dist/persistence/index.d.cts +279 -0
  88. package/dist/persistence/index.d.ts +279 -0
  89. package/dist/persistence/index.js +4 -0
  90. package/dist/persistence/index.js.map +1 -0
  91. package/dist/sanitize-7IZ-SW1f.d.ts +361 -0
  92. package/dist/sanitize-CvmgqbsA.d.cts +361 -0
  93. package/dist/server/index.cjs +400 -0
  94. package/dist/server/index.cjs.map +1 -0
  95. package/dist/server/index.d.cts +229 -0
  96. package/dist/server/index.d.ts +229 -0
  97. package/dist/server/index.js +390 -0
  98. package/dist/server/index.js.map +1 -0
  99. package/dist/styles.css +680 -0
  100. package/dist/types-B4z0Quvv.d.cts +193 -0
  101. package/dist/types-B4z0Quvv.d.ts +193 -0
  102. package/package.json +183 -0
package/dist/index.js ADDED
@@ -0,0 +1,885 @@
1
+ import { buildSchema, createCommands, createDoc, buildPlugins, createEditorState, countDocument } from './chunk-VLC7SZMT.js';
2
+ export { buildPlugins, buildSchema, countDocument, createCommands, createDoc, createEditorState, defaultSchema } from './chunk-VLC7SZMT.js';
3
+ import { exportDocument } from './chunk-IG2YLUFW.js';
4
+ export { downloadBlob, downloadText, exportDocument, printDocumentToPdf } from './chunk-IG2YLUFW.js';
5
+ import { IndexedDBStore, DocumentPersistence, SyncEngine, ConnectivityMonitor, requestPersistentStorage } from './chunk-O4GTLC3T.js';
6
+ export { ConflictError, ConnectivityMonitor, DocumentPersistence, IndexedDBStore, MemoryStore, SyncEngine, requestPersistentStorage } from './chunk-O4GTLC3T.js';
7
+ import { documentToText } from './chunk-QROUNVQK.js';
8
+ export { documentToDocxBlob, documentToDocxBuffer, documentToText } from './chunk-QROUNVQK.js';
9
+ import './chunk-G6YRIEK4.js';
10
+ export { importDocx } from './chunk-QIUIYBCZ.js';
11
+ import { documentToHtml } from './chunk-7VYJDBH7.js';
12
+ export { buildPrintDocument, documentToHtml } from './chunk-7VYJDBH7.js';
13
+ import './chunk-T6FR37IC.js';
14
+ import { preloadSanitizer } from './chunk-6NTSXJX4.js';
15
+ export { sanitizeHtml, sanitizeImageSrc, sanitizeUrl } from './chunk-6NTSXJX4.js';
16
+ import { resolvePageDimensions, themeToCssVars, DEFAULT_COLOR_PALETTE, DEFAULT_FONT_SIZES, DEFAULT_FONT_FAMILIES, DEFAULT_STRINGS, DEFAULT_PAGE, DEFAULT_FEATURES, DEFAULT_TOOLBAR_GROUPS } from './chunk-JQXTWLHL.js';
17
+ export { DEFAULT_COLOR_PALETTE, DEFAULT_FEATURES, DEFAULT_FONT_FAMILIES, DEFAULT_FONT_SIZES, DEFAULT_PAGE, DEFAULT_STRINGS, DEFAULT_TOOLBAR_GROUPS, PAGE_DIMENSIONS_MM, resolvePageDimensions, themeToCssVars } from './chunk-JQXTWLHL.js';
18
+ import './chunk-PZ5AY32C.js';
19
+ import { createContext, forwardRef, useRef, useMemo, useState, useCallback, useImperativeHandle, useEffect, Fragment, Component, useContext } from 'react';
20
+ import { EditorView } from 'prosemirror-view';
21
+ import { EditorState, TextSelection } from 'prosemirror-state';
22
+ import { Node } from 'prosemirror-model';
23
+ import { jsx, jsxs } from 'react/jsx-runtime';
24
+
25
+ var EditorContext = createContext(null);
26
+ function useEditorContext() {
27
+ const ctx = useContext(EditorContext);
28
+ if (!ctx) {
29
+ throw new Error("useEditorContext must be used within a react-next-editor <Editor>.");
30
+ }
31
+ return ctx;
32
+ }
33
+ var EditorErrorBoundary = class extends Component {
34
+ constructor(props) {
35
+ super(props);
36
+ this.handleReset = () => {
37
+ this.setState({ error: null });
38
+ };
39
+ this.state = { error: null };
40
+ }
41
+ static getDerivedStateFromError(error) {
42
+ return { error };
43
+ }
44
+ componentDidCatch(error, info) {
45
+ console.error("[react-next-editor] Editor error contained by boundary:", error, info);
46
+ this.props.onError?.(error);
47
+ }
48
+ render() {
49
+ if (this.state.error) {
50
+ return /* @__PURE__ */ jsx("div", { className: "rne-root", children: /* @__PURE__ */ jsxs("div", { className: "rne-error", role: "alert", children: [
51
+ /* @__PURE__ */ jsx("strong", { children: this.props.fallbackMessage ?? "The editor encountered a problem." }),
52
+ /* @__PURE__ */ jsx("p", { children: "Your latest saved content is preserved locally. You can try to recover the editor." }),
53
+ /* @__PURE__ */ jsx("button", { type: "button", onClick: this.handleReset, children: "Reload editor" })
54
+ ] }) });
55
+ }
56
+ return this.props.children;
57
+ }
58
+ };
59
+ var PATHS = {
60
+ undo: /* @__PURE__ */ jsx("path", { d: "M12 5V1L7 6l5 5V7a6 6 0 1 1-6 6H4a8 8 0 1 0 8-8z" }),
61
+ redo: /* @__PURE__ */ jsx("path", { d: "M12 5V1l5 5-5 5V7a6 6 0 1 0 6 6h2a8 8 0 1 1-8-8z" }),
62
+ bold: /* @__PURE__ */ jsx("path", { d: "M7 5h6a3.5 3.5 0 0 1 1.5 6.66A3.5 3.5 0 0 1 13 19H7V5zm3 2v3h3a1.5 1.5 0 0 0 0-3h-3zm0 5v4h3a2 2 0 0 0 0-4h-3z" }),
63
+ italic: /* @__PURE__ */ jsx("path", { d: "M10 4h7v2h-2.3l-3 12H14v2H7v-2h2.3l3-12H10V4z" }),
64
+ underline: /* @__PURE__ */ jsx("path", { d: "M6 4v7a6 6 0 0 0 12 0V4h-2.5v7a3.5 3.5 0 0 1-7 0V4H6zm-1 16h14v2H5v-2z" }),
65
+ strikethrough: /* @__PURE__ */ jsx("path", { d: "M3 11h18v2H3v-2zm9-7c2.5 0 4 1.3 4.3 3h-2.4c-.2-.7-.8-1.2-1.9-1.2-1.2 0-2 .6-2 1.5 0 .5.3.9 1 1.2H9.2C8.5 9 8 8.2 8 7.2 8 5.3 9.7 4 12 4zm2 11.5c0 1.9-1.6 3.5-4.2 3.5-2.6 0-4.3-1.4-4.5-3.4h2.4c.2.9 1 1.5 2.2 1.5 1.3 0 2.1-.6 2.1-1.6 0-.2 0-.4-.1-.5H14z" }),
66
+ superscript: /* @__PURE__ */ jsx("path", { d: "M4 7l4 5-4 5h2.5L9 13.5 11.5 17H14l-4-5 4-5h-2.5L9 10.5 6.5 7H4zm16-1c0-.8-.6-1.5-1.7-1.5-.9 0-1.6.5-1.8 1.3h1c.1-.3.4-.5.8-.5.4 0 .7.2.7.6 0 .6-1 1-2.3 2.1V9h3.6v-.9h-1.9c1-.8 1.6-1.3 1.6-2.2z" }),
67
+ subscript: /* @__PURE__ */ jsx("path", { d: "M4 4l4 5-4 5h2.5L9 10.5 11.5 14H14l-4-5 4-5h-2.5L9 7.5 6.5 4H4zm16 13c0-.8-.6-1.5-1.7-1.5-.9 0-1.6.5-1.8 1.3h1c.1-.3.4-.5.8-.5.4 0 .7.2.7.6 0 .6-1 1-2.3 2.1V20h3.6v-.9h-1.9c1-.8 1.6-1.3 1.6-2.1z" }),
68
+ code: /* @__PURE__ */ jsx("path", { d: "M9 7l-5 5 5 5 1.4-1.4L6.8 12l3.6-3.6L9 7zm6 0l-1.4 1.4L17.2 12l-3.6 3.6L15 17l5-5-5-5z" }),
69
+ textColor: /* @__PURE__ */ jsx("path", { d: "M5 18h14v2H5v-2zM9.6 4h2.8l4.1 11h-2.3l-1-3H8.8l-1 3H5.5L9.6 4zm-.2 6.1h3.2L11 5.6 9.4 10.1z" }),
70
+ highlight: /* @__PURE__ */ jsx("path", { d: "M4 18h16v3H4v-3zM15.6 3.4l3 3-7.8 7.8-3.6.6.6-3.6 7.8-7.8zM6 13l3 3H6v-3z" }),
71
+ clearFormatting: /* @__PURE__ */ jsx("path", { d: "M6 5v2h5l-2.8 9h2.5l2.8-9H19V5H6zM4.7 17.3 17.3 4.7l1.4 1.4L6.1 18.7l-1.4-1.4z" }),
72
+ alignLeft: /* @__PURE__ */ jsx("path", { d: "M3 4h18v2H3V4zm0 5h12v2H3V9zm0 5h18v2H3v-2zm0 5h12v2H3v-2z" }),
73
+ alignCenter: /* @__PURE__ */ jsx("path", { d: "M3 4h18v2H3V4zm3 5h12v2H6V9zm-3 5h18v2H3v-2zm3 5h12v2H6v-2z" }),
74
+ alignRight: /* @__PURE__ */ jsx("path", { d: "M3 4h18v2H3V4zm6 5h12v2H9V9zm-6 5h18v2H3v-2zm6 5h12v2H9v-2z" }),
75
+ alignJustify: /* @__PURE__ */ jsx("path", { d: "M3 4h18v2H3V4zm0 5h18v2H3V9zm0 5h18v2H3v-2zm0 5h18v2H3v-2z" }),
76
+ bulletList: /* @__PURE__ */ jsx("path", { d: "M4 5.5a1.5 1.5 0 1 1 0 3 1.5 1.5 0 0 1 0-3zm4 .5h13v2H8V6zm-4 4.5a1.5 1.5 0 1 1 0 3 1.5 1.5 0 0 1 0-3zm4 .5h13v2H8v-2zm-4 4.5a1.5 1.5 0 1 1 0 3 1.5 1.5 0 0 1 0-3zm4 .5h13v2H8v-2z" }),
77
+ orderedList: /* @__PURE__ */ jsx("path", { d: "M3 6h1V3H2v1h1v2zm5 0h13v2H8V6zm0 5h13v2H8v-2zm0 5h13v2H8v-2zM2 12.8h2v.5H3v.5h1v.5H2v.7h3v-3H2v.8zm1 4.2H2v.8h1.8v.4L2 19v.9h3V17H4l-1 .5V17z" }),
78
+ taskList: /* @__PURE__ */ jsx("path", { d: "M3 5h6v6H3V5zm2 2v2h2V7H5zm6-1h10v2H11V6zm0 5h10v2H11v-2zm0 5h10v2H11v-2zM3 15.4l1.4-1.4 1.1 1.1 2.6-2.6L9.5 14l-4 4L3 15.4z" }),
79
+ indent: /* @__PURE__ */ jsx("path", { d: "M3 4h18v2H3V4zm8 5h10v2H11V9zm0 5h10v2H11v-2zm-8 5h18v2H3v-2zm0-9 4 3-4 3V10z" }),
80
+ outdent: /* @__PURE__ */ jsx("path", { d: "M3 4h18v2H3V4zm8 5h10v2H11V9zm0 5h10v2H11v-2zm-8 5h18v2H3v-2zM7 10v6l-4-3 4-3z" }),
81
+ blockquote: /* @__PURE__ */ jsx("path", { d: "M7 7c-2 0-3.5 1.6-3.5 3.6 0 1.8 1.3 3 2.9 3 .2 0 .4 0 .6-.1-.4 1-1.4 1.8-2.5 2.1l.6 1.4C7.7 16.9 9.5 14.8 9.5 12 9.5 9.2 8.4 7 7 7zm9 0c-2 0-3.5 1.6-3.5 3.6 0 1.8 1.3 3 2.9 3 .2 0 .4 0 .6-.1-.4 1-1.4 1.8-2.5 2.1l.6 1.4c2.1-.6 3.9-2.7 3.9-5.5C18.5 9.2 17.4 7 16 7z" }),
82
+ horizontalRule: /* @__PURE__ */ jsx("path", { d: "M3 11h18v2H3v-2z" }),
83
+ link: /* @__PURE__ */ jsx("path", { d: "M10.6 13.4a1 1 0 0 0 1.4 0l3-3a3 3 0 0 0-4.3-4.3l-1.5 1.5 1.4 1.4 1.5-1.5a1 1 0 0 1 1.5 1.5l-3 3a1 1 0 0 0 0 1.4zm2.8-2.8a1 1 0 0 0-1.4 0l-3 3A3 3 0 0 0 13.3 18l1.5-1.5-1.4-1.4-1.5 1.5a1 1 0 0 1-1.5-1.5l3-3a1 1 0 0 0 0-1.4z" }),
84
+ image: /* @__PURE__ */ jsx("path", { d: "M4 4h16a1 1 0 0 1 1 1v14a1 1 0 0 1-1 1H4a1 1 0 0 1-1-1V5a1 1 0 0 1 1-1zm1 2v9l4-4 3 3 3-3 3 3V6H5zm3 1.5a1.5 1.5 0 1 1 0 3 1.5 1.5 0 0 1 0-3z" }),
85
+ table: /* @__PURE__ */ jsx("path", { d: "M3 4h18v16H3V4zm2 2v3h5V6H5zm7 0v3h7V6h-7zm-7 5v3h5v-3H5zm7 0v3h7v-3h-7zm-7 5v2h5v-2H5zm7 0v2h7v-2h-7z" }),
86
+ pageBreak: /* @__PURE__ */ jsx("path", { d: "M6 3h8l4 4v4h-2V8h-3V5H6v6H4V3h2zm-2 13h2v2h2v-2h2v2h2v-2h2v2h2v-2h2v5H4v-5z" }),
87
+ importDocx: /* @__PURE__ */ jsx("path", { d: "M5 3h9l5 5v6h-2V9h-4V5H7v14h5v2H5V3zm8 11 4 4 4-4h-3v-4h-2v4h-3z" })
88
+ };
89
+ function ToolbarIcon({ name }) {
90
+ const path = PATHS[name];
91
+ if (!path) {
92
+ return /* @__PURE__ */ jsx("span", { "aria-hidden": "true", children: name.slice(0, 2) });
93
+ }
94
+ return /* @__PURE__ */ jsx("svg", { className: "rne-btn-icon", viewBox: "0 0 24 24", "aria-hidden": "true", focusable: "false", children: path });
95
+ }
96
+ function ToolbarButton({ iconName, label, command }) {
97
+ const { state, run } = useEditorContext();
98
+ const active = state ? command.isActive?.(state) ?? false : false;
99
+ const enabled = state ? command.isEnabled ? command.isEnabled(state) : true : false;
100
+ return /* @__PURE__ */ jsx(
101
+ "button",
102
+ {
103
+ type: "button",
104
+ className: `rne-btn${active ? " rne-btn--active" : ""}`,
105
+ title: label,
106
+ "aria-label": label,
107
+ "aria-pressed": command.isActive ? active : void 0,
108
+ disabled: !enabled,
109
+ onMouseDown: (e) => e.preventDefault(),
110
+ onClick: () => run(command.run),
111
+ children: /* @__PURE__ */ jsx(ToolbarIcon, { name: iconName })
112
+ }
113
+ );
114
+ }
115
+ function ColorButton({ iconName, label, apply, clear, activeColor }) {
116
+ const { run, colorPalette } = useEditorContext();
117
+ const [open, setOpen] = useState(false);
118
+ const containerRef = useRef(null);
119
+ const buttonRef = useRef(null);
120
+ useEffect(() => {
121
+ if (!open) return;
122
+ const onDown = (e) => {
123
+ if (containerRef.current && !containerRef.current.contains(e.target)) {
124
+ setOpen(false);
125
+ }
126
+ };
127
+ document.addEventListener("mousedown", onDown);
128
+ return () => document.removeEventListener("mousedown", onDown);
129
+ }, [open]);
130
+ return /* @__PURE__ */ jsxs("div", { className: "rne-color-btn", ref: containerRef, children: [
131
+ /* @__PURE__ */ jsx(
132
+ "button",
133
+ {
134
+ ref: buttonRef,
135
+ type: "button",
136
+ className: "rne-btn",
137
+ title: label,
138
+ "aria-label": label,
139
+ "aria-haspopup": "true",
140
+ "aria-expanded": open,
141
+ onMouseDown: (e) => e.preventDefault(),
142
+ onClick: () => setOpen((v) => !v),
143
+ children: /* @__PURE__ */ jsxs("span", { style: { display: "flex", flexDirection: "column", alignItems: "center" }, children: [
144
+ /* @__PURE__ */ jsx(ToolbarIcon, { name: iconName }),
145
+ /* @__PURE__ */ jsx("span", { className: "rne-color-swatch", style: { background: activeColor ?? "#000" } })
146
+ ] })
147
+ }
148
+ ),
149
+ open && /* @__PURE__ */ jsxs(
150
+ "div",
151
+ {
152
+ className: "rne-color-popover",
153
+ role: "menu",
154
+ onKeyDown: (e) => {
155
+ if (e.key === "Escape") {
156
+ setOpen(false);
157
+ buttonRef.current?.focus();
158
+ }
159
+ },
160
+ children: [
161
+ colorPalette.map((color) => /* @__PURE__ */ jsx(
162
+ "button",
163
+ {
164
+ type: "button",
165
+ className: "rne-color-cell",
166
+ style: { background: color },
167
+ title: color,
168
+ "aria-label": color,
169
+ onMouseDown: (e) => e.preventDefault(),
170
+ onClick: () => {
171
+ run(apply(color));
172
+ setOpen(false);
173
+ }
174
+ },
175
+ color
176
+ )),
177
+ clear && /* @__PURE__ */ jsx(
178
+ "button",
179
+ {
180
+ type: "button",
181
+ className: "rne-color-cell",
182
+ style: { background: "#fff", gridColumn: "span 8", height: 22 },
183
+ onMouseDown: (e) => e.preventDefault(),
184
+ onClick: () => {
185
+ run(clear());
186
+ setOpen(false);
187
+ },
188
+ children: "\u2715"
189
+ }
190
+ )
191
+ ]
192
+ }
193
+ )
194
+ ] });
195
+ }
196
+ var FEATURE_OF = {
197
+ bold: "bold",
198
+ italic: "italic",
199
+ underline: "underline",
200
+ strikethrough: "strikethrough",
201
+ superscript: "superscript",
202
+ subscript: "subscript",
203
+ code: "code",
204
+ paragraphStyle: "headings",
205
+ fontFamily: "fontFamily",
206
+ fontSize: "fontSize",
207
+ textColor: "textColor",
208
+ highlight: "highlight",
209
+ clearFormatting: "clearFormatting",
210
+ alignLeft: "alignment",
211
+ alignCenter: "alignment",
212
+ alignRight: "alignment",
213
+ alignJustify: "alignment",
214
+ bulletList: "bulletList",
215
+ orderedList: "orderedList",
216
+ taskList: "taskList",
217
+ indent: "indentation",
218
+ outdent: "indentation",
219
+ blockquote: "blockquote",
220
+ horizontalRule: "horizontalRule",
221
+ link: "link",
222
+ image: "image",
223
+ table: "table",
224
+ pageBreak: "pageBreak",
225
+ importDocx: "docxImport",
226
+ undo: "history",
227
+ redo: "history"
228
+ };
229
+ var COMMAND_ITEMS = /* @__PURE__ */ new Set([
230
+ "undo",
231
+ "redo",
232
+ "bold",
233
+ "italic",
234
+ "underline",
235
+ "strikethrough",
236
+ "superscript",
237
+ "subscript",
238
+ "code",
239
+ "clearFormatting",
240
+ "alignLeft",
241
+ "alignCenter",
242
+ "alignRight",
243
+ "alignJustify",
244
+ "bulletList",
245
+ "orderedList",
246
+ "taskList",
247
+ "indent",
248
+ "outdent",
249
+ "blockquote",
250
+ "horizontalRule",
251
+ "pageBreak"
252
+ ]);
253
+ function activeBlockValue(state) {
254
+ if (!state) return "p";
255
+ const node = state.selection.$head.parent;
256
+ if (node.type.name === "heading") return `h${node.attrs.level}`;
257
+ return "p";
258
+ }
259
+ function Toolbar({ config }) {
260
+ const ctx = useEditorContext();
261
+ const { state, commands, strings, features, run, fontFamilies, fontSizes, importDocx: importDocx2 } = ctx;
262
+ const groups = config?.groups ?? DEFAULT_TOOLBAR_GROUPS;
263
+ const sticky = config?.sticky ?? true;
264
+ const toolbarRef = useRef(null);
265
+ const fileInputRef = useRef(null);
266
+ const onImportFile = useCallback(
267
+ async (e) => {
268
+ const file = e.target.files?.[0];
269
+ e.target.value = "";
270
+ if (!file) return;
271
+ try {
272
+ await importDocx2(file);
273
+ } catch (err) {
274
+ console.error("[react-next-editor] DOCX import failed:", err);
275
+ }
276
+ },
277
+ [importDocx2]
278
+ );
279
+ const onToolbarKeyDown = useCallback((e) => {
280
+ if (!["ArrowLeft", "ArrowRight", "Home", "End"].includes(e.key)) return;
281
+ const active = document.activeElement;
282
+ if (active?.tagName === "SELECT") return;
283
+ const root = toolbarRef.current;
284
+ if (!root) return;
285
+ const items = Array.from(root.querySelectorAll("button:not([disabled])"));
286
+ if (items.length === 0) return;
287
+ const idx = active ? items.indexOf(active) : -1;
288
+ if (idx === -1) return;
289
+ e.preventDefault();
290
+ let next = idx;
291
+ if (e.key === "ArrowRight") next = (idx + 1) % items.length;
292
+ else if (e.key === "ArrowLeft") next = (idx - 1 + items.length) % items.length;
293
+ else if (e.key === "Home") next = 0;
294
+ else if (e.key === "End") next = items.length - 1;
295
+ items[next]?.focus();
296
+ }, []);
297
+ const renderedGroups = useMemo(() => {
298
+ return groups.map((group) => group.filter((id) => isItemAvailable(id, features, commands))).filter((group) => group.length > 0);
299
+ }, [groups, features, commands]);
300
+ const labelFor = (id) => strings[id] ?? id;
301
+ function renderItem(id) {
302
+ if (COMMAND_ITEMS.has(id)) {
303
+ const command = commands.registry[id];
304
+ if (!command) return null;
305
+ return /* @__PURE__ */ jsx(ToolbarButton, { iconName: id, label: labelFor(id), command }, id);
306
+ }
307
+ switch (id) {
308
+ case "paragraphStyle":
309
+ return /* @__PURE__ */ jsxs(
310
+ "select",
311
+ {
312
+ className: "rne-select",
313
+ "aria-label": strings.paragraphStyle,
314
+ value: activeBlockValue(state),
315
+ onMouseDown: (e) => e.stopPropagation(),
316
+ onChange: (e) => {
317
+ const v = e.target.value;
318
+ if (v === "p") run(commands.blocks.setParagraph());
319
+ else run(commands.blocks.setHeading(Number(v.slice(1))));
320
+ },
321
+ children: [
322
+ /* @__PURE__ */ jsx("option", { value: "p", children: strings.paragraph }),
323
+ [1, 2, 3, 4, 5, 6].map((lvl) => /* @__PURE__ */ jsx("option", { value: `h${lvl}`, children: `${strings.heading} ${lvl}` }, lvl))
324
+ ]
325
+ },
326
+ id
327
+ );
328
+ case "fontFamily":
329
+ return /* @__PURE__ */ jsxs(
330
+ "select",
331
+ {
332
+ className: "rne-select",
333
+ "aria-label": strings.fontFamily,
334
+ value: state ? commands.marks.getActiveFontFamily(state) ?? "" : "",
335
+ onChange: (e) => {
336
+ const v = e.target.value;
337
+ run(v ? commands.marks.setFontFamily(v) : commands.marks.clearFontFamily());
338
+ },
339
+ children: [
340
+ /* @__PURE__ */ jsx("option", { value: "", children: strings.fontFamily }),
341
+ fontFamilies.map((f) => /* @__PURE__ */ jsx("option", { value: f, style: { fontFamily: f }, children: f }, f))
342
+ ]
343
+ },
344
+ id
345
+ );
346
+ case "fontSize":
347
+ return /* @__PURE__ */ jsxs(
348
+ "select",
349
+ {
350
+ className: "rne-select",
351
+ style: { maxWidth: 70 },
352
+ "aria-label": strings.fontSize,
353
+ value: state ? commands.marks.getActiveFontSize(state) ?? "" : "",
354
+ onChange: (e) => {
355
+ const v = e.target.value;
356
+ run(v ? commands.marks.setFontSize(Number(v)) : commands.marks.clearFontSize());
357
+ },
358
+ children: [
359
+ /* @__PURE__ */ jsx("option", { value: "", children: strings.fontSize }),
360
+ fontSizes.map((s) => /* @__PURE__ */ jsx("option", { value: s, children: s }, s))
361
+ ]
362
+ },
363
+ id
364
+ );
365
+ case "textColor":
366
+ return /* @__PURE__ */ jsx(
367
+ ColorButton,
368
+ {
369
+ iconName: "textColor",
370
+ label: strings.textColor,
371
+ apply: (c) => commands.marks.setTextColor(c),
372
+ clear: () => commands.marks.clearTextColor(),
373
+ activeColor: state ? commands.marks.getActiveTextColor(state) : null
374
+ },
375
+ id
376
+ );
377
+ case "highlight":
378
+ return /* @__PURE__ */ jsx(
379
+ ColorButton,
380
+ {
381
+ iconName: "highlight",
382
+ label: strings.highlight,
383
+ apply: (c) => commands.marks.setHighlight(c),
384
+ clear: () => commands.marks.clearHighlight()
385
+ },
386
+ id
387
+ );
388
+ case "link":
389
+ return /* @__PURE__ */ jsx(
390
+ "button",
391
+ {
392
+ type: "button",
393
+ className: "rne-btn",
394
+ title: strings.link,
395
+ "aria-label": strings.link,
396
+ onMouseDown: (e) => e.preventDefault(),
397
+ onClick: () => {
398
+ if (!state) return;
399
+ const prev = commands.links.getActiveLink(state);
400
+ const url = window.prompt(strings.linkPrompt, prev?.href ?? "https://");
401
+ if (url === null) return;
402
+ if (url.trim() === "") run(commands.links.removeLink);
403
+ else run(commands.links.setLink({ href: url.trim() }));
404
+ },
405
+ children: /* @__PURE__ */ jsx(ToolbarIcon, { name: "link" })
406
+ },
407
+ id
408
+ );
409
+ case "image":
410
+ return /* @__PURE__ */ jsx(
411
+ "button",
412
+ {
413
+ type: "button",
414
+ className: "rne-btn",
415
+ title: strings.image,
416
+ "aria-label": strings.image,
417
+ onMouseDown: (e) => e.preventDefault(),
418
+ onClick: () => {
419
+ const url = window.prompt(strings.imagePrompt, "https://");
420
+ if (!url || !url.trim()) return;
421
+ const alt = window.prompt(strings.imageAltPrompt, "");
422
+ run(commands.insert.image({ src: url.trim(), alt: alt?.trim() || null }));
423
+ },
424
+ children: /* @__PURE__ */ jsx(ToolbarIcon, { name: "image" })
425
+ },
426
+ id
427
+ );
428
+ case "table":
429
+ return /* @__PURE__ */ jsx(
430
+ "button",
431
+ {
432
+ type: "button",
433
+ className: "rne-btn",
434
+ title: strings.insertTable,
435
+ "aria-label": strings.insertTable,
436
+ onMouseDown: (e) => e.preventDefault(),
437
+ onClick: () => run(commands.insert.table(3, 3, true)),
438
+ children: /* @__PURE__ */ jsx(ToolbarIcon, { name: "table" })
439
+ },
440
+ id
441
+ );
442
+ case "importDocx":
443
+ return /* @__PURE__ */ jsx(
444
+ "button",
445
+ {
446
+ type: "button",
447
+ className: "rne-btn",
448
+ title: strings.importDocx,
449
+ "aria-label": strings.importDocx,
450
+ onMouseDown: (e) => e.preventDefault(),
451
+ onClick: () => fileInputRef.current?.click(),
452
+ children: /* @__PURE__ */ jsx(ToolbarIcon, { name: "importDocx" })
453
+ },
454
+ id
455
+ );
456
+ default:
457
+ return null;
458
+ }
459
+ }
460
+ return /* @__PURE__ */ jsxs(
461
+ "div",
462
+ {
463
+ ref: toolbarRef,
464
+ className: `rne-toolbar${sticky ? " rne-toolbar--sticky" : ""}`,
465
+ role: "toolbar",
466
+ "aria-label": "Formatting",
467
+ onKeyDown: onToolbarKeyDown,
468
+ children: [
469
+ renderedGroups.map((group, gi) => /* @__PURE__ */ jsxs(Fragment, { children: [
470
+ gi > 0 && /* @__PURE__ */ jsx("span", { className: "rne-toolbar-separator", "aria-hidden": "true" }),
471
+ /* @__PURE__ */ jsx("div", { className: "rne-toolbar-group", children: group.map(renderItem) })
472
+ ] }, gi)),
473
+ /* @__PURE__ */ jsx(
474
+ "input",
475
+ {
476
+ ref: fileInputRef,
477
+ type: "file",
478
+ accept: ".docx,application/vnd.openxmlformats-officedocument.wordprocessingml.document",
479
+ style: { display: "none" },
480
+ "aria-hidden": "true",
481
+ tabIndex: -1,
482
+ onChange: onImportFile
483
+ }
484
+ )
485
+ ]
486
+ }
487
+ );
488
+ }
489
+ function isItemAvailable(id, features, commands) {
490
+ if (id === "separator") return false;
491
+ const feature = FEATURE_OF[id];
492
+ if (feature && !features[feature]) return false;
493
+ if (COMMAND_ITEMS.has(id) && !commands.registry[id]) return false;
494
+ return true;
495
+ }
496
+ var STATUS_LABEL = {
497
+ idle: "",
498
+ savingLocal: "Saving\u2026",
499
+ savedLocal: "Saved locally",
500
+ syncing: "Syncing\u2026",
501
+ synced: "Synced",
502
+ syncFailed: "Sync failed",
503
+ offline: "Offline"
504
+ };
505
+ function StatusBar({ saveStatus, hasPersistence }) {
506
+ const { state, strings } = useEditorContext();
507
+ const doc = state?.doc;
508
+ const [stats, setStats] = useState(null);
509
+ useEffect(() => {
510
+ if (!doc) {
511
+ setStats(null);
512
+ return;
513
+ }
514
+ const id = setTimeout(() => setStats(countDocument(doc)), 300);
515
+ return () => clearTimeout(id);
516
+ }, [doc]);
517
+ return /* @__PURE__ */ jsxs("div", { className: "rne-statusbar", children: [
518
+ /* @__PURE__ */ jsx("span", { children: stats ? `${stats.words} ${strings.words} \xB7 ${stats.characters} ${strings.characters}` : "" }),
519
+ hasPersistence && saveStatus !== "idle" && /* @__PURE__ */ jsxs("span", { className: "rne-status-badge", children: [
520
+ /* @__PURE__ */ jsx("span", { className: `rne-status-dot rne-status-dot--${saveStatus}` }),
521
+ STATUS_LABEL[saveStatus]
522
+ ] })
523
+ ] });
524
+ }
525
+ function resolveConfig(props) {
526
+ return {
527
+ features: { ...DEFAULT_FEATURES, ...props.features },
528
+ page: {
529
+ ...DEFAULT_PAGE,
530
+ ...props.page,
531
+ margins: { ...DEFAULT_PAGE.margins, ...props.page?.margins }
532
+ },
533
+ strings: { ...DEFAULT_STRINGS, ...props.strings },
534
+ fontFamilies: props.fontFamilies ?? DEFAULT_FONT_FAMILIES,
535
+ fontSizes: props.fontSizes ?? DEFAULT_FONT_SIZES,
536
+ colorPalette: props.colorPalette ?? DEFAULT_COLOR_PALETTE,
537
+ editable: !(props.readOnly || props.mode === "readonly"),
538
+ placeholder: props.placeholder
539
+ };
540
+ }
541
+ var PX_PER_MM = 96 / 25.4;
542
+ var PAGE_GAP_PX = 24;
543
+ function computePaginationGeometry(page) {
544
+ if (page.pagination !== "visual") return null;
545
+ const { width, height } = resolvePageDimensions(page);
546
+ const m = page.margins;
547
+ const pageWidthPx = width * PX_PER_MM;
548
+ const pageHeightPx = height * PX_PER_MM;
549
+ const marginTopPx = m.top * PX_PER_MM;
550
+ const marginBottomPx = m.bottom * PX_PER_MM;
551
+ const marginLeftPx = m.left * PX_PER_MM;
552
+ const contentWidthPx = Math.max(1, (width - m.left - m.right) * PX_PER_MM);
553
+ const contentHeightPx = pageHeightPx - marginTopPx - marginBottomPx;
554
+ if (contentHeightPx <= 0) return null;
555
+ return {
556
+ pageWidthPx,
557
+ pageHeightPx,
558
+ marginTopPx,
559
+ marginBottomPx,
560
+ marginLeftPx,
561
+ contentWidthPx,
562
+ contentHeightPx,
563
+ interPageOffsetPx: marginBottomPx + PAGE_GAP_PX + marginTopPx
564
+ };
565
+ }
566
+ var EditorInner = forwardRef(function EditorInner2(props, ref) {
567
+ const mountRef = useRef(null);
568
+ const viewRef = useRef(null);
569
+ const persistenceRef = useRef(null);
570
+ const pageBgRef = useRef(null);
571
+ const remeasureRef = useRef(null);
572
+ const propsRef = useRef(props);
573
+ propsRef.current = props;
574
+ const config = useMemo(() => resolveConfig(props), [props]);
575
+ const cfgRef = useRef(config);
576
+ cfgRef.current = config;
577
+ const featureKey = useMemo(() => JSON.stringify(config.features), [config.features]);
578
+ const engine = useMemo(() => {
579
+ const schema = buildSchema(config.features);
580
+ const commands = createCommands(schema);
581
+ return { schema, commands };
582
+ }, [featureKey]);
583
+ const [editorState, setEditorState] = useState(null);
584
+ const [saveStatus, setSaveStatus] = useState("idle");
585
+ const [ready, setReady] = useState(false);
586
+ const getJSON = useCallback(() => {
587
+ const view = viewRef.current;
588
+ return view ? view.state.doc.toJSON() : createDoc(engine.schema, null).toJSON();
589
+ }, [engine.schema]);
590
+ const setContent = useCallback(
591
+ (content) => {
592
+ const view = viewRef.current;
593
+ if (!view) return;
594
+ const doc = createDoc(view.state.schema, content);
595
+ const state = EditorState.create({ doc, plugins: view.state.plugins });
596
+ view.updateState(state);
597
+ setEditorState(state);
598
+ },
599
+ []
600
+ );
601
+ const importDocxIntoEditor = useCallback(
602
+ async (file) => {
603
+ const view = viewRef.current;
604
+ if (!view) return { warnings: [] };
605
+ const { importDocx: importDocx2 } = await import('./docx-LDETXV3L.js');
606
+ const result = await importDocx2(file, view.state.schema);
607
+ const node = Node.fromJSON(view.state.schema, result.doc);
608
+ const v = viewRef.current;
609
+ if (v) {
610
+ const tr = v.state.tr.replaceWith(0, v.state.doc.content.size, node.content);
611
+ v.dispatch(tr.scrollIntoView());
612
+ }
613
+ return { warnings: result.warnings };
614
+ },
615
+ []
616
+ );
617
+ const handle = useMemo(
618
+ () => ({
619
+ getJSON,
620
+ getText: (options) => documentToText(getJSON(), options),
621
+ getHTML: () => documentToHtml(getJSON()),
622
+ setContent,
623
+ importDocx: importDocxIntoEditor,
624
+ focus: () => viewRef.current?.focus(),
625
+ isDirty: () => persistenceRef.current?.isDirty() ?? false,
626
+ save: async () => {
627
+ await persistenceRef.current?.saveNow(getJSON());
628
+ },
629
+ clearLocalData: async () => {
630
+ await persistenceRef.current?.clearLocal();
631
+ },
632
+ exportAs: (format, filename) => exportDocument(getJSON(), format, {
633
+ filename: filename ?? propsRef.current.documentId,
634
+ page: cfgRef.current.page,
635
+ title: filename ?? propsRef.current.documentId
636
+ }),
637
+ getView: () => viewRef.current,
638
+ getState: () => viewRef.current?.state ?? null,
639
+ getSchema: () => viewRef.current?.state.schema ?? null
640
+ }),
641
+ [getJSON, setContent, importDocxIntoEditor]
642
+ );
643
+ useImperativeHandle(ref, () => handle, [handle]);
644
+ useEffect(() => {
645
+ const mount = mountRef.current;
646
+ if (!mount) return;
647
+ void preloadSanitizer();
648
+ const paginated2 = cfgRef.current.page.pagination === "visual";
649
+ const plugins = buildPlugins(engine.schema, {
650
+ placeholder: cfgRef.current.placeholder,
651
+ history: cfgRef.current.features.history,
652
+ extraPlugins: propsRef.current.extensions?.plugins,
653
+ pagination: paginated2 ? {
654
+ getGeometry: () => computePaginationGeometry(cfgRef.current.page),
655
+ getBackgroundLayer: () => pageBgRef.current,
656
+ header: cfgRef.current.page.header,
657
+ footer: cfgRef.current.page.footer,
658
+ register: (fn) => {
659
+ remeasureRef.current = fn;
660
+ }
661
+ } : void 0
662
+ });
663
+ const initialContent = propsRef.current.value ?? propsRef.current.initialContent ?? null;
664
+ const state = createEditorState({ schema: engine.schema, plugins, content: initialContent });
665
+ const view = new EditorView(mount, {
666
+ state,
667
+ editable: () => !(propsRef.current.readOnly || propsRef.current.mode === "readonly"),
668
+ attributes: {
669
+ class: "rne-prosemirror",
670
+ role: "textbox",
671
+ "aria-multiline": "true",
672
+ "aria-label": propsRef.current.ariaLabel ?? "Document editor",
673
+ dir: propsRef.current.dir ?? "ltr"
674
+ },
675
+ dispatchTransaction(tr) {
676
+ const v = viewRef.current;
677
+ if (!v) return;
678
+ const newState = v.state.apply(tr);
679
+ v.updateState(newState);
680
+ setEditorState(newState);
681
+ const p = propsRef.current;
682
+ if (tr.docChanged) {
683
+ const json = newState.doc.toJSON();
684
+ p.onChange?.(json, handle);
685
+ persistenceRef.current?.scheduleSave(json);
686
+ }
687
+ if (tr.selectionSet) {
688
+ p.onSelectionChange?.(newState);
689
+ }
690
+ }
691
+ });
692
+ viewRef.current = view;
693
+ setEditorState(view.state);
694
+ setReady(true);
695
+ propsRef.current.onReady?.(handle);
696
+ return () => {
697
+ view.destroy();
698
+ viewRef.current = null;
699
+ setReady(false);
700
+ };
701
+ }, [engine]);
702
+ useEffect(() => {
703
+ viewRef.current?.setProps({
704
+ editable: () => config.editable
705
+ });
706
+ setEditorState((s) => s);
707
+ }, [config.editable]);
708
+ useEffect(() => {
709
+ const documentId = props.documentId;
710
+ const persistenceEnabled = props.persistence?.enabled ?? !!documentId;
711
+ if (!documentId || !persistenceEnabled || !ready) return;
712
+ const store = props.persistence?.store ?? new IndexedDBStore();
713
+ const sync = props.sync;
714
+ const auto = sync?.auto ?? true;
715
+ let engine2 = null;
716
+ let monitor = null;
717
+ const handleStatus = (status, detail) => {
718
+ setSaveStatus(status);
719
+ propsRef.current.onSaveStatusChange?.(status, detail);
720
+ if (status === "savedLocal" && engine2 && auto && (monitor?.isOnline() ?? true)) {
721
+ void engine2.flush();
722
+ }
723
+ };
724
+ const persistence = new DocumentPersistence({
725
+ documentId,
726
+ store,
727
+ debounceMs: props.persistence?.debounceMs,
728
+ metadata: props.metadata,
729
+ onStatus: handleStatus
730
+ });
731
+ persistenceRef.current = persistence;
732
+ if (sync?.remote) {
733
+ engine2 = new SyncEngine({
734
+ store,
735
+ remote: sync.remote,
736
+ maxAttempts: sync.maxAttempts,
737
+ onStatus: handleStatus,
738
+ onConflict: sync.onConflict
739
+ });
740
+ const remotePing = sync.remote.ping?.bind(sync.remote);
741
+ monitor = new ConnectivityMonitor({
742
+ ping: remotePing,
743
+ intervalMs: sync.pingIntervalMs,
744
+ onChange: (online) => {
745
+ if (online) {
746
+ if (auto && engine2) void engine2.flush();
747
+ } else {
748
+ handleStatus("offline");
749
+ }
750
+ }
751
+ });
752
+ monitor.start();
753
+ if (auto) void engine2.flush();
754
+ }
755
+ if (props.persistence?.requestPersistent !== false) {
756
+ void requestPersistentStorage();
757
+ }
758
+ let cancelled = false;
759
+ void (async () => {
760
+ const record = await persistence.load();
761
+ if (cancelled || !record) return;
762
+ if (propsRef.current.value == null) {
763
+ setContent(record.doc);
764
+ }
765
+ })();
766
+ return () => {
767
+ cancelled = true;
768
+ monitor?.stop();
769
+ engine2?.cancel();
770
+ void persistence.destroy();
771
+ persistenceRef.current = null;
772
+ };
773
+ }, [props.documentId, ready, props.sync?.remote]);
774
+ useEffect(() => {
775
+ const view = viewRef.current;
776
+ if (!view || props.value == null) return;
777
+ const current = JSON.stringify(view.state.doc.toJSON());
778
+ const next = JSON.stringify(props.value);
779
+ if (current === next) return;
780
+ const doc = createDoc(view.state.schema, props.value);
781
+ const selectionPos = Math.min(view.state.selection.from, doc.content.size);
782
+ const state = EditorState.create({ doc, plugins: view.state.plugins });
783
+ const withSel = state.apply(
784
+ state.tr.setSelection(TextSelection.create(state.doc, Math.max(0, selectionPos)))
785
+ );
786
+ view.updateState(withSel);
787
+ setEditorState(withSel);
788
+ }, [props.value]);
789
+ const runCommand = useCallback((command) => {
790
+ const view = viewRef.current;
791
+ if (!view) return false;
792
+ const result = command(view.state, view.dispatch, view);
793
+ view.focus();
794
+ return result;
795
+ }, []);
796
+ const contextValue = useMemo(
797
+ () => ({
798
+ view: viewRef.current,
799
+ state: editorState,
800
+ schema: engine.schema,
801
+ commands: engine.commands,
802
+ strings: config.strings,
803
+ features: config.features,
804
+ fontFamilies: config.fontFamilies,
805
+ fontSizes: config.fontSizes,
806
+ colorPalette: config.colorPalette,
807
+ editable: config.editable,
808
+ run: runCommand,
809
+ importDocx: importDocxIntoEditor
810
+ }),
811
+ [editorState, engine, config, runCommand, importDocxIntoEditor]
812
+ );
813
+ const { width } = resolvePageDimensions(config.page);
814
+ const showChrome = config.page.showPageChrome;
815
+ const paginated = config.page.pagination === "visual";
816
+ const pageGeometryKey = useMemo(
817
+ () => JSON.stringify({
818
+ p: config.page.pagination,
819
+ s: config.page.size,
820
+ o: config.page.orientation,
821
+ w: config.page.widthMm,
822
+ h: config.page.heightMm,
823
+ m: config.page.margins,
824
+ hdr: config.page.header,
825
+ ftr: config.page.footer
826
+ }),
827
+ [config.page]
828
+ );
829
+ useEffect(() => {
830
+ if (paginated) remeasureRef.current?.();
831
+ }, [pageGeometryKey, paginated]);
832
+ const geometry = useMemo(
833
+ () => computePaginationGeometry(config.page),
834
+ // eslint-disable-next-line react-hooks/exhaustive-deps
835
+ [pageGeometryKey]
836
+ );
837
+ const rootStyle = useMemo(() => {
838
+ const base = {
839
+ ...themeToCssVars(props.theme),
840
+ "--rne-page-width": `${width}mm`,
841
+ "--rne-page-padding": `${config.page.margins.top}mm ${config.page.margins.right}mm ${config.page.margins.bottom}mm ${config.page.margins.left}mm`
842
+ };
843
+ if (geometry) {
844
+ base["--rne-page-w"] = `${geometry.pageWidthPx}px`;
845
+ base["--rne-page-h"] = `${geometry.pageHeightPx}px`;
846
+ base["--rne-content-w"] = `${geometry.contentWidthPx}px`;
847
+ base["--rne-mt"] = `${geometry.marginTopPx}px`;
848
+ base["--rne-ml"] = `${geometry.marginLeftPx}px`;
849
+ }
850
+ return { ...base, ...props.style };
851
+ }, [props.theme, props.style, width, config.page.margins, geometry]);
852
+ const toolbarEnabled = props.toolbar !== false && (props.toolbar?.enabled ?? true) && config.editable;
853
+ const statusBarEnabled = props.statusBar ?? true;
854
+ return /* @__PURE__ */ jsx(EditorContext.Provider, { value: contextValue, children: /* @__PURE__ */ jsxs(
855
+ "div",
856
+ {
857
+ className: `rne-root${props.className ? ` ${props.className}` : ""}`,
858
+ style: rootStyle,
859
+ "data-ready": ready,
860
+ dir: props.dir ?? "ltr",
861
+ children: [
862
+ toolbarEnabled && /* @__PURE__ */ jsx(Toolbar, { config: props.toolbar || void 0 }),
863
+ props.children,
864
+ /* @__PURE__ */ jsx(
865
+ "div",
866
+ {
867
+ className: `rne-canvas${showChrome ? "" : " rne-canvas--plain"}${paginated ? " rne-canvas--paged" : ""}`,
868
+ children: paginated ? /* @__PURE__ */ jsxs("div", { className: "rne-paged", children: [
869
+ /* @__PURE__ */ jsx("div", { ref: pageBgRef, className: "rne-page-bg", "aria-hidden": "true" }),
870
+ /* @__PURE__ */ jsx("div", { ref: mountRef, className: "rne-mount rne-mount--paged" })
871
+ ] }) : /* @__PURE__ */ jsx("div", { className: "rne-page", children: /* @__PURE__ */ jsx("div", { ref: mountRef, className: "rne-mount" }) })
872
+ }
873
+ ),
874
+ statusBarEnabled && /* @__PURE__ */ jsx(StatusBar, { saveStatus, hasPersistence: !!props.documentId })
875
+ ]
876
+ }
877
+ ) });
878
+ });
879
+ var Editor = forwardRef(function Editor2(props, ref) {
880
+ return /* @__PURE__ */ jsx(EditorErrorBoundary, { onError: props.onError, children: /* @__PURE__ */ jsx(EditorInner, { ...props, ref }) });
881
+ });
882
+
883
+ export { Editor, EditorContext, EditorErrorBoundary, StatusBar, Toolbar, ToolbarButton, ToolbarIcon, useEditorContext };
884
+ //# sourceMappingURL=index.js.map
885
+ //# sourceMappingURL=index.js.map