1- import React , { useState , useEffect , useRef } from 'react' ;
1+ import React , { useState , useEffect , useRef , useCallback } from 'react' ;
22import { Box , Text , Link as ChakraLink , Heading , useColorModeValue , useColorMode } from '@chakra-ui/react' ;
33import MonacoEditor from '@monaco-editor/react' ;
44import ReactMarkdown from 'react-markdown' ;
55import debounce from 'lodash/debounce' ;
66
7+ function calculateChildrenHeight ( parentDiv ) {
8+ let childrenHeight = 0 ;
9+ const children = parentDiv . children ;
10+ for ( let i = 0 ; i < children . length ; i ++ ) {
11+ childrenHeight += children [ i ] . offsetHeight ;
12+ }
13+ return childrenHeight ;
14+ }
15+
716const ChakraMarkdown = React . memo < any > ( ( { content } ) => {
8- const { colorMode } = useColorMode ( ) ;
9- const editorRef = useRef ( ) ;
10- const monacoTheme = colorMode === 'dark' ? 'vs-dark' : 'vs-light' ;
11- const [ editorHeight , setEditorHeight ] = useState ( 0 ) ;
1217 const renderers = {
1318 h1 : ( { children } ) => < Heading as = "h1" size = "xl" mb = { 2 } > { children } </ Heading > ,
1419 h2 : ( { children } ) => < Heading as = "h2" size = "lg" mb = { 2 } > { children } </ Heading > ,
@@ -19,32 +24,88 @@ const ChakraMarkdown = React.memo<any>(({ content }) => {
1924 </ ChakraLink >
2025 ) ,
2126 code : ( { inline, children, className } ) => {
27+ const { colorMode } = useColorMode ( ) ;
28+ const monacoTheme = colorMode === 'dark' ? 'vs-dark' : 'vs-light' ;
29+
30+ const codeContainerRef = useRef ( null ) ;
31+
32+
33+
2234 const language = className ? className . replace ( 'language-' , '' ) : 'plaintext' ;
2335 const code = String ( children ) . trim ( ) ;
36+
37+ const lines = code . split ( '\n' ) . length ;
38+ const lineHeight = 18 ; // Approximate height of each line in pixels
39+ // const horizonalScrollBarHeight = 12;
40+ // const totalHeight = lines * lineHeight + horizonalScrollBarHeight;
41+ const defaultHeight = lines * lineHeight ;
42+ // setEditorHeight(`${totalHeight}px`);
43+
44+ const heightRef = useRef ( defaultHeight ) ;
45+ const [ editorHeight , setEditorHeight ] = useState ( defaultHeight ) ;
46+ heightRef . current = editorHeight ;
47+
2448 if ( inline ) {
2549 return < Text as = "code" bg = { useColorModeValue ( "gray.100" , "gray.700" ) } p = "1" borderRadius = "md" > { code } </ Text > ;
2650 }
51+
52+ const updateHeight = useCallback ( ( ) => {
53+ // setEditorHeight(defaultHeight);
54+ // setTimeout(() => {
55+ const childrenHeight = calculateChildrenHeight ( codeContainerRef . current ) ;
56+ const scrollHeight = codeContainerRef . current ?. scrollHeight ;
57+ const offsetHeight = codeContainerRef . current ?. offsetHeight ;
58+ // const newHeight = Math.max(childrenHeight);
59+ console . log ( 'resize' , 'childrenHeight' , childrenHeight ) ;
60+ console . log ( 'resize' , 'scrollHeight' , scrollHeight ) ;
61+ console . log ( 'resize' , 'clientHeight' , codeContainerRef . current . clientHeight ) ;
62+ console . log ( 'resize' , 'offsetHeight' , codeContainerRef . current . offsetHeight ) ;
63+ console . log ( 'resize' , 'editorHeight' , heightRef . current ) ;
64+
65+ // if (editorHeight < childrenHeight) {
66+ // setEditorHeight(childrenHeight);
67+ // } else {
68+ // const scrollHeight = codeContainerRef.current?.scrollHeight;
69+ // const offsetHeight = codeContainerRef.current?.offsetHeight;
70+ // const newHeight = Math.max(childrenHeight, scrollHeight, offsetHeight);
71+ // setEditorHeight(newHeight);
72+ // }
73+ // if (newHeight > defaultHeight && editorHeight !== newHeight) {
74+
75+ // }
76+
77+ if ( heightRef . current <= childrenHeight ) {
78+ const newHeight = Math . max ( childrenHeight , scrollHeight ) ;
79+ setEditorHeight ( newHeight ) ;
80+ } else {
81+ const newHeight = Math . min ( childrenHeight , scrollHeight ) ;
82+ setEditorHeight ( newHeight ) ;
83+ }
84+
85+
86+ // const scrollHeight = codeContainerRef.current?.scrollHeight;
87+ // console.log('resize', 'scrollHeight', scrollHeight);
88+ // setEditorHeight(scrollHeight);
89+
90+ // }, 0);
91+ } , [ editorHeight ] ) ;
92+
2793 useEffect ( ( ) => {
28- const lines = code . split ( '\n' ) . length ;
29- const lineHeight = 18 ; // Approximate height of each line in pixels
30- // const horizonalScrollBarHeight = 12;
31- // const totalHeight = lines * lineHeight + horizonalScrollBarHeight;
32- const totalHeight = lines * lineHeight ;
33- // setEditorHeight(`${totalHeight}px`);
34- } , [ children ] ) ;
94+ return ( ) => {
95+ window . removeEventListener ( 'resize' , updateHeight ) ;
96+ console . log ( 'unmount' ) ;
97+ // updateHeight.cancel(); // Cancels the debounced function
98+ } ;
99+ } , [ ] ) ;
35100 return (
36101 < Box
37102 border = "1px solid"
38103 borderColor = { useColorModeValue ( "gray.200" , "gray.600" ) }
39104 borderRadius = "0"
40105 overflow = "visible"
41- onResize = { ( ) => {
42- console . log ( 'resize' ) ;
43- setEditorHeight ( 0 ) ;
44- } }
45- my = { 2 } >
106+ my = { 2 }
107+ >
46108 < MonacoEditor
47-
48109 height = { editorHeight }
49110 language = { language }
50111 theme = { monacoTheme }
@@ -55,16 +116,15 @@ const ChakraMarkdown = React.memo<any>(({ content }) => {
55116 scrollBeyondLastLine : false ,
56117 lineNumbers : "off" ,
57118 scrollbar : { vertical : 'hidden' } ,
58- overviewRulerLanes : 0 , // Disable the overview ruler
59- hideCursorInOverviewRuler : true , // Hide cursor in the ruler
60- folding : false , // Disable code folding
61- glyphMargin : false , // Hide the glyph margin (left margin with icons)
62- renderLineHighlight : 'none' , // Disable the current line highlight
119+ overviewRulerLanes : 0 ,
120+ hideCursorInOverviewRuler : true ,
121+ folding : false ,
122+ glyphMargin : false ,
123+ renderLineHighlight : 'none' ,
63124 cursorWidth : 1 ,
64125 wordWrap : 'on' ,
65126 } }
66- onMount = { ( editor , monaco ) => {
67- console . log ( 'mount' ) ;
127+ onMount = { ( editor ) => {
68128 const keepIds = [ "editor.action.clipboardCopyAction" ] ;
69129 const contextmenu = editor . getContribution ( 'editor.contrib.contextmenu' ) ;
70130 const realMethod = contextmenu . _getMenuActions ;
@@ -75,65 +135,35 @@ const ChakraMarkdown = React.memo<any>(({ content }) => {
75135 } ) ;
76136 } ;
77137
78- console . log ( 'editor' , editor ) ;
79- const el = editor . _domElement ;
80- console . log ( 'el' , el ) ;
81- const codeContainer = el ?. querySelector ?.( '.view-lines' ) ;
82- console . log ( 'codeContainer' , codeContainer ) ;
83-
84-
85- let prevLineCount = 0 ;
86-
87- const LINE_HEIGHT = 18 ;
88- const CONTAINER_GUTTER = 10 ;
89-
90- window . addEventListener ( 'resize' , debounce ( function ( event ) {
91- // Your code here
92- // console.log('Window resized to: ', window.innerWidth, window.innerHeight);
93- // const lines = code.split('\n').length;
94- // const lineHeight = 18; // Approximate height of each line in pixels
95- // // const horizonalScrollBarHeight = 12;
96- // // const totalHeight = lines * lineHeight + horizonalScrollBarHeight;
97- // const totalHeight = lines * lineHeight;
98- // if (editorHeight === totalHeight) {
99- // setEditorHeight(totalHeight-lineHeight); // Force change
100- // } else {
101- // setEditorHeight(totalHeight);
102- // }
103-
104- if ( codeContainer . offsetHeight > 0 ) {
105- // el.style.height = codeContainer.offsetHeight + 'px';
106- const newHeight = codeContainer . offsetHeight ;
107- if ( editorHeight !== newHeight ) {
108- setEditorHeight ( newHeight ) ;
109- }
110- // editor.layout();
111- }
112- } , 200 ) ) ;
113-
114- editor . onDidChangeModelDecorations ( ( ) => {
115- // wait until dom rendered
116- setTimeout ( ( ) => {
117- console . log ( 'codeContainer.offsetHeight' , codeContainer ?. offsetHeight ) ;
118- if ( codeContainer . offsetHeight > 0 ) {
119- // el.style.height = codeContainer.offsetHeight + 'px';
120- const newHeight = codeContainer . offsetHeight ;
121- setEditorHeight ( newHeight ) ;
122- // editor.layout();
123- }
124- // const height =
125- // codeContainer.childElementCount > prevLineCount
126- // ? codeContainer.offsetHeight // unfold
127- // : codeContainer.childElementCount * LINE_HEIGHT + CONTAINER_GUTTER; // fold
128- // prevLineCount = codeContainer.childElementCount;
129- } , 10 ) ;
138+ const codeContainer = editor . _domElement ?. querySelector ( '.view-lines' ) ;
139+ codeContainerRef . current = codeContainer ; // Assign the ref
140+ // if (codeContainer?.offsetHeight > 0) {
141+ // setEditorHeight(codeContainer.offsetHeight);
142+ // }
143+
144+ console . log ( editor ) ;
145+
146+ window . addEventListener ( 'resize' , updateHeight ) ;
147+
148+ const eventHandler = editor . onDidChangeModelDecorations ( ( ) => {
149+ const childrenHeight = calculateChildrenHeight ( codeContainerRef . current ) ;
150+ const scrollHeight = codeContainerRef . current ?. scrollHeight ;
151+ const offsetHeight = codeContainerRef . current ?. offsetHeight ;
152+ const newHeight = Math . max ( childrenHeight , scrollHeight , offsetHeight ) ;
153+ console . log ( 'onmount' , 'childrenHeight' , childrenHeight ) ;
154+ console . log ( 'onmount' , 'scrollHeight' , scrollHeight ) ;
155+ console . log ( 'onmount' , 'clientHeight' , codeContainerRef . current . clientHeight ) ;
156+ console . log ( 'onmount' , 'offsetHeight' , codeContainerRef . current . offsetHeight ) ;
157+ setEditorHeight ( newHeight ) ;
158+ eventHandler . dispose ( ) ;
130159 } ) ;
131160 } }
132161 />
133162 </ Box >
134163 ) ;
135164 } ,
136165 } ;
166+
137167 return < ReactMarkdown components = { renderers } children = { content } /> ;
138168} ) ;
139169
0 commit comments