{"version":3,"names":["handleInputKey","key","state","options","multiline","value","cursorPos","result","changed","submit","name","eventType","Math","max","min","length","ctrl","lineStart","lastIndexOf","lineEnd","indexOf","moveCursorVertically","slice","end","before","trimmed","replace","meta","shift","sequence","char","startsWith","test","delta","lines","split","charCount","currentLine","currentCol","i","lineLen","targetLine","targetLineLen","targetCol","newPos"],"sources":["input-handler.ts"],"sourcesContent":["/**\n * Input element key handler — manages text editing operations for <input>.\n *\n * Given a key event and the current input state (value + cursor position),\n * produces the next state. The screen wires this into the key dispatch loop\n * for any focused <input> node.\n */\nimport type { ParsedKey } from \"./parse-keypress.ts\";\n\nexport interface InputState {\n\tcursorPos: number;\n\tvalue: string;\n}\n\nexport interface InputResult {\n\t/** Whether onChange should be called (value changed) */\n\tchanged: boolean;\n\t/** New cursor position */\n\tcursorPos: number;\n\t/** Whether onSubmit should be called (Enter without shift in single-line, or ctrl+enter) */\n\tsubmit: boolean;\n\t/** New value after the key operation */\n\tvalue: string;\n}\n\n/**\n * Process a key event against input state, returning the next state.\n * Pure function — no side effects.\n */\nexport function handleInputKey(\n\tkey: ParsedKey,\n\tstate: InputState,\n\toptions?: { multiline?: boolean },\n): InputResult {\n\tconst multiline = options?.multiline ?? false;\n\tconst { value, cursorPos } = state;\n\tconst result: InputResult = {\n\t\tvalue,\n\t\tcursorPos,\n\t\tchanged: false,\n\t\tsubmit: false,\n\t};\n\n\t// Modifier-only keys (shift, ctrl, etc.) — ignore\n\tif (\n\t\tkey.name === \"leftshift\" ||\n\t\tkey.name === \"rightshift\" ||\n\t\tkey.name === \"leftctrl\" ||\n\t\tkey.name === \"rightctrl\" ||\n\t\tkey.name === \"leftalt\" ||\n\t\tkey.name === \"rightalt\" ||\n\t\tkey.name === \"leftsuper\" ||\n\t\tkey.name === \"rightsuper\" ||\n\t\tkey.name === \"capslock\" ||\n\t\tkey.name === \"numlock\"\n\t) {\n\t\treturn result;\n\t}\n\n\t// Release events — ignore\n\tif (key.eventType === \"release\") return result;\n\n\t// Navigation\n\tif (key.name === \"left\") {\n\t\tresult.cursorPos = Math.max(0, cursorPos - 1);\n\t\treturn result;\n\t}\n\tif (key.name === \"right\") {\n\t\tresult.cursorPos = Math.min(value.length, cursorPos + 1);\n\t\treturn result;\n\t}\n\tif (key.name === \"home\" || (key.ctrl && key.name === \"a\")) {\n\t\t// Move to start of current line\n\t\tconst lineStart = value.lastIndexOf(\"\\n\", cursorPos - 1) + 1;\n\t\tresult.cursorPos = lineStart;\n\t\treturn result;\n\t}\n\tif (key.name === \"end\" || (key.ctrl && key.name === \"e\")) {\n\t\t// Move to end of current line\n\t\tconst lineEnd = value.indexOf(\"\\n\", cursorPos);\n\t\tresult.cursorPos = lineEnd === -1 ? value.length : lineEnd;\n\t\treturn result;\n\t}\n\tif (key.name === \"up\") {\n\t\tresult.cursorPos = moveCursorVertically(value, cursorPos, -1);\n\t\treturn result;\n\t}\n\tif (key.name === \"down\") {\n\t\tresult.cursorPos = moveCursorVertically(value, cursorPos, 1);\n\t\treturn result;\n\t}\n\n\t// Deletion\n\tif (key.name === \"backspace\") {\n\t\tif (cursorPos > 0) {\n\t\t\tresult.value = value.slice(0, cursorPos - 1) + value.slice(cursorPos);\n\t\t\tresult.cursorPos = cursorPos - 1;\n\t\t\tresult.changed = true;\n\t\t}\n\t\treturn result;\n\t}\n\tif (key.name === \"delete\") {\n\t\tif (cursorPos < value.length) {\n\t\t\tresult.value = value.slice(0, cursorPos) + value.slice(cursorPos + 1);\n\t\t\tresult.changed = true;\n\t\t}\n\t\treturn result;\n\t}\n\n\t// Kill line (ctrl+k) — delete from cursor to end of line\n\tif (key.ctrl && key.name === \"k\") {\n\t\tconst lineEnd = value.indexOf(\"\\n\", cursorPos);\n\t\tconst end = lineEnd === -1 ? value.length : lineEnd;\n\t\tif (cursorPos < end) {\n\t\t\tresult.value = value.slice(0, cursorPos) + value.slice(end);\n\t\t\tresult.changed = true;\n\t\t}\n\t\treturn result;\n\t}\n\n\t// Kill word backward (ctrl+w / ctrl+backspace)\n\tif (key.ctrl && (key.name === \"w\" || key.name === \"backspace\")) {\n\t\tif (cursorPos > 0) {\n\t\t\tconst before = value.slice(0, cursorPos);\n\t\t\tconst trimmed = before.replace(/\\S+\\s*$|^\\s+$/, \"\");\n\t\t\tresult.value = trimmed + value.slice(cursorPos);\n\t\t\tresult.cursorPos = trimmed.length;\n\t\t\tresult.changed = true;\n\t\t}\n\t\treturn result;\n\t}\n\n\t// Submit / newline — behavior depends on multiline prop\n\tif (key.name === \"return\" || key.name === \"linefeed\") {\n\t\tif (multiline) {\n\t\t\t// Multiline: Enter inserts newline, Ctrl+Enter submits\n\t\t\tif (key.ctrl || key.meta) {\n\t\t\t\tresult.submit = true;\n\t\t\t\treturn result;\n\t\t\t}\n\t\t\tresult.value = `${value.slice(0, cursorPos)}\\n${value.slice(cursorPos)}`;\n\t\t\tresult.cursorPos = cursorPos + 1;\n\t\t\tresult.changed = true;\n\t\t\treturn result;\n\t\t}\n\t\t// Single-line: Enter submits\n\t\tresult.submit = true;\n\t\treturn result;\n\t}\n\n\t// Tab — insert tab (or could be handled by focus system later)\n\tif (key.name === \"tab\" && !key.shift) {\n\t\tresult.value = `${value.slice(0, cursorPos)}\\t${value.slice(cursorPos)}`;\n\t\tresult.cursorPos = cursorPos + 1;\n\t\tresult.changed = true;\n\t\treturn result;\n\t}\n\n\t// Ignore other control sequences\n\tif (key.ctrl || key.meta) return result;\n\n\t// Printable character insertion\n\tif (key.sequence && key.sequence.length > 0 && !key.ctrl && !key.meta) {\n\t\tconst char = key.sequence;\n\t\t// Filter out non-printable sequences (escape, function keys, etc.)\n\t\tif (\n\t\t\tkey.name === \"escape\" ||\n\t\t\tkey.name === \"tab\" ||\n\t\t\tkey.name === \"space\" ||\n\t\t\t(key.name.startsWith(\"f\") &&\n\t\t\t\tkey.name.length <= 3 &&\n\t\t\t\t/^f\\d+$/.test(key.name))\n\t\t) {\n\t\t\tif (key.name === \"space\") {\n\t\t\t\tresult.value = `${value.slice(0, cursorPos)} ${value.slice(cursorPos)}`;\n\t\t\t\tresult.cursorPos = cursorPos + 1;\n\t\t\t\tresult.changed = true;\n\t\t\t}\n\t\t\treturn result;\n\t\t}\n\n\t\tresult.value = value.slice(0, cursorPos) + char + value.slice(cursorPos);\n\t\tresult.cursorPos = cursorPos + char.length;\n\t\tresult.changed = true;\n\t\treturn result;\n\t}\n\n\treturn result;\n}\n\n/**\n * Move cursor up or down by `delta` lines within a multi-line string.\n * Tries to maintain the column position.\n */\nfunction moveCursorVertically(\n\tvalue: string,\n\tcursorPos: number,\n\tdelta: number,\n): number {\n\tconst lines = value.split(\"\\n\");\n\n\t// Find which line and column the cursor is on\n\tlet charCount = 0;\n\tlet currentLine = 0;\n\tlet currentCol = 0;\n\n\tfor (let i = 0; i < lines.length; i++) {\n\t\tconst lineLen = (lines[i] ?? \"\").length;\n\t\tif (cursorPos <= charCount + lineLen) {\n\t\t\tcurrentLine = i;\n\t\t\tcurrentCol = cursorPos - charCount;\n\t\t\tbreak;\n\t\t}\n\t\tcharCount += lineLen + 1; // +1 for \\n\n\t}\n\n\tconst targetLine = Math.max(\n\t\t0,\n\t\tMath.min(lines.length - 1, currentLine + delta),\n\t);\n\tif (targetLine === currentLine) return cursorPos;\n\n\t// Calculate new cursor position maintaining column\n\tconst targetLineLen = (lines[targetLine] ?? \"\").length;\n\tconst targetCol = Math.min(currentCol, targetLineLen);\n\n\tlet newPos = 0;\n\tfor (let i = 0; i < targetLine; i++) {\n\t\tnewPos += (lines[i] ?? \"\").length + 1;\n\t}\n\treturn newPos + targetCol;\n}\n"],"mappings":"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","ignoreList":[]}