@libs-ui/components-inputs-keyboard 0.2.356-8 → 0.2.357-0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md
CHANGED
|
@@ -1,34 +1,31 @@
|
|
|
1
1
|
# @libs-ui/components-inputs-keyboard
|
|
2
2
|
|
|
3
|
-
> 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.
|
|
3
|
+
> 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).
|
|
4
4
|
|
|
5
5
|
## Giới thiệu
|
|
6
6
|
|
|
7
|
-
`LibsUiComponentsInputsKeyboardComponent` cung cấp giao diện bàn phím số
|
|
7
|
+
`LibsUiComponentsInputsKeyboardComponent` cung cấp giao diện bàn phím số tiêu chuẩn gồm các phím 0–9, `*` và `#`. 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.
|
|
8
8
|
|
|
9
|
-
|
|
9
|
+
## Tính năng
|
|
10
10
|
|
|
11
|
-
- ✅ Giao diện bàn phím số tiêu chuẩn (
|
|
12
|
-
- ✅ Đồng bộ
|
|
13
|
-
- ✅ Hiển thị
|
|
14
|
-
- ✅ Emit mã code phím đã chọn qua output event
|
|
15
|
-
- ✅ Sử dụng Angular Signals
|
|
16
|
-
- ✅
|
|
11
|
+
- ✅ Giao diện bàn phím số tiêu chuẩn (1–9, `*`, `0`, `#`)
|
|
12
|
+
- ✅ Đồ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)
|
|
13
|
+
- ✅ Hiển thị chuỗi đã nhập nội bộ trực tiếp trên bàn phím
|
|
14
|
+
- ✅ Emit mã code phím đã chọn qua output event `outKeyCodeSelected`
|
|
15
|
+
- ✅ Sử dụng Angular Signals — hiệu năng cao với `ChangeDetection` tối ưu
|
|
16
|
+
- ✅ Standalone component — dễ tích hợp, không cần NgModule
|
|
17
17
|
|
|
18
18
|
## Khi nào sử dụng
|
|
19
19
|
|
|
20
|
-
-
|
|
21
|
-
-
|
|
22
|
-
-
|
|
20
|
+
- Màn hình nhập mã PIN hoặc mật khẩu chỉ có số
|
|
21
|
+
- Ứng dụng tổng đài (Dialer/VoIP) cần giao diện quay số
|
|
22
|
+
- Thiết bị cảm ứng (POS, kiosk) cần bàn phím số lớn dễ bấm
|
|
23
|
+
- Cần đồng bộ giữa thao tác click chuột và bàn phím cứng
|
|
23
24
|
|
|
24
25
|
## Cài đặt
|
|
25
26
|
|
|
26
27
|
```bash
|
|
27
|
-
# npm
|
|
28
28
|
npm install @libs-ui/components-inputs-keyboard
|
|
29
|
-
|
|
30
|
-
# yarn
|
|
31
|
-
yarn add @libs-ui/components-inputs-keyboard
|
|
32
29
|
```
|
|
33
30
|
|
|
34
31
|
## Import
|
|
@@ -44,40 +41,213 @@ import { LibsUiComponentsInputsKeyboardComponent } from '@libs-ui/components-inp
|
|
|
44
41
|
export class YourComponent {}
|
|
45
42
|
```
|
|
46
43
|
|
|
47
|
-
|
|
44
|
+
Các exports phụ trợ (interface, define) cũng có thể import từ cùng package:
|
|
45
|
+
|
|
46
|
+
```typescript
|
|
47
|
+
import {
|
|
48
|
+
LibsUiComponentsInputsKeyboardComponent,
|
|
49
|
+
IKeyCode,
|
|
50
|
+
keypadConfig,
|
|
51
|
+
} from '@libs-ui/components-inputs-keyboard';
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
## Ví dụ sử dụng
|
|
48
55
|
|
|
49
|
-
### Cơ bản
|
|
56
|
+
### Ví dụ 1 — Cơ bản
|
|
57
|
+
|
|
58
|
+
Hiển thị bàn phím số và log mã phím mỗi lần nhấn.
|
|
50
59
|
|
|
51
60
|
```html
|
|
52
|
-
|
|
61
|
+
<!-- template.html -->
|
|
62
|
+
<libs_ui-components-inputs-keyboard
|
|
63
|
+
(outKeyCodeSelected)="handlerKeySelect($event)"
|
|
64
|
+
/>
|
|
53
65
|
```
|
|
54
66
|
|
|
55
|
-
|
|
67
|
+
```typescript
|
|
68
|
+
// component.ts
|
|
69
|
+
import { Component } from '@angular/core';
|
|
70
|
+
import { LibsUiComponentsInputsKeyboardComponent } from '@libs-ui/components-inputs-keyboard';
|
|
56
71
|
|
|
57
|
-
|
|
72
|
+
@Component({
|
|
73
|
+
selector: 'app-pin-entry',
|
|
74
|
+
standalone: true,
|
|
75
|
+
imports: [LibsUiComponentsInputsKeyboardComponent],
|
|
76
|
+
templateUrl: './pin-entry.component.html',
|
|
77
|
+
})
|
|
78
|
+
export class PinEntryComponent {
|
|
79
|
+
handlerKeySelect(event: Event, code: string): void {
|
|
80
|
+
// Lưu ý: outKeyCodeSelected truyền string trực tiếp, không phải DOM Event
|
|
81
|
+
// Handler này nhận code: string từ output
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
```
|
|
58
85
|
|
|
59
|
-
|
|
86
|
+
> Vì `outKeyCodeSelected` emit kiểu `string` (không phải `Event`), handler nhận thẳng `string`:
|
|
60
87
|
|
|
61
|
-
|
|
88
|
+
```typescript
|
|
89
|
+
handlerKeySelect(code: string): void {
|
|
90
|
+
console.log('Phím được nhấn:', code);
|
|
91
|
+
}
|
|
92
|
+
```
|
|
62
93
|
|
|
63
|
-
|
|
94
|
+
### Ví dụ 2 — Xây dựng chuỗi PIN
|
|
64
95
|
|
|
65
|
-
|
|
66
|
-
| ---------------------- | -------- | ------------------------------------------------------------ |
|
|
67
|
-
| `(outKeyCodeSelected)` | `string` | Emit mã code của phím khi người dùng click hoặc nhấn phím số |
|
|
96
|
+
Tích lũy các phím đã nhấn để tạo chuỗi PIN, kết hợp nút xóa.
|
|
68
97
|
|
|
69
|
-
|
|
98
|
+
```html
|
|
99
|
+
<!-- template.html -->
|
|
100
|
+
<div class="max-w-[300px] border rounded-xl p-4 bg-white shadow-sm">
|
|
101
|
+
<div class="text-center text-2xl font-mono tracking-widest mb-4 min-h-[36px]">
|
|
102
|
+
{{ pinDisplay() }}
|
|
103
|
+
</div>
|
|
104
|
+
<libs_ui-components-inputs-keyboard
|
|
105
|
+
(outKeyCodeSelected)="handlerPinKey($event)"
|
|
106
|
+
/>
|
|
107
|
+
<button class="mt-4 w-full text-sm text-red-500" (click)="handlerClearPin($event)">
|
|
108
|
+
Xóa
|
|
109
|
+
</button>
|
|
110
|
+
</div>
|
|
111
|
+
```
|
|
70
112
|
|
|
71
|
-
|
|
113
|
+
```typescript
|
|
114
|
+
// component.ts
|
|
115
|
+
import { Component, signal } from '@angular/core';
|
|
116
|
+
import { LibsUiComponentsInputsKeyboardComponent } from '@libs-ui/components-inputs-keyboard';
|
|
117
|
+
|
|
118
|
+
@Component({
|
|
119
|
+
selector: 'app-pin-input',
|
|
120
|
+
standalone: true,
|
|
121
|
+
imports: [LibsUiComponentsInputsKeyboardComponent],
|
|
122
|
+
templateUrl: './pin-input.component.html',
|
|
123
|
+
})
|
|
124
|
+
export class PinInputComponent {
|
|
125
|
+
private pinValue = signal<string>('');
|
|
126
|
+
|
|
127
|
+
protected pinDisplay = signal<string>('');
|
|
128
|
+
|
|
129
|
+
handlerPinKey(code: string): void {
|
|
130
|
+
if (this.pinValue().length >= 6) return;
|
|
131
|
+
this.pinValue.update((prev) => prev + code);
|
|
132
|
+
this.pinDisplay.set('*'.repeat(this.pinValue().length));
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
handlerClearPin(event: Event): void {
|
|
136
|
+
event.stopPropagation();
|
|
137
|
+
this.pinValue.set('');
|
|
138
|
+
this.pinDisplay.set('');
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
```
|
|
72
142
|
|
|
73
|
-
|
|
143
|
+
### Ví dụ 3 — Theo dõi từng phím và toàn bộ chuỗi
|
|
74
144
|
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
145
|
+
Hiển thị phím vừa nhấn và chuỗi đầy đủ theo thời gian thực.
|
|
146
|
+
|
|
147
|
+
```html
|
|
148
|
+
<!-- template.html -->
|
|
149
|
+
<div class="flex gap-8 items-start">
|
|
150
|
+
<div class="w-[280px] bg-slate-50 p-6 rounded-2xl border border-slate-200">
|
|
151
|
+
<libs_ui-components-inputs-keyboard
|
|
152
|
+
(outKeyCodeSelected)="handlerKeySelect($event)"
|
|
153
|
+
/>
|
|
154
|
+
</div>
|
|
155
|
+
|
|
156
|
+
<div class="flex-1 space-y-4 pt-4">
|
|
157
|
+
<div class="bg-blue-50 p-4 rounded-lg border border-blue-100">
|
|
158
|
+
<p class="text-sm text-blue-600 font-medium mb-1">Phím vừa nhấn:</p>
|
|
159
|
+
<div class="text-3xl font-bold text-blue-900">{{ lastKey() || '-' }}</div>
|
|
160
|
+
</div>
|
|
161
|
+
<div class="bg-gray-50 p-4 rounded-lg border border-gray-200">
|
|
162
|
+
<p class="text-sm text-gray-600 font-medium mb-1">Chuỗi đầy đủ:</p>
|
|
163
|
+
<div class="text-xl font-mono text-gray-800 break-all">{{ fullSequence() || '...' }}</div>
|
|
164
|
+
<button class="mt-2 text-xs text-red-500 hover:underline" (click)="handlerClear($event)">
|
|
165
|
+
Xóa lịch sử
|
|
166
|
+
</button>
|
|
167
|
+
</div>
|
|
168
|
+
</div>
|
|
169
|
+
</div>
|
|
170
|
+
```
|
|
171
|
+
|
|
172
|
+
```typescript
|
|
173
|
+
// component.ts
|
|
174
|
+
import { Component, signal } from '@angular/core';
|
|
175
|
+
import { LibsUiComponentsInputsKeyboardComponent } from '@libs-ui/components-inputs-keyboard';
|
|
176
|
+
|
|
177
|
+
@Component({
|
|
178
|
+
selector: 'app-keyboard-demo',
|
|
179
|
+
standalone: true,
|
|
180
|
+
imports: [LibsUiComponentsInputsKeyboardComponent],
|
|
181
|
+
templateUrl: './keyboard-demo.component.html',
|
|
182
|
+
})
|
|
183
|
+
export class KeyboardDemoComponent {
|
|
184
|
+
protected lastKey = signal<string>('');
|
|
185
|
+
protected fullSequence = signal<string>('');
|
|
186
|
+
|
|
187
|
+
handlerKeySelect(code: string): void {
|
|
188
|
+
this.lastKey.set(code);
|
|
189
|
+
this.fullSequence.update((prev) => prev + code);
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
handlerClear(event: Event): void {
|
|
193
|
+
event.stopPropagation();
|
|
194
|
+
this.lastKey.set('');
|
|
195
|
+
this.fullSequence.set('');
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
```
|
|
199
|
+
|
|
200
|
+
## @Input()
|
|
201
|
+
|
|
202
|
+
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, #`.
|
|
203
|
+
|
|
204
|
+
## @Output()
|
|
205
|
+
|
|
206
|
+
| Output | Type | Mô tả | Handler TS | Binding HTML |
|
|
207
|
+
|---|---|---|---|---|
|
|
208
|
+
| `(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)"` |
|
|
209
|
+
|
|
210
|
+
**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).
|
|
211
|
+
|
|
212
|
+
## Types & Interfaces
|
|
213
|
+
|
|
214
|
+
```typescript
|
|
215
|
+
import { IKeyCode, keypadConfig } from '@libs-ui/components-inputs-keyboard';
|
|
216
|
+
```
|
|
217
|
+
|
|
218
|
+
### `IKeyCode`
|
|
219
|
+
|
|
220
|
+
Cấu hình thông tin một phím bấm trên bàn phím.
|
|
221
|
+
|
|
222
|
+
```typescript
|
|
223
|
+
interface IKeyCode {
|
|
224
|
+
/** Mã định danh của phím — VD: '1', '0', '*', '#' */
|
|
225
|
+
code: string;
|
|
226
|
+
/** Nhãn hiển thị của phím trên giao diện */
|
|
227
|
+
label: string;
|
|
228
|
+
}
|
|
229
|
+
```
|
|
230
|
+
|
|
231
|
+
### `keypadConfig()`
|
|
232
|
+
|
|
233
|
+
Hàm factory trả về mảng cấu hình 12 phím mặc định.
|
|
234
|
+
|
|
235
|
+
```typescript
|
|
236
|
+
import { keypadConfig } from '@libs-ui/components-inputs-keyboard';
|
|
237
|
+
|
|
238
|
+
// Trả về IKeyCode[] gồm: 1, 2, 3, 4, 5, 6, 7, 8, 9, *, 0, #
|
|
239
|
+
const keys: IKeyCode[] = keypadConfig();
|
|
240
|
+
```
|
|
241
|
+
|
|
242
|
+
## Lưu ý quan trọng
|
|
243
|
+
|
|
244
|
+
⚠️ **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.
|
|
245
|
+
|
|
246
|
+
⚠️ **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 `*` và `#` chỉ có thể nhập bằng cách click trực tiếp trên UI.
|
|
247
|
+
|
|
248
|
+
⚠️ **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).
|
|
249
|
+
|
|
250
|
+
⚠️ **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.
|
|
81
251
|
|
|
82
252
|
## Demo
|
|
83
253
|
|
|
@@ -85,18 +255,17 @@ Component lắng nghe sự kiện `keyup` trên toàn bộ `document`. Khi ngư
|
|
|
85
255
|
npx nx serve core-ui
|
|
86
256
|
```
|
|
87
257
|
|
|
88
|
-
Truy cập:
|
|
258
|
+
Truy cập: http://localhost:4500/inputs/keyboard
|
|
89
259
|
|
|
90
260
|
## Unit Tests
|
|
91
261
|
|
|
92
262
|
```bash
|
|
93
|
-
# Chạy tests
|
|
263
|
+
# Chạy tests cho lib
|
|
94
264
|
npx nx test components-inputs-keyboard
|
|
95
265
|
|
|
96
|
-
#
|
|
266
|
+
# Chạy test một file cụ thể
|
|
267
|
+
npx nx test components-inputs-keyboard --testFile=libs-ui/components/inputs/keyboard/src/keyboard.component.spec.ts
|
|
268
|
+
|
|
269
|
+
# Chạy với coverage
|
|
97
270
|
npx nx test components-inputs-keyboard --coverage
|
|
98
271
|
```
|
|
99
|
-
|
|
100
|
-
## License
|
|
101
|
-
|
|
102
|
-
MIT
|
|
@@ -44,10 +44,10 @@ export class LibsUiComponentsInputsKeyboardComponent {
|
|
|
44
44
|
this.onDestroy.complete();
|
|
45
45
|
}
|
|
46
46
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: LibsUiComponentsInputsKeyboardComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
47
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.14", type: LibsUiComponentsInputsKeyboardComponent, isStandalone: true, selector: "libs_ui-components-inputs-keyboard", outputs: { outKeyCodeSelected: "outKeyCodeSelected" }, ngImport: i0, template: "<div class=\"libs-ui-inputs-keyboard\">\n <span class=\"libs-ui-font-h1s flex justify-center mt-[12px] h-[24px]\">{{ resultSelectKey() }}</span>\n <hr class=\"mt-[12px] mb-[20px]\" />\n <div class=\"flex w-full justify-center\">\n <div class=\"flex flex-wrap -mx-2 p-0 m-0\">\n @for (config of configKeyCodes(); track config) {\n <div class=\"w-1/3 p-0 m-0 flex justify-center !mb-[28px]\">\n <div\n class=\"libs-ui-border-general libs-ui-inputs-keyboard-item libs-ui-font-h1s\"\n (click)=\"handlerClickItem($event, config)\">\n {{ config.label }}\n </div>\n </div>\n }\n </div>\n </div>\n</div>\n", styles: [".libs-ui-inputs-keyboard{background-color:#fff;padding:8px 20px}.libs-ui-inputs-keyboard .libs-ui-inputs-keyboard-item{display:flex;align-items:center;justify-content:center;border-radius:50%;height:52px;width:52px}.libs-ui-inputs-keyboard .libs-ui-inputs-keyboard-item:hover{background-color:#4e4e4e20;cursor:pointer}\n"] });
|
|
47
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.14", type: LibsUiComponentsInputsKeyboardComponent, isStandalone: true, selector: "libs_ui-components-inputs-keyboard", outputs: { outKeyCodeSelected: "outKeyCodeSelected" }, ngImport: i0, template: "<div class=\"libs-ui-inputs-keyboard\">\n <span class=\"libs-ui-font-h1s flex justify-center mt-[12px] h-[24px]\">{{ resultSelectKey() }}</span>\n <hr class=\"mt-[12px] mb-[20px]\" />\n <div class=\"flex w-full justify-center\">\n <div class=\"flex flex-wrap -mx-2 p-0 m-0\">\n @for (config of configKeyCodes(); track config) {\n <div class=\"w-1/3 p-0 m-0 flex justify-center !mb-[28px]\">\n <div\n class=\"libs-ui-border-general libs-ui-inputs-keyboard-item libs-ui-font-h1s\"\n (click)=\"handlerClickItem($event, config)\"\n (keydown.enter)=\"handlerClickItem($event, config)\">\n {{ config.label }}\n </div>\n </div>\n }\n </div>\n </div>\n</div>\n", styles: [".libs-ui-inputs-keyboard{background-color:#fff;padding:8px 20px}.libs-ui-inputs-keyboard .libs-ui-inputs-keyboard-item{display:flex;align-items:center;justify-content:center;border-radius:50%;height:52px;width:52px}.libs-ui-inputs-keyboard .libs-ui-inputs-keyboard-item:hover{background-color:#4e4e4e20;cursor:pointer}\n"] });
|
|
48
48
|
}
|
|
49
49
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: LibsUiComponentsInputsKeyboardComponent, decorators: [{
|
|
50
50
|
type: Component,
|
|
51
|
-
args: [{ selector: 'libs_ui-components-inputs-keyboard', standalone: true, template: "<div class=\"libs-ui-inputs-keyboard\">\n <span class=\"libs-ui-font-h1s flex justify-center mt-[12px] h-[24px]\">{{ resultSelectKey() }}</span>\n <hr class=\"mt-[12px] mb-[20px]\" />\n <div class=\"flex w-full justify-center\">\n <div class=\"flex flex-wrap -mx-2 p-0 m-0\">\n @for (config of configKeyCodes(); track config) {\n <div class=\"w-1/3 p-0 m-0 flex justify-center !mb-[28px]\">\n <div\n class=\"libs-ui-border-general libs-ui-inputs-keyboard-item libs-ui-font-h1s\"\n (click)=\"handlerClickItem($event, config)\">\n {{ config.label }}\n </div>\n </div>\n }\n </div>\n </div>\n</div>\n", styles: [".libs-ui-inputs-keyboard{background-color:#fff;padding:8px 20px}.libs-ui-inputs-keyboard .libs-ui-inputs-keyboard-item{display:flex;align-items:center;justify-content:center;border-radius:50%;height:52px;width:52px}.libs-ui-inputs-keyboard .libs-ui-inputs-keyboard-item:hover{background-color:#4e4e4e20;cursor:pointer}\n"] }]
|
|
51
|
+
args: [{ selector: 'libs_ui-components-inputs-keyboard', standalone: true, template: "<div class=\"libs-ui-inputs-keyboard\">\n <span class=\"libs-ui-font-h1s flex justify-center mt-[12px] h-[24px]\">{{ resultSelectKey() }}</span>\n <hr class=\"mt-[12px] mb-[20px]\" />\n <div class=\"flex w-full justify-center\">\n <div class=\"flex flex-wrap -mx-2 p-0 m-0\">\n @for (config of configKeyCodes(); track config) {\n <div class=\"w-1/3 p-0 m-0 flex justify-center !mb-[28px]\">\n <div\n class=\"libs-ui-border-general libs-ui-inputs-keyboard-item libs-ui-font-h1s\"\n (click)=\"handlerClickItem($event, config)\"\n (keydown.enter)=\"handlerClickItem($event, config)\">\n {{ config.label }}\n </div>\n </div>\n }\n </div>\n </div>\n</div>\n", styles: [".libs-ui-inputs-keyboard{background-color:#fff;padding:8px 20px}.libs-ui-inputs-keyboard .libs-ui-inputs-keyboard-item{display:flex;align-items:center;justify-content:center;border-radius:50%;height:52px;width:52px}.libs-ui-inputs-keyboard .libs-ui-inputs-keyboard-item:hover{background-color:#4e4e4e20;cursor:pointer}\n"] }]
|
|
52
52
|
}] });
|
|
53
|
-
//# sourceMappingURL=data:application/json;base64,
|
|
53
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoia2V5Ym9hcmQuY29tcG9uZW50LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vLi4vbGlicy11aS9jb21wb25lbnRzL2lucHV0cy9rZXlib2FyZC9zcmMva2V5Ym9hcmQuY29tcG9uZW50LnRzIiwiLi4vLi4vLi4vLi4vLi4vLi4vbGlicy11aS9jb21wb25lbnRzL2lucHV0cy9rZXlib2FyZC9zcmMva2V5Ym9hcmQuY29tcG9uZW50Lmh0bWwiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFpQixTQUFTLEVBQUUsTUFBTSxFQUFFLE1BQU0sRUFBYSxNQUFNLEVBQUUsTUFBTSxFQUFFLE1BQU0sZUFBZSxDQUFDO0FBRXBHLE9BQU8sRUFBRSxTQUFTLEVBQUUsT0FBTyxFQUFFLFNBQVMsRUFBRSxNQUFNLE1BQU0sQ0FBQztBQUNyRCxPQUFPLEVBQUUsWUFBWSxFQUFFLE1BQU0sMkJBQTJCLENBQUM7O0FBR3pEOzs7R0FHRztBQVFILE1BQU0sT0FBTyx1Q0FBdUM7SUFDbEQsMERBQTBEO0lBQ2hELGVBQWUsR0FBRyxNQUFNLENBQVMsRUFBRSxDQUFDLENBQUM7SUFFL0MsMkRBQTJEO0lBQ2pELGNBQWMsR0FBRyxNQUFNLENBQWtCLFlBQVksRUFBRSxDQUFDLENBQUM7SUFFbEQsU0FBUyxHQUFHLElBQUksT0FBTyxFQUFRLENBQUM7SUFDaEMsSUFBSSxHQUFHLE1BQU0sQ0FBQyxNQUFNLENBQUMsQ0FBQztJQUV2Qyx3RUFBd0U7SUFDL0Qsa0JBQWtCLEdBQUcsTUFBTSxFQUFVLENBQUM7SUFFL0MsZUFBZTtRQUNiLFNBQVMsQ0FBUyxRQUFRLEVBQUUsT0FBTyxDQUFDO2FBQ2pDLElBQUksQ0FBQyxTQUFTLENBQUMsSUFBSSxDQUFDLFNBQVMsQ0FBQyxDQUFDO2FBQy9CLFNBQVMsQ0FBQyxDQUFDLEtBQUssRUFBRSxFQUFFO1lBQ25CLElBQUksQ0FBQyxJQUFJLENBQUMsR0FBRyxDQUFDLEdBQUcsRUFBRTtnQkFDakIsSUFBSSxDQUFDLGFBQWEsQ0FBQyxLQUFLLENBQUMsQ0FBQztZQUM1QixDQUFDLENBQUMsQ0FBQztRQUNMLENBQUMsQ0FBQyxDQUFDO0lBQ1AsQ0FBQztJQUVTLGdCQUFnQixDQUFDLEtBQVksRUFBRSxNQUFnQjtRQUN2RCxLQUFLLEVBQUUsZUFBZSxFQUFFLENBQUM7UUFDekIsSUFBSSxDQUFDLGVBQWUsQ0FBQyxHQUFHLENBQUMsR0FBRyxJQUFJLENBQUMsZUFBZSxFQUFFLEdBQUcsTUFBTSxDQUFDLEtBQUssRUFBRSxDQUFDLENBQUM7UUFDckUsSUFBSSxDQUFDLGtCQUFrQixDQUFDLElBQUksQ0FBQyxNQUFNLENBQUMsSUFBSSxDQUFDLENBQUM7SUFDNUMsQ0FBQztJQUVPLGFBQWEsQ0FBQyxLQUFhO1FBQ2pDLE1BQU0sT0FBTyxHQUFHLEtBQUssQ0FBQyxPQUFPLENBQUM7UUFFOUIsSUFBSSxDQUFDLEVBQUUsSUFBSSxPQUFPLElBQUksT0FBTyxJQUFJLEVBQUUsQ0FBQyxJQUFJLENBQUMsRUFBRSxJQUFJLE9BQU8sSUFBSSxPQUFPLElBQUksR0FBRyxDQUFDLEVBQUUsQ0FBQztZQUMxRSxNQUFNLE1BQU0sR0FBRyxJQUFJLENBQUMsY0FBYyxFQUFFLENBQUMsSUFBSSxDQUFDLENBQUMsSUFBSSxFQUFFLEVBQUUsQ0FBQyxJQUFJLENBQUMsSUFBSSxLQUFLLEdBQUcsS0FBSyxDQUFDLEdBQUcsRUFBRSxDQUFDLENBQUM7WUFFbEYsSUFBSSxNQUFNLEVBQUUsQ0FBQztnQkFDWCxJQUFJLENBQUMsZUFBZSxDQUFDLEdBQUcsQ0FBQyxHQUFHLElBQUksQ0FBQyxlQUFlLEVBQUUsR0FBRyxNQUFNLENBQUMsS0FBSyxFQUFFLENBQUMsQ0FBQztnQkFDckUsSUFBSSxDQUFDLGtCQUFrQixDQUFDLElBQUksQ0FBQyxNQUFNLENBQUMsSUFBSSxDQUFDLENBQUM7WUFDNUMsQ0FBQztRQUNILENBQUM7SUFDSCxDQUFDO0lBRUQsV0FBVztRQUNULElBQUksQ0FBQyxTQUFTLENBQUMsSUFBSSxFQUFFLENBQUM7UUFDdEIsSUFBSSxDQUFDLFNBQVMsQ0FBQyxRQUFRLEVBQUUsQ0FBQztJQUM1QixDQUFDO3dHQTdDVSx1Q0FBdUM7NEZBQXZDLHVDQUF1QyxxSkNqQnBELDh1QkFrQkE7OzRGRERhLHVDQUF1QztrQkFQbkQsU0FBUzsrQkFFRSxvQ0FBb0MsY0FDbEMsSUFBSSIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IEFmdGVyVmlld0luaXQsIENvbXBvbmVudCwgaW5qZWN0LCBOZ1pvbmUsIE9uRGVzdHJveSwgb3V0cHV0LCBzaWduYWwgfSBmcm9tICdAYW5ndWxhci9jb3JlJztcbmltcG9ydCB7IElFdmVudCB9IGZyb20gJ0BsaWJzLXVpL2ludGVyZmFjZXMtdHlwZXMnO1xuaW1wb3J0IHsgZnJvbUV2ZW50LCBTdWJqZWN0LCB0YWtlVW50aWwgfSBmcm9tICdyeGpzJztcbmltcG9ydCB7IGtleXBhZENvbmZpZyB9IGZyb20gJy4vZGVmaW5lcy9rZXlib2FyZC5kZWZpbmUnO1xuaW1wb3J0IHsgSUtleUNvZGUgfSBmcm9tICcuL2ludGVyZmFjZXMva2V5Ym9hcmQuaW50ZXJmYWNlJztcblxuLyoqXG4gKiBDb21wb25lbnQgYsOgbiBwaMOtbSBz4buRIChOdW1lcmljIEtleXBhZClcbiAqIEjhu5cgdHLhu6Mgbmjhuq1wIGxp4buHdSB04burIGNodeG7mXQgdsOgIHBow61tIGPhu6luZyAoMC05KS5cbiAqL1xuQENvbXBvbmVudCh7XG4gIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBAYW5ndWxhci1lc2xpbnQvY29tcG9uZW50LXNlbGVjdG9yXG4gIHNlbGVjdG9yOiAnbGlic191aS1jb21wb25lbnRzLWlucHV0cy1rZXlib2FyZCcsXG4gIHN0YW5kYWxvbmU6IHRydWUsXG4gIHRlbXBsYXRlVXJsOiAnLi9rZXlib2FyZC5jb21wb25lbnQuaHRtbCcsXG4gIHN0eWxlVXJsOiAnLi9rZXlib2FyZC5jb21wb25lbnQuc2NzcycsXG59KVxuZXhwb3J0IGNsYXNzIExpYnNVaUNvbXBvbmVudHNJbnB1dHNLZXlib2FyZENvbXBvbmVudCBpbXBsZW1lbnRzIEFmdGVyVmlld0luaXQsIE9uRGVzdHJveSB7XG4gIC8qKiBDaHXhu5dpIGvDvSB04buxIMSRw6Mgbmjhuq1wIGhp4buDbiB0aOG7iyB0csOqbiBtw6BuIGjDrG5oIGLDoG4gcGjDrW0gKi9cbiAgcHJvdGVjdGVkIHJlc3VsdFNlbGVjdEtleSA9IHNpZ25hbDxzdHJpbmc+KCcnKTtcblxuICAvKiogQ+G6pXUgaMOsbmggY8OhYyBwaMOtbSBi4bqlbSAobeG6t2MgxJHhu4tuaCBs4bqleSB04burIGtleXBhZENvbmZpZykgKi9cbiAgcHJvdGVjdGVkIGNvbmZpZ0tleUNvZGVzID0gc2lnbmFsPEFycmF5PElLZXlDb2RlPj4oa2V5cGFkQ29uZmlnKCkpO1xuXG4gIHByaXZhdGUgcmVhZG9ubHkgb25EZXN0cm95ID0gbmV3IFN1YmplY3Q8dm9pZD4oKTtcbiAgcHJpdmF0ZSByZWFkb25seSB6b25lID0gaW5qZWN0KE5nWm9uZSk7XG5cbiAgLyoqIEV2ZW50IGVtaXQga2hpIG5nxrDhu51pIGTDuW5nIGNo4buNbiBt4buZdCBwaMOtbSAodHLhuqMgduG7gSBtw6MgY29kZSBj4bunYSBwaMOtbSkgKi9cbiAgcmVhZG9ubHkgb3V0S2V5Q29kZVNlbGVjdGVkID0gb3V0cHV0PHN0cmluZz4oKTtcblxuICBuZ0FmdGVyVmlld0luaXQoKSB7XG4gICAgZnJvbUV2ZW50PElFdmVudD4oZG9jdW1lbnQsICdrZXl1cCcpXG4gICAgICAucGlwZSh0YWtlVW50aWwodGhpcy5vbkRlc3Ryb3kpKVxuICAgICAgLnN1YnNjcmliZSgoZXZlbnQpID0+IHtcbiAgICAgICAgdGhpcy56b25lLnJ1bigoKSA9PiB7XG4gICAgICAgICAgdGhpcy5saXN0ZW5lcktleVVwKGV2ZW50KTtcbiAgICAgICAgfSk7XG4gICAgICB9KTtcbiAgfVxuXG4gIHByb3RlY3RlZCBoYW5kbGVyQ2xpY2tJdGVtKGV2ZW50OiBFdmVudCwgY29uZmlnOiBJS2V5Q29kZSkge1xuICAgIGV2ZW50Py5zdG9wUHJvcGFnYXRpb24oKTtcbiAgICB0aGlzLnJlc3VsdFNlbGVjdEtleS5zZXQoYCR7dGhpcy5yZXN1bHRTZWxlY3RLZXkoKX0ke2NvbmZpZy5sYWJlbH1gKTtcbiAgICB0aGlzLm91dEtleUNvZGVTZWxlY3RlZC5lbWl0KGNvbmZpZy5jb2RlKTtcbiAgfVxuXG4gIHByaXZhdGUgbGlzdGVuZXJLZXlVcChldmVudDogSUV2ZW50KSB7XG4gICAgY29uc3Qga2V5Q29kZSA9IGV2ZW50LmtleUNvZGU7XG5cbiAgICBpZiAoKDQ4IDw9IGtleUNvZGUgJiYga2V5Q29kZSA8PSA1NykgfHwgKDk2IDw9IGtleUNvZGUgJiYga2V5Q29kZSA8PSAxMDUpKSB7XG4gICAgICBjb25zdCBjb25maWcgPSB0aGlzLmNvbmZpZ0tleUNvZGVzKCkuZmluZCgoaXRlbSkgPT4gaXRlbS5jb2RlID09PSBgJHtldmVudC5rZXl9YCk7XG5cbiAgICAgIGlmIChjb25maWcpIHtcbiAgICAgICAgdGhpcy5yZXN1bHRTZWxlY3RLZXkuc2V0KGAke3RoaXMucmVzdWx0U2VsZWN0S2V5KCl9JHtjb25maWcubGFiZWx9YCk7XG4gICAgICAgIHRoaXMub3V0S2V5Q29kZVNlbGVjdGVkLmVtaXQoY29uZmlnLmNvZGUpO1xuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIG5nT25EZXN0cm95KCk6IHZvaWQge1xuICAgIHRoaXMub25EZXN0cm95Lm5leHQoKTtcbiAgICB0aGlzLm9uRGVzdHJveS5jb21wbGV0ZSgpO1xuICB9XG59XG4iLCI8ZGl2IGNsYXNzPVwibGlicy11aS1pbnB1dHMta2V5Ym9hcmRcIj5cbiAgPHNwYW4gY2xhc3M9XCJsaWJzLXVpLWZvbnQtaDFzIGZsZXgganVzdGlmeS1jZW50ZXIgbXQtWzEycHhdIGgtWzI0cHhdXCI+e3sgcmVzdWx0U2VsZWN0S2V5KCkgfX08L3NwYW4+XG4gIDxociBjbGFzcz1cIm10LVsxMnB4XSBtYi1bMjBweF1cIiAvPlxuICA8ZGl2IGNsYXNzPVwiZmxleCB3LWZ1bGwganVzdGlmeS1jZW50ZXJcIj5cbiAgICA8ZGl2IGNsYXNzPVwiZmxleCBmbGV4LXdyYXAgLW14LTIgcC0wIG0tMFwiPlxuICAgICAgQGZvciAoY29uZmlnIG9mIGNvbmZpZ0tleUNvZGVzKCk7IHRyYWNrIGNvbmZpZykge1xuICAgICAgICA8ZGl2IGNsYXNzPVwidy0xLzMgcC0wIG0tMCBmbGV4IGp1c3RpZnktY2VudGVyICFtYi1bMjhweF1cIj5cbiAgICAgICAgICA8ZGl2XG4gICAgICAgICAgICBjbGFzcz1cImxpYnMtdWktYm9yZGVyLWdlbmVyYWwgbGlicy11aS1pbnB1dHMta2V5Ym9hcmQtaXRlbSBsaWJzLXVpLWZvbnQtaDFzXCJcbiAgICAgICAgICAgIChjbGljayk9XCJoYW5kbGVyQ2xpY2tJdGVtKCRldmVudCwgY29uZmlnKVwiXG4gICAgICAgICAgICAoa2V5ZG93bi5lbnRlcik9XCJoYW5kbGVyQ2xpY2tJdGVtKCRldmVudCwgY29uZmlnKVwiPlxuICAgICAgICAgICAge3sgY29uZmlnLmxhYmVsIH19XG4gICAgICAgICAgPC9kaXY+XG4gICAgICAgIDwvZGl2PlxuICAgICAgfVxuICAgIDwvZGl2PlxuICA8L2Rpdj5cbjwvZGl2PlxuIl19
|
|
@@ -97,11 +97,11 @@ class LibsUiComponentsInputsKeyboardComponent {
|
|
|
97
97
|
this.onDestroy.complete();
|
|
98
98
|
}
|
|
99
99
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: LibsUiComponentsInputsKeyboardComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
100
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.14", type: LibsUiComponentsInputsKeyboardComponent, isStandalone: true, selector: "libs_ui-components-inputs-keyboard", outputs: { outKeyCodeSelected: "outKeyCodeSelected" }, ngImport: i0, template: "<div class=\"libs-ui-inputs-keyboard\">\n <span class=\"libs-ui-font-h1s flex justify-center mt-[12px] h-[24px]\">{{ resultSelectKey() }}</span>\n <hr class=\"mt-[12px] mb-[20px]\" />\n <div class=\"flex w-full justify-center\">\n <div class=\"flex flex-wrap -mx-2 p-0 m-0\">\n @for (config of configKeyCodes(); track config) {\n <div class=\"w-1/3 p-0 m-0 flex justify-center !mb-[28px]\">\n <div\n class=\"libs-ui-border-general libs-ui-inputs-keyboard-item libs-ui-font-h1s\"\n (click)=\"handlerClickItem($event, config)\">\n {{ config.label }}\n </div>\n </div>\n }\n </div>\n </div>\n</div>\n", styles: [".libs-ui-inputs-keyboard{background-color:#fff;padding:8px 20px}.libs-ui-inputs-keyboard .libs-ui-inputs-keyboard-item{display:flex;align-items:center;justify-content:center;border-radius:50%;height:52px;width:52px}.libs-ui-inputs-keyboard .libs-ui-inputs-keyboard-item:hover{background-color:#4e4e4e20;cursor:pointer}\n"] });
|
|
100
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.14", type: LibsUiComponentsInputsKeyboardComponent, isStandalone: true, selector: "libs_ui-components-inputs-keyboard", outputs: { outKeyCodeSelected: "outKeyCodeSelected" }, ngImport: i0, template: "<div class=\"libs-ui-inputs-keyboard\">\n <span class=\"libs-ui-font-h1s flex justify-center mt-[12px] h-[24px]\">{{ resultSelectKey() }}</span>\n <hr class=\"mt-[12px] mb-[20px]\" />\n <div class=\"flex w-full justify-center\">\n <div class=\"flex flex-wrap -mx-2 p-0 m-0\">\n @for (config of configKeyCodes(); track config) {\n <div class=\"w-1/3 p-0 m-0 flex justify-center !mb-[28px]\">\n <div\n class=\"libs-ui-border-general libs-ui-inputs-keyboard-item libs-ui-font-h1s\"\n (click)=\"handlerClickItem($event, config)\"\n (keydown.enter)=\"handlerClickItem($event, config)\">\n {{ config.label }}\n </div>\n </div>\n }\n </div>\n </div>\n</div>\n", styles: [".libs-ui-inputs-keyboard{background-color:#fff;padding:8px 20px}.libs-ui-inputs-keyboard .libs-ui-inputs-keyboard-item{display:flex;align-items:center;justify-content:center;border-radius:50%;height:52px;width:52px}.libs-ui-inputs-keyboard .libs-ui-inputs-keyboard-item:hover{background-color:#4e4e4e20;cursor:pointer}\n"] });
|
|
101
101
|
}
|
|
102
102
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: LibsUiComponentsInputsKeyboardComponent, decorators: [{
|
|
103
103
|
type: Component,
|
|
104
|
-
args: [{ selector: 'libs_ui-components-inputs-keyboard', standalone: true, template: "<div class=\"libs-ui-inputs-keyboard\">\n <span class=\"libs-ui-font-h1s flex justify-center mt-[12px] h-[24px]\">{{ resultSelectKey() }}</span>\n <hr class=\"mt-[12px] mb-[20px]\" />\n <div class=\"flex w-full justify-center\">\n <div class=\"flex flex-wrap -mx-2 p-0 m-0\">\n @for (config of configKeyCodes(); track config) {\n <div class=\"w-1/3 p-0 m-0 flex justify-center !mb-[28px]\">\n <div\n class=\"libs-ui-border-general libs-ui-inputs-keyboard-item libs-ui-font-h1s\"\n (click)=\"handlerClickItem($event, config)\">\n {{ config.label }}\n </div>\n </div>\n }\n </div>\n </div>\n</div>\n", styles: [".libs-ui-inputs-keyboard{background-color:#fff;padding:8px 20px}.libs-ui-inputs-keyboard .libs-ui-inputs-keyboard-item{display:flex;align-items:center;justify-content:center;border-radius:50%;height:52px;width:52px}.libs-ui-inputs-keyboard .libs-ui-inputs-keyboard-item:hover{background-color:#4e4e4e20;cursor:pointer}\n"] }]
|
|
104
|
+
args: [{ selector: 'libs_ui-components-inputs-keyboard', standalone: true, template: "<div class=\"libs-ui-inputs-keyboard\">\n <span class=\"libs-ui-font-h1s flex justify-center mt-[12px] h-[24px]\">{{ resultSelectKey() }}</span>\n <hr class=\"mt-[12px] mb-[20px]\" />\n <div class=\"flex w-full justify-center\">\n <div class=\"flex flex-wrap -mx-2 p-0 m-0\">\n @for (config of configKeyCodes(); track config) {\n <div class=\"w-1/3 p-0 m-0 flex justify-center !mb-[28px]\">\n <div\n class=\"libs-ui-border-general libs-ui-inputs-keyboard-item libs-ui-font-h1s\"\n (click)=\"handlerClickItem($event, config)\"\n (keydown.enter)=\"handlerClickItem($event, config)\">\n {{ config.label }}\n </div>\n </div>\n }\n </div>\n </div>\n</div>\n", styles: [".libs-ui-inputs-keyboard{background-color:#fff;padding:8px 20px}.libs-ui-inputs-keyboard .libs-ui-inputs-keyboard-item{display:flex;align-items:center;justify-content:center;border-radius:50%;height:52px;width:52px}.libs-ui-inputs-keyboard .libs-ui-inputs-keyboard-item:hover{background-color:#4e4e4e20;cursor:pointer}\n"] }]
|
|
105
105
|
}] });
|
|
106
106
|
|
|
107
107
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"libs-ui-components-inputs-keyboard.mjs","sources":["../../../../../../libs-ui/components/inputs/keyboard/src/defines/keyboard.define.ts","../../../../../../libs-ui/components/inputs/keyboard/src/keyboard.component.ts","../../../../../../libs-ui/components/inputs/keyboard/src/keyboard.component.html","../../../../../../libs-ui/components/inputs/keyboard/src/libs-ui-components-inputs-keyboard.ts"],"sourcesContent":["import { IKeyCode } from '../interfaces/keyboard.interface';\n\nexport const keypadConfig = (): Array<IKeyCode> => {\n return [\n {\n code: '1',\n label: '1',\n },\n {\n code: '2',\n label: '2',\n },\n {\n code: '3',\n label: '3',\n },\n {\n code: '4',\n label: '4',\n },\n {\n code: '5',\n label: '5',\n },\n {\n code: '6',\n label: '6',\n },\n {\n code: '7',\n label: '7',\n },\n {\n code: '8',\n label: '8',\n },\n {\n code: '9',\n label: '9',\n },\n {\n code: '*',\n label: '*',\n },\n {\n code: '0',\n label: '0',\n },\n {\n code: '#',\n label: '#',\n },\n ];\n};\n","import { AfterViewInit, Component, inject, NgZone, OnDestroy, output, signal } from '@angular/core';\nimport { IEvent } from '@libs-ui/interfaces-types';\nimport { fromEvent, Subject, takeUntil } from 'rxjs';\nimport { keypadConfig } from './defines/keyboard.define';\nimport { IKeyCode } from './interfaces/keyboard.interface';\n\n/**\n * Component bàn phím số (Numeric Keypad)\n * Hỗ trợ nhập liệu từ chuột và phím cứng (0-9).\n */\n@Component({\n // eslint-disable-next-line @angular-eslint/component-selector\n selector: 'libs_ui-components-inputs-keyboard',\n standalone: true,\n templateUrl: './keyboard.component.html',\n styleUrl: './keyboard.component.scss',\n})\nexport class LibsUiComponentsInputsKeyboardComponent implements AfterViewInit, OnDestroy {\n /** Chuỗi ký tự đã nhập hiển thị trên màn hình bàn phím */\n protected resultSelectKey = signal<string>('');\n\n /** Cấu hình các phím bấm (mặc định lấy từ keypadConfig) */\n protected configKeyCodes = signal<Array<IKeyCode>>(keypadConfig());\n\n private onDestroy = new Subject<void>();\n private zone = inject(NgZone);\n\n /** Event emit khi người dùng chọn một phím (trả về mã code của phím) */\n readonly outKeyCodeSelected = output<string>();\n\n ngAfterViewInit() {\n fromEvent<IEvent>(document, 'keyup')\n .pipe(takeUntil(this.onDestroy))\n .subscribe((event) => {\n this.zone.run(() => {\n this.listenerKeyUp(event);\n });\n });\n }\n\n protected handlerClickItem(event: Event, config: IKeyCode) {\n event?.stopPropagation();\n this.resultSelectKey.set(`${this.resultSelectKey()}${config.label}`);\n this.outKeyCodeSelected.emit(config.code);\n }\n\n private listenerKeyUp(event: IEvent) {\n const keyCode = event.keyCode;\n\n if ((48 <= keyCode && keyCode <= 57) || (96 <= keyCode && keyCode <= 105)) {\n const config = this.configKeyCodes().find((item) => item.code === `${event.key}`);\n\n if (config) {\n this.resultSelectKey.set(`${this.resultSelectKey()}${config.label}`);\n this.outKeyCodeSelected.emit(config.code);\n }\n }\n }\n\n ngOnDestroy(): void {\n this.onDestroy.next();\n this.onDestroy.complete();\n }\n}\n","<div class=\"libs-ui-inputs-keyboard\">\n <span class=\"libs-ui-font-h1s flex justify-center mt-[12px] h-[24px]\">{{ resultSelectKey() }}</span>\n <hr class=\"mt-[12px] mb-[20px]\" />\n <div class=\"flex w-full justify-center\">\n <div class=\"flex flex-wrap -mx-2 p-0 m-0\">\n @for (config of configKeyCodes(); track config) {\n <div class=\"w-1/3 p-0 m-0 flex justify-center !mb-[28px]\">\n <div\n class=\"libs-ui-border-general libs-ui-inputs-keyboard-item libs-ui-font-h1s\"\n (click)=\"handlerClickItem($event, config)\">\n {{ config.label }}\n </div>\n </div>\n }\n </div>\n </div>\n</div>\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":";;;;AAEO,MAAM,YAAY,GAAG,MAAsB;IAChD,OAAO;AACL,QAAA;AACE,YAAA,IAAI,EAAE,GAAG;AACT,YAAA,KAAK,EAAE,GAAG;AACX,SAAA;AACD,QAAA;AACE,YAAA,IAAI,EAAE,GAAG;AACT,YAAA,KAAK,EAAE,GAAG;AACX,SAAA;AACD,QAAA;AACE,YAAA,IAAI,EAAE,GAAG;AACT,YAAA,KAAK,EAAE,GAAG;AACX,SAAA;AACD,QAAA;AACE,YAAA,IAAI,EAAE,GAAG;AACT,YAAA,KAAK,EAAE,GAAG;AACX,SAAA;AACD,QAAA;AACE,YAAA,IAAI,EAAE,GAAG;AACT,YAAA,KAAK,EAAE,GAAG;AACX,SAAA;AACD,QAAA;AACE,YAAA,IAAI,EAAE,GAAG;AACT,YAAA,KAAK,EAAE,GAAG;AACX,SAAA;AACD,QAAA;AACE,YAAA,IAAI,EAAE,GAAG;AACT,YAAA,KAAK,EAAE,GAAG;AACX,SAAA;AACD,QAAA;AACE,YAAA,IAAI,EAAE,GAAG;AACT,YAAA,KAAK,EAAE,GAAG;AACX,SAAA;AACD,QAAA;AACE,YAAA,IAAI,EAAE,GAAG;AACT,YAAA,KAAK,EAAE,GAAG;AACX,SAAA;AACD,QAAA;AACE,YAAA,IAAI,EAAE,GAAG;AACT,YAAA,KAAK,EAAE,GAAG;AACX,SAAA;AACD,QAAA;AACE,YAAA,IAAI,EAAE,GAAG;AACT,YAAA,KAAK,EAAE,GAAG;AACX,SAAA;AACD,QAAA;AACE,YAAA,IAAI,EAAE,GAAG;AACT,YAAA,KAAK,EAAE,GAAG;AACX,SAAA;KACF;
|
|
1
|
+
{"version":3,"file":"libs-ui-components-inputs-keyboard.mjs","sources":["../../../../../../libs-ui/components/inputs/keyboard/src/defines/keyboard.define.ts","../../../../../../libs-ui/components/inputs/keyboard/src/keyboard.component.ts","../../../../../../libs-ui/components/inputs/keyboard/src/keyboard.component.html","../../../../../../libs-ui/components/inputs/keyboard/src/libs-ui-components-inputs-keyboard.ts"],"sourcesContent":["import { IKeyCode } from '../interfaces/keyboard.interface';\n\nexport const keypadConfig = (): Array<IKeyCode> => {\n return [\n {\n code: '1',\n label: '1',\n },\n {\n code: '2',\n label: '2',\n },\n {\n code: '3',\n label: '3',\n },\n {\n code: '4',\n label: '4',\n },\n {\n code: '5',\n label: '5',\n },\n {\n code: '6',\n label: '6',\n },\n {\n code: '7',\n label: '7',\n },\n {\n code: '8',\n label: '8',\n },\n {\n code: '9',\n label: '9',\n },\n {\n code: '*',\n label: '*',\n },\n {\n code: '0',\n label: '0',\n },\n {\n code: '#',\n label: '#',\n },\n ];\n};\n","import { AfterViewInit, Component, inject, NgZone, OnDestroy, output, signal } from '@angular/core';\nimport { IEvent } from '@libs-ui/interfaces-types';\nimport { fromEvent, Subject, takeUntil } from 'rxjs';\nimport { keypadConfig } from './defines/keyboard.define';\nimport { IKeyCode } from './interfaces/keyboard.interface';\n\n/**\n * Component bàn phím số (Numeric Keypad)\n * Hỗ trợ nhập liệu từ chuột và phím cứng (0-9).\n */\n@Component({\n // eslint-disable-next-line @angular-eslint/component-selector\n selector: 'libs_ui-components-inputs-keyboard',\n standalone: true,\n templateUrl: './keyboard.component.html',\n styleUrl: './keyboard.component.scss',\n})\nexport class LibsUiComponentsInputsKeyboardComponent implements AfterViewInit, OnDestroy {\n /** Chuỗi ký tự đã nhập hiển thị trên màn hình bàn phím */\n protected resultSelectKey = signal<string>('');\n\n /** Cấu hình các phím bấm (mặc định lấy từ keypadConfig) */\n protected configKeyCodes = signal<Array<IKeyCode>>(keypadConfig());\n\n private readonly onDestroy = new Subject<void>();\n private readonly zone = inject(NgZone);\n\n /** Event emit khi người dùng chọn một phím (trả về mã code của phím) */\n readonly outKeyCodeSelected = output<string>();\n\n ngAfterViewInit() {\n fromEvent<IEvent>(document, 'keyup')\n .pipe(takeUntil(this.onDestroy))\n .subscribe((event) => {\n this.zone.run(() => {\n this.listenerKeyUp(event);\n });\n });\n }\n\n protected handlerClickItem(event: Event, config: IKeyCode) {\n event?.stopPropagation();\n this.resultSelectKey.set(`${this.resultSelectKey()}${config.label}`);\n this.outKeyCodeSelected.emit(config.code);\n }\n\n private listenerKeyUp(event: IEvent) {\n const keyCode = event.keyCode;\n\n if ((48 <= keyCode && keyCode <= 57) || (96 <= keyCode && keyCode <= 105)) {\n const config = this.configKeyCodes().find((item) => item.code === `${event.key}`);\n\n if (config) {\n this.resultSelectKey.set(`${this.resultSelectKey()}${config.label}`);\n this.outKeyCodeSelected.emit(config.code);\n }\n }\n }\n\n ngOnDestroy(): void {\n this.onDestroy.next();\n this.onDestroy.complete();\n }\n}\n","<div class=\"libs-ui-inputs-keyboard\">\n <span class=\"libs-ui-font-h1s flex justify-center mt-[12px] h-[24px]\">{{ resultSelectKey() }}</span>\n <hr class=\"mt-[12px] mb-[20px]\" />\n <div class=\"flex w-full justify-center\">\n <div class=\"flex flex-wrap -mx-2 p-0 m-0\">\n @for (config of configKeyCodes(); track config) {\n <div class=\"w-1/3 p-0 m-0 flex justify-center !mb-[28px]\">\n <div\n class=\"libs-ui-border-general libs-ui-inputs-keyboard-item libs-ui-font-h1s\"\n (click)=\"handlerClickItem($event, config)\"\n (keydown.enter)=\"handlerClickItem($event, config)\">\n {{ config.label }}\n </div>\n </div>\n }\n </div>\n </div>\n</div>\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":";;;;AAEO,MAAM,YAAY,GAAG,MAAsB;IAChD,OAAO;AACL,QAAA;AACE,YAAA,IAAI,EAAE,GAAG;AACT,YAAA,KAAK,EAAE,GAAG;AACX,SAAA;AACD,QAAA;AACE,YAAA,IAAI,EAAE,GAAG;AACT,YAAA,KAAK,EAAE,GAAG;AACX,SAAA;AACD,QAAA;AACE,YAAA,IAAI,EAAE,GAAG;AACT,YAAA,KAAK,EAAE,GAAG;AACX,SAAA;AACD,QAAA;AACE,YAAA,IAAI,EAAE,GAAG;AACT,YAAA,KAAK,EAAE,GAAG;AACX,SAAA;AACD,QAAA;AACE,YAAA,IAAI,EAAE,GAAG;AACT,YAAA,KAAK,EAAE,GAAG;AACX,SAAA;AACD,QAAA;AACE,YAAA,IAAI,EAAE,GAAG;AACT,YAAA,KAAK,EAAE,GAAG;AACX,SAAA;AACD,QAAA;AACE,YAAA,IAAI,EAAE,GAAG;AACT,YAAA,KAAK,EAAE,GAAG;AACX,SAAA;AACD,QAAA;AACE,YAAA,IAAI,EAAE,GAAG;AACT,YAAA,KAAK,EAAE,GAAG;AACX,SAAA;AACD,QAAA;AACE,YAAA,IAAI,EAAE,GAAG;AACT,YAAA,KAAK,EAAE,GAAG;AACX,SAAA;AACD,QAAA;AACE,YAAA,IAAI,EAAE,GAAG;AACT,YAAA,KAAK,EAAE,GAAG;AACX,SAAA;AACD,QAAA;AACE,YAAA,IAAI,EAAE,GAAG;AACT,YAAA,KAAK,EAAE,GAAG;AACX,SAAA;AACD,QAAA;AACE,YAAA,IAAI,EAAE,GAAG;AACT,YAAA,KAAK,EAAE,GAAG;AACX,SAAA;KACF,CAAC;AACJ;;AC/CA;;;AAGG;MAQU,uCAAuC,CAAA;;AAExC,IAAA,eAAe,GAAG,MAAM,CAAS,EAAE,CAAC,CAAC;;AAGrC,IAAA,cAAc,GAAG,MAAM,CAAkB,YAAY,EAAE,CAAC,CAAC;AAElD,IAAA,SAAS,GAAG,IAAI,OAAO,EAAQ,CAAC;AAChC,IAAA,IAAI,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC;;IAG9B,kBAAkB,GAAG,MAAM,EAAU,CAAC;IAE/C,eAAe,GAAA;AACb,QAAA,SAAS,CAAS,QAAQ,EAAE,OAAO,CAAC;AACjC,aAAA,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;AAC/B,aAAA,SAAS,CAAC,CAAC,KAAK,KAAI;AACnB,YAAA,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,MAAK;AACjB,gBAAA,IAAI,CAAC,aAAa,CAAC,KAAK,CAAC,CAAC;AAC5B,aAAC,CAAC,CAAC;AACL,SAAC,CAAC,CAAC;KACN;IAES,gBAAgB,CAAC,KAAY,EAAE,MAAgB,EAAA;QACvD,KAAK,EAAE,eAAe,EAAE,CAAC;AACzB,QAAA,IAAI,CAAC,eAAe,CAAC,GAAG,CAAC,GAAG,IAAI,CAAC,eAAe,EAAE,GAAG,MAAM,CAAC,KAAK,CAAA,CAAE,CAAC,CAAC;QACrE,IAAI,CAAC,kBAAkB,CAAC,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;KAC3C;AAEO,IAAA,aAAa,CAAC,KAAa,EAAA;AACjC,QAAA,MAAM,OAAO,GAAG,KAAK,CAAC,OAAO,CAAC;QAE9B,IAAI,CAAC,EAAE,IAAI,OAAO,IAAI,OAAO,IAAI,EAAE,MAAM,EAAE,IAAI,OAAO,IAAI,OAAO,IAAI,GAAG,CAAC,EAAE;YACzE,MAAM,MAAM,GAAG,IAAI,CAAC,cAAc,EAAE,CAAC,IAAI,CAAC,CAAC,IAAI,KAAK,IAAI,CAAC,IAAI,KAAK,CAAA,EAAG,KAAK,CAAC,GAAG,CAAE,CAAA,CAAC,CAAC;YAElF,IAAI,MAAM,EAAE;AACV,gBAAA,IAAI,CAAC,eAAe,CAAC,GAAG,CAAC,GAAG,IAAI,CAAC,eAAe,EAAE,GAAG,MAAM,CAAC,KAAK,CAAA,CAAE,CAAC,CAAC;gBACrE,IAAI,CAAC,kBAAkB,CAAC,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;aAC3C;SACF;KACF;IAED,WAAW,GAAA;AACT,QAAA,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE,CAAC;AACtB,QAAA,IAAI,CAAC,SAAS,CAAC,QAAQ,EAAE,CAAC;KAC3B;wGA7CU,uCAAuC,EAAA,IAAA,EAAA,EAAA,EAAA,MAAA,EAAA,EAAA,CAAA,eAAA,CAAA,SAAA,EAAA,CAAA,CAAA;AAAvC,IAAA,OAAA,IAAA,GAAA,EAAA,CAAA,oBAAA,CAAA,EAAA,UAAA,EAAA,QAAA,EAAA,OAAA,EAAA,SAAA,EAAA,IAAA,EAAA,uCAAuC,qJCjBpD,8uBAkBA,EAAA,MAAA,EAAA,CAAA,kUAAA,CAAA,EAAA,CAAA,CAAA;;4FDDa,uCAAuC,EAAA,UAAA,EAAA,CAAA;kBAPnD,SAAS;AAEE,YAAA,IAAA,EAAA,CAAA,EAAA,QAAA,EAAA,oCAAoC,cAClC,IAAI,EAAA,QAAA,EAAA,8uBAAA,EAAA,MAAA,EAAA,CAAA,kUAAA,CAAA,EAAA,CAAA;;;AEblB;;AAEG;;;;"}
|
package/keyboard.component.d.ts
CHANGED
|
@@ -10,8 +10,8 @@ export declare class LibsUiComponentsInputsKeyboardComponent implements AfterVie
|
|
|
10
10
|
protected resultSelectKey: import("@angular/core").WritableSignal<string>;
|
|
11
11
|
/** Cấu hình các phím bấm (mặc định lấy từ keypadConfig) */
|
|
12
12
|
protected configKeyCodes: import("@angular/core").WritableSignal<IKeyCode[]>;
|
|
13
|
-
private onDestroy;
|
|
14
|
-
private zone;
|
|
13
|
+
private readonly onDestroy;
|
|
14
|
+
private readonly zone;
|
|
15
15
|
/** Event emit khi người dùng chọn một phím (trả về mã code của phím) */
|
|
16
16
|
readonly outKeyCodeSelected: import("@angular/core").OutputEmitterRef<string>;
|
|
17
17
|
ngAfterViewInit(): void;
|
package/package.json
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@libs-ui/components-inputs-keyboard",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.357-0",
|
|
4
4
|
"peerDependencies": {
|
|
5
|
-
"@angular/
|
|
6
|
-
"@
|
|
5
|
+
"@angular/core": ">=18.0.0",
|
|
6
|
+
"@libs-ui/interfaces-types": "0.2.357-0",
|
|
7
|
+
"rxjs": "~7.8.0"
|
|
7
8
|
},
|
|
8
9
|
"sideEffects": false,
|
|
9
10
|
"module": "fesm2022/libs-ui-components-inputs-keyboard.mjs",
|