Compare commits

...

106 Commits

Author SHA1 Message Date
Francisco Hodge
3012ce24e2 Build update 2019-03-07 07:32:24 -05:00
Francisco Hodge
6e54729f46 Tests update 2019-03-07 07:32:15 -05:00
Francisco Hodge
5ab58f2528 Using PointerEvents on browsers that support it 2019-03-07 07:32:07 -05:00
Francisco Hodge
47ddf0b1e8 Build update 2019-03-06 20:26:46 -05:00
Francisco Hodge
74c3bc692f Build update 2019-03-06 20:22:18 -05:00
Francisco Hodge
ae1436a52d Reinstating method bindings 2019-03-06 20:22:09 -05:00
Francisco Hodge
adc1db7a7f Repairing CI, per node bug https://github.com/facebook/jest/issues/8069 2019-03-06 20:13:32 -05:00
Francisco Hodge
ec983bf82b Build update 2019-03-06 20:00:48 -05:00
Francisco Hodge
0d82696868 Tests update 2019-03-06 19:45:08 -05:00
Francisco Hodge
477972f26f Build update 2019-03-06 19:37:49 -05:00
Francisco Hodge
18a3aa9dd5 Added methods beforeRender, beforeFirstRender 2019-03-06 19:33:28 -05:00
Francisco Hodge
c007f7406a Added enabling isMouseHold for delete and backspace buttons 2019-03-06 19:32:46 -05:00
Francisco Hodge
1a53fae5d6 Added isTouchDevice and touch device helper methods 2019-03-06 19:32:03 -05:00
Francisco Hodge
00f8daff3c Added binding of methods 2019-03-06 19:31:07 -05:00
Francisco Hodge
abacee54ee Updated tests 2019-03-06 19:30:06 -05:00
Francisco Hodge
93a45a7c26 Added internal getButtonTheme 2019-03-06 19:29:29 -05:00
Francisco Hodge
c4005e7409 Updated types 2019-03-06 19:28:24 -05:00
Francisco Hodge
ed944d1204 Added autoUseTouchEvents and related touch device fixes 2019-03-06 19:28:12 -05:00
Francisco Hodge
30042d5d72 Disable pointer events for .hg-button span elements 2019-03-06 19:25:55 -05:00
Francisco Hodge
c97945c8b1 Updated dev dependencies 2019-03-02 18:07:43 -05:00
Francisco Hodge
bee709e3b5 Remove max-width for standard buttons 2019-02-25 20:26:30 -05:00
Francisco Hodge
92d1e822a5 Updated dev dependencies 2019-02-23 14:44:13 -05:00
Francisco Hodge
3700bbe144 MIT Licensing 2019-02-23 14:44:05 -05:00
Francisco Hodge
4e4c187cea Updated dev dependencies 2019-02-20 18:17:42 -05:00
Francisco Hodge
974eaf8f5c Updated dev dependencies 2019-02-16 11:12:38 -05:00
Francisco Hodge
70d2cca7ac Adding PrettierPlugin to build process 2019-02-15 21:49:27 -05:00
Francisco Hodge
05976e0e7b Adding unminified bundle to dist 2019-02-15 21:48:40 -05:00
Francisco Hodge
4a35dff92f Updated dev dependencies 2019-02-09 10:19:48 -05:00
Francisco Hodge
04def5da87 License: Supporting both MIT and GPLv3 2019-01-28 11:11:28 -05:00
Francisco Hodge
dc085b377d Updated dev dependencies 2019-01-27 20:02:29 -05:00
Francisco Hodge
effee00b87 Added new inputPattern option 2019-01-24 23:04:59 -05:00
Francisco Hodge
90b408eff6 Tests update 2019-01-24 23:03:48 -05:00
Francisco Hodge
21fa732b1f Types update 2019-01-24 23:03:23 -05:00
Francisco Hodge
80f4307c36 Build update 2019-01-24 23:03:14 -05:00
Francisco Hodge
681bb3d0ee npm update 2019-01-24 23:02:59 -05:00
Francisco Hodge
e1fa685c6c Merge branch 'master' of https://github.com/hodgef/simple-keyboard 2019-01-17 18:37:07 -05:00
Francisco Hodge
2de7154128 npm update 2019-01-17 18:36:48 -05:00
Francisco Hodge
c9afe43f5b Build update 2019-01-17 18:36:36 -05:00
Francisco Hodge
c59f819db9 Tests update 2019-01-17 18:36:19 -05:00
Francisco Hodge
1f9efb0c66 Ensure caretPosition is unset on disableCaretPositioning 2019-01-17 18:36:09 -05:00
Francisco Hodge
32cbce8c8a Update issue templates 2019-01-17 09:20:47 -05:00
Francisco Hodge
6c2236f762 Adding types for disableCaretPositioning option 2019-01-16 19:38:42 -05:00
Francisco Hodge
23a50e6f44 Updated devDependencies 2019-01-06 15:44:07 -05:00
Francisco Hodge
c316d493c7 Tests update 2018-12-27 13:46:15 -05:00
Francisco Hodge
70e7635f25 npm update 2018-12-27 13:38:38 -05:00
Francisco Hodge
f5b73b09e7 Merge pull request #45 from mkusher/patch-1
fixed camelCase function
2018-12-27 13:33:09 -05:00
Aleh Kashnikau
7432e01740 fixed camelCase function
Added check for empty word
2018-12-27 21:29:05 +03:00
Francisco Hodge
459ab71c45 npm update 2018-12-24 13:31:13 -05:00
Francisco Hodge
a5c177e41c Specifying layout class on keyboard element 2018-12-24 13:30:52 -05:00
Francisco Hodge
d382945de7 Updated devDependencies 2018-12-23 17:42:02 -05:00
Francisco Hodge
4335f477a1 Adding new option: useButtonTag 2018-12-14 00:28:18 -05:00
Francisco Hodge
d03f00c0d1 Updated devDependencies 2018-12-08 15:49:33 -05:00
Francisco Hodge
9cea07dd41 Merge pull request #41 from armno/fix-incorrect-return-type-definition
[Angular] Fix return type of getButtonElement()
2018-12-04 20:11:10 -05:00
Francisco Hodge
efe18e7240 Build update 2018-12-04 20:06:52 -05:00
Francisco Hodge
82e242a806 Modified getInput return type 2018-12-04 20:06:32 -05:00
Armno
4a9d485d5b add return type for getButtonElement in type definition file 2018-12-04 10:42:05 +07:00
Francisco Hodge
6ffd2e77ad Improved Angular types support 2018-12-02 14:48:46 -05:00
Francisco Hodge
7753bc5ba3 Build update 2018-11-28 09:04:10 -05:00
Francisco Hodge
9c4fa00363 Merge pull request #40 from armno/master
Add type definition file for TypeScript
2018-11-28 08:58:36 -05:00
Francisco Hodge
251af057d8 npm update 2018-11-28 08:53:06 -05:00
Francisco Hodge
e60574d56d Build update 2018-11-28 08:52:58 -05:00
Francisco Hodge
b3b482e864 Copy index.d.ts to build folder on build 2018-11-28 08:52:27 -05:00
Armno
ff037ad5b7 remove exporting KeyboardOptions interface 2018-11-28 12:43:13 +07:00
Armno
ede2ce04b1 add overloaded constructor type definition 2018-11-28 11:56:00 +07:00
Armno
10380099e6 add more types 2018-11-28 11:20:32 +07:00
Armno
058b6774da Merge remote-tracking branch 'upstream/master' 2018-11-28 09:17:25 +07:00
Francisco Hodge
3b12b278f7 build update 2018-11-27 18:00:24 -05:00
Francisco Hodge
3523df1ef5 npm update 2018-11-27 17:55:06 -05:00
Francisco Hodge
178c63cf98 Update README.md 2018-11-27 17:49:12 -05:00
Francisco Hodge
ec452963fb Update README.md 2018-11-27 17:40:17 -05:00
Armno
b5cbfa780b add public methods type definitions 2018-11-27 23:43:20 +07:00
Armno
5c40dd3109 WIP: create type definition file 2018-11-27 19:57:08 +07:00
Francisco Hodge
7ab6baa0f4 Build update 2018-11-25 21:48:14 -05:00
Francisco Hodge
0512e2c624 Fix full keyboard numpad cursor positioning 2018-11-25 21:48:08 -05:00
Francisco Hodge
2693030203 Readme update 2018-11-25 20:15:15 -05:00
Francisco Hodge
3cbdf604fe Updated dev dependencies 2018-11-25 18:16:27 -05:00
Francisco Hodge
d87cb82238 Readme update 2018-11-25 18:16:05 -05:00
Francisco Hodge
125f6b6504 Tests update 2018-11-25 18:11:09 -05:00
Francisco Hodge
97b475a2b7 Setting preventMouseDownDefault false by default 2018-11-25 12:03:40 -05:00
Francisco Hodge
682660d638 Docs update 2018-11-24 21:12:28 -05:00
Francisco Hodge
d8c1327eff Bind caret handler events once regardless of number of instances 2018-11-24 21:12:19 -05:00
Francisco Hodge
b8fc9425ba Demo test update 2018-11-24 21:10:47 -05:00
Francisco Hodge
5c42ae3fbb Demo update 2018-11-24 21:10:33 -05:00
Francisco Hodge
a8e826679f npm update 2018-11-24 21:10:07 -05:00
Francisco Hodge
f78bfc0d02 Build update 2018-11-24 21:10:00 -05:00
Francisco Hodge
9c12f410ed Build update 2018-11-24 20:31:26 -05:00
Francisco Hodge
f83884af5c Merge pull request #39 from SteinRobert/preventDefault-for-mousedown-option
Adds preventDefault to mousedown event
2018-11-24 20:21:23 -05:00
Francisco Hodge
be25e26c46 npm update 2018-11-24 20:13:02 -05:00
Francisco Hodge
3b93f37cb2 Docs update 2018-11-24 20:12:52 -05:00
Francisco Hodge
822e7a97b7 Build update 2018-11-24 20:12:04 -05:00
Francisco Hodge
bc420bb60c Adding ternary condition for preventMouseDownDefault 2018-11-24 20:11:48 -05:00
Robert Stein
1aedf9c487 - changes mousedown event simulation so that event object is passed
to `onmousedown` handler
2018-11-24 16:43:30 +01:00
Robert Stein
0052efa582 - preventDefault is now called for mousedown event by default
- this can be disabled by setting preventMouseDownDefault to false
2018-11-24 16:29:13 +01:00
Francisco Hodge
316319a311 Tests update 2018-11-19 09:32:04 -05:00
Francisco Hodge
02bc34e3b7 npm update 2018-11-19 09:30:17 -05:00
Francisco Hodge
d38433be1c Fix buttonHold issue 2018-11-19 09:29:49 -05:00
Francisco Hodge
366f4cd98e Fix clearInput issue 2018-11-19 09:25:27 -05:00
Francisco Hodge
ee3d6a18f2 npm update 2018-11-16 23:31:05 -05:00
Francisco Hodge
e6d6c78389 Updating tests 2018-11-16 23:30:57 -05:00
Francisco Hodge
ba09ac7952 Updating devDependencies 2018-11-16 23:24:53 -05:00
Francisco Hodge
3ee9873d77 2.9.0 - Adding useTouchEvents 2018-11-16 00:39:49 -05:00
Francisco Hodge
347480735c 2.9.0 2018-11-16 00:32:09 -05:00
Francisco Hodge
3086a45295 Merge pull request #35 from MadDeveloper/tactile-touch-events
feat(Keyboard): add touch events (by @MadDeveloper)
2018-11-16 00:26:12 -05:00
Francisco Hodge
d33d557f08 Updating github templates 2018-11-15 12:18:24 -05:00
Julien Sergent
f8fb18e244 feat(Keyboard): add touch events
Can be enabled passing `useTouchEvents` option to the Keyboard constructor.
2018-11-15 17:05:39 +01:00
Francisco Hodge
2d8799367a Updating har-validator 2018-11-14 14:06:26 -05:00
44 changed files with 101811 additions and 84595 deletions

View File

