@milkdown/crepe 7.7.0 → 7.9.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 (309) hide show
  1. package/lib/cjs/confirm-CNveM9QH.js +26 -0
  2. package/lib/cjs/confirm-CNveM9QH.js.map +1 -0
  3. package/lib/cjs/edit-BUtBJHpV.js +24 -0
  4. package/lib/cjs/edit-BUtBJHpV.js.map +1 -0
  5. package/lib/cjs/functions-BAY51plB.js +39 -0
  6. package/lib/cjs/functions-BAY51plB.js.map +1 -0
  7. package/lib/cjs/image-BXLkOVnO.js +24 -0
  8. package/lib/cjs/image-BXLkOVnO.js.map +1 -0
  9. package/lib/cjs/{index-Dac851tb.js → index-B7gqgc1H.js} +494 -204
  10. package/lib/cjs/index-B7gqgc1H.js.map +1 -0
  11. package/lib/cjs/{index-Dub20F3z.js → index-B91KhPew.js} +4 -4
  12. package/lib/cjs/index-B91KhPew.js.map +1 -0
  13. package/lib/cjs/{index-nrFkJeLW.js → index-BsrJn8Jp.js} +22 -7
  14. package/lib/cjs/index-BsrJn8Jp.js.map +1 -0
  15. package/lib/cjs/{index-BuSAwj4j.js → index-C2CAbC2F.js} +8 -1
  16. package/lib/cjs/index-C2CAbC2F.js.map +1 -0
  17. package/lib/cjs/{index-ooYXC5xk.js → index-CnyNb_OH.js} +45 -45
  18. package/lib/cjs/index-CnyNb_OH.js.map +1 -0
  19. package/lib/cjs/{index-7pgPMFV4.js → index-CoTb-QdE.js} +123 -105
  20. package/lib/cjs/index-CoTb-QdE.js.map +1 -0
  21. package/lib/cjs/index-DEs_IHHy.js +91 -0
  22. package/lib/cjs/index-DEs_IHHy.js.map +1 -0
  23. package/lib/cjs/index-DGAwtnNK.js +349 -0
  24. package/lib/cjs/index-DGAwtnNK.js.map +1 -0
  25. package/lib/cjs/index-DLIudQKW.js +126 -0
  26. package/lib/cjs/index-DLIudQKW.js.map +1 -0
  27. package/lib/cjs/index-Dw6lXgs6.js +81 -0
  28. package/lib/cjs/index-Dw6lXgs6.js.map +1 -0
  29. package/lib/cjs/{index-AlHHvSR_.js → index-xbwf60wt.js} +1 -6
  30. package/lib/cjs/{index-AlHHvSR_.js.map → index-xbwf60wt.js.map} +1 -1
  31. package/lib/cjs/{index-CvmlYYXX.js → index-xbxqAqH2.js} +21 -7
  32. package/lib/cjs/index-xbxqAqH2.js.map +1 -0
  33. package/lib/cjs/index.js +6 -6
  34. package/lib/cjs/plus-XLomtlXf.js +24 -0
  35. package/lib/cjs/plus-XLomtlXf.js.map +1 -0
  36. package/lib/cjs/remove-Ba-ypwBf.js +17 -0
  37. package/lib/cjs/remove-Ba-ypwBf.js.map +1 -0
  38. package/lib/esm/confirm-DtE-HkVd.js +24 -0
  39. package/lib/esm/confirm-DtE-HkVd.js.map +1 -0
  40. package/lib/esm/edit-D--t_JAb.js +22 -0
  41. package/lib/esm/edit-D--t_JAb.js.map +1 -0
  42. package/lib/esm/functions-DlJPkGmE.js +36 -0
  43. package/lib/esm/functions-DlJPkGmE.js.map +1 -0
  44. package/lib/esm/image-DoB1o1sl.js +22 -0
  45. package/lib/esm/image-DoB1o1sl.js.map +1 -0
  46. package/lib/esm/index-BAQT-9au.js +347 -0
  47. package/lib/esm/index-BAQT-9au.js.map +1 -0
  48. package/lib/esm/{index-DOrkOhki.js → index-BCvtgOeI.js} +4 -4
  49. package/lib/esm/index-BCvtgOeI.js.map +1 -0
  50. package/lib/esm/{index-s33c_M2f.js → index-BDZ_pnSv.js} +122 -104
  51. package/lib/esm/index-BDZ_pnSv.js.map +1 -0
  52. package/lib/esm/{index-D6fLMv29.js → index-BPG8iO8t.js} +2 -6
  53. package/lib/esm/{index-D6fLMv29.js.map → index-BPG8iO8t.js.map} +1 -1
  54. package/lib/esm/{index-DcRgwPLd.js → index-BUBXHhHG.js} +18 -3
  55. package/lib/esm/index-BUBXHhHG.js.map +1 -0
  56. package/lib/esm/{index-CxJ9fxJm.js → index-Bvz1Yyiz.js} +8 -1
  57. package/lib/esm/index-Bvz1Yyiz.js.map +1 -0
  58. package/lib/esm/index-C1aVAv1l.js +124 -0
  59. package/lib/esm/index-C1aVAv1l.js.map +1 -0
  60. package/lib/esm/{index-uHWmZXqe.js → index-CM4urRY9.js} +480 -190
  61. package/lib/esm/index-CM4urRY9.js.map +1 -0
  62. package/lib/esm/{index-BFsG6770.js → index-ChR5Qhyf.js} +17 -3
  63. package/lib/esm/index-ChR5Qhyf.js.map +1 -0
  64. package/lib/esm/index-CwMVnVeI.js +89 -0
  65. package/lib/esm/index-CwMVnVeI.js.map +1 -0
  66. package/lib/esm/{index-CLpluqvF.js → index-Dc_wWopW.js} +46 -46
  67. package/lib/esm/index-Dc_wWopW.js.map +1 -0
  68. package/lib/esm/index-E8UgFLeN.js +79 -0
  69. package/lib/esm/index-E8UgFLeN.js.map +1 -0
  70. package/lib/esm/index.js +6 -6
  71. package/lib/esm/plus-lrX0Q75O.js +22 -0
  72. package/lib/esm/plus-lrX0Q75O.js.map +1 -0
  73. package/lib/esm/remove-D3g0Cd6_.js +15 -0
  74. package/lib/esm/remove-D3g0Cd6_.js.map +1 -0
  75. package/lib/theme/_internal/classic-common.css +7 -1
  76. package/lib/theme/common/block-edit.css +23 -23
  77. package/lib/theme/common/code-mirror.css +43 -44
  78. package/lib/theme/common/cursor.css +5 -0
  79. package/lib/theme/common/image-block.css +79 -81
  80. package/lib/theme/common/latex.css +6 -6
  81. package/lib/theme/common/link-tooltip.css +21 -21
  82. package/lib/theme/common/list-item.css +11 -10
  83. package/lib/theme/common/table.css +39 -39
  84. package/lib/theme/common/toolbar.css +8 -8
  85. package/lib/tsconfig.tsbuildinfo +1 -0
  86. package/lib/types/core/crepe.d.ts +6 -6
  87. package/lib/types/core/crepe.d.ts.map +1 -1
  88. package/lib/types/core/slice.d.ts.map +1 -1
  89. package/lib/types/feature/block-edit/handle/component.d.ts +4 -8
  90. package/lib/types/feature/block-edit/handle/component.d.ts.map +1 -1
  91. package/lib/types/feature/block-edit/handle/index.d.ts +1 -1
  92. package/lib/types/feature/block-edit/handle/index.d.ts.map +1 -1
  93. package/lib/types/feature/block-edit/index.d.ts.map +1 -1
  94. package/lib/types/feature/block-edit/menu/component.d.ts +8 -11
  95. package/lib/types/feature/block-edit/menu/component.d.ts.map +1 -1
  96. package/lib/types/feature/block-edit/menu/config.d.ts.map +1 -1
  97. package/lib/types/feature/block-edit/menu/index.d.ts.map +1 -1
  98. package/lib/types/feature/block-edit/menu/utils.d.ts +2 -3
  99. package/lib/types/feature/block-edit/menu/utils.d.ts.map +1 -1
  100. package/lib/types/feature/code-mirror/index.d.ts +3 -4
  101. package/lib/types/feature/code-mirror/index.d.ts.map +1 -1
  102. package/lib/types/feature/cursor/index.d.ts +1 -0
  103. package/lib/types/feature/cursor/index.d.ts.map +1 -1
  104. package/lib/types/feature/image-block/index.d.ts.map +1 -1
  105. package/lib/types/feature/index.d.ts +4 -4
  106. package/lib/types/feature/index.d.ts.map +1 -1
  107. package/lib/types/feature/latex/index.d.ts.map +1 -1
  108. package/lib/types/feature/latex/inline-tooltip/component.d.ts +6 -10
  109. package/lib/types/feature/latex/inline-tooltip/component.d.ts.map +1 -1
  110. package/lib/types/feature/latex/inline-tooltip/view.d.ts.map +1 -1
  111. package/lib/types/feature/latex/input-rule.d.ts.map +1 -1
  112. package/lib/types/feature/latex/remark.d.ts.map +1 -1
  113. package/lib/types/feature/link-tooltip/index.d.ts.map +1 -1
  114. package/lib/types/feature/list-item/index.d.ts.map +1 -1
  115. package/lib/types/feature/placeholder/index.d.ts.map +1 -1
  116. package/lib/types/feature/shared.d.ts +1 -2
  117. package/lib/types/feature/shared.d.ts.map +1 -1
  118. package/lib/types/feature/table/index.d.ts.map +1 -1
  119. package/lib/types/feature/toolbar/component.d.ts +9 -12
  120. package/lib/types/feature/toolbar/component.d.ts.map +1 -1
  121. package/lib/types/feature/toolbar/index.d.ts.map +1 -1
  122. package/lib/types/icons/align-center.d.ts +1 -1
  123. package/lib/types/icons/align-center.d.ts.map +1 -1
  124. package/lib/types/icons/align-left.d.ts +1 -1
  125. package/lib/types/icons/align-left.d.ts.map +1 -1
  126. package/lib/types/icons/align-right.d.ts +1 -1
  127. package/lib/types/icons/align-right.d.ts.map +1 -1
  128. package/lib/types/icons/bold.d.ts +1 -1
  129. package/lib/types/icons/bold.d.ts.map +1 -1
  130. package/lib/types/icons/bullet-list.d.ts +1 -1
  131. package/lib/types/icons/bullet-list.d.ts.map +1 -1
  132. package/lib/types/icons/bullet.d.ts +1 -1
  133. package/lib/types/icons/bullet.d.ts.map +1 -1
  134. package/lib/types/icons/caption.d.ts +1 -1
  135. package/lib/types/icons/caption.d.ts.map +1 -1
  136. package/lib/types/icons/check-box-checked.d.ts +1 -1
  137. package/lib/types/icons/check-box-checked.d.ts.map +1 -1
  138. package/lib/types/icons/check-box-unchecked.d.ts +1 -1
  139. package/lib/types/icons/check-box-unchecked.d.ts.map +1 -1
  140. package/lib/types/icons/chevron-down.d.ts +1 -1
  141. package/lib/types/icons/chevron-down.d.ts.map +1 -1
  142. package/lib/types/icons/clear.d.ts +1 -1
  143. package/lib/types/icons/clear.d.ts.map +1 -1
  144. package/lib/types/icons/code.d.ts +1 -1
  145. package/lib/types/icons/code.d.ts.map +1 -1
  146. package/lib/types/icons/confirm.d.ts +1 -1
  147. package/lib/types/icons/confirm.d.ts.map +1 -1
  148. package/lib/types/icons/copy.d.ts +1 -1
  149. package/lib/types/icons/copy.d.ts.map +1 -1
  150. package/lib/types/icons/divider.d.ts +1 -1
  151. package/lib/types/icons/divider.d.ts.map +1 -1
  152. package/lib/types/icons/drag-handle.d.ts +1 -1
  153. package/lib/types/icons/drag-handle.d.ts.map +1 -1
  154. package/lib/types/icons/edit.d.ts +1 -1
  155. package/lib/types/icons/edit.d.ts.map +1 -1
  156. package/lib/types/icons/functions.d.ts +1 -1
  157. package/lib/types/icons/functions.d.ts.map +1 -1
  158. package/lib/types/icons/h1.d.ts +1 -1
  159. package/lib/types/icons/h1.d.ts.map +1 -1
  160. package/lib/types/icons/h2.d.ts +1 -1
  161. package/lib/types/icons/h2.d.ts.map +1 -1
  162. package/lib/types/icons/h3.d.ts +1 -1
  163. package/lib/types/icons/h3.d.ts.map +1 -1
  164. package/lib/types/icons/h4.d.ts +1 -1
  165. package/lib/types/icons/h4.d.ts.map +1 -1
  166. package/lib/types/icons/h5.d.ts +1 -1
  167. package/lib/types/icons/h5.d.ts.map +1 -1
  168. package/lib/types/icons/h6.d.ts +1 -1
  169. package/lib/types/icons/h6.d.ts.map +1 -1
  170. package/lib/types/icons/image.d.ts +1 -1
  171. package/lib/types/icons/image.d.ts.map +1 -1
  172. package/lib/types/icons/italic.d.ts +1 -1
  173. package/lib/types/icons/italic.d.ts.map +1 -1
  174. package/lib/types/icons/link.d.ts +1 -1
  175. package/lib/types/icons/link.d.ts.map +1 -1
  176. package/lib/types/icons/menu.d.ts +1 -1
  177. package/lib/types/icons/menu.d.ts.map +1 -1
  178. package/lib/types/icons/ordered-list.d.ts +1 -1
  179. package/lib/types/icons/ordered-list.d.ts.map +1 -1
  180. package/lib/types/icons/plus.d.ts +1 -1
  181. package/lib/types/icons/plus.d.ts.map +1 -1
  182. package/lib/types/icons/quote.d.ts +1 -1
  183. package/lib/types/icons/quote.d.ts.map +1 -1
  184. package/lib/types/icons/remove.d.ts +1 -1
  185. package/lib/types/icons/remove.d.ts.map +1 -1
  186. package/lib/types/icons/search.d.ts +1 -1
  187. package/lib/types/icons/search.d.ts.map +1 -1
  188. package/lib/types/icons/strikethrough.d.ts +1 -1
  189. package/lib/types/icons/strikethrough.d.ts.map +1 -1
  190. package/lib/types/icons/table.d.ts +1 -1
  191. package/lib/types/icons/table.d.ts.map +1 -1
  192. package/lib/types/icons/text.d.ts +1 -1
  193. package/lib/types/icons/text.d.ts.map +1 -1
  194. package/lib/types/icons/todo-list.d.ts +1 -1
  195. package/lib/types/icons/todo-list.d.ts.map +1 -1
  196. package/lib/types/icons/visibility-off.d.ts +1 -1
  197. package/lib/types/icons/visibility-off.d.ts.map +1 -1
  198. package/package.json +5 -26
  199. package/src/core/crepe.ts +13 -12
  200. package/src/core/slice.ts +2 -0
  201. package/src/feature/block-edit/handle/component.tsx +60 -0
  202. package/src/feature/block-edit/handle/index.ts +22 -14
  203. package/src/feature/block-edit/index.ts +3 -1
  204. package/src/feature/block-edit/menu/component.tsx +237 -0
  205. package/src/feature/block-edit/menu/config.ts +6 -3
  206. package/src/feature/block-edit/menu/index.ts +55 -17
  207. package/src/feature/block-edit/menu/utils.ts +3 -3
  208. package/src/feature/code-mirror/index.ts +20 -20
  209. package/src/feature/cursor/index.ts +10 -0
  210. package/src/feature/image-block/index.ts +3 -1
  211. package/src/feature/index.ts +5 -4
  212. package/src/feature/latex/index.ts +8 -8
  213. package/src/feature/latex/inline-tooltip/component.tsx +57 -0
  214. package/src/feature/latex/inline-tooltip/view.ts +30 -17
  215. package/src/feature/latex/input-rule.ts +4 -3
  216. package/src/feature/latex/remark.ts +3 -2
  217. package/src/feature/link-tooltip/index.ts +3 -1
  218. package/src/feature/list-item/index.ts +8 -16
  219. package/src/feature/placeholder/index.ts +6 -3
  220. package/src/feature/shared.ts +1 -2
  221. package/src/feature/table/index.ts +2 -0
  222. package/src/feature/toolbar/component.tsx +256 -0
  223. package/src/feature/toolbar/index.ts +34 -17
  224. package/src/icons/align-center.ts +1 -3
  225. package/src/icons/align-left.ts +1 -3
  226. package/src/icons/align-right.ts +1 -3
  227. package/src/icons/bold.ts +1 -3
  228. package/src/icons/bullet-list.ts +1 -3
  229. package/src/icons/bullet.ts +1 -3
  230. package/src/icons/caption.ts +1 -3
  231. package/src/icons/check-box-checked.ts +1 -3
  232. package/src/icons/check-box-unchecked.ts +1 -3
  233. package/src/icons/chevron-down.ts +1 -3
  234. package/src/icons/clear.ts +1 -3
  235. package/src/icons/code.ts +1 -3
  236. package/src/icons/confirm.ts +1 -3
  237. package/src/icons/copy.ts +1 -3
  238. package/src/icons/divider.ts +1 -3
  239. package/src/icons/drag-handle.ts +1 -3
  240. package/src/icons/edit.ts +1 -3
  241. package/src/icons/functions.ts +1 -3
  242. package/src/icons/h1.ts +1 -3
  243. package/src/icons/h2.ts +1 -3
  244. package/src/icons/h3.ts +1 -3
  245. package/src/icons/h4.ts +1 -3
  246. package/src/icons/h5.ts +1 -3
  247. package/src/icons/h6.ts +1 -3
  248. package/src/icons/image.ts +1 -3
  249. package/src/icons/italic.ts +1 -3
  250. package/src/icons/link.ts +1 -3
  251. package/src/icons/menu.ts +1 -3
  252. package/src/icons/ordered-list.ts +1 -3
  253. package/src/icons/plus.ts +1 -3
  254. package/src/icons/quote.ts +1 -3
  255. package/src/icons/remove.ts +1 -3
  256. package/src/icons/search.ts +1 -3
  257. package/src/icons/strikethrough.ts +1 -3
  258. package/src/icons/table.ts +1 -3
  259. package/src/icons/text.ts +1 -3
  260. package/src/icons/todo-list.ts +1 -3
  261. package/src/icons/visibility-off.ts +1 -3
  262. package/src/theme/_internal/classic-common.css +7 -1
  263. package/src/theme/common/block-edit.css +2 -2
  264. package/src/theme/common/code-mirror.css +5 -6
  265. package/src/theme/common/cursor.css +5 -0
  266. package/src/theme/common/image-block.css +9 -11
  267. package/src/theme/common/latex.css +1 -1
  268. package/src/theme/common/link-tooltip.css +2 -2
  269. package/src/theme/common/list-item.css +3 -2
  270. package/src/theme/common/table.css +2 -2
  271. package/src/theme/common/toolbar.css +1 -1
  272. package/lib/cjs/functions-Dk90yOUc.js +0 -690
  273. package/lib/cjs/functions-Dk90yOUc.js.map +0 -1
  274. package/lib/cjs/index-7pgPMFV4.js.map +0 -1
  275. package/lib/cjs/index-Bjy2DUKs.js +0 -272
  276. package/lib/cjs/index-Bjy2DUKs.js.map +0 -1
  277. package/lib/cjs/index-BuSAwj4j.js.map +0 -1
  278. package/lib/cjs/index-CvmlYYXX.js.map +0 -1
  279. package/lib/cjs/index-D3lu92SA.js +0 -39
  280. package/lib/cjs/index-D3lu92SA.js.map +0 -1
  281. package/lib/cjs/index-DQll67YS.js +0 -65
  282. package/lib/cjs/index-DQll67YS.js.map +0 -1
  283. package/lib/cjs/index-Dac851tb.js.map +0 -1
  284. package/lib/cjs/index-Dub20F3z.js.map +0 -1
  285. package/lib/cjs/index-hPk2gbSt.js +0 -35
  286. package/lib/cjs/index-hPk2gbSt.js.map +0 -1
  287. package/lib/cjs/index-nrFkJeLW.js.map +0 -1
  288. package/lib/cjs/index-ooYXC5xk.js.map +0 -1
  289. package/lib/esm/functions-Bsik6ikd.js +0 -652
  290. package/lib/esm/functions-Bsik6ikd.js.map +0 -1
  291. package/lib/esm/index-B3KiKTSt.js +0 -63
  292. package/lib/esm/index-B3KiKTSt.js.map +0 -1
  293. package/lib/esm/index-BFsG6770.js.map +0 -1
  294. package/lib/esm/index-CBrOT1fW.js +0 -37
  295. package/lib/esm/index-CBrOT1fW.js.map +0 -1
  296. package/lib/esm/index-CLpluqvF.js.map +0 -1
  297. package/lib/esm/index-CsEtSFhk.js +0 -270
  298. package/lib/esm/index-CsEtSFhk.js.map +0 -1
  299. package/lib/esm/index-Cuk7cL-r.js +0 -33
  300. package/lib/esm/index-Cuk7cL-r.js.map +0 -1
  301. package/lib/esm/index-CxJ9fxJm.js.map +0 -1
  302. package/lib/esm/index-DOrkOhki.js.map +0 -1
  303. package/lib/esm/index-DcRgwPLd.js.map +0 -1
  304. package/lib/esm/index-s33c_M2f.js.map +0 -1
  305. package/lib/esm/index-uHWmZXqe.js.map +0 -1
  306. package/src/feature/block-edit/handle/component.ts +0 -54
  307. package/src/feature/block-edit/menu/component.ts +0 -241
  308. package/src/feature/latex/inline-tooltip/component.ts +0 -38
  309. package/src/feature/toolbar/component.ts +0 -236
