mirror of
https://github.com/hodgef/simple-keyboard.git
synced 2025-04-09 18:23:07 +08:00
Compare commits
No commits in common. "master" and "3.7.0" have entirely different histories.
2
.github/FUNDING.yml
vendored
2
.github/FUNDING.yml
vendored
@ -1 +1 @@
|
||||
buy_me_a_coffee: hodgef
|
||||
custom: https://hge.to/thanks
|
||||
|
2
.github/pull_request_template.md
vendored
2
.github/pull_request_template.md
vendored
@ -4,4 +4,4 @@ A few sentences describing the overall goals of the pull request's commits.
|
||||
|
||||
## Checks
|
||||
|
||||
- [ ] I have read and followed the [Contributing Guidelines](https://github.com/hodgef/simple-keyboard/blob/master/CONTRIBUTING.md).
|
||||
- [ ] Tests ( `npm run test -- --coverage` ) Coverage at `./coverage/lcov-report/index.html` should be 100%
|
||||
|
17
.github/stale.yml
vendored
Normal file
17
.github/stale.yml
vendored
Normal file
@ -0,0 +1,17 @@
|
||||
# Number of days of inactivity before an issue becomes stale
|
||||
daysUntilStale: 5
|
||||
# Number of days of inactivity before a stale issue is closed
|
||||
daysUntilClose: 2
|
||||
# Issues with these labels will never be considered stale
|
||||
exemptLabels:
|
||||
- pinned
|
||||
- security
|
||||
# Label to use when marking an issue as stale
|
||||
staleLabel: Stale
|
||||
# Comment to post when marking an issue as stale. Set to `false` to disable
|
||||
markComment: >
|
||||
This issue has been automatically marked as stale because it has not had
|
||||
recent activity. It will be closed if no further activity occurs. Thank you
|
||||
for your contributions.
|
||||
# Comment to post when closing a stale issue. Set to `false` to disable
|
||||
closeComment: false
|
19
.github/workflows/mirroring.yml
vendored
Normal file
19
.github/workflows/mirroring.yml
vendored
Normal file
@ -0,0 +1,19 @@
|
||||
name: Mirroring
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
delete:
|
||||
branches:
|
||||
- master
|
||||
|
||||
jobs:
|
||||
mirroring:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v1
|
||||
- uses: pixta-dev/repository-mirroring-action@v1
|
||||
with:
|
||||
target_repo_url: git@gitlab.com:hodgef/simple-keyboard.git
|
||||
ssh_private_key: ${{ secrets.GL_KEY }}
|
6
.github/workflows/publish.yml
vendored
6
.github/workflows/publish.yml
vendored
@ -9,10 +9,6 @@ on:
|
||||
- .gitignore
|
||||
- .github/**
|
||||
|
||||
permissions:
|
||||
contents: write
|
||||
id-token: write
|
||||
|
||||
jobs:
|
||||
publish:
|
||||
runs-on: ${{ matrix.os }}
|
||||
@ -59,6 +55,6 @@ jobs:
|
||||
run: |
|
||||
export NODE_OPTIONS=--openssl-legacy-provider
|
||||
npm config set //registry.npmjs.org/:_authToken=$NODE_AUTH_TOKEN
|
||||
npm publish --provenance --access public
|
||||
npm run trypublish
|
||||
env:
|
||||
NODE_AUTH_TOKEN: ${{secrets.NODE_AUTH_TOKEN}}
|
||||
|
24
.github/workflows/pull_request_compl.yml
vendored
24
.github/workflows/pull_request_compl.yml
vendored
@ -1,24 +0,0 @@
|
||||
name: PR Compliance
|
||||
|
||||
on:
|
||||
pull_request_target:
|
||||
types: [opened]
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ${{ matrix.os }}
|
||||
if: ${{ github.actor != 'dependabot[bot]' }}
|
||||
strategy:
|
||||
matrix:
|
||||
node-version: [20.x]
|
||||
os: [ubuntu-latest]
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v3
|
||||
|
||||
- name: Comment PR
|
||||
uses: thollander/actions-comment-pull-request@v2
|
||||
with:
|
||||
message: |
|
||||
:wave: Hello @${{ github.actor }}! Please make sure to review the [Contributing Guidelines](https://github.com/hodgef/simple-keyboard/blob/master/CONTRIBUTING.md) to ensure your PR is compliant. Thank you!
|
||||
reactions: eyes
|
15
.github/workflows/stale.yml
vendored
15
.github/workflows/stale.yml
vendored
@ -1,15 +0,0 @@
|
||||
name: 'Close stale issues and PRs'
|
||||
on:
|
||||
schedule:
|
||||
- cron: '30 1 * * *'
|
||||
|
||||
jobs:
|
||||
stale:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/stale@v9
|
||||
with:
|
||||
stale-issue-message: 'This ticket is stale because it has been open 5 days with no activity. If pertaining to an Enhancement, the ticket will be tracked even after closing.'
|
||||
stale-pr-message: 'This PR is stale because it has been open 5 days with no activity. It will be closed soon if no further activity occurs. Thank you!'
|
||||
days-before-stale: 5
|
||||
days-before-close: 5
|
1
.gitignore
vendored
1
.gitignore
vendored
@ -19,4 +19,3 @@
|
||||
npm-debug.log*
|
||||
yarn-debug.log*
|
||||
yarn-error.log*
|
||||
_git*
|
@ -7,15 +7,9 @@ Please note we have a code of conduct, please follow it in all your interactions
|
||||
|
||||
## Pull Request Guidelines
|
||||
|
||||
1. Use PRs to fix issues. New features are discouraged as they bring more maintenance burden over time.
|
||||
2. Discuss the change you wish to make with the owners of this repository **before** raising a PR. If you do not discuss it beforehand, your PR might end up being rejected and your work will be lost.
|
||||
3. Please ensure your proposal will not significantly change current functionality or bring along breaking changes.
|
||||
4. PRs only consisting of typo fixes (or other automated contributions), will not be accepted.
|
||||
5. Do not add any dependencies, libraries or external codes to the project. All the code submitted should be authored by you.
|
||||
6. Avoid refactors. The changes should be succint and fix a specific issue with the least code possible.
|
||||
7. Document your changes thoroughly.
|
||||
8. Ensure that none of the tests fail.
|
||||
9. Be reactive to any comments, reviews or change requests entered in your pull request.
|
||||
10. It's up to the maintainers discretion whether the PR is accepted or rejected. Remember, the maintainer will have to maintain the code you've added (and fix any issues filed about it) for the years to come! In case of a rejection, the maintainer will explain the reasons guiding the decision.
|
||||
|
||||
Thank you for your contributions!
|
||||
1. Please ensure your proposal will not radically change current functionality or bring along breaking changes.
|
||||
2. PRs only consisting of typo fixes (or other automated contributions), will not be accepted.
|
||||
3. Do not add any dependencies to the project.
|
||||
4. Document your changes thoroughly.
|
||||
5. Ensure coverage is complete (`npm run coverage` should show 100% coverage) and that none of the tests fail.
|
||||
6. Be reactive to any comments, reviews or change requests entered in your pull request.
|
||||
|
25
README.md
25
README.md
@ -2,7 +2,26 @@
|
||||
<a href="https://simple-keyboard.com/demo">
|
||||
<img alt="simple-keyboard: Javascript Virtual Keyboard" src="https://user-images.githubusercontent.com/25509135/187999993-fb5422fd-a56f-4a9a-84a9-55c94478f61c.gif">
|
||||
</a>
|
||||
<a href="https://www.npmjs.com/package/simple-keyboard"><img src="https://badgen.net/npm/v/simple-keyboard?color=blue" alt="npm version"></a> <a href="https://github.com/hodgef/simple-keyboard/blob/master/LICENSE"><img src="https://img.shields.io/badge/License-MIT-blue.svg" alt="MIT license"></a> <a href="https://gitlab.com/hodgef/simple-keyboard" target="_blank"><img alt="Mirroring" src="https://img.shields.io/badge/Mirror-GitLab-blue" /></a> <a href="https://github.com/hodgef/simple-keyboard/actions"><img alt="Build Status" src="https://github.com/hodgef/simple-keyboard/workflows/Build/badge.svg" /></a> <a href="https://github.com/hodgef/simple-keyboard/actions"><img alt="Publish Status" src="https://github.com/hodgef/simple-keyboard/workflows/Publish/badge.svg" /></a>
|
||||
|
||||
<a href="https://www.npmjs.com/package/simple-keyboard">
|
||||
<img src="https://badgen.net/npm/v/simple-keyboard?color=blue" alt="npm version">
|
||||
</a>
|
||||
|
||||
<a href="https://github.com/hodgef/simple-keyboard/blob/master/LICENSE">
|
||||
<img src="https://img.shields.io/badge/License-MIT-blue.svg" alt="MIT license">
|
||||
</a>
|
||||
|
||||
<a href="https://github.com/hodgef/simple-keyboard/actions">
|
||||
<img alt="Build Status" src="https://github.com/hodgef/simple-keyboard/workflows/Build/badge.svg" />
|
||||
</a>
|
||||
|
||||
<a href="https://github.com/hodgef/simple-keyboard/actions">
|
||||
<img alt="Publish Status" src="https://github.com/hodgef/simple-keyboard/workflows/Publish/badge.svg" />
|
||||
</a>
|
||||
|
||||
<a href="https://gitlab.com/hodgef/simple-keyboard" target="_blank">
|
||||
<img alt="Mirroring" src="https://github.com/hodgef/simple-keyboard/actions/workflows/mirroring.yml/badge.svg" />
|
||||
</a>
|
||||
</p>
|
||||
|
||||
<blockquote>Virtual Keyboard for Javascript. Compatible with your JS, React, Angular or Vue projects.</blockquote>
|
||||
@ -63,10 +82,6 @@ Want to create your own module? Check out the [Modules page](https://hodgef.com/
|
||||
|
||||
> Note: If you don't want to support old browsers, you can use the Modern Browsers bundle ([index.modern.js](https://github.com/hodgef/simple-keyboard/blob/master/build)).
|
||||
|
||||
## 🔶 Community Libraries & Integrations
|
||||
Check out useful community modules for simple-keyboard:<br />
|
||||
https://github.com/hodgef/simple-keyboard/wiki/Community-Libraries-&-Integrations
|
||||
|
||||
## ✅ Contributing
|
||||
|
||||
PRs and issues are always welcome. Feel free to submit any issues you have at:
|
||||
|
2
build/components/Keyboard.d.ts
vendored
2
build/components/Keyboard.d.ts
vendored
@ -41,7 +41,7 @@ declare class SimpleKeyboard {
|
||||
activeInputElement: HTMLInputElement | HTMLTextAreaElement | null;
|
||||
/**
|
||||
* Creates an instance of SimpleKeyboard
|
||||
* @param {Array} selectorOrOptions If first parameter is a string, it is considered the container class. The second parameter is then considered the options object. If first parameter is an object, it is considered the options object.
|
||||
* @param {Array} params If first parameter is a string, it is considered the container class. The second parameter is then considered the options object. If first parameter is an object, it is considered the options object.
|
||||
*/
|
||||
constructor(selectorOrOptions?: string | HTMLDivElement | KeyboardOptions, keyboardOptions?: KeyboardOptions);
|
||||
/**
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*!
|
||||
*
|
||||
* simple-keyboard v3.8.48
|
||||
* simple-keyboard v3.6.42
|
||||
* https://github.com/hodgef/simple-keyboard
|
||||
*
|
||||
* Copyright (c) Francisco Hodge (https://github.com/hodgef) and project contributors.
|
||||
@ -8,4 +8,4 @@
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*
|
||||
*/.hg-theme-default{background-color:#ececec;border-radius:5px;box-sizing:border-box;font-family:HelveticaNeue-Light,Helvetica Neue Light,Helvetica Neue,Helvetica,Arial,Lucida Grande,sans-serif;overflow:hidden;padding:5px;touch-action:manipulation;-webkit-user-select:none;-moz-user-select:none;user-select:none;width:100%}.hg-theme-default .hg-button span,.hg-theme-default .hg-button span svg{pointer-events:none}.hg-theme-default button.hg-button{border-width:0;font-size:inherit;outline:0}.hg-theme-default .hg-button{display:inline-block;flex-grow:1}.hg-theme-default .hg-row{display:flex}.hg-theme-default .hg-row:not(:last-child){margin-bottom:5px}.hg-theme-default .hg-row .hg-button-container,.hg-theme-default .hg-row .hg-button:not(:last-child){margin-right:5px}.hg-theme-default .hg-row>div:last-child{margin-right:0}.hg-theme-default .hg-row .hg-button-container{display:flex}.hg-theme-default .hg-button{align-items:center;background:#fff;border-bottom:1px solid #b5b5b5;border-radius:5px;box-shadow:0 0 3px -1px rgba(0,0,0,.3);box-sizing:border-box;cursor:pointer;display:flex;height:40px;justify-content:center;padding:5px;-webkit-tap-highlight-color:rgba(0,0,0,0)}.hg-theme-default .hg-button.hg-standardBtn{width:20px}.hg-theme-default .hg-button.hg-activeButton{background:#efefef}.hg-theme-default.hg-layout-numeric .hg-button{align-items:center;display:flex;height:60px;justify-content:center;width:33.3%}.hg-theme-default .hg-button.hg-button-numpadadd,.hg-theme-default .hg-button.hg-button-numpadenter{height:85px}.hg-theme-default .hg-button.hg-button-numpad0{width:105px}.hg-theme-default .hg-button.hg-button-com{max-width:85px}.hg-theme-default .hg-button.hg-standardBtn.hg-button-at{max-width:45px}.hg-theme-default .hg-button.hg-selectedButton{background:rgba(5,25,70,.53);color:#fff}.hg-theme-default .hg-button.hg-standardBtn[data-skbtn=".com"]{max-width:82px}.hg-theme-default .hg-button.hg-standardBtn[data-skbtn="@"]{max-width:60px}.hg-candidate-box{background:#ececec;border-bottom:2px solid #b5b5b5;border-radius:5px;display:inline-flex;margin-top:-10px;position:absolute;transform:translateY(-100%);-webkit-user-select:none;-moz-user-select:none;user-select:none}ul.hg-candidate-box-list{display:flex;flex:1;list-style:none;margin:0;padding:0}li.hg-candidate-box-list-item{align-items:center;display:flex;height:40px;justify-content:center;width:40px}li.hg-candidate-box-list-item:hover{background:rgba(0,0,0,.03);cursor:pointer}li.hg-candidate-box-list-item:active{background:rgba(0,0,0,.1)}.hg-candidate-box-prev:before{content:"◄"}.hg-candidate-box-next:before{content:"►"}.hg-candidate-box-next,.hg-candidate-box-prev{align-items:center;color:#969696;cursor:pointer;display:flex;padding:0 10px}.hg-candidate-box-next{border-bottom-right-radius:5px;border-top-right-radius:5px}.hg-candidate-box-prev{border-bottom-left-radius:5px;border-top-left-radius:5px}.hg-candidate-box-btn-active{color:#444}
|
||||
*/.hg-theme-default{background-color:#ececec;border-radius:5px;box-sizing:border-box;font-family:HelveticaNeue-Light,Helvetica Neue Light,Helvetica Neue,Helvetica,Arial,Lucida Grande,sans-serif;overflow:hidden;padding:5px;touch-action:manipulation;-webkit-user-select:none;-moz-user-select:none;user-select:none;width:100%}.hg-theme-default .hg-button span{pointer-events:none}.hg-theme-default button.hg-button{border-width:0;font-size:inherit;outline:0}.hg-theme-default .hg-button{display:inline-block;flex-grow:1}.hg-theme-default .hg-row{display:flex}.hg-theme-default .hg-row:not(:last-child){margin-bottom:5px}.hg-theme-default .hg-row .hg-button-container,.hg-theme-default .hg-row .hg-button:not(:last-child){margin-right:5px}.hg-theme-default .hg-row>div:last-child{margin-right:0}.hg-theme-default .hg-row .hg-button-container{display:flex}.hg-theme-default .hg-button{-webkit-tap-highlight-color:rgba(0,0,0,0);align-items:center;background:#fff;border-bottom:1px solid #b5b5b5;border-radius:5px;box-shadow:0 0 3px -1px rgba(0,0,0,.3);box-sizing:border-box;cursor:pointer;display:flex;height:40px;justify-content:center;padding:5px}.hg-theme-default .hg-button.hg-standardBtn{width:20px}.hg-theme-default .hg-button.hg-activeButton{background:#efefef}.hg-theme-default.hg-layout-numeric .hg-button{align-items:center;display:flex;height:60px;justify-content:center;width:33.3%}.hg-theme-default .hg-button.hg-button-numpadadd,.hg-theme-default .hg-button.hg-button-numpadenter{height:85px}.hg-theme-default .hg-button.hg-button-numpad0{width:105px}.hg-theme-default .hg-button.hg-button-com{max-width:85px}.hg-theme-default .hg-button.hg-standardBtn.hg-button-at{max-width:45px}.hg-theme-default .hg-button.hg-selectedButton{background:rgba(5,25,70,.53);color:#fff}.hg-theme-default .hg-button.hg-standardBtn[data-skbtn=".com"]{max-width:82px}.hg-theme-default .hg-button.hg-standardBtn[data-skbtn="@"]{max-width:60px}.hg-candidate-box{background:#ececec;border-bottom:2px solid #b5b5b5;border-radius:5px;display:inline-flex;margin-top:-10px;max-width:272px;position:absolute;transform:translateY(-100%);-webkit-user-select:none;-moz-user-select:none;user-select:none}ul.hg-candidate-box-list{display:flex;flex:1;list-style:none;margin:0;padding:0}li.hg-candidate-box-list-item{align-items:center;display:flex;height:40px;justify-content:center;width:40px}li.hg-candidate-box-list-item:hover{background:rgba(0,0,0,.03);cursor:pointer}li.hg-candidate-box-list-item:active{background:rgba(0,0,0,.1)}.hg-candidate-box-prev:before{content:"◄"}.hg-candidate-box-next:before{content:"►"}.hg-candidate-box-next,.hg-candidate-box-prev{align-items:center;color:#969696;cursor:pointer;display:flex;padding:0 10px}.hg-candidate-box-next{border-bottom-right-radius:5px;border-top-right-radius:5px}.hg-candidate-box-prev{border-bottom-left-radius:5px;border-top-left-radius:5px}.hg-candidate-box-btn-active{color:#444}
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
19
build/interfaces.d.ts
vendored
19
build/interfaces.d.ts
vendored
@ -1,8 +1,5 @@
|
||||
import SimpleKeyboard from "./components/Keyboard";
|
||||
import Utilities from "./services/Utilities";
|
||||
export interface SKWindow extends Window {
|
||||
SimpleKeyboardInstances?: any;
|
||||
}
|
||||
export interface KeyboardLayoutObject {
|
||||
[key: string]: string[];
|
||||
}
|
||||
@ -216,22 +213,14 @@ export interface KeyboardOptions {
|
||||
* Enables onKeyPress triggering for layoutCandidate items
|
||||
*/
|
||||
enableLayoutCandidatesKeyPress?: boolean;
|
||||
/**
|
||||
* Updates caret when selectionchange event is fired
|
||||
*/
|
||||
updateCaretOnSelectionChange?: boolean;
|
||||
/**
|
||||
* When useMouseEvents is enabled, this option allows you to trigger a button click event on mousedown
|
||||
*/
|
||||
clickOnMouseDown?: boolean;
|
||||
/**
|
||||
* Executes the callback function every time simple-keyboard is rendered (e.g: when you change layouts).
|
||||
*/
|
||||
onRender?: (instance: SimpleKeyboard) => void;
|
||||
onRender?: (instance?: SimpleKeyboard) => void;
|
||||
/**
|
||||
* Executes the callback function once simple-keyboard is rendered for the first time (on initialization).
|
||||
*/
|
||||
onInit?: (instance: SimpleKeyboard) => void;
|
||||
onInit?: (instance?: SimpleKeyboard) => void;
|
||||
/**
|
||||
* Retrieves the current input
|
||||
*/
|
||||
@ -248,10 +237,6 @@ export interface KeyboardOptions {
|
||||
* Retrieves the released key
|
||||
*/
|
||||
onKeyReleased?: (button: string, e?: MouseEvent) => any;
|
||||
/**
|
||||
* Executes the callback function before an input is about to be updated
|
||||
*/
|
||||
beforeInputUpdate?: (instance: SimpleKeyboard) => void;
|
||||
/**
|
||||
* Module options can have any format
|
||||
*/
|
||||
|
6
build/services/KeyboardLayout.d.ts
vendored
6
build/services/KeyboardLayout.d.ts
vendored
@ -1,2 +1,4 @@
|
||||
import { KeyboardLayoutObject } from "../interfaces";
|
||||
export declare const getDefaultLayout: () => KeyboardLayoutObject;
|
||||
export declare const getDefaultLayout: () => {
|
||||
default: string[];
|
||||
shift: string[];
|
||||
};
|
||||
|
2
build/services/PhysicalKeyboard.d.ts
vendored
2
build/services/PhysicalKeyboard.d.ts
vendored
@ -20,6 +20,6 @@ declare class PhysicalKeyboard {
|
||||
* Retrieve key from keyCode
|
||||
*/
|
||||
keyCodeToKey(keyCode: number): string;
|
||||
isModifierKey: (e: KeyboardEvent) => boolean;
|
||||
isMofifierKey: (e: KeyboardEvent) => boolean;
|
||||
}
|
||||
export default PhysicalKeyboard;
|
||||
|
4
build/services/Utilities.d.ts
vendored
4
build/services/Utilities.d.ts
vendored
@ -197,9 +197,5 @@ declare class Utilities {
|
||||
* Reusable empty function
|
||||
*/
|
||||
static noop: () => void;
|
||||
/**
|
||||
* Check if a function is a constructor
|
||||
*/
|
||||
isConstructor(f: any): boolean;
|
||||
}
|
||||
export default Utilities;
|
||||
|
16813
package-lock.json
generated
16813
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
51
package.json
51
package.json
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "simple-keyboard",
|
||||
"version": "3.8.48",
|
||||
"version": "3.7.0",
|
||||
"description": "On-screen Javascript Virtual Keyboard",
|
||||
"main": "build/index.js",
|
||||
"scripts": {
|
||||
@ -10,7 +10,8 @@
|
||||
"build-modern-esm": "webpack --config webpack.config.modern_esm.js",
|
||||
"test": "jest --silent",
|
||||
"coverage": "npm run test -- --coverage",
|
||||
"prepare": "npm run build"
|
||||
"prepare": "npm run build",
|
||||
"trypublish": "npm publish || true"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
@ -39,40 +40,38 @@
|
||||
],
|
||||
"license": "MIT",
|
||||
"devDependencies": {
|
||||
"@babel/cli": "^7.27.0",
|
||||
"@babel/core": "^7.26.10",
|
||||
"@babel/cli": "^7.22.10",
|
||||
"@babel/core": "^7.22.10",
|
||||
"@babel/plugin-proposal-class-properties": "^7.17.12",
|
||||
"@babel/plugin-transform-typescript": "^7.27.0",
|
||||
"@babel/plugin-transform-typescript": "^7.22.10",
|
||||
"@babel/polyfill": "^7.12.1",
|
||||
"@babel/preset-env": "^7.26.9",
|
||||
"@types/jest": "^29.5.14",
|
||||
"@typescript-eslint/eslint-plugin": "^5.62.0",
|
||||
"@babel/preset-env": "^7.22.10",
|
||||
"@types/jest": "^27.5.0",
|
||||
"@typescript-eslint/eslint-plugin": "^5.60.1",
|
||||
"@typescript-eslint/parser": "^5.62.0",
|
||||
"autoprefixer": "^10.4.21",
|
||||
"autoprefixer": "^10.4.15",
|
||||
"babel-eslint": "^10.1.0",
|
||||
"babel-loader": "^9.2.1",
|
||||
"babel-loader": "^9.1.3",
|
||||
"babel-preset-minify": "^0.5.2",
|
||||
"core-js": "^3.41.0",
|
||||
"css-loader": "^7.1.2",
|
||||
"css-minimizer-webpack-plugin": "^7.0.2",
|
||||
"eslint": "^8.57.0",
|
||||
"core-js": "^3.32.0",
|
||||
"css-loader": "^6.8.1",
|
||||
"css-minimizer-webpack-plugin": "^5.0.1",
|
||||
"eslint": "^8.47.0",
|
||||
"file-loader": "^6.2.0",
|
||||
"html-webpack-plugin": "^5.6.3",
|
||||
"jest": "^29.7.0",
|
||||
"jest-environment-jsdom": "^29.7.0",
|
||||
"mini-css-extract-plugin": "^2.9.2",
|
||||
"postcss": "^8.5.3",
|
||||
"postcss-loader": "^8.1.1",
|
||||
"style-loader": "^4.0.0",
|
||||
"terser-webpack-plugin": "^5.3.14",
|
||||
"typescript": "^5.8.3",
|
||||
"html-webpack-plugin": "^5.5.3",
|
||||
"jest": "^26.6.3",
|
||||
"mini-css-extract-plugin": "^2.7.6",
|
||||
"postcss": "^8.4.28",
|
||||
"postcss-loader": "^7.3.3",
|
||||
"style-loader": "^3.3.3",
|
||||
"terser-webpack-plugin": "^5.3.9",
|
||||
"typescript": "^4.9.5",
|
||||
"url-loader": "^4.1.1",
|
||||
"webpack": "^5.99.5",
|
||||
"webpack-cli": "^6.0.1",
|
||||
"webpack": "^5.88.2",
|
||||
"webpack-cli": "^5.1.3",
|
||||
"webpack-dev-server": "4.15.0"
|
||||
},
|
||||
"jest": {
|
||||
"testEnvironment": "jsdom",
|
||||
"roots": [
|
||||
"<rootDir>/src"
|
||||
],
|
||||
|
@ -16,9 +16,8 @@ class Demo {
|
||||
* Demo Start
|
||||
*/
|
||||
this.keyboard = new Keyboard({
|
||||
onChange: this.onChange,
|
||||
onKeyPress: this.onKeyPress,
|
||||
useMouseEvents: true
|
||||
onChange: input => this.onChange(input),
|
||||
onKeyPress: button => this.onKeyPress(button)
|
||||
});
|
||||
|
||||
/**
|
||||
@ -29,13 +28,13 @@ class Demo {
|
||||
});
|
||||
}
|
||||
|
||||
onChange = (input) => {
|
||||
onChange(input) {
|
||||
document.querySelector(".input").value = input;
|
||||
console.log("Input changed", input);
|
||||
}
|
||||
|
||||
onKeyPress = (button, e) => {
|
||||
console.log("Button pressed", button, e);
|
||||
onKeyPress(button) {
|
||||
console.log("Button pressed", button);
|
||||
|
||||
/**
|
||||
* If you want to handle the shift and caps lock buttons
|
||||
@ -43,11 +42,7 @@ class Demo {
|
||||
if (button === "{shift}" || button === "{lock}") this.handleShift();
|
||||
}
|
||||
|
||||
onKeyReleased = (button, e) => {
|
||||
console.log("Button released", button, e);
|
||||
}
|
||||
|
||||
handleShift = () => {
|
||||
handleShift() {
|
||||
const currentLayout = this.keyboard.options.layoutName;
|
||||
const shiftToggle = currentLayout === "default" ? "shift" : "default";
|
||||
|
||||
|
@ -19,9 +19,8 @@ class Demo {
|
||||
onChange: input => this.onChange(input),
|
||||
onKeyPress: button => this.onKeyPress(button),
|
||||
preventMouseDownDefault: true,
|
||||
layoutCandidatesPageSize: 15,
|
||||
layoutCandidates: {
|
||||
ni: "你 尼 你 尼 你 尼 你 尼 你 尼 你 尼 你 尼 你 尼 你 尼 你 尼",
|
||||
ni: "你 尼",
|
||||
hao: "好 号"
|
||||
}
|
||||
});
|
||||
|
@ -1,5 +1,6 @@
|
||||
import "./css/Keyboard.css";
|
||||
|
||||
// Services
|
||||
import { getDefaultLayout } from "../services/KeyboardLayout";
|
||||
import PhysicalKeyboard from "../services/PhysicalKeyboard";
|
||||
import Utilities from "../services/Utilities";
|
||||
@ -9,7 +10,6 @@ import {
|
||||
KeyboardButtonElements,
|
||||
KeyboardHandlerEvent,
|
||||
KeyboardElement,
|
||||
SKWindow,
|
||||
} from "../interfaces";
|
||||
import CandidateBox from "./CandidateBox";
|
||||
|
||||
@ -48,7 +48,7 @@ class SimpleKeyboard {
|
||||
|
||||
/**
|
||||
* Creates an instance of SimpleKeyboard
|
||||
* @param {Array} selectorOrOptions If first parameter is a string, it is considered the container class. The second parameter is then considered the options object. If first parameter is an object, it is considered the options object.
|
||||
* @param {Array} params If first parameter is a string, it is considered the container class. The second parameter is then considered the options object. If first parameter is an object, it is considered the options object.
|
||||
*/
|
||||
constructor(
|
||||
selectorOrOptions?: string | HTMLDivElement | KeyboardOptions,
|
||||
@ -118,7 +118,6 @@ class SimpleKeyboard {
|
||||
* @property {function(input: string):string} onChange Executes the callback function on input change. Returns the current input’s string.
|
||||
* @property {function} onRender Executes the callback function every time simple-keyboard is rendered (e.g: when you change layouts).
|
||||
* @property {function} onInit Executes the callback function once simple-keyboard is rendered for the first time (on initialization).
|
||||
* @property {function(keyboard: Keyboard):void} beforeInputUpdate Perform an action before any input change
|
||||
* @property {function(inputs: object):object} onChangeAll Executes the callback function on input change. Returns the input object with all defined inputs.
|
||||
* @property {boolean} useButtonTag Render buttons as a button element instead of a div element.
|
||||
* @property {boolean} disableCaretPositioning A prop to ensure characters are always be added/removed at the end of the string.
|
||||
@ -137,8 +136,6 @@ class SimpleKeyboard {
|
||||
* @property {boolean} layoutCandidatesCaseSensitiveMatch Determines whether layout candidate match should be case sensitive.
|
||||
* @property {boolean} disableCandidateNormalization Disables the automatic normalization for selected layout candidates
|
||||
* @property {boolean} enableLayoutCandidatesKeyPress Enables onKeyPress triggering for layoutCandidate items
|
||||
* @property {boolean} updateCaretOnSelectionChange Updates caret when selectionchange event is fired
|
||||
* @property {boolean} clickOnMouseDown When useMouseEvents is enabled, this option allows you to trigger a button click event on mousedown
|
||||
*/
|
||||
this.options = {
|
||||
layoutName: "default",
|
||||
@ -192,17 +189,17 @@ class SimpleKeyboard {
|
||||
* Simple-keyboard Instances
|
||||
* This enables multiple simple-keyboard support with easier management
|
||||
*/
|
||||
if (!(window as SKWindow)["SimpleKeyboardInstances"])
|
||||
(window as SKWindow)["SimpleKeyboardInstances"] = {};
|
||||
if (!window["SimpleKeyboardInstances"])
|
||||
window["SimpleKeyboardInstances"] = {};
|
||||
|
||||
this.currentInstanceName = this.utilities.camelCase(this.keyboardDOMClass);
|
||||
(window as SKWindow)["SimpleKeyboardInstances"][this.currentInstanceName] = this;
|
||||
window["SimpleKeyboardInstances"][this.currentInstanceName] = this;
|
||||
|
||||
/**
|
||||
* Instance vars
|
||||
*/
|
||||
this.allKeyboardInstances = (window as SKWindow)["SimpleKeyboardInstances"];
|
||||
this.keyboardInstanceNames = Object.keys((window as SKWindow)["SimpleKeyboardInstances"]);
|
||||
this.allKeyboardInstances = window["SimpleKeyboardInstances"];
|
||||
this.keyboardInstanceNames = Object.keys(window["SimpleKeyboardInstances"]);
|
||||
this.isFirstKeyboardInstance =
|
||||
this.keyboardInstanceNames[0] === this.currentInstanceName;
|
||||
|
||||
@ -396,13 +393,6 @@ class SimpleKeyboard {
|
||||
candidateStr = selectedCandidate.normalize("NFD");
|
||||
}
|
||||
|
||||
/**
|
||||
* Perform an action before any input change
|
||||
*/
|
||||
if (typeof this.options.beforeInputUpdate === "function") {
|
||||
this.options.beforeInputUpdate(this);
|
||||
}
|
||||
|
||||
const currentInput = this.getInput(this.options.inputName, true);
|
||||
const initialCaretPosition = this.getCaretPositionEnd() || 0;
|
||||
const inputSubstr =
|
||||
@ -468,13 +458,6 @@ class SimpleKeyboard {
|
||||
*/
|
||||
if (!this.input[inputName]) this.input[inputName] = "";
|
||||
|
||||
/**
|
||||
* Perform an action before any input change
|
||||
*/
|
||||
if (typeof this.options.beforeInputUpdate === "function") {
|
||||
this.options.beforeInputUpdate(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculating new input
|
||||
*/
|
||||
@ -823,7 +806,7 @@ class SimpleKeyboard {
|
||||
* Get all simple-keyboard inputs
|
||||
*/
|
||||
getAllInputs(): KeyboardInput {
|
||||
const output = {} as KeyboardInput;
|
||||
const output = {};
|
||||
const inputNames = Object.keys(this.input);
|
||||
|
||||
inputNames.forEach((inputName) => {
|
||||
@ -953,15 +936,15 @@ class SimpleKeyboard {
|
||||
*/
|
||||
// eslint-disable-next-line no-unused-vars
|
||||
dispatch(callback: (instance: SimpleKeyboard, key?: string) => void): void {
|
||||
if (!(window as SKWindow)["SimpleKeyboardInstances"]) {
|
||||
if (!window["SimpleKeyboardInstances"]) {
|
||||
console.warn(
|
||||
`SimpleKeyboardInstances is not defined. Dispatch cannot be called.`
|
||||
);
|
||||
throw new Error("INSTANCES_VAR_ERROR");
|
||||
}
|
||||
|
||||
return Object.keys((window as SKWindow)["SimpleKeyboardInstances"]).forEach((key) => {
|
||||
callback((window as SKWindow)["SimpleKeyboardInstances"][key], key);
|
||||
return Object.keys(window["SimpleKeyboardInstances"]).forEach((key) => {
|
||||
callback(window["SimpleKeyboardInstances"][key], key);
|
||||
});
|
||||
}
|
||||
|
||||
@ -1150,11 +1133,7 @@ class SimpleKeyboard {
|
||||
document.addEventListener("keydown", this.handleKeyDown, physicalKeyboardHighlightPreventDefault);
|
||||
document.addEventListener("mouseup", this.handleMouseUp);
|
||||
document.addEventListener("touchend", this.handleTouchEnd);
|
||||
|
||||
if (this.options.updateCaretOnSelectionChange) {
|
||||
document.addEventListener("selectionchange", this.handleSelectionChange);
|
||||
}
|
||||
|
||||
document.addEventListener("selectionchange", this.handleSelectionChange);
|
||||
document.addEventListener("select", this.handleSelect);
|
||||
}
|
||||
}
|
||||
@ -1266,7 +1245,7 @@ class SimpleKeyboard {
|
||||
/**
|
||||
* Tracking current input in order to handle caret positioning edge cases
|
||||
*/
|
||||
instance.activeInputElement = event.target;
|
||||
this.activeInputElement = event.target;
|
||||
|
||||
if (instance.options.debug) {
|
||||
console.log(
|
||||
@ -1290,7 +1269,7 @@ class SimpleKeyboard {
|
||||
/**
|
||||
* Resetting activeInputElement
|
||||
*/
|
||||
instance.activeInputElement = null;
|
||||
this.activeInputElement = null;
|
||||
|
||||
if (instance.options.debug) {
|
||||
console.log(
|
||||
@ -1332,13 +1311,7 @@ class SimpleKeyboard {
|
||||
document.removeEventListener("mouseup", this.handleMouseUp);
|
||||
document.removeEventListener("touchend", this.handleTouchEnd);
|
||||
document.removeEventListener("select", this.handleSelect);
|
||||
|
||||
// selectionchange is causing caret update issues on Chrome
|
||||
// https://github.com/hodgef/simple-keyboard/issues/2346
|
||||
if (this.options.updateCaretOnSelectionChange) {
|
||||
document.removeEventListener("selectionchange", this.handleSelectionChange);
|
||||
}
|
||||
|
||||
document.removeEventListener("selectionchange", this.handleSelectionChange);
|
||||
document.onpointerup = null;
|
||||
document.ontouchend = null;
|
||||
document.ontouchcancel = null;
|
||||
@ -1404,8 +1377,8 @@ class SimpleKeyboard {
|
||||
/**
|
||||
* Remove instance
|
||||
*/
|
||||
(window as SKWindow)["SimpleKeyboardInstances"][this.currentInstanceName] = null;
|
||||
delete (window as SKWindow)["SimpleKeyboardInstances"][this.currentInstanceName];
|
||||
window["SimpleKeyboardInstances"][this.currentInstanceName] = null;
|
||||
delete window["SimpleKeyboardInstances"][this.currentInstanceName];
|
||||
|
||||
/**
|
||||
* Reset initialized flag
|
||||
@ -1614,9 +1587,7 @@ class SimpleKeyboard {
|
||||
loadModules() {
|
||||
if (Array.isArray(this.options.modules)) {
|
||||
this.options.modules.forEach((KeyboardModule) => {
|
||||
const keyboardModule = this.utilities.isConstructor(KeyboardModule) ?
|
||||
new KeyboardModule(this) : KeyboardModule(this);
|
||||
|
||||
const keyboardModule = new KeyboardModule(this);
|
||||
keyboardModule.init && keyboardModule.init(this);
|
||||
});
|
||||
|
||||
@ -1690,7 +1661,7 @@ class SimpleKeyboard {
|
||||
updated_startIndex,
|
||||
updated_endIndex - updated_startIndex + 1
|
||||
);
|
||||
removedElements += updated_endIndex - updated_startIndex;
|
||||
removedElements = updated_endIndex - updated_startIndex;
|
||||
|
||||
/**
|
||||
* Inserting elements to container
|
||||
@ -1951,10 +1922,7 @@ class SimpleKeyboard {
|
||||
* This fires handler before onKeyReleased, therefore when that option is set we will fire the handler
|
||||
* in onmousedown instead
|
||||
*/
|
||||
if (
|
||||
typeof this.options.onKeyReleased !== "function" &&
|
||||
!(this.options.useMouseEvents && this.options.clickOnMouseDown)
|
||||
) {
|
||||
if (typeof this.options.onKeyReleased !== "function") {
|
||||
this.handleButtonClicked(button, e);
|
||||
}
|
||||
};
|
||||
@ -1963,10 +1931,7 @@ class SimpleKeyboard {
|
||||
* Fire button handler for onKeyReleased use-case
|
||||
*/
|
||||
if (
|
||||
(
|
||||
typeof this.options.onKeyReleased === "function" ||
|
||||
(this.options.useMouseEvents && this.options.clickOnMouseDown)
|
||||
) &&
|
||||
typeof this.options.onKeyReleased === "function" &&
|
||||
!this.isMouseHold
|
||||
) {
|
||||
this.handleButtonClicked(button, e);
|
||||
|
@ -5,6 +5,7 @@
|
||||
background: #ececec;
|
||||
border-bottom: 2px solid #b5b5b5;
|
||||
user-select: none;
|
||||
max-width: 272px;
|
||||
transform: translateY(-100%);
|
||||
margin-top: -10px;
|
||||
}
|
||||
|
@ -15,9 +15,7 @@
|
||||
border-radius: 5px;
|
||||
}
|
||||
|
||||
.hg-theme-default .hg-button span,
|
||||
.hg-theme-default .hg-button span svg
|
||||
{
|
||||
.hg-theme-default .hg-button span {
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
|
@ -216,7 +216,7 @@ it('CandidateBox select candidate will work', () => {
|
||||
keyboard.getButtonElement("a").click();
|
||||
keyboard.candidateBox.candidateBoxElement.querySelector("li").click();
|
||||
|
||||
expect(onSelect).toHaveBeenCalledWith("1", expect.anything());
|
||||
expect(onSelect).toBeCalledWith("1", expect.anything());
|
||||
keyboard.destroy();
|
||||
});
|
||||
|
||||
@ -332,98 +332,98 @@ it('CandidateBox show not be called if keyboard.candidateBox is undefined upon s
|
||||
});
|
||||
|
||||
it('CandidateBox selection should trigger onChange', () => {
|
||||
const keyboard = new Keyboard({
|
||||
layout: {
|
||||
default: [
|
||||
"a b {bksp}"
|
||||
]
|
||||
},
|
||||
layoutCandidates: {
|
||||
a: "1 2 3 4 5 6"
|
||||
},
|
||||
onChange: jest.fn(),
|
||||
onChangeAll: jest.fn()
|
||||
});
|
||||
|
||||
let candidateBoxOnItemSelected;
|
||||
const keyboard = new Keyboard({
|
||||
layout: {
|
||||
default: [
|
||||
"a b {bksp}"
|
||||
]
|
||||
},
|
||||
layoutCandidates: {
|
||||
a: "1 2 3 4 5 6"
|
||||
},
|
||||
onChange: jest.fn(),
|
||||
onChangeAll: jest.fn()
|
||||
});
|
||||
|
||||
const onSelect = jest.fn().mockImplementation((selectedCandidate) => {
|
||||
candidateBoxOnItemSelected(selectedCandidate);
|
||||
keyboard.candidateBox.destroy();
|
||||
});
|
||||
|
||||
const candidateBoxRenderFn = keyboard.candidateBox.renderPage;
|
||||
let candidateBoxOnItemSelected;
|
||||
|
||||
const onSelect = jest.fn().mockImplementation((selectedCandidate) => {
|
||||
candidateBoxOnItemSelected(selectedCandidate);
|
||||
keyboard.candidateBox.destroy();
|
||||
});
|
||||
|
||||
jest.spyOn(keyboard.candidateBox, "renderPage").mockImplementation((params) => {
|
||||
candidateBoxOnItemSelected = params.onItemSelected;
|
||||
params.onItemSelected = onSelect;
|
||||
candidateBoxRenderFn(params);
|
||||
});
|
||||
|
||||
keyboard.getButtonElement("a").click();
|
||||
keyboard.candidateBox.candidateBoxElement.querySelector("li").click();
|
||||
|
||||
expect(keyboard.options.onChange.mock.calls[0][0]).toBe("a");
|
||||
expect(keyboard.options.onChangeAll.mock.calls[0][0]).toMatchObject({"default": "a"});
|
||||
|
||||
expect(keyboard.options.onChange.mock.calls[1][0]).toBe("1");
|
||||
expect(keyboard.options.onChangeAll.mock.calls[1][0]).toMatchObject({"default": "1"});
|
||||
keyboard.destroy();
|
||||
});
|
||||
|
||||
it('CandidateBox normalization will work', () => {
|
||||
const keyboard = new Keyboard({
|
||||
layout: {
|
||||
default: [
|
||||
"a b {bksp}"
|
||||
]
|
||||
},
|
||||
layoutCandidates: {
|
||||
a: "신"
|
||||
},
|
||||
onChange: jest.fn(),
|
||||
onChangeAll: jest.fn()
|
||||
});
|
||||
|
||||
let candidateBoxOnItemSelected;
|
||||
const candidateBoxRenderFn = keyboard.candidateBox.renderPage;
|
||||
|
||||
jest.spyOn(keyboard.candidateBox, "renderPage").mockImplementation((params) => {
|
||||
candidateBoxOnItemSelected = params.onItemSelected;
|
||||
params.onItemSelected = onSelect;
|
||||
candidateBoxRenderFn(params);
|
||||
});
|
||||
|
||||
const onSelect = jest.fn().mockImplementation((selectedCandidate) => {
|
||||
candidateBoxOnItemSelected(selectedCandidate);
|
||||
keyboard.candidateBox.destroy();
|
||||
});
|
||||
|
||||
const candidateBoxRenderFn = keyboard.candidateBox.renderPage;
|
||||
keyboard.getButtonElement("a").click();
|
||||
keyboard.candidateBox.candidateBoxElement.querySelector("li").click();
|
||||
|
||||
jest.spyOn(keyboard.candidateBox, "renderPage").mockImplementation((params) => {
|
||||
candidateBoxOnItemSelected = params.onItemSelected;
|
||||
params.onItemSelected = onSelect;
|
||||
candidateBoxRenderFn(params);
|
||||
expect(keyboard.options.onChange.mock.calls[0][0]).toBe("a");
|
||||
expect(keyboard.options.onChangeAll.mock.calls[0][0]).toMatchObject({"default": "a"});
|
||||
|
||||
expect(keyboard.options.onChange.mock.calls[1][0]).toBe("1");
|
||||
expect(keyboard.options.onChangeAll.mock.calls[1][0]).toMatchObject({"default": "1"});
|
||||
keyboard.destroy();
|
||||
});
|
||||
|
||||
keyboard.getButtonElement("a").click();
|
||||
keyboard.candidateBox.candidateBoxElement.querySelector("li").click();
|
||||
it('CandidateBox normalization will work', () => {
|
||||
const keyboard = new Keyboard({
|
||||
layout: {
|
||||
default: [
|
||||
"a b {bksp}"
|
||||
]
|
||||
},
|
||||
layoutCandidates: {
|
||||
a: "신"
|
||||
},
|
||||
onChange: jest.fn(),
|
||||
onChangeAll: jest.fn()
|
||||
});
|
||||
|
||||
let candidateBoxOnItemSelected;
|
||||
|
||||
const onSelect = jest.fn().mockImplementation((selectedCandidate) => {
|
||||
candidateBoxOnItemSelected(selectedCandidate);
|
||||
keyboard.candidateBox.destroy();
|
||||
});
|
||||
|
||||
const candidateBoxRenderFn = keyboard.candidateBox.renderPage;
|
||||
|
||||
jest.spyOn(keyboard.candidateBox, "renderPage").mockImplementation((params) => {
|
||||
candidateBoxOnItemSelected = params.onItemSelected;
|
||||
params.onItemSelected = onSelect;
|
||||
candidateBoxRenderFn(params);
|
||||
});
|
||||
|
||||
keyboard.getButtonElement("a").click();
|
||||
keyboard.candidateBox.candidateBoxElement.querySelector("li").click();
|
||||
|
||||
expect(keyboard.options.onChange.mock.calls[0][0]).toBe("a");
|
||||
expect(keyboard.options.onChangeAll.mock.calls[0][0]).toMatchObject({"default": "a"});
|
||||
|
||||
expect(keyboard.options.onChange.mock.calls[0][0]).toBe("a");
|
||||
expect(keyboard.options.onChangeAll.mock.calls[0][0]).toMatchObject({"default": "a"});
|
||||
// Selected candidate will be normalized
|
||||
expect(keyboard.options.onChange.mock.calls[1][0]).toBe("신");
|
||||
expect(keyboard.options.onChange.mock.calls[1][0].length).toBe(3);
|
||||
expect(keyboard.options.onChangeAll.mock.calls[1][0]).toMatchObject({"default": "신"});
|
||||
|
||||
// Selected candidate will be normalized
|
||||
expect(keyboard.options.onChange.mock.calls[1][0]).toBe("신");
|
||||
expect(keyboard.options.onChange.mock.calls[1][0].length).toBe(3);
|
||||
expect(keyboard.options.onChangeAll.mock.calls[1][0]).toMatchObject({"default": "신"});
|
||||
// Selected candidate will not be normalized
|
||||
keyboard.clearInput();
|
||||
keyboard.setOptions({ disableCandidateNormalization: true });
|
||||
|
||||
// Selected candidate will not be normalized
|
||||
keyboard.clearInput();
|
||||
keyboard.setOptions({ disableCandidateNormalization: true });
|
||||
keyboard.getButtonElement("a").click();
|
||||
keyboard.candidateBox.candidateBoxElement.querySelector("li").click();
|
||||
|
||||
expect(keyboard.options.onChange.mock.calls[2][0]).toBe("a");
|
||||
expect(keyboard.options.onChangeAll.mock.calls[2][0]).toMatchObject({"default": "a"});
|
||||
|
||||
keyboard.getButtonElement("a").click();
|
||||
keyboard.candidateBox.candidateBoxElement.querySelector("li").click();
|
||||
expect(keyboard.options.onChange.mock.calls[3][0]).toBe("신");
|
||||
expect(keyboard.options.onChange.mock.calls[3][0].length).toBe(1);
|
||||
expect(keyboard.options.onChangeAll.mock.calls[3][0]).toMatchObject({"default": "신"});
|
||||
|
||||
expect(keyboard.options.onChange.mock.calls[2][0]).toBe("a");
|
||||
expect(keyboard.options.onChangeAll.mock.calls[2][0]).toMatchObject({"default": "a"});
|
||||
|
||||
expect(keyboard.options.onChange.mock.calls[3][0]).toBe("신");
|
||||
expect(keyboard.options.onChange.mock.calls[3][0].length).toBe(1);
|
||||
expect(keyboard.options.onChangeAll.mock.calls[3][0]).toMatchObject({"default": "신"});
|
||||
|
||||
keyboard.destroy();
|
||||
});
|
||||
keyboard.destroy();
|
||||
});
|
@ -218,19 +218,6 @@ it('Keyboard onChange will work', () => {
|
||||
expect(output).toBe("q");
|
||||
});
|
||||
|
||||
it('Keyboard beforeInputChange will work', () => {
|
||||
const mockBeforeInputUpdate = jest.fn();
|
||||
|
||||
const keyboard = new Keyboard({
|
||||
beforeInputUpdate: mockBeforeInputUpdate,
|
||||
useMouseEvents: true
|
||||
});
|
||||
|
||||
keyboard.getButtonElement("q").onclick();
|
||||
|
||||
expect(mockBeforeInputUpdate).toHaveBeenCalledWith(keyboard);
|
||||
});
|
||||
|
||||
it('Keyboard onChangeAll will work', () => {
|
||||
let output;
|
||||
|
||||
|
@ -2,10 +2,6 @@
|
||||
import SimpleKeyboard from "./components/Keyboard";
|
||||
import Utilities from "./services/Utilities";
|
||||
|
||||
export interface SKWindow extends Window {
|
||||
SimpleKeyboardInstances?: any;
|
||||
};
|
||||
|
||||
export interface KeyboardLayoutObject {
|
||||
[key: string]: string[];
|
||||
}
|
||||
@ -265,25 +261,15 @@ export interface KeyboardOptions {
|
||||
*/
|
||||
enableLayoutCandidatesKeyPress?: boolean;
|
||||
|
||||
/**
|
||||
* Updates caret when selectionchange event is fired
|
||||
*/
|
||||
updateCaretOnSelectionChange?: boolean;
|
||||
|
||||
/**
|
||||
* When useMouseEvents is enabled, this option allows you to trigger a button click event on mousedown
|
||||
*/
|
||||
clickOnMouseDown?: boolean;
|
||||
|
||||
/**
|
||||
* Executes the callback function every time simple-keyboard is rendered (e.g: when you change layouts).
|
||||
*/
|
||||
onRender?: (instance: SimpleKeyboard) => void;
|
||||
onRender?: (instance?: SimpleKeyboard) => void;
|
||||
|
||||
/**
|
||||
* Executes the callback function once simple-keyboard is rendered for the first time (on initialization).
|
||||
*/
|
||||
onInit?: (instance: SimpleKeyboard) => void;
|
||||
onInit?: (instance?: SimpleKeyboard) => void;
|
||||
|
||||
/**
|
||||
* Retrieves the current input
|
||||
@ -305,13 +291,8 @@ export interface KeyboardOptions {
|
||||
*/
|
||||
onKeyReleased?: (button: string, e?: MouseEvent) => any;
|
||||
|
||||
/**
|
||||
* Executes the callback function before an input is about to be updated
|
||||
*/
|
||||
beforeInputUpdate?: (instance: SimpleKeyboard) => void;
|
||||
|
||||
/**
|
||||
* Module options can have any format
|
||||
*/
|
||||
[name: string]: any;
|
||||
}
|
||||
}
|
@ -1,6 +1,4 @@
|
||||
import { KeyboardLayoutObject } from "../interfaces";
|
||||
|
||||
export const getDefaultLayout = (): KeyboardLayoutObject => {
|
||||
export const getDefaultLayout = () => {
|
||||
return {
|
||||
default: [
|
||||
"` 1 2 3 4 5 6 7 8 9 0 - = {bksp}",
|
||||
|
@ -27,7 +27,7 @@ class PhysicalKeyboard {
|
||||
handleHighlightKeyDown(e: KeyboardEvent) {
|
||||
const options = this.getOptions();
|
||||
|
||||
if(options.physicalKeyboardHighlightPreventDefault && this.isModifierKey(e)){
|
||||
if(options.physicalKeyboardHighlightPreventDefault && this.isMofifierKey(e)){
|
||||
e.preventDefault();
|
||||
e.stopImmediatePropagation();
|
||||
}
|
||||
@ -66,7 +66,7 @@ class PhysicalKeyboard {
|
||||
// Even though we have an array of buttons, we just want to press one of them
|
||||
if (options.physicalKeyboardHighlightPress) {
|
||||
if (options.physicalKeyboardHighlightPressUsePointerEvents) {
|
||||
buttonDOM[0]?.onpointerdown?.(e);
|
||||
buttonDOM[0]?.onpointerdown();
|
||||
} else if (options.physicalKeyboardHighlightPressUseClick) {
|
||||
buttonDOM[0]?.click();
|
||||
} else {
|
||||
@ -78,7 +78,7 @@ class PhysicalKeyboard {
|
||||
|
||||
if (options.physicalKeyboardHighlightPress) {
|
||||
if (options.physicalKeyboardHighlightPressUsePointerEvents) {
|
||||
buttonDOM?.onpointerdown?.(e);
|
||||
buttonDOM.onpointerdown();
|
||||
} else if (options.physicalKeyboardHighlightPressUseClick) {
|
||||
buttonDOM.click();
|
||||
} else {
|
||||
@ -93,7 +93,7 @@ class PhysicalKeyboard {
|
||||
handleHighlightKeyUp(e: KeyboardEvent) {
|
||||
const options = this.getOptions();
|
||||
|
||||
if(options.physicalKeyboardHighlightPreventDefault && this.isModifierKey(e)){
|
||||
if(options.physicalKeyboardHighlightPreventDefault && this.isMofifierKey(e)){
|
||||
e.preventDefault();
|
||||
e.stopImmediatePropagation();
|
||||
}
|
||||
@ -117,13 +117,13 @@ class PhysicalKeyboard {
|
||||
|
||||
// Even though we have an array of buttons, we just want to press one of them
|
||||
if (options.physicalKeyboardHighlightPressUsePointerEvents) {
|
||||
buttonDOM[0]?.onpointerup?.(e);
|
||||
buttonDOM[0]?.onpointerup();
|
||||
}
|
||||
} else {
|
||||
applyButtonStyle(buttonDOM);
|
||||
|
||||
if (options.physicalKeyboardHighlightPressUsePointerEvents) {
|
||||
buttonDOM?.onpointerup?.(e);
|
||||
buttonDOM.onpointerup();
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -260,7 +260,7 @@ class PhysicalKeyboard {
|
||||
}[keyCode] || "";
|
||||
}
|
||||
|
||||
isModifierKey = (e: KeyboardEvent): boolean => {
|
||||
isMofifierKey = (e: KeyboardEvent): boolean => {
|
||||
return (
|
||||
e.altKey
|
||||
|| e.ctrlKey
|
||||
|
@ -561,18 +561,6 @@ class Utilities {
|
||||
* Reusable empty function
|
||||
*/
|
||||
static noop = () => {};
|
||||
|
||||
/**
|
||||
* Check if a function is a constructor
|
||||
*/
|
||||
isConstructor(f: any) {
|
||||
try {
|
||||
Reflect.construct(String, [], f);
|
||||
} catch (e) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
export default Utilities;
|
||||
|
@ -212,7 +212,7 @@ it('PhysicalKeyboard keyCodeToKey will work', () => {
|
||||
|
||||
expect(keyboard.physicalKeyboard.keyCodeToKey(186)).toBe(";");
|
||||
|
||||
const methodTest = jest.spyOn(keyboard.physicalKeyboard, "keyCodeToKey");
|
||||
const methodTest = spyOn(keyboard.physicalKeyboard, "keyCodeToKey");
|
||||
|
||||
document.dispatchEvent(new KeyboardEvent('keyup', {
|
||||
keyCode: 186,
|
||||
@ -221,5 +221,5 @@ it('PhysicalKeyboard keyCodeToKey will work', () => {
|
||||
}
|
||||
}));
|
||||
|
||||
expect(methodTest).toHaveBeenCalledWith(186);
|
||||
expect(methodTest).toBeCalledWith(186);
|
||||
});
|
@ -8,6 +8,7 @@
|
||||
"sourceMap": true,
|
||||
"declaration": true,
|
||||
"emitDeclarationOnly": true,
|
||||
"suppressImplicitAnyIndexErrors": true,
|
||||
"lib": ["es2020", "dom"],
|
||||
"moduleResolution": "node",
|
||||
"downlevelIteration": true,
|
||||
|
Loading…
x
Reference in New Issue
Block a user