npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@libs-ui/components-process-bar-standard

v0.2.357-4

Published

> Component hiển thị thanh tiến trình (progress bar) dạng stack hoặc separate với hỗ trợ Angular Signals.

Downloads

3,018

Readme

@libs-ui/components-process-bar-standard

Component hiển thị thanh tiến trình (progress bar) dạng stack hoặc separate với hỗ trợ Angular Signals.

Giới thiệu

LibsUiComponentsProcessBarStandardComponent là standalone Angular component hiển thị thanh tiến trình đa bước. Component hỗ trợ 2 chế độ: stack (các bước ghép liền nhau thành 1 thanh) và separate (mỗi bước là 1 thanh riêng). Toàn bộ state quản lý qua Angular Signals với kiến trúc Nested Signal — mỗi step là một WritableSignal độc lập, cho phép cập nhật realtime mà không re-render toàn bộ.

Tính năng

  • ✅ Chế độ Stack — các bước nối liền nhau trên 1 thanh, tỷ lệ tính tự động theo totalValue
  • ✅ Chế độ Separate — mỗi bước hiển thị thành 1 thanh riêng biệt kèm label và phần trăm
  • ✅ Hiển thị phần trăm tùy chọn cho từng bước hoặc toàn bộ config
  • Label tùy chỉnh ngay trong thanh (stack và separate)
  • ✅ Custom class, màu sắc, bo góc, chiều cao, chiều rộng linh hoạt
  • Nested Signals — cập nhật từng step riêng lẻ mà không trigger re-render toàn bộ
  • Global default config qua injection token PROCESS_BAR_STANDARD_CONFIG_DEFAULT_TOKEN_INJECT
  • OnPush Change Detection + Standalone Component

Khi nào sử dụng

  • Hiển thị tiến trình của một quy trình đa bước (upload, xử lý, phê duyệt)
  • Dashboard widget so sánh các chỉ số (doanh thu, mục tiêu, trạng thái)
  • Hiển thị tỷ lệ phân bổ dữ liệu (ví dụ: phân bổ ngân sách, nguồn lực)
  • Realtime progress với dữ liệu thay đổi thường xuyên nhờ Nested Signals

Cài đặt

npm install @libs-ui/components-process-bar-standard

Import

import { LibsUiComponentsProcessBarStandardComponent } from '@libs-ui/components-process-bar-standard';

@Component({
  standalone: true,
  imports: [LibsUiComponentsProcessBarStandardComponent],
  // ...
})
export class MyComponent {}

Ví dụ sử dụng

Ví dụ 1 — Stack cơ bản (3 bước)

import { signal } from '@angular/core';
import {
  LibsUiComponentsProcessBarStandardComponent,
  IProcessBarStandardInterface,
  IProcessBarStandardStepInterface,
} from '@libs-ui/components-process-bar-standard';

@Component({
  standalone: true,
  imports: [LibsUiComponentsProcessBarStandardComponent],
  template: `
    <libs_ui-components-process_bar-standard [config]="configStack()" />
  `,
})
export class MyComponent {
  private readonly stepProcessing = signal<IProcessBarStandardStepInterface>({
    value: 30,
    color: '#EF4444',
    label: 'Processing',
  });
  private readonly stepDone = signal<IProcessBarStandardStepInterface>({
    value: 50,
    color: '#3B82F6',
    label: 'Done',
  });
  private readonly stepPending = signal<IProcessBarStandardStepInterface>({
    value: 20,
    color: '#10B981',
  });

  readonly configStack = signal<IProcessBarStandardInterface>({
    width: '100%',
    height: '24px',
    radius: 12,
    totalValue: 100,
    mode: 'stack',
    steps: signal([this.stepProcessing, this.stepDone, this.stepPending]),
  });
}
<libs_ui-components-process_bar-standard [config]="configStack()" />

Ví dụ 2 — Separate mode với hiển thị phần trăm

import { signal } from '@angular/core';
import {
  LibsUiComponentsProcessBarStandardComponent,
  IProcessBarStandardInterface,
  IProcessBarStandardStepInterface,
} from '@libs-ui/components-process-bar-standard';

@Component({
  standalone: true,
  imports: [LibsUiComponentsProcessBarStandardComponent],
  template: `
    <libs_ui-components-process_bar-standard [config]="configSeparate()" />
  `,
})
export class MyComponent {
  private readonly stepProgress = signal<IProcessBarStandardStepInterface>({
    value: 75,
    color: '#8B5CF6',
    label: 'Tiến độ',
    showPercent: true,
  });
  private readonly stepPending = signal<IProcessBarStandardStepInterface>({
    value: 45,
    color: '#F59E0B',
    label: 'Đang chờ',
    showPercent: true,
  });

