@nocturnium/svelte-ide 1.0.0-rc.1

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 (330) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +251 -0
  3. package/dist/components/agents/AgentActivityPanel.svelte +565 -0
  4. package/dist/components/agents/AgentActivityPanel.svelte.d.ts +24 -0
  5. package/dist/components/agents/AgentAvatar.svelte +417 -0
  6. package/dist/components/agents/AgentAvatar.svelte.d.ts +23 -0
  7. package/dist/components/agents/AgentCursor.svelte +224 -0
  8. package/dist/components/agents/AgentCursor.svelte.d.ts +35 -0
  9. package/dist/components/agents/AgentPresenceBar.svelte +261 -0
  10. package/dist/components/agents/AgentPresenceBar.svelte.d.ts +20 -0
  11. package/dist/components/agents/index.d.ts +4 -0
  12. package/dist/components/agents/index.js +5 -0
  13. package/dist/components/ai/AIConversationList.svelte +524 -0
  14. package/dist/components/ai/AIConversationList.svelte.d.ts +17 -0
  15. package/dist/components/ai/AIEditPreview.svelte +132 -0
  16. package/dist/components/ai/AIEditPreview.svelte.d.ts +8 -0
  17. package/dist/components/ai/AIInlineEdit.svelte +155 -0
  18. package/dist/components/ai/AIInlineEdit.svelte.d.ts +10 -0
  19. package/dist/components/ai/AIMessage.svelte +239 -0
  20. package/dist/components/ai/AIMessage.svelte.d.ts +13 -0
  21. package/dist/components/ai/AIMessageActions.svelte +176 -0
  22. package/dist/components/ai/AIMessageActions.svelte.d.ts +12 -0
  23. package/dist/components/ai/AIMessageContent.svelte +355 -0
  24. package/dist/components/ai/AIMessageContent.svelte.d.ts +7 -0
  25. package/dist/components/ai/AIPanel.svelte +561 -0
  26. package/dist/components/ai/AIPanel.svelte.d.ts +7 -0
  27. package/dist/components/ai/AISuggestionWidget.svelte +132 -0
  28. package/dist/components/ai/AISuggestionWidget.svelte.d.ts +10 -0
  29. package/dist/components/ai/AIToolCallDisplay.svelte +317 -0
  30. package/dist/components/ai/AIToolCallDisplay.svelte.d.ts +12 -0
  31. package/dist/components/ai/index.d.ts +9 -0
  32. package/dist/components/ai/index.js +10 -0
  33. package/dist/components/core/Avatar.svelte +110 -0
  34. package/dist/components/core/Avatar.svelte.d.ts +12 -0
  35. package/dist/components/core/Badge.svelte +98 -0
  36. package/dist/components/core/Badge.svelte.d.ts +11 -0
  37. package/dist/components/core/Button.svelte +175 -0
  38. package/dist/components/core/Button.svelte.d.ts +18 -0
  39. package/dist/components/core/ConnectionStatus.svelte +294 -0
  40. package/dist/components/core/ConnectionStatus.svelte.d.ts +20 -0
  41. package/dist/components/core/ContextMenu.svelte +176 -0
  42. package/dist/components/core/ContextMenu.svelte.d.ts +19 -0
  43. package/dist/components/core/ErrorBoundary.svelte +277 -0
  44. package/dist/components/core/ErrorBoundary.svelte.d.ts +23 -0
  45. package/dist/components/core/Icon.svelte +107 -0
  46. package/dist/components/core/Icon.svelte.d.ts +8 -0
  47. package/dist/components/core/Input.svelte +138 -0
  48. package/dist/components/core/Input.svelte.d.ts +20 -0
  49. package/dist/components/core/Kbd.svelte +34 -0
  50. package/dist/components/core/Kbd.svelte.d.ts +7 -0
  51. package/dist/components/core/ResizeHandle.svelte +200 -0
  52. package/dist/components/core/ResizeHandle.svelte.d.ts +23 -0
  53. package/dist/components/core/Spinner.svelte +35 -0
  54. package/dist/components/core/Spinner.svelte.d.ts +7 -0
  55. package/dist/components/core/Textarea.svelte +112 -0
  56. package/dist/components/core/Textarea.svelte.d.ts +18 -0
  57. package/dist/components/core/Tooltip.svelte +103 -0
  58. package/dist/components/core/Tooltip.svelte.d.ts +11 -0
  59. package/dist/components/core/index.d.ts +13 -0
  60. package/dist/components/core/index.js +14 -0
  61. package/dist/components/editor/AIFocusLayer.svelte +430 -0
  62. package/dist/components/editor/AIFocusLayer.svelte.d.ts +32 -0
  63. package/dist/components/editor/Breadcrumbs.svelte +435 -0
  64. package/dist/components/editor/Breadcrumbs.svelte.d.ts +33 -0
  65. package/dist/components/editor/BreakpointLayer.svelte +642 -0
  66. package/dist/components/editor/BreakpointLayer.svelte.d.ts +20 -0
  67. package/dist/components/editor/CognitiveLoadMeter.svelte +324 -0
  68. package/dist/components/editor/CognitiveLoadMeter.svelte.d.ts +18 -0
  69. package/dist/components/editor/CollaborativeEditor.svelte +218 -0
  70. package/dist/components/editor/CollaborativeEditor.svelte.d.ts +32 -0
  71. package/dist/components/editor/CommandPalette.svelte +434 -0
  72. package/dist/components/editor/CommandPalette.svelte.d.ts +11 -0
  73. package/dist/components/editor/ComplexityLayer.svelte +293 -0
  74. package/dist/components/editor/ComplexityLayer.svelte.d.ts +23 -0
  75. package/dist/components/editor/ConflictZoneLayer.svelte +441 -0
  76. package/dist/components/editor/ConflictZoneLayer.svelte.d.ts +25 -0
  77. package/dist/components/editor/ContextLens.svelte +262 -0
  78. package/dist/components/editor/ContextLens.svelte.d.ts +27 -0
  79. package/dist/components/editor/CustomEditor.svelte +1242 -0
  80. package/dist/components/editor/CustomEditor.svelte.d.ts +37 -0
  81. package/dist/components/editor/DebugConsole.svelte +646 -0
  82. package/dist/components/editor/DebugConsole.svelte.d.ts +41 -0
  83. package/dist/components/editor/EchoCursorLayer.svelte +363 -0
  84. package/dist/components/editor/EchoCursorLayer.svelte.d.ts +24 -0
  85. package/dist/components/editor/Editor.svelte +61 -0
  86. package/dist/components/editor/Editor.svelte.d.ts +22 -0
  87. package/dist/components/editor/EditorGutter.svelte +119 -0
  88. package/dist/components/editor/EditorGutter.svelte.d.ts +19 -0
  89. package/dist/components/editor/EditorLines.svelte +182 -0
  90. package/dist/components/editor/EditorLines.svelte.d.ts +43 -0
  91. package/dist/components/editor/EditorPane.svelte +134 -0
  92. package/dist/components/editor/EditorPane.svelte.d.ts +9 -0
  93. package/dist/components/editor/EditorSelections.svelte +186 -0
  94. package/dist/components/editor/EditorSelections.svelte.d.ts +25 -0
  95. package/dist/components/editor/EditorTabs.svelte +170 -0
  96. package/dist/components/editor/EditorTabs.svelte.d.ts +12 -0
  97. package/dist/components/editor/FileExplorer.svelte +811 -0
  98. package/dist/components/editor/FileExplorer.svelte.d.ts +67 -0
  99. package/dist/components/editor/FileIcon.svelte +110 -0
  100. package/dist/components/editor/FileIcon.svelte.d.ts +10 -0
  101. package/dist/components/editor/FindReplace.svelte +448 -0
  102. package/dist/components/editor/FindReplace.svelte.d.ts +40 -0
  103. package/dist/components/editor/GhostBracketLayer.svelte +391 -0
  104. package/dist/components/editor/GhostBracketLayer.svelte.d.ts +24 -0
  105. package/dist/components/editor/GitBlameLayer.svelte +436 -0
  106. package/dist/components/editor/GitBlameLayer.svelte.d.ts +18 -0
  107. package/dist/components/editor/InlineDiagnosticsLayer.svelte +540 -0
  108. package/dist/components/editor/InlineDiagnosticsLayer.svelte.d.ts +35 -0
  109. package/dist/components/editor/InlineDiffLayer.svelte +337 -0
  110. package/dist/components/editor/InlineDiffLayer.svelte.d.ts +31 -0
  111. package/dist/components/editor/MinimalEditor.svelte +75 -0
  112. package/dist/components/editor/MinimalEditor.svelte.d.ts +6 -0
  113. package/dist/components/editor/MinimalEditor2.svelte +84 -0
  114. package/dist/components/editor/MinimalEditor2.svelte.d.ts +6 -0
  115. package/dist/components/editor/Minimap.svelte +327 -0
  116. package/dist/components/editor/Minimap.svelte.d.ts +34 -0
  117. package/dist/components/editor/PluginPreviewSandbox.svelte +793 -0
  118. package/dist/components/editor/PluginPreviewSandbox.svelte.d.ts +49 -0
  119. package/dist/components/editor/ProblemsPanel.svelte +628 -0
  120. package/dist/components/editor/ProblemsPanel.svelte.d.ts +25 -0
  121. package/dist/components/editor/QuickActionsMenu.svelte +403 -0
  122. package/dist/components/editor/QuickActionsMenu.svelte.d.ts +18 -0
  123. package/dist/components/editor/SnippetPalette.svelte +530 -0
  124. package/dist/components/editor/SnippetPalette.svelte.d.ts +16 -0
  125. package/dist/components/editor/StructureMap.svelte +431 -0
  126. package/dist/components/editor/StructureMap.svelte.d.ts +37 -0
  127. package/dist/components/editor/SymbolOutline.svelte +722 -0
  128. package/dist/components/editor/SymbolOutline.svelte.d.ts +44 -0
  129. package/dist/components/editor/TimelineScrubber.svelte +470 -0
  130. package/dist/components/editor/TimelineScrubber.svelte.d.ts +40 -0
  131. package/dist/components/editor/TokenRenderer.svelte +69 -0
  132. package/dist/components/editor/TokenRenderer.svelte.d.ts +15 -0
  133. package/dist/components/editor/constants.d.ts +32 -0
  134. package/dist/components/editor/constants.js +36 -0
  135. package/dist/components/editor/core/ai-awareness.d.ts +176 -0
  136. package/dist/components/editor/core/ai-awareness.js +210 -0
  137. package/dist/components/editor/core/bracket-healer.d.ts +189 -0
  138. package/dist/components/editor/core/bracket-healer.js +406 -0
  139. package/dist/components/editor/core/breakpoints.d.ts +203 -0
  140. package/dist/components/editor/core/breakpoints.js +414 -0
  141. package/dist/components/editor/core/commands.d.ts +108 -0
  142. package/dist/components/editor/core/commands.js +246 -0
  143. package/dist/components/editor/core/complexity-analyzer.d.ts +123 -0
  144. package/dist/components/editor/core/complexity-analyzer.js +376 -0
  145. package/dist/components/editor/core/conflict-predictor.d.ts +135 -0
  146. package/dist/components/editor/core/conflict-predictor.js +316 -0
  147. package/dist/components/editor/core/crdt-binding.d.ts +118 -0
  148. package/dist/components/editor/core/crdt-binding.js +286 -0
  149. package/dist/components/editor/core/diagnostics.d.ts +210 -0
  150. package/dist/components/editor/core/diagnostics.js +335 -0
  151. package/dist/components/editor/core/echo-cursor.d.ts +201 -0
  152. package/dist/components/editor/core/echo-cursor.js +267 -0
  153. package/dist/components/editor/core/folding.d.ts +124 -0
  154. package/dist/components/editor/core/folding.js +672 -0
  155. package/dist/components/editor/core/ghost-pair.d.ts +122 -0
  156. package/dist/components/editor/core/ghost-pair.js +221 -0
  157. package/dist/components/editor/core/git-blame.d.ts +170 -0
  158. package/dist/components/editor/core/git-blame.js +324 -0
  159. package/dist/components/editor/core/index.d.ts +26 -0
  160. package/dist/components/editor/core/index.js +24 -0
  161. package/dist/components/editor/core/keybindings.d.ts +79 -0
  162. package/dist/components/editor/core/keybindings.js +357 -0
  163. package/dist/components/editor/core/multi-cursor.d.ts +196 -0
  164. package/dist/components/editor/core/multi-cursor.js +521 -0
  165. package/dist/components/editor/core/navigation.d.ts +107 -0
  166. package/dist/components/editor/core/navigation.js +408 -0
  167. package/dist/components/editor/core/quick-actions.d.ts +189 -0
  168. package/dist/components/editor/core/quick-actions.js +427 -0
  169. package/dist/components/editor/core/search.d.ts +88 -0
  170. package/dist/components/editor/core/search.js +192 -0
  171. package/dist/components/editor/core/semantic-analyzer.d.ts +77 -0
  172. package/dist/components/editor/core/semantic-analyzer.js +424 -0
  173. package/dist/components/editor/core/snippet-manager.d.ts +202 -0
  174. package/dist/components/editor/core/snippet-manager.js +565 -0
  175. package/dist/components/editor/core/state.d.ts +367 -0
  176. package/dist/components/editor/core/state.js +900 -0
  177. package/dist/components/editor/core/timeline.d.ts +204 -0
  178. package/dist/components/editor/core/timeline.js +349 -0
  179. package/dist/components/editor/editor-find.d.ts +56 -0
  180. package/dist/components/editor/editor-find.js +148 -0
  181. package/dist/components/editor/editor-input.d.ts +77 -0
  182. package/dist/components/editor/editor-input.js +445 -0
  183. package/dist/components/editor/editor-multicursor.d.ts +21 -0
  184. package/dist/components/editor/editor-multicursor.js +196 -0
  185. package/dist/components/editor/editor-scroll.d.ts +14 -0
  186. package/dist/components/editor/editor-scroll.js +34 -0
  187. package/dist/components/editor/index.d.ts +15 -0
  188. package/dist/components/editor/index.js +21 -0
  189. package/dist/components/editor/languages.d.ts +62 -0
  190. package/dist/components/editor/languages.js +285 -0
  191. package/dist/components/editor/theme.d.ts +88 -0
  192. package/dist/components/editor/theme.js +139 -0
  193. package/dist/components/editor/tokenizer/base.d.ts +40 -0
  194. package/dist/components/editor/tokenizer/base.js +203 -0
  195. package/dist/components/editor/tokenizer/index.d.ts +56 -0
  196. package/dist/components/editor/tokenizer/index.js +215 -0
  197. package/dist/components/editor/tokenizer/languages/css.d.ts +17 -0
  198. package/dist/components/editor/tokenizer/languages/css.js +194 -0
  199. package/dist/components/editor/tokenizer/languages/go.d.ts +17 -0
  200. package/dist/components/editor/tokenizer/languages/go.js +220 -0
  201. package/dist/components/editor/tokenizer/languages/html.d.ts +24 -0
  202. package/dist/components/editor/tokenizer/languages/html.js +145 -0
  203. package/dist/components/editor/tokenizer/languages/javascript.d.ts +56 -0
  204. package/dist/components/editor/tokenizer/languages/javascript.js +452 -0
  205. package/dist/components/editor/tokenizer/languages/json.d.ts +12 -0
  206. package/dist/components/editor/tokenizer/languages/json.js +91 -0
  207. package/dist/components/editor/tokenizer/languages/markdown.d.ts +16 -0
  208. package/dist/components/editor/tokenizer/languages/markdown.js +156 -0
  209. package/dist/components/editor/tokenizer/languages/python.d.ts +20 -0
  210. package/dist/components/editor/tokenizer/languages/python.js +227 -0
  211. package/dist/components/editor/tokenizer/languages/svelte.d.ts +40 -0
  212. package/dist/components/editor/tokenizer/languages/svelte.js +326 -0
  213. package/dist/components/editor/tokenizer/types.d.ts +86 -0
  214. package/dist/components/editor/tokenizer/types.js +4 -0
  215. package/dist/components/layout/IDELayout.svelte +274 -0
  216. package/dist/components/layout/IDELayout.svelte.d.ts +29 -0
  217. package/dist/components/layout/StatusBar.svelte +511 -0
  218. package/dist/components/layout/StatusBar.svelte.d.ts +47 -0
  219. package/dist/components/layout/index.d.ts +2 -0
  220. package/dist/components/layout/index.js +3 -0
  221. package/dist/components/lsp/AutocompleteWidget.svelte +364 -0
  222. package/dist/components/lsp/AutocompleteWidget.svelte.d.ts +33 -0
  223. package/dist/components/lsp/DiagnosticMarker.svelte +166 -0
  224. package/dist/components/lsp/DiagnosticMarker.svelte.d.ts +19 -0
  225. package/dist/components/lsp/DiagnosticsPanel.svelte +388 -0
  226. package/dist/components/lsp/DiagnosticsPanel.svelte.d.ts +21 -0
  227. package/dist/components/lsp/HoverTooltip.svelte +274 -0
  228. package/dist/components/lsp/HoverTooltip.svelte.d.ts +24 -0
  229. package/dist/components/lsp/LSPEditor.svelte +486 -0
  230. package/dist/components/lsp/LSPEditor.svelte.d.ts +39 -0
  231. package/dist/components/lsp/SignatureHelpWidget.svelte +216 -0
  232. package/dist/components/lsp/SignatureHelpWidget.svelte.d.ts +22 -0
  233. package/dist/components/lsp/index.d.ts +6 -0
  234. package/dist/components/lsp/index.js +7 -0
  235. package/dist/components/plugins/PluginCard.svelte +153 -0
  236. package/dist/components/plugins/PluginCard.svelte.d.ts +19 -0
  237. package/dist/components/plugins/PluginPanel.svelte +280 -0
  238. package/dist/components/plugins/PluginPanel.svelte.d.ts +8 -0
  239. package/dist/components/plugins/PluginProposalForm.svelte +250 -0
  240. package/dist/components/plugins/PluginProposalForm.svelte.d.ts +6 -0
  241. package/dist/components/plugins/PluginStatusBadge.svelte +14 -0
  242. package/dist/components/plugins/PluginStatusBadge.svelte.d.ts +8 -0
  243. package/dist/components/plugins/index.d.ts +4 -0
  244. package/dist/components/plugins/index.js +5 -0
  245. package/dist/components/vfs/LockConflictDialog.svelte +705 -0
  246. package/dist/components/vfs/LockConflictDialog.svelte.d.ts +21 -0
  247. package/dist/components/vfs/LockIndicator.svelte +194 -0
  248. package/dist/components/vfs/LockIndicator.svelte.d.ts +29 -0
  249. package/dist/components/vfs/LockOverlay.svelte +344 -0
  250. package/dist/components/vfs/LockOverlay.svelte.d.ts +17 -0
  251. package/dist/components/vfs/VersionConflictDialog.svelte +549 -0
  252. package/dist/components/vfs/VersionConflictDialog.svelte.d.ts +24 -0
  253. package/dist/components/vfs/index.d.ts +4 -0
  254. package/dist/components/vfs/index.js +5 -0
  255. package/dist/crdt/awareness.d.ts +42 -0
  256. package/dist/crdt/awareness.js +109 -0
  257. package/dist/crdt/document.d.ts +101 -0
  258. package/dist/crdt/document.js +187 -0
  259. package/dist/crdt/index.d.ts +9 -0
  260. package/dist/crdt/index.js +8 -0
  261. package/dist/crdt/provider.d.ts +85 -0
  262. package/dist/crdt/provider.js +150 -0
  263. package/dist/crdt/types.d.ts +61 -0
  264. package/dist/crdt/types.js +4 -0
  265. package/dist/crdt/undo.d.ts +34 -0
  266. package/dist/crdt/undo.js +70 -0
  267. package/dist/index.d.ts +277 -0
  268. package/dist/index.js +280 -0
  269. package/dist/plugins/index.d.ts +103 -0
  270. package/dist/plugins/index.js +153 -0
  271. package/dist/services/error-handling.d.ts +95 -0
  272. package/dist/services/error-handling.js +413 -0
  273. package/dist/services/ide-integration.d.ts +83 -0
  274. package/dist/services/ide-integration.js +367 -0
  275. package/dist/services/lsp-client.d.ts +69 -0
  276. package/dist/services/lsp-client.js +667 -0
  277. package/dist/services/mock-ai.d.ts +37 -0
  278. package/dist/services/mock-ai.js +318 -0
  279. package/dist/services/optimistic.d.ts +141 -0
  280. package/dist/services/optimistic.js +367 -0
  281. package/dist/services/vfs-client.d.ts +81 -0
  282. package/dist/services/vfs-client.js +348 -0
  283. package/dist/stores/agents.svelte.d.ts +85 -0
  284. package/dist/stores/agents.svelte.js +459 -0
  285. package/dist/stores/ai-persistence.svelte.d.ts +76 -0
  286. package/dist/stores/ai-persistence.svelte.js +334 -0
  287. package/dist/stores/ai.svelte.d.ts +140 -0
  288. package/dist/stores/ai.svelte.js +383 -0
  289. package/dist/stores/collaboration.svelte.d.ts +164 -0
  290. package/dist/stores/collaboration.svelte.js +334 -0
  291. package/dist/stores/editor.svelte.d.ts +131 -0
  292. package/dist/stores/editor.svelte.js +250 -0
  293. package/dist/stores/index.d.ts +10 -0
  294. package/dist/stores/index.js +29 -0
  295. package/dist/stores/layout.svelte.d.ts +171 -0
  296. package/dist/stores/layout.svelte.js +351 -0
  297. package/dist/stores/plugin.svelte.d.ts +121 -0
  298. package/dist/stores/plugin.svelte.js +410 -0
  299. package/dist/stores/vfs.svelte.d.ts +123 -0
  300. package/dist/stores/vfs.svelte.js +680 -0
  301. package/dist/styles/theme.css +623 -0
  302. package/dist/types/agents.d.ts +127 -0
  303. package/dist/types/agents.js +5 -0
  304. package/dist/types/ai.d.ts +137 -0
  305. package/dist/types/ai.js +4 -0
  306. package/dist/types/crdt.d.ts +222 -0
  307. package/dist/types/crdt.js +5 -0
  308. package/dist/types/editor.d.ts +52 -0
  309. package/dist/types/editor.js +18 -0
  310. package/dist/types/events.d.ts +133 -0
  311. package/dist/types/events.js +4 -0
  312. package/dist/types/filesystem.d.ts +77 -0
  313. package/dist/types/filesystem.js +4 -0
  314. package/dist/types/index.d.ts +9 -0
  315. package/dist/types/index.js +12 -0
  316. package/dist/types/lsp.d.ts +691 -0
  317. package/dist/types/lsp.js +108 -0
  318. package/dist/types/plugin.d.ts +239 -0
  319. package/dist/types/plugin.js +5 -0
  320. package/dist/types/vfs.d.ts +191 -0
  321. package/dist/types/vfs.js +18 -0
  322. package/dist/utils/format.d.ts +55 -0
  323. package/dist/utils/format.js +152 -0
  324. package/dist/utils/index.d.ts +3 -0
  325. package/dist/utils/index.js +4 -0
  326. package/dist/utils/keybindings.d.ts +33 -0
  327. package/dist/utils/keybindings.js +171 -0
  328. package/dist/utils/language.d.ts +27 -0
  329. package/dist/utils/language.js +222 -0
  330. package/package.json +178 -0