@@ -1,6 +1,9 @@
---
name: Bug report
about: Create a report to help improve simple-keyboard
title: ''
labels: ''
assignees: hodgef
---
@@ -8,7 +11,7 @@ about: Create a report to help improve simple-keyboard
As some bugs have been addressed in later versions, please ensure you are running the latest.
**Describe the bug**
A clear and concise description of what the bug is.
A clear and concise description of what the bug is. Providing a [sandbox example](https://codesandbox.io/s/vanilla) or code depicting the issue is important, as this will help us reproduce the issue.
**Screenshots**
If applicable, add screenshots to help explain your problem.

View File

@@ -1,6 +1,9 @@
---
name: Feature request
about: Suggest an idea you'd like to see in simple-keyboard
title: ''
labels: ''
assignees: ''
---

8
.github/pull_request_template.md vendored Normal file
View File

@@ -0,0 +1,8 @@
## Description
A few sentences describing the overall goals of the pull request's commits.
## Checks
- [ ] Tests ( `npm run test -- --coverage` ) Coverage at `./coverage/lcov-report/index.html` should be 100%
- [ ] Documentation ( `npm run docs` ) Coverage at `./docs/source.html` should be 100%

View File

@@ -1,11 +1,12 @@
language: node_js
node_js:
- "node"
- '11.10.1'
install:
- npm install -g codecov
- npm install
script:
- npm run test -- --coverage
- npm run demo
- codecov
after_success:
- wget https://raw.githubusercontent.com/DiscordHooks/travis-ci-discord-webhook/master/send.sh

View File

@@ -1,6 +1,6 @@
MIT License
Copyright (c) 2018 Francisco Hodge
Copyright (c) 2019 Francisco Hodge
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
@@ -18,4 +18,4 @@ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
SOFTWARE.

View File

@@ -1,12 +1,13 @@
<div align="center">
<a href="https://simple-keyboard.com/demo" title="View Demo" target="_blank"><img src="https://franciscohodge.com/project-pages/simple-keyboard/images/simplekeyboard-banner_B.png" align="center" width="100%"></a>
<a href="https://simple-keyboard.com/demo" title="View Demo" target="_blank"><img src="https://franciscohodge.com/project-pages/simple-keyboard/images/simple-keyboard-10172018.gif" align="center" width="100%"></a>
<a href="https://simple-keyboard.com/demo" title="View Demo" target="_blank"><img src="https://franciscohodge.com/project-pages/simple-keyboard/images/skdemo-4x2.gif" align="center" width="100%"></a>
<blockquote>The easily customisable and responsive on-screen virtual keyboard for Javascript projects.</blockquote>
<p><a href="https://github.com/hodgef/simple-keyboard/blob/master/LICENSE" target="_blank"><img src="https://img.shields.io/badge/license-MIT-blue.svg" alt="License"></a>
<a href="https://www.npmjs.com/package/simple-keyboard" target="_blank"><img src="https://img.shields.io/npm/v/simple-keyboard.svg?style=flat" alt="npm version"></a>
<a href="https://travis-ci.org/hodgef/simple-keyboard" target="_blank"><img src="https://travis-ci.org/hodgef/simple-keyboard.svg?branch=master" alt="Build Status"></a>
<a href="https://codecov.io/gh/hodgef/simple-keyboard" target="_blank"><img src="https://img.shields.io/codecov/c/github/hodgef/simple-keyboard/master.svg?style=flat" alt="Coverage Status"></a>
<a href="https://doc.esdoc.org/github.com/hodgef/simple-keyboard" target="_blank"><img src="https://doc.esdoc.org/github.com/hodgef/simple-keyboard/badge.svg" alt="Documentation Status"></a>
<img src="https://img.shields.io/david/dev/hodgef/simple-keyboard.svg" alt="Dev dependencies">
<a href="https://www.codacy.com/app/hodgef/simple-keyboard?utm_source=github.com&amp;utm_medium=referral&amp;utm_content=hodgef/simple-keyboard&amp;utm_campaign=Badge_Grade" target="_blank"><img src="https://api.codacy.com/project/badge/Grade/5778fccc6a894701853d9a1f2fb44a76" alt="Codacy Badge"></a>
</p>
</div>
@@ -34,7 +35,9 @@ Feel free to browse the [Q&A / Use-cases](https://simple-keyboard.com/qa-use-cas
### Other versions
* ReactJS - [react-simple-keyboard](https://github.com/hodgef/react-simple-keyboard)
* [React.js](https://github.com/hodgef/react-simple-keyboard)
* [Angular](https://simple-keyboard.com/demo)
* [Vue.js](https://simple-keyboard.com/demo)
### Questions?

View File

@@ -1,6 +1,6 @@
/*!
*
* simple-keyboard v2.8.0
* simple-keyboard v2.17.0
* https://github.com/hodgef/simple-keyboard
*
* Copyright (c) Francisco Hodge (https://github.com/hodgef)
@@ -8,5 +8,5 @@
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
*/body,html{margin:0;padding:0}.simple-keyboard{font-family:HelveticaNeue-Light,Helvetica Neue Light,Helvetica Neue,Helvetica,Arial,Lucida Grande,sans-serif;width:100%;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;box-sizing:border-box;overflow:hidden;touch-action:manipulation}.simple-keyboard .hg-row{display:flex}.simple-keyboard .hg-row:not(:last-child){margin-bottom:5px}.simple-keyboard .hg-row .hg-button:not(:last-child){margin-right:5px}.simple-keyboard .hg-button{display:inline-block;flex-grow:1;cursor:pointer}.hg-standardBtn{max-width:100px}.simple-keyboard.hg-theme-default{background-color:rgba(0,0,0,.1);padding:5px;border-radius:5px}.simple-keyboard.hg-theme-default .hg-button{box-shadow:0 0 3px -1px rgba(0,0,0,.3);height:40px;border-radius:5px;box-sizing:border-box;padding:5px;background:#fff;border-bottom:1px solid #b5b5b5;cursor:pointer;display:flex;align-items:center;justify-content:center}.simple-keyboard.hg-theme-default .hg-button:active{background:#e4e4e4}.simple-keyboard.hg-theme-default.hg-layout-numeric .hg-button{width:33.3%;height:60px;align-items:center;display:flex;justify-content:center}.simple-keyboard.hg-theme-default .hg-button.hg-button-numpadadd,.simple-keyboard.hg-theme-default .hg-button.hg-button-numpadenter{height:85px}.simple-keyboard.hg-theme-default .hg-button.hg-button-numpad0{width:105px}.simple-keyboard.hg-theme-default .hg-button.hg-button-com{max-width:85px}.simple-keyboard.hg-theme-default .hg-button.hg-standardBtn.hg-button-at{max-width:45px}.simple-keyboard.hg-theme-default .hg-button.hg-selectedButton{background:rgba(5,25,70,.53);color:#fff}.simple-keyboard.hg-theme-default .hg-button.hg-standardBtn[data-skbtn=".com"]{max-width:82px}.simple-keyboard.hg-theme-default .hg-button.hg-standardBtn[data-skbtn="@"]{max-width:60px}
*/body,html{margin:0;padding:0}.simple-keyboard{font-family:HelveticaNeue-Light,Helvetica Neue Light,Helvetica Neue,Helvetica,Arial,Lucida Grande,sans-serif;width:100%;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;box-sizing:border-box;overflow:hidden;touch-action:manipulation}.simple-keyboard .hg-row{display:-webkit-flex;display:flex}.simple-keyboard .hg-row:not(:last-child){margin-bottom:5px}.simple-keyboard .hg-row .hg-button:not(:last-child){margin-right:5px}.simple-keyboard .hg-button{display:inline-block;-webkit-flex-grow:1;flex-grow:1;cursor:pointer}.simple-keyboard .hg-button span{pointer-events:none}.simple-keyboard.hg-theme-default{background-color:rgba(0,0,0,.1);padding:5px;border-radius:5px}.simple-keyboard.hg-theme-default .hg-button{box-shadow:0 0 3px -1px rgba(0,0,0,.3);height:40px;border-radius:5px;box-sizing:border-box;padding:5px;background:#fff;border-bottom:1px solid #b5b5b5;cursor:pointer;display:-webkit-flex;display:flex;-webkit-align-items:center;align-items:center;-webkit-justify-content:center;justify-content:center}.simple-keyboard button.hg-button{border-width:0;outline:0;font-size:inherit}.simple-keyboard.hg-theme-default:not(.hg-touch-events) .hg-button:active{background:#e4e4e4}.simple-keyboard.hg-theme-default.hg-layout-numeric .hg-button{width:33.3%;height:60px;-webkit-align-items:center;align-items:center;display:-webkit-flex;display:flex;-webkit-justify-content:center;justify-content:center}.simple-keyboard.hg-theme-default .hg-button.hg-button-numpadadd,.simple-keyboard.hg-theme-default .hg-button.hg-button-numpadenter{height:85px}.simple-keyboard.hg-theme-default .hg-button.hg-button-numpad0{width:105px}.simple-keyboard.hg-theme-default .hg-button.hg-button-com{max-width:85px}.simple-keyboard.hg-theme-default .hg-button.hg-standardBtn.hg-button-at{max-width:45px}.simple-keyboard.hg-theme-default .hg-button.hg-selectedButton{background:rgba(5,25,70,.53);color:#fff}.simple-keyboard.hg-theme-default .hg-button.hg-standardBtn[data-skbtn=".com"]{max-width:82px}.simple-keyboard.hg-theme-default .hg-button.hg-standardBtn[data-skbtn="@"]{max-width:60px}
/*# sourceMappingURL=index.css.map */

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,135 @@
/*!
*
* simple-keyboard v2.17.0 (Non-minified build)
* https://github.com/hodgef/simple-keyboard
*
* Copyright (c) Francisco Hodge (https://github.com/hodgef)
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
*/
body,
html {
margin: 0;
padding: 0;
}
.simple-keyboard {
font-family: "HelveticaNeue-Light", "Helvetica Neue Light", "Helvetica Neue",
Helvetica, Arial, "Lucida Grande", sans-serif;
width: 100%;
-webkit-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
box-sizing: border-box;
overflow: hidden;
touch-action: manipulation;
}
.simple-keyboard .hg-row {
display: -webkit-flex;
display: flex;
}
.simple-keyboard .hg-row:not(:last-child) {
margin-bottom: 5px;
}
.simple-keyboard .hg-row .hg-button:not(:last-child) {
margin-right: 5px;
}
.simple-keyboard .hg-button {
display: inline-block;
-webkit-flex-grow: 1;
flex-grow: 1;
cursor: pointer;
}
.simple-keyboard .hg-button span {
pointer-events: none;
}
/**
* hg-theme-default theme
*/
.simple-keyboard.hg-theme-default {
background-color: rgba(0, 0, 0, 0.1);
padding: 5px;
border-radius: 5px;
}
.simple-keyboard.hg-theme-default .hg-button {
box-shadow: 0px 0px 3px -1px rgba(0, 0, 0, 0.3);
height: 40px;
border-radius: 5px;
box-sizing: border-box;
padding: 5px;
background: white;
border-bottom: 1px solid #b5b5b5;
cursor: pointer;
display: -webkit-flex;
display: flex;
-webkit-align-items: center;
align-items: center;
-webkit-justify-content: center;
justify-content: center;
}
/* When using option "useButtonTag" */
.simple-keyboard button.hg-button {
border-width: 0;
outline: 0;
font-size: inherit;
}
.simple-keyboard.hg-theme-default:not(.hg-touch-events) .hg-button:active {
background: #e4e4e4;
}
.simple-keyboard.hg-theme-default.hg-layout-numeric .hg-button {
width: 33.3%;
height: 60px;
-webkit-align-items: center;
align-items: center;
display: -webkit-flex;
display: flex;
-webkit-justify-content: center;
justify-content: center;
}
.simple-keyboard.hg-theme-default .hg-button.hg-button-numpadadd {
height: 85px;
}
.simple-keyboard.hg-theme-default .hg-button.hg-button-numpadenter {
height: 85px;
}
.simple-keyboard.hg-theme-default .hg-button.hg-button-numpad0 {
width: 105px;
}
.simple-keyboard.hg-theme-default .hg-button.hg-button-com {
max-width: 85px;
}
.simple-keyboard.hg-theme-default .hg-button.hg-standardBtn.hg-button-at {
max-width: 45px;
}
.simple-keyboard.hg-theme-default .hg-button.hg-selectedButton {
background: rgba(5, 25, 70, 0.53);
color: white;
}
.simple-keyboard.hg-theme-default .hg-button.hg-standardBtn[data-skbtn=".com"] {
max-width: 82px;
}
.simple-keyboard.hg-theme-default .hg-button.hg-standardBtn[data-skbtn="@"] {
max-width: 60px;
}

219
build/index.d.ts vendored Normal file
View File

@@ -0,0 +1,219 @@
declare module 'simple-keyboard' {
interface KeyboardLayoutObject {
default: string[];
shift?: string[];
}
interface KeyboardButtonTheme {
class: string;
buttons: string;
}
interface KeyboardOptions {
/**
* Modify the keyboard layout.
*/
layout?: KeyboardLayoutObject;
/**
* Specifies which layout should be used.
*/
layoutName?: string;
/**
* Replaces variable buttons (such as `{bksp}`) with a human-friendly name (e.g.: `backspace`).
*/
display?: { [button: string]: string };
/**
* By default, when you set the display property, you replace the default one. This setting merges them instead.
*/
mergeDisplay?: boolean;
/**
* A prop to add your own css classes to the keyboard wrapper. You can add multiple classes separated by a space.
*/
theme?: string;
/**
* A prop to add your own css classes to one or several buttons.
*/
buttonTheme?: KeyboardButtonTheme[];
/**
* Runs a `console.log` every time a key is pressed. Displays the buttons pressed and the current input.
*/
debug?: boolean;
/**
* Specifies whether clicking the "ENTER" button will input a newline (`\n`) or not.
*/
newLineOnEnter?: boolean;
/**
* Specifies whether clicking the "TAB" button will input a tab character (`\t`) or not.
*/
tabCharOnTab?: boolean;
/**
* Allows you to use a single simple-keyboard instance for several inputs.
*/
inputName?: string;
/**
* `number`: Restrains all of simple-keyboard inputs to a certain length. This should be used in addition to the input elements maxlengthattribute.
*
* `{ [inputName: string]: number }`: Restrains simple-keyboards individual inputs to a certain length. This should be used in addition to the input elements maxlengthattribute.
*/
maxLength?:
| number
| {
[inputName: string]: number;
};
/**
* When set to true, this option synchronizes the internal input of every simple-keyboard instance.
*/
syncInstanceInputs?: boolean;
/**
* Enable highlighting of keys pressed on physical keyboard.
*/
physicalKeyboardHighlight?: boolean;
/**
* Calling preventDefault for the mousedown events keeps the focus on the input.
*/
preventMouseDownDefault?: boolean;
/**
* Define the text color that the physical keyboard highlighted key should have.
*/
physicalKeyboardHighlightTextColor?: string;
/**
* Define the background color that the physical keyboard highlighted key should have.
*/
physicalKeyboardHighlightBgColor?: string;
/**
* Render buttons as a button element instead of a div element.
*/
useButtonTag?: boolean;
/**
* A prop to ensure characters are always be added/removed at the end of the string.
*/
disableCaretPositioning?: boolean;
/**
* Restrains input(s) change to the defined regular expression pattern.
*/
inputPattern?: any;
/**
* Instructs simple-keyboard to use touch events instead of click events.
*/
useTouchEvents?: boolean;
/**
* Enable useTouchEvents automatically when touch device is detected.
*/
autoUseTouchEvents?: boolean;
/**
* Executes the callback function on key press. Returns button layout name (i.e.: "{shift}").
*/
onKeyPress?: (button: string) => any;
/**
* Executes the callback function on input change. Returns the current input's string.
*/
onChange?: (input: string) => any;
/**
* Executes the callback function before the first simple-keyboard render.
*/
beforeFirstRender?: () => void;
/**
* Executes the callback function before a simple-keyboard render.
*/
beforeRender?: () => void;
/**
* Executes the callback function every time simple-keyboard is rendered (e.g: when you change layouts).
*/
onRender?: () => void;
/**
* Executes the callback function once simple-keyboard is rendered for the first time (on initialization).
*/
onInit?: () => void;
/**
* Executes the callback function on input change. Returns the input object with all defined inputs.
*/
onChangeAll?: (inputs: any) => any;
}
class Keyboard {
constructor(selector: string, options: KeyboardOptions);
constructor(options: KeyboardOptions);
options: KeyboardOptions;
/**
* Adds/Modifies an entry to the `buttonTheme`. Basically a way to add a class to a button.
* @param {string} buttons List of buttons to select (separated by a space).
* @param {string} className Classes to give to the selected buttons (separated by space).
*/
addButtonTheme(buttons: string, className: string): void;
/**
* Removes/Amends an entry to the `buttonTheme`. Basically a way to remove a class previously added to a button through buttonTheme or addButtonTheme.
* @param {string} buttons List of buttons to select (separated by a space).
* @param {string} className Classes to give to the selected buttons (separated by space).
*/
removeButtonTheme(buttons: string, className: string): void;
/**
* Clear the keyboard's input.
*
* @param {string} [inputName] optional - the internal input to select
*/
clearInput(inputName?: string): void;
/**
* Get the keyboards input (You can also get it from the onChange prop).
* @param {string} [inputName] optional - the internal input to select
*/
getInput(inputName?: string): string;
/**
* Set the keyboards input.
* @param {string} input the input value
* @param {string} inputName optional - the internal input to select
*/
setInput(input: string, inputName?: string): void;
/**
* Set new option or modify existing ones after initialization.
* @param {KeyboardOptions} option The option to set
*/
setOptions(options: KeyboardOptions): void;
/**
* Send a command to all simple-keyboard instances at once (if you have multiple instances).
* @param {function(instance: object, key: string)} callback Function to run on every instance
*/
dispatch(callback: (instance: any, key: string) => void): void;
/**
* Get the DOM Element of a button. If there are several buttons with the same name, an array of the DOM Elements is returned.
* @param {string} button The button layout name to select
*/
getButtonElement(button: string): HTMLElement | HTMLElement[];
}
export default Keyboard;
}

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

1591
build/simple-keyboard.js Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -79,6 +79,7 @@ module.exports = {
appPackageJson: resolveApp('package.json'),
appSrc: resolveApp('src'),
appSrcLib: resolveApp('src/lib'),
appSrcLibTypes: resolveApp('src/lib/@types'),
appSrcDemo: resolveApp('src/demo'),
appTsConfig: resolveApp('tsconfig.json'),
yarnLockFile: resolveApp('yarn.lock'),

View File

@@ -326,10 +326,13 @@ module.exports = {
configFile: false,
compact: false,
presets: [
[
require.resolve('babel-preset-react-app/dependencies'),
{ helpers: true },
],
"@babel/preset-env",
"@babel/preset-react"
],
plugins: [
[
"@babel/plugin-proposal-class-properties"
]
],
cacheDirectory: true,
// Save disk space when time isn't as important

View File

@@ -11,9 +11,7 @@ const TerserPlugin = require('terser-webpack-plugin');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const OptimizeCSSAssetsPlugin = require('optimize-css-assets-webpack-plugin');
const safePostCssParser = require('postcss-safe-parser');
const ManifestPlugin = require('webpack-manifest-plugin');
const InterpolateHtmlPlugin = require('react-dev-utils/InterpolateHtmlPlugin');
const WorkboxWebpackPlugin = require('workbox-webpack-plugin');
const ModuleScopePlugin = require('react-dev-utils/ModuleScopePlugin');
const getCSSModuleLocalIdent = require('react-dev-utils/getCSSModuleLocalIdent');
const paths = require('./paths');
@@ -21,8 +19,9 @@ const getClientEnvironment = require('./env');
const ModuleNotFoundPlugin = require('react-dev-utils/ModuleNotFoundPlugin');
const ForkTsCheckerWebpackPlugin = require('fork-ts-checker-webpack-plugin-alt');
const typescriptFormatter = require('react-dev-utils/typescriptFormatter');
const CopyWebpackPlugin = require('copy-webpack-plugin');
const getPackageJson = require('./getPackageJson');
var PrettierPlugin = require("prettier-webpack-plugin");
// Webpack uses `publicPath` to determine where the app is being served from.
// It requires a trailing slash, or the file assets will get an incorrect path.
@@ -510,6 +509,13 @@ module.exports = {
// https://github.com/jmblog/how-to-optimize-momentjs-with-webpack
// You can remove this if you don't use Moment.js:
new webpack.IgnorePlugin(/^\.\/locale$/, /moment$/),
new CopyWebpackPlugin([
{
from: `${paths.appSrcLibTypes}`,
to: paths.appBuild
}
]),
new PrettierPlugin(),
// Generate a service worker script that will precache, and keep up to date,
// the HTML & assets that are part of the Webpack build.
/*new WorkboxWebpackPlugin.GenerateSW({

View File

@@ -0,0 +1,504 @@
'use strict';
const fs = require('fs');
const path = require('path');
const webpack = require('webpack');
const resolve = require('resolve');
const PnpWebpackPlugin = require('pnp-webpack-plugin');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const InlineChunkHtmlPlugin = require('react-dev-utils/InlineChunkHtmlPlugin');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const InterpolateHtmlPlugin = require('react-dev-utils/InterpolateHtmlPlugin');
const ModuleScopePlugin = require('react-dev-utils/ModuleScopePlugin');
const getCSSModuleLocalIdent = require('react-dev-utils/getCSSModuleLocalIdent');
const paths = require('./paths');
const getClientEnvironment = require('./env');
const ModuleNotFoundPlugin = require('react-dev-utils/ModuleNotFoundPlugin');
const ForkTsCheckerWebpackPlugin = require('fork-ts-checker-webpack-plugin-alt');
const typescriptFormatter = require('react-dev-utils/typescriptFormatter');
const getPackageJson = require('./getPackageJson');
const UglifyJsPlugin = require('uglifyjs-webpack-plugin');
// Webpack uses `publicPath` to determine where the app is being served from.
// It requires a trailing slash, or the file assets will get an incorrect path.
const publicPath = paths.servedPath;
// Some apps do not use client-side routing with pushState.
// For these, "homepage" can be set to "." to enable relative asset paths.
const shouldUseRelativeAssetPaths = publicPath === './';
// Source maps are resource heavy and can cause out of memory issue for large source files.
const shouldUseSourceMap = process.env.GENERATE_SOURCEMAP !== 'false';
// Some apps do not need the benefits of saving a web request, so not inlining the chunk
// makes for a smoother build process.
const shouldInlineRuntimeChunk = process.env.INLINE_RUNTIME_CHUNK !== 'false';
// `publicUrl` is just like `publicPath`, but we will provide it to our app
// as %PUBLIC_URL% in `index.html` and `process.env.PUBLIC_URL` in JavaScript.
// Omit trailing slash as %PUBLIC_URL%/xyz looks better than %PUBLIC_URL%xyz.
const publicUrl = publicPath.slice(0, -1);
// Get environment variables to inject into our app.
const env = getClientEnvironment(publicUrl);
// Check if TypeScript is setup
const useTypeScript = fs.existsSync(paths.appTsConfig);
// style files regexes
const cssRegex = /\.css$/;
const cssModuleRegex = /\.module\.css$/;
const sassRegex = /\.(scss|sass)$/;
const sassModuleRegex = /\.module\.(scss|sass)$/;
const {
version,
name,
license,
repository,
author,
} = getPackageJson('version', 'name', 'license', 'repository', 'author');
const banner = `
${name} v${version} (Non-minified build)
${repository.url}
Copyright (c) ${author.replace(/ *\<[^)]*\> */g, " ")}
This source code is licensed under the ${license} license found in the
LICENSE file in the root directory of this source tree.
`;
// common function to get style loaders
const getStyleLoaders = (cssOptions, preProcessor) => {
const loaders = [
{
loader: MiniCssExtractPlugin.loader,
options: Object.assign(
{},
shouldUseRelativeAssetPaths ? { publicPath: '../../' } : undefined
),
},
{
loader: require.resolve('css-loader'),
options: cssOptions,
},
{
// Options for PostCSS as we reference these options twice
// Adds vendor prefixing based on your specified browser support in
// package.json
loader: require.resolve('postcss-loader'),
options: {
// Necessary for external CSS imports to work
// https://github.com/facebook/create-react-app/issues/2677
ident: 'postcss',
plugins: () => [
require('postcss-flexbugs-fixes'),
require('postcss-preset-env')({
autoprefixer: {
flexbox: 'no-2009',
},
stage: 3,
}),
],
sourceMap: shouldUseSourceMap,
},
},
];
if (preProcessor) {
loaders.push({
loader: require.resolve(preProcessor),
options: {
sourceMap: shouldUseSourceMap,
},
});
}
return loaders;
};
// This is the production configuration.
// It compiles slowly and is focused on producing a fast and minimal bundle.
// The development configuration is different and lives in a separate file.
module.exports = {
mode: 'production',
// Don't attempt to continue if there are any errors.
bail: true,
// We generate sourcemaps in production. This is slow but gives good results.
// You can exclude the *.map files from the build during deployment.
devtool: false,
// In production, we only want to load the app code.
entry: [paths.appLibIndexJs],
output: {
// The build folder.
path: paths.appBuild,
// Generated JS file names (with nested folders).
// There will be one main bundle, and one file per asynchronous chunk.
// We don't currently advertise code splitting but Webpack supports it.
filename: 'simple-keyboard.js',
chunkFilename: 'index.[chunkhash:8].chunk.js',
// We inferred the "public path" (such as / or /my-project) from homepage.
publicPath: publicPath,
library: "SimpleKeyboard",
libraryTarget: 'umd',
umdNamedDefine: true,
// Point sourcemap entries to original disk location (format as URL on Windows)
devtoolModuleFilenameTemplate: info =>
path
.relative(paths.appSrcLib, info.absoluteResourcePath)
.replace(/\\/g, '/'),
},
optimization: {
minimizer: [
// we specify a custom UglifyJsPlugin here to get source maps in production
new UglifyJsPlugin({
cache: false,
parallel: false,
uglifyOptions: {
output: {
comments: true,
beautify: true,
braces: true,
indent_level: 2
},
mangle: false,
compress: false
},
sourceMap: false
}),
new webpack.BannerPlugin({
banner: banner,
entryOnly: true
})
]
},
resolve: {
// This allows you to set a fallback for where Webpack should look for modules.
// We placed these paths second because we want `node_modules` to "win"
// if there are any conflicts. This matches Node resolution mechanism.
// https://github.com/facebook/create-react-app/issues/253
modules: ['node_modules'].concat(
// It is guaranteed to exist because we tweak it in `env.js`
process.env.NODE_PATH.split(path.delimiter).filter(Boolean)
),
// These are the reasonable defaults supported by the Node ecosystem.
// We also include JSX as a common component filename extension to support
// some tools, although we do not recommend using it, see:
// https://github.com/facebook/create-react-app/issues/290
// `web` extension prefixes have been added for better support
// for React Native Web.
extensions: paths.moduleFileExtensions
.map(ext => `.${ext}`)
.filter(ext => useTypeScript || !ext.includes('ts')),
alias: {
// Support React Native Web
// https://www.smashingmagazine.com/2016/08/a-glimpse-into-the-future-with-react-native-for-web/
'react-native': 'react-native-web',
},
plugins: [
// Adds support for installing with Plug'n'Play, leading to faster installs and adding
// guards against forgotten dependencies and such.
PnpWebpackPlugin,
// Prevents users from importing files from outside of src/ (or node_modules/).
// This often causes confusion because we only process files within src/ with babel.
// To fix this, we prevent you from importing files out of src/ -- if you'd like to,
// please link the files into your node_modules/ and let module-resolution kick in.
// Make sure your source files are compiled, as they will not be processed in any way.
new ModuleScopePlugin(paths.appSrcLib, [paths.appPackageJson]),
],
},
resolveLoader: {
plugins: [
// Also related to Plug'n'Play, but this time it tells Webpack to load its loaders
// from the current package.
PnpWebpackPlugin.moduleLoader(module),
],
},
module: {
strictExportPresence: true,
rules: [
// Disable require.ensure as it's not a standard language feature.
{ parser: { requireEnsure: false } },
// First, run the linter.
// It's important to do this before Babel processes the JS.
{
test: /\.(js|mjs|jsx)$/,
enforce: 'pre',
use: [
{
options: {
formatter: require.resolve('react-dev-utils/eslintFormatter'),
eslintPath: require.resolve('eslint'),
},
loader: require.resolve('eslint-loader'),
},
],
include: paths.appSrcLib,
},
{
// "oneOf" will traverse all following loaders until one will
// match the requirements. When no loader matches it will fall
// back to the "file" loader at the end of the loader list.
oneOf: [
// "url" loader works just like "file" loader but it also embeds
// assets smaller than specified size as data URLs to avoid requests.
{
test: [/\.bmp$/, /\.gif$/, /\.jpe?g$/, /\.png$/],
loader: require.resolve('url-loader'),
options: {
limit: 10000,
name: 'static/media/[name].[hash:8].[ext]',
},
},
// Process application JS with Babel.
// The preset includes JSX, Flow, TypeScript and some ESnext features.
{
test: /\.(js|mjs|jsx|ts|tsx)$/,
include: paths.appSrcLib,
loader: require.resolve('babel-loader'),
options: {
customize: require.resolve(
'babel-preset-react-app/webpack-overrides'
),
plugins: [
[
require.resolve('babel-plugin-named-asset-import'),
{
loaderMap: {
svg: {
ReactComponent: '@svgr/webpack?-prettier,-svgo![path]',
},
},
},
],
],
cacheDirectory: true,
// Save disk space when time isn't as important
cacheCompression: true,
compact: true,
},
},
// Process any JS outside of the app with Babel.
// Unlike the application JS, we only compile the standard ES features.
{
test: /\.(js|mjs)$/,
exclude: /@babel(?:\/|\\{1,2})runtime/,
loader: require.resolve('babel-loader'),
options: {
babelrc: false,
configFile: false,
compact: false,
presets: [
[
require.resolve('babel-preset-react-app/dependencies'),
{ helpers: true },
],
],
cacheDirectory: true,
// Save disk space when time isn't as important
cacheCompression: true,
// If an error happens in a package, it's possible to be
// because it was compiled. Thus, we don't want the browser
// debugger to show the original code. Instead, the code
// being evaluated would be much more helpful.
sourceMaps: false,
},
},
// "postcss" loader applies autoprefixer to our CSS.
// "css" loader resolves paths in CSS and adds assets as dependencies.
// `MiniCSSExtractPlugin` extracts styles into CSS
// files. If you use code splitting, async bundles will have their own separate CSS chunk file.
// By default we support CSS Modules with the extension .module.css
{
test: cssRegex,
exclude: cssModuleRegex,
loader: getStyleLoaders({
importLoaders: 1,
sourceMap: shouldUseSourceMap,
}),
// Don't consider CSS imports dead code even if the
// containing package claims to have no side effects.
// Remove this when webpack adds a warning or an error for this.
// See https://github.com/webpack/webpack/issues/6571
sideEffects: true,
},
// Adds support for CSS Modules (https://github.com/css-modules/css-modules)
// using the extension .module.css
{
test: cssModuleRegex,
loader: getStyleLoaders({
importLoaders: 1,
sourceMap: shouldUseSourceMap,
modules: true,
getLocalIdent: getCSSModuleLocalIdent,
}),
},
// Opt-in support for SASS. The logic here is somewhat similar
// as in the CSS routine, except that "sass-loader" runs first
// to compile SASS files into CSS.
// By default we support SASS Modules with the
// extensions .module.scss or .module.sass
{
test: sassRegex,
exclude: sassModuleRegex,
loader: getStyleLoaders(
{
importLoaders: 2,
sourceMap: shouldUseSourceMap,
},
'sass-loader'
),
// Don't consider CSS imports dead code even if the
// containing package claims to have no side effects.
// Remove this when webpack adds a warning or an error for this.
// See https://github.com/webpack/webpack/issues/6571
sideEffects: true,
},
// Adds support for CSS Modules, but using SASS
// using the extension .module.scss or .module.sass
{
test: sassModuleRegex,
loader: getStyleLoaders(
{
importLoaders: 2,
sourceMap: shouldUseSourceMap,
modules: true,
getLocalIdent: getCSSModuleLocalIdent,
},
'sass-loader'
),
},
// "file" loader makes sure assets end up in the `build` folder.
// When you `import` an asset, you get its filename.
// This loader doesn't use a "test" so it will catch all modules
// that fall through the other loaders.
{
loader: require.resolve('file-loader'),
// Exclude `js` files to keep "css" loader working as it injects
// it's runtime that would otherwise be processed through "file" loader.
// Also exclude `html` and `json` extensions so they get processed
// by webpacks internal loaders.
exclude: [/\.(js|mjs|jsx|ts|tsx)$/, /\.html$/, /\.json$/],
options: {
name: 'static/media/[name].[hash:8].[ext]',
},
},
// ** STOP ** Are you adding a new loader?
// Make sure to add the new loader(s) before the "file" loader.
],
},
],
},
plugins: [
// Generates an `index.html` file with the <script> injected.
/*new HtmlWebpackPlugin({
inject: true,
template: paths.appHtml,
minify: {
removeComments: true,
collapseWhitespace: true,
removeRedundantAttributes: true,
useShortDoctype: true,
removeEmptyAttributes: true,
removeStyleLinkTypeAttributes: true,
keepClosingSlash: true,
minifyJS: true,
minifyCSS: true,
minifyURLs: true,
},
}),*/
// Inlines the webpack runtime script. This script is too small to warrant
// a network request.
shouldInlineRuntimeChunk &&
new InlineChunkHtmlPlugin(HtmlWebpackPlugin, [/runtime~.+[.]js/]),
// Makes some environment variables available in index.html.
// The public URL is available as %PUBLIC_URL% in index.html, e.g.:
// <link rel="shortcut icon" href="%PUBLIC_URL%/favicon.ico">
// In production, it will be an empty string unless you specify "homepage"
// in `package.json`, in which case it will be the pathname of that URL.
new InterpolateHtmlPlugin(HtmlWebpackPlugin, env.raw),
// This gives some necessary context to module not found errors, such as
// the requesting resource.
new ModuleNotFoundPlugin(paths.appPath),
// Makes some environment variables available to the JS code, for example:
// if (process.env.NODE_ENV === 'production') { ... }. See `./env.js`.
// It is absolutely essential that NODE_ENV was set to production here.
// Otherwise React will be compiled in the very slow development mode.
new webpack.DefinePlugin(env.stringified),
new MiniCssExtractPlugin({
// Options similar to the same options in webpackOptions.output
// both options are optional
filename: 'css/simple-keyboard.css',
chunkFilename: 'css/index.[contenthash:8].chunk.css',
}),
// Generate a manifest file which contains a mapping of all asset filenames
// to their corresponding output file so that tools can pick it up without
// having to parse `index.html`.
/*new ManifestPlugin({
fileName: 'asset-manifest.json',
publicPath: publicPath,
}),*/
// Moment.js is an extremely popular library that bundles large locale files
// by default due to how Webpack interprets its code. This is a practical
// solution that requires the user to opt into importing specific locales.
// https://github.com/jmblog/how-to-optimize-momentjs-with-webpack
// You can remove this if you don't use Moment.js:
new webpack.IgnorePlugin(/^\.\/locale$/, /moment$/),
// Generate a service worker script that will precache, and keep up to date,
// the HTML & assets that are part of the Webpack build.
/*new WorkboxWebpackPlugin.GenerateSW({
clientsClaim: true,
exclude: [/\.map$/, /asset-manifest\.json$/],
importWorkboxFrom: 'cdn',
navigateFallback: publicUrl + '/index.html',
navigateFallbackBlacklist: [
// Exclude URLs starting with /_, as they're likely an API call
new RegExp('^/_'),
// Exclude URLs containing a dot, as they're likely a resource in
// public/ and not a SPA route
new RegExp('/[^/]+\\.[^/]+$'),
],
}),*/
// TypeScript type checking
fs.existsSync(paths.appTsConfig) &&
new ForkTsCheckerWebpackPlugin({
typescript: resolve.sync('typescript', {
basedir: paths.appNodeModules,
}),
async: false,
checkSyntacticErrors: true,
tsconfig: paths.appTsConfig,
compilerOptions: {
module: 'esnext',
moduleResolution: 'node',
resolveJsonModule: true,
isolatedModules: true,
noEmit: true,
jsx: 'preserve',
},
reportFiles: [
'**',
'!**/*.json',
'!**/__tests__/**',
'!**/?(*.)(spec|test).*',
'!src/setupProxy.js',
'!src/setupTests.*',
],
watch: paths.appSrcLib,
silent: true,
formatter: typescriptFormatter,
}),
].filter(Boolean),
// Some libraries import Node modules but don't use them in the browser.
// Tell Webpack to provide empty mocks for them so importing them works.
node: {
dgram: 'empty',
fs: 'empty',
net: 'empty',
tls: 'empty',
child_process: 'empty',
},
// Turn off performance processing because we utilize
// our own hints via the FileSizeReporter
performance: false,
};

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -175,8 +175,7 @@ This class:</p>
<div>
<div data-ice="description"><p>Tracks current cursor position
As keys are pressed, text will be added/removed at that position within the input.</p>
<div data-ice="description"><p>Only first instance should insall the caret handling events</p>
</div>
</div>
</td>
@@ -1345,7 +1344,7 @@ As keys are pressed, text will be added/removed at that position within the inpu
<span class="right-info">
<span data-ice="source"><span><a href="file/src/lib/components/Keyboard.js.html#lineNumber121">source</a></span></span>
<span data-ice="source"><span><a href="file/src/lib/components/Keyboard.js.html#lineNumber123">source</a></span></span>
</span>
</h3>
@@ -1388,15 +1387,14 @@ As keys are pressed, text will be added/removed at that position within the inpu
<span class="right-info">
<span data-ice="source"><span><a href="file/src/lib/components/Keyboard.js.html#lineNumber535">source</a></span></span>
<span data-ice="source"><span><a href="file/src/lib/components/Keyboard.js.html#lineNumber512">source</a></span></span>
</span>
</h3>
<div data-ice="description"><p>Tracks current cursor position
As keys are pressed, text will be added/removed at that position within the input.</p>
<div data-ice="description"><p>Only first instance should insall the caret handling events</p>
</div>
@@ -1433,7 +1431,7 @@ As keys are pressed, text will be added/removed at that position within the inpu
<span class="right-info">
<span data-ice="source"><span><a href="file/src/lib/components/Keyboard.js.html#lineNumber613">source</a></span></span>
<span data-ice="source"><span><a href="file/src/lib/components/Keyboard.js.html#lineNumber634">source</a></span></span>
</span>
</h3>
@@ -1477,7 +1475,7 @@ As keys are pressed, text will be added/removed at that position within the inpu
<span class="right-info">
<span data-ice="source"><span><a href="file/src/lib/components/Keyboard.js.html#lineNumber623">source</a></span></span>
<span data-ice="source"><span><a href="file/src/lib/components/Keyboard.js.html#lineNumber644">source</a></span></span>
</span>
</h3>
@@ -1521,7 +1519,7 @@ As keys are pressed, text will be added/removed at that position within the inpu
<span class="right-info">
<span data-ice="source"><span><a href="file/src/lib/components/Keyboard.js.html#lineNumber272">source</a></span></span>
<span data-ice="source"><span><a href="file/src/lib/components/Keyboard.js.html#lineNumber274">source</a></span></span>
</span>
</h3>
@@ -1564,7 +1562,7 @@ As keys are pressed, text will be added/removed at that position within the inpu
<span class="right-info">
<span data-ice="source"><span><a href="file/src/lib/components/Keyboard.js.html#lineNumber233">source</a></span></span>
<span data-ice="source"><span><a href="file/src/lib/components/Keyboard.js.html#lineNumber235">source</a></span></span>
</span>
</h3>
@@ -1607,7 +1605,7 @@ As keys are pressed, text will be added/removed at that position within the inpu
<span class="right-info">
<span data-ice="source"><span><a href="file/src/lib/components/Keyboard.js.html#lineNumber768">source</a></span></span>
<span data-ice="source"><span><a href="file/src/lib/components/Keyboard.js.html#lineNumber798">source</a></span></span>
</span>
</h3>
@@ -1651,7 +1649,7 @@ As keys are pressed, text will be added/removed at that position within the inpu
<span class="right-info">
<span data-ice="source"><span><a href="file/src/lib/components/Keyboard.js.html#lineNumber110">source</a></span></span>
<span data-ice="source"><span><a href="file/src/lib/components/Keyboard.js.html#lineNumber112">source</a></span></span>
</span>
</h3>
@@ -1731,7 +1729,7 @@ keyboard.clearInput();</code></pre>
<span class="right-info">
<span data-ice="source"><span><a href="file/src/lib/components/Keyboard.js.html#lineNumber222">source</a></span></span>
<span data-ice="source"><span><a href="file/src/lib/components/Keyboard.js.html#lineNumber224">source</a></span></span>
</span>
</h3>
@@ -1818,7 +1816,7 @@ keyboard.clearInput();</code></pre>
<span class="right-info">
<span data-ice="source"><span><a href="file/src/lib/components/Keyboard.js.html#lineNumber116">source</a></span></span>
<span data-ice="source"><span><a href="file/src/lib/components/Keyboard.js.html#lineNumber118">source</a></span></span>
</span>
</h3>
@@ -1861,7 +1859,7 @@ keyboard.clearInput();</code></pre>
<span class="right-info">
<span data-ice="source"><span><a href="file/src/lib/components/Keyboard.js.html#lineNumber69">source</a></span></span>
<span data-ice="source"><span><a href="file/src/lib/components/Keyboard.js.html#lineNumber71">source</a></span></span>
</span>
</h3>
@@ -1904,7 +1902,7 @@ keyboard.clearInput();</code></pre>
<span class="right-info">
<span data-ice="source"><span><a href="file/src/lib/components/Keyboard.js.html#lineNumber150">source</a></span></span>
<span data-ice="source"><span><a href="file/src/lib/components/Keyboard.js.html#lineNumber152">source</a></span></span>
</span>
</h3>
@@ -1948,7 +1946,7 @@ keyboard.clearInput();</code></pre>
<span class="right-info">
<span data-ice="source"><span><a href="file/src/lib/components/Keyboard.js.html#lineNumber61">source</a></span></span>
<span data-ice="source"><span><a href="file/src/lib/components/Keyboard.js.html#lineNumber62">source</a></span></span>
</span>
</h3>
@@ -2065,6 +2063,13 @@ keyboard.clearInput();</code></pre>
<td data-ice="description"><p>Enable highlighting of keys pressed on physical keyboard.</p>
</td>
</tr>
<tr data-ice="property" data-depth="0">
<td data-ice="name" class="code" data-depth="0">preventMouseDownDefault</td>
<td data-ice="type" class="code"><span><a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Boolean">boolean</a></span></td>
<td data-ice="appendix"></td>
<td data-ice="description"><p>Calling preventDefault for the mousedown events keeps the focus on the input.</p>
</td>
</tr>
<tr data-ice="property" data-depth="0">
<td data-ice="name" class="code" data-depth="0">physicalKeyboardHighlightTextColor</td>
<td data-ice="type" class="code"><span><a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String">string</a></span></td>
@@ -2148,7 +2153,7 @@ keyboard.clearInput();</code></pre>
<span class="right-info">
<span data-ice="source"><span><a href="file/src/lib/components/Keyboard.js.html#lineNumber145">source</a></span></span>
<span data-ice="source"><span><a href="file/src/lib/components/Keyboard.js.html#lineNumber147">source</a></span></span>
</span>
</h3>
@@ -2192,7 +2197,7 @@ keyboard.clearInput();</code></pre>
<span class="right-info">
<span data-ice="source"><span><a href="file/src/lib/components/Keyboard.js.html#lineNumber579">source</a></span></span>
<span data-ice="source"><span><a href="file/src/lib/components/Keyboard.js.html#lineNumber600">source</a></span></span>
</span>
</h3>
@@ -2236,7 +2241,7 @@ keyboard.clearInput();</code></pre>
<span class="right-info">
<span data-ice="source"><span><a href="file/src/lib/components/Keyboard.js.html#lineNumber350">source</a></span></span>
<span data-ice="source"><span><a href="file/src/lib/components/Keyboard.js.html#lineNumber352">source</a></span></span>
</span>
</h3>
@@ -2327,7 +2332,7 @@ keyboard.clearInput();</code></pre>
<span class="right-info">
<span data-ice="source"><span><a href="file/src/lib/components/Keyboard.js.html#lineNumber386">source</a></span></span>
<span data-ice="source"><span><a href="file/src/lib/components/Keyboard.js.html#lineNumber388">source</a></span></span>
</span>
</h3>
@@ -2407,7 +2412,7 @@ keyboard.clearInput();</code></pre>
<span class="right-info">
<span data-ice="source"><span><a href="file/src/lib/components/Keyboard.js.html#lineNumber519">source</a></span></span>
<span data-ice="source"><span><a href="file/src/lib/components/Keyboard.js.html#lineNumber535">source</a></span></span>
</span>
</h3>
@@ -2467,7 +2472,7 @@ keyboard.clearInput();</code></pre>
<span class="right-info">
<span data-ice="source"><span><a href="file/src/lib/components/Keyboard.js.html#lineNumber360">source</a></span></span>
<span data-ice="source"><span><a href="file/src/lib/components/Keyboard.js.html#lineNumber362">source</a></span></span>
</span>
</h3>
@@ -2512,7 +2517,7 @@ Used interally between re-renders.</p>
<span class="right-info">
<span data-ice="source"><span><a href="file/src/lib/components/Keyboard.js.html#lineNumber295">source</a></span></span>
<span data-ice="source"><span><a href="file/src/lib/components/Keyboard.js.html#lineNumber297">source</a></span></span>
</span>
</h3>
@@ -2573,7 +2578,7 @@ Used interally between re-renders.</p>
<span class="right-info">
<span data-ice="source"><span><a href="file/src/lib/components/Keyboard.js.html#lineNumber370">source</a></span></span>
<span data-ice="source"><span><a href="file/src/lib/components/Keyboard.js.html#lineNumber372">source</a></span></span>
</span>
</h3>
@@ -2646,7 +2651,7 @@ Used interally between re-renders.</p>
<span class="right-info">
<span data-ice="source"><span><a href="file/src/lib/components/Keyboard.js.html#lineNumber488">source</a></span></span>
<span data-ice="source"><span><a href="file/src/lib/components/Keyboard.js.html#lineNumber490">source</a></span></span>
</span>
</h3>
@@ -2719,7 +2724,7 @@ Used interally between re-renders.</p>
<span class="right-info">
<span data-ice="source"><span><a href="file/src/lib/components/Keyboard.js.html#lineNumber310">source</a></span></span>
<span data-ice="source"><span><a href="file/src/lib/components/Keyboard.js.html#lineNumber312">source</a></span></span>
</span>
</h3>
@@ -2792,7 +2797,7 @@ Used interally between re-renders.</p>
<span class="right-info">
<span data-ice="source"><span><a href="file/src/lib/components/Keyboard.js.html#lineNumber158">source</a></span></span>
<span data-ice="source"><span><a href="file/src/lib/components/Keyboard.js.html#lineNumber160">source</a></span></span>
</span>
</h3>
@@ -2865,7 +2870,7 @@ Used interally between re-renders.</p>
<span class="right-info">
<span data-ice="source"><span><a href="file/src/lib/components/Keyboard.js.html#lineNumber265">source</a></span></span>
<span data-ice="source"><span><a href="file/src/lib/components/Keyboard.js.html#lineNumber267">source</a></span></span>
</span>
</h3>
@@ -2925,7 +2930,7 @@ Used interally between re-renders.</p>
<span class="right-info">
<span data-ice="source"><span><a href="file/src/lib/components/Keyboard.js.html#lineNumber218">source</a></span></span>
<span data-ice="source"><span><a href="file/src/lib/components/Keyboard.js.html#lineNumber220">source</a></span></span>
</span>
</h3>
@@ -2991,7 +2996,7 @@ Used interally between re-renders.</p>
<span class="right-info">
<span data-ice="source"><span><a href="file/src/lib/components/Keyboard.js.html#lineNumber255">source</a></span></span>
<span data-ice="source"><span><a href="file/src/lib/components/Keyboard.js.html#lineNumber257">source</a></span></span>
</span>
</h3>
@@ -3035,7 +3040,7 @@ Used interally between re-renders.</p>
<span class="right-info">
<span data-ice="source"><span><a href="file/src/lib/components/Keyboard.js.html#lineNumber506">source</a></span></span>
<span data-ice="source"><span><a href="file/src/lib/components/Keyboard.js.html#lineNumber508">source</a></span></span>
</span>
</h3>
@@ -3079,7 +3084,7 @@ Used interally between re-renders.</p>
<span class="right-info">
<span data-ice="source"><span><a href="file/src/lib/components/Keyboard.js.html#lineNumber589">source</a></span></span>
<span data-ice="source"><span><a href="file/src/lib/components/Keyboard.js.html#lineNumber610">source</a></span></span>
</span>
</h3>
@@ -3123,7 +3128,7 @@ Used interally between re-renders.</p>
<span class="right-info">
<span data-ice="source"><span><a href="file/src/lib/components/Keyboard.js.html#lineNumber546">source</a></span></span>
<span data-ice="source"><span><a href="file/src/lib/components/Keyboard.js.html#lineNumber567">source</a></span></span>
</span>
</h3>
@@ -3167,7 +3172,7 @@ Used interally between re-renders.</p>
<span class="right-info">
<span data-ice="source"><span><a href="file/src/lib/components/Keyboard.js.html#lineNumber571">source</a></span></span>
<span data-ice="source"><span><a href="file/src/lib/components/Keyboard.js.html#lineNumber592">source</a></span></span>
</span>
</h3>
@@ -3211,7 +3216,7 @@ Used interally between re-renders.</p>
<span class="right-info">
<span data-ice="source"><span><a href="file/src/lib/components/Keyboard.js.html#lineNumber563">source</a></span></span>
<span data-ice="source"><span><a href="file/src/lib/components/Keyboard.js.html#lineNumber584">source</a></span></span>
</span>
</h3>
@@ -3255,7 +3260,7 @@ Used interally between re-renders.</p>
<span class="right-info">
<span data-ice="source"><span><a href="file/src/lib/components/Keyboard.js.html#lineNumber436">source</a></span></span>
<span data-ice="source"><span><a href="file/src/lib/components/Keyboard.js.html#lineNumber438">source</a></span></span>
</span>
</h3>
@@ -3335,7 +3340,7 @@ Used interally between re-renders.</p>
<span class="right-info">
<span data-ice="source"><span><a href="file/src/lib/components/Keyboard.js.html#lineNumber630">source</a></span></span>
<span data-ice="source"><span><a href="file/src/lib/components/Keyboard.js.html#lineNumber651">source</a></span></span>
</span>
</h3>
@@ -3379,7 +3384,7 @@ Used interally between re-renders.</p>
<span class="right-info">
<span data-ice="source"><span><a href="file/src/lib/components/Keyboard.js.html#lineNumber342">source</a></span></span>
<span data-ice="source"><span><a href="file/src/lib/components/Keyboard.js.html#lineNumber344">source</a></span></span>
</span>
</h3>
@@ -3440,7 +3445,7 @@ Used interally between re-renders.</p>
<span class="right-info">
<span data-ice="source"><span><a href="file/src/lib/components/Keyboard.js.html#lineNumber327">source</a></span></span>
<span data-ice="source"><span><a href="file/src/lib/components/Keyboard.js.html#lineNumber329">source</a></span></span>
</span>
</h3>
@@ -3508,7 +3513,7 @@ Used interally between re-renders.</p>
<span class="right-info">
<span data-ice="source"><span><a href="file/src/lib/components/Keyboard.js.html#lineNumber285">source</a></span></span>
<span data-ice="source"><span><a href="file/src/lib/components/Keyboard.js.html#lineNumber287">source</a></span></span>
</span>
</h3>

View File

@@ -501,6 +501,35 @@
<td>
</td>
</tr>
<tr data-ice="target">
<td>
<span class="access" data-ice="access">public</span>
<span class="override" data-ice="override"></span>
</td>
<td>
<div>
<p>
<span class="code" data-ice="name"><span><a href="class/src/lib/services/Utilities.js~Utilities.html#instance-method-updateCaretPosAction">updateCaretPosAction</a></span></span><span class="code" data-ice="signature">(instance: <span><a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object">object</a></span>, length: <span><a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number">number</a></span>, minus: <span><a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Boolean">boolean</a></span>)</span>
</p>
</div>
<div>
<div data-ice="description"><p>Action method of updateCaretPos</p>
</div>
</div>
</td>
<td>
</td>
</tr>
</tbody>
@@ -572,7 +601,7 @@
<span class="right-info">
<span data-ice="source"><span><a href="file/src/lib/services/Utilities.js.html#lineNumber308">source</a></span></span>
<span data-ice="source"><span><a href="file/src/lib/services/Utilities.js.html#lineNumber322">source</a></span></span>
</span>
</h3>
@@ -661,7 +690,7 @@
<span class="right-info">
<span data-ice="source"><span><a href="file/src/lib/services/Utilities.js.html#lineNumber202">source</a></span></span>
<span data-ice="source"><span><a href="file/src/lib/services/Utilities.js.html#lineNumber224">source</a></span></span>
</span>
</h3>
@@ -755,7 +784,7 @@
<span class="right-info">
<span data-ice="source"><span><a href="file/src/lib/services/Utilities.js.html#lineNumber345">source</a></span></span>
<span data-ice="source"><span><a href="file/src/lib/services/Utilities.js.html#lineNumber359">source</a></span></span>
</span>
</h3>
@@ -828,7 +857,7 @@
<span class="right-info">
<span data-ice="source"><span><a href="file/src/lib/services/Utilities.js.html#lineNumber355">source</a></span></span>
<span data-ice="source"><span><a href="file/src/lib/services/Utilities.js.html#lineNumber369">source</a></span></span>
</span>
</h3>
@@ -908,7 +937,7 @@
<span class="right-info">
<span data-ice="source"><span><a href="file/src/lib/services/Utilities.js.html#lineNumber32">source</a></span></span>
<span data-ice="source"><span><a href="file/src/lib/services/Utilities.js.html#lineNumber33">source</a></span></span>
</span>
</h3>
@@ -982,7 +1011,7 @@
<span class="right-info">
<span data-ice="source"><span><a href="file/src/lib/services/Utilities.js.html#lineNumber116">source</a></span></span>
<span data-ice="source"><span><a href="file/src/lib/services/Utilities.js.html#lineNumber117">source</a></span></span>
</span>
</h3>
@@ -1069,7 +1098,7 @@
<span class="right-info">
<span data-ice="source"><span><a href="file/src/lib/services/Utilities.js.html#lineNumber46">source</a></span></span>
<span data-ice="source"><span><a href="file/src/lib/services/Utilities.js.html#lineNumber47">source</a></span></span>
</span>
</h3>
@@ -1125,7 +1154,7 @@
<span class="right-info">
<span data-ice="source"><span><a href="file/src/lib/services/Utilities.js.html#lineNumber136">source</a></span></span>
<span data-ice="source"><span><a href="file/src/lib/services/Utilities.js.html#lineNumber137">source</a></span></span>
</span>
</h3>
@@ -1226,7 +1255,7 @@
<span class="right-info">
<span data-ice="source"><span><a href="file/src/lib/services/Utilities.js.html#lineNumber284">source</a></span></span>
<span data-ice="source"><span><a href="file/src/lib/services/Utilities.js.html#lineNumber298">source</a></span></span>
</span>
</h3>
@@ -1310,7 +1339,7 @@
<span class="right-info">
<span data-ice="source"><span><a href="file/src/lib/services/Utilities.js.html#lineNumber336">source</a></span></span>
<span data-ice="source"><span><a href="file/src/lib/services/Utilities.js.html#lineNumber350">source</a></span></span>
</span>
</h3>
@@ -1366,7 +1395,7 @@
<span class="right-info">
<span data-ice="source"><span><a href="file/src/lib/services/Utilities.js.html#lineNumber233">source</a></span></span>
<span data-ice="source"><span><a href="file/src/lib/services/Utilities.js.html#lineNumber251">source</a></span></span>
</span>
</h3>
@@ -1453,7 +1482,7 @@
<span class="right-info">
<span data-ice="source"><span><a href="file/src/lib/services/Utilities.js.html#lineNumber185">source</a></span></span>
<span data-ice="source"><span><a href="file/src/lib/services/Utilities.js.html#lineNumber186">source</a></span></span>
</span>
</h3>
@@ -1508,6 +1537,81 @@
</div>
<div class="detail" data-ice="detail">
<h3 data-ice="anchor" id="instance-method-updateCaretPosAction">
<span class="access" data-ice="access">public</span>
<span class="code" data-ice="name">updateCaretPosAction</span><span class="code" data-ice="signature">(instance: <span><a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object">object</a></span>, length: <span><a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number">number</a></span>, minus: <span><a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Boolean">boolean</a></span>)</span>
<span class="right-info">
<span data-ice="source"><span><a href="file/src/lib/services/Utilities.js.html#lineNumber203">source</a></span></span>
</span>
</h3>
<div data-ice="description"><p>Action method of updateCaretPos</p>
</div>
<div data-ice="properties"><div data-ice="properties">
<h4 data-ice="title">Params:</h4>
<table class="params">
<thead>
<tr><td>Name</td><td>Type</td><td>Attribute</td><td>Description</td></tr>
</thead>
<tbody>
<tr data-ice="property" data-depth="0">
<td data-ice="name" class="code" data-depth="0">instance</td>
<td data-ice="type" class="code"><span><a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object">object</a></span></td>
<td data-ice="appendix"></td>
<td data-ice="description"><p>The instance whose position should be updated</p>
</td>
</tr>
<tr data-ice="property" data-depth="0">
<td data-ice="name" class="code" data-depth="0">length</td>
<td data-ice="type" class="code"><span><a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number">number</a></span></td>
<td data-ice="appendix"></td>
<td data-ice="description"><p>Represents by how many characters the input should be moved</p>
</td>
</tr>
<tr data-ice="property" data-depth="0">
<td data-ice="name" class="code" data-depth="0">minus</td>
<td data-ice="type" class="code"><span><a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Boolean">boolean</a></span></td>
<td data-ice="appendix"></td>
<td data-ice="description"><p>Whether the cursor should be moved to the left or not.</p>
</td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
</div>
</div>

View File

@@ -1,7 +1,7 @@
{
"coverage": "100%",
"expectCount": 77,
"actualCount": 77,
"expectCount": 78,
"actualCount": 78,
"files": {
"src/demo/App.js": {
"expectCount": 8,
@@ -24,8 +24,8 @@
"undocumentLines": []
},
"src/lib/services/Utilities.js": {
"expectCount": 15,
"actualCount": 15,
"expectCount": 16,
"actualCount": 16,
"undocumentLines": []
},
"src/lib/tests/TestUtility.js": {

View File

@@ -85,7 +85,7 @@ class App {
&lt;/div&gt;
`);
document.querySelector(&apos;.input&apos;).addEventListener(&apos;change&apos;, (event) =&gt; {
document.querySelector(&apos;.input&apos;).addEventListener(&apos;input&apos;, (event) =&gt; {
this.keyboard.setInput(event.target.value);
});
}

View File

@@ -92,8 +92,9 @@ class SimpleKeyboard {
* @property {object} maxLength Restrains simple-keyboard&#x2019;s individual inputs to a certain length. This should be used in addition to the input element&#x2019;s maxlengthattribute.
* @property {boolean} syncInstanceInputs When set to true, this option synchronizes the internal input of every simple-keyboard instance.
* @property {boolean} physicalKeyboardHighlight Enable highlighting of keys pressed on physical keyboard.
* @property {boolean} preventMouseDownDefault Calling preventDefault for the mousedown events keeps the focus on the input.
* @property {string} physicalKeyboardHighlightTextColor Define the text color that the physical keyboard highlighted key should have.
* @property {string} physicalKeyboardHighlightBgColor Define the background color that the physical keyboard highlighted key should have.
* @property {string} physicalKeyboardHighlightBgColor Define the background color that the physical keyboard highlighted key should have.
* @property {function(button: string):string} onKeyPress Executes the callback function on key press. Returns button layout name (i.e.: &#x201C;{shift}&#x201D;).
* @property {function(input: string):string} onChange Executes the callback function on input change. Returns the current input&#x2019;s string.
* @property {function} onRender Executes the callback function every time simple-keyboard is rendered (e.g: when you change layouts).
@@ -104,6 +105,7 @@ class SimpleKeyboard {
this.options.layoutName = this.options.layoutName || &quot;default&quot;;
this.options.theme = this.options.theme || &quot;hg-theme-default&quot;;
this.options.inputName = this.options.inputName || &quot;default&quot;;
this.options.preventMouseDownDefault = this.options.preventMouseDownDefault === false ? false : true;
/**
* @type {object} Classes identifying loaded plugins
@@ -336,7 +338,7 @@ class SimpleKeyboard {
*/
clearInput(inputName){
inputName = inputName || this.options.inputName;
this.input[this.options.inputName] = &apos;&apos;;
this.input[inputName] = &apos;&apos;;
/**
* Enforce syncInstanceInputs, if set
@@ -546,40 +548,59 @@ class SimpleKeyboard {
* Retrieves the current cursor position within a input or textarea (if any)
*/
handleCaret(){
/**
* Only first instance should insall the caret handling events
*/
this.caretPosition = null;
let simpleKeyboardInstances = window[&apos;SimpleKeyboardInstances&apos;];
if(
(
simpleKeyboardInstances &amp;&amp;
Object.keys(simpleKeyboardInstances)[0] === this.utilities.camelCase(this.keyboardDOMClass)
) ||
!simpleKeyboardInstances
){
if(this.options.debug){
console.log(&quot;Caret handling started&quot;);
console.log(`Caret handling started (${this.keyboardDOMClass})`)
}
document.addEventListener(&quot;keyup&quot;, this.caretEventHandler);
document.addEventListener(&quot;mouseup&quot;, this.caretEventHandler);
document.addEventListener(&quot;touchend&quot;, this.caretEventHandler);
}
}
/**
* Called by {@link handleCaret} when an event that warrants a cursor position update is triggered
*/
caretEventHandler(event){
let targetTagName;
if(event.target.tagName){
targetTagName = event.target.tagName.toLowerCase();
}
this.dispatch(instance =&gt; {
if(instance.isMouseHold){
instance.isMouseHold = false;
}
if(
(targetTagName === &quot;textarea&quot; ||
targetTagName === &quot;input&quot;) &amp;&amp;
!this.options.disableCaretPositioning
!instance.options.disableCaretPositioning
){
/**
* Tracks current cursor position
* As keys are pressed, text will be added/removed at that position within the input.
*/
this.caretPosition = event.target.selectionStart;
instance.caretPosition = event.target.selectionStart;
if(this.options.debug){
console.log(&apos;Caret at: &apos;, event.target.selectionStart, event.target.tagName.toLowerCase());
if(instance.options.debug){
console.log(&apos;Caret at: &apos;, event.target.selectionStart, event.target.tagName.toLowerCase(), `(${instance.keyboardDOMClass})`);
}
}
});
}
/**
@@ -587,7 +608,7 @@ class SimpleKeyboard {
*/
onInit(){
if(this.options.debug){
console.log(&quot;Initialized&quot;);
console.log(`${this.keyboardDOMClass} Initialized`)
}
/**
@@ -677,6 +698,7 @@ class SimpleKeyboard {
let layoutClass = this.options.layout ? &quot;hg-layout-custom&quot; : `hg-layout-${this.options.layoutName}`;
let layout = this.options.layout || KeyboardLayout.getDefaultLayout();
let useTouchEvents = this.options.useTouchEvents || false
/**
* Account for buttonTheme, if set
@@ -742,12 +764,25 @@ class SimpleKeyboard {
*/
var buttonDOM = document.createElement(&apos;div&apos;);
buttonDOM.className += `hg-button ${fctBtnClass}${buttonThemeClass ? &quot; &quot;+buttonThemeClass : &quot;&quot;}`;
buttonDOM.onclick = () =&gt; {
this.isMouseHold = false;
this.handleButtonClicked(button);
if (useTouchEvents) {
buttonDOM.ontouchstart = (e) =&gt; {
this.handleButtonClicked(button);
this.handleButtonMouseDown(button, e);
}
buttonDOM.ontouchend = e =&gt; this.handleButtonMouseUp();
buttonDOM.ontouchcancel = e =&gt; this.handleButtonMouseUp();
} else {
buttonDOM.onclick = () =&gt; {
this.isMouseHold = false;
this.handleButtonClicked(button);
}
buttonDOM.onmousedown = (e) =&gt; {
if (this.options.preventMouseDownDefault) e.preventDefault();
this.handleButtonMouseDown(button, e);
}
}
buttonDOM.onmousedown = (e) =&gt; this.handleButtonMouseDown(button, e);
/**
* Adding identifier
*/
@@ -798,17 +833,19 @@ class SimpleKeyboard {
*/
this.onRender();
/**
* Handling mouseup
*/
document.onmouseup = () =&gt; this.handleButtonMouseUp();
if(!this.initialized){
/**
* Ensures that onInit is only called once per instantiation
*/
this.initialized = true;
/**
* Handling mouseup
*/
if (!useTouchEvents) {
document.onmouseup = () =&gt; this.handleButtonMouseUp();
}
/**
* Calling onInit
*/

View File

@@ -60,6 +60,7 @@ class Utilities {
this.getButtonDisplayName = this.getButtonDisplayName.bind(this);
this.getUpdatedInput = this.getUpdatedInput.bind(this);
this.updateCaretPos = this.updateCaretPos.bind(this);
this.updateCaretPosAction = this.updateCaretPosAction.bind(this);
this.isMaxLengthReached = this.isMaxLengthReached.bind(this);
this.camelCase = this.camelCase.bind(this);
this.countInArray = this.countInArray.bind(this);
@@ -225,11 +226,32 @@ class Utilities {
* @param {boolean} minus Whether the cursor should be moved to the left or not.
*/
updateCaretPos(length, minus){
if(minus){
if(this.simpleKeyboardInstance.caretPosition &gt; 0)
this.simpleKeyboardInstance.caretPosition = this.simpleKeyboardInstance.caretPosition - length;
if(this.simpleKeyboardInstance.options.syncInstanceInputs){
this.simpleKeyboardInstance.dispatch(instance =&gt; {
this.updateCaretPosAction(instance, length, minus);
});
} else {
this.simpleKeyboardInstance.caretPosition = this.simpleKeyboardInstance.caretPosition + length;
this.updateCaretPosAction(this.simpleKeyboardInstance, length, minus);
}
}
/**
* Action method of updateCaretPos
*
* @param {object} instance The instance whose position should be updated
* @param {number} length Represents by how many characters the input should be moved
* @param {boolean} minus Whether the cursor should be moved to the left or not.
*/
updateCaretPosAction(instance, length, minus){
if(minus){
if(instance.caretPosition &gt; 0)
instance.caretPosition = instance.caretPosition - length;
} else {
instance.caretPosition = instance.caretPosition + length;
}
if(this.simpleKeyboardInstance.options.debug){
console.log(&quot;Caret at:&quot;, instance.caretPosition, `(${instance.keyboardDOMClass})`);
}
}
@@ -258,10 +280,6 @@ class Utilities {
}
if(this.simpleKeyboardInstance.options.debug &amp;&amp; moveCaret){
console.log(&quot;Caret at:&quot;, position);
}
return output;
}
@@ -310,10 +328,6 @@ class Utilities {
}
}
if(this.simpleKeyboardInstance.options.debug &amp;&amp; moveCaret){
console.log(&quot;Caret at:&quot;, this.simpleKeyboardInstance.caretPosition);
}
return output;
}
/**
@@ -397,7 +411,6 @@ class Utilities {
countInArray(array, value){
return array.reduce((n, x) =&gt; n + (x === value), 0);
}
}
export default Utilities;</code></pre>

File diff suppressed because one or more lines are too long

View File

@@ -755,6 +755,12 @@ window.esdocSearchIndex = [
"src/lib/services/Utilities.js~Utilities#updateCaretPos",
"method"
],
[
"src/lib/services/utilities.js~utilities#updatecaretposaction",
"class/src/lib/services/Utilities.js~Utilities.html#instance-method-updateCaretPosAction",
"src/lib/services/Utilities.js~Utilities#updateCaretPosAction",
"method"
],
[
"src/lib/tests/testutility.js",
"file/src/lib/tests/TestUtility.js.html",

View File

@@ -39,7 +39,7 @@
</div>
</nav>
<div class="content" data-ice="content"><h1>Source <img data-ice="coverageBadge" src="./badge.svg"><span data-ice="totalCoverageCount" class="total-coverage-count">77/77</span></h1>
<div class="content" data-ice="content"><h1>Source <img data-ice="coverageBadge" src="./badge.svg"><span data-ice="totalCoverageCount" class="total-coverage-count">78/78</span></h1>
<table class="files-summary" data-ice="files" data-use-coverage="true">
<thead>
@@ -58,9 +58,9 @@
<td data-ice="filePath"><span><a href="file/src/demo/App.js.html">src/demo/App.js</a></span></td>
<td data-ice="identifier" class="identifiers"><span><a href="class/src/demo/App.js~App.html">App</a></span></td>
<td class="coverage"><span data-ice="coverage">100 %</span><span data-ice="coverageCount" class="coverage-count">8/8</span></td>
<td style="display: none;" data-ice="size">1919 byte</td>
<td style="display: none;" data-ice="size">1918 byte</td>
<td style="display: none;" data-ice="lines">84</td>
<td style="display: none;" data-ice="updated">2018-11-02 22:34:11 (UTC)</td>
<td style="display: none;" data-ice="updated">2018-11-01 01:59:07 (UTC)</td>
</tr>
<tr data-ice="file">
<td data-ice="filePath"><span><a href="file/src/demo/index.js.html">src/demo/index.js</a></span></td>
@@ -68,15 +68,15 @@
<td class="coverage"><span data-ice="coverage">-</span></td>
<td style="display: none;" data-ice="size">70 byte</td>
<td style="display: none;" data-ice="lines">5</td>
<td style="display: none;" data-ice="updated">2018-09-02 03:31:31 (UTC)</td>
<td style="display: none;" data-ice="updated">2018-11-06 21:41:50 (UTC)</td>
</tr>
<tr data-ice="file">
<td data-ice="filePath"><span><a href="file/src/lib/components/Keyboard.js.html">src/lib/components/Keyboard.js</a></span></td>
<td data-ice="identifier" class="identifiers"><span><a href="class/src/lib/components/Keyboard.js~SimpleKeyboard.html">SimpleKeyboard</a></span></td>
<td class="coverage"><span data-ice="coverage">100 %</span><span data-ice="coverageCount" class="coverage-count">41/41</span></td>
<td style="display: none;" data-ice="size">24942 byte</td>
<td style="display: none;" data-ice="lines">778</td>
<td style="display: none;" data-ice="updated">2018-11-06 15:50:43 (UTC)</td>
<td style="display: none;" data-ice="size">26391 byte</td>
<td style="display: none;" data-ice="lines">815</td>
<td style="display: none;" data-ice="updated">2018-11-01 01:52:55 (UTC)</td>
</tr>
<tr data-ice="file">
<td data-ice="filePath"><span><a href="file/src/lib/index.js.html">src/lib/index.js</a></span></td>
@@ -84,7 +84,7 @@
<td class="coverage"><span data-ice="coverage">-</span></td>
<td style="display: none;" data-ice="size">85 byte</td>
<td style="display: none;" data-ice="lines">2</td>
<td style="display: none;" data-ice="updated">2018-06-06 23:02:53 (UTC)</td>
<td style="display: none;" data-ice="updated">2018-11-06 21:41:50 (UTC)</td>
</tr>
<tr data-ice="file">
<td data-ice="filePath"><span><a href="file/src/lib/services/KeyboardLayout.js.html">src/lib/services/KeyboardLayout.js</a></span></td>
@@ -92,7 +92,7 @@
<td class="coverage"><span data-ice="coverage">100 %</span><span data-ice="coverageCount" class="coverage-count">2/2</span></td>
<td style="display: none;" data-ice="size">746 byte</td>
<td style="display: none;" data-ice="lines">28</td>
<td style="display: none;" data-ice="updated">2018-10-03 02:14:58 (UTC)</td>
<td style="display: none;" data-ice="updated">2018-11-06 21:41:48 (UTC)</td>
</tr>
<tr data-ice="file">
<td data-ice="filePath"><span><a href="file/src/lib/services/PhysicalKeyboard.js.html">src/lib/services/PhysicalKeyboard.js</a></span></td>
@@ -100,15 +100,15 @@
<td class="coverage"><span data-ice="coverage">100 %</span><span data-ice="coverageCount" class="coverage-count">5/5</span></td>
<td style="display: none;" data-ice="size">2908 byte</td>
<td style="display: none;" data-ice="lines">96</td>
<td style="display: none;" data-ice="updated">2018-11-06 15:54:53 (UTC)</td>
<td style="display: none;" data-ice="updated">2018-11-06 21:41:48 (UTC)</td>
</tr>
<tr data-ice="file">
<td data-ice="filePath"><span><a href="file/src/lib/services/Utilities.js.html">src/lib/services/Utilities.js</a></span></td>
<td data-ice="identifier" class="identifiers"><span><a href="class/src/lib/services/Utilities.js~Utilities.html">Utilities</a></span></td>
<td class="coverage"><span data-ice="coverage">100 %</span><span data-ice="coverageCount" class="coverage-count">15/15</span></td>
<td style="display: none;" data-ice="size">11188 byte</td>
<td style="display: none;" data-ice="lines">360</td>
<td style="display: none;" data-ice="updated">2018-11-02 22:28:58 (UTC)</td>
<td class="coverage"><span data-ice="coverage">100 %</span><span data-ice="coverageCount" class="coverage-count">16/16</span></td>
<td style="display: none;" data-ice="size">11708 byte</td>
<td style="display: none;" data-ice="lines">373</td>
<td style="display: none;" data-ice="updated">2018-11-01 01:55:18 (UTC)</td>
</tr>
<tr data-ice="file">
<td data-ice="filePath"><span><a href="file/src/lib/tests/TestUtility.js.html">src/lib/tests/TestUtility.js</a></span></td>
@@ -116,7 +116,7 @@
<td class="coverage"><span data-ice="coverage">100 %</span><span data-ice="coverageCount" class="coverage-count">6/6</span></td>
<td style="display: none;" data-ice="size">2830 byte</td>
<td style="display: none;" data-ice="lines">106</td>
<td style="display: none;" data-ice="updated">2018-10-04 22:12:09 (UTC)</td>
<td style="display: none;" data-ice="updated">2018-11-06 21:41:47 (UTC)</td>
</tr>
</tbody>
</table>

4721
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -1,11 +1,12 @@
{
"name": "simple-keyboard",
"version": "2.8.0",
"version": "2.17.0",
"description": "On-screen Javascript Virtual Keyboard",
"main": "build/index.js",
"types": "build/index.d.ts",
"scripts": {
"start": "node scripts/start.js",
"build": "node scripts/build.js",
"build": "node scripts/build.js && node scripts/buildUnminified.js",
"demo": "node scripts/demo.js",
"test": "node scripts/test.js",
"postinstall": "node bin/postinstall",
@@ -34,69 +35,82 @@
"touchscreen",
"touch-screen",
"kiosk",
"osk"
"osk",
"js"
],
"license": "MIT",
"devDependencies": {
"@babel/core": "7.1.0",
"@svgr/webpack": "2.4.1",
"@babel/core": "7.3.4",
"@babel/plugin-proposal-class-properties": "^7.3.4",
"@babel/preset-env": "^7.3.4",
"@babel/preset-react": "^7.0.0",
"@svgr/webpack": "4.1.0",
"babel-core": "7.0.0-bridge.0",
"babel-eslint": "9.0.0",
"babel-eslint": "10.0.1",
"babel-jest": "23.6.0",
"babel-loader": "8.0.4",
"babel-plugin-named-asset-import": "^0.2.3",
"babel-preset-react-app": "^6.1.0",
"babel-loader": "8.0.5",
"babel-plugin-named-asset-import": "^0.3.1",
"babel-preset-react-app": "^7.0.1",
"bfj": "6.1.1",
"case-sensitive-paths-webpack-plugin": "2.1.2",
"chalk": "2.4.1",
"css-loader": "1.0.0",
"dotenv": "6.0.0",
"case-sensitive-paths-webpack-plugin": "2.2.0",
"chalk": "2.4.2",
"copy-webpack-plugin": "^5.0.0",
"css-loader": "2.1.0",
"dotenv": "6.2.0",
"dotenv-expand": "4.2.0",
"eslint": "5.6.0",
"eslint-config-react-app": "^3.0.5",
"eslint-loader": "2.1.1",
"eslint-plugin-flowtype": "2.50.1",
"eslint-plugin-import": "2.14.0",
"eslint-plugin-jsx-a11y": "6.1.2",
"eslint-plugin-react": "7.11.1",
"file-loader": "2.0.0",
"fork-ts-checker-webpack-plugin-alt": "0.4.14",
"fs-extra": "7.0.0",
"html-webpack-plugin": "4.0.0-alpha.2",
"identity-obj-proxy": "3.0.0",
"jest": "23.6.0",
"jest-pnp-resolver": "1.0.1",
"jest-resolve": "23.6.0",
"mini-css-extract-plugin": "0.4.3",
"optimize-css-assets-webpack-plugin": "5.0.1",
"pnp-webpack-plugin": "1.1.0",
"postcss-flexbugs-fixes": "4.1.0",
"postcss-loader": "3.0.0",
"postcss-preset-env": "6.0.6",
"postcss-safe-parser": "4.0.1",
"react": "^16.6.1",
"react-app-polyfill": "^0.1.3",
"react-dev-utils": "^6.1.1",
"react-dom": "^16.6.1",
"resolve": "1.8.1",
"sass-loader": "7.1.0",
"style-loader": "0.23.0",
"terser-webpack-plugin": "1.1.0",
"url-loader": "1.1.1",
"webpack": "4.19.1",
"webpack-dev-server": "3.1.9",
"webpack-manifest-plugin": "2.0.4",
"workbox-webpack-plugin": "3.6.3",
"esdoc": "^1.1.0",
"esdoc-ecmascript-proposal-plugin": "^1.0.0",
"esdoc-standard-plugin": "^1.0.0"
"esdoc-standard-plugin": "^1.0.0",
"eslint": "5.15.0",
"eslint-config-react-app": "^3.0.7",
"eslint-loader": "2.1.2",
"eslint-plugin-flowtype": "3.4.2",
"eslint-plugin-import": "2.16.0",
"eslint-plugin-jsx-a11y": "6.2.1",
"eslint-plugin-react": "7.12.4",
"file-loader": "3.0.1",
"fork-ts-checker-webpack-plugin-alt": "0.4.14",
"fs-extra": "7.0.1",
"html-webpack-plugin": "4.0.0-beta.5",
"identity-obj-proxy": "3.0.0",
"jest": "23.6.0",
"jest-pnp-resolver": "1.0.2",
"jest-resolve": "23.6.0",
"mini-css-extract-plugin": "0.5.0",
"optimize-css-assets-webpack-plugin": "5.0.1",
"pnp-webpack-plugin": "1.3.1",
"postcss-flexbugs-fixes": "4.1.0",
"postcss-loader": "3.0.0",
"postcss-preset-env": "6.6.0",
"postcss-safe-parser": "4.0.1",
"prettier": "^1.16.4",
"prettier-webpack-plugin": "^1.2.0",
"react": "^16.8.3",
"react-app-polyfill": "^0.2.1",
"react-dev-utils": "^7.0.3",
"react-dom": "^16.8.3",
"resolve": "1.10.0",
"sass-loader": "7.1.0",
"style-loader": "0.23.1",
"terser-webpack-plugin": "1.2.3",
"uglifyjs-webpack-plugin": "^2.1.2",
"url-loader": "1.1.2",
"webpack": "4.29.6",
"webpack-dev-server": "3.2.1",
"webpack-manifest-plugin": "2.0.4",
"workbox-webpack-plugin": "4.0.0"
},
"eslintConfig": {
"extends": "react-app"
"extends": "react-app",
"settings": {
"react": {
"pragma": "React",
"version": "detect"
}
}
},
"browserslist": [
">0.2%",
"not dead",
"not ie <= 11",
"not op_mini all"
],
@@ -144,7 +158,13 @@
},
"babel": {
"presets": [
"react-app"
"@babel/preset-env",
"@babel/preset-react"
],
"plugins": [
[
"@babel/plugin-proposal-class-properties"
]
]
}
}

189
scripts/buildUnminified.js Normal file
View File

@@ -0,0 +1,189 @@
'use strict';
// Do this as the first thing so that any code reading it knows the right env.
process.env.BABEL_ENV = 'production';
process.env.NODE_ENV = 'production';
// Makes the script crash on unhandled rejections instead of silently
// ignoring them. In the future, promise rejections that are not handled will
// terminate the Node.js process with a non-zero exit code.
process.on('unhandledRejection', err => {
throw err;
});
// Ensure environment variables are read.
require('../config/env');
const path = require('path');
const chalk = require('chalk');
const fs = require('fs-extra');
const webpack = require('webpack');
const bfj = require('bfj');
const config = require('../config/webpack.config.unminified');
const paths = require('../config/paths');
const checkRequiredFiles = require('react-dev-utils/checkRequiredFiles');
const formatWebpackMessages = require('react-dev-utils/formatWebpackMessages');
const printHostingInstructions = require('react-dev-utils/printHostingInstructions');
const FileSizeReporter = require('react-dev-utils/FileSizeReporter');
const printBuildError = require('react-dev-utils/printBuildError');
const measureFileSizesBeforeBuild =
FileSizeReporter.measureFileSizesBeforeBuild;
const printFileSizesAfterBuild = FileSizeReporter.printFileSizesAfterBuild;
const useYarn = fs.existsSync(paths.yarnLockFile);
// These sizes are pretty large. We'll warn for bundles exceeding them.
const WARN_AFTER_BUNDLE_GZIP_SIZE = 512 * 1024;
const WARN_AFTER_CHUNK_GZIP_SIZE = 1024 * 1024;
const isInteractive = process.stdout.isTTY;
// Warn and crash if required files are missing
if (!checkRequiredFiles([paths.appHtml, paths.appIndexJs])) {
process.exit(1);
}
// Process CLI arguments
const argv = process.argv.slice(2);
const writeStatsJson = argv.indexOf('--stats') !== -1;
// We require that you explicitly set browsers and do not fall back to
// browserslist defaults.
const { checkBrowsers } = require('react-dev-utils/browsersHelper');
checkBrowsers(paths.appPath, isInteractive)
.then(() => {
// First, read the current file sizes in build directory.
// This lets us display how much they changed later.
return measureFileSizesBeforeBuild(paths.appBuild);
})
.then(previousFileSizes => {
// Remove all content but keep the directory so that
// if you're in it, you don't end up in Trash
//fs.emptyDirSync(paths.appBuild);
// Merge with the public folder
//copyPublicFolder();
// Start the webpack build
return build(previousFileSizes);
})
.then(
({ stats, previousFileSizes, warnings }) => {
if (warnings.length) {
console.log(chalk.yellow('Compiled with warnings.\n'));
console.log(warnings.join('\n\n'));
console.log(
'\nSearch for the ' +
chalk.underline(chalk.yellow('keywords')) +
' to learn more about each warning.'
);
console.log(
'To ignore, add ' +
chalk.cyan('// eslint-disable-next-line') +
' to the line before.\n'
);
} else {
console.log(chalk.green('Compiled successfully.\n'));
}
console.log('File sizes after gzip:\n');
printFileSizesAfterBuild(
stats,
previousFileSizes,
paths.appBuild,
WARN_AFTER_BUNDLE_GZIP_SIZE,
WARN_AFTER_CHUNK_GZIP_SIZE
);
console.log();
const appPackage = require(paths.appPackageJson);
const publicUrl = paths.publicUrl;
const publicPath = config.output.publicPath;
const buildFolder = path.relative(process.cwd(), paths.appBuild);
printHostingInstructions(
appPackage,
publicUrl,
publicPath,
buildFolder,
useYarn
);
},
err => {
console.log(chalk.red('Failed to compile.\n'));
printBuildError(err);
process.exit(1);
}
)
.catch(err => {
if (err && err.message) {
console.log(err.message);
}
process.exit(1);
});
// Create the production build and print the deployment instructions.
function build(previousFileSizes) {
console.log('Creating a non-minified production build...');
let compiler = webpack(config);
return new Promise((resolve, reject) => {
compiler.run((err, stats) => {
let messages;
if (err) {
if (!err.message) {
return reject(err);
}
messages = formatWebpackMessages({
errors: [err.message],
warnings: [],
});
} else {
messages = formatWebpackMessages(
stats.toJson({ all: false, warnings: true, errors: true })
);
}
if (messages.errors.length) {
// Only keep the first error. Others are often indicative
// of the same problem, but confuse the reader with noise.
if (messages.errors.length > 1) {
messages.errors.length = 1;
}
return reject(new Error(messages.errors.join('\n\n')));
}
if (
process.env.CI &&
(typeof process.env.CI !== 'string' ||
process.env.CI.toLowerCase() !== 'false') &&
messages.warnings.length
) {
console.log(
chalk.yellow(
'\nTreating warnings as errors because process.env.CI = true.\n' +
'Most CI servers set it automatically.\n'
)
);
return reject(new Error(messages.warnings.join('\n\n')));
}
const resolveArgs = {
stats,
previousFileSizes,
warnings: messages.warnings,
};
if (writeStatsJson) {
return bfj
.write(paths.appBuild + '/bundle-stats.json', stats.toJson())
.then(() => resolve(resolveArgs))
.catch(error => reject(new Error(error)));
}
return resolve(resolveArgs);
});
});
}
function copyPublicFolder() {
fs.copySync(paths.appPublic, paths.appBuild, {
dereference: true,
filter: file => file !== paths.appHtml,
});
}

View File

@@ -31,7 +31,7 @@ class App {
onChange: input => this.onChange(input),
onKeyPress: button => this.onKeyPress(button),
newLineOnEnter: true,
physicalKeyboardHighlight: true,
physicalKeyboardHighlight: true
});
/**
@@ -43,7 +43,7 @@ class App {
</div>
`);
document.querySelector('.input').addEventListener('change', (event) => {
document.querySelector('.input').addEventListener('input', (event) => {
this.keyboard.setInput(event.target.value);
});
}

View File

@@ -8,7 +8,7 @@
#root .simple-keyboard-preview {
background: rgba(0,0,0,0.8);
border: 20px solid rgba(0,0,0,0.1);
height: 260px;
height: 200px;
border-top-right-radius: 5px;
border-top-left-radius: 5px;
padding: 10px;

View File

@@ -48,7 +48,7 @@ it('Demo input change will work', () => {
demo.onDOMLoaded();
document.body.querySelector('.input').value = "test";
document.body.querySelector('.input').dispatchEvent(new Event('change'));
document.body.querySelector('.input').dispatchEvent(new Event('input'));
expect(demo.keyboard.getInput()).toBe("test");
});

219
src/lib/@types/index.d.ts vendored Normal file
View File

@@ -0,0 +1,219 @@
declare module 'simple-keyboard' {
interface KeyboardLayoutObject {
default: string[];
shift?: string[];
}
interface KeyboardButtonTheme {
class: string;
buttons: string;
}
interface KeyboardOptions {
/**
* Modify the keyboard layout.
*/
layout?: KeyboardLayoutObject;
/**
* Specifies which layout should be used.
*/
layoutName?: string;
/**
* Replaces variable buttons (such as `{bksp}`) with a human-friendly name (e.g.: `backspace`).
*/
display?: { [button: string]: string };
/**
* By default, when you set the display property, you replace the default one. This setting merges them instead.
*/
mergeDisplay?: boolean;
/**
* A prop to add your own css classes to the keyboard wrapper. You can add multiple classes separated by a space.
*/
theme?: string;
/**
* A prop to add your own css classes to one or several buttons.
*/
buttonTheme?: KeyboardButtonTheme[];
/**
* Runs a `console.log` every time a key is pressed. Displays the buttons pressed and the current input.
*/
debug?: boolean;
/**
* Specifies whether clicking the "ENTER" button will input a newline (`\n`) or not.
*/
newLineOnEnter?: boolean;
/**
* Specifies whether clicking the "TAB" button will input a tab character (`\t`) or not.
*/
tabCharOnTab?: boolean;
/**
* Allows you to use a single simple-keyboard instance for several inputs.
*/
inputName?: string;
/**
* `number`: Restrains all of simple-keyboard inputs to a certain length. This should be used in addition to the input elements maxlengthattribute.
*
* `{ [inputName: string]: number }`: Restrains simple-keyboards individual inputs to a certain length. This should be used in addition to the input elements maxlengthattribute.
*/
maxLength?:
| number
| {
[inputName: string]: number;
};
/**
* When set to true, this option synchronizes the internal input of every simple-keyboard instance.
*/
syncInstanceInputs?: boolean;
/**
* Enable highlighting of keys pressed on physical keyboard.
*/
physicalKeyboardHighlight?: boolean;
/**
* Calling preventDefault for the mousedown events keeps the focus on the input.
*/
preventMouseDownDefault?: boolean;
/**
* Define the text color that the physical keyboard highlighted key should have.
*/
physicalKeyboardHighlightTextColor?: string;
/**
* Define the background color that the physical keyboard highlighted key should have.
*/
physicalKeyboardHighlightBgColor?: string;
/**
* Render buttons as a button element instead of a div element.
*/
useButtonTag?: boolean;
/**
* A prop to ensure characters are always be added/removed at the end of the string.
*/
disableCaretPositioning?: boolean;
/**
* Restrains input(s) change to the defined regular expression pattern.
*/
inputPattern?: any;
/**
* Instructs simple-keyboard to use touch events instead of click events.
*/
useTouchEvents?: boolean;
/**
* Enable useTouchEvents automatically when touch device is detected.
*/
autoUseTouchEvents?: boolean;
/**
* Executes the callback function on key press. Returns button layout name (i.e.: "{shift}").
*/
onKeyPress?: (button: string) => any;
/**
* Executes the callback function on input change. Returns the current input's string.
*/
onChange?: (input: string) => any;
/**
* Executes the callback function before the first simple-keyboard render.
*/
beforeFirstRender?: () => void;
/**
* Executes the callback function before a simple-keyboard render.
*/
beforeRender?: () => void;
/**
* Executes the callback function every time simple-keyboard is rendered (e.g: when you change layouts).
*/
onRender?: () => void;
/**
* Executes the callback function once simple-keyboard is rendered for the first time (on initialization).
*/
onInit?: () => void;
/**
* Executes the callback function on input change. Returns the input object with all defined inputs.
*/
onChangeAll?: (inputs: any) => any;
}
class Keyboard {
constructor(selector: string, options: KeyboardOptions);
constructor(options: KeyboardOptions);
options: KeyboardOptions;
/**
* Adds/Modifies an entry to the `buttonTheme`. Basically a way to add a class to a button.
* @param {string} buttons List of buttons to select (separated by a space).
* @param {string} className Classes to give to the selected buttons (separated by space).
*/
addButtonTheme(buttons: string, className: string): void;
/**
* Removes/Amends an entry to the `buttonTheme`. Basically a way to remove a class previously added to a button through buttonTheme or addButtonTheme.
* @param {string} buttons List of buttons to select (separated by a space).
* @param {string} className Classes to give to the selected buttons (separated by space).
*/
removeButtonTheme(buttons: string, className: string): void;
/**
* Clear the keyboard's input.
*
* @param {string} [inputName] optional - the internal input to select
*/
clearInput(inputName?: string): void;
/**
* Get the keyboards input (You can also get it from the onChange prop).
* @param {string} [inputName] optional - the internal input to select
*/
getInput(inputName?: string): string;
/**
* Set the keyboards input.
* @param {string} input the input value
* @param {string} inputName optional - the internal input to select
*/
setInput(input: string, inputName?: string): void;
/**
* Set new option or modify existing ones after initialization.
* @param {KeyboardOptions} option The option to set
*/
setOptions(options: KeyboardOptions): void;
/**
* Send a command to all simple-keyboard instances at once (if you have multiple instances).
* @param {function(instance: object, key: string)} callback Function to run on every instance
*/
dispatch(callback: (instance: any, key: string) => void): void;
/**
* Get the DOM Element of a button. If there are several buttons with the same name, an array of the DOM Elements is returned.
* @param {string} button The button layout name to select
*/
getButtonElement(button: string): HTMLElement | HTMLElement[];
}
export default Keyboard;
}

View File

@@ -1,10 +1,12 @@
body, html {
body,
html {
margin: 0;
padding: 0;
}
.simple-keyboard {
font-family: "HelveticaNeue-Light", "Helvetica Neue Light", "Helvetica Neue", Helvetica, Arial, "Lucida Grande", sans-serif;
font-family: "HelveticaNeue-Light", "Helvetica Neue Light", "Helvetica Neue",
Helvetica, Arial, "Lucida Grande", sans-serif;
width: 100%;
user-select: none;
box-sizing: border-box;
@@ -30,21 +32,21 @@ body, html {
cursor: pointer;
}
.hg-standardBtn {
max-width: 100px;
.simple-keyboard .hg-button span {
pointer-events: none;
}
/**
* hg-theme-default theme
*/
.simple-keyboard.hg-theme-default {
background-color: rgba(0,0,0,0.1);
background-color: rgba(0, 0, 0, 0.1);
padding: 5px;
border-radius: 5px;
}
}
.simple-keyboard.hg-theme-default .hg-button {
box-shadow: 0px 0px 3px -1px rgba(0,0,0,0.3);
box-shadow: 0px 0px 3px -1px rgba(0, 0, 0, 0.3);
height: 40px;
border-radius: 5px;
box-sizing: border-box;
@@ -55,11 +57,18 @@ body, html {
display: flex;
align-items: center;
justify-content: center;
}
}
.simple-keyboard.hg-theme-default .hg-button:active {
/* When using option "useButtonTag" */
.simple-keyboard button.hg-button {
border-width: 0;
outline: 0;
font-size: inherit;
}
.simple-keyboard.hg-theme-default:not(.hg-touch-events) .hg-button:active {
background: #e4e4e4;
}
}
.simple-keyboard.hg-theme-default.hg-layout-numeric .hg-button {
width: 33.3%;
@@ -100,4 +109,4 @@ body, html {
.simple-keyboard.hg-theme-default .hg-button.hg-standardBtn[data-skbtn="@"] {
max-width: 60px;
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -45,6 +45,32 @@ it('Keyboard will run with debug option set', () => {
expect(keyboard.options.debug).toBeTruthy();
});
it('Keyboard will use touch events', () => {
let touched = false
testUtil.clear()
document.body.innerHTML = `
<div id="keyboard"></div>
`;
const keyboard = new Keyboard('#keyboard', {
useTouchEvents: true,
onChange: () => touched = true,
layout: {
default: ["q"]
}
});
keyboard.getButtonElement("q").ontouchstart();
keyboard.getButtonElement("q").ontouchend();
keyboard.getButtonElement("q").ontouchcancel();
expect(keyboard.options.useTouchEvents).toBeTruthy();
expect(touched).toBeTruthy();
expect(keyboard.getInput()).toBe('q');
})
it('Keyboard standard buttons will work', () => {
testUtil.setDOM();
let keyboard = new Keyboard({
@@ -111,7 +137,9 @@ it('Keyboard onKeyPress will work', () => {
it('Keyboard standard function buttons will not change input', () => {
testUtil.setDOM();
let keyboard = new Keyboard();
let keyboard = new Keyboard({
useButtonTag: true
});
testUtil.iterateButtons((button) => {
if(button.getAttribute("data-skbtn") === "{shift}"){
@@ -158,20 +186,6 @@ it('Keyboard onChange will work', () => {
expect(output).toBe("q");
});
it('Keyboard clearInput will work', () => {
testUtil.setDOM();
let keyboard = new Keyboard();
keyboard.input = {
"default": "hello"
};
keyboard.clearInput();
expect(keyboard.getInput()).toBeFalsy();
});
it('Keyboard clearInput will work', () => {
testUtil.setDOM();
@@ -570,11 +584,49 @@ it('Keyboard caretEventHandler will detect input, textarea focus', () => {
expect(keyboard.caretPosition).toBe(3);
});
it('Keyboard caretEventHandler will not set caretPosition on disableCaretPositioning', () => {
testUtil.setDOM();
let keyboard = new Keyboard();
keyboard.caretEventHandler({
charCode: 0,
code: "KeyF",
key: "f",
which: 70,
target: {
tagName: "input",
selectionStart: 3
}
});
expect(keyboard.caretPosition).toBe(3);
keyboard.setOptions({
disableCaretPositioning: true
});
keyboard.caretEventHandler({
charCode: 0,
code: "KeyF",
key: "f",
which: 70,
target: {
tagName: "input",
selectionStart: 3
}
});
expect(keyboard.caretPosition).toBeFalsy();
});
it('Keyboard caretEventHandler ignore positioning if input, textarea is blur', () => {
testUtil.setDOM();
let keyboard = new Keyboard();
keyboard.isMouseHold = true;
keyboard.caretEventHandler({
charCode: 0,
code: "KeyF",
@@ -835,7 +887,27 @@ it('Keyboard handleButtonMouseDown will work', () => {
target: keyboard.getButtonElement("q")
});
keyboard.getButtonElement("q").onmousedown();
var clickEvent = document.createEvent('MouseEvents');
clickEvent.initEvent('mousedown', true, true);
keyboard.getButtonElement("q").dispatchEvent(clickEvent);
document.onmouseup();
});
it('Keyboard handleButtonMouseDown will work with preventMouseDownDefault', () => {
testUtil.setDOM();
let keyboard = new Keyboard();
keyboard.options.preventMouseDownDefault = true;
keyboard.handleButtonMouseDown("q", {
target: keyboard.getButtonElement("q")
});
var clickEvent = document.createEvent('MouseEvents');
clickEvent.initEvent('mousedown', true, true);
keyboard.getButtonElement("q").dispatchEvent(clickEvent);
document.onmouseup();
});
@@ -861,4 +933,130 @@ it('Keyboard onModulesLoaded will work', () => {
});
expect(foo).toBe("bar");
});
it('Keyboard inputPattern will work globally', () => {
testUtil.setDOM();
let keyboard = new Keyboard({
inputPattern: /^\d+$/
});
keyboard.getButtonElement("q").onclick();
expect(keyboard.getInput()).toBeFalsy();
keyboard.getButtonElement("1").onclick();
expect(keyboard.getInput()).toBe("1");
});
it('Keyboard inputPattern will work by input name', () => {
testUtil.setDOM();
let keyboard = new Keyboard({
debug: true,
inputName: "test1",
inputPattern: {
test1: /^\d+$/
}
});
keyboard.getButtonElement("q").onclick();
keyboard.getButtonElement("1").onclick();
expect(keyboard.getInput()).toBe("1");
keyboard.setOptions({
inputName: "default"
});
keyboard.getButtonElement("q").onclick();
keyboard.getButtonElement("1").onclick();
expect(keyboard.getInput()).toBe("q1");
});
it('Keyboard processAutoTouchEvents will work', () => {
testUtil.setDOM();
navigator.maxTouchPoints = true;
let keyboard = new Keyboard({
autoUseTouchEvents: true
});
expect(keyboard.options.useTouchEvents).toBeTruthy();
});
it('Keyboard processAutoTouchEvents will work with debugging enabled', () => {
testUtil.setDOM();
navigator.maxTouchPoints = true;
let keyboard = new Keyboard({
autoUseTouchEvents: true,
debug: true
});
expect(keyboard.options.useTouchEvents).toBeTruthy();
});
it('Keyboard beforeFirstRender method will work', () => {
testUtil.setDOM();
let timesCalled = 0;
let keyboard = new Keyboard({
beforeFirstRender: () => {
timesCalled++;
}
});
/**
* Triggering another render
*/
keyboard.setOptions({
layoutName: "shift"
});
expect(timesCalled).toBe(1);
});
it('Keyboard beforeFirstRender will show PointerEvents warning', () => {
testUtil.setDOM();
let timesCalled = 0;
window.PointerEvent = window.PointerEvent ? window.PointerEvent : () => {};
let keyboard = new Keyboard({
debug: true,
beforeFirstRender: () => {
timesCalled++;
}
});
expect(timesCalled).toBe(1);
});
it('Keyboard beforeRender method will work', () => {
testUtil.setDOM();
let timesCalled = 0;
let keyboard = new Keyboard({
beforeRender: () => {
timesCalled++;
}
});
/**
* Triggering another render
*/
keyboard.setOptions({
layoutName: "shift"
});
expect(timesCalled).toBe(2);
});

View File

@@ -1,2 +1,2 @@
import SimpleKeyboard from './components/Keyboard';
import SimpleKeyboard from "./components/Keyboard";
export default SimpleKeyboard;

View File

@@ -6,24 +6,24 @@ class KeyboardLayout {
* Get default simple-keyboard layout
* @return {object} The default layout (US-QWERTY)
*/
static getDefaultLayout(){
static getDefaultLayout() {
return {
'default': [
'` 1 2 3 4 5 6 7 8 9 0 - = {bksp}',
'{tab} q w e r t y u i o p [ ] \\',
'{lock} a s d f g h j k l ; \' {enter}',
'{shift} z x c v b n m , . / {shift}',
'.com @ {space}'
default: [
"` 1 2 3 4 5 6 7 8 9 0 - = {bksp}",
"{tab} q w e r t y u i o p [ ] \\",
"{lock} a s d f g h j k l ; ' {enter}",
"{shift} z x c v b n m , . / {shift}",
".com @ {space}"
],
'shift': [
'~ ! @ # $ % ^ & * ( ) _ + {bksp}',
'{tab} Q W E R T Y U I O P { } |',
shift: [
"~ ! @ # $ % ^ & * ( ) _ + {bksp}",
"{tab} Q W E R T Y U I O P { } |",
'{lock} A S D F G H J K L : " {enter}',
'{shift} Z X C V B N M < > ? {shift}',
'.com @ {space}'
"{shift} Z X C V B N M < > ? {shift}",
".com @ {space}"
]
}
};
}
}
export default KeyboardLayout;
export default KeyboardLayout;

View File

@@ -5,7 +5,7 @@ class PhysicalKeyboard {
/**
* Creates an instance of the PhysicalKeyboard service
*/
constructor(simpleKeyboardInstance){
constructor(simpleKeyboardInstance) {
/**
* @type {object} A simple-keyboard instance
*/
@@ -15,7 +15,9 @@ class PhysicalKeyboard {
* Bindings
*/
this.initKeyboardListener = this.initKeyboardListener.bind(this);
this.getSimpleKeyboardLayoutKey = this.getSimpleKeyboardLayoutKey.bind(this);
this.getSimpleKeyboardLayoutKey = this.getSimpleKeyboardLayoutKey.bind(
this
);
/**
* Initialize key listeners
@@ -26,32 +28,40 @@ class PhysicalKeyboard {
/**
* Initializes key event listeners
*/
initKeyboardListener(){
initKeyboardListener() {
// Adding button style on keydown
document.addEventListener("keydown", (event) => {
if(this.simpleKeyboardInstance.options.physicalKeyboardHighlight){
document.addEventListener("keydown", event => {
if (this.simpleKeyboardInstance.options.physicalKeyboardHighlight) {
let buttonPressed = this.getSimpleKeyboardLayoutKey(event);
this.simpleKeyboardInstance.dispatch(instance => {
let buttonDOM = instance.getButtonElement(buttonPressed) || instance.getButtonElement(`{${buttonPressed}}`);
let buttonDOM =
instance.getButtonElement(buttonPressed) ||
instance.getButtonElement(`{${buttonPressed}}`);
if(buttonDOM){
buttonDOM.style.backgroundColor = this.simpleKeyboardInstance.options.physicalKeyboardHighlightBgColor || "#9ab4d0";
buttonDOM.style.color = this.simpleKeyboardInstance.options.physicalKeyboardHighlightTextColor || "white";
if (buttonDOM) {
buttonDOM.style.backgroundColor =
this.simpleKeyboardInstance.options
.physicalKeyboardHighlightBgColor || "#9ab4d0";
buttonDOM.style.color =
this.simpleKeyboardInstance.options
.physicalKeyboardHighlightTextColor || "white";
}
});
}
});
// Removing button style on keyup
document.addEventListener("keyup", (event) => {
if(this.simpleKeyboardInstance.options.physicalKeyboardHighlight){
document.addEventListener("keyup", event => {
if (this.simpleKeyboardInstance.options.physicalKeyboardHighlight) {
let buttonPressed = this.getSimpleKeyboardLayoutKey(event);
this.simpleKeyboardInstance.dispatch(instance => {
let buttonDOM = instance.getButtonElement(buttonPressed) || instance.getButtonElement(`{${buttonPressed}}`);
let buttonDOM =
instance.getButtonElement(buttonPressed) ||
instance.getButtonElement(`{${buttonPressed}}`);
if(buttonDOM && buttonDOM.removeAttribute){
if (buttonDOM && buttonDOM.removeAttribute) {
buttonDOM.removeAttribute("style");
}
});
@@ -63,10 +73,10 @@ class PhysicalKeyboard {
* Transforms a KeyboardEvent's "key.code" string into a simple-keyboard layout format
* @param {object} event The KeyboardEvent
*/
getSimpleKeyboardLayoutKey(event){
getSimpleKeyboardLayoutKey(event) {
let output;
if(
if (
event.code.includes("Numpad") ||
event.code.includes("Shift") ||
event.code.includes("Space") ||
@@ -74,7 +84,7 @@ class PhysicalKeyboard {
event.code.includes("Control") ||
event.code.includes("Alt") ||
event.code.includes("Meta")
){
) {
output = event.code;
} else {
output = event.key;
@@ -85,7 +95,9 @@ class PhysicalKeyboard {
*/
if (
output !== output.toUpperCase() ||
(event.code[0] === "F" && Number.isInteger(Number(event.code[1])) && event.code.length <= 3)
(event.code[0] === "F" &&
Number.isInteger(Number(event.code[1])) &&
event.code.length <= 3)
) {
output = output.toLowerCase();
}
@@ -94,4 +106,4 @@ class PhysicalKeyboard {
}
}
export default PhysicalKeyboard;
export default PhysicalKeyboard;

View File

@@ -5,7 +5,7 @@ class Utilities {
/**
* Creates an instance of the Utility service
*/
constructor(simpleKeyboardInstance){
constructor(simpleKeyboardInstance) {
/**
* @type {object} A simple-keyboard instance
*/
@@ -14,27 +14,24 @@ class Utilities {
/**
* Bindings
*/
this.getButtonClass = this.getButtonClass.bind(this);
this.getButtonDisplayName = this.getButtonDisplayName.bind(this);
this.getUpdatedInput = this.getUpdatedInput.bind(this);
this.updateCaretPos = this.updateCaretPos.bind(this);
this.isMaxLengthReached = this.isMaxLengthReached.bind(this);
this.camelCase = this.camelCase.bind(this);
this.countInArray = this.countInArray.bind(this);
Utilities.bindMethods(Utilities, this);
}
/**
* Adds default classes to a given button
*
*
* @param {string} button The button's layout name
* @return {string} The classes to be added to the button
*/
getButtonClass(button){
let buttonTypeClass = (button.includes("{") && button.includes("}") && button !== '{//}') ? "functionBtn" : "standardBtn";
getButtonClass(button) {
let buttonTypeClass =
button.includes("{") && button.includes("}") && button !== "{//}"
? "functionBtn"
: "standardBtn";
let buttonWithoutBraces = button.replace("{", "").replace("}", "");
let buttonNormalized = '';
let buttonNormalized = "";
if(buttonTypeClass !== "standardBtn")
if (buttonTypeClass !== "standardBtn")
buttonNormalized = ` hg-button-${buttonWithoutBraces}`;
return `hg-${buttonTypeClass}${buttonNormalized}`;
@@ -43,22 +40,22 @@ class Utilities {
/**
* Default button display labels
*/
getDefaultDiplay(){
getDefaultDiplay() {
return {
'{bksp}': 'backspace',
'{backspace}': 'backspace',
'{enter}': '< enter',
'{shift}': 'shift',
'{shiftleft}': 'shift',
'{shiftright}': 'shift',
'{alt}': 'alt',
'{s}': 'shift',
'{tab}': 'tab',
'{lock}': 'caps',
'{capslock}': 'caps',
'{accept}': 'Submit',
'{space}': ' ',
'{//}': ' ',
"{bksp}": "backspace",
"{backspace}": "backspace",
"{enter}": "< enter",
"{shift}": "shift",
"{shiftleft}": "shift",
"{shiftright}": "shift",
"{alt}": "alt",
"{s}": "shift",
"{tab}": "tab",
"{lock}": "caps",
"{capslock}": "caps",
"{accept}": "Submit",
"{space}": " ",
"{//}": " ",
"{esc}": "esc",
"{escape}": "esc",
"{f1}": "f1",
@@ -73,8 +70,8 @@ class Utilities {
"{f10}": "f10",
"{f11}": "f11",
"{f12}": "f12",
'{numpaddivide}': '/',
'{numlock}': 'lock',
"{numpaddivide}": "/",
"{numlock}": "lock",
"{arrowup}": "↑",
"{arrowleft}": "←",
"{arrowdown}": "↓",
@@ -103,18 +100,18 @@ class Utilities {
"{numpad6}": "6",
"{numpad7}": "7",
"{numpad8}": "8",
"{numpad9}": "9",
"{numpad9}": "9"
};
}
/**
* Returns the display (label) name for a given button
*
*
* @param {string} button The button's layout name
* @param {object} display The provided display option
* @param {boolean} mergeDisplay Whether the provided param value should be merged with the default one.
*/
getButtonDisplayName(button, display, mergeDisplay){
if(mergeDisplay){
getButtonDisplayName(button, display, mergeDisplay) {
if (mergeDisplay) {
display = Object.assign({}, this.getDefaultDiplay(), display);
} else {
display = display || this.getDefaultDiplay();
@@ -123,54 +120,61 @@ class Utilities {
return display[button] || button;
}
/**
* Returns the updated input resulting from clicking a given button
*
*
* @param {string} button The button's layout name
* @param {string} input The input string
* @param {object} options The simple-keyboard options object
* @param {number} caretPos The cursor's current position
* @param {boolean} moveCaret Whether to update simple-keyboard's cursor
*/
getUpdatedInput(button, input, options, caretPos, moveCaret){
getUpdatedInput(button, input, options, caretPos, moveCaret) {
let output = input;
if((button === "{bksp}" || button === "{backspace}") && output.length > 0){
if (
(button === "{bksp}" || button === "{backspace}") &&
output.length > 0
) {
output = this.removeAt(output, caretPos, moveCaret);
} else if(button === "{space}")
} else if (button === "{space}")
output = this.addStringAt(output, " ", caretPos, moveCaret);
else if(button === "{tab}" && !(typeof options.tabCharOnTab === "boolean" && options.tabCharOnTab === false)){
else if (
button === "{tab}" &&
!(
typeof options.tabCharOnTab === "boolean" &&
options.tabCharOnTab === false
)
) {
output = this.addStringAt(output, "\t", caretPos, moveCaret);
} else if((button === "{enter}" || button === "{numpadenter}") && options.newLineOnEnter)
} else if (
(button === "{enter}" || button === "{numpadenter}") &&
options.newLineOnEnter
)
output = this.addStringAt(output, "\n", caretPos, moveCaret);
else if(button.includes("numpad") && Number.isInteger(Number(button[button.length - 2]))){
output = this.addStringAt(output, button[button.length - 2], caretPos);
}
else if(button === "{numpaddivide}")
output = this.addStringAt(output, '/', caretPos, moveCaret);
else if(button === "{numpadmultiply}")
output = this.addStringAt(output, '*', caretPos, moveCaret);
else if(button === "{numpadsubtract}")
output = this.addStringAt(output, '-', caretPos, moveCaret);
else if(button === "{numpadadd}")
output = this.addStringAt(output, '+', caretPos, moveCaret);
else if(button === "{numpaddecimal}")
output = this.addStringAt(output, '.', caretPos, moveCaret);
else if(button === "{" || button === "}")
else if (
button.includes("numpad") &&
Number.isInteger(Number(button[button.length - 2]))
) {
output = this.addStringAt(
output,
button[button.length - 2],
caretPos,
moveCaret
);
} else if (button === "{numpaddivide}")
output = this.addStringAt(output, "/", caretPos, moveCaret);
else if (button === "{numpadmultiply}")
output = this.addStringAt(output, "*", caretPos, moveCaret);
else if (button === "{numpadsubtract}")
output = this.addStringAt(output, "-", caretPos, moveCaret);
else if (button === "{numpadadd}")
output = this.addStringAt(output, "+", caretPos, moveCaret);
else if (button === "{numpaddecimal}")
output = this.addStringAt(output, ".", caretPos, moveCaret);
else if (button === "{" || button === "}")
output = this.addStringAt(output, button, caretPos, moveCaret);
else if(!button.includes("{") && !button.includes("}"))
else if (!button.includes("{") && !button.includes("}"))
output = this.addStringAt(output, button, caretPos, moveCaret);
return output;
@@ -178,46 +182,74 @@ class Utilities {
/**
* Moves the cursor position by a given amount
*
*
* @param {number} length Represents by how many characters the input should be moved
* @param {boolean} minus Whether the cursor should be moved to the left or not.
*/
updateCaretPos(length, minus){
if(minus){
if(this.simpleKeyboardInstance.caretPosition > 0)
this.simpleKeyboardInstance.caretPosition = this.simpleKeyboardInstance.caretPosition - length;
} else {
this.simpleKeyboardInstance.caretPosition = this.simpleKeyboardInstance.caretPosition + length;
updateCaretPos(length, minus) {
let newCaretPos = this.updateCaretPosAction(
this.simpleKeyboardInstance,
length,
minus
);
if (this.simpleKeyboardInstance.options.syncInstanceInputs) {
this.simpleKeyboardInstance.dispatch(instance => {
instance.caretPosition = newCaretPos;
});
}
}
/**
* Action method of updateCaretPos
*
* @param {object} instance The instance whose position should be updated
* @param {number} length Represents by how many characters the input should be moved
* @param {boolean} minus Whether the cursor should be moved to the left or not.
*/
updateCaretPosAction(instance, length, minus) {
if (minus) {
if (instance.caretPosition > 0)
instance.caretPosition = instance.caretPosition - length;
} else {
instance.caretPosition = instance.caretPosition + length;
}
if (this.simpleKeyboardInstance.options.debug) {
console.log(
"Caret at:",
instance.caretPosition,
`(${instance.keyboardDOMClass})`
);
}
return instance.caretPosition;
}
/**
* Adds a string to the input at a given position
*
*
* @param {string} source The source input
* @param {string} string The string to add
* @param {number} position The (cursor) position where the string should be added
* @param {boolean} moveCaret Whether to update simple-keyboard's cursor
*/
addStringAt(source, string, position, moveCaret){
addStringAt(source, string, position, moveCaret) {
let output;
if(!position && position !== 0){
if (!position && position !== 0) {
output = source + string;
} else {
output = [source.slice(0, position), string, source.slice(position)].join('');
output = [source.slice(0, position), string, source.slice(position)].join(
""
);
/**
* Avoid caret position change when maxLength is set
*/
if(!this.isMaxLengthReached()){
if(moveCaret) this.updateCaretPos(string.length);
if (!this.isMaxLengthReached()) {
if (moveCaret) this.updateCaretPos(string.length);
}
}
if(this.simpleKeyboardInstance.options.debug && moveCaret){
console.log("Caret at:", position);
}
return output;
@@ -225,13 +257,13 @@ class Utilities {
/**
* Removes an amount of characters at a given position
*
*
* @param {string} source The source input
* @param {number} position The (cursor) position from where the characters should be removed
* @param {boolean} moveCaret Whether to update simple-keyboard's cursor
*/
removeAt(source, position, moveCaret){
if(this.simpleKeyboardInstance.caretPosition === 0){
removeAt(source, position, moveCaret) {
if (this.simpleKeyboardInstance.caretPosition === 0) {
return source;
}
@@ -244,64 +276,60 @@ class Utilities {
* 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)
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);
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);
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){
if (emojiMatched) {
output = source.slice(0, -2);
if(moveCaret) this.updateCaretPos(2, true);
if (moveCaret) this.updateCaretPos(2, true);
} else {
output = source.slice(0, -1);
if(moveCaret) this.updateCaretPos(1, true);
if (moveCaret) this.updateCaretPos(1, true);
}
}
if(this.simpleKeyboardInstance.options.debug && moveCaret){
console.log("Caret at:", this.simpleKeyboardInstance.caretPosition);
}
return output;
}
/**
* Determines whether the maxLength has been reached. This function is called when the maxLength option it set.
*
*
* @param {object} inputObj
* @param {object} options
* @param {string} updatedInput
*/
handleMaxLength(inputObj, options, updatedInput){
handleMaxLength(inputObj, options, updatedInput) {
let maxLength = options.maxLength;
let currentInput = inputObj[options.inputName];
let condition = currentInput.length === maxLength;
if(
if (
/**
* If pressing this button won't add more characters
* We exit out of this limiter function
*/
updatedInput.length <= currentInput.length
){
) {
return false;
}
if(Number.isInteger(maxLength)){
if(options.debug){
if (Number.isInteger(maxLength)) {
if (options.debug) {
console.log("maxLength (num) reached:", condition);
}
if(condition){
if (condition) {
/**
* @type {boolean} Boolean value that shows whether maxLength has been reached
*/
@@ -313,14 +341,14 @@ class Utilities {
}
}
if(typeof maxLength === "object"){
if (typeof maxLength === "object") {
let condition = currentInput.length === maxLength[options.inputName];
if(options.debug){
if (options.debug) {
console.log("maxLength (obj) reached:", condition);
}
if(condition){
if (condition) {
this.maxLengthReached = true;
return true;
} else {
@@ -333,29 +361,62 @@ class Utilities {
/**
* Gets the current value of maxLengthReached
*/
isMaxLengthReached(){
isMaxLengthReached() {
return Boolean(this.maxLengthReached);
}
/**
* Determines whether a touch device is being used
*/
isTouchDevice() {
return "ontouchstart" in window || navigator.maxTouchPoints;
}
/**
* Determines whether pointer events are supported
*/
pointerEventsSupported() {
return window.PointerEvent;
}
/**
* Bind all methods in a given class
*/
static bindMethods(myClass, instance) {
for (let myMethod of Object.getOwnPropertyNames(myClass.prototype)) {
let excludeMethod =
myMethod === "constructor" || myMethod === "bindMethods";
if (!excludeMethod) {
instance[myMethod] = instance[myMethod].bind(instance);
}
}
}
/**
* Transforms an arbitrary string to camelCase
*
*
* @param {string} string The string to transform.
*/
camelCase(string){
return string.toLowerCase().trim().split(/[.\-_\s]/g).reduce((string, word) => string + word[0].toUpperCase() + word.slice(1));
};
camelCase(string) {
return string
.toLowerCase()
.trim()
.split(/[.\-_\s]/g)
.reduce((string, word) =>
word.length ? string + word[0].toUpperCase() + word.slice(1) : string
);
}
/**
* Counts the number of duplicates in a given array
*
*
* @param {Array} array The haystack to search in
* @param {string} value The needle to search for
*/
countInArray(array, value){
countInArray(array, value) {
return array.reduce((n, x) => n + (x === value), 0);
}
}
export default Utilities;
export default Utilities;

View File

@@ -210,6 +210,18 @@ it('Keyboard standard button will affect input', () => {
}
});
it('Keyboard updateCaretPos will work with minus', () => {
testUtil.setDOM();
let keyboard = new Keyboard();
keyboard.options.syncInstanceInputs = true;
keyboard.caretPosition = 5;
keyboard.utilities.updateCaretPos(2, true);
expect(keyboard.caretPosition).toBe(3);
});
it('Keyboard updateCaretPos will work with minus', () => {
testUtil.setDOM();
@@ -465,4 +477,10 @@ it('Keyboard removeAt will remove regular strings', () => {
keyboard.caretPosition = 6;
output = keyboard.utilities.removeAt("testie", 6, true);
expect(keyboard.caretPosition).toBe(5);
});
it('Keyboard will work with custom (and weird) class', () => {
testUtil.setDOM("my--weird--class");
let keyboard = new Keyboard(".my--weird--class");
expect(keyboard.keyboardDOMClass).toBe("my--weird--class");
});