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