Angular 工具库 | ng-hub-ui-utils

Angular 工具库,包含 pipes、焦点管理、overlay、过渡和翻译助手,供可复用 UI 组件共享使用。

最后更新 2026年8月26日

概览

团队为何搜索这个库

使用这个 Angular 工具库,避免重写 overlay、焦点陷阱、翻译助手和常见模板工具背后的底层部件。

安装

npm install ng-hub-ui-utils

跳转到

适用于

  • 共享 UI 基础设施
  • overlay 系统
  • 焦点管理
  • 模板助手

关于 utils

ng-hub-ui-utils 是众多可复用 UI 模式背后的共享基础。当 Angular 团队希望集中管理那些让 overlay 系统、焦点管理、pipes 和翻译助手在各项目间保持一致的底层部件时,它会非常有用。

功能指南

焦点管理

在元素内捕获并管理键盘焦点

示例:
焦点捕获

使用 hubFocusTrap() 将焦点限定在 modal 或对话框内。

Focus Trap Demo

Click "Enable Focus Trap" and try to Tab outside the blue box. Focus will stay trapped inside.

Focus Trap Area

Status: 🔓 Free

Focusable Elements

The selector FOCUSABLE_ELEMENTS_SELECTOR finds all focusable elements.

getFocusableBoundaryElements(container)→ [first, last] elements
可聚焦元素

使用 getFocusableBoundaryElements() 查询边界处的可聚焦元素。

Focus Trap Demo

Click "Enable Focus Trap" and try to Tab outside the blue box. Focus will stay trapped inside.

Focus Trap Area

Status: 🔓 Free

Focusable Elements

The selector FOCUSABLE_ELEMENTS_SELECTOR finds all focusable elements.

getFocusableBoundaryElements(container)→ [first, last] elements

国际化(i18n)

用于多语言支持的翻译服务和 pipes

示例:
翻译服务

HubTranslationService 用于管理翻译

TranslatePipe - Basic usage

'welcome' | translate→ Welcome to ng-hub-ui

TranslatePipe - With parameters

'greeting' | translate:{ name: 'Carlos' }→ Hello, Carlos!

TranslatePipe - Nested keys

'buttons.save' | translate→ Save
'buttons.cancel' | translate→ Cancel

Programmatic access

translationService.getTranslation('buttons.delete')→ Delete
翻译 pipe

TranslatePipe 用于模板中的翻译

TranslatePipe - Basic usage

'welcome' | translate→ Welcome to ng-hub-ui

TranslatePipe - With parameters

'greeting' | translate:{ name: 'Carlos' }→ Hello, Carlos!

TranslatePipe - Nested keys

'buttons.save' | translate→ Save
'buttons.cancel' | translate→ Cancel

Programmatic access

translationService.getTranslation('buttons.delete')→ Delete
翻译 provider

provideHubTranslations() 用于应用配置

TranslatePipe - Basic usage

'welcome' | translate→ Welcome to ng-hub-ui

TranslatePipe - With parameters

'greeting' | translate:{ name: 'Carlos' }→ Hello, Carlos!

TranslatePipe - Nested keys

'buttons.save' | translate→ Save
'buttons.cancel' | translate→ Cancel

Programmatic access

translationService.getTranslation('buttons.delete')→ Delete
外部 i18n 适配器

在 app.config.ts 中配置一个响应式翻译桥接器,供所有 Hub UI 库使用。

在 app.config.ts 中配置一个响应式翻译桥接器,供所有 Hub UI 库使用。

代码
导入:
模板:
组件:

覆盖层系统

创建定位的 overlays 和浮动元素

示例:
Overlay 服务

HubOverlayService 用于以编程方式创建 overlay

A connected overlay positioned below the trigger, with a backdrop that closes it on outside click.

Overlay 引用

OverlayRef 用于管理 overlay 的生命周期

A connected overlay positioned below the trigger, with a backdrop that closes it on outside click.

定位

ConnectionPositionPair 用于灵活定位

A connected overlay positioned below the trigger, with a backdrop that closes it on outside click.

Popup 服务

简化的 popup 管理

示例:
Popup 创建

HubPopupService 用于快速创建 popup

A connected overlay positioned below the trigger, with a backdrop that closes it on outside click.

Pipes

用于模板的工具 pipes

示例:
类型检查 pipes

IsStringPipe、IsObjectPipe、IsObservablePipe

