1
1
import React from 'react'
2
2
import { EditorView } from '@codemirror/view'
3
3
import { 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'
6
7
7
8
export interface EditorThemeCustomStyles {
8
9
// for all standard texts
10
+ fontSize ?: React . CSSProperties [ 'fontSize' ]
9
11
textColor ?: React . CSSProperties [ 'color' ]
12
+ caretColor ?: React . CSSProperties [ 'caretColor' ]
13
+ dropInCaretColor ?: React . CSSProperties [ 'caretColor' ]
10
14
// for headlines, with fallback to `textColor`
11
15
headlineColor ?: React . CSSProperties [ 'color' ]
12
16
backgroundColor ?: React . CSSProperties [ 'backgroundColor' ]
13
17
lineHeight ?: React . CSSProperties [ 'lineHeight' ]
14
18
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' ]
19
23
// 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
21
26
}
22
27
23
28
export const useEditorTheme = (
@@ -26,6 +31,11 @@ export const useEditorTheme = (
26
31
customVariant ?: TextFieldProps [ 'variant' ] | 'embed' ,
27
32
// overwrite some colors & styles easily, must be memoized to not force reapplying theme on each render
28
33
customStyles ?: EditorThemeCustomStyles ,
34
+ styleOverride : {
35
+ cmEditor ?: StyleSpec
36
+ cmScroller ?: StyleSpec
37
+ cmContent ?: StyleSpec
38
+ } = { } ,
29
39
) : Extension => {
30
40
const { palette, spacing, shape, components} = useTheme ( )
31
41
const variant = customVariant || components ?. MuiTextField ?. defaultProps ?. variant || 'standard'
@@ -34,14 +44,30 @@ export const useEditorTheme = (
34
44
const borderRadiusTmp = typeof styleBorderRadius !== 'undefined' ? styleBorderRadius : shape . borderRadius
35
45
const borderRadius = variant === 'standard' ? typeof borderRadiusTmp === 'number' ? borderRadiusTmp + 'px' : borderRadiusTmp : 0
36
46
47
+ const {
48
+ cmEditor,
49
+ cmScroller,
50
+ cmContent,
51
+ } = styleOverride
52
+
37
53
const styleMap = React . useMemo (
38
54
( ) => ( {
55
+ fontSize : customStyles ?. fontSize ,
39
56
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 ,
40
59
headlineColor : customStyles ?. headlineColor || customStyles ?. textColor || palette . text . primary ,
41
60
backgroundColor : customStyles ?. backgroundColor || palette . background . paper ,
42
61
lineHeight : dense ? customStyles ?. lineHeightDense || '1.3em' : customStyles ?. lineHeight || '1.43125em' ,
43
62
linePadding : dense ? '0 2px 0 4px' : '0px 3px 0px 4px' ,
44
63
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 ,
45
71
borderDefault : palette . mode === 'light' ? 'rgba(0, 0, 0, 0.23)' : 'rgba(255, 255, 255, 0.23)' ,
46
72
borderFocused : palette . primary . main ,
47
73
borderInvalid : palette . error . main ,
@@ -53,12 +79,15 @@ export const useEditorTheme = (
53
79
} ) ,
54
80
[ customStyles , dense , palette , spacing ] ,
55
81
)
82
+
56
83
return React . useMemo (
57
84
( ) =>
58
85
EditorView . theme (
59
86
{
60
87
'&' : {
88
+ ...styleMap . fontSize ? { fontSize : styleMap . fontSize } : { } ,
61
89
color : styleMap . textColor ,
90
+ caretColor : styleMap . caretColor ,
62
91
backgroundColor : styleMap . backgroundColor ,
63
92
...( typeof styleMap . width === 'undefined' || styleMap . width === null ? { } : {
64
93
width : styleMap . width ,
@@ -71,6 +100,7 @@ export const useEditorTheme = (
71
100
'transparent'
72
101
) ,
73
102
borderRadius : borderRadius ,
103
+ ...cmEditor || { } ,
74
104
} ,
75
105
...( variant !== 'standard' || readOnly ? { } : {
76
106
'&.cm-editor:hover' : {
@@ -105,15 +135,20 @@ export const useEditorTheme = (
105
135
} ,
106
136
} : { } ) ,
107
137
'& .cm-content' : {
108
- caretColor : styleMap . textColor ,
109
- padding : styleMap . contentPadding ,
138
+ caretColor : styleMap . caretColor ,
110
139
lineHeight : styleMap . lineHeight ,
140
+ ...styleMap . contentPaddingBottom ?
141
+ { paddingTop : styleMap . contentPadding , paddingBottom : styleMap . contentPaddingBottom } :
142
+ { padding : styleMap . contentPadding } ,
143
+ ...cmContent || { } ,
111
144
} ,
145
+ '& .cm-cursor, & .cm-dropCursor' : { borderLeftColor : styleMap . dropInCaretColor } ,
112
146
'& .cm-scroller' : {
113
147
lineHeight : styleMap . lineHeight ,
148
+ ...cmScroller || { } ,
114
149
} ,
115
150
'&.cm-focused .cm-cursor' : {
116
- borderLeftColor : styleMap . textColor ,
151
+ borderLeftColor : styleMap . caretColor ,
117
152
} ,
118
153
'&.cm-editor .cm-line' : {
119
154
padding : styleMap . linePadding ,
@@ -133,7 +168,7 @@ export const useEditorTheme = (
133
168
'& .cm-gutterElement.cm-activeLineGutter' : {
134
169
backgroundColor : 'transparent' ,
135
170
} ,
136
- '&.cm-focused .cm-selectionBackground, ::selection' : {
171
+ '&.cm-focused .cm-selectionBackground, & ::selection' : {
137
172
backgroundColor : styleMap . activeSelection ,
138
173
} ,
139
174
'& .cm-gutters' : {
@@ -155,6 +190,9 @@ export const useEditorTheme = (
155
190
} ,
156
191
{ dark : palette . mode === 'dark' } ,
157
192
) ,
158
- [ palette , spacing , readOnly , styleMap , borderRadius , variant ] ,
193
+ [
194
+ palette , spacing , readOnly , styleMap , borderRadius , variant ,
195
+ cmEditor , cmScroller , cmContent ,
196
+ ] ,
159
197
)
160
198
}
0 commit comments