diff --git a/core/src/theme/dimensionTheme.ts b/core/src/theme/dimensionTheme.ts new file mode 100644 index 000000000..aed59fc92 --- /dev/null +++ b/core/src/theme/dimensionTheme.ts @@ -0,0 +1,42 @@ +import { EditorView } from '@codemirror/view'; +import type { Extension } from '@codemirror/state'; + +export const scrollerTheme = EditorView.theme({ + '& .cm-scroller': { + height: '100% !important', + }, +}); + +let lastDimensionKey: string | null = null; +let lastDimensionTheme: Extension | null = null; + +export function getDimensionTheme( + height: string | null, + minHeight: string | null, + maxHeight: string | null, + width: string | null, + minWidth: string | null, + maxWidth: string | null, +): Extension | null { + if (!height && !minHeight && !maxHeight && !width && !minWidth && !maxWidth) { + return null; + } + + const cacheKey = JSON.stringify({ height, minHeight, maxHeight, width, minWidth, maxWidth }); + if (cacheKey === lastDimensionKey) { + return lastDimensionTheme; + } + + lastDimensionKey = cacheKey; + lastDimensionTheme = EditorView.theme({ + '&': { + height, + minHeight, + maxHeight, + width, + minWidth, + maxWidth, + }, + }); + return lastDimensionTheme; +} diff --git a/core/src/useCodeMirror.ts b/core/src/useCodeMirror.ts index 93c034af1..9c7933c1f 100644 --- a/core/src/useCodeMirror.ts +++ b/core/src/useCodeMirror.ts @@ -5,6 +5,7 @@ import { getDefaultExtensions } from './getDefaultExtensions'; import { getStatistics } from './utils'; import { type ReactCodeMirrorProps } from '.'; import { TimeoutLatch, getScheduler } from './timeoutLatch'; +import { scrollerTheme, getDimensionTheme } from './theme/dimensionTheme'; export const ExternalChange = Annotation.define(); const TYPING_TIMOUT = 200; // ms @@ -45,19 +46,7 @@ export function useCodeMirror(props: UseCodeMirror) { const [state, setState] = useState(); const typingLatch = useState<{ current: TimeoutLatch | null }>(() => ({ current: null }))[0]; const pendingUpdate = useState<{ current: (() => void) | null }>(() => ({ current: null }))[0]; - const defaultThemeOption = EditorView.theme({ - '&': { - height, - minHeight, - maxHeight, - width, - minWidth, - maxWidth, - }, - '& .cm-scroller': { - height: '100% !important', - }, - }); + const defaultThemeOption = getDimensionTheme(height, minHeight, maxHeight, width, minWidth, maxWidth); const updateListener = EditorView.updateListener.of((vu: ViewUpdate) => { if ( vu.docChanged && @@ -96,7 +85,12 @@ export function useCodeMirror(props: UseCodeMirror) { basicSetup: defaultBasicSetup, }); - let getExtensions = [updateListener, defaultThemeOption, ...defaultExtensions]; + let getExtensions = [ + updateListener, + ...(defaultThemeOption ? [defaultThemeOption] : []), + scrollerTheme, + ...defaultExtensions, + ]; if (onUpdate && typeof onUpdate === 'function') { getExtensions.push(EditorView.updateListener.of(onUpdate));