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