tftsr-devops_investigation/node_modules/@testing-library/user-event/dist/cjs/event/input.js
Shaun Arman 8839075805 feat: initial implementation of TFTSR IT Triage & RCA application
Implements Phases 1-8 of the TFTSR implementation plan.

Rust backend (Tauri 2.x, src-tauri/):
- Multi-provider AI: OpenAI-compatible, Anthropic, Gemini, Mistral, Ollama
- PII detection engine: 11 regex patterns with overlap resolution
- SQLCipher AES-256 encrypted database with 10 versioned migrations
- 28 Tauri IPC commands for triage, analysis, document, and system ops
- Ollama: hardware probe, model recommendations, pull/delete with events
- RCA and blameless post-mortem Markdown document generators
- PDF export via printpdf
- Audit log: SHA-256 hash of every external data send
- Integration stubs for Confluence, ServiceNow, Azure DevOps (v0.2)

Frontend (React 18 + TypeScript + Vite, src/):
- 9 pages: full triage workflow NewIssue→LogUpload→Triage→Resolution→RCA→Postmortem→History+Settings
- 7 components: ChatWindow, TriageProgress, PiiDiffViewer, DocEditor, HardwareReport, ModelSelector, UI primitives
- 3 Zustand stores: session, settings (persisted), history
- Type-safe tauriCommands.ts matching Rust backend types exactly
- 8 IT domain system prompts (Linux, Windows, Network, K8s, DB, Virt, HW, Obs)

DevOps:
- .woodpecker/test.yml: rustfmt, clippy, cargo test, tsc, vitest on every push
- .woodpecker/release.yml: linux/amd64 + linux/arm64 builds, Gogs release upload

Verified:
- cargo check: zero errors
- tsc --noEmit: zero errors
- vitest run: 13/13 unit tests passing

Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
2026-03-14 22:36:25 -05:00

158 lines
6.2 KiB
JavaScript

'use strict';
var UI = require('../document/UI.js');
var isElementType = require('../utils/misc/isElementType.js');
require('../utils/dataTransfer/Clipboard.js');
var timeValue = require('../utils/edit/timeValue.js');
var maxLength = require('../utils/edit/maxLength.js');
var cursor = require('../utils/focus/cursor.js');
var trackValue = require('../document/trackValue.js');
var getInputRange = require('./selection/getInputRange.js');
var setSelection = require('./selection/setSelection.js');
function isDateOrTime(element) {
return isElementType.isElementType(element, 'input') && [
'date',
'time'
].includes(element.type);
}
function input(instance, element, data, inputType = 'insertText') {
const inputRange = getInputRange.getInputRange(element);
/* istanbul ignore if */ if (!inputRange) {
return;
}
// There is no `beforeinput` event on `date` and `time` input
if (!isDateOrTime(element)) {
const unprevented = instance.dispatchUIEvent(element, 'beforeinput', {
inputType,
data
});
if (!unprevented) {
return;
}
}
if ('startContainer' in inputRange) {
editContenteditable(instance, element, inputRange, data, inputType);
} else {
editInputElement(instance, element, inputRange, data, inputType);
}
}
function editContenteditable(instance, element, inputRange, data, inputType) {
let del = false;
if (!inputRange.collapsed) {
del = true;
inputRange.deleteContents();
} else if ([
'deleteContentBackward',
'deleteContentForward'
].includes(inputType)) {
const nextPosition = cursor.getNextCursorPosition(inputRange.startContainer, inputRange.startOffset, inputType === 'deleteContentBackward' ? -1 : 1, inputType);
if (nextPosition) {
del = true;
const delRange = inputRange.cloneRange();
if (delRange.comparePoint(nextPosition.node, nextPosition.offset) < 0) {
delRange.setStart(nextPosition.node, nextPosition.offset);
} else {
delRange.setEnd(nextPosition.node, nextPosition.offset);
}
delRange.deleteContents();
}
}
if (data) {
if (inputRange.endContainer.nodeType === 3) {
const offset = inputRange.endOffset;
inputRange.endContainer.insertData(offset, data);
inputRange.setStart(inputRange.endContainer, offset + data.length);
inputRange.setEnd(inputRange.endContainer, offset + data.length);
} else {
const text = element.ownerDocument.createTextNode(data);
inputRange.insertNode(text);
inputRange.setStart(text, data.length);
inputRange.setEnd(text, data.length);
}
}
if (del || data) {
instance.dispatchUIEvent(element, 'input', {
inputType
});
}
}
function editInputElement(instance, element, inputRange, data, inputType) {
let dataToInsert = data;
if (maxLength.supportsMaxLength(element)) {
const maxLength$1 = maxLength.getMaxLength(element);
if (maxLength$1 !== undefined && data.length > 0) {
const spaceUntilMaxLength = maxLength$1 - element.value.length;
if (spaceUntilMaxLength > 0) {
dataToInsert = data.substring(0, spaceUntilMaxLength);
} else {
return;
}
}
}
const { newValue, newOffset, oldValue } = calculateNewValue(dataToInsert, element, inputRange, inputType);
if (newValue === oldValue && newOffset === inputRange.startOffset && newOffset === inputRange.endOffset) {
return;
}
if (isElementType.isElementType(element, 'input', {
type: 'number'
}) && !isValidNumberInput(newValue)) {
return;
}
UI.setUIValue(element, newValue);
setSelection.setSelection({
focusNode: element,
anchorOffset: newOffset,
focusOffset: newOffset
});
if (isDateOrTime(element)) {
if (timeValue.isValidDateOrTimeValue(element, newValue)) {
commitInput(instance, element, newOffset, {});
instance.dispatchUIEvent(element, 'change');
UI.clearInitialValue(element);
}
} else {
commitInput(instance, element, newOffset, {
data,
inputType
});
}
}
function calculateNewValue(inputData, node, { startOffset, endOffset }, inputType) {
const value = UI.getUIValue(node);
const prologEnd = Math.max(0, startOffset === endOffset && inputType === 'deleteContentBackward' ? startOffset - 1 : startOffset);
const prolog = value.substring(0, prologEnd);
const epilogStart = Math.min(value.length, startOffset === endOffset && inputType === 'deleteContentForward' ? startOffset + 1 : endOffset);
const epilog = value.substring(epilogStart, value.length);
let newValue = `${prolog}${inputData}${epilog}`;
let newOffset = prologEnd + inputData.length;
if (isElementType.isElementType(node, 'input', {
type: 'time'
})) {
const builtValue = timeValue.buildTimeValue(newValue);
if (builtValue !== '' && timeValue.isValidDateOrTimeValue(node, builtValue)) {
newValue = builtValue;
newOffset = builtValue.length;
}
}
return {
oldValue: value,
newValue,
newOffset
};
}
function commitInput(instance, element, newOffset, inputInit) {
instance.dispatchUIEvent(element, 'input', inputInit);
trackValue.commitValueAfterInput(element, newOffset);
}
function isValidNumberInput(value) {
var _value_match, _value_match1;
// the browser allows some invalid input but not others
// it allows up to two '-' at any place before any 'e' or one directly following 'e'
// it allows one '.' at any place before e
const valueParts = value.split('e', 2);
return !(/[^\d.\-e]/.test(value) || Number((_value_match = value.match(/-/g)) === null || _value_match === undefined ? undefined : _value_match.length) > 2 || Number((_value_match1 = value.match(/\./g)) === null || _value_match1 === undefined ? undefined : _value_match1.length) > 1 || valueParts[1] && !/^-?\d*$/.test(valueParts[1]));
}
exports.input = input;