  readonly configSeparate = signal<IProcessBarStandardInterface>({
    width: '100%',
    height: '16px',
    backgroundColor: 'transparent',
    radius: 8,
    totalValue: 100,
    mode: 'separate',
    steps: signal([this.stepProgress, this.stepPending]),
  });
}
<libs_ui-components-process_bar-standard [config]="configSeparate()" />

Ví dụ 3 — Cập nhật realtime bằng Nested Signals

import { signal, computed } from '@angular/core';
import {
  LibsUiComponentsProcessBarStandardComponent,
  IProcessBarStandardInterface,
  IProcessBarStandardStepInterface,
} from '@libs-ui/components-process-bar-standard';

@Component({
  standalone: true,
  imports: [LibsUiComponentsProcessBarStandardComponent],
  template: `
    <button (click)="handlerIncrement($event)">Tăng tiến độ</button>
    <libs_ui-components-process_bar-standard [config]="configRealtime()" />
  `,
})
export class MyComponent {
  private readonly currentValue = signal(40);

  private readonly stepMain = signal<IProcessBarStandardStepInterface>({
    value: 40,
    color: '#EC4899',
    label: 'Đang xử lý',
  });

  readonly configRealtime = computed<IProcessBarStandardInterface>(() => ({
    width: '100%',
    height: '20px',
    radius: 10,
    totalValue: 100,
    mode: 'stack',
    steps: signal([this.stepMain]),
  }));

  protected handlerIncrement(event: Event): void {
    event.stopPropagation();
    const next = Math.min(this.currentValue() + 10, 100);
    this.currentValue.set(next);
    this.stepMain.update((step) => ({ ...step, value: next }));
  }
}
<button (click)="handlerIncrement($event)">Tăng tiến độ</button>
<libs_ui-components-process_bar-standard [config]="configRealtime()" />

Ví dụ 4 — Global default config qua Injection Token

import { ApplicationConfig } from '@angular/core';
import { PROCESS_BAR_STANDARD_CONFIG_DEFAULT_TOKEN_INJECT } from '@libs-ui/utils';
import { IProcessBarStandardConfigDefaultInterface } from '@libs-ui/components-process-bar-standard';

export const appConfig: ApplicationConfig = {
  providers: [
    {
      provide: PROCESS_BAR_STANDARD_CONFIG_DEFAULT_TOKEN_INJECT,
      useValue: {
        height: '16px',
        backgroundColor: '#F1F5F9',
        radius: 8,
      } satisfies IProcessBarStandardConfigDefaultInterface,
    },
  ],
};

Sau khi cấu hình global, mọi instance của component sẽ tự động áp dụng giá trị mặc định trên nếu không truyền tường minh qua [config].

@Input()

| Input | Type | Default | Mô tả | Ví dụ | |---|---|---|---|---| | [config] | IProcessBarStandardInterface | Bắt buộc | Object cấu hình toàn bộ thanh tiến trình gồm kích thước, màu sắc, chế độ và danh sách bước | [config]="configStack()" |

IProcessBarStandardInterface

Cấu trúc object truyền vào [config]:

| Thuộc tính | Type | Bắt buộc | Default | Mô tả | Ví dụ | |---|---|---|---|---|---| | totalValue | number | Bắt buộc | — | Giá trị tổng dùng để tính phần trăm cho từng bước | totalValue: 100 | | steps | WritableSignal<Array<WritableSignal<IProcessBarStandardStepInterface>>> | Bắt buộc | — | Danh sách các bước, mỗi bước là một WritableSignal | steps: signal([stepA, stepB]) | | mode | 'stack' \| 'separate' | Không | 'stack' | Chế độ hiển thị: stack = ghép liền, separate = tách rời | mode: 'separate' | | width | string | Không | '100%' | Chiều rộng của thanh | width: '300px' | | height | string | Không | '12px' | Chiều cao của thanh | height: '20px' | | backgroundColor | string | Không | '#F8F9FA' | Màu nền của container thanh | backgroundColor: '#E5E7EB' | | radius | number | Không | 20 | Độ bo góc tính bằng px | radius: 8 | | classInclude | string | Không | '' | CSS class bổ sung cho element wrapper | classInclude: 'mt-4' | | showPercent | boolean | Không | false | Hiển thị phần trăm (áp dụng cho tất cả bước trong chế độ separate, có thể override ở từng bước) | showPercent: true | | percentClass | string | Không | '' | CSS class cho phần text phần trăm (áp dụng cho tất cả bước, có thể override ở từng bước) | percentClass: 'text-blue-600' |

