Spaces:
Running
Running
import { Compartment, type Extension } from '@codemirror/state'; | |
import { EditorView } from '@codemirror/view'; | |
import { vscodeDark, vscodeLight } from '@uiw/codemirror-theme-vscode'; | |
import type { Theme } from '~/types/theme.js'; | |
import type { EditorSettings } from './CodeMirrorEditor.js'; | |
export const darkTheme = EditorView.theme({}, { dark: true }); | |
export const themeSelection = new Compartment(); | |
export function getTheme(theme: Theme, settings: EditorSettings = {}): Extension { | |
return [ | |
getEditorTheme(settings), | |
theme === 'dark' ? themeSelection.of([getDarkTheme()]) : themeSelection.of([getLightTheme()]), | |
]; | |
} | |
export function reconfigureTheme(theme: Theme) { | |
return themeSelection.reconfigure(theme === 'dark' ? getDarkTheme() : getLightTheme()); | |
} | |
function getEditorTheme(settings: EditorSettings) { | |
return EditorView.theme({ | |
'&': { | |
fontSize: settings.fontSize ?? '12px', | |
}, | |
'&.cm-editor': { | |
height: '100%', | |
background: 'var(--cm-backgroundColor)', | |
color: 'var(--cm-textColor)', | |
}, | |
'.cm-cursor': { | |
borderLeft: 'var(--cm-cursor-width) solid var(--cm-cursor-backgroundColor)', | |
}, | |
'.cm-scroller': { | |
lineHeight: '1.5', | |
'&:focus-visible': { | |
outline: 'none', | |
}, | |
}, | |
'.cm-line': { | |
padding: '0 0 0 4px', | |
}, | |
'&.cm-focused > .cm-scroller > .cm-selectionLayer .cm-selectionBackground': { | |
backgroundColor: 'var(--cm-selection-backgroundColorFocused) !important', | |
opacity: 'var(--cm-selection-backgroundOpacityFocused, 0.3)', | |
}, | |
'&:not(.cm-focused) > .cm-scroller > .cm-selectionLayer .cm-selectionBackground': { | |
backgroundColor: 'var(--cm-selection-backgroundColorBlured)', | |
opacity: 'var(--cm-selection-backgroundOpacityBlured, 0.3)', | |
}, | |
'&.cm-focused > .cm-scroller .cm-matchingBracket': { | |
backgroundColor: 'var(--cm-matching-bracket)', | |
}, | |
'.cm-activeLine': { | |
background: 'var(--cm-activeLineBackgroundColor)', | |
}, | |
'.cm-gutters': { | |
background: 'var(--cm-gutter-backgroundColor)', | |
borderRight: 0, | |
color: 'var(--cm-gutter-textColor)', | |
}, | |
'.cm-gutter': { | |
'&.cm-lineNumbers': { | |
fontFamily: 'Roboto Mono, monospace', | |
fontSize: settings.gutterFontSize ?? settings.fontSize ?? '12px', | |
minWidth: '40px', | |
}, | |
'& .cm-activeLineGutter': { | |
background: 'transparent', | |
color: 'var(--cm-gutter-activeLineTextColor)', | |
}, | |
'&.cm-foldGutter .cm-gutterElement > .fold-icon': { | |
cursor: 'pointer', | |
color: 'var(--cm-foldGutter-textColor)', | |
transform: 'translateY(2px)', | |
'&:hover': { | |
color: 'var(--cm-foldGutter-textColorHover)', | |
}, | |
}, | |
}, | |
'.cm-foldGutter .cm-gutterElement': { | |
padding: '0 4px', | |
}, | |
'.cm-tooltip-autocomplete > ul > li': { | |
minHeight: '18px', | |
}, | |
'.cm-panel.cm-search label': { | |
marginLeft: '2px', | |
fontSize: '12px', | |
}, | |
'.cm-panel.cm-search .cm-button': { | |
fontSize: '12px', | |
}, | |
'.cm-panel.cm-search .cm-textfield': { | |
fontSize: '12px', | |
}, | |
'.cm-panel.cm-search input[type=checkbox]': { | |
position: 'relative', | |
transform: 'translateY(2px)', | |
marginRight: '4px', | |
}, | |
'.cm-panels': { | |
borderColor: 'var(--cm-panels-borderColor)', | |
}, | |
'.cm-panels-bottom': { | |
borderTop: '1px solid var(--cm-panels-borderColor)', | |
backgroundColor: 'transparent', | |
}, | |
'.cm-panel.cm-search': { | |
background: 'var(--cm-search-backgroundColor)', | |
color: 'var(--cm-search-textColor)', | |
padding: '8px', | |
}, | |
'.cm-search .cm-button': { | |
background: 'var(--cm-search-button-backgroundColor)', | |
borderColor: 'var(--cm-search-button-borderColor)', | |
color: 'var(--cm-search-button-textColor)', | |
borderRadius: '4px', | |
'&:hover': { | |
color: 'var(--cm-search-button-textColorHover)', | |
}, | |
'&:focus-visible': { | |
outline: 'none', | |
borderColor: 'var(--cm-search-button-borderColorFocused)', | |
}, | |
'&:hover:not(:focus-visible)': { | |
background: 'var(--cm-search-button-backgroundColorHover)', | |
borderColor: 'var(--cm-search-button-borderColorHover)', | |
}, | |
'&:hover:focus-visible': { | |
background: 'var(--cm-search-button-backgroundColorHover)', | |
borderColor: 'var(--cm-search-button-borderColorFocused)', | |
}, | |
}, | |
'.cm-panel.cm-search [name=close]': { | |
top: '6px', | |
right: '6px', | |
padding: '0 6px', | |
fontSize: '1rem', | |
backgroundColor: 'var(--cm-search-closeButton-backgroundColor)', | |
color: 'var(--cm-search-closeButton-textColor)', | |
'&:hover': { | |
'border-radius': '6px', | |
color: 'var(--cm-search-closeButton-textColorHover)', | |
backgroundColor: 'var(--cm-search-closeButton-backgroundColorHover)', | |
}, | |
}, | |
'.cm-search input': { | |
background: 'var(--cm-search-input-backgroundColor)', | |
borderColor: 'var(--cm-search-input-borderColor)', | |
color: 'var(--cm-search-input-textColor)', | |
outline: 'none', | |
borderRadius: '4px', | |
'&:focus-visible': { | |
borderColor: 'var(--cm-search-input-borderColorFocused)', | |
}, | |
}, | |
'.cm-tooltip': { | |
background: 'var(--cm-tooltip-backgroundColor)', | |
border: '1px solid transparent', | |
borderColor: 'var(--cm-tooltip-borderColor)', | |
color: 'var(--cm-tooltip-textColor)', | |
}, | |
'.cm-tooltip.cm-tooltip-autocomplete ul li[aria-selected]': { | |
background: 'var(--cm-tooltip-backgroundColorSelected)', | |
color: 'var(--cm-tooltip-textColorSelected)', | |
}, | |
'.cm-searchMatch': { | |
backgroundColor: 'var(--cm-searchMatch-backgroundColor)', | |
}, | |
'.cm-tooltip.cm-readonly-tooltip': { | |
padding: '4px', | |
whiteSpace: 'nowrap', | |
backgroundColor: 'var(--bolt-elements-bg-depth-2)', | |
borderColor: 'var(--bolt-elements-borderColorActive)', | |
'& .cm-tooltip-arrow:before': { | |
borderTopColor: 'var(--bolt-elements-borderColorActive)', | |
}, | |
'& .cm-tooltip-arrow:after': { | |
borderTopColor: 'transparent', | |
}, | |
}, | |
}); | |
} | |
function getLightTheme() { | |
return vscodeLight; | |
} | |
function getDarkTheme() { | |
return vscodeDark; | |
} | |