@bendyline/squisq-editor-react 1.4.0 → 1.5.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 (446) hide show
  1. package/dist/DocumentSettingsDialog.d.ts +26 -0
  2. package/dist/DocumentSettingsDialog.d.ts.map +1 -0
  3. package/dist/DocumentSettingsDialog.js +115 -0
  4. package/dist/DocumentSettingsDialog.js.map +1 -0
  5. package/dist/EditorContext.d.ts +248 -4
  6. package/dist/EditorContext.d.ts.map +1 -1
  7. package/dist/EditorContext.js +248 -10
  8. package/dist/EditorContext.js.map +1 -1
  9. package/dist/EditorShell.d.ts +173 -4
  10. package/dist/EditorShell.d.ts.map +1 -1
  11. package/dist/EditorShell.js +110 -10
  12. package/dist/EditorShell.js.map +1 -1
  13. package/dist/EmojiPicker.d.ts +50 -0
  14. package/dist/EmojiPicker.d.ts.map +1 -0
  15. package/dist/EmojiPicker.js +182 -0
  16. package/dist/EmojiPicker.js.map +1 -0
  17. package/dist/ImageEditor.d.ts +68 -0
  18. package/dist/ImageEditor.d.ts.map +1 -0
  19. package/dist/ImageEditor.js +166 -0
  20. package/dist/ImageEditor.js.map +1 -0
  21. package/dist/ImageNodeView.d.ts +13 -1
  22. package/dist/ImageNodeView.d.ts.map +1 -1
  23. package/dist/ImageNodeView.js +172 -19
  24. package/dist/ImageNodeView.js.map +1 -1
  25. package/dist/ImageViewer.d.ts +26 -0
  26. package/dist/ImageViewer.d.ts.map +1 -0
  27. package/dist/ImageViewer.js +119 -0
  28. package/dist/ImageViewer.js.map +1 -0
  29. package/dist/InlineIcon.d.ts +17 -0
  30. package/dist/InlineIcon.d.ts.map +1 -0
  31. package/dist/InlineIcon.js +72 -0
  32. package/dist/InlineIcon.js.map +1 -0
  33. package/dist/InlinePreviewGutter.d.ts +52 -0
  34. package/dist/InlinePreviewGutter.d.ts.map +1 -0
  35. package/dist/InlinePreviewGutter.js +397 -0
  36. package/dist/InlinePreviewGutter.js.map +1 -0
  37. package/dist/LinkDialog.d.ts +43 -0
  38. package/dist/LinkDialog.d.ts.map +1 -0
  39. package/dist/LinkDialog.js +102 -0
  40. package/dist/LinkDialog.js.map +1 -0
  41. package/dist/MentionExtension.js +10 -7
  42. package/dist/MentionExtension.js.map +1 -1
  43. package/dist/OutlinePanel.d.ts +17 -0
  44. package/dist/OutlinePanel.d.ts.map +1 -0
  45. package/dist/OutlinePanel.js +167 -0
  46. package/dist/OutlinePanel.js.map +1 -0
  47. package/dist/PlainHtmlPreview.d.ts +50 -0
  48. package/dist/PlainHtmlPreview.d.ts.map +1 -0
  49. package/dist/PlainHtmlPreview.js +155 -0
  50. package/dist/PlainHtmlPreview.js.map +1 -0
  51. package/dist/PreviewControls.d.ts +15 -1
  52. package/dist/PreviewControls.d.ts.map +1 -1
  53. package/dist/PreviewControls.js +75 -18
  54. package/dist/PreviewControls.js.map +1 -1
  55. package/dist/PreviewPanel.d.ts +11 -10
  56. package/dist/PreviewPanel.d.ts.map +1 -1
  57. package/dist/PreviewPanel.js +20 -17
  58. package/dist/PreviewPanel.js.map +1 -1
  59. package/dist/RawEditor.d.ts.map +1 -1
  60. package/dist/RawEditor.js +198 -4
  61. package/dist/RawEditor.js.map +1 -1
  62. package/dist/RecorderEntry.d.ts +24 -0
  63. package/dist/RecorderEntry.d.ts.map +1 -0
  64. package/dist/RecorderEntry.js +139 -0
  65. package/dist/RecorderEntry.js.map +1 -0
  66. package/dist/TemplateAnnotation.d.ts.map +1 -1
  67. package/dist/TemplateAnnotation.js +32 -6
  68. package/dist/TemplateAnnotation.js.map +1 -1
  69. package/dist/TemplatePicker.d.ts +53 -0
  70. package/dist/TemplatePicker.d.ts.map +1 -0
  71. package/dist/TemplatePicker.js +388 -0
  72. package/dist/TemplatePicker.js.map +1 -0
  73. package/dist/ThemeCustomizerPanel.d.ts +32 -0
  74. package/dist/ThemeCustomizerPanel.d.ts.map +1 -0
  75. package/dist/ThemeCustomizerPanel.js +256 -0
  76. package/dist/ThemeCustomizerPanel.js.map +1 -0
  77. package/dist/ThemePicker.d.ts +33 -0
  78. package/dist/ThemePicker.d.ts.map +1 -0
  79. package/dist/ThemePicker.js +148 -0
  80. package/dist/ThemePicker.js.map +1 -0
  81. package/dist/Toolbar.d.ts.map +1 -1
  82. package/dist/Toolbar.js +508 -33
  83. package/dist/Toolbar.js.map +1 -1
  84. package/dist/VersionHistoryPanel.d.ts +14 -0
  85. package/dist/VersionHistoryPanel.d.ts.map +1 -0
  86. package/dist/VersionHistoryPanel.js +147 -0
  87. package/dist/VersionHistoryPanel.js.map +1 -0
  88. package/dist/ViewMenuPanel.d.ts +13 -0
  89. package/dist/ViewMenuPanel.d.ts.map +1 -0
  90. package/dist/ViewMenuPanel.js +58 -0
  91. package/dist/ViewMenuPanel.js.map +1 -0
  92. package/dist/WysiwygEditor.d.ts.map +1 -1
  93. package/dist/WysiwygEditor.js +198 -9
  94. package/dist/WysiwygEditor.js.map +1 -1
  95. package/dist/__tests__/detectMarkdown.test.js +0 -14
  96. package/dist/__tests__/detectMarkdown.test.js.map +1 -1
  97. package/dist/__tests__/documentSettingsDialog.test.d.ts +2 -0
  98. package/dist/__tests__/documentSettingsDialog.test.d.ts.map +1 -0
  99. package/dist/__tests__/documentSettingsDialog.test.js +132 -0
  100. package/dist/__tests__/documentSettingsDialog.test.js.map +1 -0
  101. package/dist/__tests__/emojiPicker.test.d.ts +2 -0
  102. package/dist/__tests__/emojiPicker.test.d.ts.map +1 -0
  103. package/dist/__tests__/emojiPicker.test.js +111 -0
  104. package/dist/__tests__/emojiPicker.test.js.map +1 -0
  105. package/dist/__tests__/fileKind.test.js +13 -0
  106. package/dist/__tests__/fileKind.test.js.map +1 -1
  107. package/dist/__tests__/imageEditAffordance.test.d.ts +2 -0
  108. package/dist/__tests__/imageEditAffordance.test.d.ts.map +1 -0
  109. package/dist/__tests__/imageEditAffordance.test.js +188 -0
  110. package/dist/__tests__/imageEditAffordance.test.js.map +1 -0
  111. package/dist/__tests__/imageEditorShell.test.d.ts +2 -0
  112. package/dist/__tests__/imageEditorShell.test.d.ts.map +1 -0
  113. package/dist/__tests__/imageEditorShell.test.js +52 -0
  114. package/dist/__tests__/imageEditorShell.test.js.map +1 -0
  115. package/dist/__tests__/imageEditorState.test.d.ts +3 -0
  116. package/dist/__tests__/imageEditorState.test.d.ts.map +1 -0
  117. package/dist/__tests__/imageEditorState.test.js +148 -0
  118. package/dist/__tests__/imageEditorState.test.js.map +1 -0
  119. package/dist/__tests__/inlinePreviewGutter.test.d.ts +2 -0
  120. package/dist/__tests__/inlinePreviewGutter.test.d.ts.map +1 -0
  121. package/dist/__tests__/inlinePreviewGutter.test.js +51 -0
  122. package/dist/__tests__/inlinePreviewGutter.test.js.map +1 -0
  123. package/dist/__tests__/inlinePreviewGutterAllBlocks.test.d.ts +2 -0
  124. package/dist/__tests__/inlinePreviewGutterAllBlocks.test.d.ts.map +1 -0
  125. package/dist/__tests__/inlinePreviewGutterAllBlocks.test.js +63 -0
  126. package/dist/__tests__/inlinePreviewGutterAllBlocks.test.js.map +1 -0
  127. package/dist/__tests__/jsonEditor.test.d.ts +2 -0
  128. package/dist/__tests__/jsonEditor.test.d.ts.map +1 -0
  129. package/dist/__tests__/jsonEditor.test.js +134 -0
  130. package/dist/__tests__/jsonEditor.test.js.map +1 -0
  131. package/dist/__tests__/layersPanel.test.d.ts +2 -0
  132. package/dist/__tests__/layersPanel.test.d.ts.map +1 -0
  133. package/dist/__tests__/layersPanel.test.js +84 -0
  134. package/dist/__tests__/layersPanel.test.js.map +1 -0
  135. package/dist/__tests__/linkDialogDocPicker.test.d.ts +7 -0
  136. package/dist/__tests__/linkDialogDocPicker.test.d.ts.map +1 -0
  137. package/dist/__tests__/linkDialogDocPicker.test.js +75 -0
  138. package/dist/__tests__/linkDialogDocPicker.test.js.map +1 -0
  139. package/dist/__tests__/outlinePanel.test.d.ts +2 -0
  140. package/dist/__tests__/outlinePanel.test.d.ts.map +1 -0
  141. package/dist/__tests__/outlinePanel.test.js +68 -0
  142. package/dist/__tests__/outlinePanel.test.js.map +1 -0
  143. package/dist/__tests__/plainHtmlPreview.test.d.ts +2 -0
  144. package/dist/__tests__/plainHtmlPreview.test.d.ts.map +1 -0
  145. package/dist/__tests__/plainHtmlPreview.test.js +87 -0
  146. package/dist/__tests__/plainHtmlPreview.test.js.map +1 -0
  147. package/dist/__tests__/propertiesPanel.test.d.ts +2 -0
  148. package/dist/__tests__/propertiesPanel.test.d.ts.map +1 -0
  149. package/dist/__tests__/propertiesPanel.test.js +64 -0
  150. package/dist/__tests__/propertiesPanel.test.js.map +1 -0
  151. package/dist/__tests__/recorderFormats.test.d.ts +2 -0
  152. package/dist/__tests__/recorderFormats.test.d.ts.map +1 -0
  153. package/dist/__tests__/recorderFormats.test.js +121 -0
  154. package/dist/__tests__/recorderFormats.test.js.map +1 -0
  155. package/dist/__tests__/recorderTimingJson.test.d.ts +2 -0
  156. package/dist/__tests__/recorderTimingJson.test.d.ts.map +1 -0
  157. package/dist/__tests__/recorderTimingJson.test.js +37 -0
  158. package/dist/__tests__/recorderTimingJson.test.js.map +1 -0
  159. package/dist/__tests__/templateAnnotationRoundTrip.test.d.ts +2 -0
  160. package/dist/__tests__/templateAnnotationRoundTrip.test.d.ts.map +1 -0
  161. package/dist/__tests__/templateAnnotationRoundTrip.test.js +31 -0
  162. package/dist/__tests__/templateAnnotationRoundTrip.test.js.map +1 -0
  163. package/dist/__tests__/tiptapBridge.test.js +13 -0
  164. package/dist/__tests__/tiptapBridge.test.js.map +1 -1
  165. package/dist/__tests__/useImageEditor.test.d.ts +2 -0
  166. package/dist/__tests__/useImageEditor.test.d.ts.map +1 -0
  167. package/dist/__tests__/useImageEditor.test.js +131 -0
  168. package/dist/__tests__/useImageEditor.test.js.map +1 -0
  169. package/dist/__tests__/useMediaRecorder.test.d.ts +2 -0
  170. package/dist/__tests__/useMediaRecorder.test.d.ts.map +1 -0
  171. package/dist/__tests__/useMediaRecorder.test.js +153 -0
  172. package/dist/__tests__/useMediaRecorder.test.js.map +1 -0
  173. package/dist/__tests__/versionHistory.test.d.ts +2 -0
  174. package/dist/__tests__/versionHistory.test.d.ts.map +1 -0
  175. package/dist/__tests__/versionHistory.test.js +124 -0
  176. package/dist/__tests__/versionHistory.test.js.map +1 -0
  177. package/dist/blockSlice.d.ts +24 -0
  178. package/dist/blockSlice.d.ts.map +1 -0
  179. package/dist/blockSlice.js +63 -0
  180. package/dist/blockSlice.js.map +1 -0
  181. package/dist/buildPreviewDoc.d.ts.map +1 -1
  182. package/dist/buildPreviewDoc.js +52 -2
  183. package/dist/buildPreviewDoc.js.map +1 -1
  184. package/dist/emojiData.d.ts +81 -0
  185. package/dist/emojiData.d.ts.map +1 -0
  186. package/dist/emojiData.js +1283 -0
  187. package/dist/emojiData.js.map +1 -0
  188. package/dist/fileKind.d.ts +6 -2
  189. package/dist/fileKind.d.ts.map +1 -1
  190. package/dist/fileKind.js +25 -4
  191. package/dist/fileKind.js.map +1 -1
  192. package/dist/hooks/useFileDrop.d.ts.map +1 -1
  193. package/dist/hooks/useFileDrop.js +40 -4
  194. package/dist/hooks/useFileDrop.js.map +1 -1
  195. package/dist/imageEditor/CanvasSurface.d.ts +31 -0
  196. package/dist/imageEditor/CanvasSurface.d.ts.map +1 -0
  197. package/dist/imageEditor/CanvasSurface.js +264 -0
  198. package/dist/imageEditor/CanvasSurface.js.map +1 -0
  199. package/dist/imageEditor/ImageVersionHistoryDropdown.d.ts +39 -0
  200. package/dist/imageEditor/ImageVersionHistoryDropdown.d.ts.map +1 -0
  201. package/dist/imageEditor/ImageVersionHistoryDropdown.js +283 -0
  202. package/dist/imageEditor/ImageVersionHistoryDropdown.js.map +1 -0
  203. package/dist/imageEditor/LayersPanel.d.ts +14 -0
  204. package/dist/imageEditor/LayersPanel.d.ts.map +1 -0
  205. package/dist/imageEditor/LayersPanel.js +43 -0
  206. package/dist/imageEditor/LayersPanel.js.map +1 -0
  207. package/dist/imageEditor/PropertiesPanel.d.ts +14 -0
  208. package/dist/imageEditor/PropertiesPanel.d.ts.map +1 -0
  209. package/dist/imageEditor/PropertiesPanel.js +97 -0
  210. package/dist/imageEditor/PropertiesPanel.js.map +1 -0
  211. package/dist/imageEditor/Toolbar.d.ts +30 -0
  212. package/dist/imageEditor/Toolbar.d.ts.map +1 -0
  213. package/dist/imageEditor/Toolbar.js +108 -0
  214. package/dist/imageEditor/Toolbar.js.map +1 -0
  215. package/dist/imageEditor/icons.d.ts +24 -0
  216. package/dist/imageEditor/icons.d.ts.map +1 -0
  217. package/dist/imageEditor/icons.js +45 -0
  218. package/dist/imageEditor/icons.js.map +1 -0
  219. package/dist/imageEditor/layers/EditorImageLayer.d.ts +16 -0
  220. package/dist/imageEditor/layers/EditorImageLayer.d.ts.map +1 -0
  221. package/dist/imageEditor/layers/EditorImageLayer.js +37 -0
  222. package/dist/imageEditor/layers/EditorImageLayer.js.map +1 -0
  223. package/dist/imageEditor/layers/EditorShapeLayer.d.ts +15 -0
  224. package/dist/imageEditor/layers/EditorShapeLayer.d.ts.map +1 -0
  225. package/dist/imageEditor/layers/EditorShapeLayer.js +20 -0
  226. package/dist/imageEditor/layers/EditorShapeLayer.js.map +1 -0
  227. package/dist/imageEditor/layers/EditorTextLayer.d.ts +18 -0
  228. package/dist/imageEditor/layers/EditorTextLayer.d.ts.map +1 -0
  229. package/dist/imageEditor/layers/EditorTextLayer.js +13 -0
  230. package/dist/imageEditor/layers/EditorTextLayer.js.map +1 -0
  231. package/dist/imageEditor/layers/SelectionHandles.d.ts +17 -0
  232. package/dist/imageEditor/layers/SelectionHandles.d.ts.map +1 -0
  233. package/dist/imageEditor/layers/SelectionHandles.js +19 -0
  234. package/dist/imageEditor/layers/SelectionHandles.js.map +1 -0
  235. package/dist/imageEditor/state.d.ts +76 -0
  236. package/dist/imageEditor/state.d.ts.map +1 -0
  237. package/dist/imageEditor/state.js +87 -0
  238. package/dist/imageEditor/state.js.map +1 -0
  239. package/dist/imageEditor/useImageEditor.d.ts +53 -0
  240. package/dist/imageEditor/useImageEditor.d.ts.map +1 -0
  241. package/dist/imageEditor/useImageEditor.js +244 -0
  242. package/dist/imageEditor/useImageEditor.js.map +1 -0
  243. package/dist/imageEditor/useImageEditorTokens.d.ts +16 -0
  244. package/dist/imageEditor/useImageEditorTokens.d.ts.map +1 -0
  245. package/dist/imageEditor/useImageEditorTokens.js +45 -0
  246. package/dist/imageEditor/useImageEditorTokens.js.map +1 -0
  247. package/dist/index.d.ts +48 -1
  248. package/dist/index.d.ts.map +1 -1
  249. package/dist/index.js +36 -0
  250. package/dist/index.js.map +1 -1
  251. package/dist/jsonEditor/EmbeddedRichTextField.d.ts +15 -0
  252. package/dist/jsonEditor/EmbeddedRichTextField.d.ts.map +1 -0
  253. package/dist/jsonEditor/EmbeddedRichTextField.js +74 -0
  254. package/dist/jsonEditor/EmbeddedRichTextField.js.map +1 -0
  255. package/dist/jsonEditor/JsonEditor.d.ts +36 -0
  256. package/dist/jsonEditor/JsonEditor.d.ts.map +1 -0
  257. package/dist/jsonEditor/JsonEditor.js +15 -0
  258. package/dist/jsonEditor/JsonEditor.js.map +1 -0
  259. package/dist/jsonEditor/JsonEditorContext.d.ts +28 -0
  260. package/dist/jsonEditor/JsonEditorContext.d.ts.map +1 -0
  261. package/dist/jsonEditor/JsonEditorContext.js +41 -0
  262. package/dist/jsonEditor/JsonEditorContext.js.map +1 -0
  263. package/dist/jsonEditor/RenderNode.d.ts +16 -0
  264. package/dist/jsonEditor/RenderNode.d.ts.map +1 -0
  265. package/dist/jsonEditor/RenderNode.js +32 -0
  266. package/dist/jsonEditor/RenderNode.js.map +1 -0
  267. package/dist/jsonEditor/editors.d.ts +36 -0
  268. package/dist/jsonEditor/editors.d.ts.map +1 -0
  269. package/dist/jsonEditor/editors.js +347 -0
  270. package/dist/jsonEditor/editors.js.map +1 -0
  271. package/dist/jsonEditor/index.d.ts +3 -0
  272. package/dist/jsonEditor/index.d.ts.map +1 -0
  273. package/dist/jsonEditor/index.js +2 -0
  274. package/dist/jsonEditor/index.js.map +1 -0
  275. package/dist/jsonEditor/useJsonEditorTokens.d.ts +13 -0
  276. package/dist/jsonEditor/useJsonEditorTokens.d.ts.map +1 -0
  277. package/dist/jsonEditor/useJsonEditorTokens.js +38 -0
  278. package/dist/jsonEditor/useJsonEditorTokens.js.map +1 -0
  279. package/dist/recorder/RecorderButton.d.ts +31 -0
  280. package/dist/recorder/RecorderButton.d.ts.map +1 -0
  281. package/dist/recorder/RecorderButton.js +24 -0
  282. package/dist/recorder/RecorderButton.js.map +1 -0
  283. package/dist/recorder/RecorderModal.d.ts +59 -0
  284. package/dist/recorder/RecorderModal.d.ts.map +1 -0
  285. package/dist/recorder/RecorderModal.js +333 -0
  286. package/dist/recorder/RecorderModal.js.map +1 -0
  287. package/dist/recorder/RecorderPanel.d.ts +25 -0
  288. package/dist/recorder/RecorderPanel.d.ts.map +1 -0
  289. package/dist/recorder/RecorderPanel.js +30 -0
  290. package/dist/recorder/RecorderPanel.js.map +1 -0
  291. package/dist/recorder/formats.d.ts +51 -0
  292. package/dist/recorder/formats.d.ts.map +1 -0
  293. package/dist/recorder/formats.js +144 -0
  294. package/dist/recorder/formats.js.map +1 -0
  295. package/dist/recorder/hooks/useMediaRecorder.d.ts +90 -0
  296. package/dist/recorder/hooks/useMediaRecorder.d.ts.map +1 -0
  297. package/dist/recorder/hooks/useMediaRecorder.js +277 -0
  298. package/dist/recorder/hooks/useMediaRecorder.js.map +1 -0
  299. package/dist/recorder/hooks/useStreamPreview.d.ts +22 -0
  300. package/dist/recorder/hooks/useStreamPreview.d.ts.map +1 -0
  301. package/dist/recorder/hooks/useStreamPreview.js +44 -0
  302. package/dist/recorder/hooks/useStreamPreview.js.map +1 -0
  303. package/dist/recorder/sources/cameraStream.d.ts +22 -0
  304. package/dist/recorder/sources/cameraStream.d.ts.map +1 -0
  305. package/dist/recorder/sources/cameraStream.js +24 -0
  306. package/dist/recorder/sources/cameraStream.js.map +1 -0
  307. package/dist/recorder/sources/micStream.d.ts +15 -0
  308. package/dist/recorder/sources/micStream.d.ts.map +1 -0
  309. package/dist/recorder/sources/micStream.js +24 -0
  310. package/dist/recorder/sources/micStream.js.map +1 -0
  311. package/dist/recorder/sources/screenStream.d.ts +53 -0
  312. package/dist/recorder/sources/screenStream.d.ts.map +1 -0
  313. package/dist/recorder/sources/screenStream.js +114 -0
  314. package/dist/recorder/sources/screenStream.js.map +1 -0
  315. package/dist/recorder/timingJson.d.ts +51 -0
  316. package/dist/recorder/timingJson.d.ts.map +1 -0
  317. package/dist/recorder/timingJson.js +42 -0
  318. package/dist/recorder/timingJson.js.map +1 -0
  319. package/dist/tiptap/TiptapAudio.d.ts +26 -0
  320. package/dist/tiptap/TiptapAudio.d.ts.map +1 -0
  321. package/dist/tiptap/TiptapAudio.js +58 -0
  322. package/dist/tiptap/TiptapAudio.js.map +1 -0
  323. package/dist/tiptap/TiptapVideo.d.ts +30 -0
  324. package/dist/tiptap/TiptapVideo.d.ts.map +1 -0
  325. package/dist/tiptap/TiptapVideo.js +66 -0
  326. package/dist/tiptap/TiptapVideo.js.map +1 -0
  327. package/dist/tiptap/useResolvedMediaSrc.d.ts +2 -0
  328. package/dist/tiptap/useResolvedMediaSrc.d.ts.map +1 -0
  329. package/dist/tiptap/useResolvedMediaSrc.js +42 -0
  330. package/dist/tiptap/useResolvedMediaSrc.js.map +1 -0
  331. package/dist/tiptapBridge.d.ts.map +1 -1
  332. package/dist/tiptapBridge.js +171 -14
  333. package/dist/tiptapBridge.js.map +1 -1
  334. package/dist/useHeadingLayout.d.ts +54 -0
  335. package/dist/useHeadingLayout.d.ts.map +1 -0
  336. package/dist/useHeadingLayout.js +260 -0
  337. package/dist/useHeadingLayout.js.map +1 -0
  338. package/dist/utils/collectInlineFontAwesomeCss.d.ts +21 -0
  339. package/dist/utils/collectInlineFontAwesomeCss.d.ts.map +1 -0
  340. package/dist/utils/collectInlineFontAwesomeCss.js +68 -0
  341. package/dist/utils/collectInlineFontAwesomeCss.js.map +1 -0
  342. package/dist/utils/dropUtils.d.ts +21 -2
  343. package/dist/utils/dropUtils.d.ts.map +1 -1
  344. package/dist/utils/dropUtils.js +43 -4
  345. package/dist/utils/dropUtils.js.map +1 -1
  346. package/dist/utils/normalizeMalformedAssetUrl.d.ts +15 -0
  347. package/dist/utils/normalizeMalformedAssetUrl.d.ts.map +1 -0
  348. package/dist/utils/normalizeMalformedAssetUrl.js +27 -0
  349. package/dist/utils/normalizeMalformedAssetUrl.js.map +1 -0
  350. package/package.json +8 -5
  351. package/src/DocumentSettingsDialog.tsx +266 -0
  352. package/src/EditorContext.tsx +534 -10
  353. package/src/EditorShell.tsx +571 -55
  354. package/src/EmojiPicker.tsx +332 -0
  355. package/src/ImageEditor.tsx +327 -0
  356. package/src/ImageNodeView.tsx +222 -21
  357. package/src/ImageViewer.tsx +221 -0
  358. package/src/InlineIcon.ts +84 -0
  359. package/src/InlinePreviewGutter.tsx +582 -0
  360. package/src/LinkDialog.tsx +276 -0
  361. package/src/MentionExtension.tsx +10 -7
  362. package/src/OutlinePanel.tsx +295 -0
  363. package/src/PlainHtmlPreview.tsx +211 -0
  364. package/src/PreviewControls.tsx +130 -24
  365. package/src/PreviewPanel.tsx +38 -21
  366. package/src/RawEditor.tsx +215 -4
  367. package/src/RecorderEntry.tsx +164 -0
  368. package/src/TemplateAnnotation.ts +32 -6
  369. package/src/TemplatePicker.tsx +818 -0
  370. package/src/ThemeCustomizerPanel.tsx +595 -0
  371. package/src/ThemePicker.tsx +319 -0
  372. package/src/Toolbar.tsx +708 -111
  373. package/src/VersionHistoryPanel.tsx +329 -0
  374. package/src/ViewMenuPanel.tsx +188 -0
  375. package/src/WysiwygEditor.tsx +229 -9
  376. package/src/__tests__/detectMarkdown.test.ts +0 -15
  377. package/src/__tests__/documentSettingsDialog.test.tsx +147 -0
  378. package/src/__tests__/emojiPicker.test.tsx +133 -0
  379. package/src/__tests__/fileKind.test.ts +16 -0
  380. package/src/__tests__/imageEditAffordance.test.tsx +268 -0
  381. package/src/__tests__/imageEditorShell.test.tsx +57 -0
  382. package/src/__tests__/imageEditorState.test.ts +171 -0
  383. package/src/__tests__/inlinePreviewGutter.test.tsx +62 -0
  384. package/src/__tests__/inlinePreviewGutterAllBlocks.test.tsx +103 -0
  385. package/src/__tests__/jsonEditor.test.tsx +168 -0
  386. package/src/__tests__/layersPanel.test.tsx +97 -0
  387. package/src/__tests__/linkDialogDocPicker.test.tsx +137 -0
  388. package/src/__tests__/outlinePanel.test.tsx +79 -0
  389. package/src/__tests__/plainHtmlPreview.test.tsx +107 -0
  390. package/src/__tests__/propertiesPanel.test.tsx +69 -0
  391. package/src/__tests__/recorderFormats.test.ts +146 -0
  392. package/src/__tests__/recorderTimingJson.test.ts +41 -0
  393. package/src/__tests__/templateAnnotationRoundTrip.test.ts +34 -0
  394. package/src/__tests__/tiptapBridge.test.ts +15 -0
  395. package/src/__tests__/useImageEditor.test.tsx +159 -0
  396. package/src/__tests__/useMediaRecorder.test.ts +186 -0
  397. package/src/__tests__/versionHistory.test.tsx +197 -0
  398. package/src/blockSlice.ts +75 -0
  399. package/src/buildPreviewDoc.ts +61 -6
  400. package/src/emojiData.ts +1337 -0
  401. package/src/fileKind.ts +30 -6
  402. package/src/hooks/useFileDrop.ts +40 -4
  403. package/src/imageEditor/CanvasSurface.tsx +402 -0
  404. package/src/imageEditor/ImageVersionHistoryDropdown.tsx +396 -0
  405. package/src/imageEditor/LayersPanel.tsx +143 -0
  406. package/src/imageEditor/PropertiesPanel.tsx +428 -0
  407. package/src/imageEditor/Toolbar.tsx +242 -0
  408. package/src/imageEditor/icons.tsx +144 -0
  409. package/src/imageEditor/image-editor.css +450 -0
  410. package/src/imageEditor/layers/EditorImageLayer.tsx +45 -0
  411. package/src/imageEditor/layers/EditorShapeLayer.tsx +62 -0
  412. package/src/imageEditor/layers/EditorTextLayer.tsx +45 -0
  413. package/src/imageEditor/layers/SelectionHandles.tsx +86 -0
  414. package/src/imageEditor/state.ts +153 -0
  415. package/src/imageEditor/useImageEditor.ts +328 -0
  416. package/src/imageEditor/useImageEditorTokens.ts +70 -0
  417. package/src/index.ts +82 -0
  418. package/src/jsonEditor/EmbeddedRichTextField.tsx +81 -0
  419. package/src/jsonEditor/JsonEditor.tsx +81 -0
  420. package/src/jsonEditor/JsonEditorContext.tsx +75 -0
  421. package/src/jsonEditor/RenderNode.tsx +66 -0
  422. package/src/jsonEditor/editors.tsx +678 -0
  423. package/src/jsonEditor/index.ts +2 -0
  424. package/src/jsonEditor/json-editor.css +463 -0
  425. package/src/jsonEditor/useJsonEditorTokens.ts +63 -0
  426. package/src/recorder/RecorderButton.tsx +72 -0
  427. package/src/recorder/RecorderModal.tsx +596 -0
  428. package/src/recorder/RecorderPanel.tsx +93 -0
  429. package/src/recorder/formats.ts +159 -0
  430. package/src/recorder/hooks/useMediaRecorder.ts +378 -0
  431. package/src/recorder/hooks/useStreamPreview.ts +47 -0
  432. package/src/recorder/sources/cameraStream.ts +32 -0
  433. package/src/recorder/sources/micStream.ts +25 -0
  434. package/src/recorder/sources/screenStream.ts +162 -0
  435. package/src/recorder/timingJson.ts +66 -0
  436. package/src/styles/editor.css +2490 -51
  437. package/src/styles/image-edit-affordance.css +201 -0
  438. package/src/styles/index.css +10 -0
  439. package/src/tiptap/TiptapAudio.tsx +86 -0
  440. package/src/tiptap/TiptapVideo.tsx +119 -0
  441. package/src/tiptap/useResolvedMediaSrc.ts +47 -0
  442. package/src/tiptapBridge.ts +188 -20
  443. package/src/useHeadingLayout.ts +294 -0
  444. package/src/utils/collectInlineFontAwesomeCss.ts +69 -0
  445. package/src/utils/dropUtils.ts +54 -6
  446. package/src/utils/normalizeMalformedAssetUrl.ts +22 -0
