@termaxjs/editor 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (215) hide show
  1. package/LICENSE +201 -0
  2. package/README.md +85 -0
  3. package/dist/TermaxEditor.d.ts +74 -0
  4. package/dist/TermaxEditor.d.ts.map +1 -0
  5. package/dist/TermaxEditor.js +728 -0
  6. package/dist/TermaxEditor.js.map +1 -0
  7. package/dist/adapter.d.ts +2 -0
  8. package/dist/adapter.d.ts.map +1 -0
  9. package/dist/adapter.js +2 -0
  10. package/dist/adapter.js.map +1 -0
  11. package/dist/ai/GhostTextManager.d.ts +34 -0
  12. package/dist/ai/GhostTextManager.d.ts.map +1 -0
  13. package/dist/ai/GhostTextManager.js +116 -0
  14. package/dist/ai/GhostTextManager.js.map +1 -0
  15. package/dist/ai/StreamingDiffApplier.d.ts +28 -0
  16. package/dist/ai/StreamingDiffApplier.d.ts.map +1 -0
  17. package/dist/ai/StreamingDiffApplier.js +61 -0
  18. package/dist/ai/StreamingDiffApplier.js.map +1 -0
  19. package/dist/canvas.d.ts +2 -0
  20. package/dist/canvas.d.ts.map +1 -0
  21. package/dist/canvas.js +2 -0
  22. package/dist/canvas.js.map +1 -0
  23. package/dist/codelens/CodeLensProvider.d.ts +22 -0
  24. package/dist/codelens/CodeLensProvider.d.ts.map +1 -0
  25. package/dist/codelens/CodeLensProvider.js +36 -0
  26. package/dist/codelens/CodeLensProvider.js.map +1 -0
  27. package/dist/core.d.ts +2 -0
  28. package/dist/core.d.ts.map +1 -0
  29. package/dist/core.js +2 -0
  30. package/dist/core.js.map +1 -0
  31. package/dist/diff/ConflictResolver.d.ts +27 -0
  32. package/dist/diff/ConflictResolver.d.ts.map +1 -0
  33. package/dist/diff/ConflictResolver.js +88 -0
  34. package/dist/diff/ConflictResolver.js.map +1 -0
  35. package/dist/diff/DiffEditor.d.ts +18 -0
  36. package/dist/diff/DiffEditor.d.ts.map +1 -0
  37. package/dist/diff/DiffEditor.js +212 -0
  38. package/dist/diff/DiffEditor.js.map +1 -0
  39. package/dist/diff/InlineDiffModel.d.ts +18 -0
  40. package/dist/diff/InlineDiffModel.d.ts.map +1 -0
  41. package/dist/diff/InlineDiffModel.js +78 -0
  42. package/dist/diff/InlineDiffModel.js.map +1 -0
  43. package/dist/element/TermaxEditorElement.d.ts +28 -0
  44. package/dist/element/TermaxEditorElement.d.ts.map +1 -0
  45. package/dist/element/TermaxEditorElement.js +123 -0
  46. package/dist/element/TermaxEditorElement.js.map +1 -0
  47. package/dist/fold/computeFoldRanges.d.ts +8 -0
  48. package/dist/fold/computeFoldRanges.d.ts.map +1 -0
  49. package/dist/fold/computeFoldRanges.js +109 -0
  50. package/dist/fold/computeFoldRanges.js.map +1 -0
  51. package/dist/format/formatter.d.ts +5 -0
  52. package/dist/format/formatter.d.ts.map +1 -0
  53. package/dist/format/formatter.js +89 -0
  54. package/dist/format/formatter.js.map +1 -0
  55. package/dist/git/GitGutterManager.d.ts +17 -0
  56. package/dist/git/GitGutterManager.d.ts.map +1 -0
  57. package/dist/git/GitGutterManager.js +50 -0
  58. package/dist/git/GitGutterManager.js.map +1 -0
  59. package/dist/git/InlineBlameManager.d.ts +18 -0
  60. package/dist/git/InlineBlameManager.d.ts.map +1 -0
  61. package/dist/git/InlineBlameManager.js +33 -0
  62. package/dist/git/InlineBlameManager.js.map +1 -0
  63. package/dist/gutter/FoldGutter.d.ts +12 -0
  64. package/dist/gutter/FoldGutter.d.ts.map +1 -0
  65. package/dist/gutter/FoldGutter.js +51 -0
  66. package/dist/gutter/FoldGutter.js.map +1 -0
  67. package/dist/gutter/LineNumbers.d.ts +11 -0
  68. package/dist/gutter/LineNumbers.d.ts.map +1 -0
  69. package/dist/gutter/LineNumbers.js +71 -0
  70. package/dist/gutter/LineNumbers.js.map +1 -0
  71. package/dist/highlight/microTokenizer.d.ts +20 -0
  72. package/dist/highlight/microTokenizer.d.ts.map +1 -0
  73. package/dist/highlight/microTokenizer.js +951 -0
  74. package/dist/highlight/microTokenizer.js.map +1 -0
  75. package/dist/index.d.ts +46 -0
  76. package/dist/index.d.ts.map +1 -0
  77. package/dist/index.js +46 -0
  78. package/dist/index.js.map +1 -0
  79. package/dist/input/KeymapPresets.d.ts +10 -0
  80. package/dist/input/KeymapPresets.d.ts.map +1 -0
  81. package/dist/input/KeymapPresets.js +46 -0
  82. package/dist/input/KeymapPresets.js.map +1 -0
  83. package/dist/input/OffscreenInput.d.ts +27 -0
  84. package/dist/input/OffscreenInput.d.ts.map +1 -0
  85. package/dist/input/OffscreenInput.js +367 -0
  86. package/dist/input/OffscreenInput.js.map +1 -0
  87. package/dist/languages/GrammarRegistry.d.ts +55 -0
  88. package/dist/languages/GrammarRegistry.d.ts.map +1 -0
  89. package/dist/languages/GrammarRegistry.js +80 -0
  90. package/dist/languages/GrammarRegistry.js.map +1 -0
  91. package/dist/languages/LanguageAdapter.d.ts +11 -0
  92. package/dist/languages/LanguageAdapter.d.ts.map +1 -0
  93. package/dist/languages/LanguageAdapter.js +47 -0
  94. package/dist/languages/LanguageAdapter.js.map +1 -0
  95. package/dist/languages/TreeSitterAdapter.d.ts +29 -0
  96. package/dist/languages/TreeSitterAdapter.d.ts.map +1 -0
  97. package/dist/languages/TreeSitterAdapter.js +99 -0
  98. package/dist/languages/TreeSitterAdapter.js.map +1 -0
  99. package/dist/languages/index.d.ts +16 -0
  100. package/dist/languages/index.d.ts.map +1 -0
  101. package/dist/languages/index.js +163 -0
  102. package/dist/languages/index.js.map +1 -0
  103. package/dist/lsp/InlayHintProvider.d.ts +18 -0
  104. package/dist/lsp/InlayHintProvider.d.ts.map +1 -0
  105. package/dist/lsp/InlayHintProvider.js +26 -0
  106. package/dist/lsp/InlayHintProvider.js.map +1 -0
  107. package/dist/lsp/LspClient.d.ts +73 -0
  108. package/dist/lsp/LspClient.d.ts.map +1 -0
  109. package/dist/lsp/LspClient.js +261 -0
  110. package/dist/lsp/LspClient.js.map +1 -0
  111. package/dist/lsp/SemanticTokensDecoder.d.ts +26 -0
  112. package/dist/lsp/SemanticTokensDecoder.d.ts.map +1 -0
  113. package/dist/lsp/SemanticTokensDecoder.js +88 -0
  114. package/dist/lsp/SemanticTokensDecoder.js.map +1 -0
  115. package/dist/lsp/WorkspaceSymbolIndex.d.ts +32 -0
  116. package/dist/lsp/WorkspaceSymbolIndex.d.ts.map +1 -0
  117. package/dist/lsp/WorkspaceSymbolIndex.js +73 -0
  118. package/dist/lsp/WorkspaceSymbolIndex.js.map +1 -0
  119. package/dist/minimap/Minimap.d.ts +24 -0
  120. package/dist/minimap/Minimap.d.ts.map +1 -0
  121. package/dist/minimap/Minimap.js +31 -0
  122. package/dist/minimap/Minimap.js.map +1 -0
  123. package/dist/minimap/useMinimap.d.ts +75 -0
  124. package/dist/minimap/useMinimap.d.ts.map +1 -0
  125. package/dist/minimap/useMinimap.js +179 -0
  126. package/dist/minimap/useMinimap.js.map +1 -0
  127. package/dist/navigation/StickyScrollHeader.d.ts +16 -0
  128. package/dist/navigation/StickyScrollHeader.d.ts.map +1 -0
  129. package/dist/navigation/StickyScrollHeader.js +49 -0
  130. package/dist/navigation/StickyScrollHeader.js.map +1 -0
  131. package/dist/navigation/StickyScrollManager.d.ts +18 -0
  132. package/dist/navigation/StickyScrollManager.d.ts.map +1 -0
  133. package/dist/navigation/StickyScrollManager.js +32 -0
  134. package/dist/navigation/StickyScrollManager.js.map +1 -0
  135. package/dist/overlay/CompletionMenu.d.ts +15 -0
  136. package/dist/overlay/CompletionMenu.d.ts.map +1 -0
  137. package/dist/overlay/CompletionMenu.js +90 -0
  138. package/dist/overlay/CompletionMenu.js.map +1 -0
  139. package/dist/overlay/FindReplace.d.ts +6 -0
  140. package/dist/overlay/FindReplace.d.ts.map +1 -0
  141. package/dist/overlay/FindReplace.js +278 -0
  142. package/dist/overlay/FindReplace.js.map +1 -0
  143. package/dist/overlay/HoverTooltip.d.ts +12 -0
  144. package/dist/overlay/HoverTooltip.d.ts.map +1 -0
  145. package/dist/overlay/HoverTooltip.js +67 -0
  146. package/dist/overlay/HoverTooltip.js.map +1 -0
  147. package/dist/overlay/RemoteCursorsOverlay.d.ts +15 -0
  148. package/dist/overlay/RemoteCursorsOverlay.d.ts.map +1 -0
  149. package/dist/overlay/RemoteCursorsOverlay.js +50 -0
  150. package/dist/overlay/RemoteCursorsOverlay.js.map +1 -0
  151. package/dist/overlay/SignatureHelpTooltip.d.ts +11 -0
  152. package/dist/overlay/SignatureHelpTooltip.d.ts.map +1 -0
  153. package/dist/overlay/SignatureHelpTooltip.js +36 -0
  154. package/dist/overlay/SignatureHelpTooltip.js.map +1 -0
  155. package/dist/pairs/SelectionSurround.d.ts +14 -0
  156. package/dist/pairs/SelectionSurround.d.ts.map +1 -0
  157. package/dist/pairs/SelectionSurround.js +29 -0
  158. package/dist/pairs/SelectionSurround.js.map +1 -0
  159. package/dist/pairs/pairMatching.d.ts +6 -0
  160. package/dist/pairs/pairMatching.d.ts.map +1 -0
  161. package/dist/pairs/pairMatching.js +169 -0
  162. package/dist/pairs/pairMatching.js.map +1 -0
  163. package/dist/plugin/ViewPlugin.d.ts +20 -0
  164. package/dist/plugin/ViewPlugin.d.ts.map +1 -0
  165. package/dist/plugin/ViewPlugin.js +17 -0
  166. package/dist/plugin/ViewPlugin.js.map +1 -0
  167. package/dist/react.d.ts +2 -0
  168. package/dist/react.d.ts.map +1 -0
  169. package/dist/react.js +2 -0
  170. package/dist/react.js.map +1 -0
  171. package/dist/renderer/CanvasViewport.d.ts +23 -0
  172. package/dist/renderer/CanvasViewport.d.ts.map +1 -0
  173. package/dist/renderer/CanvasViewport.js +134 -0
  174. package/dist/renderer/CanvasViewport.js.map +1 -0
  175. package/dist/renderer/VirtualizedLines.d.ts +30 -0
  176. package/dist/renderer/VirtualizedLines.d.ts.map +1 -0
  177. package/dist/renderer/VirtualizedLines.js +427 -0
  178. package/dist/renderer/VirtualizedLines.js.map +1 -0
  179. package/dist/renderer/windowing.d.ts +33 -0
  180. package/dist/renderer/windowing.d.ts.map +1 -0
  181. package/dist/renderer/windowing.js +50 -0
  182. package/dist/renderer/windowing.js.map +1 -0
  183. package/dist/snippet/SnippetEngine.d.ts +31 -0
  184. package/dist/snippet/SnippetEngine.d.ts.map +1 -0
  185. package/dist/snippet/SnippetEngine.js +119 -0
  186. package/dist/snippet/SnippetEngine.js.map +1 -0
  187. package/dist/themes/VSCodeThemeConverter.d.ts +24 -0
  188. package/dist/themes/VSCodeThemeConverter.d.ts.map +1 -0
  189. package/dist/themes/VSCodeThemeConverter.js +118 -0
  190. package/dist/themes/VSCodeThemeConverter.js.map +1 -0
  191. package/dist/themes/index.d.ts +9 -0
  192. package/dist/themes/index.d.ts.map +1 -0
  193. package/dist/themes/index.js +128 -0
  194. package/dist/themes/index.js.map +1 -0
  195. package/dist/vim/VimState.d.ts +32 -0
  196. package/dist/vim/VimState.d.ts.map +1 -0
  197. package/dist/vim/VimState.js +276 -0
  198. package/dist/vim/VimState.js.map +1 -0
  199. package/dist/vim/VimStatusBar.d.ts +9 -0
  200. package/dist/vim/VimStatusBar.d.ts.map +1 -0
  201. package/dist/vim/VimStatusBar.js +36 -0
  202. package/dist/vim/VimStatusBar.js.map +1 -0
  203. package/dist/widgets/ColorPickerWidget.d.ts +13 -0
  204. package/dist/widgets/ColorPickerWidget.d.ts.map +1 -0
  205. package/dist/widgets/ColorPickerWidget.js +49 -0
  206. package/dist/widgets/ColorPickerWidget.js.map +1 -0
  207. package/dist/worker/WorkerBridge.d.ts +36 -0
  208. package/dist/worker/WorkerBridge.d.ts.map +1 -0
  209. package/dist/worker/WorkerBridge.js +103 -0
  210. package/dist/worker/WorkerBridge.js.map +1 -0
  211. package/dist/workspace/WorkspaceTabManager.d.ts +25 -0
  212. package/dist/workspace/WorkspaceTabManager.d.ts.map +1 -0
  213. package/dist/workspace/WorkspaceTabManager.js +71 -0
  214. package/dist/workspace/WorkspaceTabManager.js.map +1 -0
  215. package/package.json +78 -0
