EditableInput.jsx 수정

This commit is contained in:
현성필
2025-01-25 22:41:32 +09:00
parent e58855e636
commit 387bc00671
2 changed files with 76 additions and 31 deletions
@@ -77,8 +77,7 @@ export const HTTPClientView = ({model, index}) => {
}));
};
const handlePathChange = (e) => {
const path = e.target.value;
const handlePathChange = async (path) => {
if (!path) {
setCurrentModel(prev => ({
...prev,
@@ -87,12 +86,14 @@ export const HTTPClientView = ({model, index}) => {
}));
return;
}
const queryParams = parseQueryParams(path);
setCurrentModel(prev => ({
...prev,
path,
queryParams
}));
setCurrentModel(prev => {
const queryParams = parseQueryParams(path);
return {
...prev,
path,
queryParams
};
});
};
@@ -106,21 +106,67 @@ const EditableInput = ({
return parts;
};
// useEffect(() => {
// if (value !== internalValue) {
// setInternalValue(value);
// }
// }, [value]);
const getCurrentCursor = () => {
const selection = window.getSelection();
if (selection.rangeCount === 0) return null;
const range = selection.getRangeAt(0);
const preCaretRange = range.cloneRange();
preCaretRange.selectNodeContents(contentRef.current);
preCaretRange.setEnd(range.endContainer, range.endOffset);
const content = preCaretRange.toString().trim();
if (content === '\u200B') {
return 0;
}
return content.replace('\u200B', '').length;
};
const restoreCursor = (position) => {
const element = contentRef.current;
const selection = window.getSelection();
const range = document.createRange();
range.setStart(element, 0);
range.collapse(true);
const nodeStack = [element];
let node, foundStart = false, stop = false;
let charIndex = 0;
while (!stop && (node = nodeStack.pop())) {
if (node.nodeType === 3) {
const nextCharIndex = charIndex + node.length;
if (!foundStart && position >= charIndex && position <= nextCharIndex) {
range.setStart(node, position - charIndex);
foundStart = true;
}
if (foundStart && position >= charIndex && position <= nextCharIndex) {
range.setEnd(node, position - charIndex);
stop = true;
}
charIndex = nextCharIndex;
} else {
let i = node.childNodes.length;
while (i--) {
nodeStack.push(node.childNodes[i]);
}
}
}
selection.removeAllRanges();
selection.addRange(range);
};
const handleInput = (e) => {
console.log('handleInput', e);
const newValue = e.target.textContent;
const newSelection = saveSelection();
console.log(newValue);
const cursorPosition = getCurrentCursor();
setInternalValue(newValue);
setSelection(newSelection);
onChange(newValue);
requestAnimationFrame(() => {
if (contentRef.current) {
restoreCursor(cursorPosition);
}
});
};
const handlePaste = (e) => {
@@ -130,22 +176,18 @@ const EditableInput = ({
if (selection.rangeCount > 0) {
const range = selection.getRangeAt(0);
const cursorPosition = getCurrentCursor();
range.deleteContents();
const textNode = document.createTextNode(text);
range.insertNode(textNode);
const processedContent = parseContent(text);
const fragment = document.createDocumentFragment();
const newValue = contentRef.current.textContent;
setInternalValue(newValue);
onChange(newValue);
processedContent.forEach(({ type, content }) => {
const span = document.createElement('span');
span.textContent = content;
if (type === 'variable') {
span.className = 'bg-blue-100 text-blue-800 rounded px-1';
}
fragment.appendChild(span);
requestAnimationFrame(() => {
restoreCursor(cursorPosition + text.length);
});
range.insertNode(fragment);
handleInput({ target: contentRef.current });
}
};
@@ -195,7 +237,9 @@ const EditableInput = ({
data-value={internalValue}
data-name={name}
suppressContentEditableWarning={true}
/>
>
{internalValue || '\u200B'}
</div>
);
};