IProcessBarStandardStepInterface

Cấu trúc object mô tả từng bước trong steps:

| Thuộc tính | Type | Bắt buộc | Default | Mô tả | Ví dụ | |---|---|---|---|---|---| | value | number | Bắt buộc | — | Giá trị của bước, được chia cho totalValue để tính % | value: 40 | | color | string | Bắt buộc | — | Màu nền của bước (hex, rgb, tên màu CSS) | color: '#3B82F6' | | label | string | Không | undefined | Văn bản hiển thị bên trong thanh bước | label: 'Hoàn thành' | | classLabel | string | Không | '' | CSS class bổ sung cho element label | classLabel: 'text-white' | | classInclude | string | Không | '' | CSS class bổ sung cho element thanh của bước (chỉ chế độ separate) | classInclude: 'rounded-full' | | showPercent | boolean | Không | undefined | Override hiển thị phần trăm riêng cho bước này (chỉ chế độ separate) | showPercent: true | | percentClass | string | Không | '' | Override CSS class cho text phần trăm riêng cho bước này | percentClass: 'libs-ui-font-h5r' |

IProcessBarStandardConfigDefaultInterface

Interface dùng khi cung cấp global default qua PROCESS_BAR_STANDARD_CONFIG_DEFAULT_TOKEN_INJECT:

| Thuộc tính | Type | Mô tả | |---|---|---| | width | string | Chiều rộng mặc định toàn cục | | height | string | Chiều cao mặc định toàn cục | | backgroundColor | string | Màu nền mặc định toàn cục | | radius | number | Bo góc mặc định toàn cục (px) |

Types & Interfaces

import {
  IProcessBarStandardInterface,
  IProcessBarStandardStepInterface,
  IProcessBarStandardConfigDefaultInterface,
} from '@libs-ui/components-process-bar-standard';

Định nghĩa đầy đủ:

import { WritableSignal } from '@angular/core';

export interface IProcessBarStandardConfigDefaultInterface {
  width?: string;
  height?: string;
  backgroundColor?: string;
  radius?: number;
}

export interface IProcessBarStandardInterface {
  width?: string;
  height?: string;
  backgroundColor?: string;
  radius?: number;
  totalValue: number;
  mode?: 'stack' | 'separate' | 'steps';
  classInclude?: string;
  showPercent?: boolean;
  percentClass?: string;
  steps: WritableSignal<Array<WritableSignal<IProcessBarStandardStepInterface>>>;
}

export interface IProcessBarStandardStepInterface {
  classInclude?: string;
  label?: string;
  classLabel?: string;
  value: number;
  color: string;
  showPercent?: boolean;
  percentClass?: string;
}

Lưu ý quan trọng

⚠️ Nested Signals bắt buộc: Property steps yêu cầu cấu trúc WritableSignal<Array<WritableSignal<IProcessBarStandardStepInterface>>>. Mỗi step phải là một WritableSignal riêng — không được truyền plain object hay array thông thường.

⚠️ Cập nhật realtime đúng cách: Để cập nhật giá trị một bước mà không trigger re-render toàn bộ, hãy gọi .update() trực tiếp trên signal của step đó (this.stepA.update(s => ({ ...s, value: 60 }))). Không tạo lại signal mới hay thay thế toàn bộ mảng.

⚠️ Mode steps chưa implement: Thuộc tính mode có giá trị 'steps' trong type nhưng chưa được render trong template. Chỉ sử dụng 'stack' hoặc 'separate'.

⚠️ showPercent chỉ hoạt động ở chế độ separate: Trong chế độ stack, thuộc tính showPercent (cả ở config lẫn từng step) không có hiệu lực vì cấu trúc layout không hỗ trợ.

⚠️ Global default token: Nếu inject PROCESS_BAR_STANDARD_CONFIG_DEFAULT_TOKEN_INJECT, các giá trị trong token sẽ là fallback khi thuộc tính tương ứng trong [config] không được truyền. Thứ tự ưu tiên: config.xxx > tokenDefault.xxx > hardcoded default.

Demo

npx nx serve core-ui

Truy cập: http://localhost:4500/components/process-bar/standard