@@ -0,0 +1,728 @@
1
+ import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { useRef, useEffect, useState, useMemo, useId, useCallback, useImperativeHandle, forwardRef, } from "react";
3
+ import { EditorProvider, useEditorContext } from "@termaxjs/editor-react";
4
+ import { isPositionInRange, getWordRangeAt, getTextInRange, } from "@termaxjs/editor-core";
5
+ import { measureMonospaceFont } from "@termaxjs/editor-canvas";
6
+ import { OffscreenInput } from "./input/OffscreenInput.js";
7
+ import { VirtualizedLines } from "./renderer/VirtualizedLines.js";
8
+ import { computeWindowedRange, measureLongestLine } from "./renderer/windowing.js";
9
+ import { CanvasViewport } from "./renderer/CanvasViewport.js";
10
+ import { Minimap } from "./minimap/Minimap.js";
11
+ import { FindReplace } from "./overlay/FindReplace.js";
12
+ import { HoverTooltip } from "./overlay/HoverTooltip.js";
13
+ import { CompletionMenu } from "./overlay/CompletionMenu.js";
14
+ import { SignatureHelpTooltip } from "./overlay/SignatureHelpTooltip.js";
15
+ import { THEMES, githubDark } from "./themes/index.js";
16
+ import { formatCode } from "./format/formatter.js";
17
+ import { detectLanguageFromPath, getDefaultLanguageAdapter } from "./languages/index.js";
18
+ import { FoldGutter, computeFoldRanges } from "./gutter/FoldGutter.js";
19
+ import { LineNumbers } from "./gutter/LineNumbers.js";
20
+ import { filterAndSortCompletions, parseSnippet } from "./snippet/SnippetEngine.js";
21
+ import { VimEngine } from "./vim/VimState.js";
22
+ import { VimStatusBar } from "./vim/VimStatusBar.js";
23
+ import { StickyScrollHeader } from "./navigation/StickyScrollHeader.js";
24
+ import { GitGutterManager } from "./git/GitGutterManager.js";
25
+ const InnerEditor = forwardRef(function InnerEditor({ language, filePath, languageAdapter, rendererMode, readOnly = false, lineHeight, charWidth: fallbackCharWidth, showLineNumbers, foldable, showMinimap, minimapPosition = "right", minimapWidth = 70, renderMinimap, theme, diagnostics, signatureHelp, vimMode = false, className, style, stickyScroll = true, baseContent, gitGutterMarkers, blameManager, codeLensProvider, showColorSwatches = true, ghostText: propsGhostText, onAcceptGhostText, onDismissGhostText, streamingDiffChunks, onSnapshot, }, ref) {
26
+ const outerRef = useRef(null);
27
+ const scrollRef = useRef(null);
28
+ const inputRef = useRef(null);
29
+ const measureRef = useRef(null);
30
+ const vimEngine = useMemo(() => new VimEngine(), []);
31
+ const [vimState, setVimState] = useState({
32
+ mode: "NORMAL",
33
+ buffer: "",
34
+ ex: "",
35
+ });
36
+ const [exactCharWidth, setExactCharWidth] = useState(() => {
37
+ if (fallbackCharWidth)
38
+ return fallbackCharWidth;
39
+ if (typeof document !== "undefined") {
40
+ const m = measureMonospaceFont("monospace", 13);
41
+ if (m.charWidth > 0)
42
+ return m.charWidth;
43
+ }
44
+ return 7.8;
45
+ });
46
+ const { lines, setContent, getContent, undo, redo, insertText, deleteSelectionOrChar, enter, setCursor, setSelection, addCursor, applyCodeAction, cursor, selection, selections, snapshot, ghostText, setGhostText, acceptGhostText, } = useEditorContext();
47
+ useEffect(() => {
48
+ if (propsGhostText !== undefined) {
49
+ setGhostText(propsGhostText);
50
+ }
51
+ }, [propsGhostText, setGhostText]);
52
+ const onSnapshotRef = useRef(onSnapshot);
53
+ onSnapshotRef.current = onSnapshot;
54
+ useEffect(() => {
55
+ onSnapshotRef.current?.(snapshot);
56
+ }, [snapshot]);
57
+ const [foldedLines, setFoldedLines] = useState(new Set());
58
+ const [showFind, setShowFind] = useState(false);
59
+ // Active language adapter
60
+ const activeLangAdapter = useMemo(() => {
61
+ return languageAdapter || getDefaultLanguageAdapter();
62
+ }, [languageAdapter]);
63
+ const activeDiagnostic = useMemo(() => {
64
+ if (!diagnostics || diagnostics.length === 0)
65
+ return null;
66
+ return diagnostics.find((d) => isPositionInRange(cursor, d.range)) ?? null;
67
+ }, [diagnostics, cursor]);
68
+ const [completionItems, setCompletionItems] = useState([]);
69
+ const [completionIndex, setCompletionIndex] = useState(0);
70
+ const [showCompletions, setShowCompletions] = useState(false);
71
+ const listboxId = useId();
72
+ const completionsVisible = showCompletions && completionItems.length > 0;
73
+ const activeOptionId = `${listboxId}-option-${completionIndex}`;
74
+ useEffect(() => {
75
+ if (!activeLangAdapter.provideCompletionItems) {
76
+ setShowCompletions(false);
77
+ return;
78
+ }
79
+ const curLine = lines[cursor.line] ?? "";
80
+ const wordRange = getWordRangeAt(curLine, cursor.line, cursor.column);
81
+ const prefix = curLine.slice(wordRange.start.column, cursor.column);
82
+ if (prefix.length >= 1) {
83
+ void activeLangAdapter.provideCompletionItems(language, cursor, prefix).then((items) => {
84
+ if (items && items.length > 0) {
85
+ const filtered = filterAndSortCompletions(prefix, items);
86
+ if (filtered.length > 0) {
87
+ setCompletionItems(filtered);
88
+ setCompletionIndex(0);
89
+ setShowCompletions(true);
90
+ return;
91
+ }
92
+ }
93
+ setShowCompletions(false);
94
+ });
95
+ }
96
+ else {
97
+ setShowCompletions(false);
98
+ }
99
+ }, [cursor, lines, activeLangAdapter, language]);
100
+ const handleAcceptCompletion = useCallback((item) => {
101
+ const rawInsert = item.insertText || item.label;
102
+ const curLine = lines[cursor.line] ?? "";
103
+ const wordRange = getWordRangeAt(curLine, cursor.line, cursor.column);
104
+ setSelection({ start: wordRange.start, end: cursor });
105
+ // If snippet template
106
+ if (item.kind === "snippet" || rawInsert.includes("$")) {
107
+ const parsed = parseSnippet(rawInsert);
108
+ insertText(parsed.text);
109
+ }
110
+ else {
111
+ insertText(rawInsert);
112
+ }
113
+ setShowCompletions(false);
114
+ }, [cursor, lines, setSelection, insertText]);
115
+ const handleVimKeyDown = useCallback((e) => {
116
+ if (!vimMode)
117
+ return false;
118
+ const ctx = {
119
+ lines,
120
+ cursor,
121
+ selection,
122
+ selections,
123
+ insertText,
124
+ deleteSelectionOrChar,
125
+ enter,
126
+ setCursor,
127
+ setSelection,
128
+ setSelections: (sels) => {
129
+ if (sels && sels.length > 0) {
130
+ setSelection({ start: sels[0].anchor, end: sels[0].head });
131
+ }
132
+ },
133
+ setContent,
134
+ undo,
135
+ redo,
136
+ };
137
+ const handled = vimEngine.handleKey(e.key, ctx, {
138
+ ctrlKey: e.ctrlKey,
139
+ metaKey: e.metaKey,
140
+ preventDefault: () => e.preventDefault(),
141
+ });
142
+ setVimState({
143
+ mode: vimEngine.mode,
144
+ buffer: vimEngine.commandBuffer,
145
+ ex: vimEngine.exInput,
146
+ });
147
+ return handled;
148
+ }, [
149
+ vimMode,
150
+ vimEngine,
151
+ lines,
152
+ cursor,
153
+ selection,
154
+ selections,
155
+ insertText,
156
+ deleteSelectionOrChar,
157
+ enter,
158
+ setCursor,
159
+ setSelection,
160
+ setContent,
161
+ undo,
162
+ redo,
163
+ ]);
164
+ // Measure exact monospace character width
165
+ useEffect(() => {
166
+ if (typeof document !== "undefined") {
167
+ const m = measureMonospaceFont("monospace", 13);
168
+ if (m.charWidth > 0) {
169
+ setExactCharWidth(m.charWidth);
170
+ return;
171
+ }
172
+ }
173
+ if (measureRef.current) {
174
+ const rect = measureRef.current.getBoundingClientRect();
175
+ if (rect.width > 0) {
176
+ setExactCharWidth(rect.width / 10);
177
+ }
178
+ }
179
+ }, []);
180
+ const activeTheme = typeof theme === "string"
181
+ ? THEMES[theme] || (theme === "light" ? THEMES.githubLight : githubDark)
182
+ : theme || githubDark;
183
+ const focusInput = useCallback(() => {
184
+ inputRef.current?.focus();
185
+ }, []);
186
+ const isDraggingRef = useRef(false);
187
+ const dragStartRef = useRef(null);
188
+ const linesRef = useRef(lines);
189
+ linesRef.current = lines;
190
+ const cursorRef = useRef(cursor);
191
+ cursorRef.current = cursor;
192
+ const charWidthRef = useRef(exactCharWidth);
193
+ charWidthRef.current = exactCharWidth;
194
+ const lineHeightRef = useRef(lineHeight);
195
+ lineHeightRef.current = lineHeight;
196
+ const computeCanvasPosition = useCallback((clientX, clientY) => {
197
+ const scrollEl = scrollRef.current;
198
+ if (!scrollEl)
199
+ return { line: 0, column: 0 };
200
+ const rect = scrollEl.getBoundingClientRect();
201
+ const scrollTop = scrollEl.scrollTop;
202
+ const scrollLeft = scrollEl.scrollLeft;
203
+ const currentLines = linesRef.current;
204
+ const currentLineHeight = lineHeightRef.current;
205
+ const currentCharWidth = charWidthRef.current;
206
+ const maxDigits = Math.max(2, String(currentLines.length).length);
207
+ const gutterWidth = showLineNumbers ? Math.round(maxDigits * currentCharWidth + 24) : 0;
208
+ const textStartX = gutterWidth + 8;
209
+ const clickX = clientX - rect.left - textStartX + scrollLeft;
210
+ const clickY = clientY - rect.top + scrollTop;
211
+ const lineIdx = Math.max(0, Math.min(currentLines.length - 1, Math.floor(clickY / currentLineHeight)));
212
+ const lineText = currentLines[lineIdx] ?? "";
213
+ const colIdx = clickX <= 0
214
+ ? 0
215
+ : Math.max(0, Math.min(lineText.length, Math.round(clickX / currentCharWidth)));
216
+ return { line: lineIdx, column: colIdx };
217
+ }, [showLineNumbers]);
218
+ const handleCanvasMouseDown = (e) => {
219
+ if (e.button !== 0)
220
+ return;
221
+ const scrollEl = scrollRef.current;
222
+ if (!scrollEl)
223
+ return;
224
+ const rect = scrollEl.getBoundingClientRect();
225
+ // Ignore clicks on native scrollbars
226
+ if (e.clientX >= rect.left + scrollEl.clientWidth ||
227
+ e.clientY >= rect.top + scrollEl.clientHeight) {
228
+ return;
229
+ }
230
+ e.preventDefault();
231
+ focusInput();
232
+ const pos = computeCanvasPosition(e.clientX, e.clientY);
233
+ if (e.altKey) {
234
+ isDraggingRef.current = false;
235
+ dragStartRef.current = null;
236
+ addCursor(pos);
237
+ return;
238
+ }
239
+ if (e.shiftKey && cursorRef.current) {
240
+ isDraggingRef.current = false;
241
+ dragStartRef.current = null;
242
+ setCursor(pos, true);
243
+ setSelection({ start: cursorRef.current, end: pos });
244
+ }
245
+ else if (e.detail === 2) {
246
+ isDraggingRef.current = false;
247
+ dragStartRef.current = null;
248
+ // Double-click word selection
249
+ const lineText = linesRef.current[pos.line] ?? "";
250
+ const wordRange = getWordRangeAt(lineText, pos.line, pos.column);
251
+ setCursor(wordRange.end, true);
252
+ setSelection(wordRange);
253
+ }
254
+ else if (e.detail === 3) {
255
+ isDraggingRef.current = false;
256
+ dragStartRef.current = null;
257
+ // Triple-click line selection
258
+ const lineText = linesRef.current[pos.line] ?? "";
259
+ setCursor({ line: pos.line, column: lineText.length }, true);
260
+ setSelection({
261
+ start: { line: pos.line, column: 0 },
262
+ end: { line: pos.line, column: lineText.length },
263
+ });
264
+ }
265
+ else {
266
+ isDraggingRef.current = true;
267
+ dragStartRef.current = pos;
268
+ setSelection(null);
269
+ setCursor(pos);
270
+ }
271
+ };
272
+ useEffect(() => {
273
+ const handleMouseMove = (e) => {
274
+ if (!isDraggingRef.current || !dragStartRef.current)
275
+ return;
276
+ e.preventDefault();
277
+ const scrollEl = scrollRef.current;
278
+ if (scrollEl) {
279
+ const rect = scrollEl.getBoundingClientRect();
280
+ const SCROLL_MARGIN = 20;
281
+ const SCROLL_SPEED = 15;
282
+ if (e.clientY < rect.top + SCROLL_MARGIN && scrollEl.scrollTop > 0) {
283
+ scrollEl.scrollTop -= SCROLL_SPEED;
284
+ }
285
+ else if (e.clientY > rect.bottom - SCROLL_MARGIN) {
286
+ scrollEl.scrollTop += SCROLL_SPEED;
287
+ }
288
+ }
289
+ const pos = computeCanvasPosition(e.clientX, e.clientY);
290
+ if (pos.line === dragStartRef.current.line && pos.column === dragStartRef.current.column) {
291
+ setSelection(null);
292
+ setCursor(pos);
293
+ }
294
+ else {
295
+ setCursor(pos, true);
296
+ setSelection({ start: dragStartRef.current, end: pos });
297
+ }
298
+ };
299
+ const handleMouseUp = () => {
300
+ isDraggingRef.current = false;
301
+ dragStartRef.current = null;
302
+ };
303
+ window.addEventListener("mousemove", handleMouseMove);
304
+ window.addEventListener("mouseup", handleMouseUp);
305
+ return () => {
306
+ window.removeEventListener("mousemove", handleMouseMove);
307
+ window.removeEventListener("mouseup", handleMouseUp);
308
+ };
309
+ }, [computeCanvasPosition, setCursor, setSelection]);
310
+ const scrollToScrollTop = useCallback((targetTop) => {
311
+ if (scrollRef.current) {
312
+ scrollRef.current.scrollTop = targetTop;
313
+ }
314
+ }, []);
315
+ const scrollToLine = useCallback((lineIdx) => {
316
+ scrollToScrollTop(lineIdx * lineHeight);
317
+ }, [scrollToScrollTop, lineHeight]);
318
+ const handleToggleFold = (lineIdx) => {
319
+ setFoldedLines((prev) => {
320
+ const next = new Set(prev);
321
+ if (next.has(lineIdx))
322
+ next.delete(lineIdx);
323
+ else
324
+ next.add(lineIdx);
325
+ return next;
326
+ });
327
+ };
328
+ const formatDocument = useCallback(async () => {
329
+ if (readOnly)
330
+ return;
331
+ const currentText = getContent();
332
+ const formatted = languageAdapter?.formatDocument
333
+ ? await languageAdapter.formatDocument(language, currentText)
334
+ : await formatCode(currentText, language);
335
+ if (formatted !== currentText) {
336
+ setContent(formatted);
337
+ }
338
+ }, [getContent, language, languageAdapter, setContent, readOnly]);
339
+ const [searchQuery, setSearchQuery] = useState("");
340
+ const [searchMatchIndex, setSearchMatchIndex] = useState(0);
341
+ const searchMatches = useMemo(() => {
342
+ if (!searchQuery)
343
+ return [];
344
+ const results = [];
345
+ try {
346
+ const escaped = searchQuery.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
347
+ const regex = new RegExp(escaped, "gi");
348
+ lines.forEach((lineText, lineIdx) => {
349
+ for (;;) {
350
+ const match = regex.exec(lineText);
351
+ if (match === null)
352
+ break;
353
+ results.push({
354
+ line: lineIdx,
355
+ column: match.index,
356
+ length: match[0].length,
357
+ });
358
+ if (!regex.global)
359
+ break;
360
+ }
361
+ });
362
+ }
363
+ catch {
364
+ // Ignore regex errors
365
+ }
366
+ return results;
367
+ }, [lines, searchQuery]);
368
+ const goToSearchMatch = useCallback((idx) => {
369
+ if (searchMatches.length === 0)
370
+ return;
371
+ const bounded = (idx + searchMatches.length) % searchMatches.length;
372
+ setSearchMatchIndex(bounded);
373
+ const m = searchMatches[bounded];
374
+ if (!m)
375
+ return;
376
+ const start = { line: m.line, column: m.column };
377
+ const end = { line: m.line, column: m.column + m.length };
378
+ setCursor(end);
379
+ setSelection({ start, end });
380
+ scrollToLine(m.line);
381
+ }, [searchMatches, setCursor, setSelection, scrollToLine]);
382
+ useImperativeHandle(ref, () => ({
383
+ focus: focusInput,
384
+ format: formatDocument,
385
+ getValue: getContent,
386
+ setValue: (val) => {
387
+ if (!readOnly)
388
+ setContent(val);
389
+ },
390
+ undo: () => {
391
+ if (!readOnly)
392
+ undo();
393
+ },
394
+ redo: () => {
395
+ if (!readOnly)
396
+ redo();
397
+ },
398
+ gotoLine: (line) => {
399
+ setCursor({ line: Math.max(0, line - 1), column: 0 });
400
+ scrollToLine(line - 1);
401
+ },
402
+ find: (q) => {
403
+ setSearchQuery(q);
404
+ setSearchMatchIndex(0);
405
+ if (q) {
406
+ const escaped = q.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
407
+ const regex = new RegExp(escaped, "gi");
408
+ for (let lineIdx = 0; lineIdx < lines.length; lineIdx++) {
409
+ const m = regex.exec(lines[lineIdx] ?? "");
410
+ if (m) {
411
+ const start = { line: lineIdx, column: m.index };
412
+ const end = { line: lineIdx, column: m.index + m[0].length };
413
+ setCursor(end);
414
+ setSelection({ start, end });
415
+ scrollToLine(lineIdx);
416
+ break;
417
+ }
418
+ }
419
+ }
420
+ },
421
+ findNext: () => {
422
+ goToSearchMatch(searchMatchIndex + 1);
423
+ },
424
+ findPrevious: () => {
425
+ goToSearchMatch(searchMatchIndex - 1);
426
+ },
427
+ setQuery: (q) => {
428
+ setSearchQuery(q);
429
+ },
430
+ clearQuery: () => {
431
+ setSearchQuery("");
432
+ },
433
+ hasSelection: () => {
434
+ if (!selection)
435
+ return false;
436
+ const { start, end } = selection;
437
+ return start.line !== end.line || start.column !== end.column;
438
+ },
439
+ getSelection: () => {
440
+ return getTextInRange(lines, selection);
441
+ },
442
+ setGhostText: (ghost) => {
443
+ setGhostText(ghost);
444
+ },
445
+ acceptGhostText: (mode = "full") => {
446
+ acceptGhostText(mode);
447
+ onAcceptGhostText?.(mode);
448
+ },
449
+ dismissGhostText: () => {
450
+ setGhostText(null);
451
+ onDismissGhostText?.();
452
+ },
453
+ }), [
454
+ focusInput,
455
+ formatDocument,
456
+ getContent,
457
+ setContent,
458
+ undo,
459
+ redo,
460
+ setCursor,
461
+ setSelection,
462
+ readOnly,
463
+ lines,
464
+ selection,
465
+ searchMatchIndex,
466
+ goToSearchMatch,
467
+ scrollToLine,
468
+ setGhostText,
469
+ acceptGhostText,
470
+ onAcceptGhostText,
471
+ onDismissGhostText,
472
+ ]);
473
+ const handleKeyDown = (e) => {
474
+ // Intercept Tab / Escape for active AI Ghost Text
475
+ if (ghostText) {
476
+ if (e.key === "Tab") {
477
+ e.preventDefault();
478
+ acceptGhostText("full");
479
+ onAcceptGhostText?.("full");
480
+ return;
481
+ }
482
+ if (e.key === "Escape") {
483
+ e.preventDefault();
484
+ setGhostText(null);
485
+ onDismissGhostText?.();
486
+ return;
487
+ }
488
+ }
489
+ // Find shortcut (Cmd+F / Ctrl+F)
490
+ if ((e.metaKey || e.ctrlKey) && (e.key === "f" || e.key === "F")) {
491
+ e.preventDefault();
492
+ setShowFind((prev) => !prev);
493
+ return;
494
+ }
495
+ // Format Document shortcut (Alt+Shift+F or Cmd+Shift+I)
496
+ if ((e.altKey && e.shiftKey && (e.key === "f" || e.key === "F")) ||
497
+ (e.metaKey && e.shiftKey && (e.key === "i" || e.key === "I"))) {
498
+ e.preventDefault();
499
+ void formatDocument();
500
+ return;
501
+ }
502
+ };
503
+ const [viewportState, setViewportState] = useState({
504
+ scrollTop: 0,
505
+ scrollLeft: 0,
506
+ clientHeight: 600,
507
+ clientWidth: 800,
508
+ });
509
+ // biome-ignore lint/correctness/useExhaustiveDependencies: the scroll container element swaps when rendererMode changes, so the listeners must re-attach then and only then.
510
+ useEffect(() => {
511
+ const scrollEl = scrollRef.current;
512
+ if (!scrollEl)
513
+ return;
514
+ const updateViewport = () => {
515
+ setViewportState({
516
+ scrollTop: scrollEl.scrollTop,
517
+ scrollLeft: scrollEl.scrollLeft,
518
+ clientHeight: scrollEl.clientHeight || 600,
519
+ clientWidth: scrollEl.clientWidth || 800,
520
+ });
521
+ };
522
+ updateViewport();
523
+ let rafId = null;
524
+ const onScroll = () => {
525
+ if (rafId !== null)
526
+ cancelAnimationFrame(rafId);
527
+ rafId = requestAnimationFrame(() => {
528
+ updateViewport();
529
+ rafId = null;
530
+ });
531
+ };
532
+ scrollEl.addEventListener("scroll", onScroll, { passive: true });
533
+ window.addEventListener("resize", onScroll, { passive: true });
534
+ return () => {
535
+ scrollEl.removeEventListener("scroll", onScroll);
536
+ window.removeEventListener("resize", onScroll);
537
+ if (rafId !== null)
538
+ cancelAnimationFrame(rafId);
539
+ };
540
+ }, [rendererMode]);
541
+ const foldRanges = useMemo(() => {
542
+ return computeFoldRanges(lines);
543
+ }, [lines]);
544
+ const foldRangesList = useMemo(() => {
545
+ const list = [];
546
+ foldRanges.forEach((endLine, startLine) => {
547
+ list.push({ startLine, endLine });
548
+ });
549
+ return list;
550
+ }, [foldRanges]);
551
+ const gitGutterManager = useMemo(() => new GitGutterManager(), []);
552
+ const activeGitMarkers = useMemo(() => {
553
+ if (gitGutterMarkers)
554
+ return gitGutterMarkers;
555
+ if (baseContent !== undefined) {
556
+ return gitGutterManager.update(baseContent, lines.join("\n"));
557
+ }
558
+ return undefined;
559
+ }, [gitGutterMarkers, baseContent, lines, gitGutterManager]);
560
+ const visualLineIndices = useMemo(() => {
561
+ const result = [];
562
+ let skipUntil = -1;
563
+ for (let i = 0; i < lines.length; i++) {
564
+ if (skipUntil >= 0 && i <= skipUntil) {
565
+ continue;
566
+ }
567
+ result.push(i);
568
+ if (foldedLines.has(i)) {
569
+ const endLine = foldRanges.get(i);
570
+ if (endLine !== undefined && endLine > i) {
571
+ skipUntil = endLine;
572
+ }
573
+ }
574
+ }
575
+ return result;
576
+ }, [lines, foldedLines, foldRanges]);
577
+ const { startVisualIndex, endVisualIndex, topSpacerHeight, bottomSpacerHeight } = computeWindowedRange({
578
+ visualLineCount: visualLineIndices.length,
579
+ scrollTop: viewportState.scrollTop,
580
+ clientHeight: viewportState.clientHeight,
581
+ lineHeight,
582
+ });
583
+ const windowedLineIndices = useMemo(() => {
584
+ if (visualLineIndices.length === 0)
585
+ return [];
586
+ return visualLineIndices.slice(startVisualIndex, endVisualIndex + 1);
587
+ }, [visualLineIndices, startVisualIndex, endVisualIndex]);
588
+ const totalContentHeight = Math.max(1, visualLineIndices.length * lineHeight);
589
+ const longestLineLen = useMemo(() => measureLongestLine(lines), [lines]);
590
+ const totalContentWidth = longestLineLen * exactCharWidth + 200;
591
+ return (
592
+ // biome-ignore lint/a11y/noStaticElementInteractions: container-level shortcut keys for events bubbling up from the focused textarea; the container itself takes no focus.
593
+ _jsxs("div", { ref: outerRef, onKeyDown: handleKeyDown, className: ["termax-editor-frame", className].filter(Boolean).join(" "), style: {
594
+ position: "relative",
595
+ display: "flex",
596
+ flexDirection: "column",
597
+ overflow: "hidden",
598
+ backgroundColor: activeTheme.background,
599
+ color: activeTheme.foreground,
600
+ fontFamily: "monospace",
601
+ fontSize: "13px",
602
+ height: "100%",
603
+ width: "100%",
604
+ border: `1px solid ${activeTheme.border}`,
605
+ borderRadius: "6px",
606
+ boxSizing: "border-box",
607
+ ...style,
608
+ }, children: [_jsx("style", { children: `
609
+ @keyframes termax-blink {
610
+ 0%, 100% { opacity: 1; }
611
+ 50% { opacity: 0; }
612
+ }
613
+ .termax-editor-frame:focus-within {
614
+ outline: 1px solid #388bfd;
615
+ outline-offset: -1px;
616
+ }
617
+ ` }), _jsx("span", { ref: measureRef, style: {
618
+ position: "absolute",
619
+ top: -9999,
620
+ left: -9999,
621
+ visibility: "hidden",
622
+ pointerEvents: "none",
623
+ fontFamily: "inherit",
624
+ fontSize: "inherit",
625
+ whiteSpace: "pre",
626
+ }, children: "0123456789" }), showFind && _jsx(FindReplace, { onClose: () => setShowFind(false), onScrollToLine: scrollToLine }), _jsx(OffscreenInput, { inputRef: inputRef, lineHeight: lineHeight, charWidth: exactCharWidth, readOnly: readOnly, completionKeys: {
627
+ visible: completionsVisible,
628
+ listboxId,
629
+ activeId: activeOptionId,
630
+ onCycle: (delta) => setCompletionIndex((i) => (i + delta + completionItems.length) % completionItems.length),
631
+ onAccept: () => {
632
+ const item = completionItems[completionIndex];
633
+ if (item)
634
+ handleAcceptCompletion(item);
635
+ },
636
+ onClose: () => setShowCompletions(false),
637
+ }, scrollTop: viewportState.scrollTop, scrollLeft: viewportState.scrollLeft, gutterWidth: showLineNumbers
638
+ ? Math.round(Math.max(2, String(lines.length).length) * exactCharWidth + 24)
639
+ : 0, onKeyDown: handleVimKeyDown }), _jsxs("div", { style: {
640
+ position: "relative",
641
+ display: "flex",
642
+ flexDirection: "row",
643
+ flex: 1,
644
+ minHeight: 0,
645
+ width: "100%",
646
+ height: "100%",
647
+ overflow: "hidden",
648
+ }, children: [showMinimap &&
649
+ minimapPosition === "left" &&
650
+ (renderMinimap ? (renderMinimap({
651
+ width: minimapWidth,
652
+ position: "left",
653
+ lineHeight,
654
+ viewportHeight: viewportState.clientHeight,
655
+ scrollTop: viewportState.scrollTop,
656
+ onScrollTo: scrollToScrollTop,
657
+ })) : (_jsx(Minimap, { width: minimapWidth, position: "left", lineHeight: lineHeight, viewportHeight: viewportState.clientHeight, scrollTop: viewportState.scrollTop, onScrollTo: scrollToScrollTop }))), _jsxs("div", { style: {
658
+ position: "relative",
659
+ flex: 1,
660
+ minWidth: 0,
661
+ height: "100%",
662
+ overflow: "hidden",
663
+ }, children: [stickyScroll && (_jsx(StickyScrollHeader, { lines: lines, foldRanges: foldRangesList, topVisibleLine: Math.floor(viewportState.scrollTop / lineHeight), lineHeight: lineHeight, onJumpToLine: (line) => {
664
+ setCursor({ line, column: 0 });
665
+ scrollToLine(line);
666
+ focusInput();
667
+ } })), rendererMode === "canvas" ? (_jsxs(_Fragment, { children: [_jsx(CanvasViewport, { lines: lines, language: language, languageAdapter: activeLangAdapter, theme: activeTheme, fontFamily: "monospace", fontSize: 13, lineHeight: lineHeight, charWidth: exactCharWidth, showLineNumbers: showLineNumbers, cursor: cursor, selection: selection, selections: selections, diagnostics: diagnostics, scrollContainerRef: scrollRef, onSetCursor: setCursor, onSetSelection: setSelection, onFocusInput: focusInput }), _jsx("div", { ref: scrollRef, onMouseDown: handleCanvasMouseDown, style: {
668
+ position: "absolute",
669
+ inset: 0,
670
+ overflow: "auto",
671
+ zIndex: 1,
672
+ pointerEvents: "auto",
673
+ cursor: "text",
674
+ userSelect: "none",
675
+ WebkitUserSelect: "none",
676
+ }, children: _jsx("div", { style: {
677
+ height: totalContentHeight,
678
+ width: totalContentWidth,
679
+ pointerEvents: "none",
680
+ } }) })] })) : (_jsx("div", { ref: scrollRef, style: {
681
+ width: "100%",
682
+ height: "100%",
683
+ overflow: "auto",
684
+ }, children: _jsxs("div", { style: {
685
+ display: "flex",
686
+ width: "max-content",
687
+ minWidth: "100%",
688
+ minHeight: "100%",
689
+ }, children: [showLineNumbers && (_jsx(LineNumbers, { lineHeight: lineHeight, scrollTop: viewportState.scrollTop, viewportHeight: viewportState.clientHeight, totalLines: lines.length, onFocusInput: focusInput, gitGutterMarkers: activeGitMarkers })), foldable && (_jsx(FoldGutter, { lineHeight: lineHeight, scrollTop: viewportState.scrollTop, viewportHeight: viewportState.clientHeight, totalLines: lines.length, foldedLines: foldedLines, foldRanges: foldRanges, onToggleFold: handleToggleFold })), _jsx(VirtualizedLines, { lineHeight: lineHeight, charWidth: exactCharWidth, language: language, filePath: filePath, onFocusInput: focusInput, visibleLineIndices: windowedLineIndices, foldedLines: foldedLines, foldRanges: foldRanges, onToggleFold: handleToggleFold, topSpacerHeight: topSpacerHeight, bottomSpacerHeight: bottomSpacerHeight, diagnostics: diagnostics, inlineBlame: blameManager, codeLensProvider: codeLensProvider, showColorSwatches: showColorSwatches, streamingDiffChunks: streamingDiffChunks })] }) }))] }), showMinimap &&
690
+ minimapPosition !== "left" &&
691
+ (renderMinimap ? (renderMinimap({
692
+ width: minimapWidth,
693
+ position: "right",
694
+ lineHeight,
695
+ viewportHeight: viewportState.clientHeight,
696
+ scrollTop: viewportState.scrollTop,
697
+ onScrollTo: scrollToScrollTop,
698
+ })) : (_jsx(Minimap, { width: minimapWidth, position: "right", lineHeight: lineHeight, viewportHeight: viewportState.clientHeight, scrollTop: viewportState.scrollTop, onScrollTo: scrollToScrollTop })))] }), activeDiagnostic && (_jsx(HoverTooltip, { visible: true, x: (showLineNumbers
699
+ ? Math.round(Math.max(2, String(lines.length).length) * exactCharWidth + 24)
700
+ : 0) +
701
+ 8 +
702
+ activeDiagnostic.range.start.column * exactCharWidth -
703
+ viewportState.scrollLeft, y: (activeDiagnostic.range.start.line + 1) * lineHeight - viewportState.scrollTop, diagnostic: activeDiagnostic, onApplyCodeAction: applyCodeAction })), signatureHelp && (_jsx(SignatureHelpTooltip, { visible: true, x: (showLineNumbers
704
+ ? Math.round(Math.max(2, String(lines.length).length) * exactCharWidth + 24)
705
+ : 0) +
706
+ 8 +
707
+ cursor.column * exactCharWidth -
708
+ viewportState.scrollLeft, y: cursor.line * lineHeight - viewportState.scrollTop, signatureHelp: signatureHelp })), showCompletions && completionItems.length > 0 && (_jsx(CompletionMenu, { visible: showCompletions, items: completionItems, selectedIndex: completionIndex, listboxId: listboxId, x: (showLineNumbers
709
+ ? Math.round(Math.max(2, String(lines.length).length) * exactCharWidth + 24)
710
+ : 0) +
711
+ 8 +
712
+ cursor.column * exactCharWidth -
713
+ viewportState.scrollLeft, y: (cursor.line + 1) * lineHeight - viewportState.scrollTop, onSelect: handleAcceptCompletion, onSelectIndex: setCompletionIndex, onClose: () => setShowCompletions(false) })), vimMode && (_jsx(VimStatusBar, { mode: vimState.mode, commandBuffer: vimState.buffer, exInput: vimState.ex }))] }));
714
+ });
715
+ export const TermaxEditor = forwardRef(function TermaxEditor({ defaultValue = "", value, language: explicitLanguage, filePath, adapter, languageAdapter, rendererMode = "canvas", onChange, readOnly = false, lineHeight = 20, charWidth = 7.8, showLineNumbers = true, foldable = true, showMinimap = false, minimapPosition = "right", minimapWidth = 70, renderMinimap, theme = "githubDark", diagnostics, signatureHelp, vimMode = false, className, style, stickyScroll = true, baseContent, gitGutterMarkers, blameManager, codeLensProvider, showColorSwatches = true, ghostText, onAcceptGhostText, onDismissGhostText, streamingDiffChunks, onSnapshot, }, ref) {
716
+ const language = useMemo(() => {
717
+ if (explicitLanguage)
718
+ return explicitLanguage;
719
+ if (filePath)
720
+ return detectLanguageFromPath(filePath);
721
+ return "typescript";
722
+ }, [explicitLanguage, filePath]);
723
+ return (_jsx(EditorProvider, { initialContent: value ?? defaultValue, adapter: adapter,
724
+ // Keying the adapter buffer by path keeps two editors on different
725
+ // files from sharing one host buffer.
726
+ bufferId: filePath ?? "default", onChange: onChange, children: _jsx(InnerEditor, { ref: ref, language: language, filePath: filePath, languageAdapter: languageAdapter, rendererMode: rendererMode, readOnly: readOnly, lineHeight: lineHeight, charWidth: charWidth, showLineNumbers: showLineNumbers, foldable: foldable, showMinimap: showMinimap, minimapPosition: minimapPosition, minimapWidth: minimapWidth, renderMinimap: renderMinimap, theme: theme, diagnostics: diagnostics, signatureHelp: signatureHelp, vimMode: vimMode, className: className, style: style, stickyScroll: stickyScroll, baseContent: baseContent, gitGutterMarkers: gitGutterMarkers, blameManager: blameManager, codeLensProvider: codeLensProvider, showColorSwatches: showColorSwatches, ghostText: ghostText, onAcceptGhostText: onAcceptGhostText, onDismissGhostText: onDismissGhostText, streamingDiffChunks: streamingDiffChunks, onSnapshot: onSnapshot }) }, filePath ?? "default"));
727
+ });
728
+ //# sourceMappingURL=TermaxEditor.js.map