systelab-virtual-keyboard 0.0.1
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 +37 -0
- package/esm2022/lib/constants.mjs +32 -0
- package/esm2022/lib/systelab-virtual-keyboard-overlay.service.mjs +123 -0
- package/esm2022/lib/systelab-virtual-keyboard.component.mjs +352 -0
- package/esm2022/lib/systelab-virtual-keyboard.config.mjs +3 -0
- package/esm2022/lib/systelab-virtual-keyboard.directive.mjs +190 -0
- package/esm2022/lib/systelab-virtual-keyboard.module.mjs +45 -0
- package/esm2022/public-api.mjs +7 -0
- package/esm2022/systelab-virtual-keyboard.mjs +5 -0
- package/fesm2022/systelab-virtual-keyboard.mjs +739 -0
- package/fesm2022/systelab-virtual-keyboard.mjs.map +1 -0
- package/index.d.ts +6 -0
- package/lib/constants.d.ts +21 -0
- package/lib/constants.d.ts.map +1 -0
- package/lib/systelab-virtual-keyboard-overlay.service.d.ts +26 -0
- package/lib/systelab-virtual-keyboard-overlay.service.d.ts.map +1 -0
- package/lib/systelab-virtual-keyboard.component.d.ts +43 -0
- package/lib/systelab-virtual-keyboard.component.d.ts.map +1 -0
- package/lib/systelab-virtual-keyboard.config.d.ts +7 -0
- package/lib/systelab-virtual-keyboard.config.d.ts.map +1 -0
- package/lib/systelab-virtual-keyboard.directive.d.ts +42 -0
- package/lib/systelab-virtual-keyboard.directive.d.ts.map +1 -0
- package/lib/systelab-virtual-keyboard.module.d.ts +15 -0
- package/lib/systelab-virtual-keyboard.module.d.ts.map +1 -0
- package/package.json +28 -0
- package/public-api.d.ts +5 -0
- package/public-api.d.ts.map +1 -0
- package/systelab-virtual-keyboard.d.ts.map +1 -0
|
@@ -0,0 +1,739 @@
|
|
|
1
|
+
import * as i0 from '@angular/core';
|
|
2
|
+
import { InjectionToken, EventEmitter, Component, HostListener, Output, Injectable, Directive, Inject, Optional, Input, NgModule } from '@angular/core';
|
|
3
|
+
import { DOCUMENT, CommonModule } from '@angular/common';
|
|
4
|
+
import { ComponentPortal } from '@angular/cdk/portal';
|
|
5
|
+
import SimpleKeyboard from 'simple-keyboard';
|
|
6
|
+
import * as i1 from '@angular/cdk/overlay';
|
|
7
|
+
import { OverlayModule } from '@angular/cdk/overlay';
|
|
8
|
+
|
|
9
|
+
/*
|
|
10
|
+
* Copyright (c) 2020 - 2024 - Instrumentation Laboratory Company and Systelab Technologies, SA. All rights reserved.
|
|
11
|
+
* NOTICE: All information contained herein is and remains the property of Instrumentation Laboratory Company and its
|
|
12
|
+
* affiliates, if any. The intellectual and technical concepts contained herein are proprietary to Instrumentation
|
|
13
|
+
* Laboratory Company and its affiliates and may be covered by U.S. and foreign patents and patent applications, and/or
|
|
14
|
+
* are protected by trade secret or copyright law. Dissemination of this information or reproduction of this material is
|
|
15
|
+
* strictly forbidden unless prior written permission is Instrumentation Laboratory Company.
|
|
16
|
+
*/
|
|
17
|
+
var SystelabVirtualKeyboardButton;
|
|
18
|
+
(function (SystelabVirtualKeyboardButton) {
|
|
19
|
+
SystelabVirtualKeyboardButton["Done"] = "{done}";
|
|
20
|
+
SystelabVirtualKeyboardButton["Enter"] = "{enter}";
|
|
21
|
+
SystelabVirtualKeyboardButton["Shift"] = "{shift}";
|
|
22
|
+
SystelabVirtualKeyboardButton["Lock"] = "{lock}";
|
|
23
|
+
SystelabVirtualKeyboardButton["Backspace"] = "{bksp}";
|
|
24
|
+
SystelabVirtualKeyboardButton["Language"] = "{language}";
|
|
25
|
+
SystelabVirtualKeyboardButton["Space"] = "{space}";
|
|
26
|
+
SystelabVirtualKeyboardButton["Tab"] = "{tab}";
|
|
27
|
+
})(SystelabVirtualKeyboardButton || (SystelabVirtualKeyboardButton = {}));
|
|
28
|
+
var SystelabVirtualKeyboardLayouts;
|
|
29
|
+
(function (SystelabVirtualKeyboardLayouts) {
|
|
30
|
+
SystelabVirtualKeyboardLayouts["default"] = "default";
|
|
31
|
+
SystelabVirtualKeyboardLayouts["shift"] = "shift";
|
|
32
|
+
SystelabVirtualKeyboardLayouts["numeric"] = "numeric";
|
|
33
|
+
})(SystelabVirtualKeyboardLayouts || (SystelabVirtualKeyboardLayouts = {}));
|
|
34
|
+
var SystelabVirtualKeyboardInputTypes;
|
|
35
|
+
(function (SystelabVirtualKeyboardInputTypes) {
|
|
36
|
+
SystelabVirtualKeyboardInputTypes["text"] = "text";
|
|
37
|
+
SystelabVirtualKeyboardInputTypes["number"] = "number";
|
|
38
|
+
SystelabVirtualKeyboardInputTypes["password"] = "password";
|
|
39
|
+
})(SystelabVirtualKeyboardInputTypes || (SystelabVirtualKeyboardInputTypes = {}));
|
|
40
|
+
|
|
41
|
+
const VIRTUAL_KEYBOARD_CONFIG = new InjectionToken('VIRTUAL_KEYBOARD_CONFIG');
|
|
42
|
+
|
|
43
|
+
class SystelabVirtualKeyboardComponent {
|
|
44
|
+
handleKeyUp(event) {
|
|
45
|
+
if (event.isTrusted) {
|
|
46
|
+
this.caretEventHandler(event);
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
handleMouseUp(event) {
|
|
50
|
+
this.caretEventHandler(event);
|
|
51
|
+
}
|
|
52
|
+
handleSelect(event) {
|
|
53
|
+
this.caretEventHandler(event);
|
|
54
|
+
}
|
|
55
|
+
handleSelectionChange(event) {
|
|
56
|
+
this.caretEventHandler(event);
|
|
57
|
+
}
|
|
58
|
+
get maxLength() {
|
|
59
|
+
return this.activeInputElement?.maxLength ?? -1;
|
|
60
|
+
}
|
|
61
|
+
get isTextarea() {
|
|
62
|
+
return this.activeInputElement?.type === 'textarea';
|
|
63
|
+
}
|
|
64
|
+
constructor(elementRef) {
|
|
65
|
+
this.elementRef = elementRef;
|
|
66
|
+
this.debug = false;
|
|
67
|
+
this.selectedLayout = SystelabVirtualKeyboardLayouts.default;
|
|
68
|
+
this.caretPosition = null;
|
|
69
|
+
this.caretPositionEnd = null;
|
|
70
|
+
this.closePanel = new EventEmitter();
|
|
71
|
+
}
|
|
72
|
+
ngAfterViewInit() {
|
|
73
|
+
const layout = {
|
|
74
|
+
[SystelabVirtualKeyboardLayouts.default]: [
|
|
75
|
+
'` 1 2 3 4 5 6 7 8 9 0 - = {bksp}',
|
|
76
|
+
'{tab} q w e r t y u i o p [ ] \\',
|
|
77
|
+
"{lock} a s d f g h j k l ; ' {enter}",
|
|
78
|
+
'{shift} z x c v b n m , . / {shift}',
|
|
79
|
+
'{space}',
|
|
80
|
+
],
|
|
81
|
+
[SystelabVirtualKeyboardLayouts.shift]: [
|
|
82
|
+
'~ ! @ # $ % ^ & * ( ) _ + {bksp}',
|
|
83
|
+
'{tab} Q W E R T Y U I O P { } |',
|
|
84
|
+
'{lock} A S D F G H J K L : " {enter}',
|
|
85
|
+
'{shift} Z X C V B N M < > ? {shift}',
|
|
86
|
+
'{space}',
|
|
87
|
+
],
|
|
88
|
+
[SystelabVirtualKeyboardLayouts.numeric]: ['7 8 9', '4 5 6', '1 2 3', '0 {bksp}'],
|
|
89
|
+
};
|
|
90
|
+
this.keyboard = new SimpleKeyboard('.simple-keyboard', {
|
|
91
|
+
onKeyPress: (button) => this.handleKeyPress(button),
|
|
92
|
+
mergeDisplay: true,
|
|
93
|
+
display: {
|
|
94
|
+
[SystelabVirtualKeyboardButton.Backspace]: 'delete',
|
|
95
|
+
},
|
|
96
|
+
buttonTheme: [
|
|
97
|
+
{
|
|
98
|
+
class: 'virtual-keyboard-delete-button',
|
|
99
|
+
buttons: `${SystelabVirtualKeyboardButton.Backspace}`,
|
|
100
|
+
},
|
|
101
|
+
],
|
|
102
|
+
layout,
|
|
103
|
+
});
|
|
104
|
+
this.setLayout(this.selectedLayout);
|
|
105
|
+
if (this.debug) {
|
|
106
|
+
console.log('Layout: ', layout);
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
setActiveInput(input) {
|
|
110
|
+
this.activeInputElement = input;
|
|
111
|
+
if (this.debug) {
|
|
112
|
+
const inputType = this.activeInputElement?.type;
|
|
113
|
+
console.log('Layout:', `${inputType}_${this.selectedLayout}`);
|
|
114
|
+
}
|
|
115
|
+
let selectionStart;
|
|
116
|
+
let selectionEnd;
|
|
117
|
+
if (this.isInputNumeric(input)) {
|
|
118
|
+
selectionStart = this.activeInputElement.value.toString().length;
|
|
119
|
+
selectionEnd = this.activeInputElement.value.toString().length;
|
|
120
|
+
}
|
|
121
|
+
else {
|
|
122
|
+
selectionStart = this.activeInputElement.selectionStart;
|
|
123
|
+
selectionEnd = this.activeInputElement.selectionEnd;
|
|
124
|
+
}
|
|
125
|
+
this.setCaretPosition(selectionStart, selectionEnd);
|
|
126
|
+
if (this.debug) {
|
|
127
|
+
console.log('Caret start at:', this.caretPosition, this.caretPositionEnd);
|
|
128
|
+
}
|
|
129
|
+
this.focusActiveInput();
|
|
130
|
+
}
|
|
131
|
+
setLayout(layout) {
|
|
132
|
+
this.selectedLayout = layout;
|
|
133
|
+
if (this.keyboard) {
|
|
134
|
+
this.keyboard.setOptions({
|
|
135
|
+
layoutName: layout,
|
|
136
|
+
});
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
isInputAlphabetic(activeInputElement) {
|
|
140
|
+
const inputType = activeInputElement?.type;
|
|
141
|
+
return inputType && [SystelabVirtualKeyboardInputTypes.text, SystelabVirtualKeyboardInputTypes.password].some((i) => i === inputType);
|
|
142
|
+
}
|
|
143
|
+
isInputNumeric(activeInputElement) {
|
|
144
|
+
const inputType = activeInputElement?.type;
|
|
145
|
+
return inputType && [SystelabVirtualKeyboardInputTypes.number].some((i) => i === inputType);
|
|
146
|
+
}
|
|
147
|
+
handleKeyPress(button, e) {
|
|
148
|
+
if (this.debug) {
|
|
149
|
+
console.log('Key press:', button);
|
|
150
|
+
}
|
|
151
|
+
if (button === SystelabVirtualKeyboardButton.Shift || button === SystelabVirtualKeyboardButton.Lock) {
|
|
152
|
+
this.toggleShift();
|
|
153
|
+
}
|
|
154
|
+
else if (button === SystelabVirtualKeyboardButton.Done) {
|
|
155
|
+
this.closePanel.emit();
|
|
156
|
+
return;
|
|
157
|
+
}
|
|
158
|
+
if (!this.isAcceptedNonStandardButton(button) && !this.isStandardButton(button)) {
|
|
159
|
+
return;
|
|
160
|
+
}
|
|
161
|
+
const output = this.handleButtonOutput(button);
|
|
162
|
+
if (this.activeInputElement) {
|
|
163
|
+
this.activeInputElement.value = output;
|
|
164
|
+
if (this.debug) {
|
|
165
|
+
console.log('Caret at:', this.caretPosition, this.caretPositionEnd, 'Button', e);
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
this.dispatchEvents(button);
|
|
169
|
+
}
|
|
170
|
+
handleButtonOutput(button) {
|
|
171
|
+
const commonParams = this.getCommonParams();
|
|
172
|
+
let output = this.activeInputElement?.value || '';
|
|
173
|
+
if (!this.isStandardButton(button)) {
|
|
174
|
+
if (button === SystelabVirtualKeyboardButton.Backspace) {
|
|
175
|
+
output = this.removeAt(output, ...commonParams);
|
|
176
|
+
}
|
|
177
|
+
else if (button === SystelabVirtualKeyboardButton.Space) {
|
|
178
|
+
output = this.addStringAt(output, ' ', ...commonParams);
|
|
179
|
+
}
|
|
180
|
+
else if (button === SystelabVirtualKeyboardButton.Tab) {
|
|
181
|
+
output = this.addStringAt(output, '\t', ...commonParams);
|
|
182
|
+
}
|
|
183
|
+
else if (button === SystelabVirtualKeyboardButton.Enter) {
|
|
184
|
+
if (this.isTextarea) {
|
|
185
|
+
output = this.addStringAt(output, '\n', ...commonParams);
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
else {
|
|
189
|
+
return;
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
else {
|
|
193
|
+
output = this.addStringAt(output, button, ...commonParams);
|
|
194
|
+
}
|
|
195
|
+
return output;
|
|
196
|
+
}
|
|
197
|
+
getCommonParams() {
|
|
198
|
+
return [this.caretPosition || 0, this.caretPositionEnd || 0, true];
|
|
199
|
+
}
|
|
200
|
+
isAcceptedNonStandardButton(button) {
|
|
201
|
+
return [
|
|
202
|
+
SystelabVirtualKeyboardButton.Backspace.toString(),
|
|
203
|
+
SystelabVirtualKeyboardButton.Space.toString(),
|
|
204
|
+
SystelabVirtualKeyboardButton.Tab.toString(),
|
|
205
|
+
SystelabVirtualKeyboardButton.Enter.toString(),
|
|
206
|
+
].includes(button);
|
|
207
|
+
}
|
|
208
|
+
dispatchEvents(button) {
|
|
209
|
+
const { key, code } = this.convertFromButtonToCode(button);
|
|
210
|
+
const eventInit = {
|
|
211
|
+
bubbles: true,
|
|
212
|
+
cancelable: true,
|
|
213
|
+
shiftKey: this.selectedLayout === SystelabVirtualKeyboardLayouts.shift,
|
|
214
|
+
key: key,
|
|
215
|
+
code: code,
|
|
216
|
+
location: 0,
|
|
217
|
+
};
|
|
218
|
+
// Simulate all needed events on base element
|
|
219
|
+
this.activeInputElement?.dispatchEvent(new KeyboardEvent('keydown', eventInit));
|
|
220
|
+
this.activeInputElement?.dispatchEvent(new KeyboardEvent('keypress', eventInit));
|
|
221
|
+
this.activeInputElement?.dispatchEvent(new Event('input', { bubbles: true }));
|
|
222
|
+
this.activeInputElement?.dispatchEvent(new KeyboardEvent('keyup', eventInit));
|
|
223
|
+
// And set focus to input
|
|
224
|
+
this.focusActiveInput();
|
|
225
|
+
}
|
|
226
|
+
/*
|
|
227
|
+
* AUXILIARY METHODS
|
|
228
|
+
* */
|
|
229
|
+
convertFromButtonToCode(button) {
|
|
230
|
+
let key;
|
|
231
|
+
let code;
|
|
232
|
+
if (button.includes('{') && button.includes('}')) {
|
|
233
|
+
// Capitalize name
|
|
234
|
+
key = button.slice(1, button.length - 1).toLowerCase();
|
|
235
|
+
key = key.charAt(0).toUpperCase() + key.slice(1);
|
|
236
|
+
code = key;
|
|
237
|
+
// Fix to standard key code
|
|
238
|
+
if (code.toLowerCase() === SystelabVirtualKeyboardButton.Backspace.slice(1, SystelabVirtualKeyboardButton.Backspace.length - 1).toLowerCase()) {
|
|
239
|
+
code = 'Backspace';
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
else {
|
|
243
|
+
key = button;
|
|
244
|
+
code = Number.isInteger(Number(button)) ? `Digit${button}` : `Key${button.toUpperCase()}`;
|
|
245
|
+
}
|
|
246
|
+
return { key, code };
|
|
247
|
+
}
|
|
248
|
+
focusActiveInput() {
|
|
249
|
+
this.activeInputElement?.focus();
|
|
250
|
+
if (!this.isInputNumeric(this.activeInputElement)) {
|
|
251
|
+
this.activeInputElement?.setSelectionRange(this.caretPosition, this.caretPositionEnd);
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
toggleShift() {
|
|
255
|
+
let currentLayout = this.keyboard.options.layoutName;
|
|
256
|
+
let selectedLayout = currentLayout === SystelabVirtualKeyboardLayouts.default ? SystelabVirtualKeyboardLayouts.shift : SystelabVirtualKeyboardLayouts.default;
|
|
257
|
+
this.setLayout(selectedLayout);
|
|
258
|
+
}
|
|
259
|
+
isStandardButton(button) {
|
|
260
|
+
return button && !(button[0] === '{' && button[button.length - 1] === '}');
|
|
261
|
+
}
|
|
262
|
+
/*
|
|
263
|
+
* OUTPUT STRING METHODS
|
|
264
|
+
* */
|
|
265
|
+
removeAt(source, position = source.length, positionEnd = source.length, moveCaret = false) {
|
|
266
|
+
if (position === 0 && positionEnd === 0) {
|
|
267
|
+
return source;
|
|
268
|
+
}
|
|
269
|
+
let output;
|
|
270
|
+
if (position === positionEnd) {
|
|
271
|
+
if (position && position >= 0) {
|
|
272
|
+
output = source.slice(0, position - 1) + source.slice(position);
|
|
273
|
+
if (moveCaret) {
|
|
274
|
+
this.updateCaretPosition(1, true);
|
|
275
|
+
}
|
|
276
|
+
}
|
|
277
|
+
else {
|
|
278
|
+
output = source.slice(0, -1);
|
|
279
|
+
if (moveCaret) {
|
|
280
|
+
this.updateCaretPosition(1, true);
|
|
281
|
+
}
|
|
282
|
+
}
|
|
283
|
+
}
|
|
284
|
+
else {
|
|
285
|
+
output = source.slice(0, position) + source.slice(positionEnd);
|
|
286
|
+
if (moveCaret) {
|
|
287
|
+
this.setCaretPosition(position);
|
|
288
|
+
}
|
|
289
|
+
}
|
|
290
|
+
return output;
|
|
291
|
+
}
|
|
292
|
+
addStringAt(source, str, position = source.length, positionEnd = source.length, moveCaret = false) {
|
|
293
|
+
if (this.maxLength !== -1 && source.length >= this.maxLength) {
|
|
294
|
+
return source;
|
|
295
|
+
}
|
|
296
|
+
let output;
|
|
297
|
+
if (!position && position !== 0) {
|
|
298
|
+
output = source + str;
|
|
299
|
+
}
|
|
300
|
+
else {
|
|
301
|
+
output = [source.slice(0, position), str, source.slice(positionEnd)].join('');
|
|
302
|
+
if (moveCaret) {
|
|
303
|
+
this.updateCaretPosition(str.length, false);
|
|
304
|
+
}
|
|
305
|
+
}
|
|
306
|
+
return output;
|
|
307
|
+
}
|
|
308
|
+
/*
|
|
309
|
+
* CARET METHODS
|
|
310
|
+
* */
|
|
311
|
+
caretEventHandler(event) {
|
|
312
|
+
let targetTagName = '';
|
|
313
|
+
if (event.target.tagName) {
|
|
314
|
+
targetTagName = event.target.tagName.toLowerCase();
|
|
315
|
+
}
|
|
316
|
+
const isTextInput = targetTagName === 'textarea' ||
|
|
317
|
+
(targetTagName === 'input' && ['text', 'search', 'email', 'password', 'url', 'tel'].includes(event.target.type));
|
|
318
|
+
const isKeyboard = event.target === this.elementRef.nativeElement || (event.target && this.elementRef.nativeElement.contains(event.target));
|
|
319
|
+
if (isTextInput && this.activeInputElement == event.target) {
|
|
320
|
+
/**
|
|
321
|
+
* Tracks current cursor position
|
|
322
|
+
* As keys are pressed, text will be added/removed at that position within the input.
|
|
323
|
+
*/
|
|
324
|
+
this.setCaretPosition(event.target.selectionStart, event.target.selectionEnd);
|
|
325
|
+
if (this.debug) {
|
|
326
|
+
console.log('Caret at:', this.caretPosition, this.caretPositionEnd, event && event.target.tagName.toLowerCase(), event);
|
|
327
|
+
}
|
|
328
|
+
}
|
|
329
|
+
else if (event.type === 'pointerup' && this.activeInputElement === document.activeElement) {
|
|
330
|
+
return;
|
|
331
|
+
}
|
|
332
|
+
else if (!isKeyboard && event?.type !== 'selectionchange') {
|
|
333
|
+
/**
|
|
334
|
+
* we must ensure caretPosition doesn't persist once reactivated.
|
|
335
|
+
*/
|
|
336
|
+
this.setCaretPosition(null);
|
|
337
|
+
if (this.debug) {
|
|
338
|
+
console.log(`Caret position reset due to "${event?.type}" event`, event);
|
|
339
|
+
}
|
|
340
|
+
}
|
|
341
|
+
}
|
|
342
|
+
updateCaretPosition(length, minus = false) {
|
|
343
|
+
const newCaretPos = this.computeNewCaretPosition(length, minus);
|
|
344
|
+
this.setCaretPosition(newCaretPos);
|
|
345
|
+
// Scroll to bottom
|
|
346
|
+
setTimeout(() => {
|
|
347
|
+
this.activeInputElement?.scrollTo({
|
|
348
|
+
top: this.activeInputElement.scrollHeight,
|
|
349
|
+
});
|
|
350
|
+
});
|
|
351
|
+
}
|
|
352
|
+
computeNewCaretPosition(length, minus = false) {
|
|
353
|
+
let caretPosition = this.caretPosition;
|
|
354
|
+
if (caretPosition != null) {
|
|
355
|
+
if (minus) {
|
|
356
|
+
if (caretPosition > 0)
|
|
357
|
+
caretPosition = caretPosition - length;
|
|
358
|
+
}
|
|
359
|
+
else {
|
|
360
|
+
caretPosition = caretPosition + length;
|
|
361
|
+
}
|
|
362
|
+
}
|
|
363
|
+
return caretPosition;
|
|
364
|
+
}
|
|
365
|
+
setCaretPosition(position, endPosition = position) {
|
|
366
|
+
this.caretPosition = position;
|
|
367
|
+
this.caretPositionEnd = endPosition;
|
|
368
|
+
}
|
|
369
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.0.9", ngImport: i0, type: SystelabVirtualKeyboardComponent, deps: [{ token: i0.ElementRef }], target: i0.ɵɵFactoryTarget.Component }); }
|
|
370
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "17.0.9", type: SystelabVirtualKeyboardComponent, isStandalone: true, selector: "systelab-virtual-keyboard.component", outputs: { closePanel: "closePanel" }, host: { listeners: { "window:keyup": "handleKeyUp($event)", "window:pointerup": "handleMouseUp($event)", "window:select": "handleSelect($event)", "window:selectionchange": "handleSelectionChange($event)" } }, ngImport: i0, template: "<!--\n ~ Copyright (c) 2020 - 2024 - Instrumentation Laboratory Company and Systelab Technologies, SA. All rights reserved.\n ~ NOTICE: All information contained herein is and remains the property of Instrumentation Laboratory Company and its\n ~ affiliates, if any. The intellectual and technical concepts contained herein are proprietary to Instrumentation\n ~ Laboratory Company and its affiliates and may be covered by U.S. and foreign patents and patent applications, and/or\n ~ are protected by trade secret or copyright law. Dissemination of this information or reproduction of this material is\n ~ strictly forbidden unless prior written permission is Instrumentation Laboratory Company.\n -->\n\n<div class=\"simple-keyboard\"></div>\n", styles: [":host{width:100%}\n"] }); }
|
|
371
|
+
}
|
|
372
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.0.9", ngImport: i0, type: SystelabVirtualKeyboardComponent, decorators: [{
|
|
373
|
+
type: Component,
|
|
374
|
+
args: [{ selector: 'systelab-virtual-keyboard.component', standalone: true, imports: [], template: "<!--\n ~ Copyright (c) 2020 - 2024 - Instrumentation Laboratory Company and Systelab Technologies, SA. All rights reserved.\n ~ NOTICE: All information contained herein is and remains the property of Instrumentation Laboratory Company and its\n ~ affiliates, if any. The intellectual and technical concepts contained herein are proprietary to Instrumentation\n ~ Laboratory Company and its affiliates and may be covered by U.S. and foreign patents and patent applications, and/or\n ~ are protected by trade secret or copyright law. Dissemination of this information or reproduction of this material is\n ~ strictly forbidden unless prior written permission is Instrumentation Laboratory Company.\n -->\n\n<div class=\"simple-keyboard\"></div>\n", styles: [":host{width:100%}\n"] }]
|
|
375
|
+
}], ctorParameters: () => [{ type: i0.ElementRef }], propDecorators: { handleKeyUp: [{
|
|
376
|
+
type: HostListener,
|
|
377
|
+
args: ['window:keyup', ['$event']]
|
|
378
|
+
}], handleMouseUp: [{
|
|
379
|
+
type: HostListener,
|
|
380
|
+
args: ['window:pointerup', ['$event']]
|
|
381
|
+
}], handleSelect: [{
|
|
382
|
+
type: HostListener,
|
|
383
|
+
args: ['window:select', ['$event']]
|
|
384
|
+
}], handleSelectionChange: [{
|
|
385
|
+
type: HostListener,
|
|
386
|
+
args: ['window:selectionchange', ['$event']]
|
|
387
|
+
}], closePanel: [{
|
|
388
|
+
type: Output
|
|
389
|
+
}] } });
|
|
390
|
+
|
|
391
|
+
class SystelabVirtualKeyboardOverlayService {
|
|
392
|
+
constructor(overlay) {
|
|
393
|
+
this.overlay = overlay;
|
|
394
|
+
}
|
|
395
|
+
isCreated() {
|
|
396
|
+
return !!this.overlayRef;
|
|
397
|
+
}
|
|
398
|
+
isOpen() {
|
|
399
|
+
return this.open;
|
|
400
|
+
}
|
|
401
|
+
create(inputOrigin, fixedBottom, layout = SystelabVirtualKeyboardLayouts.default) {
|
|
402
|
+
this.layout = layout;
|
|
403
|
+
this.overlayRef = this.overlay.create({
|
|
404
|
+
hasBackdrop: false,
|
|
405
|
+
scrollStrategy: this.overlay.scrollStrategies.reposition(),
|
|
406
|
+
disposeOnNavigation: true,
|
|
407
|
+
});
|
|
408
|
+
this.overlayRef.addPanelClass('virtual-keyboard-overlay-pane');
|
|
409
|
+
if (fixedBottom) {
|
|
410
|
+
this.overlayRef.addPanelClass('virtual-keyboard-fixed-bottom');
|
|
411
|
+
}
|
|
412
|
+
this.updatePositionStrategy(inputOrigin, fixedBottom);
|
|
413
|
+
this.updateSize();
|
|
414
|
+
this.open = true;
|
|
415
|
+
return this.overlayRef.attach(new ComponentPortal(SystelabVirtualKeyboardComponent));
|
|
416
|
+
}
|
|
417
|
+
destroy() {
|
|
418
|
+
if (this.overlayRef) {
|
|
419
|
+
this.overlayRef.dispose();
|
|
420
|
+
}
|
|
421
|
+
this.overlayRef = null;
|
|
422
|
+
this.open = false;
|
|
423
|
+
}
|
|
424
|
+
hasAttached() {
|
|
425
|
+
return this.overlayRef?.hasAttached();
|
|
426
|
+
}
|
|
427
|
+
updatePositionStrategy(inputOrigin, fixedBottom) {
|
|
428
|
+
this.overlayRef.updatePositionStrategy(this.getPositionStrategy(inputOrigin, fixedBottom));
|
|
429
|
+
}
|
|
430
|
+
updateSize() {
|
|
431
|
+
this.overlayRef.updateSize(this.getOverlaySize());
|
|
432
|
+
}
|
|
433
|
+
getPositionStrategy(inputOrigin, fixedBottom) {
|
|
434
|
+
if (fixedBottom) {
|
|
435
|
+
return this.overlay.position().global().centerHorizontally().bottom('0');
|
|
436
|
+
}
|
|
437
|
+
const pointWithDimensions = this.computePositionStrategyOrigin(inputOrigin);
|
|
438
|
+
return this.overlay
|
|
439
|
+
.position()
|
|
440
|
+
.flexibleConnectedTo(pointWithDimensions)
|
|
441
|
+
.withFlexibleDimensions(false)
|
|
442
|
+
.withLockedPosition(true)
|
|
443
|
+
.withPush(false)
|
|
444
|
+
.withPositions([
|
|
445
|
+
{
|
|
446
|
+
originX: 'start',
|
|
447
|
+
originY: 'bottom',
|
|
448
|
+
overlayX: 'start',
|
|
449
|
+
overlayY: 'top',
|
|
450
|
+
},
|
|
451
|
+
{
|
|
452
|
+
originX: 'start',
|
|
453
|
+
originY: 'top',
|
|
454
|
+
overlayX: 'start',
|
|
455
|
+
overlayY: 'bottom',
|
|
456
|
+
},
|
|
457
|
+
{
|
|
458
|
+
originX: 'end',
|
|
459
|
+
originY: 'bottom',
|
|
460
|
+
overlayX: 'end',
|
|
461
|
+
overlayY: 'top',
|
|
462
|
+
},
|
|
463
|
+
{
|
|
464
|
+
originX: 'end',
|
|
465
|
+
originY: 'top',
|
|
466
|
+
overlayX: 'end',
|
|
467
|
+
overlayY: 'bottom',
|
|
468
|
+
},
|
|
469
|
+
]);
|
|
470
|
+
}
|
|
471
|
+
getOverlaySize() {
|
|
472
|
+
const overlayWidth = this.layout === SystelabVirtualKeyboardLayouts.numeric ? '400px' : '1200px';
|
|
473
|
+
return {
|
|
474
|
+
width: overlayWidth,
|
|
475
|
+
maxWidth: overlayWidth,
|
|
476
|
+
minWidth: overlayWidth,
|
|
477
|
+
};
|
|
478
|
+
}
|
|
479
|
+
computePositionStrategyOrigin(inputOrigin) {
|
|
480
|
+
const overlayOffsetX = this.computeOverlayOffsetX(inputOrigin);
|
|
481
|
+
const { width: overlayWidthString } = this.getOverlaySize();
|
|
482
|
+
const overlayWidth = Number(overlayWidthString.replace('px', ''));
|
|
483
|
+
const { x, y, width, height } = inputOrigin.getBoundingClientRect();
|
|
484
|
+
return {
|
|
485
|
+
width,
|
|
486
|
+
height,
|
|
487
|
+
x: width < overlayWidth ? x - overlayOffsetX : x + overlayOffsetX,
|
|
488
|
+
y,
|
|
489
|
+
};
|
|
490
|
+
}
|
|
491
|
+
computeOverlayOffsetX(inputOrigin) {
|
|
492
|
+
const { width: overlayWidthString } = this.getOverlaySize();
|
|
493
|
+
const overlayWidth = Number(overlayWidthString.replace('px', ''));
|
|
494
|
+
const inputWidth = inputOrigin.getBoundingClientRect().width;
|
|
495
|
+
const extraWidth = overlayWidth - inputWidth;
|
|
496
|
+
return Math.abs(extraWidth) / 2;
|
|
497
|
+
}
|
|
498
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.0.9", ngImport: i0, type: SystelabVirtualKeyboardOverlayService, deps: [{ token: i1.Overlay }], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
499
|
+
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "17.0.9", ngImport: i0, type: SystelabVirtualKeyboardOverlayService, providedIn: 'root' }); }
|
|
500
|
+
}
|
|
501
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.0.9", ngImport: i0, type: SystelabVirtualKeyboardOverlayService, decorators: [{
|
|
502
|
+
type: Injectable,
|
|
503
|
+
args: [{
|
|
504
|
+
providedIn: 'root',
|
|
505
|
+
}]
|
|
506
|
+
}], ctorParameters: () => [{ type: i1.Overlay }] });
|
|
507
|
+
|
|
508
|
+
/*
|
|
509
|
+
* Copyright (c) 2020 - 2024 - Instrumentation Laboratory Company and Systelab Technologies, SA. All rights reserved.
|
|
510
|
+
* NOTICE: All information contained herein is and remains the property of Instrumentation Laboratory Company and its
|
|
511
|
+
* affiliates, if any. The intellectual and technical concepts contained herein are proprietary to Instrumentation
|
|
512
|
+
* Laboratory Company and its affiliates and may be covered by U.S. and foreign patents and patent applications, and/or
|
|
513
|
+
* are protected by trade secret or copyright law. Dissemination of this information or reproduction of this material is
|
|
514
|
+
* strictly forbidden unless prior written permission is Instrumentation Laboratory Company.
|
|
515
|
+
*/
|
|
516
|
+
class SystelabVirtualKeyboardDirective {
|
|
517
|
+
onDocumentClick(event) {
|
|
518
|
+
const simpleKeyboardElement = document.querySelector('.simple-keyboard');
|
|
519
|
+
const showKeyboardButtonClicked = event.target?.classList.contains('virtual-keyboard-show-button');
|
|
520
|
+
if (!simpleKeyboardElement?.contains(event.target) &&
|
|
521
|
+
!this.elementRef?.nativeElement?.contains(event.target) &&
|
|
522
|
+
!this.showKeyboardButtonElement?.contains(event.target) &&
|
|
523
|
+
!showKeyboardButtonClicked) {
|
|
524
|
+
if (this.overlayService.isCreated()) {
|
|
525
|
+
this.overlayService.destroy();
|
|
526
|
+
}
|
|
527
|
+
}
|
|
528
|
+
}
|
|
529
|
+
onDocumentScroll() {
|
|
530
|
+
if (this.overlayService.isCreated()) {
|
|
531
|
+
// update position and size on scroll
|
|
532
|
+
}
|
|
533
|
+
}
|
|
534
|
+
set vkEnabled(enabled) {
|
|
535
|
+
if (typeof enabled === 'string') {
|
|
536
|
+
this.enabled = true;
|
|
537
|
+
}
|
|
538
|
+
else {
|
|
539
|
+
this.enabled = enabled;
|
|
540
|
+
}
|
|
541
|
+
}
|
|
542
|
+
;
|
|
543
|
+
get vkEnabled() {
|
|
544
|
+
return this.enabled;
|
|
545
|
+
}
|
|
546
|
+
get vkFixedBottom() {
|
|
547
|
+
return this.fixedBottom;
|
|
548
|
+
}
|
|
549
|
+
set vkFixedBottom(fixedBottom) {
|
|
550
|
+
if (typeof fixedBottom === 'string') {
|
|
551
|
+
this.fixedBottom = true;
|
|
552
|
+
}
|
|
553
|
+
else {
|
|
554
|
+
this.fixedBottom = fixedBottom;
|
|
555
|
+
}
|
|
556
|
+
}
|
|
557
|
+
get vkDebug() {
|
|
558
|
+
return this.debug;
|
|
559
|
+
}
|
|
560
|
+
set vkDebug(debug) {
|
|
561
|
+
this.debug = debug;
|
|
562
|
+
}
|
|
563
|
+
get vkConfig() {
|
|
564
|
+
return this.config;
|
|
565
|
+
}
|
|
566
|
+
set vkConfig(config) {
|
|
567
|
+
this.config = config;
|
|
568
|
+
}
|
|
569
|
+
constructor(elementRef, overlayService, renderer, document, virtualKeyboardConfig) {
|
|
570
|
+
this.elementRef = elementRef;
|
|
571
|
+
this.overlayService = overlayService;
|
|
572
|
+
this.renderer = renderer;
|
|
573
|
+
this.document = document;
|
|
574
|
+
this.virtualKeyboardConfig = virtualKeyboardConfig;
|
|
575
|
+
this.enabled = false;
|
|
576
|
+
this.fixedBottom = false;
|
|
577
|
+
this.debug = false;
|
|
578
|
+
this.config = this.virtualKeyboardConfig;
|
|
579
|
+
}
|
|
580
|
+
ngOnInit() {
|
|
581
|
+
this.attachKeyboardIcon();
|
|
582
|
+
}
|
|
583
|
+
ngAfterViewInit() {
|
|
584
|
+
if (this.vkEnabled) {
|
|
585
|
+
const keyboardIcon = this.elementRef.nativeElement.parentElement.querySelector('i');
|
|
586
|
+
keyboardIcon.addEventListener('click', this.togglePanel.bind(this));
|
|
587
|
+
}
|
|
588
|
+
}
|
|
589
|
+
ngOnDestroy() {
|
|
590
|
+
if (this.overlayService.isCreated()) {
|
|
591
|
+
this.overlayService.destroy();
|
|
592
|
+
}
|
|
593
|
+
}
|
|
594
|
+
togglePanel() {
|
|
595
|
+
if (this.overlayService.isOpen()) {
|
|
596
|
+
this.closePanel();
|
|
597
|
+
}
|
|
598
|
+
else {
|
|
599
|
+
this.openPanel();
|
|
600
|
+
}
|
|
601
|
+
}
|
|
602
|
+
openPanel() {
|
|
603
|
+
if (this.overlayService.isCreated()) {
|
|
604
|
+
this.overlayService.destroy();
|
|
605
|
+
}
|
|
606
|
+
if (this.overlayService.hasAttached()) {
|
|
607
|
+
return;
|
|
608
|
+
}
|
|
609
|
+
const currentLayout = this.getLayout(this.elementRef.nativeElement);
|
|
610
|
+
this.panelRef = this.overlayService.create(this.inputOrigin(), this.vkFixedBottom, currentLayout);
|
|
611
|
+
this.panelRef.instance.debug = this.vkDebug;
|
|
612
|
+
this.panelRef.instance.setActiveInput(this.elementRef.nativeElement);
|
|
613
|
+
this.panelRef.instance.setLayout(currentLayout);
|
|
614
|
+
this.panelRef.instance.closePanel.subscribe(() => this.closePanel());
|
|
615
|
+
}
|
|
616
|
+
getLayout(activeInputElement) {
|
|
617
|
+
if (this.config?.hasOwnProperty('layout')) {
|
|
618
|
+
return this.config.layout;
|
|
619
|
+
}
|
|
620
|
+
if (this.isInputAlphabetic(activeInputElement)) {
|
|
621
|
+
return SystelabVirtualKeyboardLayouts.default;
|
|
622
|
+
}
|
|
623
|
+
else if (this.isInputNumeric(activeInputElement)) {
|
|
624
|
+
return SystelabVirtualKeyboardLayouts.numeric;
|
|
625
|
+
}
|
|
626
|
+
else {
|
|
627
|
+
return SystelabVirtualKeyboardLayouts.default;
|
|
628
|
+
}
|
|
629
|
+
}
|
|
630
|
+
isInputAlphabetic(activeInputElement) {
|
|
631
|
+
const inputType = activeInputElement?.type;
|
|
632
|
+
return inputType && [SystelabVirtualKeyboardInputTypes.text, SystelabVirtualKeyboardInputTypes.password].some((i) => i === inputType);
|
|
633
|
+
}
|
|
634
|
+
isInputNumeric(activeInputElement) {
|
|
635
|
+
const inputType = activeInputElement?.type;
|
|
636
|
+
return inputType && [SystelabVirtualKeyboardInputTypes.number].some((i) => i === inputType);
|
|
637
|
+
}
|
|
638
|
+
closePanel() {
|
|
639
|
+
this.overlayService.destroy();
|
|
640
|
+
}
|
|
641
|
+
inputOrigin() {
|
|
642
|
+
return this.elementRef.nativeElement;
|
|
643
|
+
}
|
|
644
|
+
attachKeyboardIcon() {
|
|
645
|
+
if (this.vkEnabled) {
|
|
646
|
+
const child = this.document.createElement('i');
|
|
647
|
+
child.classList.add('fa');
|
|
648
|
+
child.classList.add('fa-keyboard');
|
|
649
|
+
child.classList.add('virtual-keyboard-show-button');
|
|
650
|
+
this.renderer.appendChild(this.elementRef.nativeElement.parentElement, child);
|
|
651
|
+
this.showKeyboardButtonElement = child;
|
|
652
|
+
}
|
|
653
|
+
}
|
|
654
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.0.9", ngImport: i0, type: SystelabVirtualKeyboardDirective, deps: [{ token: i0.ElementRef }, { token: SystelabVirtualKeyboardOverlayService }, { token: i0.Renderer2 }, { token: DOCUMENT }, { token: VIRTUAL_KEYBOARD_CONFIG, optional: true }], target: i0.ɵɵFactoryTarget.Directive }); }
|
|
655
|
+
static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "17.0.9", type: SystelabVirtualKeyboardDirective, selector: "input[vkEnabled], textarea[vkEnabled]", inputs: { vkEnabled: "vkEnabled", vkFixedBottom: "vkFixedBottom", vkDebug: "vkDebug", vkConfig: "vkConfig" }, host: { listeners: { "document:click": "onDocumentClick($event)", "window:touchmove": "onDocumentScroll($event)", "window:touchend": "onDocumentScroll($event)", "window:wheel": "onDocumentScroll($event)" } }, ngImport: i0 }); }
|
|
656
|
+
}
|
|
657
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.0.9", ngImport: i0, type: SystelabVirtualKeyboardDirective, decorators: [{
|
|
658
|
+
type: Directive,
|
|
659
|
+
args: [{
|
|
660
|
+
selector: 'input[vkEnabled], textarea[vkEnabled]',
|
|
661
|
+
}]
|
|
662
|
+
}], ctorParameters: () => [{ type: i0.ElementRef }, { type: SystelabVirtualKeyboardOverlayService }, { type: i0.Renderer2 }, { type: undefined, decorators: [{
|
|
663
|
+
type: Inject,
|
|
664
|
+
args: [DOCUMENT]
|
|
665
|
+
}] }, { type: undefined, decorators: [{
|
|
666
|
+
type: Optional
|
|
667
|
+
}, {
|
|
668
|
+
type: Inject,
|
|
669
|
+
args: [VIRTUAL_KEYBOARD_CONFIG]
|
|
670
|
+
}] }], propDecorators: { onDocumentClick: [{
|
|
671
|
+
type: HostListener,
|
|
672
|
+
args: ['document:click', ['$event']]
|
|
673
|
+
}], onDocumentScroll: [{
|
|
674
|
+
type: HostListener,
|
|
675
|
+
args: ['window:touchmove', ['$event']]
|
|
676
|
+
}, {
|
|
677
|
+
type: HostListener,
|
|
678
|
+
args: ['window:touchend', ['$event']]
|
|
679
|
+
}, {
|
|
680
|
+
type: HostListener,
|
|
681
|
+
args: ['window:wheel', ['$event']]
|
|
682
|
+
}], vkEnabled: [{
|
|
683
|
+
type: Input
|
|
684
|
+
}], vkFixedBottom: [{
|
|
685
|
+
type: Input
|
|
686
|
+
}], vkDebug: [{
|
|
687
|
+
type: Input
|
|
688
|
+
}], vkConfig: [{
|
|
689
|
+
type: Input
|
|
690
|
+
}] } });
|
|
691
|
+
|
|
692
|
+
const factory = () => {
|
|
693
|
+
const systelabVirtualKeyboardModuleCreated = factory._systelabVirtualKeyboardModuleCreated || false;
|
|
694
|
+
if (systelabVirtualKeyboardModuleCreated) {
|
|
695
|
+
throw new Error('SystelabVirtualKeyboardModuleCreated.forRoot imported to many times');
|
|
696
|
+
}
|
|
697
|
+
factory._systelabVirtualKeyboardModuleCreated = true;
|
|
698
|
+
};
|
|
699
|
+
class SystelabVirtualKeyboardModule {
|
|
700
|
+
static forRoot(conf) {
|
|
701
|
+
return {
|
|
702
|
+
ngModule: SystelabVirtualKeyboardModule,
|
|
703
|
+
providers: [
|
|
704
|
+
SystelabVirtualKeyboardOverlayService,
|
|
705
|
+
{
|
|
706
|
+
provide: VIRTUAL_KEYBOARD_CONFIG, useValue: conf
|
|
707
|
+
}
|
|
708
|
+
]
|
|
709
|
+
};
|
|
710
|
+
}
|
|
711
|
+
static forChild() {
|
|
712
|
+
return {
|
|
713
|
+
ngModule: SystelabVirtualKeyboardModule,
|
|
714
|
+
providers: [],
|
|
715
|
+
};
|
|
716
|
+
}
|
|
717
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.0.9", ngImport: i0, type: SystelabVirtualKeyboardModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule }); }
|
|
718
|
+
static { this.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "17.0.9", ngImport: i0, type: SystelabVirtualKeyboardModule, declarations: [SystelabVirtualKeyboardDirective], imports: [CommonModule, OverlayModule], exports: [SystelabVirtualKeyboardDirective] }); }
|
|
719
|
+
static { this.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "17.0.9", ngImport: i0, type: SystelabVirtualKeyboardModule, imports: [CommonModule, OverlayModule] }); }
|
|
720
|
+
}
|
|
721
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.0.9", ngImport: i0, type: SystelabVirtualKeyboardModule, decorators: [{
|
|
722
|
+
type: NgModule,
|
|
723
|
+
args: [{
|
|
724
|
+
imports: [CommonModule, OverlayModule],
|
|
725
|
+
declarations: [SystelabVirtualKeyboardDirective],
|
|
726
|
+
exports: [SystelabVirtualKeyboardDirective],
|
|
727
|
+
}]
|
|
728
|
+
}] });
|
|
729
|
+
|
|
730
|
+
/*
|
|
731
|
+
* Public API Surface of systelab-virtual-keyboard
|
|
732
|
+
*/
|
|
733
|
+
|
|
734
|
+
/**
|
|
735
|
+
* Generated bundle index. Do not edit.
|
|
736
|
+
*/
|
|
737
|
+
|
|
738
|
+
export { SystelabVirtualKeyboardButton, SystelabVirtualKeyboardDirective, SystelabVirtualKeyboardInputTypes, SystelabVirtualKeyboardLayouts, SystelabVirtualKeyboardModule, factory };
|
|
739
|
+
//# sourceMappingURL=systelab-virtual-keyboard.mjs.map
|