EditableInput.jsx 수정
This commit is contained in:
@@ -77,8 +77,7 @@ export const HTTPClientView = ({model, index}) => {
|
|||||||
}));
|
}));
|
||||||
};
|
};
|
||||||
|
|
||||||
const handlePathChange = (e) => {
|
const handlePathChange = async (path) => {
|
||||||
const path = e.target.value;
|
|
||||||
if (!path) {
|
if (!path) {
|
||||||
setCurrentModel(prev => ({
|
setCurrentModel(prev => ({
|
||||||
...prev,
|
...prev,
|
||||||
@@ -87,12 +86,14 @@ export const HTTPClientView = ({model, index}) => {
|
|||||||
}));
|
}));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const queryParams = parseQueryParams(path);
|
setCurrentModel(prev => {
|
||||||
setCurrentModel(prev => ({
|
const queryParams = parseQueryParams(path);
|
||||||
...prev,
|
return {
|
||||||
path,
|
...prev,
|
||||||
queryParams
|
path,
|
||||||
}));
|
queryParams
|
||||||
|
};
|
||||||
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -106,21 +106,67 @@ const EditableInput = ({
|
|||||||
return parts;
|
return parts;
|
||||||
};
|
};
|
||||||
|
|
||||||
// useEffect(() => {
|
const getCurrentCursor = () => {
|
||||||
// if (value !== internalValue) {
|
const selection = window.getSelection();
|
||||||
// setInternalValue(value);
|
if (selection.rangeCount === 0) return null;
|
||||||
// }
|
|
||||||
// }, [value]);
|
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) => {
|
const handleInput = (e) => {
|
||||||
console.log('handleInput', e);
|
|
||||||
const newValue = e.target.textContent;
|
const newValue = e.target.textContent;
|
||||||
const newSelection = saveSelection();
|
const cursorPosition = getCurrentCursor();
|
||||||
|
|
||||||
console.log(newValue);
|
|
||||||
setInternalValue(newValue);
|
setInternalValue(newValue);
|
||||||
setSelection(newSelection);
|
|
||||||
onChange(newValue);
|
onChange(newValue);
|
||||||
|
|
||||||
|
requestAnimationFrame(() => {
|
||||||
|
if (contentRef.current) {
|
||||||
|
restoreCursor(cursorPosition);
|
||||||
|
}
|
||||||
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
const handlePaste = (e) => {
|
const handlePaste = (e) => {
|
||||||
@@ -130,22 +176,18 @@ const EditableInput = ({
|
|||||||
|
|
||||||
if (selection.rangeCount > 0) {
|
if (selection.rangeCount > 0) {
|
||||||
const range = selection.getRangeAt(0);
|
const range = selection.getRangeAt(0);
|
||||||
|
const cursorPosition = getCurrentCursor();
|
||||||
range.deleteContents();
|
range.deleteContents();
|
||||||
|
const textNode = document.createTextNode(text);
|
||||||
|
range.insertNode(textNode);
|
||||||
|
|
||||||
const processedContent = parseContent(text);
|
const newValue = contentRef.current.textContent;
|
||||||
const fragment = document.createDocumentFragment();
|
setInternalValue(newValue);
|
||||||
|
onChange(newValue);
|
||||||
|
|
||||||
processedContent.forEach(({ type, content }) => {
|
requestAnimationFrame(() => {
|
||||||
const span = document.createElement('span');
|
restoreCursor(cursorPosition + text.length);
|
||||||
span.textContent = content;
|
|
||||||
if (type === 'variable') {
|
|
||||||
span.className = 'bg-blue-100 text-blue-800 rounded px-1';
|
|
||||||
}
|
|
||||||
fragment.appendChild(span);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
range.insertNode(fragment);
|
|
||||||
handleInput({ target: contentRef.current });
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -195,7 +237,9 @@ const EditableInput = ({
|
|||||||
data-value={internalValue}
|
data-value={internalValue}
|
||||||
data-name={name}
|
data-name={name}
|
||||||
suppressContentEditableWarning={true}
|
suppressContentEditableWarning={true}
|
||||||
/>
|
>
|
||||||
|
{internalValue || '\u200B'}
|
||||||
|
</div>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user