1import { withOpacity } from "../theme/color"
2import { ColorScheme, Layer, StyleSets } from "../theme/colorScheme"
3import { background, border, borderColor, foreground, text } from "./components"
4import hoverPopover from "./hoverPopover"
5
6import { buildSyntax } from "../theme/syntax"
7import { interactive, toggleable } from "../element"
8
9export default function editor(colorScheme: ColorScheme) {
10 const { isLight } = colorScheme
11
12 let layer = colorScheme.highest
13
14 const autocompleteItem = {
15 cornerRadius: 6,
16 padding: {
17 bottom: 2,
18 left: 6,
19 right: 6,
20 top: 2,
21 },
22 }
23
24 function diagnostic(layer: Layer, styleSet: StyleSets) {
25 return {
26 textScaleFactor: 0.857,
27 header: {
28 border: border(layer, {
29 top: true,
30 }),
31 },
32 message: {
33 text: text(layer, "sans", styleSet, "default", { size: "sm" }),
34 highlightText: text(layer, "sans", styleSet, "default", {
35 size: "sm",
36 weight: "bold",
37 }),
38 },
39 }
40 }
41
42 const syntax = buildSyntax(colorScheme)
43
44 return {
45 textColor: syntax.primary.color,
46 background: background(layer),
47 activeLineBackground: withOpacity(background(layer, "on"), 0.75),
48 highlightedLineBackground: background(layer, "on"),
49 // Inline autocomplete suggestions, Co-pilot suggestions, etc.
50 suggestion: syntax.predictive,
51 codeActions: {
52 indicator: toggleable({
53 base: interactive({
54 base: {
55 color: foreground(layer, "variant"),
56 },
57 state: {
58 hovered: {
59 color: foreground(layer, "variant", "hovered"),
60 },
61 clicked: {
62 color: foreground(layer, "variant", "pressed"),
63 },
64 },
65 }),
66 state: {
67 active: {
68 default: {
69 color: foreground(layer, "accent"),
70 },
71 hovered: {
72 color: foreground(layer, "accent", "hovered"),
73 },
74 clicked: {
75 color: foreground(layer, "accent", "pressed"),
76 },
77 },
78 },
79 }),
80
81 verticalScale: 0.55,
82 },
83 folds: {
84 iconMarginScale: 2.5,
85 foldedIcon: "icons/chevron_right_8.svg",
86 foldableIcon: "icons/chevron_down_8.svg",
87 indicator: toggleable({
88 base: interactive({
89 base: {
90 color: foreground(layer, "variant"),
91 },
92 state: {
93 hovered: {
94 color: foreground(layer, "on"),
95 },
96 clicked: {
97 color: foreground(layer, "base"),
98 },
99 },
100 }),
101 state: {
102 active: {
103 default: {
104 color: foreground(layer, "default"),
105 },
106 hovered: {
107 color: foreground(layer, "variant"),
108 },
109 },
110 },
111 }),
112 ellipses: {
113 textColor: colorScheme.ramps.neutral(0.71).hex(),
114 cornerRadiusFactor: 0.15,
115 background: {
116 // Copied from hover_popover highlight
117 default: {
118 color: colorScheme.ramps.neutral(0.5).alpha(0.0).hex(),
119 },
120
121 hovered: {
122 color: colorScheme.ramps.neutral(0.5).alpha(0.5).hex(),
123 },
124
125 clicked: {
126 color: colorScheme.ramps.neutral(0.5).alpha(0.7).hex(),
127 },
128 },
129 },
130 foldBackground: foreground(layer, "variant"),
131 },
132 diff: {
133 deleted: isLight
134 ? colorScheme.ramps.red(0.5).hex()
135 : colorScheme.ramps.red(0.4).hex(),
136 modified: isLight
137 ? colorScheme.ramps.yellow(0.5).hex()
138 : colorScheme.ramps.yellow(0.5).hex(),
139 inserted: isLight
140 ? colorScheme.ramps.green(0.4).hex()
141 : colorScheme.ramps.green(0.5).hex(),
142 removedWidthEm: 0.275,
143 widthEm: 0.15,
144 cornerRadius: 0.05,
145 },
146 /** Highlights matching occurrences of what is under the cursor
147 * as well as matched brackets
148 */
149 documentHighlightReadBackground: withOpacity(
150 foreground(layer, "accent"),
151 0.1
152 ),
153 documentHighlightWriteBackground: colorScheme.ramps
154 .neutral(0.5)
155 .alpha(0.4)
156 .hex(), // TODO: This was blend * 2
157 errorColor: background(layer, "negative"),
158 gutterBackground: background(layer),
159 gutterPaddingFactor: 3.5,
160 lineNumber: withOpacity(foreground(layer), 0.35),
161 lineNumberActive: foreground(layer),
162 renameFade: 0.6,
163 unnecessaryCodeFade: 0.5,
164 selection: colorScheme.players[0],
165 whitespace: colorScheme.ramps.neutral(0.5).hex(),
166 guestSelections: [
167 colorScheme.players[1],
168 colorScheme.players[2],
169 colorScheme.players[3],
170 colorScheme.players[4],
171 colorScheme.players[5],
172 colorScheme.players[6],
173 colorScheme.players[7],
174 ],
175 autocomplete: {
176 background: background(colorScheme.middle),
177 cornerRadius: 8,
178 padding: 4,
179 margin: {
180 left: -14,
181 },
182 border: border(colorScheme.middle),
183 shadow: colorScheme.popoverShadow,
184 matchHighlight: foreground(colorScheme.middle, "accent"),
185 item: autocompleteItem,
186 hoveredItem: {
187 ...autocompleteItem,
188 matchHighlight: foreground(
189 colorScheme.middle,
190 "accent",
191 "hovered"
192 ),
193 background: background(colorScheme.middle, "hovered"),
194 },
195 selectedItem: {
196 ...autocompleteItem,
197 matchHighlight: foreground(
198 colorScheme.middle,
199 "accent",
200 "active"
201 ),
202 background: background(colorScheme.middle, "active"),
203 },
204 },
205 diagnosticHeader: {
206 background: background(colorScheme.middle),
207 iconWidthFactor: 1.5,
208 textScaleFactor: 0.857,
209 border: border(colorScheme.middle, {
210 bottom: true,
211 top: true,
212 }),
213 code: {
214 ...text(colorScheme.middle, "mono", { size: "sm" }),
215 margin: {
216 left: 10,
217 },
218 },
219 source: {
220 text: text(colorScheme.middle, "sans", {
221 size: "sm",
222 weight: "bold",
223 }),
224 },
225 message: {
226 highlightText: text(colorScheme.middle, "sans", {
227 size: "sm",
228 weight: "bold",
229 }),
230 text: text(colorScheme.middle, "sans", { size: "sm" }),
231 },
232 },
233 diagnosticPathHeader: {
234 background: background(colorScheme.middle),
235 textScaleFactor: 0.857,
236 filename: text(colorScheme.middle, "mono", { size: "sm" }),
237 path: {
238 ...text(colorScheme.middle, "mono", { size: "sm" }),
239 margin: {
240 left: 12,
241 },
242 },
243 },
244 errorDiagnostic: diagnostic(colorScheme.middle, "negative"),
245 warningDiagnostic: diagnostic(colorScheme.middle, "warning"),
246 informationDiagnostic: diagnostic(colorScheme.middle, "accent"),
247 hintDiagnostic: diagnostic(colorScheme.middle, "warning"),
248 invalidErrorDiagnostic: diagnostic(colorScheme.middle, "base"),
249 invalidHintDiagnostic: diagnostic(colorScheme.middle, "base"),
250 invalidInformationDiagnostic: diagnostic(colorScheme.middle, "base"),
251 invalidWarningDiagnostic: diagnostic(colorScheme.middle, "base"),
252 hoverPopover: hoverPopover(colorScheme),
253 linkDefinition: {
254 color: syntax.linkUri.color,
255 underline: syntax.linkUri.underline,
256 },
257 jumpIcon: interactive({
258 base: {
259 color: foreground(layer, "on"),
260 iconWidth: 20,
261 buttonWidth: 20,
262 cornerRadius: 6,
263 padding: {
264 top: 6,
265 bottom: 6,
266 left: 6,
267 right: 6,
268 },
269 },
270 state: {
271 hovered: {
272 background: background(layer, "on", "hovered"),
273 },
274 },
275 }),
276
277 scrollbar: {
278 width: 12,
279 minHeightFactor: 1.0,
280 track: {
281 border: border(layer, "variant", { left: true }),
282 },
283 thumb: {
284 background: withOpacity(background(layer, "inverted"), 0.3),
285 border: {
286 width: 1,
287 color: borderColor(layer, "variant"),
288 top: false,
289 right: true,
290 left: true,
291 bottom: false,
292 },
293 },
294 git: {
295 deleted: isLight
296 ? withOpacity(colorScheme.ramps.red(0.5).hex(), 0.8)
297 : withOpacity(colorScheme.ramps.red(0.4).hex(), 0.8),
298 modified: isLight
299 ? withOpacity(colorScheme.ramps.yellow(0.5).hex(), 0.8)
300 : withOpacity(colorScheme.ramps.yellow(0.4).hex(), 0.8),
301 inserted: isLight
302 ? withOpacity(colorScheme.ramps.green(0.5).hex(), 0.8)
303 : withOpacity(colorScheme.ramps.green(0.4).hex(), 0.8),
304 },
305 },
306 compositionMark: {
307 underline: {
308 thickness: 1.0,
309 color: borderColor(layer),
310 },
311 },
312 syntax,
313 }
314}