---
title: "1.22 release notes"
canonical_url: "https://www.nutrient.io/guides/web/release-notes/1-22/"
md_url: "https://www.nutrient.io/guides/web/release-notes/1-22.md"
last_updated: "2026-09-11T00:00:00.000Z"
description: "Lists important changes for Nutrient Web SDK 1.22"
---

Nutrient Web SDK 1.22 removes the blocks UI customization API deprecated in 1.20, leaving the `ui` slot configuration as the single way to customize the viewer. It also deprecates the collection methods that sit outside the supported API, adds compound mixed-unit measurement labels, an `onInitialPageRender` callback, typed message IDs and locale tags for localization, and `setFocus()` support in PDF JavaScript. See the [changelog](https://www.nutrient.io/guides/web/changelog.md#1.22.0) for full details.

### The blocks UI customization API is removed

The blocks API deprecated in 1.20 is gone. The `ui` slot configuration is now the only supported way to customize the viewer’s UI. **If you still customize through blocks, your customization no longer applies and the viewer renders its default UI.**

`ui._blocks` and root-level block keys are ignored, and each one logs a `console.error` naming the key it ignored. Loading isn’t blocked — a stale configuration still opens the document:

```js

// Removed: block-based customization. Logged and ignored.
NutrientViewer.load({
  ui: {
    _blocks: {
      [NutrientViewer.Interfaces.Search]: ({ props }) => ({
        content: myCustomSearch(props),
      }),
    },
  },
});

// Use the equivalent slot instead.
NutrientViewer.load({
  ui: {
    search: (getInstance, id) => ({
      render: () => myCustomSearch(),
    }),
  },
});

```

Four exports were part of that API and now throw a migration error when accessed, rather than being `undefined`: `NutrientViewer.UI.createBlock`, `NutrientViewer.UI.Recipes`, `NutrientViewer.UI.Decorators`, and `NutrientViewer.UI.Interfaces`.

The rendered DOM is unchanged — every `data-block-id` attribute is preserved — so visual tests and selectors that target them keep working. For the list of slots and what each one replaces, refer to the [UI customization](https://www.nutrient.io/guides/web/user-interface/ui-customization/introduction.md) and [supported slots](https://www.nutrient.io/guides/web/user-interface/ui-customization/supported-slots.md) guides.

### Deprecated collection methods

The SDK’s collection types inherit Immutable’s full method surface, most of which the SDK has never supported. Nineteen of those methods are now marked deprecated in the published type declarations and the API reference, each naming the supported replacement. **No method was removed and every call keeps working**, but the editor now flags them before you build on something that can’t be kept.

| Method         | Replacement                                                                         |
| -------------- | ----------------------------------------------------------------------------------- |
| `asImmutable`  | Build the value once, or use `withMutations()`.                                     |
| `asMutable`    | Use `withMutations()`.                                                              |
| `cacheResult`  | Drop the call — the collections the SDK exposes are already eager.                  |
| `entrySeq`     | Use `entries()`.                                                                    |
| `filterNot`    | Use `filter()` with the predicate negated.                                          |
| `findEntry`    | Use `entries()`, taking the entry you need.                                         |
| `findKey`      | Loop over `entries()`.                                                              |
| `flatten`      | Use `flatMap()`.                                                                    |
| `fromEntrySeq` | Use `Map(entries)`.                                                                 |
| `hasIn`        | Use `get()` followed by `has()`.                                                    |
| `mergeIn`      | Use `update()` followed by `merge()`.                                               |
| `removeIn`     | Use `deleteIn()`, or `update()` followed by `delete()`.                             |
| `setSize`      | Construct the collection with the values it should hold.                            |
| `toIndexedSeq` | Use `values()`.                                                                     |
| `toKeyedSeq`   | Use `entries()`.                                                                    |
| `toMap`        | Use `Map(entries())`.                                                               |
| `toSeq`        | Use `entries()` on a keyed collection, or `values()` on an indexed or set-like one. |
| `toSetSeq`     | Use `values()`.                                                                     |
| `wasAltered`   | Compare the collections with `equals()`.                                            |

### Compound measurements

Measurement labels can show a mixed-unit value — “6 ft 3 in” instead of “6.25 ft” — matching the format Acrobat and Bluebeam Revu author. Compound units are configured per scale, as an ordered list of progressively smaller units, each with its own precision, appended to the scale’s primary unit:

```js

NutrientViewer.load({
  measurementValueConfiguration: (documentScales) => [
    {
      name: "Feet & Inches",
      scale: {
        unitFrom: NutrientViewer.MeasurementScaleUnitFrom.INCHES,
        unitTo: NutrientViewer.MeasurementScaleUnitTo.FEET,
        fromValue: 1,
        toValue: 3
      },
      precision: NutrientViewer.MeasurementPrecision.TWO,
      compoundUnits: [
        {
          unitTo: NutrientViewer.MeasurementScaleUnitTo.INCHES,
          precision: NutrientViewer.MeasurementPrecision.WHOLE
        }
      ],
      selected: true
    },...documentScales
  ]
});

```

The chain is generic across measurement systems — `ft → in`, `m → cm → mm`, `yd → ft → in` — and each annotation renders from its own scale, so a metric scale can’t pick up an imperial sub-unit. A configured sub-unit that isn’t strictly smaller than the scale’s unit falls back to a single-unit label, as do area measurements.

The chain is persisted on the annotation as a multi-entry `/Measure /D` number-format array, so it survives save, reload, and export, and compound measurements authored elsewhere are read back correctly. `instance.setMeasurementScale(scale, { compoundUnits, name })` writes the scale and its chain into the document, so the scale is offered again after reopening without re-supplying `measurementValueConfiguration`.

Compound measurements are standalone mode only. Document Engine ignores the compound chain. For more information, refer to the [measurements](https://www.nutrient.io/guides/web/measurements/configure-measurements.md) guide.

### Per-page initial render callback

`onInitialPageRender` is called once per page, the first time that page renders, which makes time to first rendered page directly measurable instead of something you infer from timers or mutation observers:

```js

const startedAt = performance.now();
let reported = false;

NutrientViewer.load({
  onInitialPageRender: function ({ pageIndex }) {
    if (reported) return;

    reported = true;
    console.log(`page ${pageIndex} rendered after ${performance.now() - startedAt}ms`);
  },
  //...
});

```

The callback fires only on a successful render, so the page already has content drawn when you’re called. It never fires twice for the same page index — zoom, rotation, resize, and scrolling back to a page don’t re-trigger it — and the first call can arrive before `load()` resolves. Pages next to the current one are pre-rendered, so a page can be reported slightly before the reader scrolls to it. The `OnInitialPageRenderCallback` and `InitialPageRenderInfo` types ship in the public declarations.

### Typed message IDs and locale tags

Localization is now typed. Every message ID the SDK ships and every locale it provides a catalog for is suggested as you type, and the types admit that a locale you haven’t loaded yet isn’t there:

```ts

NutrientViewer.I18n.messages.en = { print: "Print document" };

await NutrientViewer.I18n.preloadLocalizationData("de");
NutrientViewer.I18n.messages.de!.print = "Dokument drucken";

await instance.setLocale("de");

```

`locale`, `setLocale()`, `preloadLocalizationData()`, and `loadTextComparison()` autocomplete the shipped locale tags while still accepting a custom tag you push onto `NutrientViewer.I18n.locales`. The `Locale`, `MessageId`, `LocaleMessages`, and `LocaleMessageOverrides` types are part of the public API.

**This is a type-only tightening**: the locale keys of `NutrientViewer.I18n.messages` are now optional, so reading `NutrientViewer.I18n.messages.de.print` no longer compiles. Add a guard, or a non-null assertion after preloading. Runtime behavior is unchanged, and JavaScript integrations are unaffected. For the full list of message IDs, refer to the [localization](https://www.nutrient.io/api/web/documents/Localization.html) guide in the API reference.

### `setFocus()` in PDF JavaScript

Form fields support the `setFocus()` PDF JavaScript method, so a document script can move the cursor into a named field:

```js

this.getField("total").value = "0";
this.getField("total").setFocus();

```

The call previously threw, which discarded the rest of the script — including assignments it had already made. A field on another page is scrolled into view rather than only scrolled to the top of its page.

### Immediate saving for DWS Viewer API sessions

A DWS Viewer API session loaded with `NutrientViewer.load({ container, session })` runs Instant, but was using the save mode meant for Instant being off. It now uses `AutoSaveMode.IMMEDIATE`, the mode Instant implies. **Edits are sent as they’re made instead of being batched to the next flush point**, `hasUnsavedChanges()` reports accurately, and applying redactions completes instead of hanging indefinitely. Passing `instant: false` or an explicit `autoSaveMode` is unaffected.

### Other additions

- `NutrientViewer.Error` ships type declarations instead of being typed as `any`.

- The `inlineWorkers` configuration option moved from `StandaloneConfiguration` to `SharedConfiguration`, so server-backed deployments can opt out of inline workers as well.

- Importing Instant JSON that contains many form field values on JavaScript-backed forms is faster: the document’s calculations run once for the whole import instead of once per value.

- GdPicture is updated to 14.4.8.1. Refer to the [GdPicture changelog](https://www.nutrient.io/guides/dotnet/changelog.md#14.4.8.1) for details.

- The GdPicture WASM components are listed in the Web SDK SBOM.

- The internal static `defaultValues` property is no longer part of the published type declarations.

### Rendering

- Fixes annotation and form field text being dropped when it contains symbols such as ★ (U+2605) that were erroneously classified as emojis.

- Fixes emoji missing from annotation text when using dynamically loaded fonts.

- Fixes incorrect font styles for diacritic characters in PDFs that use configured font substitutions.

- Fixes applying a redaction removing unrelated text on the same page in more cases, including text drawn by a form XObject, an annotation appearance, a soft mask, or a Type 3 glyph.

- Fixes applying a redaction removing unrelated text on the same page when that text is drawn with the `'` or `"` operators.

### Forms and document editing

- Fixes a PDF JavaScript call to `checkThisBox` being ignored on a read-only checkbox or radio button.

- Fixes a text form field showing its previously typed value again when refocused after a PDF JavaScript action changed it.

- Fixes calculated form fields keeping a stale value, and reporting a self-modification error, when their stored values are imported through Instant JSON or XFDF.

- Fixes a crash when processing or exporting large documents whose forms use a calculation order.

- Fixes copied form fields not being fillable on the pages where they appear in some documents.

- Fixes form field text rendering as unrelated symbols when the requested font is missing from the document.

- Fixes symbols like checkmarks being replaced by fallback glyphs in exported and flattened form field appearances when dynamic fonts are enabled.

- Fixes `WidgetAnnotation#isBold` and `isItalic` deserializing as `null` instead of the documented `false` default when the document specifies no font style.

- Fixes non-image payloads being embedded into populated Office document templates. Payloads without a supported image signature, or whose explicit format conflicts with detected image data, are now rejected.

### User interface and accessibility

- Fixes Command/Control-drag failing to create an annotation selection rectangle on pages after the first.

- Fixes a font size, font family, text color, or background color change applied to a plain text annotation with `instance.update()` not appearing in the open inline editor until the editing session ends.

- Fixes an error shown in the sidebar when `ViewState#sidebarOptions` omits the entry for that sidebar.

- Fixes an uncatchable “Content editing not initialized” promise rejection when the content editor is used while a content editing session is being saved.

- Fixes annotation tools becoming usable when read-only mode is disabled on a license without annotation editing.

- Fixes misaligned comments and clipped comment edit fields when a custom `CommentAvatar` renderer is used.

- Fixes content editor errors omitting the underlying cause from their message.

- Fixes unrelated errors being reported as an invalid theme with their original message rewritten.

### Loading, platform, and API reference

- Fixes scrolling through text-heavy documents temporarily blocking interaction with the viewer and the embedding application, by moving synthetic text-selection font serialization to a dedicated worker. Deployments with a strict Content Security Policy should review the [`inlineWorkers`](https://www.nutrient.io/guides/web/troubleshooting/content-security-policy/) configuration option.

- Fixes broken links and missing type descriptions in the API reference.

- Fixes the API reference showing an internal type for the `instant` configuration option.

- Fixes the API reference showing rest parameters as a single array argument instead of `...name`.

- Fixes the `getBlocks` API reference claiming it reads all blocks, and documents that a page reads empty until its text is detected.

- Fixes the documented return value of `setDocumentComparisonMode()`, which described only one of the three outcomes the returned promise can represent.

For a full list of fixes, refer to the [changelog](https://www.nutrient.io/guides/web/changelog.md#1.22.0).

Document Engine 1.5.6 or later can run this release. In server-backed mode, using `SearchType.WORD_BASED`, removing password protection during PDF export, and removing annotation notes after an XFDF roundtrip require Document Engine 1.16.0 or later. Document-defined annotation tab order, `Annotation.createdBy`, `overprintPreview`, and `blackRendering` require Document Engine 1.18.0 or later. Compound measurements are standalone mode only and are ignored by Document Engine. See the [Web SDK and Document Engine compatibility requirements](https://www.nutrient.io/guides/document-engine/viewer/client-integration/web.md#version-compatibility).

For a complete list of changes, bug fixes, and improvements, refer to the [changelog](https://www.nutrient.io/guides/web/changelog.md#1.22.0). For previous release notes, refer to the [Web SDK 1.21 release notes](https://www.nutrient.io/guides/web/release-notes/1-21.md). We appreciate your feedback and contributions as we continue to enhance Nutrient Web SDK.
---

## Related pages

- [1 0](/guides/web/release-notes/1-0.md)
- [1 1](/guides/web/release-notes/1-1.md)
- [1 10](/guides/web/release-notes/1-10.md)
- [1 11](/guides/web/release-notes/1-11.md)
- [1 12](/guides/web/release-notes/1-12.md)
- [1 13 1](/guides/web/release-notes/1-13-1.md)
- [1 13](/guides/web/release-notes/1-13.md)
- [1 14](/guides/web/release-notes/1-14.md)
- [1 15](/guides/web/release-notes/1-15.md)
- [1 16](/guides/web/release-notes/1-16.md)
- [1 17](/guides/web/release-notes/1-17.md)
- [1 18](/guides/web/release-notes/1-18.md)
- [1 19](/guides/web/release-notes/1-19.md)
- [1 2](/guides/web/release-notes/1-2.md)
- [1 20](/guides/web/release-notes/1-20.md)
- [1 21](/guides/web/release-notes/1-21.md)
- [1 3](/guides/web/release-notes/1-3.md)
- [1 4](/guides/web/release-notes/1-4.md)
- [1 5](/guides/web/release-notes/1-5.md)
- [1 6](/guides/web/release-notes/1-6.md)
- [1 7](/guides/web/release-notes/1-7.md)
- [1 8](/guides/web/release-notes/1-8.md)
- [1 9](/guides/web/release-notes/1-9.md)
- [2017 3](/guides/web/release-notes/2017-3.md)
- [2017 6](/guides/web/release-notes/2017-6.md)
- [Update your PSPDFKit for Web to version 2017.7](/guides/web/release-notes/2017-7.md)
- [Upgrade annotations in PSPDFKit Web 2017.8](/guides/web/release-notes/2017-8.md)
- [Explore new features in PSPDFKit for Web 2017.9](/guides/web/release-notes/2017-9.md)
- [New features in the 2018.1 migration guide](/guides/web/release-notes/2018-1.md)
- [PSPDFKit for Web 2018.2 migration insights](/guides/web/release-notes/2018-2.md)
- [Discover the new features in PSPDFKit for Web 2018.3](/guides/web/release-notes/2018-3.md)
- [Explore PSPDFKit for Web 2018.4 features](/guides/web/release-notes/2018-4.md)
- [Explore new features in PSPDFKit 2018.5](/guides/web/release-notes/2018-5.md)
- [Explore PSPDFKit for Web 2018.6 enhancements](/guides/web/release-notes/2018-6.md)
- [Explore the new features in PSPDFKit 2018.7](/guides/web/release-notes/2018-7.md)
- [Key updates in PSPDFKit for Web 2019.1](/guides/web/release-notes/2019-1.md)
- [2019 2](/guides/web/release-notes/2019-2.md)
- [PSPDFKit for Web 2019.3 migration highlights](/guides/web/release-notes/2019-3.md)
- [Essential updates in PSPDFKit for Web 2019.4](/guides/web/release-notes/2019-4.md)
- [PSPDFKit for Web 2019.5 migration insights](/guides/web/release-notes/2019-5.md)
- [Key changes in PSPDFKit for Web 2020.1](/guides/web/release-notes/2020-1.md)
- [Seamless migration to PSPDFKit for Web 2020.2](/guides/web/release-notes/2020-2.md)
- [Upgrade to PSPDFKit Web 2020.3 seamlessly](/guides/web/release-notes/2020-3.md)
- [PSPDFKit Web and Server 2020.4 migration update](/guides/web/release-notes/2020-4.md)
- [Unified CRUD API enhancements for easy migration](/guides/web/release-notes/2020-5.md)
- [PSPDFKit Web 2020.6 migration insights](/guides/web/release-notes/2020-6.md)
- [Upgrade to PSPDFKit for Web 2021.1 with ease](/guides/web/release-notes/2021-1.md)
- [Seamlessly migrate to PSPDFKit for Web 2021.2](/guides/web/release-notes/2021-2.md)
- [2021 3](/guides/web/release-notes/2021-3.md)
- [PSPDFKit 2021.4 migration guide for seamless updates](/guides/web/release-notes/2021-4.md)
- [Migration guide for PSPDFKit 2021.5](/guides/web/release-notes/2021-5.md)
- [2021 6](/guides/web/release-notes/2021-6.md)
- [PSPDFKit 2022.1.1 migration changes](/guides/web/release-notes/2022-1.md)
- [Enhancements in PSPDFKit for Web 2022.2](/guides/web/release-notes/2022-2.md)
- [Explore the new features of PSPDFKit for Web 2022.3](/guides/web/release-notes/2022-3.md)
- [PSPDFKit for Web 2022.4 migration overview](/guides/web/release-notes/2022-4.md)
- [Key improvements in PSPDFKit for Web 2022.5](/guides/web/release-notes/2022-5.md)
- [Discover the key updates in PSPDFKit for Web 2023.1](/guides/web/release-notes/2023-1.md)
- [PSPDFKit 2023.2 migration and updates](/guides/web/release-notes/2023-2.md)
- [Key updates in PSPDFKit for Web 2023.3](/guides/web/release-notes/2023-3.md)
- [Explore key updates in PSPDFKit for Web 2023.4](/guides/web/release-notes/2023-4.md)
- [Key updates in PSPDFKit for Web 2023.5](/guides/web/release-notes/2023-5.md)
- [Essential Nutrient Web SDK 2024.1 migration tips](/guides/web/release-notes/2024-1.md)
- [2024 2](/guides/web/release-notes/2024-2.md)
- [2024 3](/guides/web/release-notes/2024-3.md)
- [2024 4](/guides/web/release-notes/2024-4.md)
- [2024 5](/guides/web/release-notes/2024-5.md)
- [2024 7](/guides/web/release-notes/2024-7.md)
- [2024 8](/guides/web/release-notes/2024-8.md)
- [Upgrading Nutrient Web SDK](/guides/web/release-notes/upgrading.md)

