editor.ts

  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}