ngx-touch-keyboard
Version:
Virtual Keyboard for Angular applications
1,794 lines • 83.8 kB
JavaScript
import * as i0 from '@angular/core';
import { InjectionToken, inject, ElementRef, output, Component, ViewEncapsulation, ChangeDetectionStrategy, HostListener, Directive, model, input, booleanAttribute, effect, NgModule } from '@angular/core';
import { DomSanitizer } from '@angular/platform-browser';
import * as i1 from '@angular/common';
import { NgClass } from '@angular/common';
import * as i2 from '@angular/cdk/bidi';
import { ComponentPortal, PortalModule } from '@angular/cdk/portal';
import { Overlay, OverlayModule } from '@angular/cdk/overlay';
/**
* A collection of constants representing special function buttons for a touch keyboard.
* Each constant is a string that corresponds to a specific keyboard action.
*/
const fnButton = {
DONE: `{done}`,
ENTER: `{enter}`,
SHIFT: `{shift}`,
BACKSPACE: `{backspace}`,
LANGUAGE: `{language}`,
SPACE: `{space}`,
TAB: `{tab}`,
};
/**
* An object containing SVG icons for various keyboard functions.
*/
const fnDisplay = {
DONE: `<svg xmlns="http://www.w3.org/2000/svg" height="20" width="20" viewBox="0 0 24 24"><path d="m12 15-5-5h10Z"/></svg>`,
ENTER: `<svg xmlns="http://www.w3.org/2000/svg" height="20" width="20" viewBox="0 0 24 24"><path d="m9 18-6-6 6-6 1.4 1.4L6.8 11H19V7h2v6H6.8l3.6 3.6Z"/></svg>`,
SHIFT: `<svg xmlns="http://www.w3.org/2000/svg" height="20" width="20" viewBox="0 0 24 24"><path d="M10.8796773,2.4676627 C10.7983669,2.53542133 10.7233714,2.61041687 10.6556128,2.69172724 L2.79065437,12.1296773 C2.17191723,12.8721619 2.27223434,13.9756501 3.01471891,14.5943872 L3.15432027,14.6993778 C3.44275103,14.8945506 3.78413686,15 4.13504161,15 L6.999,15 L7,20.25 C7,21.2164983 7.78350169,22 8.75,22 L15.25,22 L15.3935272,21.9941988 C16.2928897,21.9211923 17,21.1681734 17,20.25 L16.999,15 L19.8649584,15 C20.8314567,15 21.6149584,14.2164983 21.6149584,13.25 C21.6149584,12.8406111 21.47143,12.4441786 21.2093456,12.1296773 L13.3443872,2.69172724 C12.7600244,1.99049181 11.7432755,1.8620539 11.0066223,2.37118457 L10.8796773,2.4676627 Z M12.1920553,3.65200384 L20.0570137,13.0899539 C20.0944543,13.1348827 20.1149584,13.1915159 20.1149584,13.25 C20.1149584,13.3880712 20.0030296,13.5 19.8649584,13.5 L16.25,13.5 C15.8357864,13.5 15.5,13.8357864 15.5,14.25 L15.5,20.25 C15.5,20.3880712 15.3880712,20.5 15.25,20.5 L8.75,20.5 C8.61192881,20.5 8.5,20.3880712 8.5,20.25 L8.5,14.25 C8.5,13.8357864 8.16421356,13.5 7.75,13.5 L4.13504161,13.5 C4.07655749,13.5 4.01992426,13.4794959 3.97499551,13.4420553 C3.86892629,13.3536643 3.85459527,13.1960231 3.94298629,13.0899539 L11.8079447,3.65200384 C11.8176245,3.64038807 11.8283381,3.62967442 11.8399539,3.61999462 C11.9460231,3.5316036 12.1036643,3.54593461 12.1920553,3.65200384 Z"></path></svg>`,
BACKSPACE: `<svg xmlns="http://www.w3.org/2000/svg" height="20" width="20" viewBox="0 0 24 24"><path d="M18.75,4 C20.4830315,4 21.8992459,5.35645477 21.9948552,7.06557609 L22,7.25 L22,16.75 C22,18.4830315 20.6435452,19.8992459 18.9344239,19.9948552 L18.75,20 L10.2488122,20 C9.48467584,20 8.74731983,19.7308489 8.16441163,19.243553 L8.00936186,19.1052839 L3.01367221,14.3552839 C1.71288481,13.1184697 1.66102433,11.0613371 2.89783857,9.76054971 L3.01367221,9.64471607 L8.00936186,4.89471607 C8.56313355,4.36817906 9.28295917,4.05514987 10.0411712,4.00663485 L10.2488122,4 L18.75,4 Z M18.75,5.5 L10.2488122,5.5 C9.85605678,5.5 9.47644043,5.63205173 9.16975262,5.87226779 L9.04295431,5.98177019 L4.04726465,10.7317702 L3.98489269,10.7941421 C3.3580909,11.4533647 3.34595643,12.473346 3.93064574,13.1462921 L4.04726465,13.2682298 L9.04295431,18.0182298 C9.32758521,18.2888625 9.69368599,18.4547433 10.0814672,18.4919848 L10.2488122,18.5 L18.75,18.5 C19.6681734,18.5 20.4211923,17.7928897 20.4941988,16.8935272 L20.5,16.75 L20.5,7.25 C20.5,6.3318266 19.7928897,5.57880766 18.8935272,5.5058012 L18.75,5.5 Z M11.4462117,8.39705176 L11.5303301,8.46966991 L14.000116,10.939 L16.4696699,8.46966991 C16.7625631,8.1767767 17.2374369,8.1767767 17.5303301,8.46966991 C17.7965966,8.73593648 17.8208027,9.15260016 17.6029482,9.44621165 L17.5303301,9.53033009 L15.061116,12 L17.5303301,14.4696699 C17.8232233,14.7625631 17.8232233,15.2374369 17.5303301,15.5303301 C17.2640635,15.7965966 16.8473998,15.8208027 16.5537883,15.6029482 L16.4696699,15.5303301 L14.000116,13.061 L11.5303301,15.5303301 C11.2374369,15.8232233 10.7625631,15.8232233 10.4696699,15.5303301 C10.2034034,15.2640635 10.1791973,14.8473998 10.3970518,14.5537883 L10.4696699,14.4696699 L12.939116,12 L10.4696699,9.53033009 C10.1767767,9.23743687 10.1767767,8.76256313 10.4696699,8.46966991 C10.7359365,8.20340335 11.1526002,8.1791973 11.4462117,8.39705176 Z"></path></svg>`,
LANGUAGE: `<svg xmlns="http://www.w3.org/2000/svg" height="20" width="20" viewBox="0 0 24 24"><path d="M12 22q-2.05 0-3.875-.788-1.825-.787-3.187-2.15-1.363-1.362-2.15-3.187Q2 14.05 2 12q0-2.075.788-3.887.787-1.813 2.15-3.175Q6.3 3.575 8.125 2.787 9.95 2 12 2q2.075 0 3.887.787 1.813.788 3.175 2.151 1.363 1.362 2.15 3.175Q22 9.925 22 12q0 2.05-.788 3.875-.787 1.825-2.15 3.187-1.362 1.363-3.175 2.15Q14.075 22 12 22Zm0-2.05q.65-.9 1.125-1.875T13.9 16h-3.8q.3 1.1.775 2.075.475.975 1.125 1.875Zm-2.6-.4q-.45-.825-.787-1.713Q8.275 16.95 8.05 16H5.1q.725 1.25 1.812 2.175Q8 19.1 9.4 19.55Zm5.2 0q1.4-.45 2.487-1.375Q18.175 17.25 18.9 16h-2.95q-.225.95-.562 1.837-.338.888-.788 1.713ZM4.25 14h3.4q-.075-.5-.113-.988Q7.5 12.525 7.5 12t.037-1.012q.038-.488.113-.988h-3.4q-.125.5-.188.988Q4 11.475 4 12t.062 1.012q.063.488.188.988Zm5.4 0h4.7q.075-.5.113-.988.037-.487.037-1.012t-.037-1.012q-.038-.488-.113-.988h-4.7q-.075.5-.112.988Q9.5 11.475 9.5 12t.038 1.012q.037.488.112.988Zm6.7 0h3.4q.125-.5.188-.988Q20 12.525 20 12t-.062-1.012q-.063-.488-.188-.988h-3.4q.075.5.112.988.038.487.038 1.012t-.038 1.012q-.037.488-.112.988Zm-.4-6h2.95q-.725-1.25-1.813-2.175Q16 4.9 14.6 4.45q.45.825.788 1.712.337.888.562 1.838ZM10.1 8h3.8q-.3-1.1-.775-2.075Q12.65 4.95 12 4.05q-.65.9-1.125 1.875T10.1 8Zm-5 0h2.95q.225-.95.563-1.838.337-.887.787-1.712Q8 4.9 6.912 5.825 5.825 6.75 5.1 8Z"/></svg>`,
SPACE: ` `,
TAB: `<svg xmlns="http://www.w3.org/2000/svg" height="20" width="20" viewBox="0 0 24 24"><path d="m12 18-1.425-1.4 3.6-3.6H2v-2h12.175L10.6 7.4 12 6l6 6Zm8 0V6h2v12Z"/></svg>`,
};
const layouts$6 = {
text_alphabetic: [
['q', 'w', 'e', 'r', 't', 'y', 'u', 'i', 'o', 'p'],
['a', 's', 'd', 'f', 'g', 'h', 'j', 'k', 'l'],
['{shift}', 'z', 'x', 'c', 'v', 'b', 'n', 'm', '{backspace}'],
['{numeric}', '{space}', '{done}'],
],
text_shift: [
['Q', 'W', 'E', 'R', 'T', 'Y', 'U', 'I', 'O', 'P'],
['A', 'S', 'D', 'F', 'G', 'H', 'J', 'K', 'L'],
['{shift}', 'Z', 'X', 'C', 'V', 'B', 'N', 'M', '{backspace}'],
['{numeric}', '{space}', '{done}'],
],
text_numeric: [
['1', '2', '3', '4', '5', '6', '7', '8', '9', '0'],
['-', '/', ':', ';', '(', ')', '$', '&', '@', '"'],
['{symbolic}', '.', ',', '?', '!', "'", '{backspace}'],
['{alphabetic}', '{space}', '{done}'],
],
text_symbolic: [
['[', ']', '{', '}', '#', '%', '^', '*', '+', '='],
['_', '\\', '|', '~', '<', '>', '€', '£', '¥', '•'],
['{numeric}', '.', ',', '?', '!', "'", '{backspace}'],
['{alphabetic}', '{space}', '{done}'],
],
search_alphabetic: [
['q', 'w', 'e', 'r', 't', 'y', 'u', 'i', 'o', 'p'],
['a', 's', 'd', 'f', 'g', 'h', 'j', 'k', 'l'],
['{shift}', 'z', 'x', 'c', 'v', 'b', 'n', 'm', '{backspace}'],
['{numeric}', '{space}', '{done}'],
],
search_shift: [
['Q', 'W', 'E', 'R', 'T', 'Y', 'U', 'I', 'O', 'P'],
['A', 'S', 'D', 'F', 'G', 'H', 'J', 'K', 'L'],
['{shift}', 'Z', 'X', 'C', 'V', 'B', 'N', 'M', '{backspace}'],
['{numeric}', '{space}', '{done}'],
],
search_numeric: [
['1', '2', '3', '4', '5', '6', '7', '8', '9', '0'],
['-', '/', ':', ';', '(', ')', '$', '&', '@', '"'],
['{symbolic}', '.', ',', '?', '!', "'", '{backspace}'],
['{alphabetic}', '{space}', '{done}'],
],
search_symbolic: [
['[', ']', '{', '}', '#', '%', '^', '*', '+', '='],
['_', '\\', '|', '~', '<', '>', '€', '£', '¥', '•'],
['{numeric}', '.', ',', '?', '!', "'", '{backspace}'],
['{alphabetic}', '{space}', '{done}'],
],
email_alphabetic: [
['q', 'w', 'e', 'r', 't', 'y', 'u', 'i', 'o', 'p'],
['a', 's', 'd', 'f', 'g', 'h', 'j', 'k', 'l'],
['{shift}', 'z', 'x', 'c', 'v', 'b', 'n', 'm', '{backspace}'],
['{numeric}', '@', '{space}', '.', '{done}'],
],
email_shift: [
['Q', 'W', 'E', 'R', 'T', 'Y', 'U', 'I', 'O', 'P'],
['A', 'S', 'D', 'F', 'G', 'H', 'J', 'K', 'L'],
['{shift}', 'Z', 'X', 'C', 'V', 'B', 'N', 'M', '{backspace}'],
['{numeric}', '@', '{space}', '.', '{done}'],
],
email_numeric: [
['1', '2', '3', '4', '5', '6', '7', '8', '9', '0'],
['$', '!', '~', '&', '=', '#', '[', ']'],
['{symbolic}', '.', '_', '-', '+', '{backspace}'],
['{alphabetic}', '@', '{space}', '.', '{done}'],
],
email_symbolic: [
['`', '|', '{', '}', '?', '%', '^', '*', '/', "'"],
['$', '!', '~', '&', '=', '#', '[', ']'],
['{numeric}', '.', '_', '-', '+', '{backspace}'],
['{alphabetic}', '@', '{space}', '.', '{done}'],
],
url_alphabetic: [
['q', 'w', 'e', 'r', 't', 'y', 'u', 'i', 'o', 'p'],
['a', 's', 'd', 'f', 'g', 'h', 'j', 'k', 'l'],
['{shift}', 'z', 'x', 'c', 'v', 'b', 'n', 'm', '{backspace}'],
['{numeric}', '/', '.com', '.', '{done}'],
],
url_shift: [
['Q', 'W', 'E', 'R', 'T', 'Y', 'U', 'I', 'O', 'P'],
['A', 'S', 'D', 'F', 'G', 'H', 'J', 'K', 'L'],
['{shift}', 'Z', 'X', 'C', 'V', 'B', 'N', 'M', '{backspace}'],
['{numeric}', '/', '.com', '.', '{done}'],
],
url_numeric: [
['1', '2', '3', '4', '5', '6', '7', '8', '9', '0'],
['@', '&', '%', '?', ',', '=', '[', ']'],
['{symbolic}', '_', ':', '-', '+', '{backspace}'],
['{alphabetic}', '/', '.com', '.', '{done}'],
],
url_symbolic: [
['1', '2', '3', '4', '5', '6', '7', '8', '9', '0'],
['*', '$', '#', '!', "'", '^', '[', ']'],
['{numeric}', '~', ';', '(', ')', '{backspace}'],
['{alphabetic}', '/', '.com', '.', '{done}'],
],
numeric_default: [
['1', '2', '3'],
['4', '5', '6'],
['7', '8', '9'],
['0', '{backspace}'],
],
decimal_default: [
['1', '2', '3'],
['4', '5', '6'],
['7', '8', '9'],
['.', '0', '{backspace}'],
],
tel_default: [
['1', '2', '3', '*'],
['4', '5', '6', '#'],
['7', '8', '9', '+'],
['0', '{backspace}'],
],
};
const display$6 = {
'{done}': fnDisplay.DONE,
'{shift}': fnDisplay.SHIFT,
'{backspace}': fnDisplay.BACKSPACE,
'{space}': fnDisplay.SPACE,
'{alphabetic}': 'ABC',
'{numeric}': '123',
'{symbolic}': '#+=',
};
const locale$6 = {
code: 'en-GB',
dir: 'ltr',
layouts: layouts$6,
display: display$6,
};
const layouts$5 = {
text_alphabetic: [
['q', 'w', 'e', 'r', 't', 'y', 'u', 'i', 'o', 'p'],
['a', 's', 'd', 'f', 'g', 'h', 'j', 'k', 'l'],
['{shift}', 'z', 'x', 'c', 'v', 'b', 'n', 'm', '{backspace}'],
['{numeric}', '{space}', '{done}'],
],
text_shift: [
['Q', 'W', 'E', 'R', 'T', 'Y', 'U', 'I', 'O', 'P'],
['A', 'S', 'D', 'F', 'G', 'H', 'J', 'K', 'L'],
['{shift}', 'Z', 'X', 'C', 'V', 'B', 'N', 'M', '{backspace}'],
['{numeric}', '{space}', '{done}'],
],
text_numeric: [
['1', '2', '3', '4', '5', '6', '7', '8', '9', '0'],
['-', '/', ':', ';', '(', ')', '$', '&', '@', '"'],
['{symbolic}', '.', ',', '?', '!', "'", '{backspace}'],
['{alphabetic}', '{space}', '{done}'],
],
text_symbolic: [
['[', ']', '{', '}', '#', '%', '^', '*', '+', '='],
['_', '\\', '|', '~', '<', '>', '€', '£', '¥', '•'],
['{numeric}', '.', ',', '?', '!', "'", '{backspace}'],
['{alphabetic}', '{space}', '{done}'],
],
search_alphabetic: [
['q', 'w', 'e', 'r', 't', 'y', 'u', 'i', 'o', 'p'],
['a', 's', 'd', 'f', 'g', 'h', 'j', 'k', 'l'],
['{shift}', 'z', 'x', 'c', 'v', 'b', 'n', 'm', '{backspace}'],
['{numeric}', '{space}', '{done}'],
],
search_shift: [
['Q', 'W', 'E', 'R', 'T', 'Y', 'U', 'I', 'O', 'P'],
['A', 'S', 'D', 'F', 'G', 'H', 'J', 'K', 'L'],
['{shift}', 'Z', 'X', 'C', 'V', 'B', 'N', 'M', '{backspace}'],
['{numeric}', '{space}', '{done}'],
],
search_numeric: [
['1', '2', '3', '4', '5', '6', '7', '8', '9', '0'],
['-', '/', ':', ';', '(', ')', '$', '&', '@', '"'],
['{symbolic}', '.', ',', '?', '!', "'", '{backspace}'],
['{alphabetic}', '{space}', '{done}'],
],
search_symbolic: [
['[', ']', '{', '}', '#', '%', '^', '*', '+', '='],
['_', '\\', '|', '~', '<', '>', '€', '£', '¥', '•'],
['{numeric}', '.', ',', '?', '!', "'", '{backspace}'],
['{alphabetic}', '{space}', '{done}'],
],
email_alphabetic: [
['q', 'w', 'e', 'r', 't', 'y', 'u', 'i', 'o', 'p'],
['a', 's', 'd', 'f', 'g', 'h', 'j', 'k', 'l'],
['{shift}', 'z', 'x', 'c', 'v', 'b', 'n', 'm', '{backspace}'],
['{numeric}', '@', '{space}', '.', '{done}'],
],
email_shift: [
['Q', 'W', 'E', 'R', 'T', 'Y', 'U', 'I', 'O', 'P'],
['A', 'S', 'D', 'F', 'G', 'H', 'J', 'K', 'L'],
['{shift}', 'Z', 'X', 'C', 'V', 'B', 'N', 'M', '{backspace}'],
['{numeric}', '@', '{space}', '.', '{done}'],
],
email_numeric: [
['1', '2', '3', '4', '5', '6', '7', '8', '9', '0'],
['$', '!', '~', '&', '=', '#', '[', ']'],
['{symbolic}', '.', '_', '-', '+', '{backspace}'],
['{alphabetic}', '@', '{space}', '.', '{done}'],
],
email_symbolic: [
['`', '|', '{', '}', '?', '%', '^', '*', '/', "'"],
['$', '!', '~', '&', '=', '#', '[', ']'],
['{numeric}', '.', '_', '-', '+', '{backspace}'],
['{alphabetic}', '@', '{space}', '.', '{done}'],
],
url_alphabetic: [
['q', 'w', 'e', 'r', 't', 'y', 'u', 'i', 'o', 'p'],
['a', 's', 'd', 'f', 'g', 'h', 'j', 'k', 'l'],
['{shift}', 'z', 'x', 'c', 'v', 'b', 'n', 'm', '{backspace}'],
['{numeric}', '/', '.com', '.', '{done}'],
],
url_shift: [
['Q', 'W', 'E', 'R', 'T', 'Y', 'U', 'I', 'O', 'P'],
['A', 'S', 'D', 'F', 'G', 'H', 'J', 'K', 'L'],
['{shift}', 'Z', 'X', 'C', 'V', 'B', 'N', 'M', '{backspace}'],
['{numeric}', '/', '.com', '.', '{done}'],
],
url_numeric: [
['1', '2', '3', '4', '5', '6', '7', '8', '9', '0'],
['@', '&', '%', '?', ',', '=', '[', ']'],
['{symbolic}', '_', ':', '-', '+', '{backspace}'],
['{alphabetic}', '/', '.com', '.', '{done}'],
],
url_symbolic: [
['1', '2', '3', '4', '5', '6', '7', '8', '9', '0'],
['*', '$', '#', '!', "'", '^', '[', ']'],
['{numeric}', '~', ';', '(', ')', '{backspace}'],
['{alphabetic}', '/', '.com', '.', '{done}'],
],
numeric_default: [
['1', '2', '3'],
['4', '5', '6'],
['7', '8', '9'],
['0', '{backspace}'],
],
decimal_default: [
['1', '2', '3'],
['4', '5', '6'],
['7', '8', '9'],
['.', '0', '{backspace}'],
],
tel_default: [
['1', '2', '3', '*'],
['4', '5', '6', '#'],
['7', '8', '9', '+'],
['0', '{backspace}'],
],
};
const display$5 = {
'{done}': fnDisplay.DONE,
'{shift}': fnDisplay.SHIFT,
'{backspace}': fnDisplay.BACKSPACE,
'{space}': fnDisplay.SPACE,
'{alphabetic}': 'ABC',
'{numeric}': '123',
'{symbolic}': '#+=',
};
const locale$5 = {
code: 'en-US',
dir: 'ltr',
layouts: layouts$5,
display: display$5,
};
const layouts$4 = {
text_alphabetic: [
['ض', 'ص', 'ق', 'ف', 'غ', 'ع', 'ه', 'خ', 'ح', 'ج', 'چ'],
['ش', 'س', 'ی', 'ب', 'ل', 'ا', 'ت', 'ن', 'م', 'ک', 'گ'],
['ظ', 'ط', 'ژ', 'ز', 'ر', 'ذ', 'د', 'پ', 'و', 'ث', '{backspace}'],
['{numeric}', '{space}', '{done}'],
],
text_numeric: [
['۱', '۲', '۳', '۴', '۵', '۶', '۷', '۸', '۹', '۰'],
['-', '/', ':', '؛', ')', '(', '$', '@', '»', '«'],
['{symbolic}', '.', '،', '؟', '!', '٫', '{backspace}'],
['{alphabetic}', '{space}', '{done}'],
],
text_symbolic: [
[']', '[', '}', '{', '#', '%', '^', '*', '+', '='],
['_', '\\', '|', '~', '>', '<', '&', '•', '‘', '“'],
['{numeric}', '.', '،', '؟', '!', '٬', '{backspace}'],
['{alphabetic}', '{space}', '{done}'],
],
search_alphabetic: [
['ض', 'ص', 'ق', 'ف', 'غ', 'ع', 'ه', 'خ', 'ح', 'ج', 'چ'],
['ش', 'س', 'ی', 'ب', 'ل', 'ا', 'ت', 'ن', 'م', 'ک', 'گ'],
['ظ', 'ط', 'ژ', 'ز', 'ر', 'ذ', 'د', 'پ', 'و', 'ث', '{backspace}'],
['{numeric}', '{space}', '{done}'],
],
search_numeric: [
['۱', '۲', '۳', '۴', '۵', '۶', '۷', '۸', '۹', '۰'],
['-', '/', ':', '؛', ')', '(', '$', '@', '»', '«'],
['{symbolic}', '.', '،', '؟', '!', '٫', '{backspace}'],
['{alphabetic}', '{space}', '{done}'],
],
search_symbolic: [
[']', '[', '}', '{', '#', '%', '^', '*', '+', '='],
['_', '\\', '|', '~', '>', '<', '&', '•', '‘', '“'],
['{numeric}', '.', '،', '؟', '!', '٬', '{backspace}'],
['{alphabetic}', '{space}', '{done}'],
],
email_alphabetic: [
['ض', 'ص', 'ق', 'ف', 'غ', 'ع', 'ه', 'خ', 'ح', 'ج', 'چ'],
['ش', 'س', 'ی', 'ب', 'ل', 'ا', 'ت', 'ن', 'م', 'ک', 'گ'],
['ظ', 'ط', 'ژ', 'ز', 'ر', 'ذ', 'د', 'پ', 'و', 'ث', '{backspace}'],
['{numeric}', '@', '{space}', '.', '{done}'],
],
email_numeric: [
['۱', '۲', '۳', '۴', '۵', '۶', '۷', '۸', '۹', '۰'],
['$', '!', '~', '&', '=', '#', ']', '['],
['{symbolic}', '.', '_', '-', '+', '{backspace}'],
['{alphabetic}', '@', '{space}', '.', '{done}'],
],
email_symbolic: [
['`', '|', '{', '}', '?', '%', '^', '*', '/', "'"],
['$', '!', '~', '&', '=', '#', ']', '['],
['{numeric}', '.', '_', '-', '+', '{backspace}'],
['{alphabetic}', '@', '{space}', '.', '{done}'],
],
url_alphabetic: [
['ض', 'ص', 'ق', 'ف', 'غ', 'ع', 'ه', 'خ', 'ح', 'ج', 'چ'],
['ش', 'س', 'ی', 'ب', 'ل', 'ا', 'ت', 'ن', 'م', 'ک', 'گ'],
['ظ', 'ط', 'ژ', 'ز', 'ر', 'ذ', 'د', 'پ', 'و', 'ث', '{backspace}'],
['{numeric}', '/', '.com', '.', '{done}'],
],
url_numeric: [
['۱', '۲', '۳', '۴', '۵', '۶', '۷', '۸', '۹', '۰'],
['@', '&', '%', '?', ',', '=', ']', '['],
['{symbolic}', '_', ':', '-', '+', '{backspace}'],
['{alphabetic}', '/', '.com', '.', '{done}'],
],
url_symbolic: [
['۱', '۲', '۳', '۴', '۵', '۶', '۷', '۸', '۹', '۰'],
['*', '$', '#', '!', "'", '^', ']', '['],
['{numeric}', '~', ';', ')', '(', '{backspace}'],
['{alphabetic}', '/', '.com', '.', '{done}'],
],
numeric_default: [
['۱', '۲', '۳'],
['۴', '۵', '۶'],
['۷', '۸', '۹'],
['۰', '{backspace}'],
],
decimal_default: [
['۱', '۲', '۳'],
['۴', '۵', '۶'],
['۷', '۸', '۹'],
['٫', '۰', '{backspace}'],
],
tel_default: [
['۱', '۲', '۳', '*'],
['۴', '۵', '۶', '#'],
['۷', '۸', '۹', '+'],
['۰', '{backspace}'],
],
};
const display$4 = {
'{done}': fnDisplay.DONE,
'{backspace}': fnDisplay.BACKSPACE,
'{space}': fnDisplay.SPACE,
'{alphabetic}': 'ابپ',
'{numeric}': '۱۲۳',
'{symbolic}': '=+#',
};
const locale$4 = {
code: 'fa-IR',
dir: 'rtl',
layouts: layouts$4,
display: display$4,
};
const layouts$3 = {
text_alphabetic: [
['ק', 'ר', 'א', 'ט', 'ו', 'ן', 'ם', 'פ'],
['ש', 'ד', 'ג', 'כ', 'ע', 'י', 'ח', 'ל', 'ך', 'ף'],
['ז', 'ס', 'ב', 'ה', 'נ', 'מ', 'צ', 'ת', 'ץ', '{backspace}'],
['{numeric}', '{space}', '{done}'],
],
text_numeric: [
['1', '2', '3', '4', '5', '6', '7', '8', '9', '0'],
['-', '/', ':', ';', '(', ')', '₪', '@', '"', "'"],
['{symbolic}', '.', ',', '?', '!', '{backspace}'],
['{alphabetic}', '{space}', '{done}'],
],
text_symbolic: [
['[', ']', '{', '}', '#', '%', '^', '*', '+', '='],
['_', '\\', '|', '~', '<', '>', '€', '$', '&', '•'],
['{numeric}', '.', ',', '?', '!', '{backspace}'],
['{alphabetic}', '{space}', '{done}'],
],
search_alphabetic: [
['ק', 'ר', 'א', 'ט', 'ו', 'ן', 'ם', 'פ'],
['ש', 'ד', 'ג', 'כ', 'ע', 'י', 'ח', 'ל', 'ך', 'ף'],
['ז', 'ס', 'ב', 'ה', 'נ', 'מ', 'צ', 'ת', 'ץ', '{backspace}'],
['{numeric}', '{space}', '{done}'],
],
search_numeric: [
['1', '2', '3', '4', '5', '6', '7', '8', '9', '0'],
['-', '/', ':', ';', '(', ')', '₪', '@', '"', "'"],
['{symbolic}', '.', ',', '?', '!', '{backspace}'],
['{alphabetic}', '{space}', '{done}'],
],
search_symbolic: [
['[', ']', '{', '}', '#', '%', '^', '*', '+', '='],
['_', '\\', '|', '~', '<', '>', '€', '$', '&', '•'],
['{numeric}', '.', ',', '?', '!', '{backspace}'],
['{alphabetic}', '{space}', '{done}'],
],
email_alphabetic: [
['ק', 'ר', 'א', 'ט', 'ו', 'ן', 'ם', 'פ'],
['ש', 'ד', 'ג', 'כ', 'ע', 'י', 'ח', 'ל', 'ך', 'ף'],
['ז', 'ס', 'ב', 'ה', 'נ', 'מ', 'צ', 'ת', 'ץ', '{backspace}'],
['{numeric}', '@', '{space}', '.', '{done}'],
],
email_numeric: [
['1', '2', '3', '4', '5', '6', '7', '8', '9', '0'],
['₪', '!', '~', '&', '=', '#', ']', '['],
['{symbolic}', '.', '_', '-', '+', '{backspace}'],
['{alphabetic}', '@', '{space}', '.', '{done}'],
],
email_symbolic: [
['`', '|', '{', '}', '?', '%', '^', '*', '/', "'"],
['₪', '!', '~', '&', '=', '#', ']', '['],
['{numeric}', '.', '_', '-', '+', '{backspace}'],
['{alphabetic}', '@', '{space}', '.', '{done}'],
],
url_alphabetic: [
['ק', 'ר', 'א', 'ט', 'ו', 'ן', 'ם', 'פ'],
['ש', 'ד', 'ג', 'כ', 'ע', 'י', 'ח', 'ל', 'ך', 'ף'],
['ז', 'ס', 'ב', 'ה', 'נ', 'מ', 'צ', 'ת', 'ץ', '{backspace}'],
['{numeric}', '/', '.com', '.', '{done}'],
],
url_numeric: [
['1', '2', '3', '4', '5', '6', '7', '8', '9', '0'],
['@', '&', '%', '?', ',', '=', ']', '['],
['{symbolic}', '_', ':', '-', '+', '{backspace}'],
['{alphabetic}', '/', '.com', '.', '{done}'],
],
url_symbolic: [
['1', '2', '3', '4', '5', '6', '7', '8', '9', '0'],
['*', '₪', '#', '!', "'", '^', ']', '['],
['{numeric}', '~', ';', ')', '(', '{backspace}'],
['{alphabetic}', '/', '.com', '.', '{done}'],
],
numeric_default: [
['1', '2', '3'],
['4', '5', '6'],
['7', '8', '9'],
['0', '{backspace}'],
],
decimal_default: [
['1', '2', '3'],
['4', '5', '6'],
['7', '8', '9'],
['.', '0', '{backspace}'],
],
tel_default: [
['1', '2', '3', '*'],
['4', '5', '6', '#'],
['7', '8', '9', '+'],
['0', '{backspace}'],
],
};
const display$3 = {
'{done}': fnDisplay.DONE,
'{backspace}': fnDisplay.BACKSPACE,
'{space}': fnDisplay.SPACE,
'{alphabetic}': 'אבג',
'{numeric}': '123',
'{symbolic}': '=+#',
};
const locale$3 = {
code: 'he-IL',
dir: 'rtl',
layouts: layouts$3,
display: display$3,
};
const layouts$2 = {
text_alphabetic: [
['ქ', 'წ', 'ე', 'რ', 'ტ', 'ყ', 'უ', 'ი', 'ო', 'პ'],
['ა', 'ს', 'დ', 'ფ', 'გ', 'ჰ', 'ჯ', 'კ', 'ლ'],
['{shift}', 'ზ', 'ხ', 'ც', 'ვ', 'ბ', 'ნ', 'მ', '{backspace}'],
['{numeric}', '{space}', '{done}'],
],
text_shift: [
['ქ', 'ჭ', 'ე', 'ღ', 'თ', 'ყ', 'უ', 'ი', 'ო', 'პ'],
['ა', 'შ', 'დ', 'ფ', 'გ', 'ჰ', 'ჟ', 'კ', '₾'],
['{shift}', 'ძ', 'ხ', 'ჩ', 'ვ', 'ბ', 'ნ', 'მ', '{backspace}'],
['{numeric}', '{space}', '{done}'],
],
text_numeric: [
['1', '2', '3', '4', '5', '6', '7', '8', '9', '0'],
['-', '/', ':', ';', '(', ')', '$', '&', '@', '"'],
['{symbolic}', '.', ',', '?', '!', "'", '{backspace}'],
['{alphabetic}', '{space}', '{done}'],
],
text_symbolic: [
['[', ']', '{', '}', '#', '%', '^', '*', '+', '='],
['_', '\\', '|', '~', '<', '>', '€', '£', '¥', '•'],
['{numeric}', '.', ',', '?', '!', "'", '{backspace}'],
['{alphabetic}', '{space}', '{done}'],
],
search_alphabetic: [
['ქ', 'წ', 'ე', 'რ', 'ტ', 'ყ', 'უ', 'ი', 'ო', 'პ'],
['ა', 'ს', 'დ', 'ფ', 'გ', 'ჰ', 'ჯ', 'კ', 'ლ'],
['{shift}', 'ზ', 'ხ', 'ც', 'ვ', 'ბ', 'ნ', 'მ', '{backspace}'],
['{numeric}', '{space}', '{done}'],
],
search_shift: [
['ქ', 'ჭ', 'ე', 'ღ', 'თ', 'ყ', 'უ', 'ი', 'ო', 'პ'],
['ა', 'შ', 'დ', 'ფ', 'გ', 'ჰ', 'ჟ', 'კ', '₾'],
['{shift}', 'ძ', 'ხ', 'ჩ', 'ვ', 'ბ', 'ნ', 'მ', '{backspace}'],
['{numeric}', '{space}', '{done}'],
],
search_numeric: [
['1', '2', '3', '4', '5', '6', '7', '8', '9', '0'],
['-', '/', ':', ';', '(', ')', '$', '&', '@', '"'],
['{symbolic}', '.', ',', '?', '!', "'", '{backspace}'],
['{alphabetic}', '{space}', '{done}'],
],
search_symbolic: [
['[', ']', '{', '}', '#', '%', '^', '*', '+', '='],
['_', '\\', '|', '~', '<', '>', '€', '£', '¥', '•'],
['{numeric}', '.', ',', '?', '!', "'", '{backspace}'],
['{alphabetic}', '{space}', '{done}'],
],
email_alphabetic: [
['ქ', 'წ', 'ე', 'რ', 'ტ', 'ყ', 'უ', 'ი', 'ო', 'პ'],
['ა', 'ს', 'დ', 'ფ', 'გ', 'ჰ', 'ჯ', 'კ', 'ლ'],
['{shift}', 'ზ', 'ხ', 'ც', 'ვ', 'ბ', 'ნ', 'მ', '{backspace}'],
['{numeric}', '@', '{space}', '.', '{done}'],
],
email_shift: [
['ქ', 'ჭ', 'ე', 'ღ', 'თ', 'ყ', 'უ', 'ი', 'ო', 'პ'],
['ა', 'შ', 'დ', 'ფ', 'გ', 'ჰ', 'ჟ', 'კ', '₾'],
['{shift}', 'ძ', 'ხ', 'ჩ', 'ვ', 'ბ', 'ნ', 'მ', '{backspace}'],
['{numeric}', '@', '{space}', '.', '{done}'],
],
email_numeric: [
['1', '2', '3', '4', '5', '6', '7', '8', '9', '0'],
['$', '!', '~', '&', '=', '#', '[', ']'],
['{symbolic}', '.', '_', '-', '+', '{backspace}'],
['{alphabetic}', '@', '{space}', '.', '{done}'],
],
email_symbolic: [
['`', '|', '{', '}', '?', '%', '^', '*', '/', "'"],
['$', '!', '~', '&', '=', '#', '[', ']'],
['{numeric}', '.', '_', '-', '+', '{backspace}'],
['{alphabetic}', '@', '{space}', '.', '{done}'],
],
url_alphabetic: [
['ქ', 'წ', 'ე', 'რ', 'ტ', 'ყ', 'უ', 'ი', 'ო', 'პ'],
['ა', 'ს', 'დ', 'ფ', 'გ', 'ჰ', 'ჯ', 'კ', 'ლ'],
['{shift}', 'ზ', 'ხ', 'ც', 'ვ', 'ბ', 'ნ', 'მ', '{backspace}'],
['{numeric}', '/', '.com', '.', '{done}'],
],
url_shift: [
['ქ', 'ჭ', 'ე', 'ღ', 'თ', 'ყ', 'უ', 'ი', 'ო', 'პ'],
['ა', 'შ', 'დ', 'ფ', 'გ', 'ჰ', 'ჟ', 'კ', '₾'],
['{shift}', 'ძ', 'ხ', 'ჩ', 'ვ', 'ბ', 'ნ', 'მ', '{backspace}'],
['{numeric}', '/', '.com', '.', '{done}'],
],
url_numeric: [
['1', '2', '3', '4', '5', '6', '7', '8', '9', '0'],
['@', '&', '%', '?', ',', '=', '[', ']'],
['{symbolic}', '_', ':', '-', '+', '{backspace}'],
['{alphabetic}', '/', '.com', '.', '{done}'],
],
url_symbolic: [
['1', '2', '3', '4', '5', '6', '7', '8', '9', '0'],
['*', '$', '#', '!', "'", '^', '[', ']'],
['{numeric}', '~', ';', '(', ')', '{backspace}'],
['{alphabetic}', '/', '.com', '.', '{done}'],
],
numeric_default: [
['1', '2', '3'],
['4', '5', '6'],
['7', '8', '9'],
['0', '{backspace}'],
],
decimal_default: [
['1', '2', '3'],
['4', '5', '6'],
['7', '8', '9'],
['.', '0', '{backspace}'],
],
tel_default: [
['1', '2', '3', '*'],
['4', '5', '6', '#'],
['7', '8', '9', '+'],
['0', '{backspace}'],
],
};
const display$2 = {
'{done}': fnDisplay.DONE,
'{shift}': fnDisplay.SHIFT,
'{backspace}': fnDisplay.BACKSPACE,
'{space}': fnDisplay.SPACE,
'{alphabetic}': 'აბგ',
'{numeric}': '123',
'{symbolic}': '#+=',
};
const locale$2 = {
code: 'ka-GE',
dir: 'ltr',
layouts: layouts$2,
display: display$2,
};
const layouts$1 = {
text_alphabetic: [
['й', 'ц', 'у', 'к', 'е', 'н', 'г', 'ш', 'щ', 'з', 'х', 'ъ'],
['ф', 'ы', 'в', 'а', 'п', 'р', 'о', 'л', 'д', 'ж', 'э'],
['{shift}', 'я', 'ч', 'с', 'м', 'и', 'т', 'ь', 'б', 'ю', '{backspace}'],
['{numeric}', '{space}', '{done}'],
],
text_shift: [
['Й', 'Ц', 'У', 'К', 'Е', 'Н', 'Г', 'Ш', 'Щ', 'З', 'Х', 'Ъ'],
['Ф', 'Ы', 'В', 'А', 'П', 'Р', 'О', 'Л', 'Д', 'Ж', 'З'],
['{shift}', 'Я', 'Ч', 'С', 'М', 'И', 'Т', 'Ь', 'Б', 'Ю', '{backspace}'],
['{numeric}', '{space}', '{done}'],
],
text_numeric: [
['1', '2', '3', '4', '5', '6', '7', '8', '9', '0'],
['-', '/', ':', ';', '(', ')', '$', '&', '@', '"'],
['{symbolic}', '.', ',', '?', '!', "'", '{backspace}'],
['{alphabetic}', '{space}', '{done}'],
],
text_symbolic: [
['[', ']', '{', '}', '#', '%', '^', '*', '+', '='],
['_', '\\', '|', '~', '<', '>', '€', '£', '¥', '•'],
['{numeric}', '.', ',', '?', '!', "'", '{backspace}'],
['{alphabetic}', '{space}', '{done}'],
],
search_alphabetic: [
['й', 'ц', 'у', 'к', 'е', 'н', 'г', 'ш', 'щ', 'з', 'х', 'ъ'],
['ф', 'ы', 'в', 'а', 'п', 'р', 'о', 'л', 'д', 'ж', 'э'],
['{shift}', 'я', 'ч', 'с', 'м', 'и', 'т', 'ь', 'б', 'ю', '{backspace}'],
['{numeric}', '{space}', '{done}'],
],
search_shift: [
['Й', 'Ц', 'У', 'К', 'Е', 'Н', 'Г', 'Ш', 'Щ', 'З', 'Х', 'Ъ'],
['Ф', 'Ы', 'В', 'А', 'П', 'Р', 'О', 'Л', 'Д', 'Ж', 'З'],
['{shift}', 'Я', 'Ч', 'С', 'М', 'И', 'Т', 'Ь', 'Б', 'Ю', '{backspace}'],
['{numeric}', '{space}', '{done}'],
],
search_numeric: [
['1', '2', '3', '4', '5', '6', '7', '8', '9', '0'],
['-', '/', ':', ';', '(', ')', '$', '&', '@', '"'],
['{symbolic}', '.', ',', '?', '!', "'", '{backspace}'],
['{alphabetic}', '{space}', '{done}'],
],
search_symbolic: [
['[', ']', '{', '}', '#', '%', '^', '*', '+', '='],
['_', '\\', '|', '~', '<', '>', '€', '£', '¥', '•'],
['{numeric}', '.', ',', '?', '!', "'", '{backspace}'],
['{alphabetic}', '{space}', '{done}'],
],
email_alphabetic: [
['й', 'ц', 'у', 'к', 'е', 'н', 'г', 'ш', 'щ', 'з', 'х', 'ъ'],
['ф', 'ы', 'в', 'а', 'п', 'р', 'о', 'л', 'д', 'ж', 'э'],
['{shift}', 'я', 'ч', 'с', 'м', 'и', 'т', 'ь', 'б', 'ю', '{backspace}'],
['{numeric}', '@', '{space}', '.', '{done}'],
],
email_shift: [
['Й', 'Ц', 'У', 'К', 'Е', 'Н', 'Г', 'Ш', 'Щ', 'З', 'Х', 'Ъ'],
['Ф', 'Ы', 'В', 'А', 'П', 'Р', 'О', 'Л', 'Д', 'Ж', 'З'],
['{shift}', 'Я', 'Ч', 'С', 'М', 'И', 'Т', 'Ь', 'Б', 'Ю', '{backspace}'],
['{numeric}', '@', '{space}', '.', '{done}'],
],
email_numeric: [
['1', '2', '3', '4', '5', '6', '7', '8', '9', '0'],
['$', '!', '~', '&', '=', '#', '[', ']'],
['{symbolic}', '.', '_', '-', '+', '{backspace}'],
['{alphabetic}', '@', '{space}', '.', '{done}'],
],
email_symbolic: [
['`', '|', '{', '}', '?', '%', '^', '*', '/', "'"],
['$', '!', '~', '&', '=', '#', '[', ']'],
['{numeric}', '.', '_', '-', '+', '{backspace}'],
['{alphabetic}', '@', '{space}', '.', '{done}'],
],
url_alphabetic: [
['й', 'ц', 'у', 'к', 'е', 'н', 'г', 'ш', 'щ', 'з', 'х', 'ъ'],
['ф', 'ы', 'в', 'а', 'п', 'р', 'о', 'л', 'д', 'ж', 'э'],
['{shift}', 'я', 'ч', 'с', 'м', 'и', 'т', 'ь', 'б', 'ю', '{backspace}'],
['{numeric}', '/', '.ru', '.', '{done}'],
],
url_shift: [
['Й', 'Ц', 'У', 'К', 'Е', 'Н', 'Г', 'Ш', 'Щ', 'З', 'Х', 'Ъ'],
['Ф', 'Ы', 'В', 'А', 'П', 'Р', 'О', 'Л', 'Д', 'Ж', 'З'],
['{shift}', 'Я', 'Ч', 'С', 'М', 'И', 'Т', 'Ь', 'Б', 'Ю', '{backspace}'],
['{numeric}', '/', '.ru', '.', '{done}'],
],
url_numeric: [
['1', '2', '3', '4', '5', '6', '7', '8', '9', '0'],
['@', '&', '%', '?', ',', '=', '[', ']'],
['{symbolic}', '_', ':', '-', '+', '{backspace}'],
['{alphabetic}', '/', '.ru', '.', '{done}'],
],
url_symbolic: [
['1', '2', '3', '4', '5', '6', '7', '8', '9', '0'],
['*', '$', '#', '!', "'", '^', '[', ']'],
['{numeric}', '~', ';', '(', ')', '{backspace}'],
['{alphabetic}', '/', '.ru', '.', '{done}'],
],
numeric_default: [
['1', '2', '3'],
['4', '5', '6'],
['7', '8', '9'],
['0', '{backspace}'],
],
decimal_default: [
['1', '2', '3'],
['4', '5', '6'],
['7', '8', '9'],
['.', '0', '{backspace}'],
],
tel_default: [
['1', '2', '3', '*'],
['4', '5', '6', '#'],
['7', '8', '9', '+'],
['0', '{backspace}'],
],
};
const display$1 = {
'{done}': fnDisplay.DONE,
'{shift}': fnDisplay.SHIFT,
'{backspace}': fnDisplay.BACKSPACE,
'{space}': fnDisplay.SPACE,
'{alphabetic}': 'АБВ',
'{numeric}': '123',
'{symbolic}': '#+=',
};
const locale$1 = {
code: 'ru-RU',
dir: 'ltr',
layouts: layouts$1,
display: display$1,
};
const layouts = {
text_alphabetic: [
['q', 'w', 'e', 'r', 't', 'y', 'u', 'i', 'o', 'p', 'å'],
['a', 's', 'd', 'f', 'g', 'h', 'j', 'k', 'l', 'ö', 'ä'],
['{shift}', 'z', 'x', 'c', 'v', 'b', 'n', 'm', '{backspace}'],
['{numeric}', '{space}', '{done}'],
],
text_shift: [
['Q', 'W', 'E', 'R', 'T', 'Y', 'U', 'I', 'O', 'P', 'Å'],
['A', 'S', 'D', 'F', 'G', 'H', 'J', 'K', 'L', 'Ö', 'Ä'],
['{shift}', 'Z', 'X', 'C', 'V', 'B', 'N', 'M', '{backspace}'],
['{numeric}', '{space}', '{done}'],
],
text_numeric: [
['1', '2', '3', '4', '5', '6', '7', '8', '9', '0'],
['-', '/', ':', ';', '(', ')', '$', '&', '@', '"'],
['{symbolic}', '.', ',', '?', '!', "'", '{backspace}'],
['{alphabetic}', '{space}', '{done}'],
],
text_symbolic: [
['[', ']', '{', '}', '#', '%', '^', '*', '+', '='],
['_', '\\', '|', '~', '<', '>', '€', '£', '¥', '•'],
['{numeric}', '.', ',', '?', '!', "'", '{backspace}'],
['{alphabetic}', '{space}', '{done}'],
],
search_alphabetic: [
['q', 'w', 'e', 'r', 't', 'y', 'u', 'i', 'o', 'p', 'å'],
['a', 's', 'd', 'f', 'g', 'h', 'j', 'k', 'l', 'ö', 'ä'],
['{shift}', 'z', 'x', 'c', 'v', 'b', 'n', 'm', '{backspace}'],
['{numeric}', '{space}', '{done}'],
],
search_shift: [
['Q', 'W', 'E', 'R', 'T', 'Y', 'U', 'I', 'O', 'P', 'Å'],
['A', 'S', 'D', 'F', 'G', 'H', 'J', 'K', 'L', 'Ö', 'Ä'],
['{shift}', 'Z', 'X', 'C', 'V', 'B', 'N', 'M', '{backspace}'],
['{numeric}', '{space}', '{done}'],
],
search_numeric: [
['1', '2', '3', '4', '5', '6', '7', '8', '9', '0'],
['-', '/', ':', ';', '(', ')', '$', '&', '@', '"'],
['{symbolic}', '.', ',', '?', '!', "'", '{backspace}'],
['{alphabetic}', '{space}', '{done}'],
],
search_symbolic: [
['[', ']', '{', '}', '#', '%', '^', '*', '+', '='],
['_', '\\', '|', '~', '<', '>', '€', '£', '¥', '•'],
['{numeric}', '.', ',', '?', '!', "'", '{backspace}'],
['{alphabetic}', '{space}', '{done}'],
],
email_alphabetic: [
['q', 'w', 'e', 'r', 't', 'y', 'u', 'i', 'o', 'p', 'å'],
['a', 's', 'd', 'f', 'g', 'h', 'j', 'k', 'l', 'ö', 'ä'],
['{shift}', 'z', 'x', 'c', 'v', 'b', 'n', 'm', '{backspace}'],
['{numeric}', '@', '{space}', '.', '{done}'],
],
email_shift: [
['Q', 'W', 'E', 'R', 'T', 'Y', 'U', 'I', 'O', 'P', 'Å'],
['A', 'S', 'D', 'F', 'G', 'H', 'J', 'K', 'L', 'Ö', 'Ä'],
['{shift}', 'Z', 'X', 'C', 'V', 'B', 'N', 'M', '{backspace}'],
['{numeric}', '@', '{space}', '.', '{done}'],
],
email_numeric: [
['1', '2', '3', '4', '5', '6', '7', '8', '9', '0'],
['$', '!', '~', '&', '=', '#', '[', ']'],
['{symbolic}', '.', '_', '-', '+', '{backspace}'],
['{alphabetic}', '@', '{space}', '.', '{done}'],
],
email_symbolic: [
['`', '|', '{', '}', '?', '%', '^', '*', '/', "'"],
['$', '!', '~', '&', '=', '#', '[', ']'],
['{numeric}', '.', '_', '-', '+', '{backspace}'],
['{alphabetic}', '@', '{space}', '.', '{done}'],
],
url_alphabetic: [
['q', 'w', 'e', 'r', 't', 'y', 'u', 'i', 'o', 'p', 'å'],
['a', 's', 'd', 'f', 'g', 'h', 'j', 'k', 'l', 'ö', 'ä'],
['{shift}', 'z', 'x', 'c', 'v', 'b', 'n', 'm', '{backspace}'],
['{numeric}', '/', '.com', '.', '{done}'],
],
url_shift: [
['Q', 'W', 'E', 'R', 'T', 'Y', 'U', 'I', 'O', 'P', 'Å'],
['A', 'S', 'D', 'F', 'G', 'H', 'J', 'K', 'L', 'Ö', 'Ä'],
['{shift}', 'Z', 'X', 'C', 'V', 'B', 'N', 'M', '{backspace}'],
['{numeric}', '/', '.com', '.', '{done}'],
],
url_numeric: [
['1', '2', '3', '4', '5', '6', '7', '8', '9', '0'],
['@', '&', '%', '?', ',', '=', '[', ']'],
['{symbolic}', '_', ':', '-', '+', '{backspace}'],
['{alphabetic}', '/', '.com', '.', '{done}'],
],
url_symbolic: [
['1', '2', '3', '4', '5', '6', '7', '8', '9', '0'],
['*', '$', '#', '!', "'", '^', '[', ']'],
['{numeric}', '~', ';', '(', ')', '{backspace}'],
['{alphabetic}', '/', '.com', '.', '{done}'],
],
numeric_default: [
['1', '2', '3'],
['4', '5', '6'],
['7', '8', '9'],
['0', '{backspace}'],
],
decimal_default: [
['1', '2', '3'],
['4', '5', '6'],
['7', '8', '9'],
['.', '0', '{backspace}'],
],
tel_default: [
['1', '2', '3', '*'],
['4', '5', '6', '#'],
['7', '8', '9', '+'],
['0', '{backspace}'],
],
};
const display = {
'{done}': fnDisplay.DONE,
'{shift}': fnDisplay.SHIFT,
'{backspace}': fnDisplay.BACKSPACE,
'{space}': fnDisplay.SPACE,
'{alphabetic}': 'ABC',
'{numeric}': '123',
'{symbolic}': '#+=',
};
const locale = {
code: 'sv-SE',
dir: 'ltr',
layouts: layouts,
display: display,
};
/** Injection token that can be used to specify the locale data for the keyboard. */
const NGX_TOUCH_KEYBOARD_LOCALE = new InjectionToken('NGX_TOUCH_KEYBOARD_LOCALE', {
providedIn: 'root',
factory: NGX_TOUCH_KEYBOARD_LOCALE_FACTORY,
});
/** @docs-private */
function NGX_TOUCH_KEYBOARD_LOCALE_FACTORY() {
return locale$5;
}
class NgxTouchKeyboardComponent {
constructor() {
this._sanitizer = inject(DomSanitizer);
this._elementRef = inject((ElementRef));
this._defaultLocale = inject(NGX_TOUCH_KEYBOARD_LOCALE);
this.locale = this._defaultLocale;
this.layoutMode = 'text';
this.layoutName = 'alphabetic';
this.debug = false;
this.closePanel = output();
this._activeButtonClass = 'active';
this._caretPosition = null;
this._caretPositionEnd = null;
/**
* Check whether the button is a standard button
*/
this.isStandardButton = (button) => button && !(button[0] === '{' && button[button.length - 1] === '}');
}
// -----------------------------------------------------------------------------------------------------
// @ Accessors
// -----------------------------------------------------------------------------------------------------
/**
* Getter for maxLength
*/
get maxLength() {
return this._activeInputElement?.maxLength ?? -1;
}
/**
* Getter for type of input
*/
get isTextarea() {
return this._activeInputElement?.type === 'textarea';
}
// -----------------------------------------------------------------------------------------------------
// @ Decorated methods
// -----------------------------------------------------------------------------------------------------
/**
* On keyup
*/
handleKeyUp(event) {
if (event.isTrusted) {
this._caretEventHandler(event);
this._handleHighlightKeyUp(event);
}
}
/**
* On keydown
*/
handleKeyDown(event) {
if (event.isTrusted) {
this._handleHighlightKeyDown(event);
}
}
/**
* On pointerup (mouseup or touchend)
*/
handleMouseUp(event) {
this._caretEventHandler(event);
}
/**
* On select
*/
handleSelect(event) {
this._caretEventHandler(event);
}
/**
* On selectionchange
*/
handleSelectionChange(event) {
this._caretEventHandler(event);
}
// -----------------------------------------------------------------------------------------------------
// @ Public methods
// -----------------------------------------------------------------------------------------------------
/**
* Set locale
*
* @param value Locale
*/
setLocale(value = this._defaultLocale) {
if (!(value && value.layouts)) {
throw new Error('Locale is not defined');
}
this.locale = value;
}
/**
* Set active input
*
* @param input Input native element
*/
setActiveInput(input) {
this._activeInputElement = input;
/**
* Tracking keyboard layout
*/
const inputMode = this._activeInputElement?.inputMode;
if (inputMode && ['text', 'search', 'email', 'url', 'numeric', 'decimal', 'tel'].some((i) => i === inputMode)) {
this.layoutMode = inputMode;
}
else {
this.layoutMode = 'text';
}
if (inputMode && ['numeric', 'decimal', 'tel'].some((i) => i === inputMode)) {
this.layoutName = 'default';
}
else {
this.layoutName = 'alphabetic';
}
if (this.debug) {
console.log('Locale:', `${this.locale.code}`);
console.log('Layout:', `${this.layoutMode}_${this.layoutName}`);
}
/**
* we must ensure caretPosition doesn't persist once reactivated.
*/
this._setCaretPosition(this._activeInputElement.selectionStart, this._activeInputElement.selectionEnd);
if (this.debug) {
console.log('Caret start at:', this._caretPosition, this._caretPositionEnd);
}
// And set focus to input
this._focusActiveInput();
}
/**
* Retrieve button type
*
* @param button The button's layout name
* @return The button type
*/
getButtonType(button) {
return this.isStandardButton(button) ? 'standard-key' : 'function-key';
}
/**
* Adds default classes to a given button
*
* @param button The button's layout name
* @return The classes to be added to the button
*/
getButtonClass(button) {
const buttonTypeClass = this.getButtonType(button);
const buttonWithoutBraces = button.replace('{', '').replace('}', '');
let buttonNormalized = '';
if (buttonTypeClass !== 'standard-key')
buttonNormalized = `${buttonWithoutBraces}-key`;
return `${buttonTypeClass} ${buttonNormalized}`;
}
/**
* Returns the display (label) name for a given button
*
* @param button The button's layout name
* @return The display name to be show to the button
*/
getButtonDisplayName(button) {
return this._sanitizer.bypassSecurityTrustHtml(this.locale.display[button] || button);
}
/**
* Handles clicks made to keyboard buttons
*
* @param button The button layout name.
* @param event The button event.
*/
handleButtonPress(button, e) {
if (this.debug) {
console.log('Key press:', button);
}
if (button === fnButton.SHIFT) {
this.layoutName = this.layoutName === 'alphabetic' ? 'shift' : 'alphabetic';
return;
}
else if (button === fnButton.DONE) {
this.closePanel.emit();
return;
}
const commonParams = [this._caretPosition || 0, this._caretPositionEnd || 0, true];
let output = this._activeInputElement?.value || '';
// Handel functional button
if (!this.isStandardButton(button)) {
// Handel BACKSPACE
if (button === fnButton.BACKSPACE) {
output = this._removeAt(output, ...commonParams);
}
// Handel SPACE
else if (button === fnButton.SPACE) {
output = this._addStringAt(output, ' ', ...commonParams);
}
// Handel TAB
else if (button === fnButton.TAB) {
output = this._addStringAt(output, '\t', ...commonParams);
}
// Handel ENTER
else if (button === fnButton.ENTER) {
if (this.isTextarea) {
output = this._addStringAt(output, '\n', ...commonParams);
}
}
// Handel LAYOUT
else {
this.layoutName = button.substring(1, button.length - 1);
return;
}
}
// Handel standard button
else {
output = this._addStringAt(output, button, ...commonParams);
}
if (this._activeInputElement) {
this._activeInputElement.value = output;
if (this.debug) {
console.log('Caret at:', this._caretPosition, this._caretPositionEnd, 'Button', e);
}
}
this._dispatchEvents(button);
}
/**
* Handles button down
*
* @param button The button layout name.
* @param event The button event.
*/
handleButtonDown(button, e) {
if (this.debug) {
console.log('Key down:', button);
}
if (e) {
/**
* Handle event options
*/
e.preventDefault();
e.stopPropagation();
}
/**
* Add active class
*/
this._setActiveButton(button);
if (this._holdInteractionTimeout)
clearTimeout(this._holdInteractionTimeout);
if (this._holdTimeout)
clearTimeout(this._holdTimeout);
this._isMouseHold = true;
/**
* Time to wait until a key hold is detected
*/
this._holdTimeout = window.setTimeout(() => {
if (this._isMouseHold &&
((!button.includes('{') && !button.includes('}')) || button === fnButton.BACKSPACE || button === fnButton.SPACE)) {
if (this.debug) {
console.log('Button hold:', button);
}
this.handleButtonHold(button);
}
clearTimeout(this._holdTimeout);
}, 500);
/**
* Handel button Click after button down
*/
this.handleButtonPress(button, e);
}
/**
* Handles button up
*
* @param button The button layout name.
* @param event The button event.
*/
handleButtonUp(button, e) {
if (this.debug) {
console.log('Key up:', button);
}
if (e) {
/**
* Handle event options
*/
e.preventDefault();
e.stopPropagation();
}
/**
* Remove active class
*/
this._removeActiveButton();
this._isMouseHold = false;
if (this._holdInteractionTimeout)
clearTimeout(this._holdInteractionTimeout);
}
/**
* Handles button hold
*/
handleButtonHold(button) {
if (this._holdInteractionTimeout)
clearTimeout(this._holdInteractionTimeout);
/**
* Timeout dictating the speed of key hold iterations
*/
this._holdInteractionTimeout = window.setTimeout(() => {
if (this._isMouseHold) {
this.handleButtonPress(button);
this.handleButtonHold(button);
}
else {
clearTimeout(this._holdInteractionTimeout);
}
}, 100);
}
// -----------------------------------------------------------------------------------------------------
// @ Private methods
// -----------------------------------------------------------------------------------------------------
/**
* Changes the internal caret position
*
* @private
* @param position The caret's start position
* @param positionEnd The caret's end position
*/
_setCaretPosition(position, endPosition = position) {
this._caretPosition = position;
this._caretPositionEnd = endPosition;
}
/**
* Moves the cursor position by a given amount
*
* @private
* @param length Represents by how many characters the input should be moved
* @param minus Whether the cursor should be moved to the left or not.
*/
_updateCaretPos(length, minus = false) {
const newCaretPos = this._updateCaretPosAction(length, minus);
this._setCaretPosition(newCaretPos);
// Scroll to bottom
setTimeout(() => {
this._activeInputElement?.scrollTo({
top: this._activeInputElement.scrollHeight,
});
});
}
/**
* Action method of updateCaretPos
*
* @private
* @param length Represents by how many characters the input should be moved
* @param minus Whether the cursor should be moved to the left or not.
*/
_updateCaretPosAction(length, minus = false) {
let caretPosition = this._caretPosition;
if (caretPosition != null) {
if (minus) {
if (caretPosition > 0)
caretPosition = caretPosition - length;
}
else {
caretPosition = caretPosition + length;
}
}
return caretPosition;
}
/**
* Removes an amount of characters before a given position
*
* @private
* @param source The source input
* @param position The (cursor) position from where the characters should be removed
* @param moveCaret Whether to update input cursor
*/
_removeAt(source, position = source.length, positionEnd = source.length, moveCaret = false) {
if (position === 0 && positionEnd === 0) {
return source;
}
let output;
if (position === positionEnd) {
let prevTwoChars;
let emojiMatched;
const emojiMatchedReg = /([\uD800-\uDBFF][\uDC00-\uDFFF])/g;
/**
* Emojis are made out of two characters, so we must take a custom approach to trim them.
* For more info: https://mathiasbynens.be/notes/javascript-unicode
*/
if (position && position >= 0) {
prevTwoChars = source.substring(position - 2, position);
emojiMatched = prevTwoChars.match(emojiMatchedReg);
if (emojiMatched) {
output = source.substr(0, position - 2) + source.substr(position);
if (moveCaret)
this._updateCaretPos(2, true);
}
else {
output = source.substr(0, position - 1) + source.substr(position);
if (moveCaret)
this._updateCaretPos(1, true);
}
}
else {
prevTwoChars = source.slice(-2);
emojiMatched = prevTwoChars.match(emojiMatchedReg);
if (emojiMatched) {
output = source.slice(0, -2);
if (moveCaret)
this._updateCaretPos(2, true);
}
else {
output = source.slice(0, -1);
if (moveCaret)
this._updateCaretPos(1, true);
}
}
}
else {
output = source.slice(0, position) + source.slice(positionEnd);
if (moveCaret) {
this._setCaretPosition(position);
}
}
return output;
}
/**
* Adds a string to the input at a given position
*
* @private
* @param source The source input
* @param str The string to add
* @param position The (cursor) position where the string should be added
* @param moveCaret Whether to update virtual-keyboard cursor
*/
_addStringAt(source, str, position = source.length, positionEnd = source.length, moveCaret = false) {
if (this.maxLength !== -1 && source.length >= this.maxLength) {
return source;
}
let output;
if (!position && position !== 0) {
output = source + str;
}
else {
output = [source.slice(0, position), str, source.slice(positionEnd)].join('');
if (moveCaret)
this._updateCaretPos(str.length, false);
}
return output;
}
/**
* Method to dispatch necessary keyboard events to current input element.
* @see https://w3c.github.io/uievents/tools/key-event-viewer.html
*
* @param button
*/
_dispatchEvents(button) {
let key, code;
if (button.includes('{') && button.includes('}')) {
// Capitalize name
key = button.slice(1, button.length - 1).toLowerCase();
key = key.charAt(0).toUpperCase() + key.slice(1);
code = key;
}
else {
key = button;
code = Number.isInteger(Number(button)) ? `Digit${button}` : `Key${button.toUpperCase()}`;
}
const eventInit = {
bubbles: true,
cancelable: true,
shiftKey: this.layoutName == 'shift',
key: key,
code: code,
location: 0,
};
// Simulate all needed events on base element
this._activeInputElement?.dispatchEvent(new KeyboardEvent('keydown', eventInit));
this._activeInputElement?.dispatchEvent(new KeyboardEvent('keypress', eventInit));
this._activeInputElement?.dispatchEvent(new Event('input', { bubbles: true }));
this._activeInputElement?.dispatchEvent(new KeyboardEvent('keyup', eventInit));
// And set focus to input
this._focusActiveInput();
}
/**
* Called when an event that warrants a cursor position update is triggered
*
* @private
* @param event
*/
_caretEventHandler(event) {
let targetTagName = '';
if (event.target.tagName) {
targetTagName = event.target.tagName.toLowerCase();
}
const isTextInput = targetTagName === 'textarea' ||
(targetTagName === 'input' && ['text', 'search', 'email', 'password', 'url', 'tel'].includes(event.target.type));
const isKeyboard = event.target === this._elementRef.nativeElement ||
(event.target && this._elementRef.nativeElement.contains(event.target));
if (isTextInput && this._activeInputElement == event.target) {
/**
* Tracks current cursor position
* As keys are pressed, text will be added/removed at that position within the input.
*/
this._setCaretPosition(event.target.selectionStart, event.target.selectionEnd);
if (this.debug) {
console.log('Caret at:', this._caretPosition, this._caretPositionEnd, event && event.target.tagName.toLowerCase(), event);
}
}
else if (event.type === 'pointerup' && this._activeInputElement === document.activeElement) {
if (this._isMouseHold) {
this.handleButtonUp('');
}
return;
}
else if (!isKeyboard && event?.type !== 'selectionchange') {
/**
* we must ensure caretPosition doesn't persist once reactivated.
*/
this._setCaretPosition(null);
if (this.debug) {
console.log(`Caret position reset due to "${event?.type}" event`, event);
}
/**
* Close panel
*/
this.closePanel.emit();
}
}
/**
* Focus to input
*
* @private
*/
_focusActiveInput() {
this._activeInputElement?.focus();
this._activeInputElement?.setSelectionRange(this._caretPosition, this._caretPositionEnd);
}
/**
* Handel highlight on key down
*
* @private
* @param event The KeyboardEvent
*/
_handleHighlightKeyDown(event) {
const buttonPressed = this._getKeyboardLayoutKey(event);
/**
* Add active class
*/
this._setActiveButton(buttonPressed);
}
/**
* Handel highlight on key up
*
* @private
* @param event The KeyboardEvent
*/
_handleHighlightKeyUp(event) {
const buttonPressed = this._getKeyboardLayoutKey(event);
/**
* Remove active class
*/
this._removeActiveButton(buttonPressed);
}
/**
* Transforms a KeyboardEvent's "key.code" string into a virtual-keyboard layout format
*
* @private
* @param event The KeyboardEvent
*/
_getKeyboardLayoutKey(event) {
let output = '';
const keyId = event.code || event.key;
if (keyId?.includes('Space') ||
keyId?.includes('Numpad') ||
keyId?.includes('Backspace') ||
keyId?.includes('CapsLock') ||
keyId?.includes('Meta')) {
output = `{${event.code}}` || '';
}
else if (keyId?.includes('Control') || keyId?.includes('Shift') || keyId?.includes('Alt')) {
output = `{${event.key}}` || '';
}
else {
output = event.key || '';
}
return output.length > 1 ? output?.toLowerCase() : output;
}
/**
* Set active class in button
*
* @param buttonName
*/
_setActiveButton(buttonName) {
const node = this._elementRef.nativeElement.getElementsByTagName('button').namedItem(buttonName);
if (node && node.classList) {
node.classList.add(this._activeButtonClass);
}
}
/**
* Remove active button
*
* @param buttonName
*/
_removeActiveButton(buttonName) {
const nodes = this._elementRef.nativeElement.getElementsByTagName('button');
if (buttonName) {
const node = nodes.namedItem(buttonName);
if (node && node.classList) {
node.classList.remove(this._activeButtonClass);
}
}
else {
for (let i = 0; i < nodes.length; i++) {
nodes[i].classList.remove(this._activeButtonClass);
}
}
}
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.0", ngImport: i0, type: NgxTouchKeyboardComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.0", type: NgxTouchKeyboardComponent, selector: "ngx-touch-keyboard", outputs: { closePanel: "closePanel" }, host: { listeners: { "window:keyup": "handleKeyUp($event)", "window:keydown": "handleKeyDown($event)", "window:pointerup": "handleMouseUp($event)", "window:select": "handleSelect($event)", "window:selectionchange": "handleSelectionChange($event)" } }, ngImport: i0, template: "<div class=\"touch-keyboard\" [ngClass]=\"'layout-' + layoutMode + '-' + layoutName\">\r\n @for (row of locale.layouts[layoutMode + '_' + layoutName]; track row[0]; let rowIndex = $index) {\r\n <div class=\"touch-keyboard-row\">\r\n @for (key of row; track key) {\r\n <button\r\n [name]=\"key\"\r\n [dir]=\"locale.dir\"\r\n class=\"touch-keyboard-key\"\r\n [ngClass]=\"[getButtonClass(key)]\"\r\n [attr.data-layout]=\"layoutMode\"\r\n (pointerup)=\"handleButtonUp(key, $event)\"\r\n (pointerdown)=\"handleButtonDown(key, $event)\"\r\n (pointercancel)=\"handleButtonUp(key, $event)\"\r\n [innerHtml]=\"getButtonDisplayName(key)\"\r\n ></button>\r\n }\r\n </div>\r\n }\r\n</div>\r\n", styles: [".cdk-overlay-container,.cdk-global-overlay-wrapper{pointer-events:none;top:0;left:0;height:100%;width:100%}.cdk-overlay-container{position:fixed;z-index:1000}.cdk-overlay-container:empty{display:none}.cdk-global-overlay-wrapper{display:flex;position:absolute;z-index:1000}.cdk-overlay-pane{position:absolute;pointer-events:auto;box-sizing:border-box;z-index:1000;display:flex;max-width:100%;max-height:100%}.cdk-overlay-backdrop{position:absolute;inset:0;z-index:1000;pointer-events:auto;-webkit-tap-highlight-color:rgba(0,0,0,0);transition:opacity .4s cubic-bezier(.25,.8,.25,1);opacity:0}.cdk-overlay-backdrop.cdk-overlay-backdrop-showing{opacity:1}.cdk-high-contrast-active .cdk-overlay-backdrop.cdk-overlay-backdrop-showing{opacity:.6}.cdk-overlay-dark-backdrop{background:#00000052}.cdk-overlay-transparent-backdrop{transition:visibility 1ms linear,opacity 1ms linear;visibility:hidden;opacity:1}.cdk-overlay-transparent-backdrop.cdk-overlay-backdrop-showing{opacity:0;visibility:visible}.cdk-overlay-backdrop-noop-animation{transition:none}.cdk-overlay-connected-position-bounding-box{position:absolute;z-index:1000;display:flex;flex-direction:column;min-width:1px;min-height:1px}.cdk-global-scrollblock{position:fixed;width:100%;overflow-y:scroll}:root{--tk-color-text: #27272a;--tk-background: rgba(238, 238, 238, .87);--tk-background-button: rgba(255, 255, 255, .96);--tk-background-button-fn: rgba(255, 255, 255, .5);--tk-background-button-active: rgba(0, 0, 0, .04)}.dark{--tk-color-text: #ffffff;--tk-background: rgba(33, 33, 33, .87);--tk-background-button: rgba(66, 66, 66, .96);--tk-background-button-fn: rgba(66, 66, 66, .5);--tk-background-button-active: rgba(255, 255, 255, .2)}ngx-touch-keyboard{width:100%;padding:.25rem .25rem .375rem;border-radius:.375rem;touch-action:manipulation;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;display:flex;justify-content:center;-webkit-backdrop-filter:blur(8px);backdrop-filter:blur(8px);background:var(--tk-background);box-shadow:0 3px 1px -2px #0003,0 2px 2px #00000024,0 1px 5px #0000001f}.ngx-touch-keyboard-fullScreen>ngx-touch-keyboard{border-radius:0}.touch-keyboard{flex:1 1 auto;max-width:840px}.touch-keyboard .touch-keyboard-row{display:flex;flex-direction:row}.touch-keyboard .touch-keyboard-row:not(:last-child){margin-bottom:.25rem}.touch-keyboard .touch-keyboard-key{width:20px;box-sizing:border-box;position:relative;-webkit-user-select:none;user-select:none;cursor:pointer;outline:none;border:none;text-align:center;margin:0;line-height:32px;padding:.25rem;border-radius:.375rem;font-size:14px;font-weight:500;display:flex;flex-grow:1;align-items:center;justify-content:center;color:var(--tk-color-text);background-color:var(--tk-background-button);box-shadow:0 3px 1px -2px #0003,0 2px 2px #00000024,0 1px 5px #0000001f}.touch-keyboard .touch-keyboard-key>svg{fill:var(--tk-color-text)}.touch-keyboard .touch-keyboard-key.function-key:not(.space-key){background-color:var(--tk-background-button-fn)}.touch-keyboard .touch-keyboard-key.active{background-color:var(--tk-background-button-active)!important}.touch-keyboard .touch-keyboard-key.alphabetic-key,.touch-keyboard .touch-keyboard-key.backspace-key,.touch-keyboard .touch-keyboard-key.shift-key,.touch-keyboard .touch-keyboard-key.numeric-key,.touch-keyboard .touch-keyboard-key.symbolic-key,.touch-keyboard .touch-keyboard-key.language-key,.touch-keyboard .touch-keyboard-key.enter-key,.touch-keyboard .touch-keyboard-key.done-key{max-width:4rem}.touch-keyboard .touch-keyboard-key.space-key{min-width:40%}.touch-keyboard .touch-keyboard-key[data-layout=numeric],.touch-keyboard .touch-keyboard-key[data-layout=decimal],.touch-keyboard .touch-keyboard-key[data-layout=tel]{width:33%!important;max-width:none!important}.touch-keyboard .touch-keyboard-key:not(:last-child){margin-right:.25rem}@media (min-width: 600px){.touch-keyboard .touch-keyboard-key.alphabetic-key,.touch-keyboard .touch-keyboard-key.backspace-key,.touch-keyboard .touch-keyboard-key.shift-key,.touch-keyboard .touch-keyboard-key.numeric-key,.touch-keyboard .touch-keyboard-key.symbolic-key,.touch-keyboard .touch-keyboard-key.language-key,.touch-keyboard .touch-keyboard-key.enter-key,.touch-keyboard .touch-keyboard-key.done-key{max-width:6rem}}\n"], dependencies: [{ kind: "directive", type: i1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i2.Dir, selector: "[dir]", inputs: ["dir"], outputs: ["dirChange"], exportAs: ["dir"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.0", ngImport: i0, type: NgxTouchKeyboardComponent, decorators: [{
type: Component,
args: [{ selector: 'ngx-touch-keyboard', encapsulation: ViewEncapsulation.None, changeDetection: ChangeDetectionStrategy.OnPush, template: "<div class=\"touch-keyboard\" [ngClass]=\"'layout-' + layoutMode + '-' + layoutName\">\r\n @for (row of locale.layouts[layoutMode + '_' + layoutName]; track row[0]; let rowIndex = $index) {\r\n <div class=\"touch-keyboard-row\">\r\n @for (key of row; track key) {\r\n <button\r\n [name]=\"key\"\r\n [dir]=\"locale.dir\"\r\n class=\"touch-keyboard-key\"\r\n [ngClass]=\"[getButtonClass(key)]\"\r\n [attr.data-layout]=\"layoutMode\"\r\n (pointerup)=\"handleButtonUp(key, $event)\"\r\n (pointerdown)=\"handleButtonDown(key, $event)\"\r\n (pointercancel)=\"handleButtonUp(key, $event)\"\r\n [innerHtml]=\"getButtonDisplayName(key)\"\r\n ></button>\r\n }\r\n </div>\r\n }\r\n</div>\r\n", styles: [".cdk-overlay-container,.cdk-global-overlay-wrapper{pointer-events:none;top:0;left:0;height:100%;width:100%}.cdk-overlay-container{position:fixed;z-index:1000}.cdk-overlay-container:empty{display:none}.cdk-global-overlay-wrapper{display:flex;position:absolute;z-index:1000}.cdk-overlay-pane{position:absolute;pointer-events:auto;box-sizing:border-box;z-index:1000;display:flex;max-width:100%;max-height:100%}.cdk-overlay-backdrop{position:absolute;inset:0;z-index:1000;pointer-events:auto;-webkit-tap-highlight-color:rgba(0,0,0,0);transition:opacity .4s cubic-bezier(.25,.8,.25,1);opacity:0}.cdk-overlay-backdrop.cdk-overlay-backdrop-showing{opacity:1}.cdk-high-contrast-active .cdk-overlay-backdrop.cdk-overlay-backdrop-showing{opacity:.6}.cdk-overlay-dark-backdrop{background:#00000052}.cdk-overlay-transparent-backdrop{transition:visibility 1ms linear,opacity 1ms linear;visibility:hidden;opacity:1}.cdk-overlay-transparent-backdrop.cdk-overlay-backdrop-showing{opacity:0;visibility:visible}.cdk-overlay-backdrop-noop-animation{transition:none}.cdk-overlay-connected-position-bounding-box{position:absolute;z-index:1000;display:flex;flex-direction:column;min-width:1px;min-height:1px}.cdk-global-scrollblock{position:fixed;width:100%;overflow-y:scroll}:root{--tk-color-text: #27272a;--tk-background: rgba(238, 238, 238, .87);--tk-background-button: rgba(255, 255, 255, .96);--tk-background-button-fn: rgba(255, 255, 255, .5);--tk-background-button-active: rgba(0, 0, 0, .04)}.dark{--tk-color-text: #ffffff;--tk-background: rgba(33, 33, 33, .87);--tk-background-button: rgba(66, 66, 66, .96);--tk-background-button-fn: rgba(66, 66, 66, .5);--tk-background-button-active: rgba(255, 255, 255, .2)}ngx-touch-keyboard{width:100%;padding:.25rem .25rem .375rem;border-radius:.375rem;touch-action:manipulation;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;display:flex;justify-content:center;-webkit-backdrop-filter:blur(8px);backdrop-filter:blur(8px);background:var(--tk-background);box-shadow:0 3px 1px -2px #0003,0 2px 2px #00000024,0 1px 5px #0000001f}.ngx-touch-keyboard-fullScreen>ngx-touch-keyboard{border-radius:0}.touch-keyboard{flex:1 1 auto;max-width:840px}.touch-keyboard .touch-keyboard-row{display:flex;flex-direction:row}.touch-keyboard .touch-keyboard-row:not(:last-child){margin-bottom:.25rem}.touch-keyboard .touch-keyboard-key{width:20px;box-sizing:border-box;position:relative;-webkit-user-select:none;user-select:none;cursor:pointer;outline:none;border:none;text-align:center;margin:0;line-height:32px;padding:.25rem;border-radius:.375rem;font-size:14px;font-weight:500;display:flex;flex-grow:1;align-items:center;justify-content:center;color:var(--tk-color-text);background-color:var(--tk-background-button);box-shadow:0 3px 1px -2px #0003,0 2px 2px #00000024,0 1px 5px #0000001f}.touch-keyboard .touch-keyboard-key>svg{fill:var(--tk-color-text)}.touch-keyboard .touch-keyboard-key.function-key:not(.space-key){background-color:var(--tk-background-button-fn)}.touch-keyboard .touch-keyboard-key.active{background-color:var(--tk-background-button-active)!important}.touch-keyboard .touch-keyboard-key.alphabetic-key,.touch-keyboard .touch-keyboard-key.backspace-key,.touch-keyboard .touch-keyboard-key.shift-key,.touch-keyboard .touch-keyboard-key.numeric-key,.touch-keyboard .touch-keyboard-key.symbolic-key,.touch-keyboard .touch-keyboard-key.language-key,.touch-keyboard .touch-keyboard-key.enter-key,.touch-keyboard .touch-keyboard-key.done-key{max-width:4rem}.touch-keyboard .touch-keyboard-key.space-key{min-width:40%}.touch-keyboard .touch-keyboard-key[data-layout=numeric],.touch-keyboard .touch-keyboard-key[data-layout=decimal],.touch-keyboard .touch-keyboard-key[data-layout=tel]{width:33%!important;max-width:none!important}.touch-keyboard .touch-keyboard-key:not(:last-child){margin-right:.25rem}@media (min-width: 600px){.touch-keyboard .touch-keyboard-key.alphabetic-key,.touch-keyboard .touch-keyboard-key.backspace-key,.touch-keyboard .touch-keyboard-key.shift-key,.touch-keyboard .touch-keyboard-key.numeric-key,.touch-keyboard .touch-keyboard-key.symbolic-key,.touch-keyboard .touch-keyboard-key.language-key,.touch-keyboard .touch-keyboard-key.enter-key,.touch-keyboard .touch-keyboard-key.done-key{max-width:6rem}}\n"] }]
}], propDecorators: { handleKeyUp: [{
type: HostListener,
args: ['window:keyup', ['$event']]
}], handleKeyDown: [{
type: HostListener,
args: ['window:keydown', ['$event']]
}], handleMouseUp: [{
type: HostListener,
args: ['window:pointerup', ['$event']]
}], handleSelect: [{
type: HostListener,
args: ['window:select', ['$event']]
}], handleSelectionChange: [{
type: HostListener,
args: ['window:selectionchange', ['$event']]
}] } });
/**
* Directive applied to an element to make it usable as an origin for an keyboard using a
* ConnectedPositionStrategy.
*/
class NgxTouchKeyboardOrigin {
constructor() {
this.elementRef = inject(ElementRef);
}
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.0", ngImport: i0, type: NgxTouchKeyboardOrigin, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "18.2.0", type: NgxTouchKeyboardOrigin, selector: "[ngxTouchKeyboardOrigin]", exportAs: ["ngxTouchKeyboardOrigin"], ngImport: i0 }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.0", ngImport: i0, type: NgxTouchKeyboardOrigin, decorators: [{
type: Directive,
args: [{
selector: '[ngxTouchKeyboardOrigin]',
exportAs: 'ngxTouchKeyboardOrigin',
}]
}] });
/**
* This directive provides methods to open, close, and toggle the touch keyboard panel.
* It also handles the creation and configuration of the overlay used to display the keyboard.
*/
class NgxTouchKeyboardDirective {
/**
* constructor
*/
constructor() {
this._overlay = inject(Overlay);
this._elementRef = inject((ElementRef));
this.open = model(false, {
alias: 'ngxTouchKeyboardOpen',
});
this.locale = input(undefined, {
alias: 'ngxTouchKeyboardLocale',
});
this.debugMode = input(false, {
alias: 'ngxTouchKeyboardDebug',
transform: booleanAttribute,
});
this.fullScreenMode = input(false, {
alias: 'ngxTouchKeyboardFullScreen',
transform: booleanAttribute,
});
this.origin = input(null, {
alias: 'ngxConnectedTouchKeyboardOrigin',
});
effect(() => {
this.open() ? this.openPanel() : this.closePanel();
});
}
// -----------------------------------------------------------------------------------------------------
// @ Lifecycle hooks
// -----------------------------------------------------------------------------------------------------
/**
* On destroy
*/
ngOnDestroy() {
// Dispose the overlay
if (this._overlayRef) {
this._overlayRef.dispose();
}
}
// -----------------------------------------------------------------------------------------------------
// @ Public methods
// -----------------------------------------------------------------------------------------------------
/**
* Open keyboard panel
*/
openPanel() {
// return if panel is attached
if (this._overlayRef?.hasAttached()) {
return;
}
// Create the overlay if it doesn't exist
if (!this._overlayRef) {
this._createOverlay();
}
// Set overlay class
if (this.fullScreenMode()) {
this._overlayRef.addPanelClass('ngx-touch-keyboard-fullScreen');
}
else {
this._overlayRef.removePanelClass('ngx-touch-keyboard-fullScreen');
}
// Update position the overlay
this._overlayRef.updatePositionStrategy(this._getPositionStrategy(this.fullScreenMode()));
// Update size the overlay
this._overlayRef.updateSize(this._getOverlaySize(this.fullScreenMode()));
// Attach the portal to the overlay
this._panelRef = this._overlayRef.attach(new ComponentPortal(NgxTouchKeyboardComponent));
this._panelRef.instance.debug = this.debugMode();
this._panelRef.instance.setLocale(this.locale());
this._panelRef.instance.setActiveInput(this._elementRef.nativeElement);
this._panelRef.instance.closePanel.subscribe(() => this.closePanel());
this.open.set(true);
}
/**
* Close keyboard panel
*/
closePanel() {
this._overlayRef?.detach();
this.open.set(false);
}
/**
* Toggle keyboard panel
*/
togglePanel() {
if (this.open()) {
this.closePanel();
}
else {
this.openPanel();
}
}
// -----------------------------------------------------------------------------------------------------
// @ Private methods
// -----------------------------------------------------------------------------------------------------
/**
* Create the overlay
*
* @private
*/
_createOverlay() {
this._overlayRef = this._overlay.create({
direction: 'ltr',
hasBackdrop: false,
panelClass: 'ngx-touch-keyboard-overlay-pane',
scrollStrategy: this._overlay.scrollStrategies.noop(),
});
}
/**
* Get position strategy
*
* @param fullscreen
* @private
*/
_getPositionStrategy(fullscreen) {
if (fullscreen) {
return this._overlay.position().global().centerHorizontally().bottom('0');
}
return this._overlay
.position()
.flexibleConnectedTo(this._getOriginElement())
.withLockedPosition()
.withPush()
.withPositions([
{
originX: 'start',
originY: 'bottom',
overlayX: 'start',
overlayY: 'top',
},
{
originX: 'start',
originY: 'top',
overlayX: 'start',
overlayY: 'bottom',
},
{
originX: 'end',
originY: 'bottom',
overlayX: 'end',
overlayY: 'top',
},
{
originX: 'end',
originY: 'top',
overlayX: 'end',
overlayY: 'bottom',
},
]);
}
/**
* Get overlay size
*
* @param fullscreen
* @private
*/
_getOverlaySize(fullscreen) {
if (fullscreen) {
return {
width: '100%',
maxWidth: '100%',
minWidth: '100%',
};
}
return {
width: this._getOriginElement().getBoundingClientRect().width,
maxWidth: this._getOriginElement().getBoundingClientRect().width,
minWidth: '260px',
};
}
/**
* Gets the origin element for the keyboard panel.
*
* @private
*/
_getOriginElement() {
if (this.origin()) {
return this.origin()?.elementRef.nativeElement;
}
const element = this._elementRef.nativeElement;
// Material form field <= v14
if (element.classList.contains('mat-input-element')) {
// Return [mat-form-field-flex] element
return element.parentNode?.parentNode;
}
// Material form field > v14
if (element.classList.contains('mat-mdc-input-element')) {
// Return [mat-mdc-text-field-wrapper] element
return element.parentNode?.parentNode?.parentNode;
}
// Return input
return element;
}
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.0", ngImport: i0, type: NgxTouchKeyboardDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "18.2.0", type: NgxTouchKeyboardDirective, selector: "input[ngxTouchKeyboard], textarea[ngxTouchKeyboard]", inputs: { open: { classPropertyName: "open", publicName: "ngxTouchKeyboardOpen", isSignal: true, isRequired: false, transformFunction: null }, locale: { classPropertyName: "locale", publicName: "ngxTouchKeyboardLocale", isSignal: true, isRequired: false, transformFunction: null }, debugMode: { classPropertyName: "debugMode", publicName: "ngxTouchKeyboardDebug", isSignal: true, isRequired: false, transformFunction: null }, fullScreenMode: { classPropertyName: "fullScreenMode", publicName: "ngxTouchKeyboardFullScreen", isSignal: true, isRequired: false, transformFunction: null }, origin: { classPropertyName: "origin", publicName: "ngxConnectedTouchKeyboardOrigin", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { open: "ngxTouchKeyboardOpenChange" }, exportAs: ["ngxTouchKeyboard"], ngImport: i0 }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.0", ngImport: i0, type: NgxTouchKeyboardDirective, decorators: [{
type: Directive,
args: [{
selector: 'input[ngxTouchKeyboard], textarea[ngxTouchKeyboard]',
exportAs: 'ngxTouchKeyboard',
}]
}], ctorParameters: () => [] });
class NgxTouchKeyboardModule {
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.0", ngImport: i0, type: NgxTouchKeyboardModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule }); }
static { this.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "18.2.0", ngImport: i0, type: NgxTouchKeyboardModule, declarations: [NgxTouchKeyboardOrigin, NgxTouchKeyboardDirective, NgxTouchKeyboardComponent], imports: [NgClass, PortalModule, OverlayModule], exports: [NgxTouchKeyboardOrigin, NgxTouchKeyboardDirective, NgxTouchKeyboardComponent] }); }
static { this.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "18.2.0", ngImport: i0, type: NgxTouchKeyboardModule, imports: [PortalModule, OverlayModule] }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.0", ngImport: i0, type: NgxTouchKeyboardModule, decorators: [{
type: NgModule,
args: [{
imports: [NgClass, PortalModule, OverlayModule],
declarations: [NgxTouchKeyboardOrigin, NgxTouchKeyboardDirective, NgxTouchKeyboardComponent],
exports: [NgxTouchKeyboardOrigin, NgxTouchKeyboardDirective, NgxTouchKeyboardComponent],
}]
}] });
/*
* Public API Surface of ngx-touch-keyboard
*/
/**
* Generated bundle index. Do not edit.
*/
export { NGX_TOUCH_KEYBOARD_LOCALE, NGX_TOUCH_KEYBOARD_LOCALE_FACTORY, NgxTouchKeyboardComponent, NgxTouchKeyboardDirective, NgxTouchKeyboardModule, NgxTouchKeyboardOrigin, locale$6 as enGB, locale$5 as enUS, locale$4 as faIR, fnButton, fnDisplay, locale$3 as heIL, locale$2 as kaGE, locale$1 as ruRU, locale as svSE };
//# sourceMappingURL=ngx-touch-keyboard.mjs.map