@@ -0,0 +1,237 @@
1
+ import type { Ctx } from '@milkdown/kit/ctx'
2
+
3
+ import { Icon } from '@milkdown/kit/component'
4
+ import {
5
+ computed,
6
+ defineComponent,
7
+ onUnmounted,
8
+ ref,
9
+ watch,
10
+ watchEffect,
11
+ type Ref,
12
+ h,
13
+ } from 'vue'
14
+
15
+ import type { BlockEditFeatureConfig } from '..'
16
+
17
+ import { getGroups } from './config'
18
+
19
+ h
20
+
21
+ type MenuProps = {
22
+ ctx: Ctx
23
+ show: Ref<boolean>
24
+ filter: Ref<string>
25
+ hide: () => void
26
+ config?: BlockEditFeatureConfig
27
+ }
28
+
29
+ export const Menu = defineComponent<MenuProps>({
30
+ props: {
31
+ ctx: {
32
+ type: Object,
33
+ required: true,
34
+ },
35
+ show: {
36
+ type: Object,
37
+ required: true,
38
+ },
39
+ filter: {
40
+ type: Object,
41
+ required: true,
42
+ },
43
+ hide: {
44
+ type: Function,
45
+ required: true,
46
+ },
47
+ config: {
48
+ type: Object,
49
+ required: false,
50
+ },
51
+ },
52
+ setup({ ctx, show, filter, hide, config }) {
53
+ const host = ref<HTMLElement>()
54
+ const groupInfo = computed(() => getGroups(filter.value, config, ctx))
55
+ const hoverIndex = ref(0)
56
+ const prevMousePosition = ref({ x: -999, y: -999 })
57
+
58
+ const onPointerMove = (e: MouseEvent) => {
59
+ const { x, y } = e
60
+ prevMousePosition.value = { x, y }
61
+ }
62
+
63
+ watch([groupInfo, show], () => {
64
+ const { size } = groupInfo.value
65
+ if (size === 0 && show.value) hide()
66
+ else if (hoverIndex.value >= size) hoverIndex.value = 0
67
+ })
68
+
69
+ const onHover = (
70
+ index: number | ((prev: number) => number),
71
+ after?: (index: number) => void
72
+ ) => {
73
+ const prevHoverIndex = hoverIndex.value
74
+ const next = typeof index === 'function' ? index(prevHoverIndex) : index
75
+ after?.(next)
76
+ hoverIndex.value = next
77
+ }
78
+
79
+ const scrollToIndex = (index: number) => {
80
+ const target = host.value?.querySelector<HTMLElement>(
81
+ `[data-index="${index}"]`
82
+ )
83
+ const scrollRoot = host.value?.querySelector<HTMLElement>('.menu-groups')
84
+
85
+ if (!target || !scrollRoot) return
86
+
87
+ scrollRoot.scrollTop = target.offsetTop - scrollRoot.offsetTop
88
+ }
89
+
90
+ const runByIndex = (index: number) => {
91
+ const item = groupInfo.value.groups
92
+ .flatMap((group) => group.items)
93
+ .at(index)
94
+ if (item && ctx) item.onRun(ctx)
95
+
96
+ hide()
97
+ }
98
+
99
+ const onKeydown = (e: KeyboardEvent) => {
100
+ const { size, groups } = groupInfo.value
101
+ if (e.key === 'Escape') {
102
+ e.preventDefault()
103
+ hide?.()
104
+ return
105
+ }
106
+
107
+ if (e.key === 'ArrowDown') {
108
+ e.preventDefault()
109
+ return onHover(
110
+ (index) => (index < size - 1 ? index + 1 : index),
111
+ scrollToIndex
112
+ )
113
+ }
114
+
115
+ if (e.key === 'ArrowUp') {
116
+ e.preventDefault()
117
+ return onHover(
118
+ (index) => (index <= 0 ? index : index - 1),
119
+ scrollToIndex
120
+ )
121
+ }
122
+
123
+ if (e.key === 'ArrowLeft') {
124
+ e.preventDefault()
125
+ return onHover((index) => {
126
+ const group = groups.find(
127
+ (group) => group.range[0] <= index && group.range[1] > index
128
+ )
129
+ if (!group) return index
130
+
131
+ const prevGroup = groups[groups.indexOf(group) - 1]
132
+ if (!prevGroup) return index
133
+
134
+ return prevGroup.range[1] - 1
135
+ }, scrollToIndex)
136
+ }
137
+
138
+ if (e.key === 'ArrowRight') {
139
+ e.preventDefault()
140
+ return onHover((index) => {
141
+ const group = groups.find(
142
+ (group) => group.range[0] <= index && group.range[1] > index
143
+ )
144
+ if (!group) return index
145
+
146
+ const nextGroup = groups[groups.indexOf(group) + 1]
147
+ if (!nextGroup) return index
148
+
149
+ return nextGroup.range[0]
150
+ }, scrollToIndex)
151
+ }
152
+
153
+ if (e.key === 'Enter') {
154
+ e.preventDefault()
155
+ runByIndex(hoverIndex.value)
156
+ }
157
+ }
158
+
159
+ const getOnPointerEnter = (index: number) => (e: MouseEvent) => {
160
+ const prevPos = prevMousePosition.value
161
+ if (!prevPos) return
162
+
163
+ const { x, y } = e
164
+ if (x === prevPos.x && y === prevPos.y) return
165
+
166
+ onHover(index)
167
+ }
168
+
169
+ watchEffect(() => {
170
+ const isShown = show.value
171
+ if (isShown) {
172
+ window.addEventListener('keydown', onKeydown, { capture: true })
173
+ } else {
174
+ window.removeEventListener('keydown', onKeydown, { capture: true })
175
+ }
176
+ })
177
+ onUnmounted(() => {
178
+ window.removeEventListener('keydown', onKeydown, { capture: true })
179
+ })
180
+
181
+ return () => {
182
+ return (
183
+ <div ref={host} onPointerdown={(e) => e.preventDefault()}>
184
+ <nav class="tab-group">
185
+ <ul>
186
+ {groupInfo.value.groups.map((group) => (
187
+ <li
188
+ key={group.key}
189
+ onPointerdown={() => onHover(group.range[0], scrollToIndex)}
190
+ class={
191
+ hoverIndex.value >= group.range[0] &&
192
+ hoverIndex.value < group.range[1]
193
+ ? 'selected'
194
+ : ''
195
+ }
196
+ >
197
+ {group.label}
198
+ </li>
199
+ ))}
200
+ </ul>
201
+ </nav>
202
+ <div class="menu-groups" onPointermove={onPointerMove}>
203
+ {groupInfo.value.groups.map((group) => (
204
+ <div key={group.key} class="menu-group">
205
+ <h6>{group.label}</h6>
206
+ <ul>
207
+ {group.items.map((item) => (
208
+ <li
209
+ key={item.key}
210
+ data-index={item.index}
211
+ class={hoverIndex.value === item.index ? 'hover' : ''}
212
+ onPointerenter={getOnPointerEnter(item.index)}
213
+ onPointerdown={() => {
214
+ host.value
215
+ ?.querySelector(`[data-index="${item.index}"]`)
216
+ ?.classList.add('active')
217
+ }}
218
+ onPointerup={() => {
219
+ host.value
220
+ ?.querySelector(`[data-index="${item.index}"]`)
221
+ ?.classList.remove('active')
222
+ runByIndex(item.index)
223
+ }}
224
+ >
225
+ <Icon icon={item.icon} />
226
+ <span>{item.label}</span>
227
+ </li>
228
+ ))}
229
+ </ul>
230
+ </div>
231
+ ))}
232
+ </div>
233
+ </div>
234
+ )
235
+ }
236
+ },
237
+ })
@@ -1,6 +1,7 @@
1
+ import type { Ctx } from '@milkdown/kit/ctx'
2
+
1
3
  import { imageBlockSchema } from '@milkdown/kit/component/image-block'
