@theia/notebook 1.67.0-next.13 → 1.67.0-next.56

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 (244) hide show
  1. package/README.md +1 -1
  2. package/package.json +7 -7
  3. package/src/browser/contributions/notebook-actions-contribution.ts +25 -22
  4. package/src/browser/contributions/notebook-cell-actions-contribution.ts +20 -9
  5. package/src/browser/contributions/notebook-label-provider-contribution.ts +2 -1
  6. package/src/browser/contributions/notebook-outline-contribution.ts +8 -6
  7. package/src/browser/contributions/notebook-status-bar-contribution.ts +4 -6
  8. package/src/browser/index.ts +1 -0
  9. package/src/browser/notebook-cell-open-handler.ts +3 -3
  10. package/src/browser/notebook-editor-split-contribution.ts +51 -0
  11. package/src/browser/notebook-editor-widget-factory.ts +11 -1
  12. package/src/browser/notebook-editor-widget.tsx +18 -3
  13. package/src/browser/notebook-frontend-module.ts +5 -0
  14. package/src/browser/notebook-open-handler.ts +19 -11
  15. package/src/browser/notebook-types.ts +1 -0
  16. package/src/browser/service/notebook-context-manager.ts +17 -9
  17. package/src/browser/view/notebook-cell-editor.tsx +13 -5
  18. package/src/browser/view/notebook-cell-list-view.tsx +15 -12
  19. package/src/browser/view/notebook-cell-toolbar-factory.tsx +5 -4
  20. package/src/browser/view/notebook-code-cell-view.tsx +6 -1
  21. package/src/browser/view/notebook-markdown-cell-view.tsx +27 -7
  22. package/src/browser/view-model/notebook-cell-model.ts +8 -41
  23. package/src/browser/view-model/notebook-model.ts +2 -33
  24. package/src/browser/view-model/notebook-view-model.ts +138 -0
  25. package/lib/browser/contributions/cell-operations.d.ts +0 -8
  26. package/lib/browser/contributions/cell-operations.d.ts.map +0 -1
  27. package/lib/browser/contributions/cell-operations.js +0 -45
  28. package/lib/browser/contributions/cell-operations.js.map +0 -1
  29. package/lib/browser/contributions/notebook-actions-contribution.d.ts +0 -48
  30. package/lib/browser/contributions/notebook-actions-contribution.d.ts.map +0 -1
  31. package/lib/browser/contributions/notebook-actions-contribution.js +0 -341
  32. package/lib/browser/contributions/notebook-actions-contribution.js.map +0 -1
  33. package/lib/browser/contributions/notebook-cell-actions-contribution.d.ts +0 -66
  34. package/lib/browser/contributions/notebook-cell-actions-contribution.d.ts.map +0 -1
  35. package/lib/browser/contributions/notebook-cell-actions-contribution.js +0 -512
  36. package/lib/browser/contributions/notebook-cell-actions-contribution.js.map +0 -1
  37. package/lib/browser/contributions/notebook-color-contribution.d.ts +0 -6
  38. package/lib/browser/contributions/notebook-color-contribution.d.ts.map +0 -1
  39. package/lib/browser/contributions/notebook-color-contribution.js +0 -247
  40. package/lib/browser/contributions/notebook-color-contribution.js.map +0 -1
  41. package/lib/browser/contributions/notebook-context-keys.d.ts +0 -44
  42. package/lib/browser/contributions/notebook-context-keys.d.ts.map +0 -1
  43. package/lib/browser/contributions/notebook-context-keys.js +0 -108
  44. package/lib/browser/contributions/notebook-context-keys.js.map +0 -1
  45. package/lib/browser/contributions/notebook-label-provider-contribution.d.ts +0 -19
  46. package/lib/browser/contributions/notebook-label-provider-contribution.d.ts.map +0 -1
  47. package/lib/browser/contributions/notebook-label-provider-contribution.js +0 -85
  48. package/lib/browser/contributions/notebook-label-provider-contribution.js.map +0 -1
  49. package/lib/browser/contributions/notebook-outline-contribution.d.ts +0 -28
  50. package/lib/browser/contributions/notebook-outline-contribution.d.ts.map +0 -1
  51. package/lib/browser/contributions/notebook-outline-contribution.js +0 -113
  52. package/lib/browser/contributions/notebook-outline-contribution.js.map +0 -1
  53. package/lib/browser/contributions/notebook-output-action-contribution.d.ts +0 -16
  54. package/lib/browser/contributions/notebook-output-action-contribution.d.ts.map +0 -1
  55. package/lib/browser/contributions/notebook-output-action-contribution.js +0 -83
  56. package/lib/browser/contributions/notebook-output-action-contribution.js.map +0 -1
  57. package/lib/browser/contributions/notebook-status-bar-contribution.d.ts +0 -12
  58. package/lib/browser/contributions/notebook-status-bar-contribution.d.ts.map +0 -1
  59. package/lib/browser/contributions/notebook-status-bar-contribution.js +0 -63
  60. package/lib/browser/contributions/notebook-status-bar-contribution.js.map +0 -1
  61. package/lib/browser/contributions/notebook-undo-redo-handler.d.ts +0 -10
  62. package/lib/browser/contributions/notebook-undo-redo-handler.d.ts.map +0 -1
  63. package/lib/browser/contributions/notebook-undo-redo-handler.js +0 -49
  64. package/lib/browser/contributions/notebook-undo-redo-handler.js.map +0 -1
  65. package/lib/browser/index.d.ts +0 -13
  66. package/lib/browser/index.d.ts.map +0 -1
  67. package/lib/browser/index.js +0 -31
  68. package/lib/browser/index.js.map +0 -1
  69. package/lib/browser/notebook-cell-open-handler.d.ts +0 -10
  70. package/lib/browser/notebook-cell-open-handler.d.ts.map +0 -1
  71. package/lib/browser/notebook-cell-open-handler.js +0 -51
  72. package/lib/browser/notebook-cell-open-handler.js.map +0 -1
  73. package/lib/browser/notebook-cell-resource-resolver.d.ts +0 -26
  74. package/lib/browser/notebook-cell-resource-resolver.d.ts.map +0 -1
  75. package/lib/browser/notebook-cell-resource-resolver.js +0 -109
  76. package/lib/browser/notebook-cell-resource-resolver.js.map +0 -1
  77. package/lib/browser/notebook-editor-widget-factory.d.ts +0 -19
  78. package/lib/browser/notebook-editor-widget-factory.d.ts.map +0 -1
  79. package/lib/browser/notebook-editor-widget-factory.js +0 -93
  80. package/lib/browser/notebook-editor-widget-factory.js.map +0 -1
  81. package/lib/browser/notebook-editor-widget.d.ts +0 -99
  82. package/lib/browser/notebook-editor-widget.d.ts.map +0 -1
  83. package/lib/browser/notebook-editor-widget.js +0 -323
  84. package/lib/browser/notebook-editor-widget.js.map +0 -1
  85. package/lib/browser/notebook-frontend-module.d.ts +0 -5
  86. package/lib/browser/notebook-frontend-module.d.ts.map +0 -1
  87. package/lib/browser/notebook-frontend-module.js +0 -112
  88. package/lib/browser/notebook-frontend-module.js.map +0 -1
  89. package/lib/browser/notebook-open-handler.d.ts +0 -23
  90. package/lib/browser/notebook-open-handler.d.ts.map +0 -1
  91. package/lib/browser/notebook-open-handler.js +0 -113
  92. package/lib/browser/notebook-open-handler.js.map +0 -1
  93. package/lib/browser/notebook-output-utils.d.ts +0 -13
  94. package/lib/browser/notebook-output-utils.d.ts.map +0 -1
  95. package/lib/browser/notebook-output-utils.js +0 -112
  96. package/lib/browser/notebook-output-utils.js.map +0 -1
  97. package/lib/browser/notebook-renderer-registry.d.ts +0 -25
  98. package/lib/browser/notebook-renderer-registry.d.ts.map +0 -1
  99. package/lib/browser/notebook-renderer-registry.js +0 -72
  100. package/lib/browser/notebook-renderer-registry.js.map +0 -1
  101. package/lib/browser/notebook-type-registry.d.ts +0 -12
  102. package/lib/browser/notebook-type-registry.d.ts.map +0 -1
  103. package/lib/browser/notebook-type-registry.js +0 -60
  104. package/lib/browser/notebook-type-registry.js.map +0 -1
  105. package/lib/browser/notebook-types.d.ts +0 -130
  106. package/lib/browser/notebook-types.d.ts.map +0 -1
  107. package/lib/browser/notebook-types.js +0 -28
  108. package/lib/browser/notebook-types.js.map +0 -1
  109. package/lib/browser/renderers/cell-output-webview.d.ts +0 -26
  110. package/lib/browser/renderers/cell-output-webview.d.ts.map +0 -1
  111. package/lib/browser/renderers/cell-output-webview.js +0 -21
  112. package/lib/browser/renderers/cell-output-webview.js.map +0 -1
  113. package/lib/browser/service/notebook-cell-editor-service.d.ts +0 -23
  114. package/lib/browser/service/notebook-cell-editor-service.d.ts.map +0 -1
  115. package/lib/browser/service/notebook-cell-editor-service.js +0 -89
  116. package/lib/browser/service/notebook-cell-editor-service.js.map +0 -1
  117. package/lib/browser/service/notebook-cell-status-bar-service.d.ts +0 -39
  118. package/lib/browser/service/notebook-cell-status-bar-service.d.ts.map +0 -1
  119. package/lib/browser/service/notebook-cell-status-bar-service.js +0 -69
  120. package/lib/browser/service/notebook-cell-status-bar-service.js.map +0 -1
  121. package/lib/browser/service/notebook-clipboard-service.d.ts +0 -10
  122. package/lib/browser/service/notebook-clipboard-service.d.ts.map +0 -1
  123. package/lib/browser/service/notebook-clipboard-service.js +0 -42
  124. package/lib/browser/service/notebook-clipboard-service.js.map +0 -1
  125. package/lib/browser/service/notebook-context-manager.d.ts +0 -26
  126. package/lib/browser/service/notebook-context-manager.d.ts.map +0 -1
  127. package/lib/browser/service/notebook-context-manager.js +0 -131
  128. package/lib/browser/service/notebook-context-manager.js.map +0 -1
  129. package/lib/browser/service/notebook-editor-widget-service.d.ts +0 -27
  130. package/lib/browser/service/notebook-editor-widget-service.d.ts.map +0 -1
  131. package/lib/browser/service/notebook-editor-widget-service.js +0 -124
  132. package/lib/browser/service/notebook-editor-widget-service.js.map +0 -1
  133. package/lib/browser/service/notebook-execution-service.d.ts +0 -25
  134. package/lib/browser/service/notebook-execution-service.d.ts.map +0 -1
  135. package/lib/browser/service/notebook-execution-service.js +0 -150
  136. package/lib/browser/service/notebook-execution-service.js.map +0 -1
  137. package/lib/browser/service/notebook-execution-state-service.d.ts +0 -78
  138. package/lib/browser/service/notebook-execution-state-service.d.ts.map +0 -1
  139. package/lib/browser/service/notebook-execution-state-service.js +0 -247
  140. package/lib/browser/service/notebook-execution-state-service.js.map +0 -1
  141. package/lib/browser/service/notebook-kernel-history-service.d.ts +0 -28
  142. package/lib/browser/service/notebook-kernel-history-service.d.ts.map +0 -1
  143. package/lib/browser/service/notebook-kernel-history-service.js +0 -116
  144. package/lib/browser/service/notebook-kernel-history-service.js.map +0 -1
  145. package/lib/browser/service/notebook-kernel-quick-pick-service.d.ts +0 -61
  146. package/lib/browser/service/notebook-kernel-quick-pick-service.d.ts.map +0 -1
  147. package/lib/browser/service/notebook-kernel-quick-pick-service.js +0 -425
  148. package/lib/browser/service/notebook-kernel-quick-pick-service.js.map +0 -1
  149. package/lib/browser/service/notebook-kernel-service.d.ts +0 -125
  150. package/lib/browser/service/notebook-kernel-service.d.ts.map +0 -1
  151. package/lib/browser/service/notebook-kernel-service.js +0 -268
  152. package/lib/browser/service/notebook-kernel-service.js.map +0 -1
  153. package/lib/browser/service/notebook-model-resolver-service.d.ts +0 -28
  154. package/lib/browser/service/notebook-model-resolver-service.d.ts.map +0 -1
  155. package/lib/browser/service/notebook-model-resolver-service.js +0 -157
  156. package/lib/browser/service/notebook-model-resolver-service.js.map +0 -1
  157. package/lib/browser/service/notebook-monaco-text-model-service.d.ts +0 -21
  158. package/lib/browser/service/notebook-monaco-text-model-service.d.ts.map +0 -1
  159. package/lib/browser/service/notebook-monaco-text-model-service.js +0 -73
  160. package/lib/browser/service/notebook-monaco-text-model-service.js.map +0 -1
  161. package/lib/browser/service/notebook-options.d.ts +0 -30
  162. package/lib/browser/service/notebook-options.d.ts.map +0 -1
  163. package/lib/browser/service/notebook-options.js +0 -130
  164. package/lib/browser/service/notebook-options.js.map +0 -1
  165. package/lib/browser/service/notebook-renderer-messaging-service.d.ts +0 -35
  166. package/lib/browser/service/notebook-renderer-messaging-service.d.ts.map +0 -1
  167. package/lib/browser/service/notebook-renderer-messaging-service.js +0 -100
  168. package/lib/browser/service/notebook-renderer-messaging-service.js.map +0 -1
  169. package/lib/browser/service/notebook-service.d.ts +0 -68
  170. package/lib/browser/service/notebook-service.d.ts.map +0 -1
  171. package/lib/browser/service/notebook-service.js +0 -184
  172. package/lib/browser/service/notebook-service.js.map +0 -1
  173. package/lib/browser/view/notebook-cell-editor.d.ts +0 -44
  174. package/lib/browser/view/notebook-cell-editor.d.ts.map +0 -1
  175. package/lib/browser/view/notebook-cell-editor.js +0 -267
  176. package/lib/browser/view/notebook-cell-editor.js.map +0 -1
  177. package/lib/browser/view/notebook-cell-list-view.d.ts +0 -56
  178. package/lib/browser/view/notebook-cell-list-view.d.ts.map +0 -1
  179. package/lib/browser/view/notebook-cell-list-view.js +0 -222
  180. package/lib/browser/view/notebook-cell-list-view.js.map +0 -1
  181. package/lib/browser/view/notebook-cell-toolbar-factory.d.ts +0 -33
  182. package/lib/browser/view/notebook-cell-toolbar-factory.d.ts.map +0 -1
  183. package/lib/browser/view/notebook-cell-toolbar-factory.js +0 -110
  184. package/lib/browser/view/notebook-cell-toolbar-factory.js.map +0 -1
  185. package/lib/browser/view/notebook-cell-toolbar.d.ts +0 -25
  186. package/lib/browser/view/notebook-cell-toolbar.d.ts.map +0 -1
  187. package/lib/browser/view/notebook-cell-toolbar.js +0 -51
  188. package/lib/browser/view/notebook-cell-toolbar.js.map +0 -1
  189. package/lib/browser/view/notebook-code-cell-view.d.ts +0 -91
  190. package/lib/browser/view/notebook-code-cell-view.d.ts.map +0 -1
  191. package/lib/browser/view/notebook-code-cell-view.js +0 -333
  192. package/lib/browser/view/notebook-code-cell-view.js.map +0 -1
  193. package/lib/browser/view/notebook-find-widget.d.ts +0 -63
  194. package/lib/browser/view/notebook-find-widget.d.ts.map +0 -1
  195. package/lib/browser/view/notebook-find-widget.js +0 -225
  196. package/lib/browser/view/notebook-find-widget.js.map +0 -1
  197. package/lib/browser/view/notebook-main-toolbar.d.ts +0 -53
  198. package/lib/browser/view/notebook-main-toolbar.d.ts.map +0 -1
  199. package/lib/browser/view/notebook-main-toolbar.js +0 -184
  200. package/lib/browser/view/notebook-main-toolbar.js.map +0 -1
  201. package/lib/browser/view/notebook-markdown-cell-view.d.ts +0 -26
  202. package/lib/browser/view/notebook-markdown-cell-view.d.ts.map +0 -1
  203. package/lib/browser/view/notebook-markdown-cell-view.js +0 -198
  204. package/lib/browser/view/notebook-markdown-cell-view.js.map +0 -1
  205. package/lib/browser/view/notebook-viewport-service.d.ts +0 -17
  206. package/lib/browser/view/notebook-viewport-service.d.ts.map +0 -1
  207. package/lib/browser/view/notebook-viewport-service.js +0 -61
  208. package/lib/browser/view/notebook-viewport-service.js.map +0 -1
  209. package/lib/browser/view-model/notebook-cell-model.d.ts +0 -149
  210. package/lib/browser/view-model/notebook-cell-model.d.ts.map +0 -1
  211. package/lib/browser/view-model/notebook-cell-model.js +0 -391
  212. package/lib/browser/view-model/notebook-cell-model.js.map +0 -1
  213. package/lib/browser/view-model/notebook-cell-output-model.d.ts +0 -17
  214. package/lib/browser/view-model/notebook-cell-output-model.d.ts.map +0 -1
  215. package/lib/browser/view-model/notebook-cell-output-model.js +0 -87
  216. package/lib/browser/view-model/notebook-cell-output-model.js.map +0 -1
  217. package/lib/browser/view-model/notebook-model.d.ts +0 -93
  218. package/lib/browser/view-model/notebook-model.d.ts.map +0 -1
  219. package/lib/browser/view-model/notebook-model.js +0 -468
  220. package/lib/browser/view-model/notebook-model.js.map +0 -1
  221. package/lib/common/index.d.ts +0 -3
  222. package/lib/common/index.d.ts.map +0 -1
  223. package/lib/common/index.js +0 -21
  224. package/lib/common/index.js.map +0 -1
  225. package/lib/common/notebook-common.d.ts +0 -227
  226. package/lib/common/notebook-common.d.ts.map +0 -1
  227. package/lib/common/notebook-common.js +0 -151
  228. package/lib/common/notebook-common.js.map +0 -1
  229. package/lib/common/notebook-preferences.d.ts +0 -15
  230. package/lib/common/notebook-preferences.d.ts.map +0 -1
  231. package/lib/common/notebook-preferences.js +0 -89
  232. package/lib/common/notebook-preferences.js.map +0 -1
  233. package/lib/common/notebook-protocol.d.ts +0 -21
  234. package/lib/common/notebook-protocol.d.ts.map +0 -1
  235. package/lib/common/notebook-protocol.js +0 -18
  236. package/lib/common/notebook-protocol.js.map +0 -1
  237. package/lib/common/notebook-range.d.ts +0 -14
  238. package/lib/common/notebook-range.d.ts.map +0 -1
  239. package/lib/common/notebook-range.js +0 -18
  240. package/lib/common/notebook-range.js.map +0 -1
  241. package/lib/node/notebook-backend-module.d.ts +0 -4
  242. package/lib/node/notebook-backend-module.d.ts.map +0 -1
  243. package/lib/node/notebook-backend-module.js +0 -23
  244. package/lib/node/notebook-backend-module.js.map +0 -1