GetPipe - Access nested properties

user | get:'profile.name'→ John Doe
user | get:'profile.address.city'→ New York

IsStringPipe - Type checking

'Hello' | isString→ true
123 | isString→ false

IsObjectPipe - Object detection

{ a: 1 } | isObject→ true
'string' | isObject→ false

UcfirstPipe - Capitalize first letter

'hello world' | ucfirst→ Hello world
GetPipe

使用点号表示法访问嵌套对象属性

GetPipe - Access nested properties

user | get:'profile.name'→ John Doe
user | get:'profile.address.city'→ New York

IsStringPipe - Type checking

'Hello' | isString→ true
123 | isString→ false

IsObjectPipe - Object detection

{ a: 1 } | isObject→ true
'string' | isObject→ false

UcfirstPipe - Capitalize first letter

'hello world' | ucfirst→ Hello world
UcfirstPipe

将字符串的首字母大写

GetPipe - Access nested properties

user | get:'profile.name'→ John Doe
user | get:'profile.address.city'→ New York

IsStringPipe - Type checking

'Hello' | isString→ true
123 | isString→ false

IsObjectPipe - Object detection

{ a: 1 } | isObject→ true
'string' | isObject→ false

UcfirstPipe - Capitalize first letter

'hello world' | ucfirst→ Hello world
UnwrapAsyncPipe

在模板中解包 observables 和 promises

GetPipe - Access nested properties

user | get:'profile.name'→ John Doe
user | get:'profile.address.city'→ New York

IsStringPipe - Type checking

'Hello' | isString→ true
123 | isString→ false

IsObjectPipe - Object detection

{ a: 1 } | isObject→ true
'string' | isObject→ false

UcfirstPipe - Capitalize first letter

'hello world' | ucfirst→ Hello world

工具函数

通用的 helper 函数

示例:
Type guards

isString()、isNumber()、isDefined()、isPromise()

Type Guards

isString('hello')→ true
isNumber(42)→ true
isDefined(null)→ false
isDefined('value')→ true

Deep Equality

equals({a:1}, {a:1})→ true
equals([1,2], [1,2])→ true

Object Access

getValue(user, 'profile.name')→ John Doe

String Interpolation

interpolateString('Hello {{name}}', {name: 'World'})→ Hello World

String Utilities

removeAccents('Ñoño café')→ Nono cafe
padNumber(5)→ 05
字符串工具

removeAccents()、interpolateString()、regExpEscape()

Type Guards

isString('hello')→ true
isNumber(42)→ true
isDefined(null)→ false
isDefined('value')→ true

Deep Equality

equals({a:1}, {a:1})→ true
equals([1,2], [1,2])→ true

Object Access

getValue(user, 'profile.name')→ John Doe

String Interpolation

interpolateString('Hello {{name}}', {name: 'World'})→ Hello World

String Utilities

removeAccents('Ñoño café')→ Nono cafe
padNumber(5)→ 05
对象工具

equals() 用于深度比较,getValue() 用于点分表示法

Type Guards

isString('hello')→ true
isNumber(42)→ true
isDefined(null)→ false
isDefined('value')→ true

Deep Equality

equals({a:1}, {a:1})→ true
equals([1,2], [1,2])→ true

Object Access

getValue(user, 'profile.name')→ John Doe

String Interpolation

interpolateString('Hello {{name}}', {name: 'World'})→ Hello World

String Utilities

removeAccents('Ñoño café')→ Nono cafe
padNumber(5)→ 05
DOM 工具

closest()、reflow()、getActiveElement()

Type Guards

isString('hello')→ true
isNumber(42)→ true
isDefined(null)→ false
isDefined('value')→ true

Deep Equality

equals({a:1}, {a:1})→ true
equals([1,2], [1,2])→ true

Object Access

getValue(user, 'profile.name')→ John Doe

String Interpolation

interpolateString('Hello {{name}}', {name: 'World'})→ Hello World

String Utilities

removeAccents('Ñoño café')→ Nono cafe
padNumber(5)→ 05
RxJS 工具

runInZone() 操作符,用于 NgZone 集成

Type Guards

isString('hello')→ true
isNumber(42)→ true
isDefined(null)→ false
isDefined('value')→ true

Deep Equality

equals({a:1}, {a:1})→ true
equals([1,2], [1,2])→ true

Object Access

