Reusable web component and NPM package for remote desktop sessions, built with Svelte.
iron-remote-desktop is protocol-agnostic. It knows nothing about RDP, VNC, or any other
specific remote protocol. It defines only features that are universal across all remote backends:
keyboard and mouse input, canvas rendering and resize, clipboard text/binary, connection
lifecycle, and cursor style.
A backend implements the RemoteDesktopModule interface and plugs in via the module
component property/prop (for example, by assigning element.module = Backend or the
framework-specific equivalent). The RDP backend is iron-remote-desktop-rdp; other backends
can be written against the same interfaces.
Protocol-specific features that have no equivalent in other protocols must never be added to
UserInteraction, Session, or SessionBuilder. They belong in the backend package and are
delivered via the extension mechanism:
// Backend-defined factory (in iron-remote-desktop-rdp):
import { preConnectionBlob, displayControl } from '@devolutions/iron-remote-desktop-rdp';
// Consumer configures protocol-specific behaviour through extensions on the UserInteraction
// instance received from the `ready` event:
ironRemoteDesktop.addEventListener('ready', (event) => {
const ui = event.detail;
const config = ui.configBuilder().withExtension(preConnectionBlob('...')).withExtension(displayControl(true)).build();
ui.connect(config);
});The Extension type is unknown in iron-remote-desktop, opaque by design. The component
passes extension values to the backend without inspection; the backend interprets them.
At runtime, invokeExtension(ext) follows the same pattern for dynamic, post-connect control.
The guiding question for any new UserInteraction / Session / SessionBuilder method:
A method belongs in the base API if either of the following is true:
- The web component itself needs to call it to implement transparent, protocol-independent
behaviour (e.g.,
supportsUnicodeKeyboardShortcuts()is called by the component to adapt keyboard handling, without consumer involvement). - The feature is universal: every reasonable remote protocol backend would implement it in a meaningful way (e.g., resize, clipboard text, cursor style).
If neither applies, it is protocol-specific and must go through extensions.
Make you modification in the source code then use iron-svelte-client to test.
Run npm run build
As member of the Devolutions organization, you can import the Web Component from JFrog Artifactory by running the following npm command:
$ npm install @devolutions/iron-remote-desktopOtherwise, you can run npm install targeting the dist/ folder directly.
Import the iron-remote-desktop.umd.cjs from node_modules/ folder.
Then use the HTML tag <iron-remote-desktop/> in your page.
In your code add a listener for the ready event on the iron-remote-desktop HTML element.
Get evt.detail.irgUserInteraction from the Promise, a property whose type is UserInteraction.
Call the connect method on this object.
Mouse: movement, click (4 buttons), scroll. Keyboard: standard layout, Windows key, Ctrl+Alt+Del. Lock keys (Caps Lock, Num Lock, Scroll Lock, Kana): partial support.
You can add some parameters for default initialization on the component <iron-remote-desktop />.
Note that due to a limitation of the framework all parameters need to be lower-cased.
scale: The scaling behavior of the distant screen. Can befit,realorfull. Default isreal;verbose: Show logs fromiron-remote-desktop.trueorfalse. Default isfalse.debugwasm: Show debug info from web assembly. Can be"OFF","ERROR","WARN","INFO","DEBUG","TRACE". Default is"OFF".flexcentre: Helper to forceiron-remote-desktopa flex and centering the content automatically. Otherwise, you need to manage manually. Default istrue.module: An implementation of the RemoteDesktopModule
Build a Config using configBuilder(), then call connect(config). Protocol-specific
configuration (e.g., pre-connection blob, KDC proxy URL) is passed via extensions on the
ConfigBuilder — see the backend package for available extension factories.
configBuilder(): ConfigBuilder;
connect(config: Config): Promise<NewSessionInfo>;
ctrlAltDel()— Sends Ctrl+Alt+Del to the remote host.
metaKey()— Sends the Windows/Meta key to the remote host.
setVisibility(value: boolean)— Shows or hides the rendering canvas.
setScale(scale: ScreenScale)— Sets canvas scaling behaviour (fit,real, orfull). SeeScreenScale.
shutdown()— Terminates the active session.
setKeyboardUnicodeMode(useUnicode: boolean)— Toggles Unicode keyboard mode.
setCursorStyleOverride(style: string | null)— Overrides cursor style;nullrestores default.
resize(width: number, height: number, scale?: number)— Resizes the remote screen.
setEnableClipboard(enable: boolean)— Enables or disables clipboard synchronization.
setEnableAutoClipboard(enable: boolean)— Enables or disables automatic clipboard polling.
metaKey()Sends the meta key event to remote host (i.e.: Windows key).
setVisibility(value: boolean)Shows or hides rendering canvas.
setScale(scale: ScreenScale)Sets the scale behavior of the canvas. See the ScreenScale enum for possible values.
shutdown()Shutdowns the active session.
setKeyboardUnicodeMode(use_unicode: boolean)Sets the keyboard Unicode mode.
setCursorStyleOverride(style?: string)Overrides the default cursor style. If
styleisnull, the default cursor style will be used.
resize(width: number, height: number, scale?: number)Resizes the screen.
setEnableClipboard(enable: boolean)Enables or disable the clipboard based on the
enablevalue.
invokeExtension(ext: Extension)— Sends a protocol-specific extension command at runtime. The extension value is passed to the backend without inspection.
File transfer is protocol-specific. The iron-remote-desktop package defines only the
protocol-agnostic FileTransferProvider interface; the implementation lives in the backend
package (e.g., RdpFileTransferProvider in @devolutions/iron-remote-desktop-rdp).
import { RdpFileTransferProvider } from '@devolutions/iron-remote-desktop-rdp';
// Create a provider and pass it to the web component
const provider = new RdpFileTransferProvider({ chunkSize: 64 * 1024 });
component.enableFileTransfer(provider);
// Connect as usual - the provider receives builder extensions and session automatically
await component.connect(config);
// Listen for files available for download
provider.on('files-available', async (files) => {
for (let i = 0; i < files.length; i++) {
const { completion } = provider.downloadFile(files[i], i);
const blob = await completion;
saveAs(blob, files[i].name);
}
});
// Track progress
provider.on('download-progress', (progress) => {
console.log(`${progress.fileName}: ${progress.percentage}%`);
});
// Upload files via drag-and-drop or file picker
const dropped = await provider.handleDrop(event);
provider.uploadFiles(dropped);See the @devolutions/iron-remote-desktop-rdp package for the full API, events, and
extension factories.