editor.ts

  1import Theme from "../themes/common/theme";
  2import { withOpacity } from "../utils/color";
  3import {
  4  backgroundColor,
  5  border,
  6  borderColor,
  7  iconColor,
  8  player,
  9  popoverShadow,
 10  text,
 11  textColor,
 12  TextColor,
 13} from "./components";
 14import hoverPopover from "./hoverPopover";
 15
 16export default function editor(theme: Theme) {
 17  const autocompleteItem = {
 18    cornerRadius: 6,
 19    padding: {
 20      bottom: 2,
 21      left: 6,
 22      right: 6,
 23      top: 2,
 24    },
 25  };
 26
 27  function diagnostic(theme: Theme, color: TextColor) {
 28    return {
 29      textScaleFactor: 0.857,
 30      header: {
 31        border: border(theme, "primary", {
 32          top: true,
 33        }),
 34      },
 35      message: {
 36        text: text(theme, "sans", color, { size: "sm" }),
 37        highlightText: text(theme, "sans", color, {
 38          size: "sm",
 39          weight: "bold",
 40        }),
 41      },
 42    };
 43  }
 44
 45  const syntax: any = {};
 46  for (const syntaxKey in theme.syntax) {
 47    const style = theme.syntax[syntaxKey];
 48    syntax[syntaxKey] = {
 49      color: style.color,
 50      weight: style.weight,
 51      underline: style.underline,
 52      italic: style.italic,
 53    };
 54  }
 55
 56  return {
 57    textColor: theme.syntax.primary.color,
 58    background: backgroundColor(theme, 500),
 59    activeLineBackground: theme.editor.line.active,
 60    codeActions: {
 61      indicator: iconColor(theme, "secondary"),
 62      verticalScale: 0.618
 63    },
 64    diff: {
 65      deleted: theme.iconColor.error,
 66      inserted: theme.iconColor.ok,
 67      modified: theme.iconColor.warning,
 68      removedWidthEm: 0.275,
 69      widthEm: 0.16,
 70      cornerRadius: 0.05,
 71    },
 72    documentHighlightReadBackground: theme.editor.highlight.occurrence,
 73    documentHighlightWriteBackground: theme.editor.highlight.activeOccurrence,
 74    errorColor: theme.textColor.error,
 75    gutterBackground: backgroundColor(theme, 500),
 76    gutterPaddingFactor: 3.5,
 77    highlightedLineBackground: theme.editor.line.highlighted,
 78    lineNumber: theme.editor.gutter.primary,
 79    lineNumberActive: theme.editor.gutter.active,
 80    renameFade: 0.6,
 81    unnecessaryCodeFade: 0.5,
 82    selection: player(theme, 1).selection,
 83    guestSelections: [
 84      player(theme, 2).selection,
 85      player(theme, 3).selection,
 86      player(theme, 4).selection,
 87      player(theme, 5).selection,
 88      player(theme, 6).selection,
 89      player(theme, 7).selection,
 90      player(theme, 8).selection,
 91    ],
 92    autocomplete: {
 93      background: backgroundColor(theme, 500),
 94      cornerRadius: 8,
 95      padding: 4,
 96      border: border(theme, "secondary"),
 97      shadow: popoverShadow(theme),
 98      item: autocompleteItem,
 99      hoveredItem: {
100        ...autocompleteItem,
101        background: backgroundColor(theme, 500, "hovered"),
102      },
103      margin: {
104        left: -14,
105      },
106      matchHighlight: text(theme, "mono", "feature"),
107      selectedItem: {
108        ...autocompleteItem,
109        background: backgroundColor(theme, 500, "active"),
110      },
111    },
112    diagnosticHeader: {
113      background: backgroundColor(theme, 300),
114      iconWidthFactor: 1.5,
115      textScaleFactor: 0.857, // NateQ: Will we need dynamic sizing for text? If so let's create tokens for these.
116      border: border(theme, "secondary", {
117        bottom: true,
118        top: true,
119      }),
120      code: {
121        ...text(theme, "mono", "secondary", { size: "sm" }),
122        margin: {
123          left: 10,
124        },
125      },
126      message: {
127        highlightText: text(theme, "sans", "primary", {
128          size: "sm",
129          weight: "bold",
130        }),
131        text: text(theme, "sans", "secondary", { size: "sm" }),
132      },
133    },
134    diagnosticPathHeader: {
135      background: theme.editor.line.active,
136      textScaleFactor: 0.857,
137      filename: text(theme, "mono", "primary", { size: "sm" }),
138      path: {
139        ...text(theme, "mono", "muted", { size: "sm" }),
140        margin: {
141          left: 12,
142        },
143      },
144    },
145    errorDiagnostic: diagnostic(theme, "error"),
146    warningDiagnostic: diagnostic(theme, "warning"),
147    informationDiagnostic: diagnostic(theme, "info"),
148    hintDiagnostic: diagnostic(theme, "info"),
149    invalidErrorDiagnostic: diagnostic(theme, "secondary"),
150    invalidHintDiagnostic: diagnostic(theme, "secondary"),
151    invalidInformationDiagnostic: diagnostic(theme, "secondary"),
152    invalidWarningDiagnostic: diagnostic(theme, "secondary"),
153    hoverPopover: hoverPopover(theme),
154    linkDefinition: {
155      color: theme.syntax.linkUri.color,
156      underline: theme.syntax.linkUri.underline,
157    },
158    jumpIcon: {
159      color: iconColor(theme, "secondary"),
160      iconWidth: 20,
161      buttonWidth: 20,
162      cornerRadius: 6,
163      padding: {
164        top: 6,
165        bottom: 6,
166        left: 6,
167        right: 6,
168      },
169      hover: {
170        color: iconColor(theme, "active"),
171        background: backgroundColor(theme, "on500"),
172      },
173    },
174    scrollbar: {
175      width: 12,
176      track: {
177        border: {
178          left: true,
179          width: 1,
180          color: borderColor(theme, "secondary"),
181        },
182      },
183      thumb: {
184        background: withOpacity(borderColor(theme, "secondary"), 0.5),
185        border: {
186          width: 1,
187          color: withOpacity(borderColor(theme, 'muted'), 0.5),
188        }
189      }
190    },
191    compositionMark: {
192      underline: {
193        thickness: 1.0,
194        color: borderColor(theme, "active")
195      },
196    },
197    syntax,
198  };
199}