editor.ts

  1import { withOpacity } from "../utils/color"
  2import { ColorScheme, Layer, StyleSets } from "../themes/common/colorScheme"
  3import { background, border, borderColor, foreground, text } from "./components"
  4import hoverPopover from "./hoverPopover"
  5
  6import { SyntaxHighlightStyle, buildSyntax } from "../themes/common/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.3).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 occurences 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", { size: "sm", weight: "bold", }),
190            },
191            message: {
192                highlightText: text(colorScheme.middle, "sans", {
193                    size: "sm",
194                    weight: "bold",
195                }),
196                text: text(colorScheme.middle, "sans", { size: "sm" }),
197            },
198        },
199        diagnosticPathHeader: {
200            background: background(colorScheme.middle),
201            textScaleFactor: 0.857,
202            filename: text(colorScheme.middle, "mono", { size: "sm" }),
203            path: {
204                ...text(colorScheme.middle, "mono", { size: "sm" }),
205                margin: {
206                    left: 12,
207                },
208            },
209        },
210        errorDiagnostic: diagnostic(colorScheme.middle, "negative"),
211        warningDiagnostic: diagnostic(colorScheme.middle, "warning"),
212        informationDiagnostic: diagnostic(colorScheme.middle, "accent"),
213        hintDiagnostic: diagnostic(colorScheme.middle, "warning"),
214        invalidErrorDiagnostic: diagnostic(colorScheme.middle, "base"),
215        invalidHintDiagnostic: diagnostic(colorScheme.middle, "base"),
216        invalidInformationDiagnostic: diagnostic(colorScheme.middle, "base"),
217        invalidWarningDiagnostic: diagnostic(colorScheme.middle, "base"),
218        hoverPopover: hoverPopover(colorScheme),
219        linkDefinition: {
220            color: syntax.linkUri.color,
221            underline: syntax.linkUri.underline,
222        },
223        jumpIcon: {
224            color: foreground(layer, "on"),
225            iconWidth: 20,
226            buttonWidth: 20,
227            cornerRadius: 6,
228            padding: {
229                top: 6,
230                bottom: 6,
231                left: 6,
232                right: 6,
233            },
234            hover: {
235                background: background(layer, "on", "hovered"),
236            },
237        },
238        scrollbar: {
239            width: 12,
240            minHeightFactor: 1.0,
241            track: {
242                border: border(layer, "variant", { left: true }),
243            },
244            thumb: {
245                background: withOpacity(background(layer, "inverted"), 0.3),
246                border: {
247                        width: 1,
248                        color: borderColor(layer, "variant"),
249                        top: false,
250                        right: true,
251                        left: true,
252                        bottom: false,
253                }
254            },
255            git: {
256                deleted: isLight
257                    ? withOpacity(colorScheme.ramps.red(0.5).hex(), 0.8)
258                    : withOpacity(colorScheme.ramps.red(0.4).hex(), 0.8),
259                modified: isLight
260                    ? withOpacity(colorScheme.ramps.yellow(0.5).hex(), 0.8)
261                    : withOpacity(colorScheme.ramps.yellow(0.4).hex(), 0.8),
262                inserted: isLight
263                    ? withOpacity(colorScheme.ramps.green(0.5).hex(), 0.8)
264                    : withOpacity(colorScheme.ramps.green(0.4).hex(), 0.8),
265            }
266        },
267        compositionMark: {
268            underline: {
269                thickness: 1.0,
270                color: borderColor(layer),
271            },
272        },
273        syntax,
274    }
275}