• CMSnpm version

    • Overview
    • ContentBuilder
    • InviteUserForm
    • LoginForm
    • RenewPasswordForm
    • WysiwygInput
  • UInpm version

    • Overview
    • Accordion
    • AlertBubble
    • AnnouncementBar
    • Avatar
    • AvatarFileInput
    • Badge
    • Button
    • ButtonGroup
    • ButtonList
    • Calendar
    • Checkbox
    • CheckboxButton
    • CheckboxInput
    • CheckboxList
    • Chip
    • ColorRadio
    • ColorRadioGroup
    • Combobox
    • DatePicker
    • DatePickerInput
    • DateRangePicker
    • DateRangePickerInput
    • DatetimePicker
    • DatetimePickerInput
    • Dialog
    • Dropdown
    • Dropzone
    • ErrorMessage
    • FileInput
    • FlashMessages
    • FormComponent
    • Icon
    • IconButton
    • ImageGallery
    • InfoBox
    • Input
    • Label
    • Layout
    • Lightbox
    • ListItem
    • Loader
    • Lozenge
    • Menu
    • Message
    • Modal
    • ✅ ModalDialog
    • ✅ ModalHeader
    • MultiCombobox
    • MultiSelect
    • Pagination
    • Paper
    • Popover
    • Radio
    • RadioGroup
    • RasterImage
    • Select
    • Switch
    • ✅ Tabs
    • TextInput
    • TextLink
    • Textarea
    • TimePicker
    • TimePickerInput
    • Toggle
    • Tooltip
    • Typography
  • Formnpm version

    • Overview
    • AvatarFileInput
    • CheckboxButton
    • CheckboxInput
    • CheckboxList
    • ColorRadioGroup
    • Combobox
    • DatePickerInput
    • DateRangePickerInput
    • DatetimePickerInput
    • Dropzone
    • FileInput
    • Form
    • FormRenderer
    • GpsInput
    • MoneyInput
    • MultiCombobox
    • MultiSelect
    • NumberInput
    • PasswordInput
    • RadioGroup
    • Select
    • TextInput
    • Textarea
    • TimePickerInput
    • Toggle
  • DataGridnpm version

    • Overview
    • DataGrid
    • DataGridCustomExample
    • ExportButton
    • FilterList
    • Filters
    • FiltersButton
    • FulltextInput
    • HiddenColumns
    • HiddenColumnsButton
    • Pagination
    • RowCounts
    • RowsPerPageSelect
    • SelectedRowsToolbar
    • TableV2
    • ToolbarControl
    • ToolbarCustoms
    • ToolbarTabs
  • Wysiwygnpm version

    • Overview
  • Resizernpm version

    • Overview
  • Routernpm version

    • Overview
  • Corenpm version

    • Overview
  • Core-Reactnpm version

    • Overview
  • DnDnpm version

    • Overview
  • Stylesnpm version

    • Overview
  • Localizenpm version

    • Overview
  • Analyticsnpm version

    • Overview
  • Datepickernpm version

    • Overview
  • Icons-generatornpm version

    • Overview
  • Smart-addressnpm version

    • Overview
  • E2Enpm version

    • Overview
  • E2E-Playwrightnpm version

    • Overview

@uxf/icons-generator

CLI that bundles a project's SVG icons into a single sprite and generates the matching TypeScript definitions that power @uxf/ui's <Icon> component.

When to use

Use it in any UXF web project that renders icons through @uxf/ui/icon. From a declarative config (icons.config.js) of inline SVGs and/or Font Awesome Pro references it produces an SVG sprite, one standalone SVG per icon, and a generated icons.ts that:

  • exports ICONS (per-icon { w, h } map) and ICONS_VERSION (md5 of the sprite), and
  • augments @uxf/ui/icon/theme's IconsSet interface, so IconName (keyof IconsSet) autocompletes every icon you declared.

This is a build-time dev tool run via the icons-gen binary. The runtime <Icon> component itself lives in @uxf/ui/icon, not here.

Installation

yarn add -D @uxf/icons-generator

Requires Node >= 24. Peer dependency: @uxf/core (11.114.0). The Font Awesome Pro adapter needs no extra packages — it streams icons from the kit at generation time, so it only needs the @awesome.me scope to resolve through your registry (see Providers).

Quick start

  1. Create icons.config.js in your project root:

    /** @type {import('@uxf/icons-generator/src/types').IconsConfig} */
    module.exports = {
        generatedDirectory: "/public/icons-generated/",
        icons: {
            flame: {
                width: 43,
                height: 48,
                data: `<path fill="#fff" d="M30.84 20.51a1.51 1.51 0 0 0-1.16-.71..." />`,
            },
        },
    };
    
  2. Run the generator:

    icons-gen
    
  3. Wire the generated ICONS + sprite into @uxf/ui and render icons (see Integration).

CLI

icons-gen [options]
FlagAliasDefaultDescription
--configFile-cicons.config.jsPath to the config file, resolved from cwd.
--help-h—Print help and exit.
icons-gen --configFile=custom.icons.config.js

