11import React from 'react'
22import { EditorView } from '@codemirror/view'
33import { Extension } from '@codemirror/state'
4- import useTheme from '@mui/material/styles/useTheme'
5- import { TextFieldProps } from '@mui/material'
4+ import { useTheme } from '@mui/material/styles'
5+ import { TextFieldProps } from '@mui/material/TextField'
6+ import { StyleSpec } from 'style-mod'
67
78export interface EditorThemeCustomStyles {
89 // for all standard texts
10+ fontSize ?: React . CSSProperties [ 'fontSize' ]
911 textColor ?: React . CSSProperties [ 'color' ]
12+ caretColor ?: React . CSSProperties [ 'caretColor' ]
13+ dropInCaretColor ?: React . CSSProperties [ 'caretColor' ]
1014 // for headlines, with fallback to `textColor`
1115 headlineColor ?: React . CSSProperties [ 'color' ]
1216 backgroundColor ?: React . CSSProperties [ 'backgroundColor' ]
1317 lineHeight ?: React . CSSProperties [ 'lineHeight' ]
1418 lineHeightDense ?: React . CSSProperties [ 'lineHeight' ]
15- selectionMatch : React . CSSProperties [ 'backgroundColor' ]
16- activeLineGutter : React . CSSProperties [ 'backgroundColor' ]
17- activeLine : React . CSSProperties [ 'backgroundColor' ]
18- activeSelection : React . CSSProperties [ 'backgroundColor' ]
19+ selectionMatch ? : React . CSSProperties [ 'backgroundColor' ]
20+ activeLineGutter ? : React . CSSProperties [ 'backgroundColor' ]
21+ activeLine ? : React . CSSProperties [ 'backgroundColor' ]
22+ activeSelection ? : React . CSSProperties [ 'backgroundColor' ]
1923 // defaults to `100%`, set no width at all with `null`
20- width : React . CSSProperties [ 'width' ] | null
24+ width ?: React . CSSProperties [ 'width' ] | null
25+ paddingBottom ?: boolean | number | string
2126}
2227
2328export const useEditorTheme = (
@@ -26,6 +31,11 @@ export const useEditorTheme = (
2631 customVariant ?: TextFieldProps [ 'variant' ] | 'embed' ,
2732 // overwrite some colors & styles easily, must be memoized to not force reapplying theme on each render
2833 customStyles ?: EditorThemeCustomStyles ,
34+ styleOverride : {
35+ cmEditor ?: StyleSpec
36+ cmScroller ?: StyleSpec
37+ cmContent ?: StyleSpec
38+ } = { } ,
2939) : Extension => {
3040 const { palette, spacing, shape, components} = useTheme ( )
3141 const variant = customVariant || components ?. MuiTextField ?. defaultProps ?. variant || 'standard'
@@ -34,14 +44,30 @@ export const useEditorTheme = (
3444 const borderRadiusTmp = typeof styleBorderRadius !== 'undefined' ? styleBorderRadius : shape . borderRadius
3545 const borderRadius = variant === 'standard' ? typeof borderRadiusTmp === 'number' ? borderRadiusTmp + 'px' : borderRadiusTmp : 0
3646
47+ const {
48+ cmEditor,
49+ cmScroller,
50+ cmContent,
51+ } = styleOverride
52+
3753 const styleMap = React . useMemo (
3854 ( ) => ( {
55+ fontSize : customStyles ?. fontSize ,
3956 textColor : customStyles ?. textColor || palette . text . primary ,
57+ caretColor : customStyles ?. caretColor || customStyles ?. textColor || palette . text . primary ,
58+ dropInCaretColor : customStyles ?. dropInCaretColor || customStyles ?. caretColor || customStyles ?. textColor || palette . text . primary ,
4059 headlineColor : customStyles ?. headlineColor || customStyles ?. textColor || palette . text . primary ,
4160 backgroundColor : customStyles ?. backgroundColor || palette . background . paper ,
4261 lineHeight : dense ? customStyles ?. lineHeightDense || '1.3em' : customStyles ?. lineHeight || '1.43125em' ,
4362 linePadding : dense ? '0 2px 0 4px' : '0px 3px 0px 4px' ,
4463 contentPadding : dense ? 0 : spacing ( 0.5 ) + ' 0' ,
64+ contentPaddingBottom :
65+ typeof customStyles ?. paddingBottom === 'number' ? customStyles ?. paddingBottom + 'px' :
66+ typeof customStyles ?. paddingBottom === 'string' ? customStyles ?. paddingBottom + 'px' :
67+ // todo: when boolean, add the paddingBottom linear based on number of lines/content height
68+ // to smoothly expand until a certain point is reached, where the lower lines still can be 1/3
69+ // or increase padding dynamically while scrolling down?
70+ customStyles ?. paddingBottom ? spacing ( 8 ) : undefined ,
4571 borderDefault : palette . mode === 'light' ? 'rgba(0, 0, 0, 0.23)' : 'rgba(255, 255, 255, 0.23)' ,
4672 borderFocused : palette . primary . main ,
4773 borderInvalid : palette . error . main ,
@@ -53,12 +79,15 @@ export const useEditorTheme = (
5379 } ) ,
5480 [ customStyles , dense , palette , spacing ] ,
5581 )
82+
5683 return React . useMemo (
5784 ( ) =>
5885 EditorView . theme (
5986 {
6087 '&' : {
88+ ...styleMap . fontSize ? { fontSize : styleMap . fontSize } : { } ,
6189 color : styleMap . textColor ,
90+ caretColor : styleMap . caretColor ,
6291 backgroundColor : styleMap . backgroundColor ,
6392 ...( typeof styleMap . width === 'undefined' || styleMap . width === null ? { } : {
6493 width : styleMap . width ,
@@ -71,6 +100,7 @@ export const useEditorTheme = (
71100 'transparent'
72101 ) ,
73102 borderRadius : borderRadius ,
103+ ...cmEditor || { } ,
74104 } ,
75105 ...( variant !== 'standard' || readOnly ? { } : {
76106 '&.cm-editor:hover' : {
@@ -105,15 +135,20 @@ export const useEditorTheme = (
105135 } ,
106136 } : { } ) ,
107137 '& .cm-content' : {
108- caretColor : styleMap . textColor ,
109- padding : styleMap . contentPadding ,
138+ caretColor : styleMap . caretColor ,
110139 lineHeight : styleMap . lineHeight ,
140+ ...styleMap . contentPaddingBottom ?
141+ { paddingTop : styleMap . contentPadding , paddingBottom : styleMap . contentPaddingBottom } :
142+ { padding : styleMap . contentPadding } ,
143+ ...cmContent || { } ,
111144 } ,
145+ '& .cm-cursor, & .cm-dropCursor' : { borderLeftColor : styleMap . dropInCaretColor } ,
112146 '& .cm-scroller' : {
113147 lineHeight : styleMap . lineHeight ,
148+ ...cmScroller || { } ,
114149 } ,
115150 '&.cm-focused .cm-cursor' : {
116- borderLeftColor : styleMap . textColor ,
151+ borderLeftColor : styleMap . caretColor ,
117152 } ,
118153 '&.cm-editor .cm-line' : {
119154 padding : styleMap . linePadding ,
@@ -133,7 +168,7 @@ export const useEditorTheme = (
133168 '& .cm-gutterElement.cm-activeLineGutter' : {
134169 backgroundColor : 'transparent' ,
135170 } ,
136- '&.cm-focused .cm-selectionBackground, ::selection' : {
171+ '&.cm-focused .cm-selectionBackground, & ::selection' : {
137172 backgroundColor : styleMap . activeSelection ,
138173 } ,
139174 '& .cm-gutters' : {
@@ -155,6 +190,9 @@ export const useEditorTheme = (
155190 } ,
156191 { dark : palette . mode === 'dark' } ,
157192 ) ,
158- [ palette , spacing , readOnly , styleMap , borderRadius , variant ] ,
193+ [
194+ palette , spacing , readOnly , styleMap , borderRadius , variant ,
195+ cmEditor , cmScroller , cmContent ,
196+ ] ,
159197 )
160198}
0 commit comments