@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,793 @@
1
+ <script lang="ts">
2
+ /**
3
+ * Plugin Preview Sandbox
4
+ *
5
+ * A sandboxed environment for previewing plugin effects
6
+ * before applying them to the main editor. Supports live
7
+ * code transformation preview with rollback capability.
8
+ */
9
+
10
+ import { onMount, onDestroy } from 'svelte';
11
+
12
+ interface PluginTransform {
13
+ /** Transform ID */
14
+ id: string;
15
+ /** Plugin name */
16
+ pluginName: string;
17
+ /** Transform description */
18
+ description: string;
19
+ /** Original code */
20
+ original: string;
21
+ /** Transformed code */
22
+ transformed: string;
23
+ /** Diff hunks */
24
+ diffs: DiffHunk[];
25
+ /** Whether transform is valid */
26
+ isValid: boolean;
27
+ /** Error message if invalid */
28
+ error?: string;
29
+ /** Execution time in ms */
30
+ executionTime: number;
31
+ }
32
+
33
+ interface DiffHunk {
34
+ type: 'add' | 'remove' | 'unchanged';
35
+ content: string;
36
+ lineNumber: number;
37
+ }
38
+
39
+ interface Props {
40
+ /** Code to transform */
41
+ code: string;
42
+ /** Language for syntax highlighting */
43
+ language?: string;
44
+ /** Available plugins */
45
+ plugins?: PluginDefinition[];
46
+ /** Whether sandbox is visible */
47
+ visible?: boolean;
48
+ /** Callback when transform is applied */
49
+ onApply?: (transform: PluginTransform) => void;
50
+ /** Callback when closed */
51
+ onClose?: () => void;
52
+ }
53
+
54
+ interface PluginDefinition {
55
+ id: string;
56
+ name: string;
57
+ description: string;
58
+ icon?: string;
59
+ transform: (code: string) => string | Promise<string>;
60
+ }
61
+
62
+ let {
63
+ code,
64
+ language = 'javascript',
65
+ plugins = [],
66
+ visible = false,
67
+ onApply,
68
+ onClose
69
+ }: Props = $props();
70
+
71
+ let selectedPlugin = $state<PluginDefinition | null>(null);
72
+ let currentTransform = $state<PluginTransform | null>(null);
73
+ let isProcessing = $state(false);
74
+ let previewMode = $state<'split' | 'unified' | 'diff'>('split');
75
+ let sandboxContainer = $state<HTMLDivElement>(null!);
76
+
77
+ // Demo plugins for showcase
78
+ const demoPlugins: PluginDefinition[] = [
79
+ {
80
+ id: 'prettier',
81
+ name: 'Prettier',
82
+ description: 'Format code with Prettier',
83
+ icon: 'P',
84
+ transform: (code) => {
85
+ // Simulate prettier formatting
86
+ return code
87
+ .split('\n')
88
+ .map((line) => line.trimEnd())
89
+ .join('\n');
90
+ }
91
+ },
92
+ {
93
+ id: 'sort-imports',
94
+ name: 'Sort Imports',
95
+ description: 'Alphabetically sort import statements',
96
+ icon: 'S',
97
+ transform: (code) => {
98
+ const lines = code.split('\n');
99
+ const imports: string[] = [];
100
+ const rest: string[] = [];
101
+ let inImports = true;
102
+
103
+ for (const line of lines) {
104
+ if (inImports && line.startsWith('import ')) {
105
+ imports.push(line);
106
+ } else {
107
+ if (imports.length > 0) inImports = false;
108
+ rest.push(line);
109
+ }
110
+ }
111
+
112
+ imports.sort((a, b) => a.localeCompare(b));
113
+ return [...imports, ...rest].join('\n');
114
+ }
115
+ },
116
+ {
117
+ id: 'add-types',
118
+ name: 'Add Types',
119
+ description: 'Add TypeScript type annotations',
120
+ icon: 'T',
121
+ transform: (code) => {
122
+ // Simple demo: add basic types
123
+ return code
124
+ .replace(/const (\w+) = (\d+)/g, 'const $1: number = $2')
125
+ .replace(/const (\w+) = ['"](.*)["']/g, "const $1: string = '$2'")
126
+ .replace(/const (\w+) = \[/g, 'const $1: unknown[] = [');
127
+ }
128
+ },
129
+ {
130
+ id: 'add-jsdoc',
131
+ name: 'Add JSDoc',
132
+ description: 'Generate JSDoc comments for functions',
133
+ icon: 'D',
134
+ transform: (code) => {
135
+ return code.replace(
136
+ /^(export )?(async )?(function )(\w+)\((.*?)\)/gm,
137
+ (_match, exp, async, fn, name, params) => {
138
+ const paramList = params
139
+ .split(',')
140
+ .filter((p: string) => p.trim())
141
+ .map((p: string) => ` * @param {unknown} ${p.trim().split(':')[0]}`)
142
+ .join('\n');
143
+ const jsdoc = `/**\n * ${name}\n${paramList}\n * @returns {unknown}\n */\n`;
144
+ return `${jsdoc}${exp || ''}${async || ''}${fn}${name}(${params})`;
145
+ }
146
+ );
147
+ }
148
+ },
149
+ {
150
+ id: 'minify',
151
+ name: 'Minify',
152
+ description: 'Minify code by removing whitespace',
153
+ icon: 'M',
154
+ transform: (code) => {
155
+ return code
156
+ .split('\n')
157
+ .map((line) => line.trim())
158
+ .filter((line) => line.length > 0)
159
+ .join(' ')
160
+ .replace(/\s+/g, ' ')
161
+ .replace(/\s*([{};,:])\s*/g, '$1');
162
+ }
163
+ }
164
+ ];
165
+
166
+ const activePlugins = $derived(plugins.length > 0 ? plugins : demoPlugins);
167
+
168
+ /**
169
+ * Run plugin transform
170
+ */
171
+ async function runTransform(plugin: PluginDefinition) {
172
+ selectedPlugin = plugin;
173
+ isProcessing = true;
174
+
175
+ const startTime = performance.now();
176
+
177
+ try {
178
+ const result = await Promise.resolve(plugin.transform(code));
179
+ const executionTime = performance.now() - startTime;
180
+
181
+ currentTransform = {
182
+ id: `${plugin.id}-${Date.now()}`,
183
+ pluginName: plugin.name,
184
+ description: plugin.description,
185
+ original: code,
186
+ transformed: result,
187
+ diffs: computeDiffs(code, result),
188
+ isValid: true,
189
+ executionTime
190
+ };
191
+ } catch (error) {
192
+ currentTransform = {
193
+ id: `${plugin.id}-${Date.now()}`,
194
+ pluginName: plugin.name,
195
+ description: plugin.description,
196
+ original: code,
197
+ transformed: code,
198
+ diffs: [],
199
+ isValid: false,
200
+ error: error instanceof Error ? error.message : 'Unknown error',
201
+ executionTime: performance.now() - startTime
202
+ };
203
+ }
204
+
205
+ isProcessing = false;
206
+ }
207
+
208
+ /**
209
+ * Compute simple diff between original and transformed
210
+ */
211
+ function computeDiffs(original: string, transformed: string): DiffHunk[] {
212
+ const originalLines = original.split('\n');
213
+ const transformedLines = transformed.split('\n');
214
+ const diffs: DiffHunk[] = [];
215
+
216
+ // Simple line-by-line diff
217
+ const maxLen = Math.max(originalLines.length, transformedLines.length);
218
+
219
+ for (let i = 0; i < maxLen; i++) {
220
+ const origLine = originalLines[i];
221
+ const newLine = transformedLines[i];
222
+
223
+ if (origLine === undefined && newLine !== undefined) {
224
+ diffs.push({ type: 'add', content: newLine, lineNumber: i + 1 });
225
+ } else if (origLine !== undefined && newLine === undefined) {
226
+ diffs.push({ type: 'remove', content: origLine, lineNumber: i + 1 });
227
+ } else if (origLine !== newLine) {
228
+ diffs.push({ type: 'remove', content: origLine, lineNumber: i + 1 });
229
+ diffs.push({ type: 'add', content: newLine, lineNumber: i + 1 });
230
+ } else {
231
+ diffs.push({ type: 'unchanged', content: origLine, lineNumber: i + 1 });
232
+ }
233
+ }
234
+
235
+ return diffs;
236
+ }
237
+
238
+ /**
239
+ * Apply the current transform
240
+ */
241
+ function applyTransform() {
242
+ if (currentTransform && currentTransform.isValid) {
243
+ onApply?.(currentTransform);
244
+ }
245
+ }
246
+
247
+ /**
248
+ * Reset to original
249
+ */
250
+ function resetTransform() {
251
+ currentTransform = null;
252
+ selectedPlugin = null;
253
+ }
254
+
255
+ /**
256
+ * Close sandbox
257
+ */
258
+ function closeSandbox() {
259
+ resetTransform();
260
+ onClose?.();
261
+ }
262
+
263
+ /**
264
+ * Get stats about the transform
265
+ */
266
+ function getTransformStats(transform: PluginTransform) {
267
+ const added = transform.diffs.filter((d) => d.type === 'add').length;
268
+ const removed = transform.diffs.filter((d) => d.type === 'remove').length;
269
+ const unchanged = transform.diffs.filter((d) => d.type === 'unchanged').length;
270
+
271
+ return { added, removed, unchanged };
272
+ }
273
+ </script>
274
+
275
+ {#if visible}
276
+ <div class="plugin-sandbox" bind:this={sandboxContainer}>
277
+ <div class="plugin-sandbox__header">
278
+ <h3 class="plugin-sandbox__title">Plugin Preview Sandbox</h3>
279
+ <div class="plugin-sandbox__actions">
280
+ <div class="preview-mode-toggle">
281
+ <button
282
+ class="mode-btn"
283
+ class:active={previewMode === 'split'}
284
+ onclick={() => (previewMode = 'split')}
285
+ >
286
+ Split
287
+ </button>
288
+ <button
289
+ class="mode-btn"
290
+ class:active={previewMode === 'unified'}
291
+ onclick={() => (previewMode = 'unified')}
292
+ >
293
+ Unified
294
+ </button>
295
+ <button
296
+ class="mode-btn"
297
+ class:active={previewMode === 'diff'}
298
+ onclick={() => (previewMode = 'diff')}
299
+ >
300
+ Diff
301
+ </button>
302
+ </div>
303
+ <button class="plugin-sandbox__close" onclick={closeSandbox}>Close</button>
304
+ </div>
305
+ </div>
306
+
307
+ <div class="plugin-sandbox__content">
308
+ <!-- Plugin selector sidebar -->
309
+ <div class="plugin-sidebar">
310
+ <h4 class="plugin-sidebar__title">Available Plugins</h4>
311
+ <div class="plugin-list">
312
+ {#each activePlugins as plugin (plugin.id)}
313
+ <button
314
+ class="plugin-item"
315
+ class:plugin-item--selected={selectedPlugin?.id === plugin.id}
316
+ onclick={() => runTransform(plugin)}
317
+ disabled={isProcessing}
318
+ >
319
+ <span class="plugin-item__icon">{plugin.icon || plugin.name[0]}</span>
320
+ <div class="plugin-item__info">
321
+ <span class="plugin-item__name">{plugin.name}</span>
322
+ <span class="plugin-item__desc">{plugin.description}</span>
323
+ </div>
324
+ </button>
325
+ {/each}
326
+ </div>
327
+ </div>
328
+
329
+ <!-- Preview area -->
330
+ <div class="preview-area">
331
+ {#if isProcessing}
332
+ <div class="preview-loading">
333
+ <span class="loading-spinner"></span>
334
+ <span>Processing...</span>
335
+ </div>
336
+ {:else if currentTransform}
337
+ {@const stats = getTransformStats(currentTransform)}
338
+
339
+ <!-- Transform info bar -->
340
+ <div class="transform-info">
341
+ <span class="transform-plugin">{currentTransform.pluginName}</span>
342
+ <span class="transform-stats">
343
+ <span class="stat stat--add">+{stats.added}</span>
344
+ <span class="stat stat--remove">-{stats.removed}</span>
345
+ </span>
346
+ <span class="transform-time">{currentTransform.executionTime.toFixed(1)}ms</span>
347
+
348
+ {#if currentTransform.isValid}
349
+ <button class="apply-btn" onclick={applyTransform}>Apply Changes</button>
350
+ {:else}
351
+ <span class="transform-error">Error: {currentTransform.error}</span>
352
+ {/if}
353
+
354
+ <button class="reset-btn" onclick={resetTransform}>Reset</button>
355
+ </div>
356
+
357
+ <!-- Preview content -->
358
+ <div class="preview-content preview-content--{previewMode}">
359
+ {#if previewMode === 'split'}
360
+ <div class="split-view">
361
+ <div class="split-pane">
362
+ <div class="pane-header">Original</div>
363
+ <pre class="code-block">{currentTransform.original}</pre>
364
+ </div>
365
+ <div class="split-pane">
366
+ <div class="pane-header">Transformed</div>
367
+ <pre class="code-block">{currentTransform.transformed}</pre>
368
+ </div>
369
+ </div>
370
+ {:else if previewMode === 'unified'}
371
+ <pre class="code-block">{currentTransform.transformed}</pre>
372
+ {:else}
373
+ <div class="diff-view">
374
+ {#each currentTransform.diffs as hunk}
375
+ {#if hunk.type !== 'unchanged' || true}
376
+ <div class="diff-line diff-line--{hunk.type}">
377
+ <span class="diff-line__num">{hunk.lineNumber}</span>
378
+ <span class="diff-line__sign"
379
+ >{hunk.type === 'add' ? '+' : hunk.type === 'remove' ? '-' : ' '}</span
380
+ >
381
+ <span class="diff-line__content">{hunk.content}</span>
382
+ </div>
383
+ {/if}
384
+ {/each}
385
+ </div>
386
+ {/if}
387
+ </div>
388
+ {:else}
389
+ <div class="preview-empty">
390
+ <p>Select a plugin to preview its transformation</p>
391
+ <p class="preview-hint">Your code will be transformed in this sandbox before applying</p>
392
+ </div>
393
+ {/if}
394
+ </div>
395
+ </div>
396
+ </div>
397
+ {/if}
398
+
399
+ <style>
400
+ .plugin-sandbox {
401
+ position: fixed;
402
+ top: 50%;
403
+ left: 50%;
404
+ transform: translate(-50%, -50%);
405
+ width: 90vw;
406
+ max-width: 1200px;
407
+ height: 80vh;
408
+ background: var(--color-surface, #1e1e2e);
409
+ border: 1px solid var(--color-border, #333);
410
+ border-radius: 12px;
411
+ box-shadow: 0 8px 32px rgba(0, 0, 0, 0.5);
412
+ display: flex;
413
+ flex-direction: column;
414
+ z-index: 1000;
415
+ }
416
+
417
+ .plugin-sandbox__header {
418
+ display: flex;
419
+ align-items: center;
420
+ justify-content: space-between;
421
+ padding: 12px 16px;
422
+ border-bottom: 1px solid var(--color-border, #333);
423
+ }
424
+
425
+ .plugin-sandbox__title {
426
+ margin: 0;
427
+ font-size: 16px;
428
+ font-weight: 600;
429
+ color: var(--color-text, #e8e8f0);
430
+ }
431
+
432
+ .plugin-sandbox__actions {
433
+ display: flex;
434
+ align-items: center;
435
+ gap: 12px;
436
+ }
437
+
438
+ .preview-mode-toggle {
439
+ display: flex;
440
+ background: rgba(255, 255, 255, 0.05);
441
+ border-radius: 6px;
442
+ padding: 2px;
443
+ }
444
+
445
+ .mode-btn {
446
+ padding: 4px 12px;
447
+ background: transparent;
448
+ border: none;
449
+ border-radius: 4px;
450
+ color: var(--color-text-secondary, #aaa);
451
+ font-size: 12px;
452
+ cursor: pointer;
453
+ transition: all 0.15s ease;
454
+ }
455
+
456
+ .mode-btn:hover {
457
+ color: var(--color-text, #e8e8f0);
458
+ }
459
+
460
+ .mode-btn.active {
461
+ background: rgba(168, 85, 247, 0.2);
462
+ color: #a855f7;
463
+ }
464
+
465
+ .plugin-sandbox__close {
466
+ padding: 6px 12px;
467
+ background: rgba(239, 68, 68, 0.2);
468
+ border: none;
469
+ border-radius: 4px;
470
+ color: #ef4444;
471
+ font-size: 12px;
472
+ cursor: pointer;
473
+ transition: all 0.15s ease;
474
+ }
475
+
476
+ .plugin-sandbox__close:hover {
477
+ background: rgba(239, 68, 68, 0.3);
478
+ }
479
+
480
+ .plugin-sandbox__content {
481
+ display: flex;
482
+ flex: 1;
483
+ overflow: hidden;
484
+ }
485
+
486
+ /* Plugin sidebar */
487
+ .plugin-sidebar {
488
+ width: 240px;
489
+ border-right: 1px solid var(--color-border, #333);
490
+ padding: 12px;
491
+ overflow-y: auto;
492
+ }
493
+
494
+ .plugin-sidebar__title {
495
+ margin: 0 0 12px;
496
+ font-size: 12px;
497
+ font-weight: 600;
498
+ color: var(--color-text-secondary, #aaa);
499
+ text-transform: uppercase;
500
+ }
501
+
502
+ .plugin-list {
503
+ display: flex;
504
+ flex-direction: column;
505
+ gap: 6px;
506
+ }
507
+
508
+ .plugin-item {
509
+ display: flex;
510
+ align-items: flex-start;
511
+ gap: 10px;
512
+ padding: 10px;
513
+ background: transparent;
514
+ border: 1px solid transparent;
515
+ border-radius: 8px;
516
+ text-align: left;
517
+ cursor: pointer;
518
+ transition: all 0.15s ease;
519
+ }
520
+
521
+ .plugin-item:hover {
522
+ background: rgba(255, 255, 255, 0.05);
523
+ border-color: var(--color-border, #333);
524
+ }
525
+
526
+ .plugin-item--selected {
527
+ background: rgba(168, 85, 247, 0.1);
528
+ border-color: rgba(168, 85, 247, 0.3);
529
+ }
530
+
531
+ .plugin-item:disabled {
532
+ opacity: 0.5;
533
+ cursor: not-allowed;
534
+ }
535
+
536
+ .plugin-item__icon {
537
+ display: flex;
538
+ align-items: center;
539
+ justify-content: center;
540
+ width: 32px;
541
+ height: 32px;
542
+ background: rgba(168, 85, 247, 0.2);
543
+ border-radius: 6px;
544
+ color: #a855f7;
545
+ font-weight: 600;
546
+ flex-shrink: 0;
547
+ }
548
+
549
+ .plugin-item__info {
550
+ display: flex;
551
+ flex-direction: column;
552
+ gap: 2px;
553
+ }
554
+
555
+ .plugin-item__name {
556
+ font-size: 13px;
557
+ font-weight: 500;
558
+ color: var(--color-text, #e8e8f0);
559
+ }
560
+
561
+ .plugin-item__desc {
562
+ font-size: 11px;
563
+ color: var(--color-text-muted, #888);
564
+ }
565
+
566
+ /* Preview area */
567
+ .preview-area {
568
+ flex: 1;
569
+ display: flex;
570
+ flex-direction: column;
571
+ overflow: hidden;
572
+ }
573
+
574
+ .preview-loading {
575
+ display: flex;
576
+ align-items: center;
577
+ justify-content: center;
578
+ gap: 8px;
579
+ height: 100%;
580
+ color: var(--color-text-secondary, #aaa);
581
+ }
582
+
583
+ .loading-spinner {
584
+ width: 20px;
585
+ height: 20px;
586
+ border: 2px solid rgba(168, 85, 247, 0.2);
587
+ border-top-color: #a855f7;
588
+ border-radius: 50%;
589
+ animation: spin 0.8s linear infinite;
590
+ }
591
+
592
+ @keyframes spin {
593
+ to {
594
+ transform: rotate(360deg);
595
+ }
596
+ }
597
+
598
+ .transform-info {
599
+ display: flex;
600
+ align-items: center;
601
+ gap: 12px;
602
+ padding: 8px 12px;
603
+ background: rgba(255, 255, 255, 0.03);
604
+ border-bottom: 1px solid var(--color-border, #333);
605
+ font-size: 12px;
606
+ }
607
+
608
+ .transform-plugin {
609
+ font-weight: 600;
610
+ color: #a855f7;
611
+ }
612
+
613
+ .transform-stats {
614
+ display: flex;
615
+ gap: 8px;
616
+ }
617
+
618
+ .stat {
619
+ padding: 2px 6px;
620
+ border-radius: 4px;
621
+ font-family: monospace;
622
+ font-size: 11px;
623
+ }
624
+
625
+ .stat--add {
626
+ background: rgba(34, 197, 94, 0.2);
627
+ color: #22c55e;
628
+ }
629
+
630
+ .stat--remove {
631
+ background: rgba(239, 68, 68, 0.2);
632
+ color: #ef4444;
633
+ }
634
+
635
+ .transform-time {
636
+ color: var(--color-text-muted, #888);
637
+ }
638
+
639
+ .transform-error {
640
+ color: #ef4444;
641
+ flex: 1;
642
+ }
643
+
644
+ .apply-btn {
645
+ margin-left: auto;
646
+ padding: 6px 16px;
647
+ background: rgba(34, 197, 94, 0.2);
648
+ border: none;
649
+ border-radius: 4px;
650
+ color: #22c55e;
651
+ font-size: 12px;
652
+ font-weight: 500;
653
+ cursor: pointer;
654
+ transition: all 0.15s ease;
655
+ }
656
+
657
+ .apply-btn:hover {
658
+ background: rgba(34, 197, 94, 0.3);
659
+ }
660
+
661
+ .reset-btn {
662
+ padding: 6px 12px;
663
+ background: rgba(255, 255, 255, 0.1);
664
+ border: none;
665
+ border-radius: 4px;
666
+ color: var(--color-text-secondary, #aaa);
667
+ font-size: 12px;
668
+ cursor: pointer;
669
+ transition: all 0.15s ease;
670
+ }
671
+
672
+ .reset-btn:hover {
673
+ background: rgba(255, 255, 255, 0.15);
674
+ }
675
+
676
+ .preview-content {
677
+ flex: 1;
678
+ overflow: auto;
679
+ padding: 12px;
680
+ }
681
+
682
+ .preview-empty {
683
+ display: flex;
684
+ flex-direction: column;
685
+ align-items: center;
686
+ justify-content: center;
687
+ height: 100%;
688
+ color: var(--color-text-secondary, #aaa);
689
+ text-align: center;
690
+ }
691
+
692
+ .preview-hint {
693
+ font-size: 12px;
694
+ color: var(--color-text-muted, #888);
695
+ margin-top: 8px;
696
+ }
697
+
698
+ .code-block {
699
+ margin: 0;
700
+ padding: 12px;
701
+ background: rgba(0, 0, 0, 0.3);
702
+ border-radius: 6px;
703
+ font-family: 'JetBrains Mono', 'Fira Code', monospace;
704
+ font-size: 13px;
705
+ line-height: 1.5;
706
+ color: var(--color-text, #e8e8f0);
707
+ overflow: auto;
708
+ white-space: pre;
709
+ }
710
+
711
+ /* Split view */
712
+ .split-view {
713
+ display: grid;
714
+ grid-template-columns: 1fr 1fr;
715
+ gap: 12px;
716
+ height: 100%;
717
+ }
718
+
719
+ .split-pane {
720
+ display: flex;
721
+ flex-direction: column;
722
+ overflow: hidden;
723
+ }
724
+
725
+ .pane-header {
726
+ padding: 6px 12px;
727
+ background: rgba(255, 255, 255, 0.05);
728
+ border-radius: 6px 6px 0 0;
729
+ font-size: 11px;
730
+ font-weight: 600;
731
+ color: var(--color-text-secondary, #aaa);
732
+ text-transform: uppercase;
733
+ }
734
+
735
+ .split-pane .code-block {
736
+ flex: 1;
737
+ border-radius: 0 0 6px 6px;
738
+ }
739
+
740
+ /* Diff view */
741
+ .diff-view {
742
+ font-family: 'JetBrains Mono', 'Fira Code', monospace;
743
+ font-size: 13px;
744
+ line-height: 1.5;
745
+ }
746
+
747
+ .diff-line {
748
+ display: flex;
749
+ padding: 0 8px;
750
+ }
751
+
752
+ .diff-line--add {
753
+ background: rgba(34, 197, 94, 0.1);
754
+ }
755
+
756
+ .diff-line--remove {
757
+ background: rgba(239, 68, 68, 0.1);
758
+ }
759
+
760
+ .diff-line__num {
761
+ width: 40px;
762
+ color: var(--color-text-muted, #888);
763
+ text-align: right;
764
+ padding-right: 8px;
765
+ user-select: none;
766
+ }
767
+
768
+ .diff-line__sign {
769
+ width: 16px;
770
+ color: var(--color-text-muted, #888);
771
+ }
772
+
773
+ .diff-line--add .diff-line__sign {
774
+ color: #22c55e;
775
+ }
776
+
777
+ .diff-line--remove .diff-line__sign {
778
+ color: #ef4444;
779
+ }
780
+
781
+ .diff-line__content {
782
+ flex: 1;
783
+ white-space: pre;
784
+ }
785
+
786
+ .diff-line--add .diff-line__content {
787
+ color: #22c55e;
788
+ }
789
+
790
+ .diff-line--remove .diff-line__content {
791
+ color: #ef4444;
792
+ }
793
+ </style>