2
4
  import { editorViewCtx } from '@milkdown/kit/core'
3
- import type { Ctx } from '@milkdown/kit/ctx'
4
5
  import {
5
6
  blockquoteSchema,
6
7
  bulletListSchema,
@@ -13,6 +14,10 @@ import {
13
14
  } from '@milkdown/kit/preset/commonmark'
14
15
  import { createTable } from '@milkdown/kit/preset/gfm'
15
16
  import { TextSelection } from '@milkdown/kit/prose/state'
17
+
18
+ import type { BlockEditFeatureConfig } from '../index'
19
+ import type { MenuItemGroup } from './utils'
20
+
16
21
  import { CrepeFeature } from '../../..'
17
22
  import { FeaturesCtx } from '../../../core/slice'
18
23
  import {
@@ -33,9 +38,7 @@ import {
33
38
  textIcon,
34
39
  todoListIcon,
35
40
  } from '../../../icons'
36
- import type { BlockEditFeatureConfig } from '../index'
37
41
  import { GroupBuilder } from './group-builder'
38
- import type { MenuItemGroup } from './utils'
39
42
  import {
40
43
  clearContentAndAddBlockType,
41
44
  clearContentAndSetBlockType,
@@ -1,13 +1,19 @@
1
- import type { PluginView } from '@milkdown/kit/prose/state'
1
+ import type { Ctx } from '@milkdown/kit/ctx'
2
2
  import type { EditorView } from '@milkdown/kit/prose/view'
3
+
3
4
  import { SlashProvider, slashFactory } from '@milkdown/kit/plugin/slash'
4
- import type { Ctx } from '@milkdown/kit/ctx'
5
- import type { AtomicoThis } from 'atomico/types/dom'
5
+ import {
6
+ TextSelection,
7
+ type PluginView,
8
+ type Selection,
9
+ } from '@milkdown/kit/prose/state'
6
10
  import { $ctx } from '@milkdown/kit/utils'
7
- import { defIfNotExists, isInCodeBlock, isInList } from '../../../utils'
11
+ import { createApp, ref, type App, type Ref } from 'vue'
12
+
8
13
  import type { BlockEditFeatureConfig } from '../index'
9
- import type { MenuProps } from './component'
10
- import { MenuElement } from './component'
14
+
15
+ import { isInCodeBlock, isInList } from '../../../utils'
16
+ import { Menu } from './component'
11
17
 
12
18
  export const menu = slashFactory('CREPE_MENU')
13
19
 
@@ -24,7 +30,6 @@ export const menuAPI = $ctx(
24
30
  'menuAPICtx'
25
31
  )
26
32
 
27
- defIfNotExists('milkdown-slash-menu', MenuElement)
28
33
  export function configureMenu(ctx: Ctx, config?: BlockEditFeatureConfig) {
29
34
  ctx.set(menu.key, {
30
35
  view: (view) => new MenuView(ctx, view, config),
@@ -32,16 +37,34 @@ export function configureMenu(ctx: Ctx, config?: BlockEditFeatureConfig) {
32
37
  }
33
38
 
34
39
  class MenuView implements PluginView {
35
- readonly #content: AtomicoThis<MenuProps, HTMLElement>
40
+ readonly #content: HTMLElement
41
+ readonly #app: App
42
+ readonly #filter: Ref<string>
36
43
  readonly #slashProvider: SlashProvider
37
44
  #programmaticallyPos: number | null = null
38
45
 
39
46
  constructor(ctx: Ctx, view: EditorView, config?: BlockEditFeatureConfig) {
40
- this.#content = new MenuElement()
41
- this.#content.hide = this.hide
42
- this.#content.ctx = ctx
43
- this.#content.config = config
44
- // eslint-disable-next-line ts/no-this-alias
47
+ const content = document.createElement('div')
48
+ content.classList.add('milkdown-slash-menu')
49
+ const show = ref(false)
50
+
51
+ const filter = ref('')
52
+ this.#filter = filter
53
+
54
+ const hide = this.hide
55
+
56
+ const app = createApp(Menu, {
57
+ ctx,
58
+ config,
59
+ show,
60
+ filter,
61
+ hide,
62
+ })
63
+ this.#app = app
64
+ app.mount(content)
65
+
66
+ this.#content = content
67
+ // oxlint-disable-next-line ts/no-this-alias
45
68
  const self = this
46
69
  this.#slashProvider = new SlashProvider({
47
70
  content: this.#content,
@@ -59,9 +82,13 @@ class MenuView implements PluginView {
59
82
 
60
83
  if (currentText == null) return false
61
84
 
85
+ if (!isSelectionAtEndOfNode(view.state.selection)) {
86
+ return false
87
+ }
88
+
62
89
  const pos = self.#programmaticallyPos
63
90
 
64
- self.#content.filter = currentText.startsWith('/')
91
+ filter.value = currentText.startsWith('/')
65
92
  ? currentText.slice(1)
66
93
  : currentText
67
94
 
@@ -86,10 +113,10 @@ class MenuView implements PluginView {
86
113
  })
87
114
 
88
115
  this.#slashProvider.onShow = () => {
89
- this.#content.show = true
116
+ show.value = true
90
117
  }
91
118
  this.#slashProvider.onHide = () => {
92
- this.#content.show = false
119
+ show.value = false
93
120
  }
94
121
  this.update(view)
95
122
 
@@ -105,7 +132,7 @@ class MenuView implements PluginView {
105
132
 
106
133
  show = (pos: number) => {
107
134
  this.#programmaticallyPos = pos
108
- this.#content.filter = ''
135
+ this.#filter.value = ''
109
136
  this.#slashProvider.show()
110
137
  }
111
138
 
@@ -116,6 +143,17 @@ class MenuView implements PluginView {
116
143
 
117
144
  destroy = () => {
118
145
  this.#slashProvider.destroy()
146
+ this.#app.unmount()
119
147
  this.#content.remove()
120
148
  }
121
149
  }
150
+
151
+ function isSelectionAtEndOfNode(selection: Selection) {
152
+ if (!(selection instanceof TextSelection)) return false
153
+
154
+ const { $head } = selection
155
+ const parent = $head.parent
156
+ const offset = $head.parentOffset
157
+
158
+ return offset === parent.content.size
159
+ }
@@ -1,14 +1,14 @@
1
- import type { html } from 'atomico'
2
1
  import type { Ctx } from '@milkdown/kit/ctx'
3
- import type { Command, Transaction } from '@milkdown/kit/prose/state'
4
2
  import type { Attrs, NodeType } from '@milkdown/kit/prose/model'
3
+ import type { Command, Transaction } from '@milkdown/kit/prose/state'
4
+
5
5
  import { findWrapping } from '@milkdown/kit/prose/transform'
6
6
 
7
7
  export interface MenuItem {
8
8
  index: number
9
9
  key: string
10
10
  label: string
11
- icon: ReturnType<typeof html>
11
+ icon: string
12
12
  onRun: (ctx: Ctx) => void
13
13
  }
14
14
 
@@ -1,14 +1,16 @@
1
+ import type { LanguageDescription } from '@codemirror/language'
2
+ import type { Extension } from '@codemirror/state'
3
+
4
+ import { defaultKeymap, indentWithTab } from '@codemirror/commands'
5
+ import { keymap } from '@codemirror/view'
1
6
  import {
2
7
  codeBlockComponent,
3
8
  codeBlockConfig,
4
9
  } from '@milkdown/kit/component/code-block'
5
- import type { LanguageDescription } from '@codemirror/language'
6
- import type { Extension } from '@codemirror/state'
7
10
  import { basicSetup } from 'codemirror'
8
- import { keymap } from '@codemirror/view'
9
- import { defaultKeymap, indentWithTab } from '@codemirror/commands'
10
- import { html } from 'atomico'
11
+
11
12
  import type { DefineFeature, Icon } from '../shared'
13
+
12
14
  import { chevronDownIcon, clearIcon, editIcon, searchIcon } from '../../icons'
13
15
  import { visibilityOffIcon } from '../../icons/visibility-off'
14
16
 
@@ -24,10 +26,7 @@ interface CodeMirrorConfig {
24
26
  searchPlaceholder: string
25
27
  noResultText: string
26
28
 
27
- renderLanguage: (
28
- language: string,
29
- selected: boolean
30
- ) => ReturnType<typeof html> | string
29
+ renderLanguage: (language: string, selected: boolean) => string
31
30
 
32
31
  renderPreview: (
33
32
  language: string,
@@ -35,8 +34,8 @@ interface CodeMirrorConfig {
35
34
  ) => string | HTMLElement | null
36
35
 
37
36
  previewToggleIcon: (previewOnlyMode: boolean) => ReturnType<Icon>
38
- previewToggleText: (previewOnlyMode: boolean) => ReturnType<typeof html>
39
- previewLabel: () => ReturnType<typeof html>
37
+ previewToggleText: (previewOnlyMode: boolean) => string
38
+ previewLabel: () => string
40
39
  }
41
40
  export type CodeMirrorFeatureConfig = Partial<CodeMirrorConfig>
42
41
 
@@ -66,20 +65,21 @@ export const defineFeature: DefineFeature<CodeMirrorFeatureConfig> = (
66
65
  ],
67
66
  languages,
68
67
 
69
- expandIcon: config.expandIcon || (() => chevronDownIcon),
70
- searchIcon: config.searchIcon || (() => searchIcon),
71
- clearSearchIcon: config.clearSearchIcon || (() => clearIcon),
68
+ expandIcon: () => config.expandIcon?.() || chevronDownIcon,
69
+ searchIcon: () => config.searchIcon?.() || searchIcon,
70
+ clearSearchIcon: () => config.clearSearchIcon?.() || clearIcon,
72
71
  searchPlaceholder: config.searchPlaceholder || 'Search language',
73
72
  noResultText: config.noResultText || 'No result',
74
73
  renderLanguage: config.renderLanguage || defaultConfig.renderLanguage,
75
74
  renderPreview: config.renderPreview || defaultConfig.renderPreview,
76
75
  previewToggleButton: (previewOnlyMode) => {
77
- return html`
78
- ${config.previewToggleIcon?.(previewOnlyMode) ||
79
- (previewOnlyMode ? editIcon : visibilityOffIcon)}
80
- ${config.previewToggleText?.(previewOnlyMode) ||
81
- (previewOnlyMode ? 'Edit' : 'Hide')}
82
- `
76
+ const icon =
77
+ config.previewToggleIcon?.(previewOnlyMode) ||
78
+ (previewOnlyMode ? editIcon : visibilityOffIcon)
79
+ const text =
80
+ config.previewToggleText?.(previewOnlyMode) ||
81
+ (previewOnlyMode ? 'Edit' : 'Hide')
82
+ return [icon, text].map((v) => v.trim()).join(' ')
83
83
  },
84
84
  previewLabel: config.previewLabel || defaultConfig.previewLabel,
85
85
  }))
@@ -1,10 +1,13 @@
1
1
  import { cursor, dropCursorConfig } from '@milkdown/kit/plugin/cursor'
2
+ import { $prose } from '@milkdown/kit/utils'
3
+ import { createVirtualCursor } from 'prosemirror-virtual-cursor'
2
4
 
3
5
  import type { DefineFeature } from '../shared'
4
6
 
5
7
  interface CursorConfig {
6
8
  color: string | false
7
9
  width: number
10
+ virtual: boolean
8
11
  }
9
12
  export type CursorFeatureConfig = Partial<CursorConfig>
10
13
 
@@ -21,4 +24,11 @@ export const defineFeature: DefineFeature<CursorFeatureConfig> = (
21
24
  }))
22
25
  })
23
26
  .use(cursor)
27
+
28
+ if (config?.virtual === false) {
29
+ return
30
+ }
31
+
32
+ const virtualCursor = createVirtualCursor()
33
+ editor.use($prose(() => virtualCursor))
24
34
  }
