ResizableAIWidget.tsx89 lines · main
1import type { editor as monacoEditor } from 'monaco-editor'
2import { useCallback, useEffect, useRef, useState } from 'react'
3
4import { AskAIWidget } from '@/components/interfaces/SQLEditor/AskAIWidget'
5import InlineWidget from '@/components/interfaces/SQLEditor/InlineWidget'
6
7interface ResizableAIWidgetProps {
8 editor: monacoEditor.IStandaloneCodeEditor | monacoEditor.IStandaloneDiffEditor
9 id: string
10 value: string
11 onChange: (value: string) => void
12 onSubmit: (prompt: string) => void
13 onAccept?: () => void
14 onReject?: () => void
15 onCancel?: () => void
16 isDiffVisible: boolean
17 isLoading?: boolean
18 startLineNumber: number
19 endLineNumber: number
20}
21
22const LINE_HEIGHT = 20 // height of each line in pixels
23const MIN_LINES = 3 // minimum number of lines to show
24
25const ResizableAIWidget = ({
26 editor,
27 id,
28 value,
29 onChange,
30 onSubmit,
31 onAccept,
32 onReject,
33 onCancel,
34 isDiffVisible,
35 isLoading = false,
36 startLineNumber,
37 endLineNumber,
38}: ResizableAIWidgetProps) => {
39 const containerRef = useRef<HTMLDivElement>(null)
40 const [heightInLines, setHeightInLines] = useState(MIN_LINES)
41
42 const updateHeight = useCallback(() => {
43 if (containerRef.current) {
44 const height = containerRef.current.offsetHeight
45 const newHeightInLines = Math.max(MIN_LINES, Math.ceil(height / LINE_HEIGHT))
46 setHeightInLines(newHeightInLines)
47 }
48 }, [])
49
50 useEffect(() => {
51 // Update height on value change
52 updateHeight()
53
54 // Set up resize observer to track height changes
55 const resizeObserver = new ResizeObserver(updateHeight)
56 if (containerRef.current) {
57 resizeObserver.observe(containerRef.current)
58 }
59
60 return () => {
61 resizeObserver.disconnect()
62 }
63 }, [updateHeight])
64
65 return (
66 <InlineWidget
67 editor={editor}
68 id={id}
69 heightInLines={heightInLines}
70 afterLineNumber={endLineNumber}
71 beforeLineNumber={Math.max(0, startLineNumber - 1)}
72 >
73 <div ref={containerRef}>
74 <AskAIWidget
75 value={value}
76 onChange={onChange}
77 onSubmit={onSubmit}
78 onAccept={onAccept}
79 onReject={onReject}
80 onCancel={onCancel}
81 isDiffVisible={isDiffVisible}
82 isLoading={isLoading}
83 />
84 </div>
85 </InlineWidget>
86 )
87}
88
89export default ResizableAIWidget