Skip to content

Commit 37cbac3

Browse files
committed
Refactor hooks and utils to use props object pattern and add inline code styling
- text between backticks that is not a file symbol should have monospaced font - map_raw_pos_to_display_pos should accept params variable, don't destructure - use_drag_drop should accept params variable, don't destructure - [Fragment] should accept props and input_ref as positional params - [Fragment] should accept props variable - use_ghost_text should accept variable params, don't destructure inside - [Fragment] should accept two positional params: props and params variable, don't destructure - updated prompt_type prop should focus and select text in the field - updated prompt_type prop focuses field correctly, but text is not selected
1 parent 48d2b45 commit 37cbac3

9 files changed

Lines changed: 158 additions & 181 deletions

File tree

packages/ui/src/components/editor/panel/PromptField/PromptField.module.scss

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -587,3 +587,11 @@
587587
}
588588
}
589589
}
590+
591+
.inline-code {
592+
font-family: var(--vscode-editor-font-family, monospace);
593+
font-size: 12px;
594+
background-color: var(--cwc-bg-secondary);
595+
border-radius: 4px;
596+
padding: 2px 2px 1px 2px;
597+
}

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

Lines changed: 13 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -114,16 +114,13 @@ export const PromptField: React.FC<PromptFieldProps> = (props) => {
114114
set_is_invocation_dropdown_open((prev) => !prev)
115115
}, [])
116116

117-
const { is_alt_pressed, handle_container_key_down } = use_keyboard_shortcuts({
118-
show_edit_format_selector: props.show_edit_format_selector,
119-
on_edit_format_change: props.on_edit_format_change,
120-
on_copy: props.on_copy,
121-
on_invocation_count_change: props.on_invocation_count_change,
122-
is_invocation_dropdown_open,
123-
on_toggle_invocation_dropdown: toggle_invocation_dropdown,
124-
is_recording: props.is_recording,
125-
on_recording_finished: props.on_recording_finished
126-
})
117+
const { is_alt_pressed, handle_container_key_down } = use_keyboard_shortcuts(
118+
props,
119+
{
120+
is_invocation_dropdown_open,
121+
on_toggle_invocation_dropdown: toggle_invocation_dropdown
122+
}
123+
)
127124

128125
const {
129126
is_dropdown_open,
@@ -160,12 +157,7 @@ export const PromptField: React.FC<PromptFieldProps> = (props) => {
160157
})
161158

162159
const { handle_drag_start, handle_drag_over, handle_drop, handle_drag_end } =
163-
use_drag_drop({
164-
input_ref,
165-
value: props.value,
166-
context_file_paths: props.context_file_paths,
167-
on_change: props.on_change
168-
})
160+
use_drag_drop(props, input_ref)
169161

170162
const mouse_down_pos_ref = useRef<{ x: number; y: number } | null>(null)
171163

