@difizen/libro-core 0.0.0-snapshot-20241017072317

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 (433) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +280 -0
  3. package/es/add-cell/index.d.ts +4 -0
  4. package/es/add-cell/index.d.ts.map +1 -0
  5. package/es/add-cell/index.js +3 -0
  6. package/es/add-cell/index.less +38 -0
  7. package/es/add-cell/libro-add-cell-module.d.ts +3 -0
  8. package/es/add-cell/libro-add-cell-module.d.ts.map +1 -0
  9. package/es/add-cell/libro-add-cell-module.js +4 -0
  10. package/es/add-cell/libro-add-cell-slot-contribution.d.ts +11 -0
  11. package/es/add-cell/libro-add-cell-slot-contribution.d.ts.map +1 -0
  12. package/es/add-cell/libro-add-cell-slot-contribution.js +59 -0
  13. package/es/add-cell/libro-add-cell-view.d.ts +21 -0
  14. package/es/add-cell/libro-add-cell-view.d.ts.map +1 -0
  15. package/es/add-cell/libro-add-cell-view.js +121 -0
  16. package/es/cell/index.d.ts +10 -0
  17. package/es/cell/index.d.ts.map +1 -0
  18. package/es/cell/index.js +9 -0
  19. package/es/cell/libro-cell-contribution.d.ts +12 -0
  20. package/es/cell/libro-cell-contribution.d.ts.map +1 -0
  21. package/es/cell/libro-cell-contribution.js +47 -0
  22. package/es/cell/libro-cell-model.d.ts +29 -0
  23. package/es/cell/libro-cell-model.d.ts.map +1 -0
  24. package/es/cell/libro-cell-model.js +130 -0
  25. package/es/cell/libro-cell-module.d.ts +10 -0
  26. package/es/cell/libro-cell-module.d.ts.map +1 -0
  27. package/es/cell/libro-cell-module.js +30 -0
  28. package/es/cell/libro-cell-protocol.d.ts +44 -0
  29. package/es/cell/libro-cell-protocol.d.ts.map +1 -0
  30. package/es/cell/libro-cell-protocol.js +11 -0
  31. package/es/cell/libro-cell-service.d.ts +28 -0
  32. package/es/cell/libro-cell-service.d.ts.map +1 -0
  33. package/es/cell/libro-cell-service.js +245 -0
  34. package/es/cell/libro-cell-view.d.ts +74 -0
  35. package/es/cell/libro-cell-view.d.ts.map +1 -0
  36. package/es/cell/libro-cell-view.js +239 -0
  37. package/es/cell/libro-edit-cell-view.d.ts +44 -0
  38. package/es/cell/libro-edit-cell-view.d.ts.map +1 -0
  39. package/es/cell/libro-edit-cell-view.js +256 -0
  40. package/es/cell/libro-executable-cell-model.d.ts +14 -0
  41. package/es/cell/libro-executable-cell-model.d.ts.map +1 -0
  42. package/es/cell/libro-executable-cell-model.js +7 -0
  43. package/es/cell/libro-executable-cell-view.d.ts +34 -0
  44. package/es/cell/libro-executable-cell-view.d.ts.map +1 -0
  45. package/es/cell/libro-executable-cell-view.js +74 -0
  46. package/es/cell/libro-markdown-cell-model.d.ts +9 -0
  47. package/es/cell/libro-markdown-cell-model.d.ts.map +1 -0
  48. package/es/cell/libro-markdown-cell-model.js +7 -0
  49. package/es/collapse-service.d.ts +36 -0
  50. package/es/collapse-service.d.ts.map +1 -0
  51. package/es/collapse-service.js +55 -0
  52. package/es/command/document-commands.d.ts +5 -0
  53. package/es/command/document-commands.d.ts.map +1 -0
  54. package/es/command/document-commands.js +21 -0
  55. package/es/command/index.d.ts +7 -0
  56. package/es/command/index.d.ts.map +1 -0
  57. package/es/command/index.js +6 -0
  58. package/es/command/kernel-command.d.ts +5 -0
  59. package/es/command/kernel-command.d.ts.map +1 -0
  60. package/es/command/kernel-command.js +40 -0
  61. package/es/command/libro-command-contribution.d.ts +13 -0
  62. package/es/command/libro-command-contribution.d.ts.map +1 -0
  63. package/es/command/libro-command-contribution.js +1842 -0
  64. package/es/command/libro-command-register.d.ts +21 -0
  65. package/es/command/libro-command-register.d.ts.map +1 -0
  66. package/es/command/libro-command-register.js +111 -0
  67. package/es/command/module.d.ts +3 -0
  68. package/es/command/module.d.ts.map +1 -0
  69. package/es/command/module.js +4 -0
  70. package/es/command/notebook-commands.d.ts +6 -0
  71. package/es/command/notebook-commands.d.ts.map +1 -0
  72. package/es/command/notebook-commands.js +472 -0
  73. package/es/components/cell-protocol.d.ts +20 -0
  74. package/es/components/cell-protocol.d.ts.map +1 -0
  75. package/es/components/cell-protocol.js +4 -0
  76. package/es/components/dnd-cell-item-render.d.ts +16 -0
  77. package/es/components/dnd-cell-item-render.d.ts.map +1 -0
  78. package/es/components/dnd-cell-item-render.js +364 -0
  79. package/es/components/dnd-component/custom-drag-layer.d.ts +9 -0
  80. package/es/components/dnd-component/custom-drag-layer.d.ts.map +1 -0
  81. package/es/components/dnd-component/custom-drag-layer.js +140 -0
  82. package/es/components/dnd-component/default-dnd-content.d.ts +11 -0
  83. package/es/components/dnd-component/default-dnd-content.d.ts.map +1 -0
  84. package/es/components/dnd-component/default-dnd-content.js +292 -0
  85. package/es/components/dnd-component/dnd-context.d.ts +3 -0
  86. package/es/components/dnd-component/dnd-context.d.ts.map +1 -0
  87. package/es/components/dnd-component/dnd-context.js +20 -0
  88. package/es/components/dnd-component/dnd-list.d.ts +14 -0
  89. package/es/components/dnd-component/dnd-list.d.ts.map +1 -0
  90. package/es/components/dnd-component/dnd-list.js +182 -0
  91. package/es/components/dnd-component/index.d.ts +5 -0
  92. package/es/components/dnd-component/index.d.ts.map +1 -0
  93. package/es/components/dnd-component/index.js +4 -0
  94. package/es/components/dnd-component/index.less +8 -0
  95. package/es/components/dnd-component/overscanIndices-getter.d.ts +22 -0
  96. package/es/components/dnd-component/overscanIndices-getter.d.ts.map +1 -0
  97. package/es/components/dnd-component/overscanIndices-getter.js +58 -0
  98. package/es/components/dnd-component/virtualized-manager.d.ts +19 -0
  99. package/es/components/dnd-component/virtualized-manager.d.ts.map +1 -0
  100. package/es/components/dnd-component/virtualized-manager.js +60 -0
  101. package/es/components/index.d.ts +6 -0
  102. package/es/components/index.d.ts.map +1 -0
  103. package/es/components/index.js +5 -0
  104. package/es/components/libro-component.d.ts +5 -0
  105. package/es/components/libro-component.d.ts.map +1 -0
  106. package/es/components/libro-component.js +35 -0
  107. package/es/components/libro-side-toolbar-menu.d.ts +21 -0
  108. package/es/components/libro-side-toolbar-menu.d.ts.map +1 -0
  109. package/es/components/libro-side-toolbar-menu.js +58 -0
  110. package/es/components/libro-view-header.d.ts +3 -0
  111. package/es/components/libro-view-header.d.ts.map +1 -0
  112. package/es/components/libro-view-header.js +37 -0
  113. package/es/components/libro-virtualized-render.d.ts +15 -0
  114. package/es/components/libro-virtualized-render.d.ts.map +1 -0
  115. package/es/components/libro-virtualized-render.js +174 -0
  116. package/es/content/index.d.ts +6 -0
  117. package/es/content/index.d.ts.map +1 -0
  118. package/es/content/index.js +5 -0
  119. package/es/content/libro-content-contribution.d.ts +11 -0
  120. package/es/content/libro-content-contribution.d.ts.map +1 -0
  121. package/es/content/libro-content-contribution.js +31 -0
  122. package/es/content/libro-content-module.d.ts +3 -0
  123. package/es/content/libro-content-module.d.ts.map +1 -0
  124. package/es/content/libro-content-module.js +6 -0
  125. package/es/content/libro-content-protocol.d.ts +13 -0
  126. package/es/content/libro-content-protocol.d.ts.map +1 -0
  127. package/es/content/libro-content-protocol.js +3 -0
  128. package/es/content/libro-content-service.d.ts +11 -0
  129. package/es/content/libro-content-service.d.ts.map +1 -0
  130. package/es/content/libro-content-service.js +63 -0
  131. package/es/content/libro-save-content-contribution.d.ts +6 -0
  132. package/es/content/libro-save-content-contribution.d.ts.map +1 -0
  133. package/es/content/libro-save-content-contribution.js +27 -0
  134. package/es/formatter/index.d.ts +6 -0
  135. package/es/formatter/index.d.ts.map +1 -0
  136. package/es/formatter/index.js +5 -0
  137. package/es/formatter/libro-formatter-json-contribution.d.ts +18 -0
  138. package/es/formatter/libro-formatter-json-contribution.d.ts.map +1 -0
  139. package/es/formatter/libro-formatter-json-contribution.js +41 -0
  140. package/es/formatter/libro-formatter-manager.d.ts +16 -0
  141. package/es/formatter/libro-formatter-manager.d.ts.map +1 -0
  142. package/es/formatter/libro-formatter-manager.js +86 -0
  143. package/es/formatter/libro-formatter-module.d.ts +3 -0
  144. package/es/formatter/libro-formatter-module.d.ts.map +1 -0
  145. package/es/formatter/libro-formatter-module.js +7 -0
  146. package/es/formatter/libro-formatter-protocol.d.ts +37 -0
  147. package/es/formatter/libro-formatter-protocol.d.ts.map +1 -0
  148. package/es/formatter/libro-formatter-protocol.js +18 -0
  149. package/es/formatter/libro-formatter-string-contribution.d.ts +18 -0
  150. package/es/formatter/libro-formatter-string-contribution.d.ts.map +1 -0
  151. package/es/formatter/libro-formatter-string-contribution.js +41 -0
  152. package/es/formatter/libro-formatter-trans-default-contribution.d.ts +7 -0
  153. package/es/formatter/libro-formatter-trans-default-contribution.d.ts.map +1 -0
  154. package/es/formatter/libro-formatter-trans-default-contribution.js +19 -0
  155. package/es/index.d.ts +26 -0
  156. package/es/index.d.ts.map +1 -0
  157. package/es/index.js +25 -0
  158. package/es/index.less +781 -0
  159. package/es/libro-context-key.d.ts +26 -0
  160. package/es/libro-context-key.d.ts.map +1 -0
  161. package/es/libro-context-key.js +84 -0
  162. package/es/libro-keybind-registry.d.ts +5 -0
  163. package/es/libro-keybind-registry.d.ts.map +1 -0
  164. package/es/libro-keybind-registry.js +68 -0
  165. package/es/libro-model.d.ts +145 -0
  166. package/es/libro-model.d.ts.map +1 -0
  167. package/es/libro-model.js +921 -0
  168. package/es/libro-protocol.d.ts +315 -0
  169. package/es/libro-protocol.d.ts.map +1 -0
  170. package/es/libro-protocol.js +47 -0
  171. package/es/libro-service.d.ts +69 -0
  172. package/es/libro-service.d.ts.map +1 -0
  173. package/es/libro-service.js +303 -0
  174. package/es/libro-setting-contribution.d.ts +5 -0
  175. package/es/libro-setting-contribution.d.ts.map +1 -0
  176. package/es/libro-setting-contribution.js +23 -0
  177. package/es/libro-setting.d.ts +12 -0
  178. package/es/libro-setting.d.ts.map +1 -0
  179. package/es/libro-setting.js +101 -0
  180. package/es/libro-view-tracker.d.ts +6 -0
  181. package/es/libro-view-tracker.d.ts.map +1 -0
  182. package/es/libro-view-tracker.js +13 -0
  183. package/es/libro-view.d.ts +170 -0
  184. package/es/libro-view.d.ts.map +1 -0
  185. package/es/libro-view.js +2077 -0
  186. package/es/libro-workspace-service.d.ts +17 -0
  187. package/es/libro-workspace-service.d.ts.map +1 -0
  188. package/es/libro-workspace-service.js +36 -0
  189. package/es/material-from-designer.d.ts +31 -0
  190. package/es/material-from-designer.d.ts.map +1 -0
  191. package/es/material-from-designer.js +697 -0
  192. package/es/module.d.ts +3 -0
  193. package/es/module.d.ts.map +1 -0
  194. package/es/module.js +71 -0
  195. package/es/output/index.d.ts +6 -0
  196. package/es/output/index.d.ts.map +1 -0
  197. package/es/output/index.js +5 -0
  198. package/es/output/output-area.d.ts +51 -0
  199. package/es/output/output-area.d.ts.map +1 -0
  200. package/es/output/output-area.js +399 -0
  201. package/es/output/output-contribution.d.ts +10 -0
  202. package/es/output/output-contribution.d.ts.map +1 -0
  203. package/es/output/output-contribution.js +36 -0
  204. package/es/output/output-model.d.ts +28 -0
  205. package/es/output/output-model.d.ts.map +1 -0
  206. package/es/output/output-model.js +105 -0
  207. package/es/output/output-module.d.ts +3 -0
  208. package/es/output/output-module.d.ts.map +1 -0
  209. package/es/output/output-module.js +6 -0
  210. package/es/output/output-protocol.d.ts +134 -0
  211. package/es/output/output-protocol.d.ts.map +1 -0
  212. package/es/output/output-protocol.js +16 -0
  213. package/es/settings/index.d.ts +5 -0
  214. package/es/settings/index.d.ts.map +1 -0
  215. package/es/settings/index.js +4 -0
  216. package/es/settings/index.less +3 -0
  217. package/es/settings/module.d.ts +3 -0
  218. package/es/settings/module.d.ts.map +1 -0
  219. package/es/settings/module.js +4 -0
  220. package/es/settings/setting-editor/configuration-panel-view.d.ts +13 -0
  221. package/es/settings/setting-editor/configuration-panel-view.d.ts.map +1 -0
  222. package/es/settings/setting-editor/configuration-panel-view.js +115 -0
  223. package/es/settings/setting-editor/configuration-render-contribution.d.ts +6 -0
  224. package/es/settings/setting-editor/configuration-render-contribution.d.ts.map +1 -0
  225. package/es/settings/setting-editor/configuration-render-contribution.js +77 -0
  226. package/es/settings/setting-editor/default-node-render.d.ts +9 -0
  227. package/es/settings/setting-editor/default-node-render.d.ts.map +1 -0
  228. package/es/settings/setting-editor/default-node-render.js +79 -0
  229. package/es/settings/setting-editor/index.d.ts +7 -0
  230. package/es/settings/setting-editor/index.d.ts.map +1 -0
  231. package/es/settings/setting-editor/index.js +6 -0
  232. package/es/settings/setting-editor/index.less +12 -0
  233. package/es/settings/setting-editor/module.d.ts +3 -0
  234. package/es/settings/setting-editor/module.d.ts.map +1 -0
  235. package/es/settings/setting-editor/module.js +11 -0
  236. package/es/settings/setting-editor/setting-editor-view.d.ts +15 -0
  237. package/es/settings/setting-editor/setting-editor-view.d.ts.map +1 -0
  238. package/es/settings/setting-editor/setting-editor-view.js +169 -0
  239. package/es/settings/setting-editor/setting-tree-service.d.ts +9 -0
  240. package/es/settings/setting-editor/setting-tree-service.d.ts.map +1 -0
  241. package/es/settings/setting-editor/setting-tree-service.js +118 -0
  242. package/es/settings/setting-editor/setting-tree-view.d.ts +19 -0
  243. package/es/settings/setting-editor/setting-tree-view.d.ts.map +1 -0
  244. package/es/settings/setting-editor/setting-tree-view.js +87 -0
  245. package/es/settings/settings-contribution.d.ts +7 -0
  246. package/es/settings/settings-contribution.d.ts.map +1 -0
  247. package/es/settings/settings-contribution.js +36 -0
  248. package/es/settings/settings-modal.d.ts +5 -0
  249. package/es/settings/settings-modal.d.ts.map +1 -0
  250. package/es/settings/settings-modal.js +53 -0
  251. package/es/settings/settings-modal.less +3 -0
  252. package/es/settings/settings-protocol.d.ts +4 -0
  253. package/es/settings/settings-protocol.d.ts.map +1 -0
  254. package/es/settings/settings-protocol.js +5 -0
  255. package/es/slot/index.d.ts +5 -0
  256. package/es/slot/index.d.ts.map +1 -0
  257. package/es/slot/index.js +4 -0
  258. package/es/slot/libro-slot-manager.d.ts +13 -0
  259. package/es/slot/libro-slot-manager.d.ts.map +1 -0
  260. package/es/slot/libro-slot-manager.js +66 -0
  261. package/es/slot/libro-slot-protocol.d.ts +19 -0
  262. package/es/slot/libro-slot-protocol.d.ts.map +1 -0
  263. package/es/slot/libro-slot-protocol.js +5 -0
  264. package/es/slot/libro-slot-view.d.ts +9 -0
  265. package/es/slot/libro-slot-view.d.ts.map +1 -0
  266. package/es/slot/libro-slot-view.js +81 -0
  267. package/es/slot/module.d.ts +3 -0
  268. package/es/slot/module.d.ts.map +1 -0
  269. package/es/slot/module.js +5 -0
  270. package/es/theme/libro-color-registry.d.ts +6 -0
  271. package/es/theme/libro-color-registry.d.ts.map +1 -0
  272. package/es/theme/libro-color-registry.js +515 -0
  273. package/es/toolbar/all-outputs-scroll-icon.d.ts +3 -0
  274. package/es/toolbar/all-outputs-scroll-icon.d.ts.map +1 -0
  275. package/es/toolbar/all-outputs-scroll-icon.js +10 -0
  276. package/es/toolbar/change-cell-to-selector.d.ts +5 -0
  277. package/es/toolbar/change-cell-to-selector.d.ts.map +1 -0
  278. package/es/toolbar/change-cell-to-selector.js +51 -0
  279. package/es/toolbar/hide-all-selector.d.ts +5 -0
  280. package/es/toolbar/hide-all-selector.d.ts.map +1 -0
  281. package/es/toolbar/hide-all-selector.js +99 -0
  282. package/es/toolbar/index.d.ts +4 -0
  283. package/es/toolbar/index.d.ts.map +1 -0
  284. package/es/toolbar/index.js +3 -0
  285. package/es/toolbar/index.less +59 -0
  286. package/es/toolbar/libro-toolbar-protocol.d.ts +4 -0
  287. package/es/toolbar/libro-toolbar-protocol.d.ts.map +1 -0
  288. package/es/toolbar/libro-toolbar-protocol.js +1 -0
  289. package/es/toolbar/libro-toolbar.d.ts +9 -0
  290. package/es/toolbar/libro-toolbar.d.ts.map +1 -0
  291. package/es/toolbar/libro-toolbar.js +275 -0
  292. package/es/toolbar/module.d.ts +3 -0
  293. package/es/toolbar/module.d.ts.map +1 -0
  294. package/es/toolbar/module.js +5 -0
  295. package/es/toolbar/restart-clear-outputs-contribution.d.ts +5 -0
  296. package/es/toolbar/restart-clear-outputs-contribution.d.ts.map +1 -0
  297. package/es/toolbar/restart-clear-outputs-contribution.js +23 -0
  298. package/es/toolbar/restart-clear-outputs-modal.d.ts +5 -0
  299. package/es/toolbar/restart-clear-outputs-modal.d.ts.map +1 -0
  300. package/es/toolbar/restart-clear-outputs-modal.js +30 -0
  301. package/es/toolbar/save-icon.d.ts +3 -0
  302. package/es/toolbar/save-icon.d.ts.map +1 -0
  303. package/es/toolbar/save-icon.js +54 -0
  304. package/es/toolbar/shutdown-contribution.d.ts +5 -0
  305. package/es/toolbar/shutdown-contribution.d.ts.map +1 -0
  306. package/es/toolbar/shutdown-contribution.js +23 -0
  307. package/es/toolbar/shutdown-modal.d.ts +5 -0
  308. package/es/toolbar/shutdown-modal.d.ts.map +1 -0
  309. package/es/toolbar/shutdown-modal.js +30 -0
  310. package/es/toolbar/side-toolar-more-select.d.ts +4 -0
  311. package/es/toolbar/side-toolar-more-select.d.ts.map +1 -0
  312. package/es/toolbar/side-toolar-more-select.js +161 -0
  313. package/es/typings/index.d.ts +1 -0
  314. package/es/virtualized-manager-helper.d.ts +11 -0
  315. package/es/virtualized-manager-helper.d.ts.map +1 -0
  316. package/es/virtualized-manager-helper.js +51 -0
  317. package/es/virtualized-manager.d.ts +23 -0
  318. package/es/virtualized-manager.d.ts.map +1 -0
  319. package/es/virtualized-manager.js +65 -0
  320. package/package.json +73 -0
  321. package/src/add-cell/index.less +38 -0
  322. package/src/add-cell/index.ts +3 -0
  323. package/src/add-cell/libro-add-cell-module.ts +9 -0
  324. package/src/add-cell/libro-add-cell-slot-contribution.ts +28 -0
  325. package/src/add-cell/libro-add-cell-view.tsx +99 -0
  326. package/src/cell/README.md +14 -0
  327. package/src/cell/index.ts +9 -0
  328. package/src/cell/libro-cell-contribution.ts +34 -0
  329. package/src/cell/libro-cell-model.ts +119 -0
  330. package/src/cell/libro-cell-module.ts +40 -0
  331. package/src/cell/libro-cell-protocol.ts +55 -0
  332. package/src/cell/libro-cell-service.ts +158 -0
  333. package/src/cell/libro-cell-view.tsx +156 -0
  334. package/src/cell/libro-edit-cell-view.tsx +205 -0
  335. package/src/cell/libro-executable-cell-model.ts +32 -0
  336. package/src/cell/libro-executable-cell-view.ts +86 -0
  337. package/src/cell/libro-markdown-cell-model.ts +20 -0
  338. package/src/collapse-service.ts +69 -0
  339. package/src/command/document-commands.ts +24 -0
  340. package/src/command/index.ts +6 -0
  341. package/src/command/kernel-command.ts +42 -0
  342. package/src/command/libro-command-contribution.ts +1346 -0
  343. package/src/command/libro-command-register.ts +168 -0
  344. package/src/command/module.ts +9 -0
  345. package/src/command/notebook-commands.ts +502 -0
  346. package/src/components/cell-protocol.ts +26 -0
  347. package/src/components/dnd-cell-item-render.tsx +465 -0
  348. package/src/components/dnd-component/custom-drag-layer.tsx +144 -0
  349. package/src/components/dnd-component/default-dnd-content.tsx +330 -0
  350. package/src/components/dnd-component/dnd-context.tsx +28 -0
  351. package/src/components/dnd-component/dnd-list.tsx +211 -0
  352. package/src/components/dnd-component/index.less +12 -0
  353. package/src/components/dnd-component/index.tsx +4 -0
  354. package/src/components/dnd-component/overscanIndices-getter.ts +92 -0
  355. package/src/components/dnd-component/virtualized-manager.ts +34 -0
  356. package/src/components/index.ts +5 -0
  357. package/src/components/libro-component.tsx +30 -0
  358. package/src/components/libro-side-toolbar-menu.tsx +82 -0
  359. package/src/components/libro-view-header.tsx +33 -0
  360. package/src/components/libro-virtualized-render.tsx +178 -0
  361. package/src/content/index.ts +5 -0
  362. package/src/content/libro-content-contribution.ts +16 -0
  363. package/src/content/libro-content-module.ts +17 -0
  364. package/src/content/libro-content-protocol.ts +14 -0
  365. package/src/content/libro-content-service.ts +48 -0
  366. package/src/content/libro-save-content-contribution.ts +12 -0
  367. package/src/formatter/index.ts +5 -0
  368. package/src/formatter/libro-formatter-json-contribution.ts +42 -0
  369. package/src/formatter/libro-formatter-manager.ts +85 -0
  370. package/src/formatter/libro-formatter-module.ts +19 -0
  371. package/src/formatter/libro-formatter-protocol.ts +63 -0
  372. package/src/formatter/libro-formatter-string-contribution.ts +41 -0
  373. package/src/formatter/libro-formatter-trans-default-contribution.ts +15 -0
  374. package/src/index.less +789 -0
  375. package/src/index.spec.ts +12 -0
  376. package/src/index.tsx +25 -0
  377. package/src/libro-context-key.ts +84 -0
  378. package/src/libro-keybind-registry.ts +43 -0
  379. package/src/libro-model.ts +710 -0
  380. package/src/libro-protocol.ts +435 -0
  381. package/src/libro-service.ts +234 -0
  382. package/src/libro-setting-contribution.ts +28 -0
  383. package/src/libro-setting.ts +110 -0
  384. package/src/libro-view-tracker.ts +9 -0
  385. package/src/libro-view.tsx +1532 -0
  386. package/src/libro-workspace-service.ts +28 -0
  387. package/src/material-from-designer.tsx +579 -0
  388. package/src/module.ts +121 -0
  389. package/src/output/index.ts +5 -0
  390. package/src/output/output-area.tsx +286 -0
  391. package/src/output/output-contribution.ts +14 -0
  392. package/src/output/output-model.tsx +70 -0
  393. package/src/output/output-module.ts +10 -0
  394. package/src/output/output-protocol.ts +168 -0
  395. package/src/settings/index.less +3 -0
  396. package/src/settings/index.ts +4 -0
  397. package/src/settings/module.ts +8 -0
  398. package/src/settings/setting-editor/configuration-panel-view.tsx +89 -0
  399. package/src/settings/setting-editor/configuration-render-contribution.ts +81 -0
  400. package/src/settings/setting-editor/default-node-render.tsx +65 -0
  401. package/src/settings/setting-editor/index.less +12 -0
  402. package/src/settings/setting-editor/index.ts +6 -0
  403. package/src/settings/setting-editor/module.ts +17 -0
  404. package/src/settings/setting-editor/setting-editor-view.tsx +93 -0
  405. package/src/settings/setting-editor/setting-tree-service.ts +82 -0
  406. package/src/settings/setting-editor/setting-tree-view.tsx +95 -0
  407. package/src/settings/settings-contribution.tsx +24 -0
  408. package/src/settings/settings-modal.less +3 -0
  409. package/src/settings/settings-modal.tsx +51 -0
  410. package/src/settings/settings-protocol.ts +7 -0
  411. package/src/slot/index.ts +4 -0
  412. package/src/slot/libro-slot-manager.ts +38 -0
  413. package/src/slot/libro-slot-protocol.ts +28 -0
  414. package/src/slot/libro-slot-view.tsx +48 -0
  415. package/src/slot/module.ts +9 -0
  416. package/src/theme/libro-color-registry.ts +386 -0
  417. package/src/toolbar/all-outputs-scroll-icon.tsx +19 -0
  418. package/src/toolbar/change-cell-to-selector.tsx +67 -0
  419. package/src/toolbar/hide-all-selector.tsx +126 -0
  420. package/src/toolbar/index.less +59 -0
  421. package/src/toolbar/index.ts +3 -0
  422. package/src/toolbar/libro-toolbar-protocol.ts +4 -0
  423. package/src/toolbar/libro-toolbar.tsx +231 -0
  424. package/src/toolbar/module.ts +11 -0
  425. package/src/toolbar/restart-clear-outputs-contribution.tsx +10 -0
  426. package/src/toolbar/restart-clear-outputs-modal.tsx +37 -0
  427. package/src/toolbar/save-icon.tsx +47 -0
  428. package/src/toolbar/shutdown-contribution.tsx +10 -0
  429. package/src/toolbar/shutdown-modal.tsx +37 -0
  430. package/src/toolbar/side-toolar-more-select.tsx +177 -0
  431. package/src/typings/index.d.ts +1 -0
  432. package/src/virtualized-manager-helper.ts +29 -0
  433. package/src/virtualized-manager.ts +47 -0
