Skip to content

Commit 06b360d

Browse files
committed
expand editor+highlight style config; fix mui useTheme imports;
1 parent a8fbbee commit 06b360d

File tree

4 files changed

+80
-26
lines changed

4 files changed

+80
-26
lines changed

packages/demo/src/pages/PageDemoComponent.tsx

+1-1
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ import { highlightSelectionMatches, searchKeymap } from '@codemirror/search'
1818
import { closeBrackets, autocompletion, closeBracketsKeymap, completionKeymap } from '@codemirror/autocomplete'
1919
import { lintKeymap } from '@codemirror/lint'
2020
import { Compartment, EditorState } from '@codemirror/state'
21-
import useTheme from '@mui/material/styles/useTheme'
21+
import { useTheme } from '@mui/material/styles'
2222
import { Button } from '@mui/material'
2323

2424
export const PageDemoComponent: React.ComponentType = () => {

packages/demo/src/pages/PageDemoComponentMui.tsx

+1-1
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ export const PageDemoComponentMui: React.ComponentType = () => {
3333
<Box mb={2}>
3434
<Typography variant={'h1'} gutterBottom>Component</Typography>
3535
<Typography variant={'body1'}>Plain React components demo, no UI-Schema widgets, using Material-UI styling with <code>@mui</code>.</Typography>
36-
<Typography variant={'body1'}>Page filling style, where the scrollable area is the CodeMirror Editor, use <code>variant: &qout;embed&qout;</code> to deactivate outlined/borders-radius.</Typography>
36+
<Typography variant={'body1'}>Page filling style, where the scrollable area is the CodeMirror Editor, use <code>{'variant: "embed"'}</code> to deactivate outlined/borders-radius.</Typography>
3737
<Typography variant={'body1'}>
3838
<Link
3939
href={'https://github.com/ui-schema/react-codemirror/blob/main/packages/demo/src/pages/PageDemoComponentMui.tsx'}

packages/material-code/src/useEditorTheme/useEditorTheme.ts

+50-12
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,28 @@
11
import React from 'react'
22
import { EditorView } from '@codemirror/view'
33
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'
67

78
export 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

2328
export 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
}

packages/material-code/src/useHighlightStyle/useHighlightStyle.ts

+28-12
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,15 @@
11
import React from 'react'
22
import { tags } from '@lezer/highlight'
33
import { HighlightStyle } from '@codemirror/language'
4-
import useTheme from '@mui/material/styles/useTheme'
4+
import { useTheme } from '@mui/material/styles'
55

6-
export const useHighlightStyle = (): HighlightStyle => {
6+
export const useHighlightStyle = (
7+
{
8+
headlineUnderline = true,
9+
}: {
10+
headlineUnderline?: boolean
11+
} = {},
12+
): HighlightStyle => {
713
const {palette} = useTheme()
814
return React.useMemo(() => HighlightStyle.define([
915
{
@@ -12,7 +18,7 @@ export const useHighlightStyle = (): HighlightStyle => {
1218
},
1319
{
1420
tag: tags.heading,
15-
textDecoration: 'underline',
21+
...headlineUnderline ? {textDecoration: 'underline'} : {},
1622
fontWeight: 'bold',
1723
},
1824
{
@@ -36,13 +42,17 @@ export const useHighlightStyle = (): HighlightStyle => {
3642
color: palette.mode === 'dark' ? '#f746ec' : '#8e0b99',
3743
},
3844
{
39-
tag: [tags.atom, tags.bool, tags.url, tags.contentSeparator, tags.labelName],
45+
tag: [tags.atom, tags.bool, tags.null, tags.url, tags.contentSeparator, tags.labelName],
4046
color: palette.mode === 'dark' ? '#978ed3' : '#121cb1',
4147
},
4248
{
43-
tag: [tags.literal, tags.inserted],
49+
tag: [tags.literal], // numbers in json+yaml
4450
color: palette.mode === 'dark' ? '#2da273' : '#116644',
4551
},
52+
{
53+
tag: [tags.inserted],
54+
color: palette.mode === 'dark' ? '#1a9544' : '#068248',
55+
},
4656
{
4757
tag: [tags.deleted],
4858
color: palette.mode === 'dark' ? '#d22c2c' : '#aa1111',
@@ -64,36 +74,42 @@ export const useHighlightStyle = (): HighlightStyle => {
6474
color: '#ee4400',
6575
},
6676
{
67-
tag: tags.definition(tags.variableName),
77+
tag: [
78+
tags.definition(tags.variableName),
79+
// e.g. sass-vars
80+
tags.special(tags.variableName),
81+
tags.variableName,
82+
tags.attributeName,
83+
],
6884
color: palette.mode === 'dark' ? '#5279ec' : '#255fb9',
6985
},
7086
{
7187
tag: tags.local(tags.variableName),
72-
color: '#3300aa',
88+
color: palette.mode === 'dark' ? '#8e6bdf' : '#6b38e1',
7389
},
7490
{
7591
tag: [tags.typeName, tags.namespace],
7692
color: palette.mode === 'dark' ? '#ec4837' : '#b7382b',
7793
},
7894
{
7995
tag: tags.className,
80-
color: '#116677',
96+
color: palette.mode === 'dark' ? '#3c8b9b' : '#116677',
8197
},
8298
{
83-
tag: [tags.special(tags.variableName), tags.macroName],
99+
tag: [tags.macroName],
84100
color: '#225566',
85101
},
86102
{
87103
tag: tags.definition(tags.propertyName),
88-
color: '#0000cc',
104+
color: palette.mode === 'dark' ? '#2981df' : '#0000cc',
89105
},
90106
{
91107
tag: tags.comment,
92108
color: palette.mode === 'dark' ? '#738284' : '#6b7677',
93109
},
94110
{
95111
tag: tags.invalid,
96-
color: '#ff0000',
112+
color: palette.error.main,
97113
},
98-
]), [palette])
114+
]), [headlineUnderline, palette.mode, palette.text.secondary, palette.error.main])
99115
}

0 commit comments

Comments
 (0)