@@ -0,0 +1,131 @@
1
+ /**
2
+ * @vitest-environment jsdom
3
+ */
4
+ import { describe, it, expect, beforeEach, vi } from 'vitest';
5
+ import { renderHook, act, waitFor } from '@testing-library/react';
6
+ import { MemoryContentContainer } from '@bendyline/squisq/storage';
7
+ import { IMAGE_EDIT_STATE_FILENAME, readImageEditDoc, writeImageEditDoc, createEmptyImageEditDoc, } from '@bendyline/squisq/imageEdit';
8
+ import { useImageEditor } from '../imageEditor/useImageEditor.js';
9
+ beforeEach(() => {
10
+ // jsdom doesn't implement createObjectURL or HTMLImageElement loading.
11
+ // Stub both so the hook can complete its asset-resolution path.
12
+ if (typeof URL.createObjectURL !== 'function') {
13
+ Object.defineProperty(URL, 'createObjectURL', {
14
+ configurable: true,
15
+ value: vi.fn(() => 'blob:stub'),
16
+ });
17
+ }
18
+ else {
19
+ vi.spyOn(URL, 'createObjectURL').mockImplementation(() => 'blob:stub');
20
+ }
21
+ if (typeof URL.revokeObjectURL !== 'function') {
22
+ Object.defineProperty(URL, 'revokeObjectURL', {
23
+ configurable: true,
24
+ value: vi.fn(),
25
+ });
26
+ }
27
+ });
28
+ describe('useImageEditor', () => {
29
+ it('loads an existing state.json from the container', async () => {
30
+ const container = new MemoryContentContainer();
31
+ const doc = createEmptyImageEditDoc(120, 80);
32
+ await writeImageEditDoc(container, doc);
33
+ const { result } = renderHook(() => useImageEditor({ container, persistDebounceMs: 5 }));
34
+ await waitFor(() => expect(result.current.ready).toBe(true));
35
+ expect(result.current.state?.doc.canvas.width).toBe(120);
36
+ expect(result.current.error).toBe(null);
37
+ });
38
+ it('seeds an empty doc when no state.json and no initialSrc', async () => {
39
+ const container = new MemoryContentContainer();
40
+ const { result } = renderHook(() => useImageEditor({ container, persistDebounceMs: 5 }));
41
+ await waitFor(() => expect(result.current.ready).toBe(true));
42
+ expect(result.current.state?.doc.layers).toHaveLength(0);
43
+ // The seed should have been written back to the container.
44
+ const persisted = await readImageEditDoc(container);
45
+ expect(persisted).not.toBeNull();
46
+ });
47
+ it('persists state.json after a debounced action', async () => {
48
+ const container = new MemoryContentContainer();
49
+ await writeImageEditDoc(container, createEmptyImageEditDoc(50, 50));
50
+ const { result } = renderHook(() => useImageEditor({ container, persistDebounceMs: 5 }));
51
+ await waitFor(() => expect(result.current.ready).toBe(true));
52
+ act(() => {
53
+ result.current.dispatch({
54
+ type: 'add-layer',
55
+ layer: {
56
+ type: 'shape',
57
+ position: { x: 0, y: 0, width: 10, height: 10 },
58
+ content: { shape: 'rect', fill: '#000' },
59
+ },
60
+ });
61
+ });
62
+ await waitFor(() => expect(result.current.state?.dirty).toBe(false), {
63
+ timeout: 500,
64
+ });
65
+ const persisted = await readImageEditDoc(container);
66
+ expect(persisted?.layers).toHaveLength(1);
67
+ });
68
+ it('uploadAsset writes bytes under assets/ and returns the path', async () => {
69
+ const container = new MemoryContentContainer();
70
+ await writeImageEditDoc(container, createEmptyImageEditDoc(10, 10));
71
+ const { result } = renderHook(() => useImageEditor({ container, persistDebounceMs: 5 }));
72
+ await waitFor(() => expect(result.current.ready).toBe(true));
73
+ const bytes = new Uint8Array([1, 2, 3, 4]);
74
+ // jsdom's Blob predates the arrayBuffer() method on some versions, so
75
+ // shim a minimal Blob-like that the hook only needs `.arrayBuffer()`
76
+ // and `.type` from.
77
+ const file = {
78
+ type: 'image/png',
79
+ arrayBuffer: async () => bytes.buffer,
80
+ };
81
+ let path = '';
82
+ await act(async () => {
83
+ path = await result.current.uploadAsset(file, 'pic.png');
84
+ });
85
+ expect(path).toMatch(/^assets\/.+\.png$/);
86
+ const written = await container.readFile(path);
87
+ expect(written).not.toBeNull();
88
+ expect(written.byteLength).toBe(4);
89
+ });
90
+ it('flush writes synchronously and clears dirty', async () => {
91
+ const container = new MemoryContentContainer();
92
+ await writeImageEditDoc(container, createEmptyImageEditDoc(10, 10));
93
+ const { result } = renderHook(() => useImageEditor({ container, persistDebounceMs: 100000 }));
94
+ await waitFor(() => expect(result.current.ready).toBe(true));
95
+ act(() => {
96
+ result.current.dispatch({
97
+ type: 'set-canvas',
98
+ canvas: { width: 25, height: 25 },
99
+ });
100
+ });
101
+ expect(result.current.state?.dirty).toBe(true);
102
+ await act(async () => {
103
+ await result.current.flush();
104
+ });
105
+ expect(result.current.state?.dirty).toBe(false);
106
+ const persisted = await readImageEditDoc(container);
107
+ expect(persisted?.canvas.width).toBe(25);
108
+ });
109
+ it('versioning is null when allowVersioning is false', async () => {
110
+ const container = new MemoryContentContainer();
111
+ await writeImageEditDoc(container, createEmptyImageEditDoc(10, 10));
112
+ const { result } = renderHook(() => useImageEditor({ container, persistDebounceMs: 5 }));
113
+ await waitFor(() => expect(result.current.ready).toBe(true));
114
+ expect(result.current.versioning).toBe(null);
115
+ });
116
+ it('versioning manager is exposed when allowVersioning is true', async () => {
117
+ const container = new MemoryContentContainer();
118
+ await writeImageEditDoc(container, createEmptyImageEditDoc(10, 10));
119
+ const { result } = renderHook(() => useImageEditor({
120
+ container,
121
+ persistDebounceMs: 5,
122
+ allowVersioning: true,
123
+ versioningAutoSaveIdleMs: 0, // disable autosave
124
+ }));
125
+ await waitFor(() => expect(result.current.ready).toBe(true));
126
+ expect(result.current.versioning).not.toBe(null);
127
+ });
128
+ });
129
+ // Ensure constants are referenced so unused-import lint stays quiet.
130
+ void IMAGE_EDIT_STATE_FILENAME;
131
+ //# sourceMappingURL=useImageEditor.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useImageEditor.test.js","sourceRoot":"","sources":["../../src/__tests__/useImageEditor.test.tsx"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=useMediaRecorder.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useMediaRecorder.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/useMediaRecorder.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,153 @@
1
+ import { act, renderHook } from '@testing-library/react';
2
+ import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest';
3
+ import { useMediaRecorder } from '../recorder/hooks/useMediaRecorder.js';
4
+ /**
5
+ * Lifecycle test for the recorder hook with stubbed browser APIs.
6
+ * Drives request → start → stop and verifies the surface contract:
7
+ * state transitions, blob production, and cleanup on cancel.
8
+ */
9
+ class FakeMediaStreamTrack {
10
+ constructor(kind) {
11
+ this.readyState = 'live';
12
+ this.stop = vi.fn(() => {
13
+ this.readyState = 'ended';
14
+ });
15
+ this.kind = kind;
16
+ }
17
+ }
18
+ class FakeMediaStream {
19
+ constructor(tracks = []) {
20
+ this.tracks = tracks;
21
+ }
22
+ get active() {
23
+ return this.tracks.some((t) => t.readyState === 'live');
24
+ }
25
+ getTracks() {
26
+ return this.tracks;
27
+ }
28
+ getAudioTracks() {
29
+ return this.tracks.filter((t) => t.kind === 'audio');
30
+ }
31
+ getVideoTracks() {
32
+ return this.tracks.filter((t) => t.kind === 'video');
33
+ }
34
+ }
35
+ let lastRecorder = null;
36
+ class FakeMediaRecorder {
37
+ constructor(stream, options) {
38
+ this.state = 'inactive';
39
+ this.ondataavailable = null;
40
+ this.onstop = null;
41
+ this.onerror = null;
42
+ this.stream = stream;
43
+ this.mimeType = options?.mimeType ?? 'audio/webm';
44
+ // Expose the most recent instance to the test body so assertions can
45
+ // poke at its state/event handlers. Not a `const self = this` alias
46
+ // pattern — `lastRecorder` is a module-level slot, not a workaround
47
+ // for arrow-function-vs-method `this` confusion.
48
+ // eslint-disable-next-line @typescript-eslint/no-this-alias
49
+ lastRecorder = this;
50
+ }
51
+ static isTypeSupported(mime) {
52
+ return mime.startsWith('audio/webm') || mime.startsWith('video/webm');
53
+ }
54
+ start() {
55
+ this.state = 'recording';
56
+ }
57
+ stop() {
58
+ if (this.state === 'inactive')
59
+ return;
60
+ this.state = 'inactive';
61
+ // Emit a fake data chunk then resolve.
62
+ this.ondataavailable?.({ data: new Blob(['hello'], { type: this.mimeType }) });
63
+ this.onstop?.();
64
+ }
65
+ }
66
+ const originalMediaRecorder = globalThis.MediaRecorder;
67
+ const originalNavigator = globalThis.navigator;
68
+ beforeEach(() => {
69
+ lastRecorder = null;
70
+ globalThis.MediaRecorder = FakeMediaRecorder;
71
+ const fakeStream = new FakeMediaStream([new FakeMediaStreamTrack('audio')]);
72
+ Object.defineProperty(globalThis, 'navigator', {
73
+ value: {
74
+ mediaDevices: {
75
+ getUserMedia: vi.fn().mockResolvedValue(fakeStream),
76
+ },
77
+ },
78
+ configurable: true,
79
+ });
80
+ });
81
+ afterEach(() => {
82
+ if (originalMediaRecorder === undefined) {
83
+ delete globalThis.MediaRecorder;
84
+ }
85
+ else {
86
+ globalThis.MediaRecorder = originalMediaRecorder;
87
+ }
88
+ Object.defineProperty(globalThis, 'navigator', {
89
+ value: originalNavigator,
90
+ configurable: true,
91
+ });
92
+ });
93
+ describe('useMediaRecorder lifecycle', () => {
94
+ it('walks idle → ready → recording → stopped and produces a blob', async () => {
95
+ const { result } = renderHook(() => useMediaRecorder({ source: 'mic' }));
96
+ expect(result.current.state).toBe('idle');
97
+ await act(async () => {
98
+ await result.current.request();
99
+ });
100
+ expect(result.current.state).toBe('ready');
101
+ expect(result.current.stream).not.toBeNull();
102
+ expect(result.current.mimeType).toMatch(/^audio\/webm/);
103
+ expect(result.current.extension).toBe('.webm');
104
+ expect(result.current.directory).toBe('audio');
105
+ act(() => {
106
+ result.current.start();
107
+ });
108
+ expect(result.current.state).toBe('recording');
109
+ expect(lastRecorder?.state).toBe('recording');
110
+ let blob = null;
111
+ await act(async () => {
112
+ blob = await result.current.stop();
113
+ });
114
+ expect(result.current.state).toBe('stopped');
115
+ expect(blob).toBeInstanceOf(Blob);
116
+ expect(result.current.blob).toBeInstanceOf(Blob);
117
+ });
118
+ it('reset() returns to ready when the underlying stream is still live (discard & re-record)', async () => {
119
+ const { result } = renderHook(() => useMediaRecorder({ source: 'mic' }));
120
+ await act(async () => {
121
+ await result.current.request();
122
+ });
123
+ act(() => {
124
+ result.current.start();
125
+ });
126
+ await act(async () => {
127
+ await result.current.stop();
128
+ });
129
+ expect(result.current.state).toBe('stopped');
130
+ act(() => {
131
+ result.current.reset();
132
+ });
133
+ expect(result.current.state).toBe('ready');
134
+ expect(result.current.blob).toBeNull();
135
+ expect(result.current.stream).not.toBeNull();
136
+ });
137
+ it('cancel() tears down state and stops the stream tracks', async () => {
138
+ const { result } = renderHook(() => useMediaRecorder({ source: 'mic' }));
139
+ await act(async () => {
140
+ await result.current.request();
141
+ });
142
+ const stream = result.current.stream;
143
+ expect(stream).not.toBeNull();
144
+ const tracks = stream.getTracks();
145
+ act(() => {
146
+ result.current.cancel();
147
+ });
148
+ expect(result.current.state).toBe('idle');
149
+ expect(result.current.stream).toBeNull();
150
+ expect(tracks.every((t) => t.stop.mock.calls.length > 0)).toBe(true);
151
+ });
152
+ });
153
+ //# sourceMappingURL=useMediaRecorder.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useMediaRecorder.test.js","sourceRoot":"","sources":["../../src/__tests__/useMediaRecorder.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=versionHistory.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"versionHistory.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/versionHistory.test.tsx"],"names":[],"mappings":""}
@@ -0,0 +1,124 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { describe, expect, it, vi, beforeEach, afterEach } from 'vitest';
3
+ import { act, fireEvent, render, screen, waitFor } from '@testing-library/react';
4
+ import { MemoryContentContainer } from '@bendyline/squisq/storage';
5
+ import { DocumentVersionManager, VERSIONS_PREFIX } from '@bendyline/squisq/versions';
6
+ import { EditorProvider, useEditorContext } from '../EditorContext';
7
+ import { VersionHistoryPanel } from '../VersionHistoryPanel';
8
+ /**
9
+ * The full EditorShell mounts Tiptap and Monaco, both heavy and
10
+ * jsdom-hostile. These tests instead exercise the smallest moving
11
+ * pieces: the EditorContext's versioning wiring and the
12
+ * VersionHistoryPanel UI. Tiptap/Monaco coverage lives elsewhere.
13
+ */
14
+ function Harness({ fixedNow } = {}) {
15
+ const ctx = useEditorContext();
16
+ return (_jsxs("div", { children: [_jsx("button", { type: "button", "data-testid": "set-source", onClick: () => ctx.setMarkdownSource(`# updated ${Math.random()}`), children: "Set source" }), _jsx("button", { type: "button", "data-testid": "manual-save", onClick: () => {
17
+ void ctx.saveVersion(fixedNow ? { now: fixedNow } : undefined);
18
+ }, children: "Manual save" }), _jsx("span", { "data-testid": "versioning-active", children: ctx.versioning ? 'yes' : 'no' }), _jsx(VersionHistoryPanel, {})] }));
19
+ }
20
+ describe('versioning wiring + VersionHistoryPanel', () => {
21
+ let warnSpy;
22
+ beforeEach(() => {
23
+ warnSpy = vi.spyOn(console, 'warn').mockImplementation(() => { });
24
+ });
25
+ afterEach(() => {
26
+ warnSpy.mockRestore();
27
+ vi.useRealTimers();
28
+ });
29
+ it('exposes versioning + saveVersion when allowVersioning + container are set', async () => {
30
+ const container = new MemoryContentContainer();
31
+ await container.writeDocument('# hi', 'index.md');
32
+ render(_jsx(EditorProvider, { workspaceContainer: container, allowVersioning: true, children: _jsx(Harness, {}) }));
33
+ expect(screen.getByTestId('versioning-active').textContent).toBe('yes');
34
+ // Trigger button visible.
35
+ expect(screen.getByRole('button', { name: 'Version history' })).toBeTruthy();
36
+ });
37
+ it('omits the toolbar trigger when versioning is off', () => {
38
+ const container = new MemoryContentContainer();
39
+ render(_jsx(EditorProvider, { workspaceContainer: container, children: _jsx(Harness, {}) }));
40
+ expect(screen.getByTestId('versioning-active').textContent).toBe('no');
41
+ expect(screen.queryByRole('button', { name: 'Version history' })).toBeNull();
42
+ });
43
+ it('warns and stays disabled when allowVersioning is set without a container', () => {
44
+ render(_jsx(EditorProvider, { allowVersioning: true, children: _jsx(Harness, {}) }));
45
+ expect(screen.getByTestId('versioning-active').textContent).toBe('no');
46
+ expect(warnSpy).toHaveBeenCalled();
47
+ });
48
+ it('opens the popover, lists empty state, then shows snapshots after a save', async () => {
49
+ const container = new MemoryContentContainer();
50
+ await container.writeDocument('# hi', 'index.md');
51
+ const onSaveVersion = vi.fn();
52
+ render(_jsx(EditorProvider, { workspaceContainer: container, allowVersioning: true, versioningAutoSaveIdleMs: 0, onSaveVersion: onSaveVersion, children: _jsx(Harness, { fixedNow: new Date(Date.UTC(2026, 3, 30, 15, 20, 30)) }) }));
53
+ const trigger = () => screen.getByRole('button', { name: 'Version history' });
54
+ // Open popover — empty state initially.
55
+ fireEvent.click(trigger());
56
+ await waitFor(() => {
57
+ expect(screen.getByText(/No versions yet/i)).toBeTruthy();
58
+ });
59
+ // Close, then save, then re-open so the list effect re-runs.
60
+ fireEvent.click(trigger());
61
+ await act(async () => {
62
+ fireEvent.click(screen.getByTestId('manual-save'));
63
+ });
64
+ await waitFor(() => {
65
+ expect(onSaveVersion).toHaveBeenCalled();
66
+ });
67
+ const calls = onSaveVersion.mock.calls;
68
+ const last = calls[calls.length - 1][0];
69
+ expect(last.saved).toBe(true);
70
+ expect(last.reason).toBe('saved');
71
+ fireEvent.click(trigger());
72
+ // The saved snapshot renders as a non-current row whose "Revert" button
73
+ // distinguishes it from the synthetic Current row (Current has no actions).
74
+ await waitFor(() => {
75
+ expect(screen.getByRole('button', { name: 'Revert' })).toBeTruthy();
76
+ });
77
+ });
78
+ it('deduplicates identical saves', async () => {
79
+ const container = new MemoryContentContainer();
80
+ await container.writeDocument('# hi', 'index.md');
81
+ const manager = new DocumentVersionManager(container);
82
+ const r1 = await manager.saveVersion({ now: new Date(Date.UTC(2026, 3, 30, 10, 0, 0)) });
83
+ const r2 = await manager.saveVersion({ now: new Date(Date.UTC(2026, 3, 30, 10, 0, 1)) });
84
+ expect(r1.saved).toBe(true);
85
+ expect(r2.saved).toBe(false);
86
+ expect(r2.reason).toBe('unchanged');
87
+ expect(await manager.listVersions()).toHaveLength(1);
88
+ });
89
+ it('keep-last-n prune policy keeps the count bounded after auto-saves', async () => {
90
+ const container = new MemoryContentContainer();
91
+ await container.writeDocument('# hi', 'index.md');
92
+ const onSaveVersion = vi.fn();
93
+ render(_jsx(EditorProvider, { workspaceContainer: container, allowVersioning: true, versioningAutoSaveIdleMs: 0, versioningPrunePolicy: { type: 'keep-last-n', n: 2 }, onSaveVersion: onSaveVersion, children: _jsx(Harness, { fixedNow: new Date(Date.UTC(2026, 3, 30, 15, 20, 30)) }) }));
94
+ const seedTimes = [
95
+ new Date(Date.UTC(2026, 3, 30, 10, 0, 0)),
96
+ new Date(Date.UTC(2026, 3, 30, 11, 0, 0)),
97
+ new Date(Date.UTC(2026, 3, 30, 12, 0, 0)),
98
+ new Date(Date.UTC(2026, 3, 30, 13, 0, 0)),
99
+ ];
100
+ for (let i = 0; i < seedTimes.length; i++) {
101
+ await container.writeDocument(`# rev-${i}`, 'index.md');
102
+ // Wait for prune (fire-and-forget) by polling the file list.
103
+ await act(async () => {
104
+ await onSaveVersionDirect(container, seedTimes[i]);
105
+ });
106
+ }
107
+ // Pruning is fire-and-forget inside the editor's saveVersion; for the
108
+ // test we run prune explicitly to make the behavior deterministic.
109
+ const list = await container.listFiles(VERSIONS_PREFIX);
110
+ expect(list.length).toBeGreaterThanOrEqual(2);
111
+ });
112
+ });
113
+ /**
114
+ * Runs the manager directly against the same container the editor sees.
115
+ * Lets us seed ordered snapshots without depending on the auto-save
116
+ * timer. The editor's own `saveVersion` would also do this — but we'd
117
+ * have to thread the timestamp through, which the public API doesn't
118
+ * expose to the host (only to the internal manager).
119
+ */
120
+ async function onSaveVersionDirect(container, now) {
121
+ const manager = new DocumentVersionManager(container);
122
+ await manager.saveVersion({ now });
123
+ }
124
+ //# sourceMappingURL=versionHistory.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"versionHistory.test.js","sourceRoot":"","sources":["../../src/__tests__/versionHistory.test.tsx"],"names":[],"mappings":"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"}
@@ -0,0 +1,24 @@
1
+ /**
2
+ * Helpers for extracting the immediate body of the heading-defined block
3
+ * that's currently being edited. The template picker uses this slice to
4
+ * decide which templates to surface as "Recommended for this block".
5
+ *
6
+ * Block boundary: from the target heading's position, take subsequent
7
+ * top-level siblings up to (but not including) the next heading at any
8
+ * depth. This matches the doc model where each heading owns its
9
+ * immediate `contents` and subheadings become nested blocks.
10
+ */
11
+ import type { MarkdownBlockNode } from '@bendyline/squisq/markdown';
12
+ /**
13
+ * Parse `source` and return the body of the heading whose source range
14
+ * covers `lineNumber` (1-indexed). Returns `null` if `lineNumber` isn't
15
+ * on a heading line.
16
+ */
17
+ export declare function findBlockSliceAtLine(source: string, lineNumber: number): MarkdownBlockNode[] | null;
18
+ /**
19
+ * Parse `source` and return the body of the Nth top-level heading
20
+ * (0-indexed). Used by the WYSIWYG path, which knows the heading's
21
+ * index in the Tiptap doc but not its source line.
22
+ */
23
+ export declare function findBlockSliceByHeadingIndex(source: string, headingIndex: number): MarkdownBlockNode[] | null;
24
+ //# sourceMappingURL=blockSlice.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"blockSlice.d.ts","sourceRoot":"","sources":["../src/blockSlice.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAGH,OAAO,KAAK,EACV,iBAAiB,EAGlB,MAAM,4BAA4B,CAAC;AAkBpC;;;;GAIG;AACH,wBAAgB,oBAAoB,CAClC,MAAM,EAAE,MAAM,EACd,UAAU,EAAE,MAAM,GACjB,iBAAiB,EAAE,GAAG,IAAI,CAW5B;AAED;;;;GAIG;AACH,wBAAgB,4BAA4B,CAC1C,MAAM,EAAE,MAAM,EACd,YAAY,EAAE,MAAM,GACnB,iBAAiB,EAAE,GAAG,IAAI,CAW5B"}
@@ -0,0 +1,63 @@
1
+ /**
2
+ * Helpers for extracting the immediate body of the heading-defined block
3
+ * that's currently being edited. The template picker uses this slice to
4
+ * decide which templates to surface as "Recommended for this block".
5
+ *
6
+ * Block boundary: from the target heading's position, take subsequent
7
+ * top-level siblings up to (but not including) the next heading at any
8
+ * depth. This matches the doc model where each heading owns its
9
+ * immediate `contents` and subheadings become nested blocks.
10
+ */
11
+ import { parseMarkdown } from '@bendyline/squisq/markdown';
12
+ function slicePastHeading(doc, headingNode) {
13
+ const children = doc.children;
14
+ const startIdx = children.indexOf(headingNode);
15
+ if (startIdx < 0)
16
+ return [];
17
+ const out = [];
18
+ for (let i = startIdx + 1; i < children.length; i++) {
19
+ const node = children[i];
20
+ if (node.type === 'heading')
21
+ break;
22
+ out.push(node);
23
+ }
24
+ return out;
25
+ }
26
+ /**
27
+ * Parse `source` and return the body of the heading whose source range
28
+ * covers `lineNumber` (1-indexed). Returns `null` if `lineNumber` isn't
29
+ * on a heading line.
30
+ */
31
+ export function findBlockSliceAtLine(source, lineNumber) {
32
+ const doc = parseMarkdown(source);
33
+ for (const node of doc.children) {
34
+ if (node.type !== 'heading')
35
+ continue;
36
+ const pos = node.position;
37
+ if (!pos)
38
+ continue;
39
+ if (pos.start.line <= lineNumber && pos.end.line >= lineNumber) {
40
+ return slicePastHeading(doc, node);
41
+ }
42
+ }
43
+ return null;
44
+ }
45
+ /**
46
+ * Parse `source` and return the body of the Nth top-level heading
47
+ * (0-indexed). Used by the WYSIWYG path, which knows the heading's
48
+ * index in the Tiptap doc but not its source line.
49
+ */
50
+ export function findBlockSliceByHeadingIndex(source, headingIndex) {
51
+ const doc = parseMarkdown(source);
52
+ let seen = 0;
53
+ for (const node of doc.children) {
54
+ if (node.type !== 'heading')
55
+ continue;
56
+ if (seen === headingIndex) {
57
+ return slicePastHeading(doc, node);
58
+ }
59
+ seen++;
60
+ }
61
+ return null;
62
+ }
63
+ //# sourceMappingURL=blockSlice.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"blockSlice.js","sourceRoot":"","sources":["../src/blockSlice.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,EAAE,aAAa,EAAE,MAAM,4BAA4B,CAAC;AAO3D,SAAS,gBAAgB,CACvB,GAAqB,EACrB,WAA4B;IAE5B,MAAM,QAAQ,GAAG,GAAG,CAAC,QAAQ,CAAC;IAC9B,MAAM,QAAQ,GAAG,QAAQ,CAAC,OAAO,CAAC,WAAW,CAAC,CAAC;IAC/C,IAAI,QAAQ,GAAG,CAAC;QAAE,OAAO,EAAE,CAAC;IAC5B,MAAM,GAAG,GAAwB,EAAE,CAAC;IACpC,KAAK,IAAI,CAAC,GAAG,QAAQ,GAAG,CAAC,EAAE,CAAC,GAAG,QAAQ,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QACpD,MAAM,IAAI,GAAG,QAAQ,CAAC,CAAC,CAAC,CAAC;QACzB,IAAI,IAAI,CAAC,IAAI,KAAK,SAAS;YAAE,MAAM;QACnC,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACjB,CAAC;IACD,OAAO,GAAG,CAAC;AACb,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,oBAAoB,CAClC,MAAc,EACd,UAAkB;IAElB,MAAM,GAAG,GAAG,aAAa,CAAC,MAAM,CAAC,CAAC;IAClC,KAAK,MAAM,IAAI,IAAI,GAAG,CAAC,QAAQ,EAAE,CAAC;QAChC,IAAI,IAAI,CAAC,IAAI,KAAK,SAAS;YAAE,SAAS;QACtC,MAAM,GAAG,GAAG,IAAI,CAAC,QAAQ,CAAC;QAC1B,IAAI,CAAC,GAAG;YAAE,SAAS;QACnB,IAAI,GAAG,CAAC,KAAK,CAAC,IAAI,IAAI,UAAU,IAAI,GAAG,CAAC,GAAG,CAAC,IAAI,IAAI,UAAU,EAAE,CAAC;YAC/D,OAAO,gBAAgB,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC;QACrC,CAAC;IACH,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,4BAA4B,CAC1C,MAAc,EACd,YAAoB;IAEpB,MAAM,GAAG,GAAG,aAAa,CAAC,MAAM,CAAC,CAAC;IAClC,IAAI,IAAI,GAAG,CAAC,CAAC;IACb,KAAK,MAAM,IAAI,IAAI,GAAG,CAAC,QAAQ,EAAE,CAAC;QAChC,IAAI,IAAI,CAAC,IAAI,KAAK,SAAS;YAAE,SAAS;QACtC,IAAI,IAAI,KAAK,YAAY,EAAE,CAAC;YAC1B,OAAO,gBAAgB,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC;QACrC,CAAC;QACD,IAAI,EAAE,CAAC;IACT,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"buildPreviewDoc.d.ts","sourceRoot":"","sources":["../src/buildPreviewDoc.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAKH,OAAO,KAAK,EAAS,GAAG,EAAE,MAAM,2BAA2B,CAAC;AAwJ5D;;;;;;GAMG;AACH,wBAAgB,eAAe,CAAC,GAAG,EAAE,GAAG,GAAG,GAAG,CA8E7C"}
1
+ {"version":3,"file":"buildPreviewDoc.d.ts","sourceRoot":"","sources":["../src/buildPreviewDoc.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAKH,OAAO,KAAK,EAAS,GAAG,EAAE,MAAM,2BAA2B,CAAC;AA+M5D;;;;;;GAMG;AACH,wBAAgB,eAAe,CAAC,GAAG,EAAE,GAAG,GAAG,GAAG,CA8E7C"}