Mohammad Shahheydar
Mohammad Shahheydar

Reputation: 31

monaco editor / react add view zone

i monaco-editor/react in my project . Somewhere in the project, I want to add a view zone to the editor, but the addZone method in Monaco does not accept the react component (jsx) editor. I asked gpt chat and he suggested using ReactDOM?.render. code:

const onMouseDown = useCallback((e: monacoEditor.editor.IEditorMouseEvent) => {
    if (e.event.target.classList.contains('myGlyphMarginClass')) {
      const zone = document.createElement('div');
      zone.className = 'my-custom-zone';
      zone.style.zIndex = '1000';

      editorRef.current?.getModifiedEditor().changeViewZones(accessor => {
        const zoneId = accessor.addZone({
          afterLineNumber: e.target.position?.lineNumber ?? 0,
          domNode: zone,
          heightInPx: 5
        });
        setZoneId(zoneId);
      });

      ReactDOM?.render(
        <CommentForm
          onMount={(height) => {
            setZone({ height: 1, domNode: zone, line: e.target.position?.lineNumber });
          }}
        />,
        zone
      );
    }
  }, []);

Is there any other way I can do this?

My main problem is that I want the height of the view zone to be dynamic (the height of its content), and for this I have to render it once on the page, calculate its height, delete the previous one and render it again with the correct height. This is the code I wrote to delete and re-render. But zone?.domNode.children[0].clientHeight is sometimes 0

useEffect(() => {
    console.log('maybe null', zone , zoneId);
    if (zone && zoneId) {
      const height = zone?.domNode.children[0].clientHeight
      editorRef.current?.getModifiedEditor().changeViewZones(accessor => {
        accessor.removeZone(zoneId)
        const newZoneId = accessor.addZone({
          afterLineNumber: zone?.line ?? 0,
          domNode: zone.domNode,
          heightInPx: height
        });
        accessor.layoutZone(newZoneId)
        setZone(undefined)
        setZoneId(undefined)
      });
    }
  }, [zone, zoneId]);

CommentForm.tsx:

const CommentForm = ({ onMount }: { onMount: (height: number) => void }) => {

  const ref = useRef<HTMLDivElement>(null);
  const [height, setHeight] = useState<number>();

  useEffect(() => {
    if (ref.current)
      setHeight(ref?.current.offsetHeight);
  }, []);

  useEffect(() => {
    console.log('use effect call', height);
    if (height)
      onMount(height);
  }, [height, onMount]);

  return (
    <div ref={ref} style={{ backgroundColor: 'red', width: '100%', height: 'fit-content' }}>
      <textarea
        rows={4}
        style={{
          width: '100%',
          padding: '18px',
          height: 'fit-content',
          color: 'black',
          backgroundColor: 'rgba(0,146,250,0.5)'
        }}
        onChange={(e) => console.log(e.target.value)}
      >
      </textarea>
    </div>
  );
};

DiffEditor:

<DiffEditor
        height={'100%'}
        width={'100%'}
        originalLanguage={'json'}
        modifiedLanguage={'json'}
        original={oldDash}
        modified={newDash}
        language="json"
        theme={'light'}
        onMount={editor => {
          editorRef.current = editor;
          editor.getModifiedEditor().onMouseMove(onMouseMove);
          editor.getModifiedEditor().onMouseLeave(onMouseLeave);
          editor.getModifiedEditor().onMouseDown(onMouseDown);
        }}
        options={{
          fontSize: 20,
          glyphMargin: true,
          readOnly: true,
          folding: true,
          hideUnchangedRegions: {
            enabled: true,
            revealLineCount: 20,
            minimumLineCount: 1,
            contextLineCount: 1
          }
        }}
      />

I looked everywhere but there was no documentation for monaco editor in react (except the npm package home page but that was also very incomplete)

Upvotes: 0

Views: 57

Answers (0)

Related Questions