Nutrient Web SDK

Namespace UI

UI Namespace - types for the slot-based UI customization API.

Every visible piece of the SDK UI is a slot - a named placeholder you can fully replace with your own DOM, partially customize (header/body/footer sub-slots), or hide entirely.

Slots are organized by feature domain in UI.Configuration:

Group Slots
tools main (always-visible), contextual (mode-specific)
annotations actions, status, textMarkupInline, deleteConfirm, link, note
contentEditor exitConfirm, downloadConfirm, cannotSavePrompt, fontMismatch, subsetFont
signatures create, list, digitalSigning, digitalStatus
stamps create, list
measurements calibration, settings
documentComparison controls, view
formCreator propertyEditor
sidebar container, plus dynamic custom sidebar panels
standalone commentThread, search, documentEditor, attachmentPreview, passwordPrompt, reloadConfirm, aiAssistant
loader loader (applies to all backend modes)

Every slot accepts one of two forms:

  1. Full replacement - a callback (getInstance, id) => SlotConfiguration that returns render, onMount, and onUnmount. The SDK renders whatever DOM node render returns.
  2. Sub-slot customization - an object { header?, body?, footer? } where each region is its own callback. Regions you omit keep their default rendering.

To hide a slot entirely, return null from render:

ui: { search: (getInstance, id) => ({ render: () => null }) }

The slot callback (getInstance, id, helpers) => { render, onMount?, onUnmount? } is called once when the SDK prepares to render the component — treat its body as the slot's initialization phase. Some slots, like loader and passwordPrompt, can render before load() resolves, so getInstance() returns null until the instance is available. render(params) is called on every re-render.

For most slots, onMount(id) fires once the SDK instance is available, so getInstance() is guaranteed non-null inside it — making it the right place to subscribe to instance events. onUnmount(id) fires once on teardown and is guaranteed to run even when the instance never arrived and onMount was skipped, so setup done in the callback body (timers, listeners) always has a cleanup path; guard instance-dependent cleanup, as getInstance() may still be null. loader and passwordPrompt keep raw mount timing because they can mount and unmount entirely before an instance exists; getInstance() may return null in their lifecycle hooks. Lifecycle hooks are not a place to query the DOM node returned from render, because that node may not be inserted yet.

render is invoked once at mount, then again automatically when the SDK instance becomes available. To re-invoke it on additional changes, call helpers.requestUpdate() from async work, event handlers, lifecycle hooks, or other imperative code (but not synchronously from within render).

Namespace

Example

Full replacement - custom comment thread with lifecycle:

NutrientViewer.load({
ui: {
commentThread: (getInstance, id) => {
const root = document.createElement("div");
return {
render: (params) => {
root.innerText = `Custom comment thread: ${id}`;
return root;
},
onMount: (id) => console.log("Mounted", id),
onUnmount: (id) => console.log("Unmounted", id),
};
},
},
});

Sub-slot customization - add a banner above the search panel:

NutrientViewer.load({
ui: {
search: {
header: (getInstance, id) => ({
render: () => {
const div = document.createElement("div");
div.textContent = "Custom search header";
return div;
},
}),
},
},
});

Hide a slot entirely:

NutrientViewer.load({
ui: {
tools: {
main: (getInstance, id) => ({ render: () => null }),
},
},
});

Preset - hide everything, then selectively restore:

NutrientViewer.load({
ui: {
preset: "minimal", // hides all UI
search: (getInstance, id) => ({
render: () => {
const div = document.createElement("div");
div.textContent = "Only search is visible";
return div;
},
}),
},
});

Runtime update - switch between custom and default UI:

// Apply custom UI at runtime:
instance.setUI({
annotations: {
actions: (getInstance, id) => ({
render: () => {
const div = document.createElement("div");
div.textContent = "Custom annotation actions";
return div;
},
}),
},
});

// Reset to default:
instance.setUI({});

See Also

Interfaces

Type Aliases