package/README.md CHANGED
@@ -16,7 +16,7 @@ The `@theia/notebook` extension contributes functionality for integrated noteboo
16
16
 
17
17
  ## Additional Information
18
18
 
19
- - [API documentation for `@theia/notebook`](https://eclipse-theia.github.io/theia/docs/next/modules/notebook.html)
19
+ - [API documentation for `@theia/notebook`](https://eclipse-theia.github.io/theia/docs/next/modules/_theia_notebook.html)
20
20
  - [Theia - GitHub](https://github.com/eclipse-theia/theia)
21
21
  - [Theia - Website](https://theia-ide.org/)
22
22
 
package/package.json CHANGED
@@ -1,14 +1,14 @@
1
1
  {
2
2
  "name": "@theia/notebook",
3
- "version": "1.67.0-next.13+c409d5d18",
3
+ "version": "1.67.0-next.56+d8f18cc386c",
4
4
  "description": "Theia - Notebook Extension",
5
5
  "dependencies": {
6
- "@theia/core": "1.67.0-next.13+c409d5d18",
7
- "@theia/editor": "1.67.0-next.13+c409d5d18",
8
- "@theia/filesystem": "1.67.0-next.13+c409d5d18",
9
- "@theia/monaco": "1.67.0-next.13+c409d5d18",
6
+ "@theia/core": "1.67.0-next.56+d8f18cc386c",
7
+ "@theia/editor": "1.67.0-next.56+d8f18cc386c",
8
+ "@theia/filesystem": "1.67.0-next.56+d8f18cc386c",
9
+ "@theia/monaco": "1.67.0-next.56+d8f18cc386c",
10
10
  "@theia/monaco-editor-core": "1.96.302",
11
- "@theia/outline-view": "1.67.0-next.13+c409d5d18",
11
+ "@theia/outline-view": "1.67.0-next.56+d8f18cc386c",
12
12
  "advanced-mark.js": "^2.6.0",
13
13
  "react-perfect-scrollbar": "^1.5.8",
14
14
  "tslib": "^2.6.2"
@@ -54,5 +54,5 @@
54
54
  "nyc": {
55
55
  "extends": "../../configs/nyc.json"
56
56
  },
57
- "gitHead": "c409d5d18d8c4f5a722f87b37ea9d6fd5af47ea8"
57
+ "gitHead": "d8f18cc386c45a736cd193d42eab02c8f64c6b10"
58
58
  }
@@ -131,13 +131,14 @@ export class NotebookActionsContribution implements CommandContribution, MenuCon
131
131
  commands.registerCommand(NotebookCommands.ADD_NEW_CELL_COMMAND, {
132
132
  execute: (notebookModel: NotebookModel, cellKind: CellKind = CellKind.Markup, index?: number | 'above' | 'below', focusContainer?: boolean) => {
133
133
  notebookModel = notebookModel ?? this.notebookEditorWidgetService.focusedEditor?.model;
134
+ const viewModel = this.notebookEditorWidgetService.focusedEditor?.viewModel;
134
135
 
135
136
  let insertIndex: number = 0;
136
137
  if (typeof index === 'number' && index >= 0) {
137
138
  insertIndex = index;
138
- } else if (notebookModel.selectedCell && typeof index === 'string') {
139
+ } else if (viewModel?.selectedCell && typeof index === 'string') {
139
140
  // if index is -1 insert below otherwise at the index of the selected cell which is above the selected.
140
- insertIndex = notebookModel.cells.indexOf(notebookModel.selectedCell) + (index === 'below' ? 1 : 0);
141
+ insertIndex = notebookModel.cells.indexOf(viewModel.selectedCell) + (index === 'below' ? 1 : 0);
141
142
  }
142
143
 
143
144
  let cellLanguage: string = 'markdown';
@@ -158,7 +159,7 @@ export class NotebookActionsContribution implements CommandContribution, MenuCon
158
159
  }]
159
160
  }], true);
160
161
  if (focusContainer) {
161
- notebookModel.selectedCell?.requestBlurEditor();
162
+ viewModel?.cellViewModels.get(viewModel.selectedCell?.handle ?? -1)?.requestBlurEditor();
162
163
  }
163
164
  }
164
165
  });
