@area2-ai/a2-node-keystroke-package
Version:
## Description
929 lines (904 loc) • 31.7 kB
JavaScript
import emojiRegex from 'emoji-regex';
import { v4 } from 'uuid';
function _defineProperties(e, r) {
for (var t = 0; t < r.length; t++) {
var o = r[t];
o.enumerable = o.enumerable || !1, o.configurable = !0, "value" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o);
}
}
function _createClass(e, r, t) {
return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, "prototype", {
writable: !1
}), e;
}
function _extends() {
return _extends = Object.assign ? Object.assign.bind() : function (n) {
for (var e = 1; e < arguments.length; e++) {
var t = arguments[e];
for (var r in t) ({}).hasOwnProperty.call(t, r) && (n[r] = t[r]);
}
return n;
}, _extends.apply(null, arguments);
}
function _toPrimitive(t, r) {
if ("object" != typeof t || !t) return t;
var e = t[Symbol.toPrimitive];
if (void 0 !== e) {
var i = e.call(t, r || "default");
if ("object" != typeof i) return i;
throw new TypeError("@@toPrimitive must return a primitive value.");
}
return ("string" === r ? String : Number)(t);
}
function _toPropertyKey(t) {
var i = _toPrimitive(t, "string");
return "symbol" == typeof i ? i : i + "";
}
var defaultCountriesAndLayoutByLanguage = {
en: {
country: "US",
keyboardLayout: "QWERTY"
},
zh: {
country: "CN",
keyboardLayout: "QWERTY"
},
es: {
country: "ES",
keyboardLayout: "QWERTY (Spanish)"
},
fr: {
country: "FR",
keyboardLayout: "AZERTY"
},
ar: {
country: "SA",
keyboardLayout: "Arabic (Standard)"
},
pt: {
country: "PT",
keyboardLayout: "QWERTY (Portuguese)"
},
ru: {
country: "RU",
keyboardLayout: "ЙЦУКЕН"
},
ja: {
country: "JP",
keyboardLayout: "QWERTY (JIS)"
},
de: {
country: "DE",
keyboardLayout: "QWERTZ"
},
it: {
country: "IT",
keyboardLayout: "QWERTY (Italian)"
}
};
var keyZones = {
1: /[12qwaszx]/i,
2: /[34erdfcv]/i,
3: /[56tyghbn]/i,
4: /[78uijkm,]/i,
5: /[90opl;./]/i,
6: /[-=']/i
};
var specialKeys = {
Backspace: /Backspace/i,
Meta: /(Shift|Alt|Control|CapsLock)/i,
Enter: /Enter/i,
Space: / /i
};
var keyTypes = {
alphanumeric: /^[a-z0-9]$/i,
punctuation: /[!"#$%&'()*+,\-./:;<=>?@[\\\]^_`{|}~]/,
modifierKeys: /^(Shift|Alt|Control|CapsLock|Meta|ContextMenu|NumLock|ScrollLock)$/i,
space: / /,
backspace: /Backspace/i,
emoji: /*#__PURE__*/emojiRegex(),
enterKey: /Enter/i //* Regex to match "Enter" key
};
var seasons = {
1: 'Winter',
2: "Winter",
3: "Spring",
4: "Spring",
5: "Spring",
6: "Summer",
7: "Summer",
8: "Summer",
9: "Fall",
10: "Fall",
11: "Fall",
12: "Winter"
};
var specialKeyMap = {
'Backspace': 8,
'Tab': 9,
'Enter': 13,
'Shift': 16,
'Ctrl': 17,
'Alt': 18,
'Pause': 19,
'CapsLock': 20,
'Esc': 27,
'Space': 32,
'PageUp': 33,
'PageDown': 34,
'End': 35,
'Home': 36,
'LeftArrow': 37,
'UpArrow': 38,
'RightArrow': 39,
'DownArrow': 40,
'Insert': 45,
'Delete': 46,
'Meta': 91,
'ContextMenu': 93,
'NumLock': 144,
'ScrollLock': 145,
'SemiColon': 186,
'EqualSign': 187,
'Comma': 188,
'Dash': 189,
'Period': 190,
'ForwardSlash': 191,
'GraveAccent': 192,
'OpenBracket': 219,
'BackSlash': 220,
'CloseBracket': 221,
'SingleQuote': 222
};
var checkIsEmoji = function checkIsEmoji(character) {
var regex = emojiRegex();
return regex.test(character);
};
/**
* Formats the user's language and country code based on the browser's language settings.
*
* @returns {string} A formatted language code in the form of `language-country` (e.g., `en-US`).
*
* ### Functionality:
* - Retrieves the user's browser language using `navigator.language`.
* - Splits the language string into a language code (e.g., `en`) and a country code (e.g., `US`).
* - Checks if the country code is valid (i.e., not numeric):
* - If valid, returns the original `language-country` format.
* - If invalid or missing, assigns a default country code based on the language.
* - Returns the final formatted language string.
*/
var formatLanguage = function formatLanguage() {
var _defaultCountriesAndL;
var lang = navigator.language.split('-');
var userLanguageCode = lang[0];
var userCountryCode = lang[1];
var countryCodeToNumber = Number(userCountryCode);
if (userCountryCode && isNaN(countryCodeToNumber)) {
return lang.join('-');
}
userCountryCode = ((_defaultCountriesAndL = defaultCountriesAndLayoutByLanguage[userLanguageCode]) == null ? void 0 : _defaultCountriesAndL.country) || 'not-found';
if (userCountryCode === 'not-found') {
return 'en-US';
}
return userLanguageCode + "-" + userCountryCode;
};
// Function to generate a UUID
var generateUUID = function generateUUID() {
return v4();
};
/**
* Returns the day of the week as a string based on a given date.
* @param date - The date object to get the day of the week from.
* @returns The corresponding day of the week as a string.
*/
var getDayOfWeek = function getDayOfWeek(date) {
var daysOfWeek = ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'];
return daysOfWeek[date.getDay()];
};
/**
* Compares two strings and returns the words present in the first string but not in the second.
* The comparison is case-insensitive and ignores leading/trailing spaces.
*
* @param {string} string1 - The first string to compare.
* @param {string} string2 - The second string to compare against.
* @returns {string} - A single string containing the words from `string1` that are not found in `string2`, separated by spaces.
*
* @example
* const string1 = "Hello world from TypeScript";
* const string2 = "Hello from JavaScript";
* const result = getDifferenceBetweenWords(string1, string2);
* console.log(result); // Output: "world TypeScript"
*/
var getDifferenceBetweenWords = function getDifferenceBetweenWords(string1, string2) {
//? Splits both strings into words and removes extra spaces
var words1 = string1.toLowerCase().trim().split(/\s+/);
var words2 = string2.toLowerCase().trim().split(/\s+/);
//? Filters out words in string1 that are not in string2
var differences = words1.filter(function (word) {
return !words2.includes(word);
});
return differences.join(' ');
};
/**
* Converts an emoji character to its Unicode code point representation.
*
* @param {string} emoji - The emoji character to convert.
* @param {boolean} [isAndroid=false] - Determines if the emoji should be normalized for Android devices.
* - `true`: Normalizes the emoji using NFC (Normalization Form Canonical Composition) before converting.
* - `false`: Directly retrieves the Unicode code point without normalization.
* @returns {string} The Unicode code point of the emoji in uppercase hexadecimal format.
*
* @example
* getEmojiUnicode('😀');
* // Returns: "1F600"
*
* getEmojiUnicode('😀', true);
* // Returns: "1F600"
*/
var getEmojiUnicode = function getEmojiUnicode(emoji, isAndroid) {
if (isAndroid === void 0) {
isAndroid = false;
}
if (isAndroid) {
var normalizedCodePoint = emoji.normalize('NFC').codePointAt(0).toString(16).toUpperCase();
return normalizedCodePoint;
}
// Get the code in UTF-32 format
var utf32CodePoint = emoji.codePointAt(0).toString(16).toUpperCase();
return utf32CodePoint;
};
var getInputType = function getInputType(target) {
var hasAutocorrect = target.getAttribute('autocorrect') ? true : false;
var isSpellcheckEnabled = target.spellcheck;
if (target.tagName !== 'INPUT' && target.tagName !== 'TEXTAREA') {
return 'Text_ACOFF';
}
if (hasAutocorrect || isSpellcheckEnabled) {
return 'Text';
}
return 'Text_ACOFF';
};
/**
* Calculates the area occupied by the on-screen keyboard on mobile devices.
*
* This function determines the dimensions of the keyboard area based on the
* difference between the total screen height and the current viewport height.
* If the difference is below a certain threshold, it assumes that the keyboard
* is not visible.
*
* @returns {KeyboardArea | undefined} - An object representing the keyboard's position and dimensions:
* - `x`: The x-coordinate of the keyboard's starting position (always `0` for full-width keyboards).
* - `y`: The y-coordinate of the top edge of the keyboard, which matches the viewport's bottom edge.
* - `width`: The width of the keyboard (matches the viewport's width).
* - `height`: The height of the keyboard.
*
* Returns `undefined` if the keyboard is not visible or if the function is called outside a browser environment.
*
* @example
* const keyboardArea = getKeyboardArea();
* if (keyboardArea) {
* console.log(`Keyboard height: ${keyboardArea.height}`);
* }
*/
var getKeyboardArea = function getKeyboardArea() {
var viewportHeight = window.innerHeight;
var fullHeight = window.screen.height; // Total screen height
//? If the difference between the height of the window and the screen is significant, there is a visible keyboard.
var keyboardHeight = fullHeight - viewportHeight;
if (keyboardHeight <= 100) {
return;
} // Arbitrary threshold for considering the keypad to be active
return {
x: 0,
y: viewportHeight,
width: window.innerWidth,
height: keyboardHeight
};
};
var getKeyboardLayout = function getKeyboardLayout() {
var _defaultCountriesAndL;
var userLanguageCode = navigator.language.split('-')[0];
return ((_defaultCountriesAndL = defaultCountriesAndLayoutByLanguage[userLanguageCode]) == null ? void 0 : _defaultCountriesAndL.keyboardLayout) || 'QWERTY';
};
/**
* Calculates the screen size of the device in the specified unit ('px' or 'mm').
*
* @param {('px' | 'mm')} unit - The unit of measurement for the screen size.
* 'px' returns the dimensions in pixels,
* while 'mm' returns the dimensions in millimeters (estimated).
* @returns {ScreenSize} An object containing the width and height of the screen in the selected unit.
* - If 'px', dimensions are returned as integers.
* - If 'mm', dimensions are returned as numbers rounded to two decimal places.
*
* @example
* // Get screen size in pixels
* const sizeInPixels = getScreenDeviceSize('px');
* console.log(sizeInPixels); // { width: 1920, height: 1080 }
*
* @example
* // Get screen size in millimeters
* const sizeInMillimeters = getScreenDeviceSize('mm');
* console.log(sizeInMillimeters); // { width: 508.02, height: 285.75 }
*
* @note The conversion to millimeters is an estimation based on the device's pixel density (DPI).
* The accuracy may vary depending on the device and browser.
*/
var getScreenDeviceSize = function getScreenDeviceSize(unit) {
var screenWidthPixels = screen.width;
var screenHeightPixels = screen.height;
if (unit === 'px') {
return {
width: screenWidthPixels,
height: screenHeightPixels
};
}
var dpi = window.devicePixelRatio * 96; // Estimation based on browser pixel rate
var inchToMm = 25.4; // Conversion from inches to mm
var screenWidthMm = screen.width / dpi * inchToMm;
var screenHeightMm = screen.height / dpi * inchToMm;
return {
width: Number(screenWidthMm.toFixed(2)),
height: Number(screenHeightMm.toFixed(2))
};
};
/**
* Returns the season for a given month.
* @param month - The month as a number (1 for January, 12 for December).
* @returns The corresponding season as a string.
*/
var getSeason = function getSeason(month) {
if (month < 1 || month > 12) throw new Error('The month must be a number between 1 and 12');
return seasons[month];
};
/**
* Returns the time of day based on the hour.
* @param hour - The hour as a number (0-23).
* @returns The corresponding time of day as a string.
*/
var getTimeOfDay = function getTimeOfDay(hour) {
if (hour < 0 || hour >= 24) throw new Error('The time must be a number between 0 and 23');
if (hour >= 6 && hour < 12) return 'Morning';
if (hour >= 12 && hour < 18) return 'Afternoon';
if (hour >= 18 && hour <= 23) return 'Evening';
return 'Night';
};
var getKeyCode = function getKeyCode(character) {
if (checkIsEmoji(character)) {
return 900;
} //* Special code for emojis
if (character.length === 1) {
return character.charCodeAt(0);
}
return specialKeyMap[character] || 0; //* Default to 0 if no match is found
};
var getKeyArea = function getKeyArea(character) {
//? Determine the key zone for the given character
for (var _i = 0, _Object$entries = Object.entries(keyZones); _i < _Object$entries.length; _i++) {
var _Object$entries$_i = _Object$entries[_i],
zone = _Object$entries$_i[0],
regex = _Object$entries$_i[1];
if (regex.test(character)) {
return parseInt(zone);
}
}
//? Check if the character matches a special key
if (specialKeys.Backspace.test(character) || specialKeys.Meta.test(character) || specialKeys.Enter.test(character) || specialKeys.Space.test(character)) {
return 0;
}
return 0; //* Default to 0 if no match is found
};
var getKeyType = function getKeyType(character) {
for (var _i2 = 0, _Object$entries2 = Object.entries(keyTypes); _i2 < _Object$entries2.length; _i2++) {
var _Object$entries2$_i = _Object$entries2[_i2],
type = _Object$entries2$_i[0],
regex = _Object$entries2$_i[1];
if (regex.test(character)) {
switch (type) {
case 'alphanumeric':
return 'an';
case 'punctuation':
return 'pt';
case 'modifierKeys':
return 'md';
case 'space':
return 'sp';
case 'backspace':
return 'bk';
case 'emoji':
return 'em';
case 'enterKey':
return 'en';
}
}
}
return 'ukn'; //* Returns 'ukn' if the type is not found
};
var getInitialMobileTypingData = function getInitialMobileTypingData() {
return {
autocorrectLengths: [],
autocorrectTimes: [],
emojis: [],
keyArea: [],
keyTypes: [],
language: formatLanguage(),
layout: getKeyboardLayout(),
pasteLengths: [],
pasteTimes: [],
performance: [],
predictionLengths: [],
predictionTimes: [],
pressTimes: [],
qualityCheck: [],
releaseTimes: [],
screenSizeMm: getScreenDeviceSize('mm'),
screenSizePx: getScreenDeviceSize('px'),
season: getSeason(new Date().getMonth() + 1),
sessionID: generateUUID(),
startUnixTime: null,
textField: "Text_ACOFF",
time: getTimeOfDay(new Date().getHours()),
timeZone: new Date().getTimezoneOffset() / -60,
weekday: getDayOfWeek(new Date())
};
};
var getInitialTypingData = function getInitialTypingData() {
return {
// startTimestamp: getFormattedTimestamp(),
keyArea: [],
keyTypes: [],
length: 0,
pressTimes: [],
qualityCheck: [],
releaseTimes: [],
season: getSeason(new Date().getMonth() + 1),
sessionID: generateUUID(),
setting: "ah",
source: "mech",
startUnixTime: null,
study: "demo",
task: "free",
textStructure: [],
time: getTimeOfDay(new Date().getHours()),
timeZone: new Date().getTimezoneOffset() / -60,
weekday: getDayOfWeek(new Date())
};
};
/**
* Manages keystroke data for a typing session on Android devices.
*/
var AndroidKeystrokeManager = /*#__PURE__*/function () {
function AndroidKeystrokeManager() {
this.isTypingSessionActive = false;
this.typingData = getInitialMobileTypingData();
this.openKeyEntry = undefined;
this.textWasPasted = false;
this.previousText = undefined;
this.backspaceWasPressed = false;
this.performanceStart = 0;
this.lastKeyPressed = undefined;
this.prevContentLength = 0;
}
/**
* Returns whether a typing session is active.
*/
var _proto = AndroidKeystrokeManager.prototype;
/**
* Processes the input content before it changes.
* @param currentValue - Current value of the input.
* @param inputContentValue - Previous value of the input.
*/
_proto.processBeforeInput = function processBeforeInput(currentValue, inputContentValue) {
this.prevContentLength = currentValue.length;
this.previousText = inputContentValue; // Before it changes
}
/**
* Processes the paste event.
* @param pastedText - Text that was pasted.
*/;
_proto.processPaste = function processPaste(pastedText) {
this.textWasPasted = true;
if (!this.isTypingSessionActive) {
return;
}
var diff = Date.now() / 1000 - this.typingData.startUnixTime; //* Seconds
this.typingData = _extends({}, this.typingData, {
pasteTimes: [].concat(this.typingData.pasteTimes, [Math.trunc(diff * 1000)]),
pasteLengths: [].concat(this.typingData.pasteLengths, [pastedText.length])
});
}
/**
* Processes the autocorrection event.
* @param keyPressed - Key that was pressed.
* @param newValue - New value of the input.
*/;
_proto.processAutocorrection = function processAutocorrection(keyPressed, newValue) {
if (this.textWasPasted) {
this.textWasPasted = false;
return;
}
if (this.backspaceWasPressed) {
this.backspaceWasPressed = false;
return;
}
if (checkIsEmoji(keyPressed)) {
return;
}
if (keyPressed.length <= 1) {
return;
}
var diff = Date.now() / 1000 - this.typingData.startUnixTime; //* Seconds
var autocorrectedWord;
//? If they are the same, it was already a correction
if (keyPressed === newValue) {
autocorrectedWord = keyPressed.trim().toLowerCase();
}
autocorrectedWord = getDifferenceBetweenWords(newValue, this.previousText);
if (autocorrectedWord.length === 0) {
return;
}
this.previousText = undefined;
this.typingData = _extends({}, this.typingData, {
autocorrectLengths: [].concat(this.typingData.autocorrectLengths, [autocorrectedWord.length]),
autocorrectTimes: [].concat(this.typingData.autocorrectTimes, [Math.trunc(diff * 1000)])
});
}
/**
* Processes the key input event.
* @param inputContent - Content of the input.
*/;
_proto.processKeyInput = function processKeyInput(inputContent) {
var _this$openKeyEntry;
var diff = inputContent.length - this.prevContentLength;
var keyPressed = inputContent.slice(-diff);
if (diff < 1) {
this.backspaceWasPressed = true;
keyPressed = 'Backspace';
}
this.lastKeyPressed = keyPressed;
this.processAutocorrection(keyPressed, inputContent);
//? Ensure a key press event is not duplicated
if (((_this$openKeyEntry = this.openKeyEntry) == null ? void 0 : _this$openKeyEntry.keyValue) === keyPressed) {
return;
}
this.openKeyEntry = {
keyValue: keyPressed
};
}
/**
* Processes a keydown event and updates typing data.
* @param target - The target input element.
*/;
_proto.processKeydown = function processKeydown(target) {
this.performanceStart = performance.now();
var temporalStartUnixTime = Date.now() / 1000; //* Seconds
var pressTime;
if (!this.isTypingSessionActive) {
this.isTypingSessionActive = true;
pressTime = Date.now() / 1000 - temporalStartUnixTime; //* Compute relative time in seconds
this.typingData = _extends({}, this.typingData, {
textField: getInputType(target),
keyboardArea: getKeyboardArea(),
startUnixTime: temporalStartUnixTime,
pressTimes: [].concat(this.typingData.pressTimes, [Math.trunc(pressTime * 1000000)])
});
return;
}
pressTime = Date.now() / 1000 - this.typingData.startUnixTime; //* Compute relative time in seconds
this.typingData = _extends({}, this.typingData, {
pressTimes: [].concat(this.typingData.pressTimes, [Math.trunc(pressTime * 1000000)])
});
}
/**
* Processes a keyup event and updates typing data.
*/;
_proto.processKeyup = function processKeyup() {
var emojiUnicode;
var keyCode = getKeyCode(this.lastKeyPressed);
var keyArea = getKeyArea(this.lastKeyPressed);
var keyType = getKeyType(this.lastKeyPressed);
//? If is emoji
if (keyCode === 900) {
emojiUnicode = getEmojiUnicode(this.lastKeyPressed, true);
}
var releaseTime = Date.now() / 1000 - this.typingData.startUnixTime; //* Compute relative time in Seconds
var performanceEnd = performance.now();
this.typingData = _extends({}, this.typingData, {
releaseTimes: [].concat(this.typingData.releaseTimes, [Math.trunc(releaseTime * 1000000)]),
performance: [].concat(this.typingData.performance, [performanceEnd - this.performanceStart]),
keyArea: [].concat(this.typingData.keyArea, [keyArea]),
keyTypes: [].concat(this.typingData.keyTypes, [keyType]),
emojis: [].concat(this.typingData.emojis, emojiUnicode ? [emojiUnicode] : [])
});
this.openKeyEntry = undefined;
}
/**
* Ends the current typing session and returns the collected typing data.
* @returns The collected typing data.
*/;
_proto.endTypingSession = function endTypingSession() {
this.isTypingSessionActive = false;
return this.typingData;
}
/**
* Resets the typing data to its initial state.
*/;
_proto.resetTypingData = function resetTypingData() {
this.typingData = getInitialMobileTypingData();
this.performanceStart = 0;
};
return _createClass(AndroidKeystrokeManager, [{
key: "getIsTypingSessionActive",
get: function get() {
return this.isTypingSessionActive;
}
}]);
}();
/**
* Manages keystroke data for a typing session on iOS devices.
*/
var IosKeystrokeManager = /*#__PURE__*/function () {
function IosKeystrokeManager() {
this.isTypingSessionActive = false;
this.typingData = getInitialMobileTypingData();
this.openKeyEntry = {};
this.textWasPasted = false;
this.previousText = undefined;
this.backspaceWasPressed = false;
this.performanceStart = 0;
this.prevContentLength = 0;
}
/**
* Returns whether a typing session is active.
*/
var _proto = IosKeystrokeManager.prototype;
/**
* Processes the paste event.
* @param pastedText - Text that was pasted.
*/
_proto.processPaste = function processPaste(pastedText) {
this.textWasPasted = true;
if (!this.isTypingSessionActive) {
return;
}
var diff = Date.now() / 1000 - this.typingData.startUnixTime; //* Seconds
this.typingData = _extends({}, this.typingData, {
pasteTimes: [].concat(this.typingData.pasteTimes, [Math.trunc(diff * 1000)]),
pasteLengths: [].concat(this.typingData.pasteLengths, [pastedText.length])
});
}
/**
* Processes the autocorrection event.
* @param textInputValue - New value of the input.
*/;
_proto.processAutocorrection = function processAutocorrection(textInputValue) {
if (!this.previousText) {
return;
}
if (textInputValue.startsWith(this.previousText)) {
return;
}
var diff = Date.now() / 1000 - this.typingData.startUnixTime; //* Seconds
var autocorrectedWord = getDifferenceBetweenWords(textInputValue, this.previousText);
this.typingData = _extends({}, this.typingData, {
autocorrectTimes: [].concat(this.typingData.autocorrectTimes, [Math.trunc(diff * 1000)]),
autocorrectLengths: [].concat(this.typingData.autocorrectLengths, [autocorrectedWord.length])
});
this.previousText = undefined;
}
/**
* Processes the prediction event.
* @param newValue - New value of the input.
* @param textSnapshot - Previous value of the input.
*/;
_proto.processPrediction = function processPrediction(newValue, textSnapshot) {
if (this.textWasPasted) {
this.textWasPasted = false;
return;
}
if (this.backspaceWasPressed) {
this.backspaceWasPressed = false;
return;
}
//? Checks if the last character contains an emoji
var lastCharLength = newValue.length - this.prevContentLength;
var lastChar = newValue.slice(-lastCharLength); // May be a composite emoji
if (checkIsEmoji(lastChar)) {
return;
}
if (newValue.length - textSnapshot.length === 1 || newValue === textSnapshot) {
return;
}
var diff = Date.now() / 1000 - this.typingData.startUnixTime; //* Seconds
var predictedWord = getDifferenceBetweenWords(newValue, textSnapshot);
this.typingData = _extends({}, this.typingData, {
predictionTimes: [].concat(this.typingData.predictionTimes, [Math.trunc(diff * 1000)]),
predictionLengths: [].concat(this.typingData.predictionLengths, [predictedWord.length])
});
}
/**
* Handles the autocorrection trigger.
* @param key - The key that was pressed.
* @param text - The current text in the input.
*/;
_proto.handleAutocorrectionTrigger = function handleAutocorrectionTrigger(key, text) {
if (key !== ' ' && key !== 'Enter') {
return;
}
this.previousText = text;
}
/**
* Processes a keydown event and updates typing data.
* @param keyPressed - The key that was pressed.
* @param target - The target input element.
*/;
_proto.processKeydown = function processKeydown(keyPressed, target) {
var _extends2;
this.performanceStart = performance.now();
var temporalStartUnitTime = Date.now() / 1000; //* Seconds
if (keyPressed === 'Backspace') {
this.backspaceWasPressed = true;
}
if (!this.isTypingSessionActive) {
var timeZone = new Date().getTimezoneOffset() / -60;
this.isTypingSessionActive = true;
this.typingData = _extends({}, this.typingData, {
timeZone: timeZone,
textField: getInputType(target),
keyboardArea: getKeyboardArea(),
startUnixTime: temporalStartUnitTime
});
}
//? Ensure a key press event is not duplicated
if (keyPressed in this.openKeyEntry) {
return;
}
var pressTime = Date.now() / 1000 - this.typingData.startUnixTime; //* Compute relative time in seconds
this.handleAutocorrectionTrigger(keyPressed, target.value);
this.openKeyEntry = _extends({}, this.openKeyEntry, (_extends2 = {}, _extends2[keyPressed] = {
pressTime: Math.trunc(pressTime * 1000000),
keyCode: getKeyCode(keyPressed),
keyArea: getKeyArea(keyPressed),
keyType: getKeyType(keyPressed)
}, _extends2));
}
/**
* Processes a keyup event and updates typing data.
* @param keyPressed - The key that was released.
*/;
_proto.processKeyup = function processKeyup(keyPressed) {
var emojiUnicode;
if (!(keyPressed in this.openKeyEntry)) {
return;
}
var keyEntry = this.openKeyEntry[keyPressed];
//? If is emoji
if (keyEntry.keyCode === 900) {
emojiUnicode = getEmojiUnicode(keyPressed);
}
var releaseTime = Date.now() / 1000 - this.typingData.startUnixTime; //* Compute relative time in Seconds
var performanceEnd = performance.now();
this.typingData = _extends({}, this.typingData, {
pressTimes: [].concat(this.typingData.pressTimes, [keyEntry.pressTime]),
releaseTimes: [].concat(this.typingData.releaseTimes, [Math.trunc(releaseTime * 1000000)]),
keyArea: [].concat(this.typingData.keyArea, [keyEntry.keyArea]),
keyTypes: [].concat(this.typingData.keyTypes, [keyEntry.keyType]),
emojis: [].concat(this.typingData.emojis, emojiUnicode ? [emojiUnicode] : []),
performance: [].concat(this.typingData.performance, [performanceEnd - this.performanceStart])
});
delete this.openKeyEntry[keyPressed];
}
/**
* Ends the current typing session and returns the collected typing data.
* @returns The collected typing data.
*/;
_proto.endTypingSession = function endTypingSession() {
this.isTypingSessionActive = false;
return this.typingData;
}
/**
* Resets the typing data to its initial state.
*/;
_proto.resetTypingData = function resetTypingData() {
this.openKeyEntry = {};
this.typingData = getInitialMobileTypingData();
this.performanceStart = 0;
};
return _createClass(IosKeystrokeManager, [{
key: "getIsTypingSessionActive",
get: function get() {
return this.isTypingSessionActive;
}
/**
* Sets the previous content length.
*/
}, {
key: "setPrevContentLength",
set: function set(value) {
this.prevContentLength = value;
}
}]);
}();
/**
* Manages keystroke data for a typing session.
*/
var KeystrokeManager = /*#__PURE__*/function () {
function KeystrokeManager() {
this.isTypingSessionActive = false;
this.typingData = getInitialTypingData();
this.openKeyEntries = {};
}
/**
* Returns whether a typing session is active.
*/
var _proto = KeystrokeManager.prototype;
/**
* Processes input changes and updates typing data length.
* @param newValue - The new input value.
*/
_proto.processInputChange = function processInputChange(newValue) {
this.typingData = _extends({}, this.typingData, {
length: newValue.length
});
}
/**
* Processes a keydown event and updates typing data.
* @param keyPressed - The key that was pressed.
*/;
_proto.processKeydown = function processKeydown(keyPressed) {
var temporalStartUnixTime = Date.now() / 1000; //* Seconds
if (!this.isTypingSessionActive) {
this.isTypingSessionActive = true;
this.typingData = _extends({}, this.typingData, {
startUnixTime: temporalStartUnixTime
});
}
//? Ensure a key press event is not duplicated
if (keyPressed in this.openKeyEntries) return;
var pressTime = Date.now() / 1000 - this.typingData.startUnixTime; //* Compute relative time in seconds
this.openKeyEntries[keyPressed] = {
pressTime: Math.trunc(pressTime * 1000000),
keyCode: getKeyCode(keyPressed),
keyArea: getKeyArea(keyPressed),
keyType: getKeyType(keyPressed)
};
}
/**
* Processes a keyup event and updates typing data.
* @param keyPressed - The key that was released.
*/;
_proto.processKeyup = function processKeyup(keyPressed) {
if (!(keyPressed in this.openKeyEntries)) return;
var keyEntry = this.openKeyEntries[keyPressed];
var releaseTime = Date.now() / 1000 - this.typingData.startUnixTime; //* Compute relative time in Seconds
this.typingData = _extends({}, this.typingData, {
pressTimes: [].concat(this.typingData.pressTimes, [keyEntry.pressTime]),
releaseTimes: [].concat(this.typingData.releaseTimes, [Math.trunc(releaseTime * 1000000)]),
keyArea: [].concat(this.typingData.keyArea, [keyEntry.keyArea]),
keyTypes: [].concat(this.typingData.keyTypes, [keyEntry.keyType])
});
delete this.openKeyEntries[keyPressed];
}
/**
* Ends the current typing session and returns the collected typing data.
* @returns The collected typing data.
*/;
_proto.endTypingSession = function endTypingSession() {
this.isTypingSessionActive = false;
return this.typingData;
}
/**
* Resets the typing data to its initial state.
*/;
_proto.resetTypingData = function resetTypingData() {
this.typingData = getInitialTypingData();
this.openKeyEntries = {};
};
return _createClass(KeystrokeManager, [{
key: "getIsTypingSessionActive",
get: function get() {
return this.isTypingSessionActive;
}
}]);
}();
export { AndroidKeystrokeManager, IosKeystrokeManager, KeystrokeManager };
//# sourceMappingURL=a2-node-keystroke-package.esm.js.map