@portone/docx-editor 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 (347) hide show
  1. package/CHANGELOG.md +7 -0
  2. package/CONTRIBUTING.md +63 -0
  3. package/LICENSE +203 -0
  4. package/README.md +48 -0
  5. package/assets/editor.png +0 -0
  6. package/dist/DocxEditor.d.ts +123 -0
  7. package/dist/DocxEditor.js +348 -0
  8. package/dist/core.d.ts +36 -0
  9. package/dist/core.js +38 -0
  10. package/dist/docx/comments/constants.d.ts +8 -0
  11. package/dist/docx/comments/constants.js +20 -0
  12. package/dist/docx/comments/model.d.ts +37 -0
  13. package/dist/docx/comments/model.js +104 -0
  14. package/dist/docx/comments/reading.d.ts +36 -0
  15. package/dist/docx/comments/reading.js +149 -0
  16. package/dist/docx/comments/writing.d.ts +11 -0
  17. package/dist/docx/comments/writing.js +327 -0
  18. package/dist/docx/comments.d.ts +3 -0
  19. package/dist/docx/comments.js +4 -0
  20. package/dist/docx/container.d.ts +12 -0
  21. package/dist/docx/container.js +130 -0
  22. package/dist/docx/documentSettings.d.ts +4 -0
  23. package/dist/docx/documentSettings.js +14 -0
  24. package/dist/docx/exportDocx.d.ts +15 -0
  25. package/dist/docx/exportDocx.js +163 -0
  26. package/dist/docx/exportRefs.d.ts +16 -0
  27. package/dist/docx/exportRefs.js +10 -0
  28. package/dist/docx/formatting/direct.d.ts +30 -0
  29. package/dist/docx/formatting/direct.js +201 -0
  30. package/dist/docx/formatting/effectiveParagraph.d.ts +15 -0
  31. package/dist/docx/formatting/effectiveParagraph.js +81 -0
  32. package/dist/docx/formatting/styles.d.ts +67 -0
  33. package/dist/docx/formatting/styles.js +165 -0
  34. package/dist/docx/formatting/tabStops.d.ts +8 -0
  35. package/dist/docx/formatting/tabStops.js +65 -0
  36. package/dist/docx/formatting.d.ts +4 -0
  37. package/dist/docx/formatting.js +4 -0
  38. package/dist/docx/headersFooters.d.ts +36 -0
  39. package/dist/docx/headersFooters.js +218 -0
  40. package/dist/docx/hyperlink.d.ts +75 -0
  41. package/dist/docx/hyperlink.js +71 -0
  42. package/dist/docx/importDocx.d.ts +21 -0
  43. package/dist/docx/importDocx.js +263 -0
  44. package/dist/docx/importParagraph.d.ts +32 -0
  45. package/dist/docx/importParagraph.js +308 -0
  46. package/dist/docx/importTable.d.ts +9 -0
  47. package/dist/docx/importTable.js +275 -0
  48. package/dist/docx/media.d.ts +60 -0
  49. package/dist/docx/media.js +213 -0
  50. package/dist/docx/notes.d.ts +22 -0
  51. package/dist/docx/notes.js +71 -0
  52. package/dist/docx/pageGeometry.d.ts +75 -0
  53. package/dist/docx/pageGeometry.js +88 -0
  54. package/dist/docx/paraProps.d.ts +74 -0
  55. package/dist/docx/paraProps.js +167 -0
  56. package/dist/docx/propsXml.d.ts +49 -0
  57. package/dist/docx/propsXml.js +302 -0
  58. package/dist/docx/relationships.d.ts +42 -0
  59. package/dist/docx/relationships.js +94 -0
  60. package/dist/docx/runProps.d.ts +51 -0
  61. package/dist/docx/runProps.js +207 -0
  62. package/dist/docx/scan.d.ts +20 -0
  63. package/dist/docx/scan.js +110 -0
  64. package/dist/docx/sdt.d.ts +56 -0
  65. package/dist/docx/sdt.js +104 -0
  66. package/dist/docx/sdtProps.d.ts +18 -0
  67. package/dist/docx/sdtProps.js +11 -0
  68. package/dist/docx/serializeBlock.d.ts +4 -0
  69. package/dist/docx/serializeBlock.js +30 -0
  70. package/dist/docx/serializeParagraph.d.ts +15 -0
  71. package/dist/docx/serializeParagraph.js +208 -0
  72. package/dist/docx/serializeTable.d.ts +12 -0
  73. package/dist/docx/serializeTable.js +134 -0
  74. package/dist/docx/session.d.ts +81 -0
  75. package/dist/docx/session.js +79 -0
  76. package/dist/docx/tableFormatting/editing.d.ts +64 -0
  77. package/dist/docx/tableFormatting/editing.js +318 -0
  78. package/dist/docx/tableFormatting/reading.d.ts +96 -0
  79. package/dist/docx/tableFormatting/reading.js +221 -0
  80. package/dist/docx/tableFormatting.d.ts +2 -0
  81. package/dist/docx/tableFormatting.js +3 -0
  82. package/dist/docx/tableTemplate.d.ts +22 -0
  83. package/dist/docx/tableTemplate.js +111 -0
  84. package/dist/docx/theme.d.ts +40 -0
  85. package/dist/docx/theme.js +61 -0
  86. package/dist/docx/uniqueControls.d.ts +14 -0
  87. package/dist/docx/uniqueControls.js +62 -0
  88. package/dist/download.d.ts +57 -0
  89. package/dist/download.js +44 -0
  90. package/dist/editor/clipboard/images.d.ts +14 -0
  91. package/dist/editor/clipboard/images.js +158 -0
  92. package/dist/editor/clipboard/inlineFormatting.d.ts +21 -0
  93. package/dist/editor/clipboard/inlineFormatting.js +232 -0
  94. package/dist/editor/commands/breakCommands.d.ts +8 -0
  95. package/dist/editor/commands/breakCommands.js +19 -0
  96. package/dist/editor/commands/canRunCommand.d.ts +6 -0
  97. package/dist/editor/commands/canRunCommand.js +10 -0
  98. package/dist/editor/commands/commentCommands.d.ts +3 -0
  99. package/dist/editor/commands/commentCommands.js +4 -0
  100. package/dist/editor/commands/comments/editing.d.ts +21 -0
  101. package/dist/editor/commands/comments/editing.js +305 -0
  102. package/dist/editor/commands/comments/model.d.ts +31 -0
  103. package/dist/editor/commands/comments/model.js +0 -0
  104. package/dist/editor/commands/comments/reading.d.ts +8 -0
  105. package/dist/editor/commands/comments/reading.js +58 -0
  106. package/dist/editor/commands/formatting/editing.d.ts +32 -0
  107. package/dist/editor/commands/formatting/editing.js +138 -0
  108. package/dist/editor/commands/formatting/reading.d.ts +57 -0
  109. package/dist/editor/commands/formatting/reading.js +82 -0
  110. package/dist/editor/commands/formatting/shared.d.ts +32 -0
  111. package/dist/editor/commands/formatting/shared.js +53 -0
  112. package/dist/editor/commands/formattingCommands.d.ts +2 -0
  113. package/dist/editor/commands/formattingCommands.js +3 -0
  114. package/dist/editor/commands/historyCommands.d.ts +11 -0
  115. package/dist/editor/commands/historyCommands.js +16 -0
  116. package/dist/editor/commands/indentCommands.d.ts +15 -0
  117. package/dist/editor/commands/indentCommands.js +44 -0
  118. package/dist/editor/commands/index.d.ts +82 -0
  119. package/dist/editor/commands/index.js +171 -0
  120. package/dist/editor/commands/linkCommands.d.ts +56 -0
  121. package/dist/editor/commands/linkCommands.js +146 -0
  122. package/dist/editor/commands/listCommands.d.ts +58 -0
  123. package/dist/editor/commands/listCommands.js +140 -0
  124. package/dist/editor/commands/lockCommands.d.ts +47 -0
  125. package/dist/editor/commands/lockCommands.js +198 -0
  126. package/dist/editor/commands/noteQueries.d.ts +12 -0
  127. package/dist/editor/commands/noteQueries.js +29 -0
  128. package/dist/editor/commands/paragraphCommands.d.ts +59 -0
  129. package/dist/editor/commands/paragraphCommands.js +113 -0
  130. package/dist/editor/commands/spacingCommands.d.ts +23 -0
  131. package/dist/editor/commands/spacingCommands.js +48 -0
  132. package/dist/editor/commands/tabCommands.d.ts +5 -0
  133. package/dist/editor/commands/tabCommands.js +65 -0
  134. package/dist/editor/createEditor.d.ts +59 -0
  135. package/dist/editor/createEditor.js +160 -0
  136. package/dist/editor/documentStyles.d.ts +60 -0
  137. package/dist/editor/documentStyles.js +80 -0
  138. package/dist/editor/externalClipboard.d.ts +11 -0
  139. package/dist/editor/externalClipboard.js +323 -0
  140. package/dist/editor/imageFiles.d.ts +74 -0
  141. package/dist/editor/imageFiles.js +173 -0
  142. package/dist/editor/insertImage.d.ts +31 -0
  143. package/dist/editor/insertImage.js +35 -0
  144. package/dist/editor/insertTable.d.ts +18 -0
  145. package/dist/editor/insertTable.js +44 -0
  146. package/dist/editor/paragraphEdits.d.ts +42 -0
  147. package/dist/editor/paragraphEdits.js +59 -0
  148. package/dist/editor/plainText.d.ts +3 -0
  149. package/dist/editor/plainText.js +50 -0
  150. package/dist/editor/plugins/bookmarkProtection.d.ts +3 -0
  151. package/dist/editor/plugins/bookmarkProtection.js +28 -0
  152. package/dist/editor/plugins/columnResize.d.ts +27 -0
  153. package/dist/editor/plugins/columnResize.js +192 -0
  154. package/dist/editor/plugins/commentDecorations.d.ts +3 -0
  155. package/dist/editor/plugins/commentDecorations.js +23 -0
  156. package/dist/editor/plugins/commentReservations.d.ts +5 -0
  157. package/dist/editor/plugins/commentReservations.js +26 -0
  158. package/dist/editor/plugins/dropCaret.d.ts +10 -0
  159. package/dist/editor/plugins/dropCaret.js +11 -0
  160. package/dist/editor/plugins/imagePaste.d.ts +8 -0
  161. package/dist/editor/plugins/imagePaste.js +265 -0
  162. package/dist/editor/plugins/keymap.d.ts +5 -0
  163. package/dist/editor/plugins/keymap.js +94 -0
  164. package/dist/editor/plugins/linkPanel.d.ts +23 -0
  165. package/dist/editor/plugins/linkPanel.js +39 -0
  166. package/dist/editor/plugins/listInputRules.d.ts +14 -0
  167. package/dist/editor/plugins/listInputRules.js +36 -0
  168. package/dist/editor/plugins/lockedContent.d.ts +6 -0
  169. package/dist/editor/plugins/lockedContent.js +41 -0
  170. package/dist/editor/plugins/noteProtection.d.ts +3 -0
  171. package/dist/editor/plugins/noteProtection.js +25 -0
  172. package/dist/editor/plugins/numberingDecorations.d.ts +42 -0
  173. package/dist/editor/plugins/numberingDecorations.js +110 -0
  174. package/dist/editor/plugins/rowResize.d.ts +15 -0
  175. package/dist/editor/plugins/rowResize.js +196 -0
  176. package/dist/editor/plugins/styledParagraphs.d.ts +15 -0
  177. package/dist/editor/plugins/styledParagraphs.js +65 -0
  178. package/dist/editor/plugins/tabCaret.d.ts +3 -0
  179. package/dist/editor/plugins/tabCaret.js +126 -0
  180. package/dist/editor/plugins/tabDecorations.d.ts +11 -0
  181. package/dist/editor/plugins/tabDecorations.js +87 -0
  182. package/dist/editor/plugins/tabLayout.d.ts +16 -0
  183. package/dist/editor/plugins/tabLayout.js +328 -0
  184. package/dist/editor/plugins/tabPointer.d.ts +7 -0
  185. package/dist/editor/plugins/tabPointer.js +95 -0
  186. package/dist/editor/plugins/tableContextMenu.d.ts +21 -0
  187. package/dist/editor/plugins/tableContextMenu.js +88 -0
  188. package/dist/editor/plugins/textContextMenu.d.ts +15 -0
  189. package/dist/editor/plugins/textContextMenu.js +90 -0
  190. package/dist/editor/views/imageResize.d.ts +53 -0
  191. package/dist/editor/views/imageResize.js +167 -0
  192. package/dist/editor/views/runMarkView.d.ts +15 -0
  193. package/dist/editor/views/runMarkView.js +9 -0
  194. package/dist/editor/views/tableView.d.ts +24 -0
  195. package/dist/editor/views/tableView.js +32 -0
  196. package/dist/index.d.ts +44 -0
  197. package/dist/index.js +38 -0
  198. package/dist/model/format.d.ts +240 -0
  199. package/dist/model/format.js +305 -0
  200. package/dist/model/tabStops.d.ts +17 -0
  201. package/dist/model/tabStops.js +22 -0
  202. package/dist/numbering/listTemplate.d.ts +29 -0
  203. package/dist/numbering/listTemplate.js +83 -0
  204. package/dist/numbering/markers.d.ts +24 -0
  205. package/dist/numbering/markers.js +93 -0
  206. package/dist/numbering/parseNumbering.d.ts +65 -0
  207. package/dist/numbering/parseNumbering.js +116 -0
  208. package/dist/numbering/writeNumbering.d.ts +13 -0
  209. package/dist/numbering/writeNumbering.js +49 -0
  210. package/dist/ooxml/errors.d.ts +39 -0
  211. package/dist/ooxml/errors.js +21 -0
  212. package/dist/ooxml/image.d.ts +88 -0
  213. package/dist/ooxml/image.js +106 -0
  214. package/dist/ooxml/tabStops.d.ts +3 -0
  215. package/dist/ooxml/tabStops.js +51 -0
  216. package/dist/ooxml/units.d.ts +37 -0
  217. package/dist/ooxml/units.js +116 -0
  218. package/dist/ooxml/xml.d.ts +36 -0
  219. package/dist/ooxml/xml.js +89 -0
  220. package/dist/page/PageGuides.d.ts +16 -0
  221. package/dist/page/PageGuides.js +114 -0
  222. package/dist/page/measureBlocks.d.ts +25 -0
  223. package/dist/page/measureBlocks.js +80 -0
  224. package/dist/page/pageDecorations.d.ts +36 -0
  225. package/dist/page/pageDecorations.js +211 -0
  226. package/dist/page/pageLayout.d.ts +176 -0
  227. package/dist/page/pageLayout.js +157 -0
  228. package/dist/page/tableMeasurements.d.ts +10 -0
  229. package/dist/page/tableMeasurements.js +115 -0
  230. package/dist/page/usePageLayout.d.ts +57 -0
  231. package/dist/page/usePageLayout.js +141 -0
  232. package/dist/schema/docxSchema.d.ts +9 -0
  233. package/dist/schema/docxSchema.js +863 -0
  234. package/dist/schema/index.d.ts +2 -0
  235. package/dist/schema/index.js +9 -0
  236. package/dist/schema/locks.d.ts +112 -0
  237. package/dist/schema/locks.js +211 -0
  238. package/dist/schema/rendering.d.ts +6 -0
  239. package/dist/schema/rendering.js +46 -0
  240. package/dist/styles/classNames.d.ts +214 -0
  241. package/dist/styles/classNames.js +208 -0
  242. package/dist/styles/colors.d.ts +11 -0
  243. package/dist/styles/colors.js +14 -0
  244. package/dist/styles/fontSizes.d.ts +6 -0
  245. package/dist/styles/fontSizes.js +20 -0
  246. package/dist/styles/fontStack.d.ts +55 -0
  247. package/dist/styles/fontStack.js +262 -0
  248. package/dist/styles/fonts.d.ts +6 -0
  249. package/dist/styles/fonts.js +11 -0
  250. package/dist/styles/inlineStyle.d.ts +67 -0
  251. package/dist/styles/inlineStyle.js +212 -0
  252. package/dist/styles/lineSpacings.d.ts +11 -0
  253. package/dist/styles/lineSpacings.js +10 -0
  254. package/dist/styles.css +1650 -0
  255. package/dist/table/cellBorders.d.ts +12 -0
  256. package/dist/table/cellBorders.js +9 -0
  257. package/dist/table/cellFormatting.d.ts +57 -0
  258. package/dist/table/cellFormatting.js +173 -0
  259. package/dist/table/columns.d.ts +25 -0
  260. package/dist/table/columns.js +155 -0
  261. package/dist/table/commands.d.ts +19 -0
  262. package/dist/table/commands.js +63 -0
  263. package/dist/table/format.d.ts +35 -0
  264. package/dist/table/format.js +26 -0
  265. package/dist/table/gridBorders.d.ts +42 -0
  266. package/dist/table/gridBorders.js +192 -0
  267. package/dist/table/index.d.ts +16 -0
  268. package/dist/table/index.js +52 -0
  269. package/dist/table/merge.d.ts +36 -0
  270. package/dist/table/merge.js +125 -0
  271. package/dist/table/resize.d.ts +55 -0
  272. package/dist/table/resize.js +66 -0
  273. package/dist/table/rowResize.d.ts +14 -0
  274. package/dist/table/rowResize.js +44 -0
  275. package/dist/table/rows.d.ts +32 -0
  276. package/dist/table/rows.js +89 -0
  277. package/dist/table/widths.d.ts +69 -0
  278. package/dist/table/widths.js +97 -0
  279. package/dist/ui/AlignMenu.d.ts +15 -0
  280. package/dist/ui/AlignMenu.js +64 -0
  281. package/dist/ui/CellStyleGroup.d.ts +15 -0
  282. package/dist/ui/CellStyleGroup.js +232 -0
  283. package/dist/ui/ColorPicker.d.ts +13 -0
  284. package/dist/ui/ColorPicker.js +165 -0
  285. package/dist/ui/CommentsPanel.d.ts +15 -0
  286. package/dist/ui/CommentsPanel.js +348 -0
  287. package/dist/ui/FontFamilySelect.d.ts +14 -0
  288. package/dist/ui/FontFamilySelect.js +59 -0
  289. package/dist/ui/FontSizeSelect.d.ts +11 -0
  290. package/dist/ui/FontSizeSelect.js +49 -0
  291. package/dist/ui/InsertImageButton.d.ts +9 -0
  292. package/dist/ui/InsertImageButton.js +47 -0
  293. package/dist/ui/LinkCard.d.ts +12 -0
  294. package/dist/ui/LinkCard.js +127 -0
  295. package/dist/ui/LinkPanel.d.ts +9 -0
  296. package/dist/ui/LinkPanel.js +121 -0
  297. package/dist/ui/MenuChoice.d.ts +11 -0
  298. package/dist/ui/MenuChoice.js +32 -0
  299. package/dist/ui/NotesPanel.d.ts +6 -0
  300. package/dist/ui/NotesPanel.js +33 -0
  301. package/dist/ui/ParagraphStyleSelect.d.ts +11 -0
  302. package/dist/ui/ParagraphStyleSelect.js +62 -0
  303. package/dist/ui/Popover.d.ts +22 -0
  304. package/dist/ui/Popover.js +74 -0
  305. package/dist/ui/SpacingMenu.d.ts +12 -0
  306. package/dist/ui/SpacingMenu.js +54 -0
  307. package/dist/ui/TableMenu.d.ts +12 -0
  308. package/dist/ui/TableMenu.js +112 -0
  309. package/dist/ui/TableSizePicker.d.ts +9 -0
  310. package/dist/ui/TableSizePicker.js +53 -0
  311. package/dist/ui/TextMenu.d.ts +15 -0
  312. package/dist/ui/TextMenu.js +194 -0
  313. package/dist/ui/Toolbar.d.ts +19 -0
  314. package/dist/ui/Toolbar.js +448 -0
  315. package/dist/ui/ToolbarButton.d.ts +23 -0
  316. package/dist/ui/ToolbarButton.js +56 -0
  317. package/dist/ui/Tooltip.d.ts +19 -0
  318. package/dist/ui/Tooltip.js +47 -0
  319. package/dist/ui/ZoomSelect.d.ts +7 -0
  320. package/dist/ui/ZoomSelect.js +44 -0
  321. package/dist/ui/comments/CommentComposer.d.ts +17 -0
  322. package/dist/ui/comments/CommentComposer.js +59 -0
  323. package/dist/ui/comments/useCommentRailLayout.d.ts +18 -0
  324. package/dist/ui/comments/useCommentRailLayout.js +183 -0
  325. package/dist/ui/keyboardWalk.d.ts +22 -0
  326. package/dist/ui/keyboardWalk.js +70 -0
  327. package/dist/ui/openAddress.d.ts +11 -0
  328. package/dist/ui/openAddress.js +16 -0
  329. package/dist/ui/panelPlacement.d.ts +51 -0
  330. package/dist/ui/panelPlacement.js +71 -0
  331. package/dist/ui/presets.d.ts +11 -0
  332. package/dist/ui/presets.js +0 -0
  333. package/dist/ui/rovingFocus.d.ts +20 -0
  334. package/dist/ui/rovingFocus.js +61 -0
  335. package/dist/ui/runCommand.d.ts +5 -0
  336. package/dist/ui/runCommand.js +13 -0
  337. package/dist/ui/useDismiss.d.ts +6 -0
  338. package/dist/ui/useDismiss.js +31 -0
  339. package/dist/ui/useFitWidthZoom.d.ts +2 -0
  340. package/dist/ui/useFitWidthZoom.js +26 -0
  341. package/dist/ui/useGridKeyboard.d.ts +12 -0
  342. package/dist/ui/useGridKeyboard.js +90 -0
  343. package/dist/ui/useMenuKeyboard.d.ts +12 -0
  344. package/dist/ui/useMenuKeyboard.js +56 -0
  345. package/dist/ui/zoom.d.ts +4 -0
  346. package/dist/ui/zoom.js +21 -0
  347. package/package.json +120 -0