@@ -0,0 +1,1532 @@
1
+ import { ToTopOutlined } from '@ant-design/icons';
2
+ import type { IModelContentChange } from '@difizen/libro-code-editor';
3
+ import {
4
+ concatMultilineString,
5
+ copy2clipboard,
6
+ readFromClipboard,
7
+ } from '@difizen/libro-common';
8
+ import {
9
+ equals,
10
+ useInject,
11
+ inject,
12
+ transient,
13
+ BaseView,
14
+ Slot,
15
+ view,
16
+ ViewInstance,
17
+ ViewManager,
18
+ ViewOption,
19
+ Deferred,
20
+ Disposable,
21
+ DisposableCollection,
22
+ Emitter,
23
+ getOrigin,
24
+ prop,
25
+ watch,
26
+ ConfigurationService,
27
+ useConfigurationValue,
28
+ } from '@difizen/mana-app';
29
+ import { FloatButton, Button, Spin } from 'antd';
30
+ import type { FC, ForwardRefExoticComponent, RefAttributes } from 'react';
31
+ import { forwardRef, memo, useCallback, useEffect, useRef } from 'react';
32
+ import { v4 } from 'uuid';
33
+
34
+ import {
35
+ CellService,
36
+ EditorCellView,
37
+ ExecutableCellModel,
38
+ ExecutableCellView,
39
+ } from './cell/index.js';
40
+ import type { LibroCell } from './cell/index.js';
41
+ import type { LibroCellModel } from './cell/libro-cell-model.js';
42
+ import { CollapseServiceFactory } from './collapse-service.js';
43
+ import type { CollapseService } from './collapse-service.js';
44
+ import {
45
+ CustomDragLayer,
46
+ DndCellContainer,
47
+ DndCellItemRender,
48
+ DndContext,
49
+ DndList,
50
+ } from './components/index.js';
51
+ import { LibroViewHeader } from './components/libro-view-header.js';
52
+ import { LibroContextKey } from './libro-context-key.js';
53
+ import { LibroModel } from './libro-model.js';
54
+ import { NotebookService, notebookViewFactoryId } from './libro-protocol.js';
55
+ import type {
56
+ CellOptions,
57
+ CellView,
58
+ DndContentProps,
59
+ DndItemProps,
60
+ NotebookView,
61
+ NotebookModel,
62
+ NotebookOption,
63
+ } from './libro-protocol.js';
64
+ import { LibroService } from './libro-service.js';
65
+ import {
66
+ AutoInsertWhenNoCell,
67
+ EnterEditModeWhenAddCell,
68
+ HeaderToolbarVisible,
69
+ RightContentFixed,
70
+ } from './libro-setting.js';
71
+ import { LibroSlotManager, LibroSlotView } from './slot/index.js';
72
+ import { VirtualizedManagerHelper } from './virtualized-manager-helper.js';
73
+ import type { VirtualizedManager } from './virtualized-manager.js';
74
+ import './index.less';
75
+
76
+ export interface ClipboardType {
77
+ action: 'copy' | 'cut';
78
+ cells: LibroCell[];
79
+ }
80
+
81
+ export const LibroContentComponent = memo(function LibroContentComponent() {
82
+ const libroSlotManager = useInject(LibroSlotManager);
83
+ const ref = useRef<HTMLDivElement | null>(null);
84
+ const libroViewTopRef = useRef<HTMLDivElement>(null);
85
+ const libroViewRightContentRef = useRef<HTMLDivElement>(null);
86
+ const libroViewLeftContentRef = useRef<HTMLDivElement>(null);
87
+ const libroViewContentRef = useRef<HTMLDivElement>(null);
88
+ const instance = useInject<LibroView>(ViewInstance);
89
+ const HeaderRender = getOrigin(instance.headerRender);
90
+ const [headerVisible] = useConfigurationValue(HeaderToolbarVisible);
91
+ const [rightContentFixed] = useConfigurationValue(RightContentFixed);
92
+
93
+ const handleScroll = useCallback(() => {
94
+ instance.cellScrollEmitter.fire();
95
+ const cellRightToolbar = instance.container?.current?.getElementsByClassName(
96
+ 'libro-cell-right-toolbar',
97
+ )[instance.model.activeIndex] as HTMLDivElement;
98
+ const activeCellOffsetY =
99
+ instance.activeCell?.container?.current?.getBoundingClientRect().y;
100
+ const activeCellOffsetRight =
101
+ instance.activeCell?.container?.current?.getBoundingClientRect().right;
102
+ const activeOutput =
103
+ ExecutableCellView.is(instance.activeCell) && instance.activeCell?.outputArea;
104
+ const activeOutputOffsetBottom =
105
+ activeOutput && activeOutput.length > 0
106
+ ? activeOutput?.outputs[
107
+ activeOutput.length - 1
108
+ ].container?.current?.getBoundingClientRect().bottom
109
+ : instance.activeCell?.container?.current?.getBoundingClientRect().bottom;
110
+ const libroViewTopOffsetBottom =
111
+ libroViewTopRef.current?.getBoundingClientRect().bottom;
112
+
113
+ if (!cellRightToolbar) {
114
+ return;
115
+ }
116
+ if (
117
+ activeCellOffsetY !== undefined &&
118
+ libroViewTopOffsetBottom !== undefined &&
119
+ activeOutputOffsetBottom !== undefined &&
120
+ activeCellOffsetY <= libroViewTopOffsetBottom + 12 &&
121
+ activeOutputOffsetBottom >= libroViewTopOffsetBottom &&
122
+ activeCellOffsetRight !== undefined
123
+ ) {
124
+ cellRightToolbar.style.cssText = `position:fixed;top:${
125
+ libroViewTopOffsetBottom + 12
126
+ }px;left:${activeCellOffsetRight + 44 - 34}px;right:unset;`;
127
+ } else {
128
+ cellRightToolbar.style.cssText = ' position: absolute;top: 0px;right: -44px;';
129
+ }
130
+ }, [instance]);
131
+
132
+ useEffect(() => {
133
+ if (
134
+ rightContentFixed &&
135
+ libroViewRightContentRef.current &&
136
+ libroViewContentRef.current &&
137
+ libroViewLeftContentRef.current
138
+ ) {
139
+ libroViewContentRef.current.style.cssText = 'display: block;';
140
+ libroViewRightContentRef.current.style.cssText =
141
+ 'position: absolute;top:44px;right:20px';
142
+ libroViewLeftContentRef.current.style.cssText = 'padding-right: 80px;';
143
+ }
144
+ }, [rightContentFixed]);
145
+
146
+ return (
147
+ <>
148
+ {headerVisible && (
149
+ <div className="libro-view-top" ref={libroViewTopRef}>
150
+ <HeaderRender />
151
+ </div>
152
+ )}
153
+ <div
154
+ className="libro-view-content"
155
+ onScroll={handleScroll}
156
+ ref={libroViewContentRef}
157
+ >
158
+ <div className="libro-view-content-left" ref={libroViewLeftContentRef}>
159
+ <DndContext>
160
+ <CustomDragLayer />
161
+ <DndList libroView={instance} ref={ref}>
162
+ <Slot
163
+ name={libroSlotManager.getSlotName(instance, 'list')}
164
+ slotView={LibroSlotView}
165
+ />
166
+ </DndList>
167
+ </DndContext>
168
+ </div>
169
+ <div className="libro-view-content-right" ref={libroViewRightContentRef}>
170
+ {/* {tocVisible && instance.toc && <ViewRender view={instance.toc} />} */}
171
+ <Slot
172
+ name={libroSlotManager.getSlotName(instance, 'right')}
173
+ slotView={LibroSlotView}
174
+ />
175
+ </div>
176
+ <FloatButton.BackTop target={() => libroViewContentRef.current || document}>
177
+ <div className="libro-totop-button">
178
+ <Button shape="circle" icon={<ToTopOutlined />} />
179
+ </div>
180
+ </FloatButton.BackTop>
181
+ <Slot
182
+ name={libroSlotManager.getSlotName(instance, 'content')}
183
+ slotView={LibroSlotView}
184
+ />
185
+ </div>
186
+ <Slot
187
+ name={libroSlotManager.getSlotName(instance, 'container')}
188
+ slotView={LibroSlotView}
189
+ />
190
+ </>
191
+ );
192
+ });
193
+
194
+ export const LibroRender = forwardRef<HTMLDivElement>(function LibroRender(props, ref) {
195
+ const instance = useInject<LibroView>(ViewInstance);
196
+ const libroService = useInject(LibroService);
197
+
198
+ const handleMouseDown = useCallback(
199
+ (e: React.MouseEvent<HTMLDivElement>) => {
200
+ if (e.defaultPrevented) {
201
+ return;
202
+ }
203
+ if (!instance.model.commandMode) {
204
+ instance.enterCommandMode(true);
205
+ }
206
+ },
207
+ [instance],
208
+ );
209
+
210
+ const handFocus = useCallback(
211
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
212
+ (e: React.FocusEvent<HTMLDivElement>) => {
213
+ if (!equals(libroService.active, instance)) {
214
+ libroService.active = instance;
215
+ }
216
+ if (!equals(libroService.focus, instance)) {
217
+ libroService.focus = instance;
218
+ }
219
+ },
220
+ [instance, libroService],
221
+ );
222
+
223
+ const handBlur = useCallback(
224
+ (e: React.FocusEvent<HTMLDivElement>) => {
225
+ if (typeof ref === 'function') {
226
+ return;
227
+ }
228
+ // focus编辑器host
229
+ if (!e.relatedTarget) {
230
+ return;
231
+ }
232
+ // focus编辑器外部区域
233
+ if (ref?.current?.contains(e.relatedTarget)) {
234
+ const dndDom = ref?.current?.getElementsByClassName(
235
+ 'libro-dnd-cells-container',
236
+ )[0];
237
+
238
+ if (
239
+ !dndDom?.contains(e.relatedTarget) &&
240
+ (!instance.model.inputEditable ||
241
+ !instance.model.outputEditable ||
242
+ !instance.model.cellsEditable) &&
243
+ !instance.model.runnable
244
+ ) {
245
+ instance.selectCell(undefined);
246
+ }
247
+ } else {
248
+ instance.enterCommandMode(false);
249
+ libroService.focus = undefined;
250
+ instance.onBlurEmitter.fire('');
251
+ if (
252
+ (!instance.model.inputEditable ||
253
+ !instance.model.outputEditable ||
254
+ !instance.model.cellsEditable) &&
255
+ !instance.model.runnable
256
+ ) {
257
+ instance.selectCell(undefined);
258
+ }
259
+ }
260
+ },
261
+ [instance, libroService, ref],
262
+ );
263
+
264
+ return (
265
+ <div
266
+ className={`${instance.model.libroViewClass} libro-view`}
267
+ onMouseDown={handleMouseDown}
268
+ ref={ref}
269
+ tabIndex={0}
270
+ onFocus={handFocus}
271
+ onBlur={handBlur}
272
+ >
273
+ <LibroContentComponent />
274
+ </div>
275
+ );
276
+ });
277
+
278
+ @transient()
279
+ @view(notebookViewFactoryId)
280
+ export class LibroView extends BaseView implements NotebookView {
281
+ protected override toDispose = new DisposableCollection();
282
+ @prop()
283
+ model: NotebookModel;
284
+ headerRender: FC<any> = LibroViewHeader;
285
+ loadingRender: FC<any> = () => (
286
+ <div className="libro-loading">
287
+ <Spin />
288
+ </div>
289
+ );
290
+ dndContentRender: FC<DndContentProps> = DndCellContainer;
291
+ dndItemRender: React.MemoExoticComponent<
292
+ ForwardRefExoticComponent<DndItemProps & RefAttributes<HTMLDivElement>>
293
+ > = DndCellItemRender;
294
+ protected onCellCreateEmitter: Emitter<CellView> = new Emitter();
295
+ get onCellCreate() {
296
+ return this.onCellCreateEmitter.event;
297
+ }
298
+ protected onCellDeleteEmitter: Emitter<CellView> = new Emitter();
299
+ get onCellDelete() {
300
+ return this.onCellDeleteEmitter.event;
301
+ }
302
+
303
+ onBlurEmitter: Emitter = new Emitter();
304
+ get onBlur() {
305
+ return this.onBlurEmitter.event;
306
+ }
307
+
308
+ onRestartEmitter: Emitter = new Emitter();
309
+ get onRestart() {
310
+ return this.onRestartEmitter.event;
311
+ }
312
+
313
+ @inject(CellService) cellService: CellService;
314
+ @inject(LibroService) libroService: LibroService;
315
+ @inject(LibroSlotManager) libroSlotManager: LibroSlotManager;
316
+ @inject(LibroContextKey) contextKey: LibroContextKey;
317
+
318
+ @inject(ViewManager) protected viewManager: ViewManager;
319
+ @inject(ConfigurationService) protected configurationService: ConfigurationService;
320
+
321
+ protected virtualizedManager: VirtualizedManager;
322
+ protected virtualizedManagerHelper: VirtualizedManagerHelper;
323
+ protected notebookService: NotebookService;
324
+ protected collapseService: CollapseService;
325
+ isDragging = false;
326
+
327
+ clipboard: ClipboardType;
328
+
329
+ @prop()
330
+ collapserVisible = false;
331
+
332
+ @prop()
333
+ outputsScroll = false;
334
+
335
+ get hasModal() {
336
+ return this.model.cells.some((item) => item.hasModal);
337
+ }
338
+
339
+ @prop()
340
+ saving?: boolean;
341
+
342
+ onSaveEmitter: Emitter<boolean> = new Emitter();
343
+ get onSave() {
344
+ return this.onSaveEmitter.event;
345
+ }
346
+ onCellContentChangedEmitter: Emitter<IModelContentChange[]> = new Emitter();
347
+ get onCellContentChanged() {
348
+ return this.onCellContentChangedEmitter.event;
349
+ }
350
+
351
+ runCellEmitter: Emitter<CellView> = new Emitter();
352
+ get onRunCell() {
353
+ return this.runCellEmitter.event;
354
+ }
355
+
356
+ cellScrollEmitter = new Emitter<void>();
357
+ get onCellScroll() {
358
+ return this.cellScrollEmitter.event;
359
+ }
360
+
361
+ protected initializedDefer = new Deferred<void>();
362
+
363
+ get initialized() {
364
+ return this.initializedDefer.promise;
365
+ }
366
+
367
+ constructor(
368
+ @inject(ViewOption) options: NotebookOption,
369
+ @inject(CollapseServiceFactory) collapseServiceFactory: CollapseServiceFactory,
370
+ @inject(NotebookService) notebookService: NotebookService,
371
+ @inject(VirtualizedManagerHelper)
372
+ virtualizedManagerHelper: VirtualizedManagerHelper,
373
+ ) {
374
+ super();
375
+ if (options.id) {
376
+ this.id = options.id;
377
+ }
378
+ this.notebookService = notebookService;
379
+ this.model = this.notebookService.getOrCreateModel(options);
380
+ this.collapseService = collapseServiceFactory({ view: this });
381
+ this.collapserVisible = this.collapseService.collapserVisible;
382
+ this.virtualizedManagerHelper = virtualizedManagerHelper;
383
+ this.virtualizedManager = virtualizedManagerHelper.getOrCreate(this.model);
384
+
385
+ this.initialize();
386
+ this.initView();
387
+ }
388
+
389
+ initView() {
390
+ // this.configurationService.get(TOCVisible).then(() => {
391
+ // this.viewManager.getOrCreateView(MarkdownCellTocView, { id: this.id }).then(toc => {
392
+ // this.toc = toc;
393
+ // toc.parent = this;
394
+ // });
395
+ // });
396
+ // this.viewManager
397
+ // .getOrCreateView(LibroKeybindInstrutionsView, { id: 'libro-keybind-instructions' })
398
+ // .then(keybindInstrutions => {
399
+ // this.keybindInstrutionsView = keybindInstrutions;
400
+ // });
401
+ }
402
+
403
+ async initialize() {
404
+ this.model.isInitialized = false;
405
+ const options = await this.model.initialize();
406
+ this.configurationService
407
+ .get(AutoInsertWhenNoCell)
408
+ .then((value) => {
409
+ const isAutoInsertWhenNoCell = value;
410
+ if (isAutoInsertWhenNoCell && options.length === 0) {
411
+ this.addCell(
412
+ { id: v4(), cell: { cell_type: 'code', source: '', metadata: {} } },
413
+ 0,
414
+ );
415
+ }
416
+ return;
417
+ })
418
+ .catch((e) => {
419
+ //
420
+ });
421
+ await this.insertCells(options);
422
+ // 第一次insert不需要历史
423
+ setTimeout(() => {
424
+ this.model.sharedModel.clearUndoHistory();
425
+ // 未初始化完成不做渲染,防止重复渲染多次
426
+ this.model.isInitialized = true;
427
+ this.configurationService
428
+ .get(EnterEditModeWhenAddCell)
429
+ .then((value) => {
430
+ if (value) {
431
+ this.enterEditMode();
432
+ } else {
433
+ this.enterCommandMode(true);
434
+ }
435
+ return;
436
+ })
437
+ .catch((e) => {
438
+ //
439
+ });
440
+ this.toDispose.push(
441
+ watch(this.model, 'cells', () => {
442
+ this.model.onChange?.();
443
+ }),
444
+ );
445
+ this.initializedDefer.resolve();
446
+ }, 0);
447
+ }
448
+
449
+ override view = LibroRender;
450
+
451
+ override onViewMount = () => {
452
+ this.libroService.active = this;
453
+ this.libroSlotManager.setup(this);
454
+
455
+ // this.libroService.libroPerformanceStatistics.setRenderEnd(new Date());
456
+
457
+ // console.log(
458
+ // '[performance] render Time: ',
459
+ // this.libroService.libroPerformanceStatistics.getRenderTime(),
460
+ // );
461
+ };
462
+
463
+ override onViewUnmount = () => {
464
+ if (equals(this.libroService.active, this)) {
465
+ this.libroService.active = undefined;
466
+ }
467
+ };
468
+
469
+ async getCellViewByOption(option: CellOptions) {
470
+ const toDispose = new DisposableCollection();
471
+ option.cell.metadata.trusted = this.model.trusted;
472
+ const cellView = await this.cellService.getOrCreateView(option, this.id);
473
+ cellView.parent = this;
474
+ this.onCellCreateEmitter.fire(cellView);
475
+ toDispose.push(
476
+ Disposable.create(() => {
477
+ this.deleteCell(cellView);
478
+ }),
479
+ );
480
+ const disposable = cellView.onDisposed(() => {
481
+ toDispose.dispose();
482
+ });
483
+ toDispose.push(disposable);
484
+ return cellView;
485
+ }
486
+
487
+ focus = () => {
488
+ if (this.container?.current?.contains(document.activeElement)) {
489
+ return;
490
+ }
491
+ this.container?.current?.focus();
492
+ };
493
+
494
+ insertCells = async (options: CellOptions[], position?: number): Promise<void> => {
495
+ const cellView = await Promise.all(
496
+ options.map(async (option) => {
497
+ const newView = await this.getCellViewByOption(option);
498
+ return newView;
499
+ }),
500
+ );
501
+
502
+ this.model.insertCells(cellView, position);
503
+ };
504
+
505
+ selectCell = (cell?: CellView) => {
506
+ this.model.active = cell;
507
+ this.model.selectCell(cell);
508
+ };
509
+
510
+ addCell = async (option: CellOptions, position?: number) => {
511
+ const cellView = await this.getCellViewByOption(option);
512
+ this.model.addCell(cellView, position);
513
+ };
514
+
515
+ addCellAbove = async (option: CellOptions, position?: number) => {
516
+ const cellView = await this.getCellViewByOption(option);
517
+ this.model.addCell(cellView, position, 'above');
518
+ };
519
+
520
+ get activeCell(): CellView | undefined {
521
+ return this.model.active;
522
+ }
523
+
524
+ get activeCellIndex(): number {
525
+ return this.model.activeIndex;
526
+ }
527
+
528
+ findCellIndex = (cell: CellView) => {
529
+ const cellList = this.model.getCells();
530
+ if (cell) {
531
+ const cellIndex = cellList.findIndex((item) => {
532
+ return item.id === cell.id;
533
+ });
534
+ return cellIndex;
535
+ }
536
+ return -1;
537
+ };
538
+
539
+ deleteCell = (cell: CellView) => {
540
+ const deleteIndex = this.model.getCells().findIndex((item) => {
541
+ return equals(item, cell);
542
+ });
543
+ if (this.model.selections.length !== 0 && this.isSelected(cell)) {
544
+ const startIndex = this.model.getCells().findIndex((item) => {
545
+ return equals(item, this.model.selections[0]);
546
+ });
547
+ const endIndex = startIndex + this.model.selections.length;
548
+ getOrigin(this.model.sharedModel).transact(() => {
549
+ getOrigin(this.model.sharedModel).deleteCellRange(startIndex, endIndex);
550
+ });
551
+ this.configurationService
552
+ .get(AutoInsertWhenNoCell)
553
+ .then((value) => {
554
+ const isAutoInsertWhenNoCell = value;
555
+ if (isAutoInsertWhenNoCell && this.model.cells.length === 0) {
556
+ this.addCell(
557
+ { id: v4(), cell: { cell_type: 'code', source: '', metadata: {} } },
558
+ 0,
559
+ );
560
+ }
561
+ return;
562
+ })
563
+ .catch((e) => {
564
+ //
565
+ });
566
+ } else {
567
+ if (deleteIndex > -1) {
568
+ this.model.deletedCells.push(cell);
569
+ this.model.deleteCell(cell.id);
570
+ cell.isAttached = false;
571
+ }
572
+ this.configurationService
573
+ .get(AutoInsertWhenNoCell)
574
+ .then((value) => {
575
+ const isAutoInsertWhenNoCell = value;
576
+ if (isAutoInsertWhenNoCell && this.model.cells.length === 0) {
577
+ this.addCell(
578
+ { id: v4(), cell: { cell_type: 'code', source: '', metadata: {} } },
579
+ 0,
580
+ );
581
+ }
582
+ return;
583
+ })
584
+ .catch((e) => {
585
+ //
586
+ });
587
+ }
588
+ };
589
+
590
+ executeCellRun(cell: CellView) {
591
+ this.runCellEmitter.fire(cell);
592
+ if (ExecutableCellView.is(cell)) {
593
+ return cell.run();
594
+ } else {
595
+ return undefined;
596
+ }
597
+ }
598
+
599
+ runCells = async (cells: CellView[]) => {
600
+ if (this.model.canRun && !this.model.canRun()) {
601
+ return false;
602
+ }
603
+
604
+ return Promise.all(
605
+ cells.map((cell) => {
606
+ return this.executeCellRun(cell);
607
+ }),
608
+ )
609
+ .then((resultList) => {
610
+ return resultList.filter((item) => item !== undefined).every((item) => !!item);
611
+ })
612
+ .catch((reason: any) => {
613
+ if (reason.message.startsWith('KernelReplyNotOK')) {
614
+ return undefined;
615
+ } else {
616
+ throw reason;
617
+ }
618
+ });
619
+ };
620
+
621
+ runAllCell = async () => {
622
+ this.runCells(this.model.cells);
623
+ };
624
+
625
+ runAllAbove = async (cell: CellView) => {
626
+ const index = this.findCellIndex(cell);
627
+ this.runCells(this.model.cells.slice(0, index));
628
+ };
629
+
630
+ runAllBelow = async (cell: CellView) => {
631
+ const index = this.findCellIndex(cell);
632
+ this.runCells(this.model.cells.slice(index));
633
+ };
634
+
635
+ runCell = async (cell: CellView) => {
636
+ this.enterCommandMode(true);
637
+ if (this.model.selections.length !== 0 && this.isSelected(cell)) {
638
+ await this.runCells(this.model.selections);
639
+ } else {
640
+ await this.runCells([cell]);
641
+ }
642
+ };
643
+
644
+ runCellandSelectNext = async (cell: CellView) => {
645
+ this.enterCommandMode(true);
646
+ this.collapseCell(cell, false);
647
+ if (this.model.selections.length !== 0 && this.isSelected(cell)) {
648
+ const toRunCells = this.model.selections;
649
+ const selectIndex = this.findCellIndex(
650
+ this.model.selections[this.model.selections.length - 1],
651
+ );
652
+ if (selectIndex >= 0 && selectIndex < this.model.cells.length - 1) {
653
+ this.model.selectCell(this.model.cells[selectIndex + 1]);
654
+ }
655
+ if (selectIndex === this.model.cells.length - 1) {
656
+ this.addCell(
657
+ { id: v4(), cell: { cell_type: cell.model.type, source: '', metadata: {} } },
658
+ selectIndex + 1,
659
+ )
660
+ .then(() => {
661
+ this.enterEditMode();
662
+ return;
663
+ })
664
+ .catch((e) => {
665
+ //
666
+ });
667
+ }
668
+ this.runCells(toRunCells);
669
+ } else {
670
+ const selectIndex = this.findCellIndex(cell);
671
+ if (selectIndex >= 0 && selectIndex < this.model.cells.length - 1) {
672
+ this.model.selectCell(this.model.cells[selectIndex + 1]);
673
+ }
674
+ if (selectIndex === this.model.cells.length - 1) {
675
+ this.addCell(
676
+ { id: v4(), cell: { cell_type: cell.model.type, source: '', metadata: {} } },
677
+ selectIndex + 1,
678
+ )
679
+ .then(() => {
680
+ this.enterEditMode();
681
+ return;
682
+ })
683
+ .catch((e) => {
684
+ //
685
+ });
686
+ }
687
+ this.runCells([cell]);
688
+ }
689
+ setTimeout(() => {
690
+ if (this.activeCell) {
691
+ this.model.scrollToView(this.activeCell);
692
+ }
693
+ });
694
+ };
695
+
696
+ runCellandInsertBelow = async (cell: CellView) => {
697
+ this.enterCommandMode(true);
698
+ if (this.model.selections.length !== 0 && this.isSelected(cell)) {
699
+ const insertIndex = this.findCellIndex(
700
+ this.model.selections[this.model.selections.length - 1],
701
+ );
702
+ this.addCell(
703
+ { id: v4(), cell: { cell_type: cell.model.type, source: '', metadata: {} } },
704
+ insertIndex + 1,
705
+ );
706
+ this.runCells(this.model.selections);
707
+ } else {
708
+ const insertIndex = this.findCellIndex(cell);
709
+ this.addCell(
710
+ { id: v4(), cell: { cell_type: cell.model.type, source: '', metadata: {} } },
711
+ insertIndex + 1,
712
+ );
713
+ this.runCells([cell]);
714
+ }
715
+ };
716
+
717
+ moveUpCell = (cell: CellView) => {
718
+ this.collapseCell(cell, false);
719
+ const previousCell = this.getPreviousVisibleCell(cell);
720
+ if (previousCell) {
721
+ this.collapseCell(previousCell, false);
722
+ }
723
+ if (this.model.selections.length !== 0 && this.isSelected(cell)) {
724
+ for (const selectedCell of this.model.selections) {
725
+ const selectIndex = this.findCellIndex(selectedCell);
726
+ if (selectIndex === 0) {
727
+ return;
728
+ }
729
+ this.model.exchangeCells(this.model.selections, selectIndex - 1);
730
+ }
731
+ } else {
732
+ const sourceIndex = this.findCellIndex(cell);
733
+ if (sourceIndex > -1) {
734
+ this.model.exchangeCell(sourceIndex, sourceIndex - 1);
735
+ }
736
+ }
737
+ };
738
+
739
+ moveDownCell = (cell: CellView) => {
740
+ this.collapseCell(cell, false);
741
+ const nextCell = this.getNextVisibleCell(cell);
742
+ if (nextCell) {
743
+ this.collapseCell(nextCell, false);
744
+ }
745
+ if (this.model.selections.length !== 0 && this.isSelected(cell)) {
746
+ for (let i = this.model.selections.length - 1; i > -1; i--) {
747
+ const selectIndex = this.findCellIndex(this.model.selections[i]);
748
+ if (selectIndex === this.model.cells.length - 1) {
749
+ return;
750
+ }
751
+ this.model.exchangeCells(this.model.selections, selectIndex + 1);
752
+ }
753
+ } else {
754
+ const sourceIndex = this.findCellIndex(cell);
755
+ if (sourceIndex > -1) {
756
+ this.model.exchangeCell(sourceIndex, sourceIndex + 1);
757
+ }
758
+ }
759
+ };
760
+
761
+ getPreviousVisibleCell(cell: CellView) {
762
+ const currentIndex = this.findCellIndex(cell);
763
+ return this.model.cells
764
+ .slice()
765
+ .reverse()
766
+ .find(
767
+ (item, index) =>
768
+ index > this.model.cells.length - currentIndex - 1 &&
769
+ item.collapsedHidden === false,
770
+ );
771
+ }
772
+
773
+ getNextVisibleCell(cell: CellView) {
774
+ const currentIndex = this.findCellIndex(cell);
775
+ return this.model.cells.find(
776
+ (item, index) => index > currentIndex && item.collapsedHidden === false,
777
+ );
778
+ }
779
+
780
+ copyCell = (cell: CellView) => {
781
+ if (this.model.selections.length !== 0 && this.isSelected(cell)) {
782
+ const clipboard: ClipboardType = {
783
+ action: 'copy',
784
+ cells: this.model.selections.map((selection) => selection.toJSONWithoutId()),
785
+ };
786
+ copy2clipboard(JSON.stringify(clipboard));
787
+ this.clipboard = clipboard;
788
+ } else {
789
+ const clipboard: ClipboardType = {
790
+ action: 'copy',
791
+ cells: [cell.toJSONWithoutId()],
792
+ };
793
+ copy2clipboard(JSON.stringify(clipboard));
794
+ this.clipboard = clipboard;
795
+ }
796
+ };
797
+
798
+ cutCell = (cell: CellView) => {
799
+ if (this.model.selections.length !== 0 && this.isSelected(cell)) {
800
+ const clipboard: ClipboardType = {
801
+ action: 'cut',
802
+ cells: this.model.selections.map((selection) => selection.toJSONWithoutId()),
803
+ };
804
+ copy2clipboard(JSON.stringify(clipboard));
805
+ this.clipboard = clipboard;
806
+ this.deleteCell(cell);
807
+ } else {
808
+ const clipboard: ClipboardType = {
809
+ action: 'cut',
810
+ cells: [cell.toJSONWithoutId()],
811
+ };
812
+ copy2clipboard(JSON.stringify(clipboard));
813
+ this.clipboard = clipboard;
814
+ this.deleteCell(cell);
815
+ }
816
+ };
817
+
818
+ pasteCell = async (cell: CellView) => {
819
+ const pasteIndex = this.model.getCells().findIndex((item) => {
820
+ return equals(item, cell);
821
+ });
822
+ try {
823
+ let pasteValue: ClipboardType;
824
+ if (this.clipboard) {
825
+ pasteValue = this.clipboard;
826
+ } else {
827
+ pasteValue = JSON.parse(await readFromClipboard()) as ClipboardType;
828
+ }
829
+ if (pasteValue.action === 'copy' || pasteValue.action === 'cut') {
830
+ this.insertCells(
831
+ pasteValue.cells.map((item) => {
832
+ return {
833
+ id: v4(),
834
+ cell: item,
835
+ };
836
+ }),
837
+ pasteIndex + 1,
838
+ );
839
+ return;
840
+ }
841
+ } catch (e) {
842
+ console.error(e);
843
+ }
844
+ };
845
+
846
+ pasteCellAbove = async (cell: CellView) => {
847
+ const pasteIndex = this.model.getCells().findIndex((item) => {
848
+ return equals(item, cell);
849
+ });
850
+ try {
851
+ let pasteValue: ClipboardType;
852
+ if (this.clipboard) {
853
+ pasteValue = this.clipboard;
854
+ } else {
855
+ pasteValue = JSON.parse(await readFromClipboard()) as ClipboardType;
856
+ }
857
+ if (pasteValue.action === 'copy' || pasteValue.action === 'cut') {
858
+ this.insertCells(
859
+ pasteValue.cells.map((item) => {
860
+ return {
861
+ id: v4(),
862
+ cell: item,
863
+ };
864
+ }),
865
+ pasteIndex,
866
+ );
867
+ return;
868
+ }
869
+ } catch (e) {
870
+ console.error(e);
871
+ }
872
+ };
873
+
874
+ invertCell = async (cell: CellView, type: string) => {
875
+ const cellIndex = this.model.getCells().findIndex((item) => {
876
+ return equals(item, cell);
877
+ });
878
+ if (this.model.selections.length !== 0 && this.isSelected(cell)) {
879
+ for (const selectedCell of this.model.selections) {
880
+ const cellOptions: CellOptions = {
881
+ cell: {
882
+ cell_type: type,
883
+ source: selectedCell.model.source,
884
+ metadata: {
885
+ ...selectedCell.model.metadata,
886
+ libroFormatter: (selectedCell.model as LibroCellModel).libroFormatType,
887
+ },
888
+ },
889
+ };
890
+ const cellView = await this.getCellViewByOption(cellOptions);
891
+ this.model.invertCell(cellView, cellIndex);
892
+ }
893
+ } else {
894
+ const cellOptions: CellOptions = {
895
+ cell: {
896
+ cell_type: type,
897
+ source: cell.model.source,
898
+ metadata: {
899
+ ...cell.model.metadata,
900
+ libroFormatter: (cell.model as LibroCellModel).libroFormatType,
901
+ libroCellType: type,
902
+ },
903
+ },
904
+ };
905
+
906
+ const cellView = await this.getCellViewByOption(cellOptions);
907
+ this.model.invertCell(cellView, cellIndex);
908
+ }
909
+ };
910
+
911
+ clearOutputs = (cell: CellView) => {
912
+ if (this.model.selections.length !== 0 && this.isSelected(cell)) {
913
+ for (const selectedCell of this.model.selections) {
914
+ if (
915
+ ExecutableCellView.is(selectedCell) &&
916
+ ExecutableCellModel.is(selectedCell.model)
917
+ ) {
918
+ selectedCell.clearExecution();
919
+ selectedCell.model.executing = false;
920
+ selectedCell.model.hasOutputHidden = false;
921
+ }
922
+ }
923
+ } else {
924
+ if (ExecutableCellView.is(cell) && ExecutableCellModel.is(cell.model)) {
925
+ cell.clearExecution();
926
+ cell.model.executing = false;
927
+ cell.model.hasOutputHidden = false;
928
+ }
929
+ }
930
+ };
931
+
932
+ clearAllOutputs = () => {
933
+ // 清空所有 cell滚动到最上面
934
+ this.model.scrollToView(this.model.cells[0]);
935
+ for (const cell of this.model.cells) {
936
+ if (ExecutableCellView.is(cell) && ExecutableCellModel.is(cell.model)) {
937
+ cell.clearExecution();
938
+ cell.model.executing = false;
939
+ cell.model.hasOutputHidden = false;
940
+ }
941
+ }
942
+ };
943
+
944
+ hideCellCode = (cell: CellView) => {
945
+ if (this.model.selections.length !== 0 && this.isSelected(cell)) {
946
+ for (const selectedCell of this.model.selections) {
947
+ selectedCell.hasInputHidden = true;
948
+ }
949
+ } else {
950
+ cell.hasInputHidden = true;
951
+ }
952
+ };
953
+
954
+ hideOrShowCellCode = (cell: CellView) => {
955
+ if (this.model.selections.length !== 0 && this.isSelected(cell)) {
956
+ for (const selectedCell of this.model.selections) {
957
+ selectedCell.hasInputHidden = !selectedCell.hasInputHidden;
958
+ }
959
+ } else {
960
+ cell.hasInputHidden = !cell.hasInputHidden;
961
+ }
962
+ };
963
+
964
+ hideOutputs = (cell: CellView) => {
965
+ if (this.model.selections.length !== 0 && this.isSelected(cell)) {
966
+ for (const selectedCell of this.model.selections) {
967
+ if (ExecutableCellModel.is(selectedCell.model)) {
968
+ selectedCell.model.hasOutputHidden = true;
969
+ }
970
+ }
971
+ } else {
972
+ if (ExecutableCellModel.is(cell.model)) {
973
+ cell.model.hasOutputHidden = true;
974
+ }
975
+ }
976
+ };
977
+
978
+ hideOrShowOutputs = (cell: CellView) => {
979
+ if (this.model.selections.length !== 0 && this.isSelected(cell)) {
980
+ for (const selectedCell of this.model.selections) {
981
+ if (ExecutableCellModel.is(selectedCell.model)) {
982
+ selectedCell.model.hasOutputHidden = !selectedCell.model.hasOutputHidden;
983
+ }
984
+ }
985
+ } else {
986
+ if (ExecutableCellModel.is(cell.model)) {
987
+ cell.model.hasOutputHidden = !cell.model.hasOutputHidden;
988
+ }
989
+ }
990
+ };
991
+
992
+ hideAllOutputs = () => {
993
+ for (const cell of this.model.cells) {
994
+ if (ExecutableCellModel.is(cell.model)) {
995
+ cell.model.hasOutputHidden = true;
996
+ }
997
+ }
998
+ };
999
+
1000
+ hideAllCellCode = () => {
1001
+ for (const cell of this.model.cells) {
1002
+ cell.hasInputHidden = true;
1003
+ }
1004
+ };
1005
+
1006
+ showCellCode = (cell: CellView) => {
1007
+ if (this.model.selections.length !== 0 && this.isSelected(cell)) {
1008
+ for (const selectedCell of this.model.selections) {
1009
+ selectedCell.hasInputHidden = false;
1010
+ }
1011
+ } else {
1012
+ cell.hasInputHidden = false;
1013
+ }
1014
+ };
1015
+
1016
+ showAllCellCode = () => {
1017
+ for (const cell of this.model.cells) {
1018
+ cell.hasInputHidden = false;
1019
+ }
1020
+ };
1021
+
1022
+ showCellOutputs = (cell: CellView) => {
1023
+ if (this.model.selections.length !== 0 && this.isSelected(cell)) {
1024
+ for (const selectedCell of this.model.selections) {
1025
+ if (ExecutableCellModel.is(selectedCell.model)) {
1026
+ selectedCell.model.hasOutputHidden = false;
1027
+ }
1028
+ }
1029
+ } else {
1030
+ if (ExecutableCellModel.is(cell.model)) {
1031
+ cell.model.hasOutputHidden = false;
1032
+ }
1033
+ }
1034
+ };
1035
+
1036
+ showAllCellOutputs = () => {
1037
+ for (const cell of this.model.cells) {
1038
+ if (ExecutableCellModel.is(cell.model)) {
1039
+ cell.model.hasOutputHidden = false;
1040
+ }
1041
+ }
1042
+ };
1043
+
1044
+ /**
1045
+ * Whether a cell is selected.
1046
+ */
1047
+ isSelected(cell: CellView): boolean {
1048
+ if (equals(this.activeCell, cell)) {
1049
+ return true;
1050
+ }
1051
+ if (this.model.selections.length !== 0) {
1052
+ return this.model.selections.findIndex((item) => item.id === cell.id) >= 0
1053
+ ? true
1054
+ : false;
1055
+ }
1056
+ return false;
1057
+ }
1058
+
1059
+ extendSelectionAbove = () => {
1060
+ if (this.activeCell) {
1061
+ const previousCell = this.getPreviousVisibleCell(this.activeCell);
1062
+ if (previousCell) {
1063
+ this.collapseCell(previousCell, false);
1064
+ }
1065
+ const activeIndex = this.findCellIndex(this.activeCell);
1066
+ if (this.findCellIndex(this.activeCell) > 0) {
1067
+ this.extendContiguousSelectionTo(activeIndex - 1);
1068
+ }
1069
+ this.model.scrollToView(this.activeCell);
1070
+ }
1071
+ };
1072
+
1073
+ extendSelectionToTop = () => {
1074
+ if (this.activeCell) {
1075
+ if (this.findCellIndex(this.activeCell) > 0) {
1076
+ this.extendContiguousSelectionTo(0);
1077
+ }
1078
+ this.model.scrollToView(this.activeCell);
1079
+ }
1080
+ };
1081
+
1082
+ extendSelectionBelow = () => {
1083
+ if (this.activeCell) {
1084
+ const nextCell = this.getNextVisibleCell(this.activeCell);
1085
+ if (nextCell) {
1086
+ this.collapseCell(nextCell, false);
1087
+ }
1088
+ const activeIndex = this.findCellIndex(this.activeCell);
1089
+ if (this.findCellIndex(this.activeCell) >= 0) {
1090
+ this.extendContiguousSelectionTo(activeIndex + 1);
1091
+ }
1092
+ this.model.scrollToView(this.activeCell);
1093
+ }
1094
+ };
1095
+
1096
+ extendSelectionToBottom = () => {
1097
+ if (this.activeCell) {
1098
+ if (this.findCellIndex(this.activeCell) > 0) {
1099
+ this.extendContiguousSelectionTo(this.model.cells.length - 1);
1100
+ }
1101
+ this.model.scrollToView(this.activeCell);
1102
+ }
1103
+ };
1104
+
1105
+ /**
1106
+ * Move the head of an existing contiguous selection to extend the selection.
1107
+ *
1108
+ * @param index - The new head of the existing selection.
1109
+ *
1110
+ * #### Notes
1111
+ * If there is no existing selection, the active cell is considered an
1112
+ * existing one-cell selection.
1113
+ *
1114
+ * If the new selection is a single cell, that cell becomes the active cell
1115
+ * and all cells are deselected.
1116
+ *
1117
+ * There is no change if there are no cells (i.e., activeCellIndex is -1).
1118
+ */
1119
+ extendContiguousSelectionTo(index: number): void {
1120
+ let selectIndex = index;
1121
+ let { head, anchor } = this.getContiguousSelection();
1122
+ if (this.activeCell) {
1123
+ // Handle the case of no current selection.
1124
+ if (anchor === null || head === null) {
1125
+ if (selectIndex === this.model.activeIndex) {
1126
+ // Already collapsed selection, nothing more to do.
1127
+ return;
1128
+ }
1129
+
1130
+ // We will start a new selection below.
1131
+ head = this.model.activeIndex;
1132
+ anchor = this.model.activeIndex;
1133
+ }
1134
+ // Move the active cell. We do this before the collapsing shortcut below.
1135
+ if (this.model.cells[selectIndex]) {
1136
+ this.model.active = this.model.cells[selectIndex];
1137
+ this.model.activeIndex = selectIndex;
1138
+ }
1139
+ // Make sure the index is valid, according to the rules for setting and clipping the
1140
+ // active cell index. This may change the index.
1141
+ selectIndex = this.model.activeIndex;
1142
+
1143
+ // Collapse the selection if it is only the active cell.
1144
+ if (selectIndex === anchor) {
1145
+ // this.deselectAll();
1146
+ this.model.selections = [];
1147
+ return;
1148
+ }
1149
+ this.model.selections = this.model.cells.slice(
1150
+ Math.min(anchor, selectIndex),
1151
+ Math.max(anchor, selectIndex) + 1,
1152
+ );
1153
+ }
1154
+ }
1155
+
1156
+ /**
1157
+ * Get the head and anchor of a contiguous cell selection.
1158
+ *
1159
+ * The head of a contiguous selection is always the active cell.
1160
+ *
1161
+ * If there are no cells selected, `{head: null, anchor: null}` is returned.
1162
+ *
1163
+ * Throws an error if the currently selected cells do not form a contiguous
1164
+ * selection.
1165
+ */
1166
+ getContiguousSelection():
1167
+ | { head: number; anchor: number }
1168
+ | { head: null; anchor: null } {
1169
+ if (this.model.selections.length !== 0 && this.activeCell) {
1170
+ const first = this.findCellIndex(this.model.selections[0]);
1171
+ const last = this.findCellIndex(
1172
+ this.model.selections[this.model.selections.length - 1],
1173
+ );
1174
+ // Check that the active cell is one of the endpoints of the selection.
1175
+ const activeIndex = this.findCellIndex(this.activeCell);
1176
+ if (first !== activeIndex && last !== activeIndex) {
1177
+ throw new Error('Active cell not at endpoint of selection');
1178
+ }
1179
+
1180
+ // Determine the head and anchor of the selection.
1181
+ if (first === activeIndex) {
1182
+ return { head: first, anchor: last };
1183
+ } else {
1184
+ return { head: last, anchor: first };
1185
+ }
1186
+ }
1187
+ return { head: null, anchor: null };
1188
+ }
1189
+
1190
+ enableOutputScrolling = (cell: CellView) => {
1191
+ if (this.model.selections.length !== 0 && this.isSelected(cell)) {
1192
+ for (const selectedCell of this.model.selections) {
1193
+ if (ExecutableCellModel.is(selectedCell.model)) {
1194
+ selectedCell.model.hasOutputsScrolled = true;
1195
+ }
1196
+ }
1197
+ } else {
1198
+ if (ExecutableCellModel.is(cell.model)) {
1199
+ cell.model.hasOutputsScrolled = true;
1200
+ }
1201
+ }
1202
+ };
1203
+
1204
+ disableOutputScrolling = (cell: CellView) => {
1205
+ this.outputsScroll = false;
1206
+ if (this.model.selections.length !== 0 && this.isSelected(cell)) {
1207
+ for (const selectedCell of this.model.selections) {
1208
+ if (ExecutableCellModel.is(selectedCell.model)) {
1209
+ selectedCell.model.hasOutputsScrolled = false;
1210
+ }
1211
+ }
1212
+ } else {
1213
+ if (ExecutableCellModel.is(cell.model)) {
1214
+ cell.model.hasOutputsScrolled = false;
1215
+ }
1216
+ }
1217
+ };
1218
+
1219
+ disableAllOutputScrolling = () => {
1220
+ this.outputsScroll = false;
1221
+ for (const cell of this.model.cells) {
1222
+ if (ExecutableCellModel.is(cell.model)) {
1223
+ cell.model.hasOutputsScrolled = false;
1224
+ }
1225
+ }
1226
+ };
1227
+
1228
+ enableAllOutputScrolling = () => {
1229
+ this.outputsScroll = true;
1230
+ for (const cell of this.model.cells) {
1231
+ if (ExecutableCellModel.is(cell.model)) {
1232
+ cell.model.hasOutputsScrolled = true;
1233
+ }
1234
+ }
1235
+ };
1236
+
1237
+ disposed = false;
1238
+
1239
+ override dispose() {
1240
+ if (!this.disposed) {
1241
+ this.libroService.deleteLibroViewFromCache(this);
1242
+ this.toDispose.dispose();
1243
+ }
1244
+ this.disposed = true;
1245
+ super.dispose();
1246
+ }
1247
+
1248
+ enterCommandMode = (isInLibro: boolean) => {
1249
+ if (this.hasModal) {
1250
+ return;
1251
+ }
1252
+ if (this.model.enterCommandMode) {
1253
+ this.model.enterCommandMode();
1254
+ }
1255
+ if (isInLibro) {
1256
+ this.container?.current?.focus();
1257
+ }
1258
+ };
1259
+
1260
+ enterEditMode = () => {
1261
+ if (this.model.enterEditMode) {
1262
+ this.model.enterEditMode();
1263
+ }
1264
+ };
1265
+
1266
+ moveCursorDown = (cell: CellView) => {
1267
+ const newSelectedCell = this.getNextVisibleCell(cell);
1268
+ if (newSelectedCell) {
1269
+ this.model.selectCell(newSelectedCell);
1270
+ this.model.selections = [];
1271
+ this.model.scrollToView(newSelectedCell);
1272
+ }
1273
+ };
1274
+
1275
+ moveCursorUp = (cell: CellView) => {
1276
+ const newSelectedCell = this.getPreviousVisibleCell(cell);
1277
+ if (newSelectedCell) {
1278
+ this.model.selectCell(newSelectedCell);
1279
+ this.model.selections = [];
1280
+ this.model.scrollToView(newSelectedCell);
1281
+ }
1282
+ };
1283
+
1284
+ mergeCellBelow = async (cell: CellView) => {
1285
+ const { cells, selections } = this.model;
1286
+ if (selections.length > 1) {
1287
+ this.mergeCells(cell);
1288
+ return;
1289
+ }
1290
+ const selectedIndex = this.findCellIndex(cell);
1291
+ if (selectedIndex >= cells.length - 1) {
1292
+ return;
1293
+ }
1294
+ const nextCell = cells[selectedIndex + 1];
1295
+ const source = concatMultilineString([
1296
+ cell.model.value + '\n',
1297
+ nextCell.model.value,
1298
+ ]);
1299
+ const cellView = await this.getCellViewByOption({
1300
+ id: v4(),
1301
+ cell: { cell_type: cell.model.type, source, metadata: {} },
1302
+ });
1303
+ if (this.model instanceof LibroModel) {
1304
+ this.model.activeIndex = selectedIndex;
1305
+ const cellData = [cellView].map((_cell) => {
1306
+ (this.model as LibroModel).cellViewCache.set(_cell.model.id, _cell);
1307
+ return _cell.toJSON();
1308
+ });
1309
+ this.model.sharedModel.transact(() => {
1310
+ this.model.sharedModel.deleteCell(selectedIndex);
1311
+ this.model.sharedModel.insertCells(selectedIndex, cellData);
1312
+ this.model.sharedModel.deleteCell(selectedIndex + 1);
1313
+ });
1314
+ }
1315
+ };
1316
+
1317
+ mergeCellAbove = async (cell: CellView) => {
1318
+ const { cells, selections } = this.model;
1319
+ if (selections.length > 1) {
1320
+ this.mergeCells(cell);
1321
+ return;
1322
+ }
1323
+ const selectedIndex = this.findCellIndex(cell);
1324
+ if (selectedIndex <= 0) {
1325
+ return;
1326
+ }
1327
+ const prevCell = cells[selectedIndex - 1];
1328
+ const source = concatMultilineString([
1329
+ prevCell.model.value + '\n' + cell.model.value,
1330
+ ]);
1331
+ const cellView = await this.getCellViewByOption({
1332
+ id: v4(),
1333
+ cell: { cell_type: cell.model.type, source, metadata: {} },
1334
+ });
1335
+ if (this.model instanceof LibroModel) {
1336
+ this.model.activeIndex = selectedIndex - 1;
1337
+ const cellData = [cellView].map((_cell) => {
1338
+ (this.model as LibroModel).cellViewCache.set(_cell.model.id, _cell);
1339
+ return _cell.toJSON();
1340
+ });
1341
+ this.model.sharedModel.transact(() => {
1342
+ this.model.sharedModel.deleteCell(selectedIndex - 1);
1343
+ this.model.sharedModel.insertCells(selectedIndex - 1, cellData);
1344
+ this.model.sharedModel.deleteCell(selectedIndex);
1345
+ });
1346
+ }
1347
+ };
1348
+
1349
+ mergeCells = async (cell: CellView) => {
1350
+ const { selections } = this.model;
1351
+ if (selections.length <= 1) {
1352
+ return;
1353
+ }
1354
+ const selectionsValue: string[] = [];
1355
+ const selectionsIndex: number[] = [];
1356
+ selections.map((item) => {
1357
+ selectionsValue.push(item.model.value);
1358
+ selectionsValue.push('\n');
1359
+ const index = this.findCellIndex(item);
1360
+ selectionsIndex.push(index);
1361
+ });
1362
+ const source = concatMultilineString(selectionsValue);
1363
+ const cellView = await this.getCellViewByOption({
1364
+ id: v4(),
1365
+ cell: { cell_type: cell.model.type, source, metadata: {} },
1366
+ });
1367
+
1368
+ if (this.model instanceof LibroModel) {
1369
+ this.model.activeIndex = Math.min(...selectionsIndex);
1370
+ const cellData = [cellView].map((_cell) => {
1371
+ (this.model as LibroModel).cellViewCache.set(_cell.model.id, _cell);
1372
+ return _cell.toJSON();
1373
+ });
1374
+ const startIndex = Math.min(...selectionsIndex);
1375
+ const endIndex = Math.max(...selectionsIndex);
1376
+ this.model.sharedModel.transact(() => {
1377
+ this.model.sharedModel.deleteCellRange(startIndex, endIndex + 1);
1378
+ this.model.sharedModel.insertCells(Math.min(...selectionsIndex), cellData);
1379
+ });
1380
+ }
1381
+ };
1382
+ selectAllCell = () => {
1383
+ this.model.selections = this.model.cells;
1384
+ };
1385
+
1386
+ splitCell = async (cell: CellView) => {
1387
+ const index = this.findCellIndex(cell);
1388
+ if (EditorCellView.is(cell)) {
1389
+ const selections = cell.editor?.getSelections() ?? [];
1390
+ const offsets = [0];
1391
+ for (let i = 0; i < selections.length; i++) {
1392
+ // append start and end to handle selections
1393
+ // cursors will have same start and end
1394
+ const select = selections[i];
1395
+ const start = cell.editor?.getOffsetAt(select.start) ?? 0;
1396
+ const end = cell.editor?.getOffsetAt(select.end) ?? 0;
1397
+ if (start < end) {
1398
+ offsets.push(start);
1399
+ offsets.push(end);
1400
+ } else if (end < start) {
1401
+ offsets.push(end);
1402
+ offsets.push(start);
1403
+ } else {
1404
+ offsets.push(start);
1405
+ }
1406
+ }
1407
+
1408
+ offsets.push(cell.model.value.length);
1409
+
1410
+ const splitCells = await Promise.all(
1411
+ offsets.slice(0, -1).map(async (offset, offsetIdx) => {
1412
+ const cellView = await this.getCellViewByOption({
1413
+ id: v4(),
1414
+ cell: {
1415
+ cell_type: cell.model.type,
1416
+ source: cell.model.value
1417
+ .slice(offset, offsets[offsetIdx + 1])
1418
+ .replace(/^\n+/, '')
1419
+ .replace(/\n+$/, ''),
1420
+ metadata: {},
1421
+ },
1422
+ });
1423
+ return cellView;
1424
+ }),
1425
+ );
1426
+ this.model.splitCell(splitCells, index);
1427
+ }
1428
+ };
1429
+ restartClearOutput = () => {
1430
+ if (this.model.restart) {
1431
+ this.model.restart();
1432
+ }
1433
+ this.clearAllOutputs();
1434
+ };
1435
+
1436
+ closeAndShutdown = () => {
1437
+ if (this.model.shutdown) {
1438
+ this.model.shutdown();
1439
+ }
1440
+ };
1441
+
1442
+ /**
1443
+ * Set the markdown header level of a cell.
1444
+ */
1445
+ setMarkdownHeader = async (cell: CellView, level: number) => {
1446
+ if (this.model.selections.length !== 0 && this.isSelected(cell)) {
1447
+ const { selections } = this.model;
1448
+ const selectionsValue: string[] = [];
1449
+ const selectionsIndex: number[] = [];
1450
+ const cellViews = await Promise.all(
1451
+ selections.map(async (item) => {
1452
+ let source = item.model.value;
1453
+ const regex = /^(#+\s*)|^(\s*)/;
1454
+ const newHeader = Array(level + 1).join('#') + ' ';
1455
+ const matches = regex.exec(source);
1456
+ if (matches) {
1457
+ source = source.slice(matches[0].length);
1458
+ }
1459
+ source = newHeader + source;
1460
+ selectionsValue.push(source);
1461
+ const index = this.findCellIndex(item);
1462
+ selectionsIndex.push(index);
1463
+ const cellView = await this.getCellViewByOption({
1464
+ id: v4(),
1465
+ cell: { cell_type: 'markdown', source, metadata: {} },
1466
+ });
1467
+ return cellView;
1468
+ }),
1469
+ );
1470
+ // TODO: why is this needed?
1471
+ // const source = concatMultilineString(selectionsValue);
1472
+
1473
+ if (this.model instanceof LibroModel) {
1474
+ this.model.activeIndex = Math.min(...selectionsIndex);
1475
+ const cellData = cellViews.map((_cell) => {
1476
+ (this.model as LibroModel).cellViewCache.set(_cell.model.id, _cell);
1477
+ return _cell.toJSON();
1478
+ });
1479
+ const startIndex = Math.min(...selectionsIndex);
1480
+ const endIndex = Math.max(...selectionsIndex);
1481
+ this.model.sharedModel.transact(() => {
1482
+ this.model.sharedModel.deleteCellRange(startIndex, endIndex + 1);
1483
+ this.model.sharedModel.insertCells(startIndex, cellData);
1484
+ });
1485
+ }
1486
+ } else {
1487
+ const index = this.findCellIndex(cell);
1488
+ let source = cell.model.value;
1489
+ const regex = /^(#+\s*)|^(\s*)/;
1490
+ const newHeader = Array(level + 1).join('#') + ' ';
1491
+ const matches = regex.exec(source);
1492
+ if (matches) {
1493
+ source = source.slice(matches[0].length);
1494
+ }
1495
+ source = newHeader + source;
1496
+ const cellView = await this.getCellViewByOption({
1497
+ id: v4(),
1498
+ cell: { cell_type: 'markdown', source, metadata: {} },
1499
+ });
1500
+
1501
+ if (this.model instanceof LibroModel) {
1502
+ this.model.activeIndex = index;
1503
+ const cellData = [cellView].map((_cell) => {
1504
+ (this.model as LibroModel).cellViewCache.set(_cell.model.id, _cell);
1505
+ return _cell.toJSON();
1506
+ });
1507
+ this.model.sharedModel.transact(() => {
1508
+ this.model.sharedModel.deleteCell(index);
1509
+ this.model.sharedModel.insertCells(index, cellData);
1510
+ });
1511
+ }
1512
+ }
1513
+ this.enterCommandMode(true);
1514
+ };
1515
+
1516
+ collapseCell(cell: CellView, collspse: boolean) {
1517
+ this.collapseService.setHeadingCollapse(cell, collspse);
1518
+ }
1519
+
1520
+ save() {
1521
+ this.saving = true;
1522
+ try {
1523
+ this.model.saveNotebookContent();
1524
+ this.onSaveEmitter.fire(true);
1525
+ this.model.dirty = false;
1526
+ } catch (ex) {
1527
+ this.onSaveEmitter.fire(false);
1528
+ } finally {
1529
+ this.saving = false;
1530
+ }
1531
+ }
1532
+ }