Configuration

The config file exports an IconsConfig object via module.exports.

KeyTypeDefaultRequiredDescription
iconsPartial<Record<string, SimpleIcon | SizedIcon | IconFromProviderFunction>>—YesIcons to generate, keyed by icon name (see Icon types).
generatedDirectorystring"/public/icons-generated/"NoOutput dir (relative to cwd) for the sprite and standalone SVG files. Must start/end with /.
configDirectorystring"/src/config/"NoOutput dir (relative to cwd) for the generated icons.ts and provider fallbacks. Must start/end with /.
spriteFileNamestring"_icon-sprite.svg"NoSprite file name written into generatedDirectory.
typeNamestring"IconsSet"NoName of the keyof typeof ICONS type exported by the generated file.
typescriptbooleantrueNoEmit icons.ts vs icons.js. See Gotchas.
moduleDefinitionModuleDefinition | falseaugments @uxf/ui/icon/theme (see below)NoControls the declare module type augmentation; false disables it.
customDefinitionContentstring—NoExtra content appended verbatim to the end of the generated definition file.

Icon types

SimpleIcon

A single-size icon.

type SimpleIcon = {
    data: string;
    height: number;
    width: number;
};
flame: {
    width: 43,
    height: 48,
    data: `<path fill="#fff" d="M30.84 20.51a1.51 1.51 0 0 0-1.16-.71..." />`,
}

SizedIcon

Different SVG data per pixel size. Each size produces its own sprite symbol (icon-sprite--<name>_<size>) and standalone file (<name>_<size>.svg).

type SizedIcon = Record<number, string>;
logo: {
    24: `<path fill="#fff" d="..." />`,
    48: `<path fill="#fff" d="..." />`,
}

IconFromProviderFunction

A function that resolves an icon from a provider (e.g. faPro.icon(...)). See Providers.

type IconFromProviderFunction = (config: _IconsConfig) => { width: number; height: number; path: string };

Module augmentation (moduleDefinition)

type ModuleDefinition = {
    moduleName: string;
    typeName: string;
    format: "type" | "interface";
};

Defaults to { moduleName: "@uxf/ui/icon/theme", typeName: "IconsSet", format: "interface" }. With these defaults the generated file emits:

declare module "@uxf/ui/icon/theme" {
    interface IconsSet {
        flame: true;
        // ...one line per icon
    }
}

This augmentation is what makes @uxf/ui/icon's IconName (keyof IconsSet) aware of your icons. Set moduleDefinition: false to skip it.

Providers — Font Awesome Pro adapter

The faPro adapter resolves icons from a Font Awesome kit package (@awesome.me/kit-…), the only distribution channel that carries every style FA 7 offers. Nothing is installed: at generation time the CLI streams the kit tarball, pulls out just the SVGs your config names, and discards the rest. A ~110 MB archive therefore leaves behind a few kilobytes and never lands in node_modules or a Docker image.

Resolution order