@@ -191,27 +192,28 @@ export class NotebookActionsContribution implements CommandContribution, MenuCon
191
192
  execute: (change: number | CellChangeDirection) => {
192
193
  const focusedEditor = this.notebookEditorWidgetService.focusedEditor;
193
194
  const model = focusedEditor?.model;
195
+ const viewModel = focusedEditor?.viewModel;
194
196
  if (model && typeof change === 'number') {
195
- model.setSelectedCell(model.cells[change]);
196
- } else if (model && model.selectedCell) {
197
- const currentIndex = model.cells.indexOf(model.selectedCell);
197
+ viewModel?.setSelectedCell(model.cells[change]);
198
+ } else if (model && viewModel?.selectedCell) {
199
+ const currentIndex = model.cells.indexOf(viewModel?.selectedCell);
198
200
  const shouldFocusEditor = this.contextKeyService.match('editorTextFocus');
199
201
 
200
202
  if (change === CellChangeDirection.Up && currentIndex > 0) {
201
- model.setSelectedCell(model.cells[currentIndex - 1]);
202
- if ((model.selectedCell?.cellKind === CellKind.Code
203
- || (model.selectedCell?.cellKind === CellKind.Markup && model.selectedCell?.editing)) && shouldFocusEditor) {
204
- model.selectedCell.requestFocusEditor('lastLine');
203
+ viewModel?.setSelectedCell(model.cells[currentIndex - 1]);
204
+ if ((viewModel?.selectedCell?.cellKind === CellKind.Code
205
+ || (viewModel?.selectedCell?.cellKind === CellKind.Markup && viewModel?.selectedCellViewModel?.editing)) && shouldFocusEditor) {
206
+ viewModel?.cellViewModels.get(viewModel.selectedCell.handle)?.requestFocusEditor('lastLine');
205
207
  }
206
208
  } else if (change === CellChangeDirection.Down && currentIndex < model.cells.length - 1) {
207
- model.setSelectedCell(model.cells[currentIndex + 1]);
208
- if ((model.selectedCell?.cellKind === CellKind.Code
209
- || (model.selectedCell?.cellKind === CellKind.Markup && model.selectedCell?.editing)) && shouldFocusEditor) {
210
- model.selectedCell.requestFocusEditor();
209
+ viewModel?.setSelectedCell(model.cells[currentIndex + 1]);
210
+ if ((viewModel?.selectedCell?.cellKind === CellKind.Code
211
+ || (viewModel?.selectedCell?.cellKind === CellKind.Markup && viewModel?.selectedCellViewModel?.editing)) && shouldFocusEditor) {
212
+ viewModel?.cellViewModels.get(viewModel.selectedCell.handle)?.requestFocusEditor();
211
213
  }
212
214
  }
213
215
 
214
- if (model.selectedCell.cellKind === CellKind.Markup) {
216
+ if (viewModel?.selectedCell.cellKind === CellKind.Markup) {
215
217
  // since were losing focus from the cell editor, we need to focus the notebook editor again
216
218
  focusedEditor?.node.focus();
217
219
  }
@@ -229,8 +231,8 @@ export class NotebookActionsContribution implements CommandContribution, MenuCon
229
231
  commands.registerCommand(NotebookCommands.CUT_SELECTED_CELL, this.editableCommandHandler(
230
232
  () => {
231
233
  const model = this.notebookEditorWidgetService.focusedEditor?.model;
232
- const selectedCell = model?.selectedCell;
233
- if (selectedCell) {
234
+ const selectedCell = this.notebookEditorWidgetService.focusedEditor?.viewModel?.selectedCell;
235
+ if (selectedCell && model) {
234
236
  model.applyEdits([{ editType: CellEditType.Replace, index: model.cells.indexOf(selectedCell), count: 1, cells: [] }], true);
235
237
  this.notebookClipboardService.copyCell(selectedCell);
236
238
  }
@@ -238,8 +240,8 @@ export class NotebookActionsContribution implements CommandContribution, MenuCon
238
240
 
239
241
  commands.registerCommand(NotebookCommands.COPY_SELECTED_CELL, {
240
242
  execute: () => {
241
- const model = this.notebookEditorWidgetService.focusedEditor?.model;
242
- const selectedCell = model?.selectedCell;
243
+ const viewModel = this.notebookEditorWidgetService.focusedEditor?.viewModel;
244
+ const selectedCell = viewModel?.selectedCell;
243
245
  if (selectedCell) {
244
246
  this.notebookClipboardService.copyCell(selectedCell);
245
247
  }
@@ -253,7 +255,8 @@ export class NotebookActionsContribution implements CommandContribution, MenuCon
253
255
  const copiedCell = this.notebookClipboardService.getCell();
254
256
  if (copiedCell) {
255
257
  const model = this.notebookEditorWidgetService.focusedEditor?.model;
256
- const insertIndex = model?.selectedCell ? model.cells.indexOf(model.selectedCell) + (position === 'above' ? 0 : 1) : 0;
258
+ const viewModel = this.notebookEditorWidgetService.focusedEditor?.viewModel;
259
+ const insertIndex = viewModel?.selectedCell && model ? model.cells.indexOf(viewModel?.selectedCell) + (position === 'above' ? 0 : 1) : 0;
257
260
  model?.applyEdits([{ editType: CellEditType.Replace, index: insertIndex, count: 0, cells: [copiedCell] }], true);
258
261
  }
259
262
  }
@@ -267,8 +270,8 @@ export class NotebookActionsContribution implements CommandContribution, MenuCon
267
270
 
268
271
  commands.registerCommand(NotebookCommands.CENTER_ACTIVE_CELL, {
269
272
  execute: (editor?: NotebookEditorWidget) => {
270
- const model = editor ? editor.model : this.notebookEditorWidgetService.focusedEditor?.model;
271
- model?.selectedCell?.requestCenterEditor();
273
+ const viewModel = editor ? editor.viewModel : this.notebookEditorWidgetService.focusedEditor?.viewModel;
274
+ viewModel?.selectedCell?.requestCenterEditor();
272
275
  }
273
276
  });
274
277
 
@@ -284,8 +284,16 @@ export class NotebookCellActionContribution implements MenuContribution, Command
284
284
  }
285
285
 
286
286
  registerCommands(commands: CommandRegistry): void {
287
- commands.registerCommand(NotebookCellCommands.EDIT_COMMAND, this.editableCellCommandHandler((_, cell) => cell.requestFocusEditor()));
288
- commands.registerCommand(NotebookCellCommands.STOP_EDIT_COMMAND, { execute: (_, cell: NotebookCellModel) => (cell ?? this.getSelectedCell()).requestBlurEditor() });
287
+ commands.registerCommand(NotebookCellCommands.EDIT_COMMAND, this.editableCellCommandHandler((_, cell) => {
288
+ const cellViewModel = this.notebookEditorWidgetService.focusedEditor?.viewModel.cellViewModels.get(cell.handle);
289
+ cellViewModel?.requestFocusEditor();
290
+ }));
291
+ commands.registerCommand(NotebookCellCommands.STOP_EDIT_COMMAND, {
292
+ execute: (_, cell: NotebookCellModel) => {
293
+ const cellViewModel = this.notebookEditorWidgetService.focusedEditor?.viewModel.cellViewModels.get(cell.handle);
294
+ cellViewModel?.requestBlurEditor();
295
+ }
296
+ });
289
297
  commands.registerCommand(NotebookCellCommands.DELETE_COMMAND,
290
298
  this.editableCellCommandHandler((notebookModel, cell) => {
291
299
  notebookModel.applyEdits([{
@@ -346,6 +354,8 @@ export class NotebookCellActionContribution implements MenuContribution, Command
346
354
 
347
355
  commands.registerCommand(NotebookCellCommands.EXECUTE_SINGLE_CELL_AND_FOCUS_NEXT_COMMAND, this.editableCellCommandHandler(
348
356
  (notebookModel, cell) => {
357
+ const viewModel = this.notebookEditorWidgetService.focusedEditor?.viewModel;
358
+
349
359
  if (cell.cellKind === CellKind.Code) {
350
360
  commands.executeCommand(NotebookCellCommands.EXECUTE_SINGLE_CELL_COMMAND.id, notebookModel, cell);
351
361
  } else {
@@ -353,7 +363,7 @@ export class NotebookCellActionContribution implements MenuContribution, Command
353
363
  }
354
364
  const index = notebookModel.cells.indexOf(cell);
355
365
  if (index < notebookModel.cells.length - 1) {
356
- notebookModel.setSelectedCell(notebookModel.cells[index + 1]);
366
+ viewModel?.setSelectedCell(notebookModel.cells[index + 1]);
357
367
  } else if (cell.cellKind === CellKind.Code) {
358
368
  commands.executeCommand(NotebookCellCommands.INSERT_NEW_CELL_BELOW_COMMAND.id);
359
369
  } else {
@@ -375,7 +385,8 @@ export class NotebookCellActionContribution implements MenuContribution, Command
375
385
  }
376
386
 
377
387
  const index = notebookModel.cells.indexOf(cell);
378
- notebookModel.setSelectedCell(notebookModel.cells[index + 1]);
388
+ const viewModel = this.notebookEditorWidgetService.focusedEditor?.viewModel;
389
+ viewModel?.setSelectedCell(notebookModel.cells[index + 1]);
379
390
  })
380
391
  );
381
392
 
@@ -436,7 +447,7 @@ export class NotebookCellActionContribution implements MenuContribution, Command
436
447
 
437
448
  commands.registerCommand(NotebookCellCommands.TOGGLE_CELL_OUTPUT, {
438
449
  execute: () => {
439
- const selectedCell = this.notebookEditorWidgetService.focusedEditor?.model?.selectedCell;
450
+ const selectedCell = this.notebookEditorWidgetService.focusedEditor?.viewModel?.selectedCell;
440
451
  if (selectedCell) {
441
452
  selectedCell.outputVisible = !selectedCell.outputVisible;
442
453
  }
@@ -444,9 +455,9 @@ export class NotebookCellActionContribution implements MenuContribution, Command
444
455
  });
445
456
 
446
457
  commands.registerCommand(NotebookCellCommands.CHANGE_CELL_LANGUAGE, {
447
- isVisible: () => !!this.notebookEditorWidgetService.focusedEditor?.model?.selectedCell,
458
+ isVisible: () => !!this.notebookEditorWidgetService.focusedEditor?.viewModel?.selectedCell,
448
459
  execute: async (notebook?: NotebookModel, cell?: NotebookCellModel) => {
449
- const selectedCell = cell ?? this.notebookEditorWidgetService.focusedEditor?.model?.selectedCell;
460
+ const selectedCell = cell ?? this.notebookEditorWidgetService.focusedEditor?.viewModel?.selectedCell;
450
461
  const activeNotebook = notebook ?? this.notebookEditorWidgetService.focusedEditor?.model;
451
462
  if (!selectedCell || !activeNotebook) {
452
463
  return;
@@ -475,7 +486,7 @@ export class NotebookCellActionContribution implements MenuContribution, Command
475
486
 
476
487
  commands.registerCommand(NotebookCellCommands.TOGGLE_LINE_NUMBERS, {
477
488
  execute: () => {
478
- const selectedCell = this.notebookEditorWidgetService.focusedEditor?.model?.selectedCell;
489
+ const selectedCell = this.notebookEditorWidgetService.focusedEditor?.viewModel?.selectedCell;
479
490
  if (selectedCell) {
480
491
  const currentLineNumber = selectedCell.editorOptions?.lineNumbers;
481
492
  selectedCell.editorOptions = { ...selectedCell.editorOptions, lineNumbers: !currentLineNumber || currentLineNumber === 'off' ? 'on' : 'off' };
@@ -498,7 +509,7 @@ export class NotebookCellActionContribution implements MenuContribution, Command
498
509
  }
499
510
 
500
511
  protected getSelectedCell(): NotebookCellModel | undefined {
501
- return this.notebookEditorWidgetService.focusedEditor?.model?.selectedCell;
512
+ return this.notebookEditorWidgetService.focusedEditor?.viewModel?.selectedCell;
502
513
  }
503
514
 
504
515
  registerKeybindings(keybindings: KeybindingRegistry): void {
@@ -21,6 +21,7 @@ import { NotebookService } from '../service/notebook-service';
21
21
  import { NotebookCellOutlineNode } from './notebook-outline-contribution';
22
22
  import type Token = require('markdown-it/lib/token');
23
23
  import markdownit = require('@theia/core/shared/markdown-it');
24
+ import * as markdownitemoji from '@theia/core/shared/markdown-it-emoji';
24
25
  import { NotebookCellModel } from '../view-model/notebook-cell-model';
25
26
  import { URI } from '@theia/core';
26
27
 
@@ -33,7 +34,7 @@ export class NotebookLabelProviderContribution implements LabelProviderContribut
33
34
  @inject(LabelProvider)
34
35
  protected readonly labelProvider: LabelProvider;
35
36
 
36
- protected markdownIt = markdownit();
37
+ protected markdownIt = markdownit().use(markdownitemoji.full);
37
38
 
38
39
  canHandle(element: object): number {
39
40
  if (NotebookCellOutlineNode.is(element)) {
@@ -24,6 +24,7 @@ import { NotebookEditorWidget } from '../notebook-editor-widget';
24
24
  import { DisposableCollection, isObject, URI } from '@theia/core';
25
25
  import { CellKind, CellUri } from '../../common';
26
26
  import { NotebookService } from '../service/notebook-service';
27
+ import { NotebookViewModel } from '../view-model/notebook-view-model';
27
28
  export interface NotebookCellOutlineNode extends OutlineSymbolInformationNode {
28
29
  uri: URI;
29
30
  }
@@ -77,36 +78,37 @@ export class NotebookOutlineContribution implements FrontendApplicationContribut
77
78
  }));
78
79
  if (editor.model) {
79
80
  this.editorModelListeners.dispose();
80
- this.editorModelListeners.push(editor.model.onDidChangeSelectedCell(() => {
81
+ this.editorModelListeners.push(editor.viewModel.onDidChangeSelectedCell(() => {
81
82
  if (editor === this.currentEditor) {
82
83
  this.updateOutline(editor);
83
84
  }
84
85
  }));
85
- const roots = editor && editor.model && await this.createRoots(editor.model);
86
+ const roots = editor && editor.model && await this.createRoots(editor.model, editor.viewModel);
86
87
  this.outlineViewService.publish(roots || []);
87
88
  }
88
89
  }
89
90
  }
90
91
 
91
- protected async createRoots(model: NotebookModel): Promise<OutlineSymbolInformationNode[] | undefined> {
92
+ protected async createRoots(model: NotebookModel, viewModel: NotebookViewModel): Promise<OutlineSymbolInformationNode[] | undefined> {
92
93
  return model.cells.map(cell => ({
93
94
  id: cell.uri.toString(),
94
95
  iconClass: cell.cellKind === CellKind.Markup ? codicon('markdown') : codicon('code'),
95
96
  parent: undefined,
96
97
  children: [],
97
- selected: model.selectedCell === cell,
98
+ selected: viewModel.selectedCell === cell,
98
99
  expanded: false,
99
100
  uri: cell.uri,
100
101
  } as NotebookCellOutlineNode));
101
102
  }
102
103
 
103
- selectCell(node: object): void {
104
+ protected selectCell(node: object): void {
104
105
  if (NotebookCellOutlineNode.is(node)) {
105
106
  const parsed = CellUri.parse(node.uri);
106
107
  const model = parsed && this.notebookService.getNotebookEditorModel(parsed.notebook);
108
+ const viewModel = this.currentEditor?.viewModel;
107
109
  const cell = model?.cells.find(c => c.handle === parsed?.handle);
108
110
  if (model && cell) {
109
- model.setSelectedCell(cell);
111
+ viewModel?.setSelectedCell(cell);
110
112
  }
111
113
  }
112
114
  }
@@ -33,10 +33,8 @@ export class NotebookStatusBarContribution implements WidgetStatusBarContributio
33
33
  }
34
34
 
35
35
  activate(statusBar: StatusBar, widget: NotebookEditorWidget): void {
36
- widget.ready.then(model => {
37
- this.onDeactivate = model.onDidChangeSelectedCell(() => {
38
- this.updateStatusbar(statusBar, widget);
39
- });
36
+ this.onDeactivate = widget.viewModel.onDidChangeSelectedCell(() => {
37
+ this.updateStatusbar(statusBar, widget);
40
38
  });
41
39
  this.updateStatusbar(statusBar, widget);
42
40
  }
@@ -48,12 +46,12 @@ export class NotebookStatusBarContribution implements WidgetStatusBarContributio
48
46
 
49
47
  protected async updateStatusbar(statusBar: StatusBar, editor?: NotebookEditorWidget): Promise<void> {
50
48
  const model = await editor?.ready;
51
- if (!model || model.cells.length === 0 || !model.selectedCell) {
49
+ if (!model || model.cells.length === 0 || !editor?.viewModel.selectedCell) {
52
50
  statusBar.removeElement(NOTEBOOK_CELL_SELECTION_STATUS_BAR_ID);
53
51
  return;
54
52
  }
55
53
 
56
- const selectedCellIndex = model.cells.indexOf(model.selectedCell) + 1;
54
+ const selectedCellIndex = model.cells.indexOf(editor.viewModel.selectedCell) + 1;
57
55
 
58
56
  statusBar.setElement(NOTEBOOK_CELL_SELECTION_STATUS_BAR_ID, {
59
57
  text: nls.localizeByDefault('Cell {0} of {1}', selectedCellIndex, model.cells.length),
@@ -26,3 +26,4 @@ export * from './service/notebook-renderer-messaging-service';
26
26
  export * from './service/notebook-cell-editor-service';
27
27
  export * from './renderers/cell-output-webview';
28
28
  export * from './notebook-types';
29
+ export * from './notebook-editor-split-contribution';
@@ -44,9 +44,9 @@ export class NotebookCellOpenHandler implements OpenHandler {
44
44
 
45
45
  const executionCount = parseInt(executionCountParam);
46
46
 
47
- this.notebookEditorWidgetService.currentEditor?.model?.cells
48
- .find(c => c.metadata.execution_count === executionCount)
49
- ?.requestFocusEditor(parseInt(lineParam));
47
+ const cell = this.notebookEditorWidgetService.currentEditor?.model?.cells
48
+ .find(c => c.metadata.execution_count === executionCount);
49
+ this.notebookEditorWidgetService.currentEditor?.viewModel.cellViewModels.get(cell?.handle ?? -1)?.requestFocusEditor();
50
50
  }
51
51
 
52
52
  }
@@ -0,0 +1,51 @@
1
+ // *****************************************************************************
2
+ // Copyright (C) 2025 TypeFox and others.
3
+ //
4
+ // This program and the accompanying materials are made available under the
5
+ // terms of the Eclipse Public License v. 2.0 which is available at
6
+ // http://www.eclipse.org/legal/epl-2.0.
7
+ //
8
+ // This Source Code may also be made available under the following Secondary
9
+ // Licenses when the conditions for such availability set forth in the Eclipse
10
+ // Public License v. 2.0 are satisfied: GNU General Public License, version 2
11
+ // with the GNU Classpath Exception which is available at
12
+ // https://www.gnu.org/software/classpath/license.html.
13
+ //
14
+ // SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-only WITH Classpath-exception-2.0
15
+ // *****************************************************************************
16
+
17
+ import { inject, injectable } from '@theia/core/shared/inversify';
18
+ import { Widget, DockLayout } from '@theia/core/lib/browser';
19
+ import { SplitEditorContribution } from '@theia/editor/lib/browser/split-editor-contribution';
20
+ import { NotebookEditorWidget } from './notebook-editor-widget';
21
+ import { NotebookOpenHandler } from './notebook-open-handler';
22
+
23
+ /**
24
+ * Implementation of SplitEditorContribution for notebook editors (NotebookEditorWidget).
25
+ * Delegates to NotebookOpenHandler.openToSide which handles counter management for splits.
26
+ */
27
+ @injectable()
28
+ export class NotebookEditorSplitContribution implements SplitEditorContribution<NotebookEditorWidget> {
29
+
30
+ @inject(NotebookOpenHandler)
31
+ protected readonly notebookOpenHandler: NotebookOpenHandler;
32
+
33
+ canHandle(widget: Widget): number {
34
+ return widget instanceof NotebookEditorWidget ? 100 : 0;
35
+ }
36
+
37
+ async split(widget: NotebookEditorWidget, splitMode: DockLayout.InsertMode): Promise<NotebookEditorWidget | undefined> {
38
+ const uri = widget.getResourceUri();
39
+ if (!uri) {
40
+ return undefined;
41
+ }
42
+
43
+ const newNotebook = await this.notebookOpenHandler.openToSide(uri, {
44
+ notebookType: widget.notebookType,
45
+ widgetOptions: { mode: splitMode, ref: widget }
46
+ });
47
+
48
+ return newNotebook;
49
+ }
50
+ }
51
+
@@ -17,7 +17,7 @@
17
17
  import { nls, URI } from '@theia/core';
18
18
  import { WidgetFactory, NavigatableWidgetOptions, LabelProvider } from '@theia/core/lib/browser';
19
19
  import { inject, injectable } from '@theia/core/shared/inversify';
20
- import { NotebookEditorWidget, NotebookEditorWidgetContainerFactory, NotebookEditorProps } from './notebook-editor-widget';
20
+ import { NotebookEditorWidget, NotebookEditorWidgetContainerFactory, NotebookEditorProps, NOTEBOOK_EDITOR_ID_PREFIX } from './notebook-editor-widget';
21
21
  import { NotebookService } from './service/notebook-service';
22
22
  import { NotebookModelResolverService } from './service/notebook-model-resolver-service';
23
23
  import { Deferred } from '@theia/core/lib/common/promise-util';
@@ -29,6 +29,13 @@ export interface NotebookEditorWidgetOptions extends NavigatableWidgetOptions {
29
29
 
30
30
  @injectable()
31
31
  export class NotebookEditorWidgetFactory implements WidgetFactory {
32
+
33
+ static createID(uri: URI, counter?: number): string {
34
+ return NOTEBOOK_EDITOR_ID_PREFIX
35
+ + uri.toString()
36
+ + (counter !== undefined ? `:${counter}` : '');
37
+ }
38
+
32
39
  readonly id: string = NotebookEditorWidget.ID;
33
40
 
34
41
  @inject(NotebookService)
@@ -53,6 +60,9 @@ export class NotebookEditorWidgetFactory implements WidgetFactory {
53
60
 
54
61
  const editor = await this.createEditor(uri, options.notebookType);
55
62
 
63
+ // Set the widget ID with counter to support multiple instances
64
+ editor.id = NotebookEditorWidgetFactory.createID(uri, options.counter);
65
+
56
66
  this.setLabels(editor, uri);
57
67
  const labelListener = this.labelProvider.onDidChange(event => {
58
68
  if (event.affects(uri)) {
@@ -37,6 +37,7 @@ import { NotebookFindWidget } from './view/notebook-find-widget';
37
37
  import debounce = require('@theia/core/shared/lodash.debounce');
38
38
  import { CellOutputWebview, CellOutputWebviewFactory } from './renderers/cell-output-webview';
39
39
  import { NotebookCellOutputModel } from './view-model/notebook-cell-output-model';
40
+ import { NotebookViewModel } from './view-model/notebook-view-model';
40
41
  const PerfectScrollbar = require('react-perfect-scrollbar');
41
42
 
42
43
  export const NotebookEditorWidgetContainerFactory = Symbol('NotebookEditorWidgetContainerFactory');
@@ -49,6 +50,8 @@ export function createNotebookEditorWidgetContainer(parent: interfaces.Container
49
50
  const cellOutputWebviewFactory: CellOutputWebviewFactory = parent.get(CellOutputWebviewFactory);
50
51
  child.bind(CellOutputWebview).toConstantValue(cellOutputWebviewFactory());
51
52
 
53
+ child.bind(NotebookViewModel).toSelf().inSingletonScope();
54
+
52
55
  child.bind(NotebookContextManager).toSelf().inSingletonScope();
53
56
  child.bind(NotebookMainToolbarRenderer).toSelf().inSingletonScope();
54
57
  child.bind(NotebookCellToolbarFactory).toSelf().inSingletonScope();
@@ -113,6 +116,9 @@ export class NotebookEditorWidget extends ReactWidget implements Navigatable, Sa
113
116
  @inject(CellOutputWebview)
114
117
  protected readonly cellOutputWebview: CellOutputWebview;
115
118
 
119
+ @inject(NotebookViewModel)
120
+ protected readonly _viewModel: NotebookViewModel;
121
+
116
122
  protected readonly onDidChangeModelEmitter = new Emitter<void>();
117
123
  readonly onDidChangeModel = this.onDidChangeModelEmitter.event;
118
124
 
@@ -161,9 +167,16 @@ export class NotebookEditorWidget extends ReactWidget implements Navigatable, Sa
161
167
  return this._model;
162
168
  }
163
169
 
170
+ get viewModel(): NotebookViewModel {
171
+ return this._viewModel;
172
+ }
173
+
164
174
  @postConstruct()
165
175
  protected init(): void {
166
- this.id = NOTEBOOK_EDITOR_ID_PREFIX + this.props.uri.toString();
176
+ // ID is set by NotebookEditorWidgetFactory to include counter for multiple instances
177
+ if (!this.id) {
178
+ this.id = NOTEBOOK_EDITOR_ID_PREFIX + this.props.uri.toString();
179
+ }
167
180
 
168
181
  this.scrollOptions = {
169
182
  suppressScrollY: true
@@ -181,7 +194,7 @@ export class NotebookEditorWidget extends ReactWidget implements Navigatable, Sa
181
194
  this.ready.then(model => {
182
195
  if (model.cells.length === 1 && model.cells[0].source === '') {
183
196
  this.commandRegistry.executeCommand(NotebookCellCommands.EDIT_COMMAND.id, model, model.cells[0]);
184
- model.setSelectedCell(model.cells[0]);
197
+ this.viewModel.setSelectedCell(model.cells[0]);
185
198
  }
186
199
  model.onDidChangeContent(changeEvents => {
187
200
  const cellEvent = changeEvents.filter(event => event.kind === NotebookCellsChangeType.Move || event.kind === NotebookCellsChangeType.ModelChange);
@@ -198,6 +211,7 @@ export class NotebookEditorWidget extends ReactWidget implements Navigatable, Sa
198
211
 
199
212
  protected async waitForData(): Promise<NotebookModel> {
200
213
  this._model = await this.props.notebookData;
214
+ this.viewModel.initDataModel(this._model);
201
215
  this.cellOutputWebview.init(this._model, this);
202
216
  this.saveable.delegate = this._model;
203
217
  this.toDispose.push(this._model);
@@ -225,7 +239,7 @@ export class NotebookEditorWidget extends ReactWidget implements Navigatable, Sa
225
239
  }
226
240
  // Ensure that the model is loaded before adding the editor
227
241
  this.notebookEditorService.addNotebookEditor(this);
228
- this._model.selectedCell = this._model.cells[0];
242
+ this.viewModel.selectedCell = this._model.cells[0];
229
243
  this.update();
230
244
  this.notebookContextManager.init(this);
231
245
  return this._model;
@@ -286,6 +300,7 @@ export class NotebookEditorWidget extends ReactWidget implements Navigatable, Sa
286
300
  {this.cellOutputWebview.render()}
287
301
  <NotebookCellListView renderers={this.renderers}
288
302
  notebookModel={this._model}
303
+ notebookViewModel={this.viewModel}
289
304
  notebookContext={this.notebookContextManager}
290
305
  toolbarRenderer={this.cellToolbarFactory}
291
306
  commandRegistry={this.commandRegistry}
@@ -55,11 +55,16 @@ import { NotebookCellStatusBarService } from './service/notebook-cell-status-bar
55
55
  import { MonacoEditorModelFilter } from '@theia/monaco/lib/browser/monaco-text-model-service';
56
56
  import { ActiveMonacoEditorContribution } from '@theia/monaco/lib/browser/monaco-editor-service';
57
57
  import { NotebookCellOpenHandler } from './notebook-cell-open-handler';
58
+ import { SplitEditorContribution } from '@theia/editor/lib/browser/split-editor-contribution';
59
+ import { NotebookEditorSplitContribution } from './notebook-editor-split-contribution';
58
60
 
59
61
  export default new ContainerModule(bind => {
60
62
  bind(NotebookColorContribution).toSelf().inSingletonScope();
61
63
  bind(ColorContribution).toService(NotebookColorContribution);
62
64
 
65
+ bind(NotebookEditorSplitContribution).toSelf().inSingletonScope();
66
+ bind(SplitEditorContribution).toService(NotebookEditorSplitContribution);
67
+
63
68
  bind(NotebookOpenHandler).toSelf().inSingletonScope();
64
69
  bind(OpenHandler).toService(NotebookOpenHandler);
65
70
  bind(NotebookCellOpenHandler).toSelf().inSingletonScope();
@@ -24,6 +24,7 @@ import { NotebookEditorWidgetOptions } from './notebook-editor-widget-factory';
24
24
 
25
25
  export interface NotebookWidgetOpenerOptions extends WidgetOpenerOptions {
26
26
  notebookType?: string;
27
+ counter?: number;
27
28
  }
28
29
 
29
30
  @injectable()
@@ -91,24 +92,31 @@ export class NotebookOpenHandler extends NavigatableWidgetOpenHandler<NotebookEd
91
92
 
92
93
  protected override createWidgetOptions(uri: URI, options?: NotebookWidgetOpenerOptions): NotebookEditorWidgetOptions {
93
94
  const widgetOptions = super.createWidgetOptions(uri, options);
94
- if (options?.notebookType) {
95
- return {
96
- notebookType: options.notebookType,
97
- ...widgetOptions
98
- };
99
- }
100
- const defaultHandler = getDefaultHandler(uri, this.preferenceService);
101
- const notebookType = this.notebookTypes.find(type => type.type === defaultHandler)
102
- || this.findHighestPriorityType(uri);
95
+ const notebookType = options?.notebookType
96
+ ? options.notebookType
97
+ : (this.notebookTypes.find(type => type.type === getDefaultHandler(uri, this.preferenceService))
98
+ || this.findHighestPriorityType(uri))?.type;
99
+
103
100
  if (!notebookType) {
104
101
  throw new Error('No notebook types registered for uri: ' + uri.toString());
105
102
  }
106
103
  return {
107
- notebookType: notebookType.type,
108
- ...widgetOptions
104
+ notebookType,
105
+ ...widgetOptions,
106
+ counter: options?.counter ?? widgetOptions.counter
109
107
  };
110
108
  }
111
109
 
110
+ /**
111
+ * Opens a notebook to the side of the current notebook.
112
+ * Uses timestamp to ensure unique widget IDs for multiple instances without needing to track state.
113
+ */
114
+ openToSide(uri: URI, options?: NotebookWidgetOpenerOptions): Promise<NotebookEditorWidget> {
115
+ const counter = Date.now();
116
+ const splitOptions: NotebookWidgetOpenerOptions = { widgetOptions: { mode: 'split-right' }, ...options, counter };
117
+ return this.open(uri, splitOptions);
118
+ }
119
+
112
120
  protected matches(selectors: readonly NotebookFileSelector[], resource: URI): boolean {
113
121
  return selectors.some(selector => this.selectorMatches(selector, resource));
114
122
  }
@@ -105,6 +105,7 @@ export type SelectionState = SelectionHandleState | SelectionIndexState;
105
105
  export interface NotebookModelWillAddRemoveEvent {
106
106
  readonly newCellIds?: number[];
107
107
  readonly rawEvent: NotebookCellsModelChangedEvent<CellData>;
108
+ readonly externalEvent?: boolean;
108
109
  };
109
110
 
110
111
  export interface CellOutputEdit {