Dev #6
@@ -2190,23 +2190,20 @@ export const WorkspaceView: React.FC<WorkspaceViewProps> = ({
|
||||
if (el instanceof HTMLTextAreaElement) {
|
||||
autoResizeTextarea(el);
|
||||
}
|
||||
if ('setSelectionRange' in el && typeof el.value === 'string') {
|
||||
// Only programmatically adjust selection if the element is NOT already the actively focused element!
|
||||
if (document.activeElement !== el && 'setSelectionRange' in el && typeof el.value === 'string') {
|
||||
const segStartAttr = el.getAttribute('data-seg-start');
|
||||
const segStart = segStartAttr !== null ? parseInt(segStartAttr, 10) || 0 : 0;
|
||||
const desiredOffset = activeCursorOffsetRef.current;
|
||||
const localPos = Math.max(0, Math.min(el.value.length, desiredOffset - segStart));
|
||||
if (document.activeElement !== el) {
|
||||
el.focus();
|
||||
}
|
||||
el.focus();
|
||||
try {
|
||||
if (el.selectionStart !== localPos || el.selectionEnd !== localPos) {
|
||||
el.setSelectionRange(localPos, localPos);
|
||||
}
|
||||
el.setSelectionRange(localPos, localPos);
|
||||
} catch {
|
||||
// Ignore selection range errors on unsupported inputs
|
||||
}
|
||||
}
|
||||
}, [activeEditingBlockId, activeCursorOffset, selectedDoc]);
|
||||
}, [activeEditingBlockId]);
|
||||
|
||||
// Keyboard Navigation: Enter, Shift+Enter, Tab, Shift+Tab, Backspace, / Slash Commands
|
||||
const handleKeyDown = (
|
||||
@@ -3073,7 +3070,29 @@ export const WorkspaceView: React.FC<WorkspaceViewProps> = ({
|
||||
onClick={(e) => {
|
||||
if (isReadOnly) return;
|
||||
if ((e.target as HTMLElement).closest('button, a')) return;
|
||||
focusBlock(block.id);
|
||||
let clickOffset: number | undefined = undefined;
|
||||
try {
|
||||
if (document.caretRangeFromPoint) {
|
||||
const range = document.caretRangeFromPoint(e.clientX, e.clientY);
|
||||
if (range && e.currentTarget.contains(range.startContainer)) {
|
||||
const preCaretRange = range.cloneRange();
|
||||
preCaretRange.selectNodeContents(e.currentTarget);
|
||||
preCaretRange.setEnd(range.endContainer, range.endOffset);
|
||||
clickOffset = preCaretRange.toString().length;
|
||||
}
|
||||
} else if ((document as any).caretPositionFromPoint) {
|
||||
const pos = (document as any).caretPositionFromPoint(e.clientX, e.clientY);
|
||||
if (pos && pos.offsetNode && e.currentTarget.contains(pos.offsetNode)) {
|
||||
const range = document.createRange();
|
||||
range.selectNodeContents(e.currentTarget);
|
||||
range.setEnd(pos.offsetNode, pos.offset);
|
||||
clickOffset = range.toString().length;
|
||||
}
|
||||
}
|
||||
} catch {
|
||||
// fallback to end of text
|
||||
}
|
||||
focusBlock(block.id, clickOffset);
|
||||
}}
|
||||
className={`w-full text-sm leading-relaxed break-words whitespace-pre-wrap min-h-[22px] cursor-text ${extraTextClass}`}
|
||||
>
|
||||
@@ -3099,7 +3118,7 @@ export const WorkspaceView: React.FC<WorkspaceViewProps> = ({
|
||||
value={block.content || ''}
|
||||
placeholder="Notiz eingeben… (/ für Befehle)"
|
||||
onFocus={() => {
|
||||
handleBlockFocus();
|
||||
handleBlockFocus(block.id);
|
||||
}}
|
||||
onBlur={() => {
|
||||
setActiveEditingBlockId((prev) => (prev === block.id ? null : prev));
|
||||
@@ -3107,8 +3126,24 @@ export const WorkspaceView: React.FC<WorkspaceViewProps> = ({
|
||||
}}
|
||||
onChange={(e) => {
|
||||
autoResizeTextarea(e.target);
|
||||
const pos = e.target.selectionStart;
|
||||
if (typeof pos === 'number') {
|
||||
activeCursorOffsetRef.current = pos;
|
||||
}
|
||||
handleContentChange(block, e.target.value);
|
||||
}}
|
||||
onSelect={(e) => {
|
||||
const target = e.target as HTMLTextAreaElement;
|
||||
if (typeof target.selectionStart === 'number') {
|
||||
activeCursorOffsetRef.current = target.selectionStart;
|
||||
}
|
||||
}}
|
||||
onClick={(e) => {
|
||||
const target = e.target as HTMLTextAreaElement;
|
||||
if (typeof target.selectionStart === 'number') {
|
||||
activeCursorOffsetRef.current = target.selectionStart;
|
||||
}
|
||||
}}
|
||||
onKeyDown={(e) => handleKeyDown(e, block, originalIndex)}
|
||||
className={`w-full bg-transparent text-sm leading-relaxed focus:outline-none resize-none overflow-hidden break-words whitespace-pre-wrap placeholder:text-faint p-0 m-0 border-0 ${extraTextClass}`}
|
||||
/>
|
||||
@@ -4642,12 +4677,18 @@ export const WorkspaceView: React.FC<WorkspaceViewProps> = ({
|
||||
rows={1}
|
||||
readOnly={isReadOnly}
|
||||
value={block.content}
|
||||
onFocus={handleBlockFocus}
|
||||
onFocus={() => handleBlockFocus(block.id)}
|
||||
onBlur={handleBlockBlur}
|
||||
onChange={(e) => {
|
||||
autoResizeTextarea(e.target);
|
||||
const pos = e.target.selectionStart;
|
||||
if (typeof pos === 'number') activeCursorOffsetRef.current = pos;
|
||||
handleContentChange(block, e.target.value);
|
||||
}}
|
||||
onSelect={(e) => {
|
||||
const target = e.target as HTMLTextAreaElement;
|
||||
if (typeof target.selectionStart === 'number') activeCursorOffsetRef.current = target.selectionStart;
|
||||
}}
|
||||
onKeyDown={(e) => handleKeyDown(e, block, originalIndex)}
|
||||
className={`w-full bg-transparent text-lg font-bold text-main focus:outline-none resize-none overflow-hidden break-words whitespace-pre-wrap p-0 m-0 border-0 ${
|
||||
isReadOnly ? 'cursor-default' : ''
|
||||
@@ -4665,12 +4706,18 @@ export const WorkspaceView: React.FC<WorkspaceViewProps> = ({
|
||||
rows={1}
|
||||
readOnly={isReadOnly}
|
||||
value={block.content}
|
||||
onFocus={handleBlockFocus}
|
||||
onFocus={() => handleBlockFocus(block.id)}
|
||||
onBlur={handleBlockBlur}
|
||||
onChange={(e) => {
|
||||
autoResizeTextarea(e.target);
|
||||
const pos = e.target.selectionStart;
|
||||
if (typeof pos === 'number') activeCursorOffsetRef.current = pos;
|
||||
handleContentChange(block, e.target.value);
|
||||
}}
|
||||
onSelect={(e) => {
|
||||
const target = e.target as HTMLTextAreaElement;
|
||||
if (typeof target.selectionStart === 'number') activeCursorOffsetRef.current = target.selectionStart;
|
||||
}}
|
||||
onKeyDown={(e) => handleKeyDown(e, block, originalIndex)}
|
||||
className={`w-full bg-transparent text-base font-semibold text-accent focus:outline-none resize-none overflow-hidden break-words whitespace-pre-wrap p-0 m-0 border-0 ${
|
||||
isReadOnly ? 'cursor-default' : ''
|
||||
@@ -4688,12 +4735,18 @@ export const WorkspaceView: React.FC<WorkspaceViewProps> = ({
|
||||
rows={1}
|
||||
readOnly={isReadOnly}
|
||||
value={block.content}
|
||||
onFocus={handleBlockFocus}
|
||||
onFocus={() => handleBlockFocus(block.id)}
|
||||
onBlur={handleBlockBlur}
|
||||
onChange={(e) => {
|
||||
autoResizeTextarea(e.target);
|
||||
const pos = e.target.selectionStart;
|
||||
if (typeof pos === 'number') activeCursorOffsetRef.current = pos;
|
||||
handleContentChange(block, e.target.value);
|
||||
}}
|
||||
onSelect={(e) => {
|
||||
const target = e.target as HTMLTextAreaElement;
|
||||
if (typeof target.selectionStart === 'number') activeCursorOffsetRef.current = target.selectionStart;
|
||||
}}
|
||||
onKeyDown={(e) => handleKeyDown(e, block, originalIndex)}
|
||||
className={`w-full bg-transparent text-sm font-semibold text-main focus:outline-none resize-none overflow-hidden break-words whitespace-pre-wrap p-0 m-0 border-0 ${
|
||||
isReadOnly ? 'cursor-default' : ''
|
||||
|
||||
Reference in new issue
Block a user