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-inputs-keyboard

v0.2.357-5

Published

> Component bàn phím số (Numeric Keypad) hỗ trợ nhập liệu bằng chuột và bàn phím cứng (phím số 0-9).

Readme

@libs-ui/components-inputs-keyboard

Component bàn phím số (Numeric Keypad) hỗ trợ nhập liệu bằng chuột và bàn phím cứng (phím số 0-9).

Giới thiệu

LibsUiComponentsInputsKeyboardComponent cung cấp giao diện bàn phím số tiêu chuẩn gồm các phím 0–9, *#. Component tự động lắng nghe sự kiện keyup toàn cục trên document, cho phép người dùng nhập liệu đồng bộ cả từ UI lẫn bàn phím cứng. Mỗi lần nhấn phím, component emit mã code tương ứng ra ngoài qua output outKeyCodeSelected, phù hợp cho các màn hình nhập mã PIN, quay số tổng đài hoặc thiết bị cảm ứng.

Tính năng

  • ✅ Giao diện bàn phím số tiêu chuẩn (1–9, *, 0, #)
  • ✅ Đồng bộ tự động với bàn phím cứng (phím số 0–9, cả hàng số chính và numpad)
  • ✅ Hiển thị chuỗi đã nhập nội bộ trực tiếp trên bàn phím
  • ✅ Emit mã code phím đã chọn qua output event outKeyCodeSelected
  • ✅ Sử dụng Angular Signals — hiệu năng cao với ChangeDetection tối ưu
  • ✅ Standalone component — dễ tích hợp, không cần NgModule

Khi nào sử dụng

  • Màn hình nhập mã PIN hoặc mật khẩu chỉ có số
  • Ứng dụng tổng đài (Dialer/VoIP) cần giao diện quay số
  • Thiết bị cảm ứng (POS, kiosk) cần bàn phím số lớn dễ bấm
  • Cần đồng bộ giữa thao tác click chuột và bàn phím cứng

Cài đặt

npm install @libs-ui/components-inputs-keyboard

Import

import { LibsUiComponentsInputsKeyboardComponent } from '@libs-ui/components-inputs-keyboard';

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

Các exports phụ trợ (interface, define) cũng có thể import từ cùng package:

import {
  LibsUiComponentsInputsKeyboardComponent,
  IKeyCode,
  keypadConfig,
} from '@libs-ui/components-inputs-keyboard';

Ví dụ sử dụng

Ví dụ 1 — Cơ bản

Hiển thị bàn phím số và log mã phím mỗi lần nhấn.

<!-- template.html -->
<libs_ui-components-inputs-keyboard
  (outKeyCodeSelected)="handlerKeySelect($event)"
/>
// component.ts
import { Component } from '@angular/core';
import { LibsUiComponentsInputsKeyboardComponent } from '@libs-ui/components-inputs-keyboard';

@Component({
  selector: 'app-pin-entry',
  standalone: true,
  imports: [LibsUiComponentsInputsKeyboardComponent],
  templateUrl: './pin-entry.component.html',
})
export class PinEntryComponent {
  handlerKeySelect(event: Event, code: string): void {
    // Lưu ý: outKeyCodeSelected truyền string trực tiếp, không phải DOM Event
    // Handler này nhận code: string từ output
  }
}

outKeyCodeSelected emit kiểu string (không phải Event), handler nhận thẳng string:

handlerKeySelect(code: string): void {
  console.log('Phím được nhấn:', code);
}

Ví dụ 2 — Xây dựng chuỗi PIN

Tích lũy các phím đã nhấn để tạo chuỗi PIN, kết hợp nút xóa.

<!-- template.html -->
<div class="max-w-[300px] border rounded-xl p-4 bg-white shadow-sm">
  <div class="text-center text-2xl font-mono tracking-widest mb-4 min-h-[36px]">
    {{ pinDisplay() }}
  </div>
  <libs_ui-components-inputs-keyboard
    (outKeyCodeSelected)="handlerPinKey($event)"
  />
  <button class="mt-4 w-full text-sm text-red-500" (click)="handlerClearPin($event)">
    Xóa
  </button>
</div>
// component.ts
import { Component, signal } from '@angular/core';
import { LibsUiComponentsInputsKeyboardComponent } from '@libs-ui/components-inputs-keyboard';

@Component({
  selector: 'app-pin-input',
  standalone: true,
  imports: [LibsUiComponentsInputsKeyboardComponent],
  templateUrl: './pin-input.component.html',
})
export class PinInputComponent {
  private pinValue = signal<string>('');

  protected pinDisplay = signal<string>('');

  handlerPinKey(code: string): void {
    if (this.pinValue().length >= 6) return;
    this.pinValue.update((prev) => prev + code);
    this.pinDisplay.set('*'.repeat(this.pinValue().length));
  }

  handlerClearPin(event: Event): void {
    event.stopPropagation();
    this.pinValue.set('');
    this.pinDisplay.set('');
  }
}

Ví dụ 3 — Theo dõi từng phím và toàn bộ chuỗi

Hiển thị phím vừa nhấn và chuỗi đầy đủ theo thời gian thực.

<!-- template.html -->
<div class="flex gap-8 items-start">
  <div class="w-[280px] bg-slate-50 p-6 rounded-2xl border border-slate-200">
    <libs_ui-components-inputs-keyboard
      (outKeyCodeSelected)="handlerKeySelect($event)"
    />
  </div>

  <div class="flex-1 space-y-4 pt-4">
    <div class="bg-blue-50 p-4 rounded-lg border border-blue-100">
      <p class="text-sm text-blue-600 font-medium mb-1">Phím vừa nhấn:</p>
      <div class="text-3xl font-bold text-blue-900">{{ lastKey() || '-' }}</div>
    </div>
    <div class="bg-gray-50 p-4 rounded-lg border border-gray-200">
      <p class="text-sm text-gray-600 font-medium mb-1">Chuỗi đầy đủ:</p>
      <div class="text-xl font-mono text-gray-800 break-all">{{ fullSequence() || '...' }}</div>
      <button class="mt-2 text-xs text-red-500 hover:underline" (click)="handlerClear($event)">
        Xóa lịch sử
      </button>
    </div>
  </div>
</div>
// component.ts
import { Component, signal } from '@angular/core';
import { LibsUiComponentsInputsKeyboardComponent } from '@libs-ui/components-inputs-keyboard';

@Component({
  selector: 'app-keyboard-demo',
  standalone: true,
  imports: [LibsUiComponentsInputsKeyboardComponent],
  templateUrl: './keyboard-demo.component.html',
})
export class KeyboardDemoComponent {
  protected lastKey = signal<string>('');
  protected fullSequence = signal<string>('');

  handlerKeySelect(code: string): void {
    this.lastKey.set(code);
    this.fullSequence.update((prev) => prev + code);
  }

  handlerClear(event: Event): void {
    event.stopPropagation();
    this.lastKey.set('');
    this.fullSequence.set('');
  }
}

@Input()

Component hiện tại không có @Input() công khai. Toàn bộ cấu hình phím được quản lý nội bộ thông qua keypadConfig() — mảng mặc định 12 phím: 1, 2, 3, 4, 5, 6, 7, 8, 9, *, 0, #.

@Output()

| Output | Type | Mô tả | Handler TS | Binding HTML | |---|---|---|---|---| | (outKeyCodeSelected) | string | Emit mã code của phím khi người dùng click vào phím trên UI hoặc nhấn phím số trên bàn phím cứng (0–9) | handlerKeySelect(code: string): void { /* xử lý */ } | (outKeyCodeSelected)="handlerKeySelect($event)" |

Lưu ý về handler: Output emit thẳng string (không phải DOM Event), nên handler nhận tham số kiểu string. Nếu cần event.stopPropagation(), hãy gắn lên sự kiện DOM bao ngoài (không phải output này).

Types & Interfaces

import { IKeyCode, keypadConfig } from '@libs-ui/components-inputs-keyboard';

IKeyCode

Cấu hình thông tin một phím bấm trên bàn phím.

interface IKeyCode {
  /** Mã định danh của phím — VD: '1', '0', '*', '#' */
  code: string;
  /** Nhãn hiển thị của phím trên giao diện */
  label: string;
}

keypadConfig()

Hàm factory trả về mảng cấu hình 12 phím mặc định.

import { keypadConfig } from '@libs-ui/components-inputs-keyboard';

// Trả về IKeyCode[] gồm: 1, 2, 3, 4, 5, 6, 7, 8, 9, *, 0, #
const keys: IKeyCode[] = keypadConfig();

Lưu ý quan trọng

⚠️ Lắng nghe phím cứng toàn cục: Component đăng ký lắng nghe sự kiện document:keyup khi được mount. Nếu nhiều instance libs_ui-components-inputs-keyboard cùng tồn tại trong DOM, tất cả đều sẽ nhận và xử lý sự kiện bàn phím đồng thời.

⚠️ Phạm vi phím cứng hỗ trợ: Chỉ lắng nghe phím số 0–9 từ bàn phím cứng (cả hàng số chính keyCode 48–57 và numpad keyCode 96–105). Các phím *# chỉ có thể nhập bằng cách click trực tiếp trên UI.

⚠️ State hiển thị nội bộ: Chuỗi ký tự hiển thị trên bàn phím (resultSelectKey) được quản lý hoàn toàn nội bộ bởi component và không bị reset tự động. Nếu cần reset, hãy destroy và tạo lại component (ví dụ: dùng @if để unmount/remount).

⚠️ Không có @Input() cấu hình phím: Cấu hình danh sách phím hiện tại được hardcode nội bộ qua keypadConfig(). Không thể tùy biến danh sách phím từ bên ngoài thông qua input binding.

Demo

npx nx serve core-ui

Truy cập: http://localhost:4500/inputs/keyboard

Unit Tests

# Chạy tests cho lib
npx nx test components-inputs-keyboard

# Chạy test một file cụ thể
npx nx test components-inputs-keyboard --testFile=libs-ui/components/inputs/keyboard/src/keyboard.component.spec.ts

# Chạy với coverage
npx nx test components-inputs-keyboard --coverage