suren-atoyan / monaco-react

Monaco Editor for React - use the monaco-editor in any React application without needing to use webpack (or rollup/parcel/etc) configuration files / plugins
https://monaco-react.surenatoyan.com/
MIT License
3.67k stars 262 forks source link

Exporting the Editor in a window using React Portals #387

Open flightmodee opened 2 years ago

flightmodee commented 2 years ago

Hello! I am currently building a React web app embedding a Monaco Editor. I would like to be able to export the editor out of the main app in a window, so it can be displayed on a secondary screen, for example.

I have managed to work my way to a somewhat functional solution using React Portals, but it's lackluster in many ways: the cursor doesn't show when it should (it seems focus is lost whenever I actually click on the editor), it's impossible to use common keyboard shortcuts whenever focus is lost (yet I can still write in the editor), and it is fairly slow. Has anyone tried this approach, or could give me glimpses of hints? Any help would be immensely appreciated.

suren-atoyan commented 2 years ago

@flightmodee here is an example where Editor is being rendered in a portal - don't see any issues.

so it can be displayed on a secondary screen, for example

what does exactly secondary screen mean? can be dialog considered a secondary screen?

briangrider commented 2 years ago

Hi there @suren-atoyan! I'm facing the same issues. I believe @flightmodee is referring to using window.open to move the editor to a new browser window which can then be moved to a secondary monitor/screen. The issue is that the window object needs to be updated so that the Monaco/editor instance always uses the current root of the editor container. When it is loaded in the window object, this should be the window object (and this works how it should). When it is loaded in a new window, the root should be the new window (this doesn't seem to work).

I believe this could be fixed by adding a prop like "currentWindow" where the user can pass in whatever window object they'd like (this would default to window when unset). This currentWindow prop would need to be passed to the loader script (probably through the config settings) here: https://github.com/suren-atoyan/monaco-loader/blob/master/src/loader/index.js

and then anywhere in that script where you have window or document hardcoded (currently lines 57, 58, 59, 114, 78, 87) you would replace those with the currentWindow config setting (or currentWindow.document for document) that was passed from the prop. If unset, it would default to window. This will also make the loader script more flexible (even when not used with the monaco-react component). I'm sure I'm oversimplifying things, but I think this should work or be close to working!

Separate question but just curious... is there a reason you don't allow the config options to be passed as a prop to the Editor component and then sent to the loader with loader.config() before loader.init() in Editor.js on line 51?

briangrider commented 2 years ago

@suren-atoyan Well, I spent all day working on modifying the code and I got all of the monaco js files to open and init in the new window but it didn't solve the issue. I'm not really sure what's going on here but I'm sure you'll be able to solve it easily.

So just to summarize, the issue is:

When using window.open with React Portal to send a react component into a new window (to be used on a separate screen, etc.), the user can no longer click in the code editor without removing focus from the code editor entirely. To get the cursor to display at all, I have to tab back and forth until I find it and then I can type and things seem to work as expected until I try clicking anywhere on the editor again. Also, all hotkeys are broken, for example F1 opens google help in a new window instead of opening commands in the editor.

It would be incredible if you could get this working... please let me know if there is anything I can do to help!

briangrider commented 2 years ago

@suren-atoyan Hi there, Just wanted to see if you had a chance to look over this thread. Thank you in advance!

suren-atoyan commented 2 years ago

hi @briangrider, sorry for the late answer.

I've just checked the thread. I've never tried to render the same instance of monaco on a separate screen - this is something new for me. To save some time I would like to ask you to create a reproducible snippet/repo demonstrating the issue. Thanks in advance.

briangrider commented 2 years ago

Hi @suren-atoyan,

Thanks for the response! I should clarify, I'm not concerned with the same instance of the editor being created on the new screen... it's fine if it creates a new instance, it just doesn't work at all once it's in the newWindow.

Here's a codesandbox showing the problem:

https://codesandbox.io/s/awesome-raman-mwy79e

Thank you!

gt-tm-3310 commented 7 months ago

@briangrider , @flightmodee , @suren-atoyan could you please let me know if there is any update on this issue? Have you managed to find a workaround for this?