For each "<namespace>.<icon-name>" the adapter tries, in order:

  1. An installed @fortawesome/*-svg-icons package — deprecated, kept so existing projects keep building. Using one prints a warning; support is removed in a future major.
  2. The streamed kit package — the supported path.
  3. <configDirectory>/icons-fallbacks/faPro.json — the snapshot written on every successful resolve, so a project without Font Awesome access can still rebuild the icons it already has.

The monolithic @fortawesome/fontawesome-pro is no longer supported at all: the adapter throws if it finds it installed.

Registry access

Kits live in the @awesome.me scope on Font Awesome's own registry, so that scope has to resolve through our Verdaccio (which caches the tarballs, keeping FA bandwidth costs down). See docs/recipes/fontawesome-kit-verdaccio.md for the server side, and docs/migration/fa-pro-kit-stream.md for what a consuming project has to change.

Registry and credentials are read from the same .npmrc and .yarnrc.yml files your package manager uses — npm-based and Yarn-based projects both work without extra configuration.

Namespaces

A namespace is the style directory inside the package, so "regular.calendar-check" resolves to regular/calendar-check.svg. For the classic families it matches what the per-style packages used: brands, regular, solid, light, thin, duotone, duotone-regular, duotone-light, duotone-thin, and the sharp- and sharp-duotone- variants of each. Styles a kit adds on top appear under their own directory name.

The exhaustive list is the generated FaProIconName union in src/fa-pro-types.ts, regenerated by npm run icon-types:gen in this monorepo.

Usage

const { faPro } = require("@uxf/icons-generator/src/providers/fa-pro");

module.exports = {
    generatedDirectory: "/public/icons-generated/",
    icons: {
        // keeps the default name, e.g. "faPro_brands.linkedin"
        ...faPro.adapter(["brands.linkedin"]),
        // or assign a custom name
        twitter: faPro.icon("brands.twitter"),
    },
};

faPro.adapter([...]) names each icon faPro_<namespace>.<name>, while faPro.icon(...) lets you assign a custom key. Both register the icon for the prefetch that runs before generation, so they must be called while the config module is being loaded — which is what the examples above do.

Which kit version, and how it is upgraded

The kit and its version are pinned in src/utils/_faProTarballCache.ts, next to the generated FaProIconName union they belong to. Both ship in this package, so a project gets a matched pair and never has to configure a version: bumping @uxf/icons-generator is how you move to a newer kit.

That also means a warm run needs no registry access at all, and that a kit republished upstream cannot change anybody's sprite behind their back.

Adopting a new kit version is one commit here:

UXF_FA_PRO_VERSION=latest npx tsx packages/icons-generator/scripts/generate-fa-pro-types.ts  # what is out there?
# set DEFAULT_VERSION in src/utils/_faProTarballCache.ts to that version
npm run icon-types:gen

The generator refuses to write a union built from a version other than the pinned one, so the two cannot drift.

Caching

Fetched SVGs and the package's icon-name index are cached under ~/.cache/uxf-icons-generator/fa-pro/v<schema>/<package>_<version>/ — the package and version are slugified, so the real directory looks like v2/_awesome.me_kit-0618a3d496_1.0.2. A run that introduces no new icon performs no network I/O. Point UXF_FA_PRO_CACHE_ROOT somewhere inside the build directory to let CI cache it; a version bump simply misses the cache and refills it.

VariableDefaultPurpose
UXF_FA_PRO_PACKAGE@awesome.me/kit-0618a3d496Source package. Accepts any kit, or @fortawesome/fontawesome-pro.
UXF_FA_PRO_VERSIONthe pinned DEFAULT_VERSIONOverride the version. latest asks the registry — for discovery, not builds.
UXF_FA_PRO_CACHE_ROOT~/.cache/uxf-icons-generatorWhere cached SVGs and the index live.

Generated output

Running icons-gen (re)writes:

  • <generatedDirectory>/<spriteFileName> — the SVG sprite: one <symbol id="icon-sprite--<name>"> per icon (sized icons: icon-sprite--<name>_<size>).
  • <generatedDirectory>/<name>.svg — one standalone SVG per icon (sized: <name>_<size>.svg). SVGs for icons removed from the config are cleaned up on the next run.
  • <configDirectory>/icons.ts — the definition file (see below).
  • <configDirectory>/icons-fallbacks/<provider>.json — cached provider icon data (e.g. faPro.json).

The definition file exports:

// this file is generated automatically, do not change anything manually in the contents of this file

export const ICONS_VERSION = "<md5 of the sprite file>";

export const ICONS = {
    flame: { w: 43, h: 48 },
    logo: [24, 48],
    // ...
} as const;

export type IconsSet = keyof typeof ICONS; // name comes from `typeName`

declare module "@uxf/ui/icon/theme" {
    // omitted when moduleDefinition: false
    interface IconsSet {
        flame: true;
        // ...
    }
}

Integration with @uxf/ui/icon

  1. Run icons-gen (wire it into a gen/prebuild script).

  2. Pass the generated ICONS and sprite path to @uxf/ui's UiContextProvider. Because generatedDirectory lives under public/, the browser URL drops that segment (/public/icons-generated/… → /icons-generated/…):

    import { UiContextProvider, UiContextType } from "@uxf/ui/context";
    import { ICONS, ICONS_VERSION } from "@/config/icons";
    
    const uiConfig: UiContextType = {
        icon: {
            iconsConfig: ICONS,
            spriteFilePath: `/icons-generated/_icon-sprite.svg?v=${ICONS_VERSION}`,
        },
        // ...other UI context options (colorScheme, localeConfig, rasterImage, translationFn)
    };
    
  3. Render icons via @uxf/ui's <Icon>. The name prop autocompletes every generated icon thanks to the module augmentation:

    import { Icon } from "@uxf/ui/icon";
    
    <Icon name="flame" size={24} />;
    
  4. (Optional) Preload the sprite:

    <link as="image" href={`/icons-generated/_icon-sprite.svg?v=${ICONS_VERSION}`} rel="preload" type="image/svg+xml" />
    

Gotchas

  • Dev/build tool only. The <Icon> runtime component is @uxf/ui/icon; this package just generates the sprite and types.
  • Paths are cwd-relative and need slashes. configDirectory and generatedDirectory are joined onto process.cwd(), so both must start and end with /.
  • typescript: false currently has no effect. The generator always emits icons.ts — the flag falls back to true internally.
  • The faPro provider is a deep import: @uxf/icons-generator/src/providers/fa-pro (the published files preserve the src/ layout). The IconsConfig type is at @uxf/icons-generator/src/types.
  • Provider icons are resolved before generation, not lazily. faPro.icon(...) and faPro.adapter([...]) register their names when the config module loads, and the CLI resolves them all in one streamed pass. Building an icon name inside a callback that runs later than config load will not be prefetched.
  • Keep the default moduleName (@uxf/ui/icon/theme) unless you intentionally augment a different module; changing it breaks the @uxf/ui IconName inference.

Links

  • Repository: gitlab.com/uxf-npm/icons-generator
  • Consumed by @uxf/ui/icon (the <Icon> component and IconsSet/IconName types).