@@ -234,11 +226,11 @@ export const PromptField: React.FC<PromptFieldProps> = (props) => {
234226

235227
if (tab_changed) {
236228
prev_tab_index_ref.current = props.active_tab_index
237-
const display_pos = map_raw_pos_to_display_pos(
238-
props.value.length,
239-
props.value,
240-
props.context_file_paths ?? []
241-
)
229+
const display_pos = map_raw_pos_to_display_pos({
230+
raw_pos: props.value.length,
231+
raw_text: props.value,
232+
context_file_paths: props.context_file_paths ?? []
233+
})
242234
input_ref.current.focus()
243235
set_caret_position_for_div(input_ref.current, display_pos)
244236
} else if (is_focused) {

packages/ui/src/components/editor/panel/PromptField/hooks/use-drag-drop.ts

Lines changed: 27 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -6,19 +6,10 @@ import {
66
import { set_caret_position_for_div } from '../utils/caret'
77
import type { PromptFieldProps } from '../PromptField'
88

9-
type UseDragDropParams = {
9+
export const use_drag_drop = (
10+
props: PromptFieldProps,
1011
input_ref: RefObject<HTMLDivElement>
11-
value: PromptFieldProps['value']
12-
context_file_paths: PromptFieldProps['context_file_paths']
13-
on_change: PromptFieldProps['on_change']
14-
}
15-
16-
export const use_drag_drop = ({
17-
input_ref,
18-
value,
19-
context_file_paths,
20-
on_change
21-
}: UseDragDropParams) => {
12+
) => {
2213
const dragged_text_range_ref = useRef<{ start: number; end: number } | null>(
2314
null
2415
)
@@ -44,17 +35,17 @@ export const use_drag_drop = ({
4435

4536
const raw_start = map_display_pos_to_raw_pos({
4637
display_pos: display_start,
47-
raw_text: value,
48-
context_file_paths: context_file_paths ?? []
38+
raw_text: props.value,
39+
context_file_paths: props.context_file_paths ?? []
4940
})
5041
const raw_end = map_display_pos_to_raw_pos({
5142
display_pos: display_end,
52-
raw_text: value,
53-
context_file_paths: context_file_paths ?? []
43+
raw_text: props.value,
44+
context_file_paths: props.context_file_paths ?? []
5445
})
5546

5647
dragged_text_range_ref.current = { start: raw_start, end: raw_end }
57-
const dragged_text = value.substring(raw_start, raw_end)
48+
const dragged_text = props.value.substring(raw_start, raw_end)
5849
e.dataTransfer.setData('text/plain', dragged_text)
5950
}
6051

@@ -98,11 +89,14 @@ export const use_drag_drop = ({
9889

9990
let raw_drop_pos = map_display_pos_to_raw_pos({
10091
display_pos: display_drop_pos,
101-
raw_text: value,
102-
context_file_paths: context_file_paths ?? []
92+
raw_text: props.value,
93+
context_file_paths: props.context_file_paths ?? []
10394
})
10495

105-
const dragged_text = value.substring(dragged_range.start, dragged_range.end)
96+
const dragged_text = props.value.substring(
97+
dragged_range.start,
98+
dragged_range.end
99+
)
106100

107101
if (
108102
raw_drop_pos >= dragged_range.start &&
@@ -112,8 +106,8 @@ export const use_drag_drop = ({
112106
}
113107

114108
const value_without_dragged =
115-
value.substring(0, dragged_range.start) +
116-
value.substring(dragged_range.end)
109+
props.value.substring(0, dragged_range.start) +
110+
props.value.substring(dragged_range.end)
117111

118112
if (raw_drop_pos > dragged_range.start) {
119113
raw_drop_pos -= dragged_text.length
@@ -124,22 +118,22 @@ export const use_drag_drop = ({
124118
dragged_text +
125119
value_without_dragged.substring(raw_drop_pos)
126120

127-
on_change(new_value)
121+
props.on_change(new_value)
128122

129123
const new_raw_selection_start = raw_drop_pos
130124
const new_raw_selection_end = raw_drop_pos + dragged_text.length
131125
setTimeout(() => {
132126
if (input_ref.current) {
133-
const display_start = map_raw_pos_to_display_pos(
134-
new_raw_selection_start,
135-
new_value,
136-
context_file_paths ?? []
137-
)
138-
const display_end = map_raw_pos_to_display_pos(
139-
new_raw_selection_end,
140-
new_value,
141-
context_file_paths ?? []
142-
)
127+
const display_start = map_raw_pos_to_display_pos({
128+
raw_pos: new_raw_selection_start,
129+
raw_text: new_value,
130+
context_file_paths: props.context_file_paths ?? []
131+
})
132+
const display_end = map_raw_pos_to_display_pos({
133+
raw_pos: new_raw_selection_end,
134+
raw_text: new_value,
135+
context_file_paths: props.context_file_paths ?? []
136+
})
143137
set_caret_position_for_div(
144138
input_ref.current,
145139
display_start,

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

Lines changed: 3 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,7 @@
11
import { useState, useRef, useEffect } from 'react'
22
import type { PromptFieldProps } from '../PromptField'
33

4-
type UseDropdownParams = Pick<
5-
PromptFieldProps,
6-
'on_copy' | 'on_submit_with_control'
7-
>
8-
9-
export const use_dropdown = ({
10-
on_copy,
11-
on_submit_with_control
12-
}: UseDropdownParams) => {
4+
export const use_dropdown = (props: PromptFieldProps) => {
135
const dropdown_ref = useRef<HTMLDivElement>(null)
146
const [is_dropdown_open, set_is_dropdown_open] = useState(false)
157

@@ -38,12 +30,12 @@ export const use_dropdown = ({
3830
}, [])
3931

4032
const handle_copy_click = () => {
41-
on_copy()
33+
props.on_copy()
4234
close_dropdown()
4335
}
4436

4537
const handle_select_click = () => {
46-
on_submit_with_control()
38+
props.on_submit_with_control()
4739
close_dropdown()
4840
}
4941

packages/ui/src/components/editor/panel/PromptField/hooks/use-ghost-text.ts

Lines changed: 28 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -7,49 +7,43 @@ import {
77
useCallback
88
} from 'react'
99

10-
type UseGhostTextParams = {
10+
export const use_ghost_text = (params: {
1111
value: string
1212
input_ref: RefObject<HTMLDivElement>
1313
is_focused: boolean
1414
currently_open_file_text?: string
1515
caret_position: number
16-
}
17-
18-
export const use_ghost_text = ({
19-
value,
20-
input_ref,
21-
is_focused,
22-
currently_open_file_text,
23-
caret_position
24-
}: UseGhostTextParams) => {
16+
}) => {
2517
const [ghost_text, set_ghost_text] = useState('')
2618
const ghost_text_debounce_timer_ref = useRef<ReturnType<
2719
typeof setTimeout
2820
> | null>(null)
2921
const [can_show_ghost_text, set_can_show_ghost_text] = useState(false)
30-
const prev_is_focused_ref = useRef(is_focused)
22+
const prev_is_focused_ref = useRef(params.is_focused)
3123
const initial_value_on_focus_ref = useRef('')
3224

3325
useEffect(() => {
34-
if (is_focused && !prev_is_focused_ref.current) {
26+
if (params.is_focused && !prev_is_focused_ref.current) {
3527
set_can_show_ghost_text(false)
36-
initial_value_on_focus_ref.current = value
28+
initial_value_on_focus_ref.current = params.value
3729
} else if (
38-
is_focused &&
30+
params.is_focused &&
3931
!can_show_ghost_text &&
40-
value !== initial_value_on_focus_ref.current
32+
params.value !== initial_value_on_focus_ref.current
4133
) {
4234
set_can_show_ghost_text(true)
4335
}
44-
prev_is_focused_ref.current = is_focused
45-
}, [is_focused, value, can_show_ghost_text])
36+
prev_is_focused_ref.current = params.is_focused
37+
}, [params.is_focused, params.value, can_show_ghost_text])
4638

4739
const identifiers = useMemo(() => {
48-
if (!currently_open_file_text) return new Set<string>()
49-
const matches = currently_open_file_text.match(/[a-zA-Z_][a-zA-Z0-9_]*/g)
40+
if (!params.currently_open_file_text) return new Set<string>()
41+
const matches = params.currently_open_file_text.match(
42+
/[a-zA-Z_][a-zA-Z0-9_]*/g
43+
)
5044
if (!matches) return new Set<string>()
5145
return new Set(matches.filter((id) => id.length >= 3))
52-
}, [currently_open_file_text])
46+
}, [params.currently_open_file_text])
5347

5448
useEffect(() => {
5549
if (ghost_text_debounce_timer_ref.current) {
@@ -59,14 +53,14 @@ export const use_ghost_text = ({
5953

6054
let potential_ghost_text = ''
6155

62-
if (input_ref.current && is_focused && can_show_ghost_text) {
56+
if (params.input_ref.current && params.is_focused && can_show_ghost_text) {
6357
const selection = window.getSelection()
6458
if (selection && selection.rangeCount > 0) {
6559
const range = selection.getRangeAt(0)
6660
if (range.collapsed) {
6761
let is_inside_symbol = false
6862
let current_node: Node | null = range.startContainer
69-
while (current_node && current_node !== input_ref.current) {
63+
while (current_node && current_node !== params.input_ref.current) {
7064
if (
7165
current_node.nodeType === Node.ELEMENT_NODE &&
7266
(current_node as HTMLElement).dataset.type?.endsWith('-symbol')
@@ -79,13 +73,13 @@ export const use_ghost_text = ({
7973

8074
if (!is_inside_symbol) {
8175
const post_caret_range = range.cloneRange()
82-
post_caret_range.selectNodeContents(input_ref.current)
76+
post_caret_range.selectNodeContents(params.input_ref.current)
8377
post_caret_range.setStart(range.endContainer, range.endOffset)
8478
const text_after_cursor = post_caret_range.toString()
8579

8680
if (text_after_cursor == '' || /^\s/.test(text_after_cursor)) {
8781
const pre_caret_range = range.cloneRange()
88-
pre_caret_range.selectNodeContents(input_ref.current)
82+
pre_caret_range.selectNodeContents(params.input_ref.current)
8983
pre_caret_range.setEnd(range.startContainer, range.startOffset)
9084
const text_before_cursor = pre_caret_range.toString()
9185
const last_word_match = text_before_cursor.match(/[\S]+$/)
@@ -132,17 +126,17 @@ export const use_ghost_text = ({
132126
}
133127
}
134128
}, [
135-
value,
136-
caret_position,
129+
params.value,
130+
params.caret_position,
137131
identifiers,
138-
is_focused,
132+
params.is_focused,
139133
ghost_text,
140-
input_ref,
134+
params.input_ref,
141135
can_show_ghost_text
142136
])
143137

144138
useEffect(() => {
145-
const input = input_ref.current
139+
const input = params.input_ref.current
146140
if (!input) return
147141

148142
const existing_ghost = input.querySelector('span[data-type="ghost-text"]')
@@ -170,12 +164,12 @@ export const use_ghost_text = ({
170164
}
171165
}
172166
}
173-
}, [ghost_text, input_ref])
167+
}, [ghost_text, params.input_ref])
174168

175169
const handle_accept_ghost_text = useCallback(() => {
176-
if (!ghost_text || !input_ref.current) return
170+
if (!ghost_text || !params.input_ref.current) return
177171

178-
const ghost_node = input_ref.current.querySelector(
172+
const ghost_node = params.input_ref.current.querySelector(
179173
'span[data-type="ghost-text"]'
180174
)
181175
if (ghost_node) {
@@ -195,11 +189,11 @@ export const use_ghost_text = ({
195189
}
196190
}
197191

198-
input_ref.current.dispatchEvent(
192+
params.input_ref.current.dispatchEvent(
199193
new Event('input', { bubbles: true, cancelable: true })
200194
)
201195
}
202-
}, [ghost_text, input_ref])
196+
}, [ghost_text, params.input_ref])
203197

204198
return { ghost_text, handle_accept_ghost_text }
205199
}

0 commit comments

Comments
 (0)