EditableInput.jsx 수정
This commit is contained in:
@@ -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>
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user