UNPKG

ngx-touch-keyboard

Version:
1,794 lines 83.8 kB
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