getValue(user, 'profile.name')→ John Doe

String Interpolation

interpolateString('Hello {{name}}', {name: 'World'})→ Hello World

String Utilities

removeAccents('Ñoño café')→ Nono cafe
padNumber(5)→ 05

Scrollbar 工具

测量并补偿 scrollbar 宽度

示例:
Scrollbar 宽度

scrollbarWidth() 和 scrollbarPadding() 函数

ScrollBar Service

The ScrollBar service helps manage scrollbar visibility and compensate for layout shifts when hiding scrollbars (e.g., when opening modals).

Use Case: Modal Body Lock

When opening a modal, you typically hide the body scrollbar. The ScrollBar.hide() method handles this automatically and returns a reverter function.

Status: 🔓 Normal scrolling

Code Example

import { inject } from '@angular/core';
import { ScrollBar } from 'ng-hub-ui-utils';

export class ModalService {
  private scrollBar = inject(ScrollBar);
  private revertScrollbar: (() => void) | null = null;

  openModal() {
    // Hide scrollbar and get reverter function
    this.revertScrollbar = this.scrollBar.hide();
  }

  closeModal() {
    // Restore scrollbar
    if (this.revertScrollbar) {
      this.revertScrollbar();
      this.revertScrollbar = null;
    }
  }
}

过渡

CSS 过渡辅助函数

示例:
运行过渡

hubRunTransition() 用于以编程方式实现 CSS 过渡

该示例暂不支持实时预览。

提示

通过 [tooltip] 指令为任意元素提供轻量、可主题化的提示。

示例:
提示指令

为元素应用 [tooltip] 并指定位置,即可在悬停或聚焦时显示定位的标签,并可通过 --hub-tooltip-* 变量设置主题。

Placements (hover the buttons)
Themed with --hub-tooltip-* variables

核心特性

最近更改

Version 22.8.0 - 8/14/26, 12:00 AM

added: provideHubTranslationAdapter() — the application-wide reactive bridge from an external translation service (transloco, ngx-translate, i18next…) into HubTranslationService. Register it once at bootstrap and every ng-hub-ui library picks up the host dictionary, re-emitting on every language change. Supports optional namespacing and deliberate per-label reactive overrides.

added: HUB_TRANSLATION_PREFIX — injection token that scopes the lookups of a library to a collision-safe HUBUI.<LIBRARY>.* namespace. TranslatePipe resolves the prefixed key first and falls back to the bare key, so existing flat dictionaries keep working untouched.

Version 22.7.2 - 8/8/26, 12:00 AM

fixed: Documentation links now point at the canonical localized URLs. The README linked to https://hubui.dev/<path> with no locale prefix and no trailing slash, and both forms are 301-redirected, so every reader arriving from npm or GitHub landed on a redirect instead of the canonical page.

Version 22.7.1 - 7/27/26, 12:00 AM

fixed: --hub-overlay-zindex / --hub-overlay-backdrop-zindex actually work now: OverlayRef resolves its inline z-index through var(--hub-overlay-zindex, 1000) / var(--hub-overlay-backdrop-zindex, 999) instead of literal values, so re-stacking an overlay no longer requires !important. Defaults are unchanged.

added: OverlayConfig.zIndex — optional explicit layer for a single overlay instance; when set it takes precedence over the token.

Version 22.7.0 - 7/7/26, 12:00 AM

added: resolveHubAccent(value) — the canonical "any colour" accent resolver shared across the ng-hub-ui family: barewords map to var(--hub-sys-color-<name>, <name>), literal #hex / rgb() / oklch() / var() values pass through unchanged, empty values yield null.

Version 22.6.1 - 7/2/26, 12:00 AM

fixed: CSS variable fallbacks realigned to the ds light defaults (e.g. --hub-ref-font-family-base falls back to the system-ui stack instead of inherit); fallbacks only apply when ng-hub-ui-ds is not loaded.

Version 22.6.0 - 6/30/26, 12:00 AM

added: HubOverflowTooltipDirective ([hubOverflowTooltip]) — shows a tooltip only while the host label is actually truncated, with live tracking via ResizeObserver + MutationObserver.

added: Agnostic tooltip token — HUB_TOOLTIP_ADAPTER plus provideHubTooltip(adapter) let any tooltip implementation back [hubOverflowTooltip], app-wide or per subtree; defaults to the built-in hubTooltipAdapter.