@@ -0,0 +1,408 @@
1
+ /**
2
+ * Cursor navigation utilities
3
+ *
4
+ * This module provides cursor movement operations for the custom editor.
5
+ * Properly handles Unicode including emoji and characters outside the BMP.
6
+ */
7
+ /**
8
+ * Word boundary pattern - supports Unicode letters and digits
9
+ * Uses Unicode property escapes for proper internationalization
10
+ */
11
+ const WORD_PATTERN = /[\p{L}\p{N}_]/u;
12
+ /**
13
+ * Check if character is a word character
14
+ * Supports Unicode identifiers (e.g., café, π, 日本語)
15
+ */
16
+ export function isWordChar(char) {
17
+ if (!char || char.length === 0)
18
+ return false;
19
+ return WORD_PATTERN.test(char);
20
+ }
21
+ /**
22
+ * Get the code point at a position in a string
23
+ * Properly handles surrogate pairs (emoji, etc.)
24
+ * @returns The code point string and its UTF-16 length (1 or 2)
25
+ */
26
+ function getCodePointAt(text, index) {
27
+ if (index < 0 || index >= text.length)
28
+ return null;
29
+ const code = text.charCodeAt(index);
30
+ // Check if this is a high surrogate (first half of a surrogate pair)
31
+ if (code >= 0xd800 && code <= 0xdbff && index + 1 < text.length) {
32
+ const nextCode = text.charCodeAt(index + 1);
33
+ // Check if next is a low surrogate (second half)
34
+ if (nextCode >= 0xdc00 && nextCode <= 0xdfff) {
35
+ return { char: text.slice(index, index + 2), length: 2 };
36
+ }
37
+ }
38
+ return { char: text[index], length: 1 };
39
+ }
40
+ /**
41
+ * Get the code point before a position in a string
42
+ * Properly handles surrogate pairs (emoji, etc.)
43
+ * @returns The code point string and its UTF-16 length (1 or 2)
44
+ */
45
+ function getCodePointBefore(text, index) {
46
+ if (index <= 0 || index > text.length)
47
+ return null;
48
+ const code = text.charCodeAt(index - 1);
49
+ // Check if this is a low surrogate (second half of a surrogate pair)
50
+ if (code >= 0xdc00 && code <= 0xdfff && index >= 2) {
51
+ const prevCode = text.charCodeAt(index - 2);
52
+ // Check if prev is a high surrogate (first half)
53
+ if (prevCode >= 0xd800 && prevCode <= 0xdbff) {
54
+ return { char: text.slice(index - 2, index), length: 2 };
55
+ }
56
+ }
57
+ return { char: text[index - 1], length: 1 };
58
+ }
59
+ /**
60
+ * Navigation operations for the editor
61
+ */
62
+ export class Navigation {
63
+ state;
64
+ /**
65
+ * Sticky column (preferred column) for vertical navigation.
66
+ * Remembers the column position when moving through lines of varying lengths.
67
+ */
68
+ stickyColumn = -1;
69
+ constructor(state) {
70
+ this.state = state;
71
+ }
72
+ /**
73
+ * Reset sticky column - call this when cursor moves horizontally
74
+ */
75
+ resetStickyColumn() {
76
+ this.stickyColumn = -1;
77
+ }
78
+ /**
79
+ * Get the target column for vertical movement, using sticky column if set
80
+ */
81
+ getTargetColumn(currentColumn) {
82
+ if (this.stickyColumn < 0) {
83
+ this.stickyColumn = currentColumn;
84
+ }
85
+ return this.stickyColumn;
86
+ }
87
+ // ============================================
88
+ // Basic Movement
89
+ // ============================================
90
+ /**
91
+ * Move cursor left
92
+ * Properly handles Unicode surrogate pairs (emoji, etc.)
93
+ */
94
+ moveLeft(extend = false) {
95
+ this.resetStickyColumn(); // Horizontal movement resets sticky column
96
+ const { line, column } = this.state.cursor;
97
+ if (column > 0) {
98
+ const currentLine = this.state.getLine(line);
99
+ if (currentLine) {
100
+ // Get the code point before cursor to handle surrogate pairs
101
+ const cp = getCodePointBefore(currentLine.text, column);
102
+ const step = cp?.length ?? 1;
103
+ this.moveTo({ line, column: column - step }, extend);
104
+ }
105
+ else {
106
+ this.moveTo({ line, column: column - 1 }, extend);
107
+ }
108
+ }
109
+ else if (line > 0) {
110
+ // Move to end of previous line
111
+ const prevLine = this.state.getLine(line - 1);
112
+ if (prevLine) {
113
+ this.moveTo({ line: line - 1, column: prevLine.text.length }, extend);
114
+ }
115
+ }
116
+ }
117
+ /**
118
+ * Move cursor right
119
+ * Properly handles Unicode surrogate pairs (emoji, etc.)
120
+ */
121
+ moveRight(extend = false) {
122
+ this.resetStickyColumn(); // Horizontal movement resets sticky column
123
+ const { line, column } = this.state.cursor;
124
+ const currentLine = this.state.getLine(line);
125
+ if (!currentLine)
126
+ return;
127
+ if (column < currentLine.text.length) {
128
+ // Get the code point at cursor to handle surrogate pairs
129
+ const cp = getCodePointAt(currentLine.text, column);
130
+ const step = cp?.length ?? 1;
131
+ this.moveTo({ line, column: column + step }, extend);
132
+ }
133
+ else if (line < this.state.lineCount - 1) {
134
+ // Move to start of next line
135
+ this.moveTo({ line: line + 1, column: 0 }, extend);
136
+ }
137
+ }
138
+ /**
139
+ * Move cursor up
140
+ * Uses sticky column to preserve horizontal position through lines of varying lengths
141
+ */
142
+ moveUp(extend = false) {
143
+ const { line, column } = this.state.cursor;
144
+ if (line > 0) {
145
+ const prevLine = this.state.getLine(line - 1);
146
+ if (prevLine) {
147
+ // Use sticky column to remember preferred position
148
+ const targetColumn = this.getTargetColumn(column);
149
+ const newColumn = Math.min(targetColumn, prevLine.text.length);
150
+ this.moveTo({ line: line - 1, column: newColumn }, extend);
151
+ }
152
+ }
153
+ }
154
+ /**
155
+ * Move cursor down
156
+ * Uses sticky column to preserve horizontal position through lines of varying lengths
157
+ */
158
+ moveDown(extend = false) {
159
+ const { line, column } = this.state.cursor;
160
+ if (line < this.state.lineCount - 1) {
161
+ const nextLine = this.state.getLine(line + 1);
162
+ if (nextLine) {
163
+ // Use sticky column to remember preferred position
164
+ const targetColumn = this.getTargetColumn(column);
165
+ const newColumn = Math.min(targetColumn, nextLine.text.length);
166
+ this.moveTo({ line: line + 1, column: newColumn }, extend);
167
+ }
168
+ }
169
+ }
170
+ // ============================================
171
+ // Line Movement
172
+ // ============================================
173
+ /**
174
+ * Move to start of line
175
+ */
176
+ moveToLineStart(extend = false) {
177
+ const { line } = this.state.cursor;
178
+ const currentLine = this.state.getLine(line);
179
+ if (!currentLine)
180
+ return;
181
+ // Find first non-whitespace character
182
+ const firstNonWs = currentLine.text.search(/\S/);
183
+ const targetColumn = firstNonWs === -1 ? 0 : firstNonWs;
184
+ // If already at first non-ws, go to column 0
185
+ if (this.state.cursor.column === targetColumn && targetColumn > 0) {
186
+ this.moveTo({ line, column: 0 }, extend);
187
+ }
188
+ else {
189
+ this.moveTo({ line, column: targetColumn }, extend);
190
+ }
191
+ }
192
+ /**
193
+ * Move to end of line
194
+ */
195
+ moveToLineEnd(extend = false) {
196
+ const { line } = this.state.cursor;
197
+ const currentLine = this.state.getLine(line);
198
+ if (currentLine) {
199
+ this.moveTo({ line, column: currentLine.text.length }, extend);
200
+ }
201
+ }
202
+ // ============================================
203
+ // Word Movement
204
+ // ============================================
205
+ /**
206
+ * Move to start of previous word
207
+ * Properly handles Unicode surrogate pairs (emoji, etc.)
208
+ */
209
+ moveWordLeft(extend = false) {
210
+ const { line, column } = this.state.cursor;
211
+ const currentLine = this.state.getLine(line);
212
+ if (!currentLine)
213
+ return;
214
+ if (column === 0) {
215
+ // Move to end of previous line
216
+ if (line > 0) {
217
+ const prevLine = this.state.getLine(line - 1);
218
+ if (prevLine) {
219
+ this.moveTo({ line: line - 1, column: prevLine.text.length }, extend);
220
+ }
221
+ }
222
+ return;
223
+ }
224
+ const text = currentLine.text;
225
+ let pos = column;
226
+ // Skip backwards, handling surrogate pairs
227
+ // First, skip whitespace/punctuation
228
+ while (pos > 0) {
229
+ const cp = getCodePointBefore(text, pos);
230
+ if (!cp || isWordChar(cp.char))
231
+ break;
232
+ pos -= cp.length;
233
+ }
234
+ // Then skip word characters
235
+ while (pos > 0) {
236
+ const cp = getCodePointBefore(text, pos);
237
+ if (!cp || !isWordChar(cp.char))
238
+ break;
239
+ pos -= cp.length;
240
+ }
241
+ this.moveTo({ line, column: pos }, extend);
242
+ }
243
+ /**
244
+ * Move to start of next word
245
+ * Properly handles Unicode surrogate pairs (emoji, etc.)
246
+ */
247
+ moveWordRight(extend = false) {
248
+ const { line, column } = this.state.cursor;
249
+ const currentLine = this.state.getLine(line);
250
+ if (!currentLine)
251
+ return;
252
+ const text = currentLine.text;
253
+ if (column >= text.length) {
254
+ // Move to start of next line
255
+ if (line < this.state.lineCount - 1) {
256
+ this.moveTo({ line: line + 1, column: 0 }, extend);
257
+ }
258
+ return;
259
+ }
260
+ let pos = column;
261
+ // Skip forwards, handling surrogate pairs
262
+ // First, skip current word characters
263
+ while (pos < text.length) {
264
+ const cp = getCodePointAt(text, pos);
265
+ if (!cp || !isWordChar(cp.char))
266
+ break;
267
+ pos += cp.length;
268
+ }
269
+ // Then skip whitespace/punctuation
270
+ while (pos < text.length) {
271
+ const cp = getCodePointAt(text, pos);
272
+ if (!cp || isWordChar(cp.char))
273
+ break;
274
+ pos += cp.length;
275
+ }
276
+ this.moveTo({ line, column: pos }, extend);
277
+ }
278
+ // ============================================
279
+ // Document Movement
280
+ // ============================================
281
+ /**
282
+ * Move to start of document
283
+ */
284
+ moveToDocumentStart(extend = false) {
285
+ this.moveTo({ line: 0, column: 0 }, extend);
286
+ }
287
+ /**
288
+ * Move to end of document
289
+ */
290
+ moveToDocumentEnd(extend = false) {
291
+ const lastLine = this.state.getLine(this.state.lineCount - 1);
292
+ if (lastLine) {
293
+ this.moveTo({ line: this.state.lineCount - 1, column: lastLine.text.length }, extend);
294
+ }
295
+ }
296
+ /**
297
+ * Move up by a page
298
+ */
299
+ movePageUp(pageSize, extend = false) {
300
+ const { line, column } = this.state.cursor;
301
+ const targetLine = Math.max(0, line - pageSize);
302
+ const targetLineContent = this.state.getLine(targetLine);
303
+ const newColumn = targetLineContent
304
+ ? Math.min(column, targetLineContent.text.length)
305
+ : 0;
306
+ this.moveTo({ line: targetLine, column: newColumn }, extend);
307
+ }
308
+ /**
309
+ * Move down by a page
310
+ */
311
+ movePageDown(pageSize, extend = false) {
312
+ const { line, column } = this.state.cursor;
313
+ const targetLine = Math.min(this.state.lineCount - 1, line + pageSize);
314
+ const targetLineContent = this.state.getLine(targetLine);
315
+ const newColumn = targetLineContent
316
+ ? Math.min(column, targetLineContent.text.length)
317
+ : 0;
318
+ this.moveTo({ line: targetLine, column: newColumn }, extend);
319
+ }
320
+ // ============================================
321
+ // Selection
322
+ // ============================================
323
+ /**
324
+ * Select current word
325
+ * Properly handles Unicode surrogate pairs (emoji, etc.)
326
+ */
327
+ selectWord() {
328
+ const { line, column } = this.state.cursor;
329
+ const currentLine = this.state.getLine(line);
330
+ if (!currentLine)
331
+ return;
332
+ const text = currentLine.text;
333
+ // Find word boundaries, handling surrogate pairs
334
+ let start = column;
335
+ let end = column;
336
+ // Find start of word
337
+ while (start > 0) {
338
+ const cp = getCodePointBefore(text, start);
339
+ if (!cp || !isWordChar(cp.char))
340
+ break;
341
+ start -= cp.length;
342
+ }
343
+ // Find end of word
344
+ while (end < text.length) {
345
+ const cp = getCodePointAt(text, end);
346
+ if (!cp || !isWordChar(cp.char))
347
+ break;
348
+ end += cp.length;
349
+ }
350
+ if (start !== end) {
351
+ this.state.setSelection({ line, column: start }, { line, column: end });
352
+ }
353
+ }
354
+ /**
355
+ * Select current line
356
+ */
357
+ selectLine() {
358
+ const { line } = this.state.cursor;
359
+ const currentLine = this.state.getLine(line);
360
+ if (!currentLine)
361
+ return;
362
+ // Select from start of current line to start of next line (or end of document)
363
+ if (line < this.state.lineCount - 1) {
364
+ this.state.setSelection({ line, column: 0 }, { line: line + 1, column: 0 });
365
+ }
366
+ else {
367
+ this.state.setSelection({ line, column: 0 }, { line, column: currentLine.text.length });
368
+ }
369
+ }
370
+ // ============================================
371
+ // Helpers
372
+ // ============================================
373
+ /**
374
+ * Move to position, optionally extending selection
375
+ */
376
+ moveTo(position, extend) {
377
+ if (extend) {
378
+ this.state.extendSelection(position);
379
+ }
380
+ else {
381
+ this.state.setCursor(position);
382
+ }
383
+ }
384
+ /**
385
+ * Get position from mouse coordinates
386
+ */
387
+ positionFromPoint(x, y, lineHeight, charWidth, scrollTop, scrollLeft, paddingLeft, gutterWidth) {
388
+ // Calculate line from y position
389
+ const adjustedY = y + scrollTop;
390
+ const line = Math.max(0, Math.min(Math.floor(adjustedY / lineHeight), this.state.lineCount - 1));
391
+ // Calculate column from x position
392
+ const adjustedX = x + scrollLeft - paddingLeft - gutterWidth;
393
+ const column = Math.max(0, Math.round(adjustedX / charWidth));
394
+ // Clamp to line length
395
+ const lineContent = this.state.getLine(line);
396
+ const maxColumn = lineContent ? lineContent.text.length : 0;
397
+ return {
398
+ line,
399
+ column: Math.min(column, maxColumn)
400
+ };
401
+ }
402
+ }
403
+ /**
404
+ * Create navigation helper
405
+ */
406
+ export function createNavigation(state) {
407
+ return new Navigation(state);
408
+ }
@@ -0,0 +1,189 @@
1
+ /**
2
+ * Quick Actions (Code Actions) Manager
3
+ *
4
+ * Provides contextual code actions like:
5
+ * - Quick fixes for errors/warnings
6
+ * - Refactoring operations
7
+ * - Code generation
8
+ * - Import suggestions
9
+ */
10
+ export interface Position {
11
+ line: number;
12
+ column: number;
13
+ }
14
+ export interface Range {
15
+ start: Position;
16
+ end: Position;
17
+ }
18
+ export type CodeActionKind = 'quickfix' | 'refactor' | 'refactor.extract' | 'refactor.inline' | 'refactor.rename' | 'source' | 'source.organizeImports' | 'source.fixAll' | 'generate';
19
+ export interface CodeAction {
20
+ /** Unique identifier */
21
+ id: string;
22
+ /** Display title */
23
+ title: string;
24
+ /** Action kind for categorization */
25
+ kind: CodeActionKind;
26
+ /** Optional description */
27
+ description?: string;
28
+ /** Keyboard shortcut hint */
29
+ shortcut?: string;
30
+ /** Whether this is a preferred action */
31
+ isPreferred?: boolean;
32
+ /** Whether this action is disabled */
33
+ disabled?: boolean;
34
+ /** Reason why action is disabled */
35
+ disabledReason?: string;
36
+ /** The edit to apply */
37
+ edit?: CodeEdit;
38
+ /** Command to execute instead of/after edit */
39
+ command?: CodeCommand;
40
+ /** Diagnostics this action addresses */
41
+ diagnostics?: Diagnostic[];
42
+ }
43
+ export interface CodeEdit {
44
+ /** Text changes to apply */
45
+ changes: TextChange[];
46
+ }
47
+ export interface TextChange {
48
+ /** Range to replace */
49
+ range: Range;
50
+ /** New text */
51
+ newText: string;
52
+ }
53
+ export interface CodeCommand {
54
+ /** Command identifier */
55
+ command: string;
56
+ /** Command title */
57
+ title: string;
58
+ /** Command arguments */
59
+ arguments?: unknown[];
60
+ }
61
+ export interface Diagnostic {
62
+ /** Diagnostic range */
63
+ range: Range;
64
+ /** Severity level */
65
+ severity: 'error' | 'warning' | 'info' | 'hint';
66
+ /** Message */
67
+ message: string;
68
+ /** Source (e.g., "typescript", "eslint") */
69
+ source?: string;
70
+ /** Error code */
71
+ code?: string | number;
72
+ }
73
+ export interface CodeActionContext {
74
+ /** Current cursor position */
75
+ position: Position;
76
+ /** Current selection range */
77
+ selection?: Range;
78
+ /** Diagnostics at current position */
79
+ diagnostics: Diagnostic[];
80
+ /** Current line content */
81
+ lineContent: string;
82
+ /** Selected text (if any) */
83
+ selectedText?: string;
84
+ /** Language ID */
85
+ language: string;
86
+ /** Full document content */
87
+ content: string;
88
+ }
89
+ export type CodeActionProvider = (context: CodeActionContext) => CodeAction[];
90
+ interface QuickActionsConfig {
91
+ /** Whether quick actions are enabled */
92
+ enabled: boolean;
93
+ /** Show lightbulb indicator */
94
+ showLightbulb: boolean;
95
+ /** Auto-show on cursor position change */
96
+ autoShow: boolean;
97
+ /** Delay before showing actions (ms) */
98
+ showDelay: number;
99
+ }
100
+ type Listener = () => void;
101
+ /**
102
+ * Quick Actions Manager
103
+ */
104
+ export declare class QuickActionsManager {
105
+ private _config;
106
+ private _providers;
107
+ private _currentActions;
108
+ private _currentContext;
109
+ private _listeners;
110
+ private _showTimeout;
111
+ constructor();
112
+ /**
113
+ * Register built-in action providers
114
+ */
115
+ private registerBuiltinProviders;
116
+ /**
117
+ * Register a code action provider
118
+ */
119
+ registerProvider(id: string, provider: CodeActionProvider): () => void;
120
+ /**
121
+ * Get available actions for context
122
+ */
123
+ getActions(context: CodeActionContext): CodeAction[];
124
+ /**
125
+ * Update context and refresh actions
126
+ */
127
+ updateContext(context: CodeActionContext): void;
128
+ /**
129
+ * Force refresh actions
130
+ */
131
+ refresh(): void;
132
+ /**
133
+ * Execute a code action
134
+ */
135
+ executeAction(action: CodeAction): Promise<boolean>;
136
+ /**
137
+ * Get current actions
138
+ */
139
+ get currentActions(): CodeAction[];
140
+ /**
141
+ * Check if actions are available
142
+ */
143
+ get hasActions(): boolean;
144
+ /**
145
+ * Get config
146
+ */
147
+ get config(): QuickActionsConfig;
148
+ /**
149
+ * Update config
150
+ */
151
+ setConfig(config: Partial<QuickActionsConfig>): void;
152
+ /**
153
+ * Enable/disable quick actions
154
+ */
155
+ setEnabled(enabled: boolean): void;
156
+ /**
157
+ * Check if enabled
158
+ */
159
+ isEnabled(): boolean;
160
+ /**
161
+ * Subscribe to changes
162
+ */
163
+ subscribe(listener: Listener): () => void;
164
+ /**
165
+ * Notify listeners
166
+ */
167
+ private notify;
168
+ /**
169
+ * Clean up
170
+ */
171
+ destroy(): void;
172
+ }
173
+ /**
174
+ * Create a new QuickActionsManager instance
175
+ */
176
+ export declare function createQuickActionsManager(): QuickActionsManager;
177
+ /**
178
+ * Group actions by kind for display
179
+ */
180
+ export declare function groupActionsByKind(actions: CodeAction[]): Map<string, CodeAction[]>;
181
+ /**
182
+ * Get display label for action kind
183
+ */
184
+ export declare function getKindLabel(kind: CodeActionKind | string): string;
185
+ /**
186
+ * Get icon for action kind
187
+ */
188
+ export declare function getKindIcon(kind: CodeActionKind | string): string;
189
+ export {};