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