1import { with_opacity } from "../theme/color"
2import { Layer, StyleSets } from "../theme/create_theme"
3import {
4 background,
5 border,
6 border_color,
7 foreground,
8 text,
9} from "./components"
10import hover_popover from "./hover_popover"
11
12import { interactive, toggleable } from "../element"
13import { useTheme } from "../theme"
14import chroma from "chroma-js"
15
16export default function editor(): any {
17 const theme = useTheme()
18
19 const { is_light } = theme
20
21 const layer = theme.highest
22
23 const autocomplete_item = {
24 corner_radius: 6,
25 padding: {
26 bottom: 2,
27 left: 6,
28 right: 6,
29 top: 2,
30 },
31 }
32
33 function diagnostic(layer: Layer, style_set: StyleSets) {
34 return {
35 text_scale_factor: 0.857,
36 header: {
37 border: border(layer, {
38 top: true,
39 }),
40 },
41 message: {
42 text: text(layer, "sans", style_set, "default", { size: "sm" }),
43 highlight_text: text(layer, "sans", style_set, "default", {
44 size: "sm",
45 weight: "bold",
46 }),
47 },
48 }
49 }
50
51 return {
52 text_color: theme.syntax.primary.color,
53 background: background(layer),
54 active_line_background: with_opacity(background(layer, "on"), 0.75),
55 highlighted_line_background: background(layer, "on"),
56 // Inline autocomplete suggestions, Co-pilot suggestions, etc.
57 hint: chroma
58 .mix(
59 theme.ramps.neutral(0.6).hex(),
60 theme.ramps.blue(0.4).hex(),
61 0.45,
62 "lch"
63 )
64 .hex(),
65 suggestion: chroma
66 .mix(
67 theme.ramps.neutral(0.4).hex(),
68 theme.ramps.blue(0.4).hex(),
69 0.45,
70 "lch"
71 )
72 .hex(),
73 code_actions: {
74 indicator: toggleable({
75 base: interactive({
76 base: {
77 color: foreground(layer, "variant"),
78 },
79 state: {
80 hovered: {
81 color: foreground(layer, "variant", "hovered"),
82 },
83 clicked: {
84 color: foreground(layer, "variant", "pressed"),
85 },
86 },
87 }),
88 state: {
89 active: {
90 default: {
91 color: foreground(layer, "accent"),
92 },
93 hovered: {
94 color: foreground(layer, "accent", "hovered"),
95 },
96 clicked: {
97 color: foreground(layer, "accent", "pressed"),
98 },
99 },
100 },
101 }),
102
103 vertical_scale: 0.55,
104 },
105 folds: {
106 icon_margin_scale: 2.5,
107 folded_icon: "icons/chevron_right_8.svg",
108 foldable_icon: "icons/chevron_down_8.svg",
109 indicator: toggleable({
110 base: interactive({
111 base: {
112 color: foreground(layer, "variant"),
113 },
114 state: {
115 hovered: {
116 color: foreground(layer, "on"),
117 },
118 clicked: {
119 color: foreground(layer, "base"),
120 },
121 },
122 }),
123 state: {
124 active: {
125 default: {
126 color: foreground(layer, "default"),
127 },
128 hovered: {
129 color: foreground(layer, "on"),
130 },
131 },
132 },
133 }),
134 ellipses: {
135 text_color: theme.ramps.neutral(0.71).hex(),
136 corner_radius_factor: 0.15,
137 background: {
138 // Copied from hover_popover highlight
139 default: {
140 color: theme.ramps.neutral(0.5).alpha(0.0).hex(),
141 },
142
143 hovered: {
144 color: theme.ramps.neutral(0.5).alpha(0.5).hex(),
145 },
146
147 clicked: {
148 color: theme.ramps.neutral(0.5).alpha(0.7).hex(),
149 },
150 },
151 },
152 fold_background: foreground(layer, "variant"),
153 },
154 diff: {
155 deleted: is_light
156 ? theme.ramps.red(0.5).hex()
157 : theme.ramps.red(0.4).hex(),
158 modified: is_light
159 ? theme.ramps.yellow(0.5).hex()
160 : theme.ramps.yellow(0.5).hex(),
161 inserted: is_light
162 ? theme.ramps.green(0.4).hex()
163 : theme.ramps.green(0.5).hex(),
164 removed_width_em: 0.275,
165 width_em: 0.15,
166 corner_radius: 0.05,
167 },
168 /** Highlights matching occurrences of what is under the cursor
169 * as well as matched brackets
170 */
171 document_highlight_read_background: with_opacity(
172 foreground(layer, "accent"),
173 0.1
174 ),
175 document_highlight_write_background: theme.ramps
176 .neutral(0.5)
177 .alpha(0.4)
178 .hex(), // TODO: This was blend * 2
179 error_color: background(layer, "negative"),
180 gutter_background: background(layer),
181 gutter_padding_factor: 3.5,
182 line_number: with_opacity(foreground(layer), 0.35),
183 line_number_active: foreground(layer),
184 rename_fade: 0.6,
185 wrap_guide: with_opacity(foreground(layer), 0.1),
186 active_wrap_guide: with_opacity(foreground(layer), 0.2),
187 unnecessary_code_fade: 0.5,
188 selection: theme.players[0],
189 whitespace: theme.ramps.neutral(0.5).hex(),
190 guest_selections: [
191 theme.players[1],
192 theme.players[2],
193 theme.players[3],
194 theme.players[4],
195 theme.players[5],
196 theme.players[6],
197 theme.players[7],
198 ],
199 autocomplete: {
200 background: background(theme.middle),
201 corner_radius: 8,
202 padding: 4,
203 margin: {
204 left: -14,
205 },
206 border: border(theme.middle),
207 shadow: theme.popover_shadow,
208 match_highlight: foreground(theme.middle, "accent"),
209 item: autocomplete_item,
210 hovered_item: {
211 ...autocomplete_item,
212 match_highlight: foreground(theme.middle, "accent", "hovered"),
213 background: background(theme.middle, "hovered"),
214 },
215 selected_item: {
216 ...autocomplete_item,
217 match_highlight: foreground(theme.middle, "accent", "active"),
218 background: background(theme.middle, "active"),
219 },
220 },
221 diagnostic_header: {
222 background: background(theme.middle),
223 icon_width_factor: 1.5,
224 text_scale_factor: 0.857,
225 border: border(theme.middle, {
226 bottom: true,
227 top: true,
228 }),
229 code: {
230 ...text(theme.middle, "mono", { size: "sm" }),
231 margin: {
232 left: 10,
233 },
234 },
235 source: {
236 text: text(theme.middle, "sans", {
237 size: "sm",
238 weight: "bold",
239 }),
240 },
241 message: {
242 highlight_text: text(theme.middle, "sans", {
243 size: "sm",
244 weight: "bold",
245 }),
246 text: text(theme.middle, "sans", { size: "sm" }),
247 },
248 },
249 diagnostic_path_header: {
250 background: background(theme.middle),
251 text_scale_factor: 0.857,
252 filename: text(theme.middle, "mono", { size: "sm" }),
253 path: {
254 ...text(theme.middle, "mono", { size: "sm" }),
255 margin: {
256 left: 12,
257 },
258 },
259 },
260 error_diagnostic: diagnostic(theme.middle, "negative"),
261 warning_diagnostic: diagnostic(theme.middle, "warning"),
262 information_diagnostic: diagnostic(theme.middle, "accent"),
263 hint_diagnostic: diagnostic(theme.middle, "warning"),
264 invalid_error_diagnostic: diagnostic(theme.middle, "base"),
265 invalid_hint_diagnostic: diagnostic(theme.middle, "base"),
266 invalid_information_diagnostic: diagnostic(theme.middle, "base"),
267 invalid_warning_diagnostic: diagnostic(theme.middle, "base"),
268 hover_popover: hover_popover(),
269 link_definition: {
270 color: theme.syntax.link_uri.color,
271 underline: theme.syntax.link_uri.underline,
272 },
273 jump_icon: interactive({
274 base: {
275 color: foreground(layer, "on"),
276 icon_width: 20,
277 button_width: 20,
278 corner_radius: 6,
279 padding: {
280 top: 6,
281 bottom: 6,
282 left: 6,
283 right: 6,
284 },
285 },
286 state: {
287 hovered: {
288 background: background(layer, "on", "hovered"),
289 },
290 },
291 }),
292
293 scrollbar: {
294 width: 12,
295 min_height_factor: 1.0,
296 track: {
297 border: border(layer, "variant", { left: true }),
298 },
299 thumb: {
300 background: with_opacity(background(layer, "inverted"), 0.3),
301 border: {
302 width: 1,
303 color: border_color(layer, "variant"),
304 top: false,
305 right: true,
306 left: true,
307 bottom: false,
308 },
309 },
310 git: {
311 deleted: is_light
312 ? with_opacity(theme.ramps.red(0.5).hex(), 0.8)
313 : with_opacity(theme.ramps.red(0.4).hex(), 0.8),
314 modified: is_light
315 ? with_opacity(theme.ramps.yellow(0.5).hex(), 0.8)
316 : with_opacity(theme.ramps.yellow(0.4).hex(), 0.8),
317 inserted: is_light
318 ? with_opacity(theme.ramps.green(0.5).hex(), 0.8)
319 : with_opacity(theme.ramps.green(0.4).hex(), 0.8),
320 },
321 selections: foreground(layer, "accent"),
322 },
323 composition_mark: {
324 underline: {
325 thickness: 1.0,
326 color: border_color(layer),
327 },
328 },
329 syntax: theme.syntax,
330 }
331}