theme.ts 1.9 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071
  1. import { EditorView } from '@codemirror/view'
  2. import { Compartment, TransactionSpec } from '@codemirror/state'
  3. import { FontFamily, LineHeight, userStyles } from '@/shared/utils/styles'
  4. export type Options = {
  5. fontSize: number
  6. fontFamily: FontFamily
  7. lineHeight: LineHeight
  8. }
  9. const optionsThemeConf = new Compartment()
  10. export const theme = (options: Options) => [
  11. baseTheme,
  12. optionsThemeConf.of(createThemeFromOptions(options)),
  13. ]
  14. const createThemeFromOptions = ({
  15. fontSize = 12,
  16. fontFamily = 'monaco',
  17. lineHeight = 'normal',
  18. }: Options) => {
  19. // Theme styles that depend on settings
  20. const styles = userStyles({ fontSize, fontFamily, lineHeight })
  21. return [
  22. EditorView.editorAttributes.of({
  23. style: Object.entries({
  24. '--font-size': styles.fontSize,
  25. '--source-font-family': styles.fontFamily,
  26. '--line-height': styles.lineHeight,
  27. })
  28. .map(([key, value]) => `${key}: ${value}`)
  29. .join(';'),
  30. }),
  31. // Set variables for tooltips, which are outside the editor
  32. // TODO: set these on document.body, or a new container element for the tooltips, without using a style mod
  33. EditorView.theme({
  34. '.cm-tooltip': {
  35. '--font-size': styles.fontSize,
  36. '--source-font-family': styles.fontFamily,
  37. },
  38. }),
  39. ]
  40. }
  41. const baseTheme = EditorView.theme({
  42. '.cm-content': {
  43. fontSize: 'var(--font-size)',
  44. fontFamily: 'var(--source-font-family)',
  45. lineHeight: 'var(--line-height)',
  46. color: '#000',
  47. },
  48. '.cm-gutters': {
  49. fontSize: 'var(--font-size)',
  50. lineHeight: 'var(--line-height)',
  51. },
  52. '.cm-lineNumbers': {
  53. fontFamily: 'var(--source-font-family)',
  54. },
  55. '.cm-tooltip': {
  56. // NOTE: fontFamily is not set here, as most tooltips use the UI font
  57. fontSize: 'var(--font-size)',
  58. },
  59. })
  60. export const setOptionsTheme = (options: Options): TransactionSpec => {
  61. return {
  62. effects: optionsThemeConf.reconfigure(createThemeFromOptions(options)),
  63. }
  64. }