@uipath/du-utils
v1.0.0-rc.2
Published
Framework-agnostic loaders and TypeScript contracts for embedding the UiPath Document Understanding web components (Validation Station and Classification Station).
Readme
@uipath/du-utils
Framework-agnostic utilities for embedding the UiPath Document Understanding web components — Validation Station and Classification Station — in any web application.
This package lets a host application load a DU web component from a deployment URL you control (a path or origin you host the built assets on) and interact with it through strongly-typed custom elements. It has no Angular/React dependency and works in plain HTML, React, Angular, or any other framework.
What's in the box
loadValidationStationWebComponent/loadClassificationStationWebComponent— load a web component's assets from a deployment URL and register its custom element.- TypeScript contracts for the registered custom elements — element interfaces, event maps, and
ambient
HTMLElementTagNameMap/ JSX augmentations soquerySelector,viewChild, and JSX all return the right types. - Shadow-DOM styling helpers used by the components' own bootstrap (advanced).
import {
loadValidationStationWebComponent,
loadClassificationStationWebComponent,
type IValidationStationWcElement,
type IValidationStationWcEventMap,
} from '@uipath/du-utils';Install
# npm
npm install @uipath/du-utils
# yarn
yarn add @uipath/du-utils
# pnpm
pnpm add @uipath/du-utilsThe only runtime dependency is @uipath/uipath-typescript
(the DU SDK types the Validation Station contract is built on).
Loading a web component
Point the loader at the URL where the web component's build artifacts are served. It injects the
component's <script type="module"> files (polyfills.js, then main.js) and a <link> to
cache-warm the theme (styles.css), then resolves once the component's custom element is
registered.
import { loadValidationStationWebComponent } from '@uipath/du-utils';
await loadValidationStationWebComponent(document, 'https://assets.example.com/du-vs-wc/latest');
// The custom element is now registered — create it and set its inputs.
const el = document.createElement('ui-du-validation-station-wc-element');
el.theme = 'light';
el.language = 'en';
el.platform = { organizationName: 'acme', tenantId: 't1' };
document.body.appendChild(el);The deployment URL is the directory that serves the component's assets:
https://assets.example.com/du-vs-wc/latest/
├── main.js
├── polyfills.js
├── styles.css (theme — preloaded, adopted into the shadow root)
├── fonts.css (opt-in — see `includeFonts`)
├── media/ (the font binaries fonts.css references)
└── du-assets/ (runtime assets: pdf.js, translations, business-rules executor)Deploy the component build's entire output at this URL, not just the
top-level files. media/ and du-assets/ are directories the component
fetches at runtime; if they are missing, the failures surface in the
browser with nothing reported at build time.
Validation Station assets are produced by the
@uipath/du-validation-station-wc
build; Classification Station assets by the corresponding Classification Station web-component build.
A UiPath-hosted deployment serves the full fonts.css (Apollo text fonts + Material Icons). Those
npm packages are built differently — their fonts.css carries Material Icons only — so a base
you assemble by copying files out of one of them still serves includeFonts correctly, it just
supplies the icons rather than the whole Apollo set.
Options
await loadValidationStationWebComponent(document, deploymentUrl, { includeFonts: true });| Option | Default | Description |
|---|---|---|
| includeFonts | false | Inject a light-DOM <link rel="stylesheet"> to the component's fonts.css. Requires both fonts.css and the sibling media/ directory it references to be served at the deployment URL. What you get depends on how that base was built: a UiPath-hosted deployment serves Apollo text fonts + Material Icons, while a base assembled from the component's npm package serves Material Icons only. Leave it false when the host already loads Apollo globally (e.g. Action Center, DU Center) to avoid double-loading. |
With
includeFonts: falsethe loader injects no fonts at all — including the icon font. That is correct for hosts that already load Apollo globally (Action Center, DU Center), because Apollo'sfont.csscontains Material Icons. A host that loads neither will render every icon as its ligature text (menu,close, …) — setincludeFonts: true, or link the deployment'sfonts.cssyourself.
Idempotency & caching
Each component is loaded once per page: the load promise is cached on window per component,
so calling the loader again returns the same promise without re-injecting scripts. A later call
with { includeFonts: true } still injects the fonts stylesheet against the already-resolved base,
so opting into fonts after an initial load works.
Trailing slashes on the deployment URL are normalized, so .../latest and .../latest/ behave
identically.
Typed custom elements
Once a component is loaded, its custom element is available with full type support. The
HTMLElementTagNameMap and React.JSX.IntrinsicElements augmentations are ambient — they
apply as soon as the package is referenced, so querySelector / viewChild / JSX return the typed
element with no cast.
| Element tag | Interface |
|---|---|
| <ui-du-validation-station-wc-element> | IValidationStationWcElement |
| <ui-du-validation-station-wc-persistent-element> | IPersistentValidationStationWcElement |
| <ui-du-classification-station-wc-element> | IClassificationStationWcElement |
The standalone element variants ship their own type declarations in
@uipath/du-validation-station-wc— see that package for typed consumption of those.
React
import { useEffect, useRef } from 'react';
import {
loadValidationStationWebComponent,
type IValidationStationWcElement,
type IValidationStationWcEventMap,
} from '@uipath/du-utils';
function ValidationStation({ deploymentUrl }: { deploymentUrl: string }) {
const ref = useRef<IValidationStationWcElement | null>(null);
useEffect(() => {
void loadValidationStationWebComponent(document, deploymentUrl);
}, [deploymentUrl]);
useEffect(() => {
const el = ref.current;
if (!el) return;
el.platform = { organizationName: 'acme', tenantId: 't1' };
// addEventListener overloads give a typed `event.detail`.
const onSaveResult = (e: CustomEvent<IValidationStationWcEventMap['saveResult']>) =>
console.log('saved ok?', e.detail.success);
el.addEventListener('saveResult', onSaveResult);
return () => el.removeEventListener('saveResult', onSaveResult);
}, []);
// React 19: pass inputs directly as JSX props (augmentation is automatic).
return <ui-du-validation-station-wc-element ref={ref} theme="light" language="en" />;
}Angular
Angular passes inputs as element properties and listens to outputs as DOM events via (eventName)
binding. The HTMLElementTagNameMap augmentation makes viewChild / querySelector return the
typed element.
import { Component, viewChild } from '@angular/core';
import {
loadValidationStationWebComponent,
type IValidationStationWcElement,
type IValidationStationWcEventMap,
} from '@uipath/du-utils';
@Component({
template: `
<ui-du-validation-station-wc-element
#vsWc
[theme]="theme"
[platform]="platform"
(saveResult)="onSaveResult($event)"
/>
`,
})
export class ValidationStationComponent {
readonly vsWc = viewChild.required<IValidationStationWcElement>('vsWc');
constructor() {
void loadValidationStationWebComponent(document, this.deploymentUrl);
}
onSaveResult(e: CustomEvent<IValidationStationWcEventMap['saveResult']>): void {
console.log('save ok?', e.detail.success);
}
}The event maps (IValidationStationWcEventMap, IClassificationStationWcEventMap) map every event
name to the type carried in CustomEvent.detail — e.g. loaded: boolean,
fieldValueChanged: IFieldValueDetailsDto, saveResult: ISaveResult,
actionCenterTaskComplete: number. Import the detail types you need directly from this package.
