{
  "version": 3,
  "sources": ["../../../plugins/keyboard/input.js", "../../../plugins/keyboard/index.js"],
  "sourcesContent": ["/**\r\n * Keyboard Input Command for Pi.js\r\n * \r\n * Provides text input functionality with cursor blinking and validation.\r\n * \r\n * @module plugins/keyboard/input\r\n */\r\n\r\n\"use strict\";\r\n\r\nconst CURSOR_BLINK = 500;\r\n\r\n// Input state\r\nlet m_inputData = null;\r\n\r\n// Store pluginApi reference for use in functions\r\nlet m_pluginApi = null;\r\n\r\n\r\n\r\n/***************************************************************************************************\r\n * Input Command Registration\r\n **************************************************************************************************/\r\n\r\n\r\n/**\r\n * Initialize input command\r\n * \r\n * @param {Object} pluginApi - Plugin API provided by Pi.js\r\n * @returns {void}\r\n */\r\nexport function initInput( pluginApi ) {\r\n\r\n\tm_pluginApi = pluginApi;\r\n\r\n\t// Register screen commands\r\n\tpluginApi.addCommand(\r\n\t\t\"input\", input, true,\r\n\t\t[ \"prompt\", \"fn\", \"cursor\", \"isNumber\", \"isInteger\", \"allowNegative\", \"maxLength\" ]\r\n\t);\r\n\tpluginApi.addCommand( \"cancelInput\", cancelInput, true, [] );\r\n}\r\n\r\n\r\n/***************************************************************************************************\r\n * External API Commands\r\n **************************************************************************************************/\r\n\r\n\r\n/**\r\n * Input command - Get text input from user\r\n * \r\n * @param {Object} screenData - Screen data object\r\n * @param {Object} options - Input options\r\n * @param {string} options.prompt - Prompt text to display\r\n * @param {Function} [options.fn] - Callback function called with result\r\n * @param {string} [options.cursor] - Cursor character (default: block character)\r\n * @param {boolean} [options.isNumber] - If true, only allow numeric input\r\n * @param {boolean} [options.isInteger] - If true, only allow integer input\r\n * @param {boolean} [options.allowNegative] - If true, allow negative numbers\r\n * @param {number} [options.maxLength] - Maximum length of input string\r\n * @returns {Promise} Promise that resolves with input value or rejects on cancel\r\n */\r\nfunction input( screenData, options ) {\r\n\tconst prompt = options.prompt;\r\n\tconst fn = options.fn;\r\n\tconst cursor = options.cursor ? options.cursor : String.fromCharCode( 219 );\r\n\tconst isNumber = !!options.isNumber;\r\n\tconst isInteger = !!options.isInteger;\r\n\tconst allowNegative = !!options.allowNegative;\r\n\tconst maxLength = options.maxLength;\r\n\r\n\tif( typeof prompt !== \"string\" ) {\r\n\t\tconst error = new TypeError( \"input: prompt must be a string\" );\r\n\t\terror.code = \"INVALID_PARAMETERS\";\r\n\t\tthrow error;\r\n\t}\r\n\r\n\tif( fn && typeof fn !== \"function\" ) {\r\n\t\tconst error = new TypeError( \"input: fn must be a function.\" );\r\n\t\terror.code = \"INVALID_PARAMETERS\";\r\n\t\tthrow error;\r\n\t}\r\n\r\n\tif( typeof cursor !== \"string\" ) {\r\n\t\tconst error = new TypeError( \"input: cursor must be a string\" );\r\n\t\terror.code = \"INVALID_PARAMETERS\";\r\n\t\tthrow error;\r\n\t}\r\n\r\n\tif(\r\n\t\tmaxLength !== null &&\r\n\t\t( typeof maxLength !== \"number\" || maxLength < 0 || !Number.isInteger( maxLength ) )\r\n\t) {\r\n\t\tconst error = new TypeError( \"input: maxLength must be a non-negative integer\" );\r\n\t\terror.code = \"INVALID_PARAMETERS\";\r\n\t\tthrow error;\r\n\t}\r\n\r\n\t// Create promise for async/await support\r\n\tlet resolvePromise, rejectPromise;\r\n\tconst promise = new Promise( ( resolve, reject ) => {\r\n\t\tresolvePromise = resolve;\r\n\t\trejectPromise = reject;\r\n\t} );\r\n\r\n\tif( m_inputData ) {\r\n\t\tfinishInput( true );\r\n\t}\r\n\r\n\tm_inputData = {\r\n\t\t\"screenData\": screenData,\r\n\t\t\"prompt\": prompt,\r\n\t\t\"cursor\": cursor,\r\n\t\t\"lastCursorBlink\": Date.now(),\r\n\t\t\"showCursor\": true,\r\n\t\t\"isNumber\": isNumber,\r\n\t\t\"isInteger\": isInteger,\r\n\t\t\"allowNegative\": allowNegative,\r\n\t\t\"maxLength\": maxLength,\r\n\t\t\"val\": \"\",\r\n\t\t\"fn\": fn,\r\n\t\t\"resolve\": resolvePromise,\r\n\t\t\"reject\": rejectPromise,\r\n\t\t\"backgroundImageName\": null,\r\n\t\t\"backgroundImage\": null,\r\n\t\t\"captureX\": null,\r\n\t\t\"captureY\": null\r\n\t};\r\n\r\n\tstartInput();\r\n\r\n\treturn promise;\r\n}\r\n\r\n/**\r\n * Cancel input command - Cancel current input\r\n * \r\n * @param {Object} screenData - Screen data object\r\n * @returns {void}\r\n */\r\nfunction cancelInput( screenData ) {\r\n\tif( m_inputData && m_inputData.screenData === screenData ) {\r\n\t\tfinishInput( true );\r\n\t}\r\n}\r\n\r\n\r\n/***************************************************************************************************\r\n * Internal Helper Functions\r\n **************************************************************************************************/\r\n\r\n\r\nfunction startInput() {\r\n\tconst api = m_pluginApi.getApi();\r\n\r\n\t// Create unique image name for background\r\n\tconst key = `${Date.now()}_${Math.random().toString( 36 ).substring( 2, 9 )}`;\r\n\tm_inputData.backgroundImageName = `__input_bg_${key}`;\r\n\r\n\t// Capture the background image\r\n\tcaptureBackground();\r\n\r\n\t// Add input event listener\r\n\tapi.onkey( \"any\", \"down\", onInputKeyDown, false, true );\r\n\r\n\t// Add interval for blinking cursor\r\n\tm_inputData.interval = setInterval( showPrompt, 100 );\r\n}\r\n\r\nfunction captureBackground() {\r\n\tconst screenData = m_inputData.screenData;\r\n\r\n\t// Check if need to scroll first\r\n\tlet pos = screenData.api.getPos();\r\n\tif( pos.row >= screenData.api.getRows() ) {\r\n\t\tscreenData.api.print( \"\" );\r\n\t\tscreenData.api.setPos( pos.col, pos.row - 1 );\r\n\t}\r\n\t\r\n\t// Get current position to capture background region\r\n\tconst posPx = screenData.api.getPosPx();\r\n\tconst font = screenData.font;\r\n\tconst width = screenData.width;\r\n\tconst height = font.height;\r\n\r\n\t// Capture background region using createImageFromScreen\r\n\t// Capture from the pixel position until the end the screen\r\n\tconst captureWidth = width - posPx.x;\r\n\tconst captureHeight = height;\r\n\t\r\n\tscreenData.api.createImageFromScreen( {\r\n\t\t\"name\": m_inputData.backgroundImageName ,\r\n\t\t\"x1\": posPx.x,\r\n\t\t\"y1\": posPx.y,\r\n\t\t\"x2\": posPx.x + captureWidth - 1,\r\n\t\t\"y2\": posPx.y + captureHeight - 1\r\n\t} );\r\n\tm_inputData.backgroundImage = m_pluginApi.getApi().getImage( m_inputData.backgroundImageName  );\r\n\tm_inputData.captureX = posPx.x;\r\n\tm_inputData.captureY = posPx.y;\r\n\tm_inputData.captureWidth = captureWidth;\r\n\tm_inputData.captureHeight = captureHeight;\r\n}\r\n\r\nfunction onInputKeyDown( keyData ) {\r\n\r\n\t// Handle Enter Key - Complete Input\r\n\tif( keyData.key === \"Enter\" ) {\r\n\t\tfinishInput();\r\n\t\treturn;\r\n\t\r\n\t// Handle Escape - Cancel Input\r\n\t} else if( keyData.key === \"Escape\" ) {\r\n\t\tfinishInput( true );\r\n\t\treturn;\r\n\t\r\n\t// Handle Backspace - Erase last character\r\n\t} else if( keyData.key === \"Backspace\" ) {\r\n\t\tif( m_inputData.val.length > 0 ) {\r\n\t\t\tm_inputData.val = m_inputData.val.substring( 0, m_inputData.val.length - 1 );\r\n\t\t}\r\n\t\r\n\t// Handle single length keys\r\n\t} else if( keyData.key && keyData.key.length === 1 ) {\r\n\r\n\t\tlet inputHandled = false;\r\n\r\n\t\t// Handle +/- numbers\r\n\t\tif( m_inputData.isNumber && m_inputData.allowNegative ) {\r\n\r\n\t\t\t// If user enters a \"-\" then insert \"-\" at the start\r\n\t\t\tif( keyData.key === \"-\" ) {\r\n\t\t\t\tif( m_inputData.val.charAt( 0 ) !== \"-\" ) {\r\n\t\t\t\t\tm_inputData.val = \"-\" + m_inputData.val;\r\n\t\t\t\t}\r\n\t\t\t\tinputHandled = true;\r\n\t\t\t\r\n\t\t\t// Any time the user enters a \"+\" key then replace the minus symbol\r\n\t\t\t} else if(\r\n\t\t\t\t( keyData.key === \"+\" || keyData.code === \"Equal\" ) &&\r\n\t\t\t\tm_inputData.val.charAt( 0 ) === \"-\"\r\n\t\t\t) {\r\n\t\t\t\tm_inputData.val = m_inputData.val.substring( 1 );\r\n\t\t\t\tinputHandled = true;\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\t// Don't allow decimal points for integer number\r\n\t\tif( m_inputData.isInteger && keyData.code === \"Period\" ) {\r\n\t\t\tinputHandled = true;\r\n\t\t}\r\n\r\n\t\t// If the input is valid append the next character and validate\r\n\t\tif( !inputHandled ) {\r\n\t\t\t\r\n\t\t\t// Check maxLength before appending\r\n\t\t\tif(\r\n\t\t\t\tm_inputData.maxLength !== null && m_inputData.val.length >= m_inputData.maxLength\r\n\t\t\t) {\r\n\t\t\t\tinputHandled = true;\r\n\t\t\t} else {\r\n\t\t\t\tm_inputData.val += keyData.key;\r\n\r\n\t\t\t\t// Make sure it's a valid number or valid integer\r\n\t\t\t\tif(\r\n\t\t\t\t\t( m_inputData.isNumber && isNaN( Number( m_inputData.val ) ) ) ||\r\n\t\t\t\t\t( m_inputData.isInteger && !Number.isInteger( Number( m_inputData.val ) ) )\r\n\t\t\t\t) {\r\n\t\t\t\t\tm_inputData.val = m_inputData.val.substring( 0, m_inputData.val.length - 1 );\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\tshowPrompt();\r\n}\r\n\r\nfunction showPrompt( hideCursorOverride ) {\r\n\tconst screenData = m_inputData.screenData;\r\n\tlet msg = m_inputData.prompt + m_inputData.val;\r\n\r\n\t// Blink cursor after every blink duration\r\n\tif( !hideCursorOverride ) {\r\n\t\tconst now = Date.now();\r\n\t\tif( now - m_inputData.lastCursorBlink > CURSOR_BLINK ) {\r\n\t\t\tm_inputData.lastCursorBlink = now;\r\n\t\t\tm_inputData.showCursor = !m_inputData.showCursor;\r\n\t\t}\r\n\r\n\t\t// Show cursor if not hidden\r\n\t\tif( m_inputData.showCursor ) {\r\n\t\t\tmsg += m_inputData.cursor;\r\n\t\t}\r\n\t}\r\n\r\n\t// Restore the background image over the prompt area\r\n\tscreenData.api.blitImage( \r\n\t\tm_inputData.backgroundImage,\r\n\t\tm_inputData.captureX,\r\n\t\tm_inputData.captureY\r\n\t);\r\n\t\r\n\t// Get cursor position\r\n\tconst posPx = $.getPosPx();\r\n\r\n\t// Print the prompt + input + cursor\r\n\t$.setPosPx( m_inputData.captureX, m_inputData.captureY );\r\n\tscreenData.api.print( msg, true );\r\n\r\n\t// Restore the cursor\r\n\tscreenData.api.setPosPx( posPx );\r\n}\r\n\r\nfunction finishInput( isCancel ) {\r\n\tconst screenData = m_inputData.screenData;\r\n\tconst api = m_pluginApi.getApi();\r\n\r\n\t// Remove input key handler\r\n\tapi.offkey( \"any\", \"down\", onInputKeyDown, false, true );\r\n\r\n\t// Show prompt on complete, without the cursor\r\n\tshowPrompt( true );\r\n\r\n\t// Move cursor down one line\r\n\tscreenData.printCursor.y += screenData.font.height;\r\n\r\n\t// Clear the interval\r\n\tclearInterval( m_inputData.interval );\r\n\r\n\t// Process Input Value\r\n\tlet val = m_inputData.val;\r\n\tif( m_inputData.isNumber ) {\r\n\t\tif( val === \"\" || val === \"-\" ) {\r\n\t\t\tval = 0;\r\n\t\t} else {\r\n\t\t\tval = Number( val );\r\n\t\t\tif( m_inputData.isInteger ) {\r\n\t\t\t\tval = Math.floor( val );\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\t// Clean up background image texture\r\n\tapi.removeImage( m_inputData.backgroundImageName );\r\n\t\r\n\t// Clear out the inputData\r\n\tconst tempInputData = m_inputData;\r\n\tm_inputData = null;\r\n\r\n\t// Handle cancel input\r\n\tif( isCancel ) {\r\n\t\ttempInputData.resolve( null );\r\n\r\n\t\t// Callback function\r\n\t\tif( tempInputData.fn ) {\r\n\t\t\ttempInputData.fn( null );\r\n\t\t}\r\n\t\r\n\t// Handle successful input\r\n\t} else {\r\n\t\ttempInputData.resolve( val );\r\n\r\n\t\t// Callback function\r\n\t\tif( tempInputData.fn ) {\r\n\t\t\ttempInputData.fn( val );\r\n\t\t}\r\n\t}\r\n}\r\n\r\n/**\r\n * Cancel all active input prompts\r\n * Called by clearKeyboardEvents\r\n * \r\n * @param {Object} [screenData] - Optional screen data to cancel input for specific screen only\r\n * @returns {void}\r\n */\r\nexport function cancelAllInputs( screenData ) {\r\n\tif( m_inputData ) {\r\n\t\tif( screenData === null || screenData === undefined ) {\r\n\r\n\t\t\t// Cancel all inputs (there can only be one active at a time)\r\n\t\t\tfinishInput( true );\r\n\t\t} else if( m_inputData.screenData === screenData ) {\r\n\r\n\t\t\t// Cancel input for specific screen\r\n\t\t\tfinishInput( true );\r\n\t\t}\r\n\t}\r\n}\r\n", "/**\n * Keyboard Plugin for Pi.js\n * \n * Provides keyboard input handling including key state tracking, event handlers,\n * and action key management.\n * \n * @module plugins/keyboard\n * @version 1.0.0\n */\n\n\"use strict\";\n\nimport { initInput, cancelAllInputs } from \"./input.js\";\n\n// Input tags that we don't want to capture\nconst INPUT_TAGS = new Set( [ \"INPUT\", \"TEXTAREA\", \"SELECT\", \"BUTTON\" ] );\n\n// Key information containers\nconst m_inCodes = {};\nconst m_inKeys = {};\nconst m_actionKeys = new Set();\nconst m_onKeyHandlers = {};\n\n// Status variables\nlet m_isKeyboardActive = false;\n\n\n/***************************************************************************************************\n * Plugin Initialization\n **************************************************************************************************/\n\n\nexport default function keyboardPlugin( pluginApi ) {\n\n\t// Initialize keyboard on plugin load\n\tstartKeyboard();\n\twindow.addEventListener( \"blur\", clearInKeys );\n\n\t// Add screen cleanup function to clear keyboard events when screen is removed\n\tpluginApi.addScreenCleanupFunction( () => {\n\t\t// Keyboard events are global, so we don't need screen-specific cleanup\n\t\t// But we can use this hook if needed in the future\n\t} );\n\n\t// Register global commands\n\tpluginApi.addCommand( \"startKeyboard\", startKeyboard, false, [] );\n\tpluginApi.addCommand( \"stopKeyboard\", stopKeyboard, false, [] );\n\tpluginApi.addCommand( \"inkey\", inkey, false, [ \"key\" ] );\n\tpluginApi.addCommand( \"setActionKeys\", setActionKeys, false, [ \"keys\" ] );\n\tpluginApi.addCommand( \"removeActionKeys\", removeActionKeys, false, [ \"keys\" ] );\n\tpluginApi.addCommand( \"onkey\", onkey, false, [ \"key\", \"mode\", \"fn\", \"once\", \"allowRepeat\" ] );\n\tpluginApi.addCommand( \"offkey\", offkey, false, [ \"key\", \"mode\", \"fn\", \"once\", \"allowRepeat\" ] );\n\n\t// Initialize input command\n\tinitInput( pluginApi );\n\n\t// Register clearEvents handler\n\tpluginApi.registerClearEvents( \"keyboard\", clearKeyboardEvents );\n}\n\n\n/***************************************************************************************************\n * External API Commands\n **************************************************************************************************/\n\n\nfunction startKeyboard() {\n\tif( m_isKeyboardActive ) {\n\t\treturn;\n\t}\n\twindow.addEventListener( \"keydown\", onKeyDown, { \"capture\": true } );\n\twindow.addEventListener( \"keyup\", onKeyUp, { \"capture\": true } );\n\tm_isKeyboardActive = true;\n\tif( document.activeElement ) {\n\t\tdocument.activeElement.blur();\n\t}\n}\n\nfunction stopKeyboard() {\n\tif( !m_isKeyboardActive ) {\n\t\treturn;\n\t}\n\twindow.removeEventListener( \"keydown\", onKeyDown, { \"capture\": true } );\n\twindow.removeEventListener( \"keyup\", onKeyUp, { \"capture\": true } );\n\tm_isKeyboardActive = false;\n\n\t// Clear keys to prevent any after effects\n\tclearInKeys();\n}\n\nfunction inkey( options ) {\n\tconst key = options.key;\n\n\tif( key ) {\n\n\t\tif( typeof key !== \"string\" ) {\n\t\t\tconst error = new TypeError( \"inkey: key must be a string.\" );\n\t\t\terror.code = \"INVALID_PARAMETERS\";\n\t\t\tthrow error;\n\t\t}\n\n\t\t// Get key by code property\n\t\tif( m_inCodes[ key ] ) {\n\t\t\treturn m_inCodes[ key ];\n\t\t}\n\n\t\t// Get key by key property\n\t\tif( m_inKeys[ key ] ) {\n\t\t\treturn m_inKeys[ key ];\n\t\t}\n\n\t\treturn null;\n\t}\n\n\t// If inkey is blank return all key codes\n\tconst keyCodes = [];\n\tfor( const code in m_inCodes ) {\n\t\tif( m_inCodes[ code ] ) {\n\t\t\tkeyCodes.push( m_inCodes[ code ] );\n\t\t}\n\t}\n\n\treturn keyCodes;\n}\n\nfunction setActionKeys( options ) {\n\tconst keys = options.keys;\n\n\tif( !Array.isArray( keys ) ) {\n\t\tconst error = new TypeError( \"setActionKeys: keys must be an array.\" );\n\t\terror.code = \"INVALID_PARAMETERS\";\n\t\tthrow error;\n\t}\n\tfor( const key of keys ) {\n\t\tm_actionKeys.add( key );\n\t}\n}\n\nfunction removeActionKeys( options ) {\n\tconst keys = options.keys;\n\n\tif( !Array.isArray( keys ) ) {\n\t\tconst error = new TypeError( \"removeActionKeys: keys must be an array.\" );\n\t\terror.code = \"INVALID_PARAMETERS\";\n\t\tthrow error;\n\t}\n\tfor( const key of keys ) {\n\t\tm_actionKeys.delete( key );\n\t}\n}\n\nfunction onkey( options ) {\n\tconst key = options.key;\n\tconst mode = options.mode;\n\tconst fn = options.fn;\n\tconst once = !!options.once;\n\tconst allowRepeat = !!options.allowRepeat;\n\t\n\tif( !key || ( typeof key !== \"string\" && !Array.isArray( key ) ) ) {\n\t\tconst error = new TypeError( \"onkey: key must be a string or an array of strings.\" );\n\t\terror.code = \"INVALID_PARAMETERS\";\n\t\tthrow error;\n\t}\n\n\tif( !mode || ( typeof mode !== \"string\" ) ) {\n\t\tconst error = new TypeError( \"onkey: mode must be a string with value of up or down.\" );\n\t\terror.code = \"INVALID_PARAMETERS\";\n\t\tthrow error;\n\t}\n\n\tif( typeof fn !== \"function\" ) {\n\t\tconst error = new TypeError( \"onkey: fn must be a function.\" );\n\t\terror.code = \"INVALID_PARAMETERS\";\n\t\tthrow error;\n\t}\n\n\t// Normalize key into an array for easier processing\n\tconst combo = typeof key === \"string\" ? [ key ] : key;\n\n\tconst handler = {\n\t\t\"comboKey\": combo.sort().join( \"\" ),\n\t\t\"combo\": combo,\n\t\t\"mode\": mode,\n\t\t\"fn\": fn,\n\t\t\"once\": once,\n\t\t\"allowRepeat\": allowRepeat,\n\t\t\"isRemoved\": false\n\t};\n\t\n\t// Add a on key handler for each of the key codes - in combo all must be pressed\n\tfor( const key of combo ) {\n\t\tif( !m_onKeyHandlers[ key ] ) {\n\t\t\tm_onKeyHandlers[ key ] = [];\n\t\t}\n\t\tm_onKeyHandlers[ key ].push( handler );\n\t}\n}\n\nfunction offkey( options ) {\n\tconst key = options.key;\n\tconst mode = options.mode;\n\tconst fn = options.fn;\n\tconst once = !!options.once;\n\tconst allowRepeat = !!options.allowRepeat;\n\n\tif( !key || ( typeof key !== \"string\" && !Array.isArray( key ) ) ) {\n\t\tconst error = new TypeError( \"offkey: key must be a string or an array of strings.\" );\n\t\terror.code = \"INVALID_PARAMETERS\";\n\t\tthrow error;\n\t}\n\n\tif( typeof fn !== \"function\" ) {\n\t\tconst error = new TypeError( \"offkey: callback must be a function.\" );\n\t\terror.code = \"INVALID_PARAMETERS\";\n\t\tthrow error;\n\t}\n\n\t// Normalize key into an array for easier processing\n\tconst combo = typeof key === \"string\" ? [ key ] : key;\n\tconst comboKey = combo.sort().join( \"\" );\n\n\t// Find the handlers and remove them\n\tfor( const key of combo ) {\n\t\tconst handlers = m_onKeyHandlers[ key ];\n\t\tif( !handlers ) {\n\t\t\tcontinue;\n\t\t}\n\t\tconst toRemove = [];\n\t\tfor( let i = 0; i < handlers.length; i += 1 ) {\n\t\t\tconst handler = handlers[ i ];\n\t\t\tif(\n\t\t\t\thandler.comboKey === comboKey &&\n\t\t\t\thandler.mode === mode &&\n\t\t\t\thandler.fn === fn &&\n\t\t\t\thandler.once === once &&\n\t\t\t\thandler.allowRepeat === allowRepeat\n\t\t\t) {\n\t\t\t\ttoRemove.push( i );\n\t\t\t\thandler.isRemoved = true;\n\t\t\t}\n\t\t}\n\t\tfor( let i = toRemove.length - 1; i >= 0; i -= 1 ) {\n\t\t\thandlers.splice( toRemove[ i ], 1 );\n\t\t}\n\t\tif( handlers.length === 0 ) {\n\t\t\tdelete m_onKeyHandlers[ key ];\n\t\t}\n\t}\n}\n\n\n/***************************************************************************************************\n * Internal Helper Functions\n **************************************************************************************************/\n\n\nfunction onKeyDown( event ) {\n\n\t// Ignore typing when focus is inside an editable\n\tif( isFromEditableTarget( event ) ) {\n\t\tclearInKeys();\n\t\treturn;\n\t}\n\tconst keyData = {\n\t\t\"code\": event.code,\n\t\t\"key\": event.key,\n\t\t\"location\": event.location,\n\t\t\"altKey\": event.altKey,\n\t\t\"ctrlKey\": event.ctrlKey,\n\t\t\"metaKey\": event.metaKey,\n\t\t\"shiftKey\": event.shiftKey,\n\t\t\"repeat\": event.repeat\n\t};\n\tm_inCodes[ event.code ] = keyData;\n\tm_inKeys[ event.key ] = keyData;\n\n\ttriggerKeyEventHandlers( event, \"down\", event.code );\n\tif( event.code !== event.key ) {\n\t\ttriggerKeyEventHandlers( event, \"down\", event.key );\n\t}\n\ttriggerKeyEventHandlers( event, \"down\", \"any\" );\n\tif( m_actionKeys.has( event.code ) || m_actionKeys.has( event.key ) ) {\n\t\tevent.preventDefault();\n\t}\n}\n\nfunction onKeyUp( event ) {\n\t\n\t// Ignore typing when focus is inside an editable\n\tif( isFromEditableTarget( event ) ) {\n\t\tclearInKeys();\n\t\treturn;\n\t}\n\ttriggerKeyEventHandlers( event, \"up\", event.code );\n\n\tif( event.code !== event.key ) {\n\t\ttriggerKeyEventHandlers( event, \"up\", event.key );\n\t}\n\ttriggerKeyEventHandlers( event, \"up\", \"any\" );\n\n\tdelete m_inCodes[ event.code ];\n\tdelete m_inKeys[ event.key ];\n\n\tif( m_actionKeys.has( event.code ) || m_actionKeys.has( event.key ) ) {\n\t\tevent.preventDefault();\n\t}\n}\n\nfunction triggerKeyEventHandlers( event, mode, keyOrCode ) {\n\tconst handlers = m_onKeyHandlers[ keyOrCode ];\n\tif( !handlers ) {\n\t\treturn;\n\t}\n\n\tconst isAnyKey = keyOrCode === \"any\";\n\tconst handlersCopy = handlers.slice();\n\tconst toRemove = new Set();\n\n\tfor( let i = 0; i < handlersCopy.length; i += 1 ) {\n\t\tconst handler = handlersCopy[ i ];\n\n\t\tif( handler.mode !== mode ) {\n\t\t\tcontinue;\n\t\t}\n\n\t\tif( event.repeat && !handler.allowRepeat ) {\n\t\t\tcontinue;\n\t\t}\n\n\t\t// Need to check if handler has been removed in case a previous handler includes an offkey\n\t\tif( handler.isRemoved ) {\n\t\t\tcontinue;\n\t\t}\n\n\t\t// For \"any\" key handlers, pass the current key data\n\t\tif( isAnyKey ) {\n\t\t\tlet keyData = m_inCodes[ event.code ];\n\t\t\tif( !keyData ) {\n\t\t\t\tkeyData = m_inKeys[ event.key ];\n\t\t\t}\n\n\t\t\t// In case stopKeyboard gets called in another key event handler keyData will be blank\n\t\t\tif( keyData !== undefined ) {\n\t\t\t\thandler.fn( keyData );\n\t\t\t}\n\n\t\t\tif( handler.once ) {\n\t\t\t\ttoRemove.add( handler );\n\t\t\t\thandler.isRemoved = true;\n\t\t\t}\n\t\t\tcontinue;\n\t\t}\n\n\t\t// For specific key handlers, check combo and pass combo data\n\t\tconst isAllKeysPressed = handler.combo.every( key => m_inKeys[ key ] || m_inCodes[ key ] );\n\n\t\tif( isAllKeysPressed ) {\n\t\t\tconst comboData = handler.combo.map( key => {\n\t\t\t\tif( m_inKeys[ key ] ) {\n\t\t\t\t\treturn m_inKeys[ key ];\n\t\t\t\t}\n\t\t\t\treturn m_inCodes[ key ];\n\t\t\t} );\n\n\t\t\tif( comboData.length === 1 ) {\n\t\t\t\thandler.fn( comboData[ 0 ] );\n\t\t\t} else {\n\t\t\t\thandler.fn( comboData );\n\t\t\t}\n\n\t\t\tif( handler.once ) {\n\t\t\t\ttoRemove.add( handler );\n\t\t\t\thandler.isRemoved = true;\n\t\t\t}\n\t\t}\n\t}\n\n\t// Remove the handlers that are one time only calls\n\tif( toRemove.size > 0 ) {\n\t\tm_onKeyHandlers[ keyOrCode ] = handlers.filter( h => !toRemove.has( h ) );\n\t\t\n\t\t// Delete the array if empty\n\t\tif( m_onKeyHandlers[ keyOrCode ].length === 0 ) {\n\t\t\tdelete m_onKeyHandlers[ keyOrCode ];\n\t\t}\n\t}\n}\n\nfunction isFromEditableTarget ( event ) {\n\tconst element = event.target;\n\tif( !element ) {\n\t\treturn false;\n\t}\n\n\t// Standard form controls\n\tif( INPUT_TAGS.has( element.tagName ) ) {\n\t\treturn true;\n\t}\n\n\t// Contenteditable\n\tif( element.isContentEditable ) {\n\t\treturn true;\n\t}\n\n\t// Inputs inside shadow roots\n\tconst role = element.getAttribute && element.getAttribute( \"role\" );\n\tif( role === \"textbox\" || role === \"searchbox\" ) {\n\t\treturn true;\n\t}\n\n\treturn false;\n}\n\nfunction clearInKeys() {\n\n\t// Clear all key states\n\tfor( const code in m_inCodes ) {\n\t\tdelete m_inCodes[ code ];\n\t}\n\tfor( const key in m_inKeys ) {\n\t\tdelete m_inKeys[ key ];\n\t}\n}\n\n\n/***************************************************************************************************\n * Module Exports for Other Modules\n **************************************************************************************************/\n\n\n/**\n * Clear all keyboard event handlers\n * Called by clearEvents command and exported for use by other modules\n * \n * @param {Object} [screenData] - Screen data to clear events for specific screen\n * @returns {void}\n */\nexport function clearKeyboardEvents( screenData ) {\n\t\n\t// Clear all keyboard event handlers\n\tfor( const mode in m_onKeyHandlers ) {\n\t\tdelete m_onKeyHandlers[ mode ];\n\t}\n\t\n\t// Cancel all active input prompts\n\tcancelAllInputs( screenData );\n}\n\n\n// Auto-register in IIFE mode (when loaded via <script> tag)\nif( typeof window !== \"undefined\" && window.pi ) {\n\twindow.pi.registerPlugin( {\n\t\t\"name\": \"keyboard\",\n\t\t\"version\": \"1.0.0\",\n\t\t\"description\": \"Keyboard input handling for Pi.js\",\n\t\t\"init\": keyboardPlugin\n\t} );\n}\n\n"],
  "mappings": "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",
  "names": ["key"]
}
