@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ố trực quan (0-9, \*, #). Component này tự động lắng nghe các sự kiện từ bàn phím cứng của người dùng để đồng bộ hóa việc nhập liệu, phù hợp cho các màn hình nhập mã PIN, mật khẩu số hoặc các ứng dụng Dialer.
7
+ `LibsUiComponentsInputsKeyboardComponent` cung cấp giao diện bàn phím số tiêu chuẩn gồm các phím 09, `*` `#`. 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
- ### Tính năng
9
+ ## Tính năng
10
10
 
11
- - ✅ Giao diện bàn phím số tiêu chuẩn (0-9, \*, #)
12
- - ✅ Đồng bộ hóa tự động với bàn phím cứng (0-9)
13
- - ✅ Hiển thị kết quả nhập liệu nội bộ trực quan
14
- - ✅ Emit mã code phím đã chọn qua output event
15
- - ✅ Sử dụng Angular Signals cho hiệu năng cao
16
- - ✅ Thiết kế Responsive, dễ dàng tích hợp
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ố 09, 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
- - Khi cần màn hình nhập mã PIN hoặc mật khẩu chỉ có số.
21
- - Các ứng dụng cần bàn phím số lớn (vd: trên máy POS, thiết bị cảm ứng).
22
- - Tích hợp trong các module quay số (Dialer/VoIP).
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
- ## dụ
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
- <libs_ui-components-inputs-keyboard (outKeyCodeSelected)="onKeySelect($event)" />
61
+ <!-- template.html -->
62
+ <libs_ui-components-inputs-keyboard
63
+ (outKeyCodeSelected)="handlerKeySelect($event)"
64
+ />
53
65
  ```
54
66
 
55
- ## API
67
+ ```typescript
68
+ // component.ts
69
+ import { Component } from '@angular/core';
70
+ import { LibsUiComponentsInputsKeyboardComponent } from '@libs-ui/components-inputs-keyboard';
56
71
 
57
- ### libs_ui-components-inputs-keyboard
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
- #### Inputs
86
+ > Vì `outKeyCodeSelected` emit kiểu `string` (không phải `Event`), handler nhận thẳng `string`:
60
87
 
61
- _Component hiện tại không có inputs công khai._
88
+ ```typescript
89
+ handlerKeySelect(code: string): void {
90
+ console.log('Phím được nhấn:', code);
91
+ }
92
+ ```
62
93
 
63
- #### Outputs
94
+ ### Ví dụ 2 — Xây dựng chuỗi PIN
64
95
 
65
- | Property | Type | Description |
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
- ## Tuyến bố về sự kiện (Events)
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
- Component lắng nghe sự kiện `keyup` trên toàn bộ `document`. Khi người dùng nhấn các phím từ `0` đến `9` trên bàn phím cứng, component sẽ tự động cập nhật trạng thái hiển thị và emit event ra ngoài tương tự như khi click chuột vào phím tương ứng trên UI.
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
- ## Công nghệ
143
+ ### dụ 3 — Theo dõi từng phím và toàn bộ chuỗi
74
144
 
75
- | Technology | Version | Purpose |
76
- | --------------- | ------- | ---------------- |
77
- | Angular | 18+ | Framework |
78
- | Angular Signals | - | State management |
79
- | RxJS | 7.x | Event handling |
80
- | OnPush | - | Change Detection |
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: `http://localhost:4500/inputs/keyboard`
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
- # Coverage
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,eyJ2ZXJzaW9uIjozLCJmaWxlIjoia2V5Ym9hcmQuY29tcG9uZW50LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vLi4vbGlicy11aS9jb21wb25lbnRzL2lucHV0cy9rZXlib2FyZC9zcmMva2V5Ym9hcmQuY29tcG9uZW50LnRzIiwiLi4vLi4vLi4vLi4vLi4vLi4vbGlicy11aS9jb21wb25lbnRzL2lucHV0cy9rZXlib2FyZC9zcmMva2V5Ym9hcmQuY29tcG9uZW50Lmh0bWwiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFpQixTQUFTLEVBQUUsTUFBTSxFQUFFLE1BQU0sRUFBYSxNQUFNLEVBQUUsTUFBTSxFQUFFLE1BQU0sZUFBZSxDQUFDO0FBRXBHLE9BQU8sRUFBRSxTQUFTLEVBQUUsT0FBTyxFQUFFLFNBQVMsRUFBRSxNQUFNLE1BQU0sQ0FBQztBQUNyRCxPQUFPLEVBQUUsWUFBWSxFQUFFLE1BQU0sMkJBQTJCLENBQUM7O0FBR3pEOzs7R0FHRztBQVFILE1BQU0sT0FBTyx1Q0FBdUM7SUFDbEQsMERBQTBEO0lBQ2hELGVBQWUsR0FBRyxNQUFNLENBQVMsRUFBRSxDQUFDLENBQUM7SUFFL0MsMkRBQTJEO0lBQ2pELGNBQWMsR0FBRyxNQUFNLENBQWtCLFlBQVksRUFBRSxDQUFDLENBQUM7SUFFM0QsU0FBUyxHQUFHLElBQUksT0FBTyxFQUFRLENBQUM7SUFDaEMsSUFBSSxHQUFHLE1BQU0sQ0FBQyxNQUFNLENBQUMsQ0FBQztJQUU5Qix3RUFBd0U7SUFDL0Qsa0JBQWtCLEdBQUcsTUFBTSxFQUFVLENBQUM7SUFFL0MsZUFBZTtRQUNiLFNBQVMsQ0FBUyxRQUFRLEVBQUUsT0FBTyxDQUFDO2FBQ2pDLElBQUksQ0FBQyxTQUFTLENBQUMsSUFBSSxDQUFDLFNBQVMsQ0FBQyxDQUFDO2FBQy9CLFNBQVMsQ0FBQyxDQUFDLEtBQUssRUFBRSxFQUFFO1lBQ25CLElBQUksQ0FBQyxJQUFJLENBQUMsR0FBRyxDQUFDLEdBQUcsRUFBRTtnQkFDakIsSUFBSSxDQUFDLGFBQWEsQ0FBQyxLQUFLLENBQUMsQ0FBQztZQUM1QixDQUFDLENBQUMsQ0FBQztRQUNMLENBQUMsQ0FBQyxDQUFDO0lBQ1AsQ0FBQztJQUVTLGdCQUFnQixDQUFDLEtBQVksRUFBRSxNQUFnQjtRQUN2RCxLQUFLLEVBQUUsZUFBZSxFQUFFLENBQUM7UUFDekIsSUFBSSxDQUFDLGVBQWUsQ0FBQyxHQUFHLENBQUMsR0FBRyxJQUFJLENBQUMsZUFBZSxFQUFFLEdBQUcsTUFBTSxDQUFDLEtBQUssRUFBRSxDQUFDLENBQUM7UUFDckUsSUFBSSxDQUFDLGtCQUFrQixDQUFDLElBQUksQ0FBQyxNQUFNLENBQUMsSUFBSSxDQUFDLENBQUM7SUFDNUMsQ0FBQztJQUVPLGFBQWEsQ0FBQyxLQUFhO1FBQ2pDLE1BQU0sT0FBTyxHQUFHLEtBQUssQ0FBQyxPQUFPLENBQUM7UUFFOUIsSUFBSSxDQUFDLEVBQUUsSUFBSSxPQUFPLElBQUksT0FBTyxJQUFJLEVBQUUsQ0FBQyxJQUFJLENBQUMsRUFBRSxJQUFJLE9BQU8sSUFBSSxPQUFPLElBQUksR0FBRyxDQUFDLEVBQUUsQ0FBQztZQUMxRSxNQUFNLE1BQU0sR0FBRyxJQUFJLENBQUMsY0FBYyxFQUFFLENBQUMsSUFBSSxDQUFDLENBQUMsSUFBSSxFQUFFLEVBQUUsQ0FBQyxJQUFJLENBQUMsSUFBSSxLQUFLLEdBQUcsS0FBSyxDQUFDLEdBQUcsRUFBRSxDQUFDLENBQUM7WUFFbEYsSUFBSSxNQUFNLEVBQUUsQ0FBQztnQkFDWCxJQUFJLENBQUMsZUFBZSxDQUFDLEdBQUcsQ0FBQyxHQUFHLElBQUksQ0FBQyxlQUFlLEVBQUUsR0FBRyxNQUFNLENBQUMsS0FBSyxFQUFFLENBQUMsQ0FBQztnQkFDckUsSUFBSSxDQUFDLGtCQUFrQixDQUFDLElBQUksQ0FBQyxNQUFNLENBQUMsSUFBSSxDQUFDLENBQUM7WUFDNUMsQ0FBQztRQUNILENBQUM7SUFDSCxDQUFDO0lBRUQsV0FBVztRQUNULElBQUksQ0FBQyxTQUFTLENBQUMsSUFBSSxFQUFFLENBQUM7UUFDdEIsSUFBSSxDQUFDLFNBQVMsQ0FBQyxRQUFRLEVBQUUsQ0FBQztJQUM1QixDQUFDO3dHQTdDVSx1Q0FBdUM7NEZBQXZDLHVDQUF1QyxxSkNqQnBELDRxQkFpQkE7OzRGREFhLHVDQUF1QztrQkFQbkQsU0FBUzsrQkFFRSxvQ0FBb0MsY0FDbEMsSUFBSSIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IEFmdGVyVmlld0luaXQsIENvbXBvbmVudCwgaW5qZWN0LCBOZ1pvbmUsIE9uRGVzdHJveSwgb3V0cHV0LCBzaWduYWwgfSBmcm9tICdAYW5ndWxhci9jb3JlJztcbmltcG9ydCB7IElFdmVudCB9IGZyb20gJ0BsaWJzLXVpL2ludGVyZmFjZXMtdHlwZXMnO1xuaW1wb3J0IHsgZnJvbUV2ZW50LCBTdWJqZWN0LCB0YWtlVW50aWwgfSBmcm9tICdyeGpzJztcbmltcG9ydCB7IGtleXBhZENvbmZpZyB9IGZyb20gJy4vZGVmaW5lcy9rZXlib2FyZC5kZWZpbmUnO1xuaW1wb3J0IHsgSUtleUNvZGUgfSBmcm9tICcuL2ludGVyZmFjZXMva2V5Ym9hcmQuaW50ZXJmYWNlJztcblxuLyoqXG4gKiBDb21wb25lbnQgYsOgbiBwaMOtbSBz4buRIChOdW1lcmljIEtleXBhZClcbiAqIEjhu5cgdHLhu6Mgbmjhuq1wIGxp4buHdSB04burIGNodeG7mXQgdsOgIHBow61tIGPhu6luZyAoMC05KS5cbiAqL1xuQENvbXBvbmVudCh7XG4gIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBAYW5ndWxhci1lc2xpbnQvY29tcG9uZW50LXNlbGVjdG9yXG4gIHNlbGVjdG9yOiAnbGlic191aS1jb21wb25lbnRzLWlucHV0cy1rZXlib2FyZCcsXG4gIHN0YW5kYWxvbmU6IHRydWUsXG4gIHRlbXBsYXRlVXJsOiAnLi9rZXlib2FyZC5jb21wb25lbnQuaHRtbCcsXG4gIHN0eWxlVXJsOiAnLi9rZXlib2FyZC5jb21wb25lbnQuc2NzcycsXG59KVxuZXhwb3J0IGNsYXNzIExpYnNVaUNvbXBvbmVudHNJbnB1dHNLZXlib2FyZENvbXBvbmVudCBpbXBsZW1lbnRzIEFmdGVyVmlld0luaXQsIE9uRGVzdHJveSB7XG4gIC8qKiBDaHXhu5dpIGvDvSB04buxIMSRw6Mgbmjhuq1wIGhp4buDbiB0aOG7iyB0csOqbiBtw6BuIGjDrG5oIGLDoG4gcGjDrW0gKi9cbiAgcHJvdGVjdGVkIHJlc3VsdFNlbGVjdEtleSA9IHNpZ25hbDxzdHJpbmc+KCcnKTtcblxuICAvKiogQ+G6pXUgaMOsbmggY8OhYyBwaMOtbSBi4bqlbSAobeG6t2MgxJHhu4tuaCBs4bqleSB04burIGtleXBhZENvbmZpZykgKi9cbiAgcHJvdGVjdGVkIGNvbmZpZ0tleUNvZGVzID0gc2lnbmFsPEFycmF5PElLZXlDb2RlPj4oa2V5cGFkQ29uZmlnKCkpO1xuXG4gIHByaXZhdGUgb25EZXN0cm95ID0gbmV3IFN1YmplY3Q8dm9pZD4oKTtcbiAgcHJpdmF0ZSB6b25lID0gaW5qZWN0KE5nWm9uZSk7XG5cbiAgLyoqIEV2ZW50IGVtaXQga2hpIG5nxrDhu51pIGTDuW5nIGNo4buNbiBt4buZdCBwaMOtbSAodHLhuqMgduG7gSBtw6MgY29kZSBj4bunYSBwaMOtbSkgKi9cbiAgcmVhZG9ubHkgb3V0S2V5Q29kZVNlbGVjdGVkID0gb3V0cHV0PHN0cmluZz4oKTtcblxuICBuZ0FmdGVyVmlld0luaXQoKSB7XG4gICAgZnJvbUV2ZW50PElFdmVudD4oZG9jdW1lbnQsICdrZXl1cCcpXG4gICAgICAucGlwZSh0YWtlVW50aWwodGhpcy5vbkRlc3Ryb3kpKVxuICAgICAgLnN1YnNjcmliZSgoZXZlbnQpID0+IHtcbiAgICAgICAgdGhpcy56b25lLnJ1bigoKSA9PiB7XG4gICAgICAgICAgdGhpcy5saXN0ZW5lcktleVVwKGV2ZW50KTtcbiAgICAgICAgfSk7XG4gICAgICB9KTtcbiAgfVxuXG4gIHByb3RlY3RlZCBoYW5kbGVyQ2xpY2tJdGVtKGV2ZW50OiBFdmVudCwgY29uZmlnOiBJS2V5Q29kZSkge1xuICAgIGV2ZW50Py5zdG9wUHJvcGFnYXRpb24oKTtcbiAgICB0aGlzLnJlc3VsdFNlbGVjdEtleS5zZXQoYCR7dGhpcy5yZXN1bHRTZWxlY3RLZXkoKX0ke2NvbmZpZy5sYWJlbH1gKTtcbiAgICB0aGlzLm91dEtleUNvZGVTZWxlY3RlZC5lbWl0KGNvbmZpZy5jb2RlKTtcbiAgfVxuXG4gIHByaXZhdGUgbGlzdGVuZXJLZXlVcChldmVudDogSUV2ZW50KSB7XG4gICAgY29uc3Qga2V5Q29kZSA9IGV2ZW50LmtleUNvZGU7XG5cbiAgICBpZiAoKDQ4IDw9IGtleUNvZGUgJiYga2V5Q29kZSA8PSA1NykgfHwgKDk2IDw9IGtleUNvZGUgJiYga2V5Q29kZSA8PSAxMDUpKSB7XG4gICAgICBjb25zdCBjb25maWcgPSB0aGlzLmNvbmZpZ0tleUNvZGVzKCkuZmluZCgoaXRlbSkgPT4gaXRlbS5jb2RlID09PSBgJHtldmVudC5rZXl9YCk7XG5cbiAgICAgIGlmIChjb25maWcpIHtcbiAgICAgICAgdGhpcy5yZXN1bHRTZWxlY3RLZXkuc2V0KGAke3RoaXMucmVzdWx0U2VsZWN0S2V5KCl9JHtjb25maWcubGFiZWx9YCk7XG4gICAgICAgIHRoaXMub3V0S2V5Q29kZVNlbGVjdGVkLmVtaXQoY29uZmlnLmNvZGUpO1xuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIG5nT25EZXN0cm95KCk6IHZvaWQge1xuICAgIHRoaXMub25EZXN0cm95Lm5leHQoKTtcbiAgICB0aGlzLm9uRGVzdHJveS5jb21wbGV0ZSgpO1xuICB9XG59XG4iLCI8ZGl2IGNsYXNzPVwibGlicy11aS1pbnB1dHMta2V5Ym9hcmRcIj5cbiAgPHNwYW4gY2xhc3M9XCJsaWJzLXVpLWZvbnQtaDFzIGZsZXgganVzdGlmeS1jZW50ZXIgbXQtWzEycHhdIGgtWzI0cHhdXCI+e3sgcmVzdWx0U2VsZWN0S2V5KCkgfX08L3NwYW4+XG4gIDxociBjbGFzcz1cIm10LVsxMnB4XSBtYi1bMjBweF1cIiAvPlxuICA8ZGl2IGNsYXNzPVwiZmxleCB3LWZ1bGwganVzdGlmeS1jZW50ZXJcIj5cbiAgICA8ZGl2IGNsYXNzPVwiZmxleCBmbGV4LXdyYXAgLW14LTIgcC0wIG0tMFwiPlxuICAgICAgQGZvciAoY29uZmlnIG9mIGNvbmZpZ0tleUNvZGVzKCk7IHRyYWNrIGNvbmZpZykge1xuICAgICAgICA8ZGl2IGNsYXNzPVwidy0xLzMgcC0wIG0tMCBmbGV4IGp1c3RpZnktY2VudGVyICFtYi1bMjhweF1cIj5cbiAgICAgICAgICA8ZGl2XG4gICAgICAgICAgICBjbGFzcz1cImxpYnMtdWktYm9yZGVyLWdlbmVyYWwgbGlicy11aS1pbnB1dHMta2V5Ym9hcmQtaXRlbSBsaWJzLXVpLWZvbnQtaDFzXCJcbiAgICAgICAgICAgIChjbGljayk9XCJoYW5kbGVyQ2xpY2tJdGVtKCRldmVudCwgY29uZmlnKVwiPlxuICAgICAgICAgICAge3sgY29uZmlnLmxhYmVsIH19XG4gICAgICAgICAgPC9kaXY+XG4gICAgICAgIDwvZGl2PlxuICAgICAgfVxuICAgIDwvZGl2PlxuICA8L2Rpdj5cbjwvZGl2PlxuIl19
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":"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"}
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":"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"}
@@ -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.356-8",
3
+ "version": "0.2.357-0",
4
4
  "peerDependencies": {
5
- "@angular/common": ">=18.0.0",
6
- "@angular/core": ">=18.0.0"
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",