@@ -0,0 +1,47 @@
1
+ // src/ui/InsertImageButton.tsx
2
+ import { Image } from "lucide-react";
3
+ import { useRef } from "react";
4
+ import {
5
+ IMAGE_FILE_ACCEPT,
6
+ imageFilesIn,
7
+ insertImageFiles
8
+ } from "../editor/imageFiles.js";
9
+ import { canInsertImage } from "../editor/insertImage.js";
10
+ import { ToolbarButton } from "./ToolbarButton.js";
11
+ import { Fragment, jsx, jsxs } from "react/jsx-runtime";
12
+ function InsertImageButton({
13
+ view,
14
+ state
15
+ }) {
16
+ const pickerRef = useRef(null);
17
+ return /* @__PURE__ */ jsxs(Fragment, { children: [
18
+ /* @__PURE__ */ jsx(
19
+ ToolbarButton,
20
+ {
21
+ label: "Insert image",
22
+ icon: Image,
23
+ disabled: !view.editable || !canInsertImage(state),
24
+ onRun: () => pickerRef.current?.click()
25
+ }
26
+ ),
27
+ /* @__PURE__ */ jsx(
28
+ "input",
29
+ {
30
+ ref: pickerRef,
31
+ type: "file",
32
+ accept: IMAGE_FILE_ACCEPT,
33
+ hidden: true,
34
+ onChange: async (event) => {
35
+ const picker = event.currentTarget;
36
+ const files = imageFilesIn(picker);
37
+ picker.value = "";
38
+ await insertImageFiles(view, files);
39
+ if (!view.isDestroyed) view.focus();
40
+ }
41
+ }
42
+ )
43
+ ] });
44
+ }
45
+ export {
46
+ InsertImageButton
47
+ };
@@ -0,0 +1,12 @@
1
+ /** Shows the destination and available actions for the link under the selection. */
2
+ import type { EditorState } from "prosemirror-state";
3
+ import type { EditorView } from "prosemirror-view";
4
+ import { type ReactElement } from "react";
5
+ import { type ActiveLinkSpan } from "../editor/commands/linkCommands";
6
+ export interface LinkCardProps {
7
+ view: EditorView;
8
+ state: EditorState;
9
+ link: ActiveLinkSpan;
10
+ readOnly?: boolean;
11
+ }
12
+ export declare function LinkCard({ view, state, link, readOnly, }: LinkCardProps): ReactElement | null;
@@ -0,0 +1,127 @@
1
+ // src/ui/LinkCard.tsx
2
+ import { ExternalLink, Link2Off, Pencil } from "lucide-react";
3
+ import {
4
+ useCallback,
5
+ useEffect,
6
+ useRef,
7
+ useState
8
+ } from "react";
9
+ import {
10
+ removeLink
11
+ } from "../editor/commands/linkCommands.js";
12
+ import { openLinkPanel } from "../editor/plugins/linkPanel.js";
13
+ import { editorClassNames } from "../styles/classNames.js";
14
+ import { openAddress, openable } from "./openAddress.js";
15
+ import {
16
+ pointBelowPos,
17
+ usePanelAtPoint
18
+ } from "./panelPlacement.js";
19
+ import { commandRunner } from "./runCommand.js";
20
+ import { ICON_SIZE } from "./ToolbarButton.js";
21
+ import { Tooltip, tooltipAttribute } from "./Tooltip.js";
22
+ import { jsx, jsxs } from "react/jsx-runtime";
23
+ function useLinkPoint(view, at) {
24
+ const [point, setPoint] = useState(() => pointBelowPos(view, at));
25
+ useEffect(() => {
26
+ const measure = () => setPoint((was) => {
27
+ const now = pointBelowPos(view, at);
28
+ return was.clientX === now.clientX && was.clientY === now.clientY ? was : now;
29
+ });
30
+ measure();
31
+ document.addEventListener("scroll", measure, true);
32
+ window.addEventListener("resize", measure);
33
+ return () => {
34
+ document.removeEventListener("scroll", measure, true);
35
+ window.removeEventListener("resize", measure);
36
+ };
37
+ }, [view, at]);
38
+ return point;
39
+ }
40
+ function useEscape(onEscape) {
41
+ useEffect(() => {
42
+ const onKeyDown = (event) => {
43
+ if (event.key === "Escape") onEscape();
44
+ };
45
+ document.addEventListener("keydown", onKeyDown, true);
46
+ return () => document.removeEventListener("keydown", onKeyDown, true);
47
+ }, [onEscape]);
48
+ }
49
+ function LinkCard({
50
+ view,
51
+ state,
52
+ link,
53
+ readOnly = false
54
+ }) {
55
+ const box = useRef(null);
56
+ const [hidden, setHidden] = useState(false);
57
+ const placement = usePanelAtPoint(box, useLinkPoint(view, link.from));
58
+ const run = commandRunner(view);
59
+ const hide = useCallback(() => {
60
+ if (box.current?.contains(document.activeElement)) view.focus();
61
+ setHidden(true);
62
+ }, [view]);
63
+ useEscape(hide);
64
+ if (hidden) return null;
65
+ const href = link.href;
66
+ return /* @__PURE__ */ jsxs(
67
+ "div",
68
+ {
69
+ ref: box,
70
+ className: editorClassNames.linkCard,
71
+ role: "group",
72
+ "aria-label": "Link",
73
+ style: {
74
+ left: placement?.left,
75
+ top: placement?.top,
76
+ // Hide until the card has been measured.
77
+ visibility: placement ? void 0 : "hidden"
78
+ },
79
+ children: [
80
+ href === null ? /* @__PURE__ */ jsx("span", { className: editorClassNames.linkCardNote, children: "This link points at a place in the document rather than at an address." }) : (
81
+ // Keep the tooltip outside the address's clipped overflow.
82
+ /* @__PURE__ */ jsx(Tooltip, { label: href, children: /* @__PURE__ */ jsx("span", { className: editorClassNames.linkCardAddress, children: href }) })
83
+ ),
84
+ href !== null && /* @__PURE__ */ jsx(
85
+ "button",
86
+ {
87
+ type: "button",
88
+ className: editorClassNames.toolbarButton,
89
+ disabled: !openable(href),
90
+ onMouseDown: (event) => event.preventDefault(),
91
+ onClick: () => openAddress(href),
92
+ "aria-label": "Open",
93
+ ...tooltipAttribute("Open"),
94
+ children: /* @__PURE__ */ jsx(ExternalLink, { size: ICON_SIZE, "aria-hidden": "true" })
95
+ }
96
+ ),
97
+ !readOnly && openLinkPanel(state) && /* @__PURE__ */ jsx(
98
+ "button",
99
+ {
100
+ type: "button",
101
+ className: editorClassNames.toolbarButton,
102
+ onMouseDown: (event) => event.preventDefault(),
103
+ onClick: () => run(openLinkPanel),
104
+ "aria-label": "Edit",
105
+ ...tooltipAttribute("Edit"),
106
+ children: /* @__PURE__ */ jsx(Pencil, { size: ICON_SIZE, "aria-hidden": "true" })
107
+ }
108
+ ),
109
+ !readOnly && removeLink(state) && /* @__PURE__ */ jsx(
110
+ "button",
111
+ {
112
+ type: "button",
113
+ className: editorClassNames.toolbarButton,
114
+ onMouseDown: (event) => event.preventDefault(),
115
+ onClick: () => run(removeLink),
116
+ "aria-label": "Remove",
117
+ ...tooltipAttribute("Remove"),
118
+ children: /* @__PURE__ */ jsx(Link2Off, { size: ICON_SIZE, "aria-hidden": "true" })
119
+ }
120
+ )
121
+ ]
122
+ }
123
+ );
124
+ }
125
+ export {
126
+ LinkCard
127
+ };
@@ -0,0 +1,9 @@
1
+ /** Edits or removes the link on the current selection. */
2
+ import type { EditorState } from "prosemirror-state";
3
+ import type { EditorView } from "prosemirror-view";
4
+ import { type ReactElement } from "react";
5
+ export interface LinkPanelProps {
6
+ view: EditorView;
7
+ state: EditorState;
8
+ }
9
+ export declare function LinkPanel({ view, state }: LinkPanelProps): ReactElement;
@@ -0,0 +1,121 @@
1
+ // src/ui/LinkPanel.tsx
2
+ import { Check, Link2 } from "lucide-react";
3
+ import {
4
+ useCallback,
5
+ useEffect,
6
+ useRef,
7
+ useState
8
+ } from "react";
9
+ import {
10
+ activeLink,
11
+ removeLink,
12
+ setLink
13
+ } from "../editor/commands/linkCommands.js";
14
+ import { closeLinkPanel } from "../editor/plugins/linkPanel.js";
15
+ import { editorClassNames } from "../styles/classNames.js";
16
+ import { pointBelowPos, usePanelAtPoint } from "./panelPlacement.js";
17
+ import { commandRunner } from "./runCommand.js";
18
+ import { ICON_SIZE } from "./ToolbarButton.js";
19
+ import { tooltipAttribute } from "./Tooltip.js";
20
+ import { useDismiss } from "./useDismiss.js";
21
+ import { jsx, jsxs } from "react/jsx-runtime";
22
+ var FOCUSABLE = "input,button:not(:disabled)";
23
+ function LinkPanel({ view, state }) {
24
+ const box = useRef(null);
25
+ const field = useRef(null);
26
+ const current = activeLink(state);
27
+ const [address, setAddress] = useState(current ?? "");
28
+ const placement = usePanelAtPoint(
29
+ box,
30
+ pointBelowPos(view, state.selection.head)
31
+ );
32
+ const run = commandRunner(view);
33
+ const close = useCallback(() => {
34
+ closeLinkPanel(view.state, (tr) => view.dispatch(tr));
35
+ view.focus();
36
+ }, [view]);
37
+ useDismiss(box, true, close);
38
+ useEffect(() => {
39
+ const input = field.current;
40
+ if (!input || !placement || input === document.activeElement) return;
41
+ input.focus({ preventScroll: true });
42
+ input.select();
43
+ }, [placement]);
44
+ const emptied = address.trim() === "";
45
+ const applies = emptied ? removeLink(state) : setLink(address)(state);
46
+ const apply = () => {
47
+ run(emptied ? removeLink : setLink(address));
48
+ close();
49
+ };
50
+ const onKeyDown = (event) => {
51
+ if (event.key !== "Tab") return;
52
+ const controls = Array.from(
53
+ box.current?.querySelectorAll(FOCUSABLE) ?? []
54
+ );
55
+ if (controls.length === 0) return;
56
+ const at = controls.findIndex(
57
+ (control) => control === document.activeElement
58
+ );
59
+ const step = event.shiftKey ? -1 : 1;
60
+ const next = controls[(at + step + controls.length) % controls.length];
61
+ next.focus();
62
+ event.preventDefault();
63
+ };
64
+ return /* @__PURE__ */ jsx(
65
+ "div",
66
+ {
67
+ ref: box,
68
+ className: editorClassNames.linkPanel,
69
+ role: "dialog",
70
+ "aria-label": "Link",
71
+ onKeyDown,
72
+ style: {
73
+ left: placement?.left,
74
+ top: placement?.top,
75
+ // Hide until the dialog has been measured.
76
+ visibility: placement ? void 0 : "hidden"
77
+ },
78
+ children: /* @__PURE__ */ jsxs("div", { className: editorClassNames.linkPanelRow, children: [
79
+ /* @__PURE__ */ jsx(
80
+ Link2,
81
+ {
82
+ size: ICON_SIZE,
83
+ "aria-hidden": "true",
84
+ className: editorClassNames.linkPanelIcon
85
+ }
86
+ ),
87
+ /* @__PURE__ */ jsx(
88
+ "input",
89
+ {
90
+ ref: field,
91
+ type: "text",
92
+ className: editorClassNames.linkAddress,
93
+ "aria-label": "Address",
94
+ value: address,
95
+ onChange: (event) => setAddress(event.target.value),
96
+ onKeyDown: (event) => {
97
+ if (event.key !== "Enter") return;
98
+ event.preventDefault();
99
+ apply();
100
+ }
101
+ }
102
+ ),
103
+ /* @__PURE__ */ jsx(
104
+ "button",
105
+ {
106
+ type: "button",
107
+ className: editorClassNames.toolbarButton,
108
+ disabled: !applies,
109
+ onClick: apply,
110
+ "aria-label": "Apply",
111
+ ...tooltipAttribute("Apply"),
112
+ children: /* @__PURE__ */ jsx(Check, { size: ICON_SIZE, "aria-hidden": "true" })
113
+ }
114
+ )
115
+ ] })
116
+ }
117
+ );
118
+ }
119
+ export {
120
+ LinkPanel
121
+ };
@@ -0,0 +1,11 @@
1
+ /** Choice row with a fixed check slot for stable label alignment. */
2
+ import { type LucideIcon } from "lucide-react";
3
+ import type { ReactElement } from "react";
4
+ export interface MenuChoiceProps {
5
+ label: string;
6
+ icon?: LucideIcon;
7
+ role: "menuitemradio" | "menuitemcheckbox";
8
+ checked: boolean;
9
+ onChoose: () => void;
10
+ }
11
+ export declare function MenuChoice({ label, icon: Icon, role, checked, onChoose, }: MenuChoiceProps): ReactElement;
@@ -0,0 +1,32 @@
1
+ // src/ui/MenuChoice.tsx
2
+ import { Check } from "lucide-react";
3
+ import { editorClassNames } from "../styles/classNames.js";
4
+ import { ICON_SIZE } from "./ToolbarButton.js";
5
+ import { jsx, jsxs } from "react/jsx-runtime";
6
+ function MenuChoice({
7
+ label,
8
+ icon: Icon,
9
+ role,
10
+ checked,
11
+ onChoose
12
+ }) {
13
+ return /* @__PURE__ */ jsxs(
14
+ "button",
15
+ {
16
+ type: "button",
17
+ role,
18
+ className: editorClassNames.menuItem,
19
+ "aria-checked": checked,
20
+ onMouseDown: (event) => event.preventDefault(),
21
+ onClick: onChoose,
22
+ children: [
23
+ /* @__PURE__ */ jsx("span", { className: editorClassNames.menuCheck, children: checked && /* @__PURE__ */ jsx(Check, { size: ICON_SIZE, "aria-hidden": "true" }) }),
24
+ Icon && /* @__PURE__ */ jsx(Icon, { size: ICON_SIZE, "aria-hidden": "true" }),
25
+ label
26
+ ]
27
+ }
28
+ );
29
+ }
30
+ export {
31
+ MenuChoice
32
+ };
@@ -0,0 +1,6 @@
1
+ import type { EditorState } from "prosemirror-state";
2
+ import type { ReactElement } from "react";
3
+ export declare function NotesPanel({ state, pageWidth, }: {
4
+ state: EditorState;
5
+ pageWidth: number;
6
+ }): ReactElement | null;
@@ -0,0 +1,33 @@
1
+ // src/ui/NotesPanel.tsx
2
+ import { documentNotes } from "../editor/commands/noteQueries.js";
3
+ import { editorClassNames } from "../styles/classNames.js";
4
+ import { jsx, jsxs } from "react/jsx-runtime";
5
+ function NotesPanel({
6
+ state,
7
+ pageWidth
8
+ }) {
9
+ const notes = documentNotes(state);
10
+ if (notes.length === 0) return null;
11
+ return /* @__PURE__ */ jsxs(
12
+ "section",
13
+ {
14
+ className: editorClassNames.notesPanel,
15
+ "aria-label": "Document notes",
16
+ style: { width: `${pageWidth}px` },
17
+ children: [
18
+ /* @__PURE__ */ jsx("h2", { className: editorClassNames.notesHeading, children: "Footnotes and endnotes" }),
19
+ /* @__PURE__ */ jsx("ol", { className: editorClassNames.notesList, children: notes.map((note) => /* @__PURE__ */ jsxs("li", { children: [
20
+ /* @__PURE__ */ jsxs("span", { className: editorClassNames.noteLabel, children: [
21
+ note.kind === "footnote" ? "Footnote" : "Endnote",
22
+ " ",
23
+ note.label
24
+ ] }),
25
+ /* @__PURE__ */ jsx("p", { className: editorClassNames.noteBody, children: note.text })
26
+ ] }, `${note.kind}:${note.id}`)) })
27
+ ]
28
+ }
29
+ );
30
+ }
31
+ export {
32
+ NotesPanel
33
+ };
@@ -0,0 +1,11 @@
1
+ /** Selects document-defined paragraph styles and clears explicit styles through the default entry. */
2
+ import type { ReactElement } from "react";
3
+ import type { ParagraphStyleOption } from "../docx/formatting";
4
+ import { type ActiveParagraphStyle } from "../editor/commands/paragraphCommands";
5
+ import type { RunCommand } from "./runCommand";
6
+ export interface ParagraphStyleSelectProps {
7
+ current: ActiveParagraphStyle;
8
+ styles: readonly ParagraphStyleOption[];
9
+ run: RunCommand;
10
+ }
11
+ export declare function ParagraphStyleSelect({ current, styles, run, }: ParagraphStyleSelectProps): ReactElement;
@@ -0,0 +1,62 @@
1
+ // src/ui/ParagraphStyleSelect.tsx
2
+ import {
3
+ setParagraphStyle
4
+ } from "../editor/commands/paragraphCommands.js";
5
+ import { editorClassNames } from "../styles/classNames.js";
6
+ import { Tooltip } from "./Tooltip.js";
7
+ import { jsx, jsxs } from "react/jsx-runtime";
8
+ var LABEL = "Style";
9
+ var CLEAR = "default";
10
+ var BLANK = "";
11
+ var ID_PREFIX = "id:";
12
+ var styleValue = (id) => `${ID_PREFIX}${id}`;
13
+ function defaultName(styles) {
14
+ return styles.find((style) => style.isDefault)?.name ?? "Normal";
15
+ }
16
+ function namedStyles(styles) {
17
+ return styles.filter(
18
+ (style) => !style.isDefault && style.primary && !style.hidden
19
+ );
20
+ }
21
+ function selectedValue(styles, current) {
22
+ if (current.kind !== "shared") return BLANK;
23
+ if (current.styleId === null) return CLEAR;
24
+ const named = styles.find((style) => style.id === current.styleId);
25
+ if (!named || named.hidden || !named.isDefault && !named.primary) {
26
+ return BLANK;
27
+ }
28
+ return named?.isDefault ? CLEAR : styleValue(current.styleId);
29
+ }
30
+ function ParagraphStyleSelect({
31
+ current,
32
+ styles,
33
+ run
34
+ }) {
35
+ const value = selectedValue(styles, current);
36
+ return /* @__PURE__ */ jsx(Tooltip, { label: LABEL, children: /* @__PURE__ */ jsxs(
37
+ "select",
38
+ {
39
+ className: editorClassNames.toolbarSelect,
40
+ "aria-label": LABEL,
41
+ value,
42
+ disabled: current.kind === "none",
43
+ onChange: (event) => {
44
+ const chosen = event.target.value;
45
+ if (chosen === BLANK) return;
46
+ run(
47
+ setParagraphStyle(
48
+ chosen === CLEAR ? null : chosen.slice(ID_PREFIX.length)
49
+ )
50
+ );
51
+ },
52
+ children: [
53
+ value === BLANK && /* @__PURE__ */ jsx("option", { value: BLANK }),
54
+ /* @__PURE__ */ jsx("option", { value: CLEAR, children: defaultName(styles) }),
55
+ namedStyles(styles).map((style) => /* @__PURE__ */ jsx("option", { value: styleValue(style.id), children: style.name }, style.id))
56
+ ]
57
+ }
58
+ ) });
59
+ }
60
+ export {
61
+ ParagraphStyleSelect
62
+ };
@@ -0,0 +1,22 @@
1
+ /**
2
+ * Toolbar-button popover. Keyboard activation moves focus inside and restores it on close;
3
+ * pointer activation leaves the current focus unchanged.
4
+ */
5
+ import type { LucideIcon } from "lucide-react";
6
+ import { type ReactElement, type ReactNode } from "react";
7
+ /** Menus provide their own role; dialogs use the popover wrapper. */
8
+ export type PopoverPanel = "menu" | "dialog";
9
+ export interface PanelHandle {
10
+ close: () => void;
11
+ /** Whether keyboard activation requested focus inside the panel. */
12
+ takeFocus: boolean;
13
+ }
14
+ export interface PopoverProps {
15
+ label: string;
16
+ icon: LucideIcon;
17
+ indicatorColor?: string;
18
+ panel: PopoverPanel;
19
+ disabled?: boolean;
20
+ children: (handle: PanelHandle) => ReactNode;
21
+ }
22
+ export declare function Popover({ label, icon, indicatorColor, panel: kind, disabled, children, }: PopoverProps): ReactElement;
@@ -0,0 +1,74 @@
1
+ // src/ui/Popover.tsx
2
+ import {
3
+ useCallback,
4
+ useRef,
5
+ useState
6
+ } from "react";
7
+ import { editorClassNames } from "../styles/classNames.js";
8
+ import { usePanelUnderControl } from "./panelPlacement.js";
9
+ import { ToolbarButton } from "./ToolbarButton.js";
10
+ import { useDismiss } from "./useDismiss.js";
11
+ import { jsx, jsxs } from "react/jsx-runtime";
12
+ function Popover({
13
+ label,
14
+ icon,
15
+ indicatorColor,
16
+ panel: kind,
17
+ disabled,
18
+ children
19
+ }) {
20
+ const [open, setOpen] = useState(false);
21
+ const box = useRef(null);
22
+ const button = useRef(null);
23
+ const panel = useRef(null);
24
+ const holdsFocus = useRef(false);
25
+ const close = useCallback(() => {
26
+ setOpen(false);
27
+ if (holdsFocus.current) button.current?.focus({ preventScroll: true });
28
+ holdsFocus.current = false;
29
+ }, []);
30
+ useDismiss(box, open, close);
31
+ const position = usePanelUnderControl(panel, button, open);
32
+ const toggle = (source) => {
33
+ if (open) {
34
+ close();
35
+ return;
36
+ }
37
+ holdsFocus.current = source === "keyboard";
38
+ setOpen(true);
39
+ };
40
+ return /* @__PURE__ */ jsxs("div", { className: editorClassNames.popoverBox, ref: box, children: [
41
+ /* @__PURE__ */ jsx(
42
+ ToolbarButton,
43
+ {
44
+ ref: button,
45
+ label,
46
+ icon,
47
+ indicatorColor,
48
+ popup: kind,
49
+ expanded: open,
50
+ disabled,
51
+ onRun: toggle
52
+ }
53
+ ),
54
+ open && /* @__PURE__ */ jsx(
55
+ "div",
56
+ {
57
+ ref: panel,
58
+ className: editorClassNames.popover,
59
+ role: kind === "dialog" ? "dialog" : void 0,
60
+ "aria-label": kind === "dialog" ? label : void 0,
61
+ style: {
62
+ left: position?.left,
63
+ top: position?.top,
64
+ // Hide until the panel has been measured.
65
+ visibility: position ? void 0 : "hidden"
66
+ },
67
+ children: children({ close, takeFocus: holdsFocus.current })
68
+ }
69
+ )
70
+ ] });
71
+ }
72
+ export {
73
+ Popover
74
+ };
@@ -0,0 +1,12 @@
1
+ import type { EditorState } from "prosemirror-state";
2
+ import { type ReactElement } from "react";
3
+ import { type LineSpacingOption } from "../styles/lineSpacings";
4
+ import type { RunCommand } from "./runCommand";
5
+ export interface SpacingMenuProps {
6
+ state: EditorState;
7
+ lineSpacings?: readonly LineSpacingOption[];
8
+ run: RunCommand;
9
+ close: () => void;
10
+ takeFocus: boolean;
11
+ }
12
+ export declare function SpacingMenu({ state, lineSpacings, run, close, takeFocus, }: SpacingMenuProps): ReactElement;
@@ -0,0 +1,54 @@
1
+ // src/ui/SpacingMenu.tsx
2
+ import { useRef } from "react";
3
+ import {
4
+ activeLineSpacing,
5
+ setLineSpacing
6
+ } from "../editor/commands/spacingCommands.js";
7
+ import { editorClassNames } from "../styles/classNames.js";
8
+ import {
9
+ DEFAULT_LINE_SPACINGS
10
+ } from "../styles/lineSpacings.js";
11
+ import { MenuChoice } from "./MenuChoice.js";
12
+ import { useMenuKeyboard } from "./useMenuKeyboard.js";
13
+ import { jsx } from "react/jsx-runtime";
14
+ function isCurrentChoice(current, { spacing }) {
15
+ return current?.rule === "auto" && spacing.rule === "auto" && current.lines === spacing.lines;
16
+ }
17
+ function SpacingMenu({
18
+ state,
19
+ lineSpacings = DEFAULT_LINE_SPACINGS,
20
+ run,
21
+ close,
22
+ takeFocus
23
+ }) {
24
+ const current = activeLineSpacing(state);
25
+ const menu = useRef(null);
26
+ const keys = useMenuKeyboard({ menu, onClose: close, takeFocus });
27
+ const choose = (command) => {
28
+ run(command);
29
+ close();
30
+ };
31
+ return /* @__PURE__ */ jsx(
32
+ "div",
33
+ {
34
+ ref: menu,
35
+ className: editorClassNames.menuList,
36
+ role: "menu",
37
+ "aria-label": "Line and paragraph spacing",
38
+ ...keys,
39
+ children: lineSpacings.map((option) => /* @__PURE__ */ jsx(
40
+ MenuChoice,
41
+ {
42
+ label: option.label,
43
+ role: "menuitemradio",
44
+ checked: isCurrentChoice(current, option),
45
+ onChoose: () => choose(setLineSpacing(option.spacing))
46
+ },
47
+ option.label
48
+ ))
49
+ }
50
+ );
51
+ }
52
+ export {
53
+ SpacingMenu
54
+ };
@@ -0,0 +1,12 @@
1
+ /** Table context menu with an optional Unlock action for whole-cell locks. */
2
+ import type { EditorState } from "prosemirror-state";
3
+ import type { EditorView } from "prosemirror-view";
4
+ import { type ReactElement } from "react";
5
+ import { type TableMenuAnchor } from "../editor/plugins/tableContextMenu";
6
+ export interface TableMenuProps {
7
+ view: EditorView;
8
+ state: EditorState;
9
+ anchor: TableMenuAnchor;
10
+ allowLocking?: boolean;
11
+ }
12
+ export declare function TableMenu({ view, state, anchor, allowLocking, }: TableMenuProps): ReactElement;