@@ -6,8 +6,10 @@ import {
6
6
  imageInlineComponent,
7
7
  inlineImageConfig,
8
8
  } from '@milkdown/kit/component/image-inline'
9
+
9
10
  import type { DefineFeature, Icon } from '../shared'
10
- import { captionIcon, confirmIcon, imageIcon } from '../../icons'
11
+
12
+ import { captionIcon, imageIcon, confirmIcon } from '../../icons'
11
13
 
12
14
  interface ImageBlockConfig {
13
15
  onUpload: (file: File) => Promise<string>
@@ -1,14 +1,15 @@
1
1
  import type { Editor } from '@milkdown/kit/core'
2
- import type { PlaceHolderFeatureConfig } from './placeholder'
3
- import type { CodeMirrorFeatureConfig } from './code-mirror'
2
+
4
3
  import type { BlockEditFeatureConfig } from './block-edit'
4
+ import type { CodeMirrorFeatureConfig } from './code-mirror'
5
5
  import type { CursorFeatureConfig } from './cursor'
6
6
  import type { ImageBlockFeatureConfig } from './image-block'
7
+ import type { LatexFeatureConfig } from './latex'
7
8
  import type { LinkTooltipFeatureConfig } from './link-tooltip'
8
9
  import type { ListItemFeatureConfig } from './list-item'
9
- import type { ToolbarFeatureConfig } from './toolbar'
10
+ import type { PlaceHolderFeatureConfig } from './placeholder'
10
11
  import type { TableFeatureConfig } from './table'
11
- import type { LatexFeatureConfig } from './latex'
12
+ import type { ToolbarFeatureConfig } from './toolbar'
12
13
 
13
14
  export enum CrepeFeature {
14
15
  CodeMirror = 'code-mirror',
@@ -1,18 +1,19 @@
1
1
  import type { KatexOptions } from 'katex'
2
- import katex from 'katex'
2
+
3
3
  import { codeBlockConfig } from '@milkdown/kit/component/code-block'
4
+ import katex from 'katex'
5
+
6
+ import type { DefineFeature, Icon } from '../shared'
7
+
4
8
  import { CrepeFeature } from '../..'
5
9
  import { FeaturesCtx } from '../../core/slice'
6
- import type { DefineFeature, Icon } from '../shared'
7
- import { remarkMathBlockPlugin, remarkMathPlugin } from './remark'
10
+ import { confirmIcon } from '../../icons'
11
+ import { blockLatexSchema } from './block-latex'
8
12
  import { mathInlineSchema } from './inline-latex'
9
- import { defIfNotExists } from '../../utils'
10
- import { LatexInlineEditElement } from './inline-tooltip/component'
11
13
  import { inlineLatexTooltip } from './inline-tooltip/tooltip'
12
14
  import { LatexInlineTooltip } from './inline-tooltip/view'
13
- import { confirmIcon } from '../../icons'
14
15
  import { mathBlockInputRule, mathInlineInputRule } from './input-rule'
15
- import { blockLatexSchema } from './block-latex'
16
+ import { remarkMathBlockPlugin, remarkMathPlugin } from './remark'
16
17
 
17
18
  export interface LatexConfig {
18
19
  katexOptions: KatexOptions
@@ -21,7 +22,6 @@ export interface LatexConfig {
21
22
 
22
23
  export type LatexFeatureConfig = Partial<LatexConfig>
23
24
 
24
- defIfNotExists('milkdown-latex-inline-edit', LatexInlineEditElement)
25
25
  export const defineFeature: DefineFeature<LatexFeatureConfig> = (
26
26
  editor,
27
27
  config
@@ -0,0 +1,57 @@
1
+ import type { EditorView } from '@milkdown/kit/prose/view'
2
+
3
+ import { Icon } from '@milkdown/kit/component'
4
+ import { defineComponent, type ShallowRef, type VNodeRef, h } from 'vue'
5
+
6
+ import type { LatexConfig } from '..'
7
+
8
+ type LatexTooltipProps = {
9
+ config: Partial<LatexConfig>
10
+ innerView: ShallowRef<EditorView | null>
11
+ updateValue: ShallowRef<() => void>
12
+ }
13
+
14
+ h
15
+
16
+ export const LatexTooltip = defineComponent<LatexTooltipProps>({
17
+ props: {
18
+ config: {
19
+ type: Object,
20
+ required: true,
21
+ },
22
+ innerView: {
23
+ type: Object,
24
+ required: true,
25
+ },
26
+ updateValue: {
27
+ type: Object,
28
+ required: true,
29
+ },
30
+ },
31
+ setup(props) {
32
+ const innerViewRef: VNodeRef = (el) => {
33
+ if (!el || !(el instanceof HTMLElement)) return
34
+ while (el.firstChild) {
35
+ el.removeChild(el.firstChild)
36
+ }
37
+ if (props.innerView.value) {
38
+ el.appendChild(props.innerView.value.dom)
39
+ }
40
+ }
41
+ const onUpdate = (e: Event) => {
42
+ e.preventDefault()
43
+ props.updateValue.value()
44
+ }
45
+
46
+ return () => {
47
+ return (
48
+ <div class="container">
49
+ {props.innerView && <div ref={innerViewRef} />}
50
+ <button onPointerdown={onUpdate}>
51
+ <Icon icon={props.config.inlineEditConfirm?.()} />
52
+ </button>
53
+ </div>
54
+ )
55
+ }
56
+ },
57
+ })