Utils
utils/ holds the non-visual half of the library: 32 modules of date maths, device
detection, URL and file helpers, cookie access, email parsing and the small generic
helpers the components lean on. Every one of them is re-exported from utils/index.ts,
and from there from the package root.
Importing
Two ways, and which one is right depends on who you are.
// Applications: import by subpath. The exports map serves every module
// directly, so the bundler drops what you do not use.
import { isMobile } from "@onlyoffice/apps-ui-kit/utils/device";
import { formatDate } from "@onlyoffice/apps-ui-kit/utils/date";
// DocSpace plugins: the root barrel is the only entry the portal exposes.
// A subpath import throws at plugin load.
import { isMobile, formatDate } from "@onlyoffice/apps-ui-kit";
The portal hands a plugin its own mounted copy of the kit through a one-line re-export of the root barrel and refuses every subpath, so for a plugin the barrel is the API. The client does the opposite and imports by subpath everywhere. Do not carry one convention into the other.
Dates and durations
utils/date is the largest module — 60 exports, all built on
luxon. It replaces moment.js across the kit and keeps
the portal's timezone handling in one place.
import {
parseISO,
formatDateLocalized,
fromNow,
isSameDay,
} from "@onlyoffice/apps-ui-kit/utils/date";
const created = parseISO(file.created); // DateTime | null
formatDateLocalized(created, "DATE_MED", { locale: "en" }); // "Sep 21, 2026"
fromNow(created, { addSuffix: true }); // "3 days ago"
isSameDay(created, new Date()); // false
formatDateLocalized takes one of luxon's presets — DATE_SHORT, DATE_MED,
DATE_FULL, TIME_SIMPLE, DATETIME_MED and so on — not a format string; formatDate
is the one that takes a pattern, and it converts moment.js tokens for you when passed
{ convertFromMomentFormat: true }. fromNow returns a bare duration ("3 days") unless
you ask for addSuffix.
setDefaultLocale and setDefaultTimezone are process-wide: call them once at app
startup, not per render.
Device, viewport and DOM
mobile, tablet, desktop and mobileMore are media-query strings, so they work
both in window.matchMedia and in a SCSS-free inline style guard:
import { mobile, isMobile, checkIsSSR } from "@onlyoffice/apps-ui-kit/utils/device";
if (!checkIsSSR() && window.matchMedia(mobile).matches) {
// ...
}
Prefer the useIsMobile / useIsDesktop hooks over calling isMobile() in render — the
hooks subscribe to the media query and re-render, the functions read it once.
URLs, files and icons
import { combineUrl } from "@onlyoffice/apps-ui-kit/utils/combineUrl";
import { iconSize32 } from "@onlyoffice/apps-ui-kit/utils/image-helpers";
combineUrl("https://portal.example.com/", "/api/2.0", "files");
// "https://portal.example.com/api/2.0/files"
const FileIcon = iconSize32.get("docx.svg"); // a React component, not a URL
return FileIcon ? <FileIcon /> : null;
The map keys carry no leading dot: an extension of .docx looks up as "docx.svg".
The kit's own drag-and-drop surface is the Dropzone component; reach for useDropzone
only when you are building a different one.
Browser state
Every one of these is SSR-safe: with no document they return undefined rather than
throwing.
Text, i18n and validation
import { parseAddress, EmailSettings } from "@onlyoffice/apps-ui-kit/utils/email";
parseAddress("jane@example.com").isValid(); // true
parseAddress("a@b.com, c@d.com").parseErrors?.[0]?.errorKey; // "ManyEmails"
// A display name is rejected unless the settings allow it.
const settings = new EmailSettings();
settings.allowName = true;
const parsed = parseAddress('"Jane Doe" <jane@example.com>', settings);
parsed.name; // "Jane Doe"
parsed.email; // "jane@example.com"
EmailSettings also toggles punycode in the domain and the local part, IP-literal
domains, spaces, strict local parts and local domain names — each defaulting to the
portal's own rules.
Portal domain helpers
These encode DocSpace concepts rather than generic browser behaviour.
Small generic helpers
What is deliberately not in the barrel
Three modules ship in the package and resolve by subpath, but are left out of
utils/index.ts — so they are not reachable from a DocSpace plugin:
utils/socket—SocketHelper,SocketEventsandSocketCommands, the portal's WebSocket singleton. It is the only importer ofsocket.io-client, which is an optional peer dependency, and it is meaningless without a DocSpace portal to talk to.utils/interop-default— a Node CJS/ESM interop shim used by the build, not application code.utils/add-log— socket logging gated onwindow.ClientConfig.
Everything else under utils/ is in the barrel. See docs/public-api.md in the
repository for the full public-versus-portal-internal tiering.