Skip to content

Commit 96582cd

Browse files
committed
Add cut functionality to the prompt field with proper text selection handling and clipboard integration
1 parent c460e86 commit 96582cd

2 files changed

Lines changed: 42 additions & 0 deletions

File tree

‎packages/ui/src/components/editor/panel/PromptField/PromptField.tsx‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,7 @@ export const PromptField: React.FC<PromptFieldProps> = (props) => {
126126
handle_key_down,
127127
is_history_enabled,
128128
handle_copy,
129+
handle_cut,
129130
handle_paste,
130131
handle_input_click
131132
} = use_handlers(props, input_ref, ghost_text, handle_accept_ghost_text)
@@ -391,6 +392,7 @@ export const PromptField: React.FC<PromptFieldProps> = (props) => {
391392
handle_key_down(e)
392393
}}
393394
onCopy={handle_copy}
395+
onCut={handle_cut}
394396
onPaste={handle_paste}
395397
onClick={handle_input_click}
396398
onMouseDown={handle_mouse_down}

‎packages/ui/src/components/editor/panel/PromptField/hooks/use-handlers.ts‎

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -393,6 +393,45 @@ export const use_handlers = (
393393
e.clipboardData.setData('text/plain', raw_text_slice)
394394
}
395395

396+
const handle_cut = (e: React.ClipboardEvent<HTMLDivElement>) => {
397+
const selection = window.getSelection()
398+
if (!selection || selection.rangeCount == 0 || selection.isCollapsed) return
399+
400+
const range = selection.getRangeAt(0)
401+
const input_element = input_ref.current
402+
if (!input_element || !input_element.contains(range.startContainer)) return
403+
404+
e.preventDefault()
405+
406+
const pre_selection_range = document.createRange()
407+
pre_selection_range.selectNodeContents(input_element)
408+
pre_selection_range.setEnd(range.startContainer, range.startOffset)
409+
const display_start = pre_selection_range.toString().length
410+
411+
pre_selection_range.setEnd(range.endContainer, range.endOffset)
412+
const display_end = pre_selection_range.toString().length
413+
414+
const raw_start = map_display_pos_to_raw_pos(
415+
display_start,
416+
props.value,
417+
props.context_file_paths ?? []
418+
)
419+
const raw_end = map_display_pos_to_raw_pos(
420+
display_end,
421+
props.value,
422+
props.context_file_paths ?? []
423+
)
424+
425+
const raw_text_slice = props.value.substring(raw_start, raw_end)
426+
e.clipboardData.setData('text/plain', raw_text_slice)
427+
428+
const new_value =
429+
props.value.substring(0, raw_start) + props.value.substring(raw_end)
430+
431+
has_modified_current_entry_ref.current = true
432+
update_value(new_value, raw_start)
433+
}
434+
396435
const handle_paste = (e: React.ClipboardEvent<HTMLDivElement>) => {
397436
e.preventDefault()
398437
const text = e.clipboardData.getData('text/plain')
@@ -1141,6 +1180,7 @@ export const use_handlers = (
11411180
is_history_enabled,
11421181
handle_clear,
11431182
handle_copy,
1183+
handle_cut,
11441184
handle_paste,
11451185
handle_input_click
11461186
}

0 commit comments

Comments
 (0)