@@ -5,9 +5,9 @@ import { LexicalErrorBoundary } from "@lexical/react/LexicalErrorBoundary"
55import { LexicalNestedComposer } from "@lexical/react/LexicalNestedComposer"
66import { OnChangePlugin } from "@lexical/react/LexicalOnChangePlugin"
77import { RichTextPlugin } from "@lexical/react/LexicalRichTextPlugin"
8- import { Button , TextInput } from "@mantine/core"
8+ import { Autocomplete , Button } from "@mantine/core"
99import { modals } from "@mantine/modals"
10- import { IconDeviceFloppy , IconFunction } from "@tabler/icons-react"
10+ import { IconDeviceFloppy , IconFunction , IconPlus } from "@tabler/icons-react"
1111import {
1212 $createNodeSelection ,
1313 $getNodeByKey ,
@@ -17,10 +17,12 @@ import {
1717 LexicalEditor ,
1818 NodeKey ,
1919} from "lexical"
20- import { useEffect , useState } from "react"
20+ import { useEffect , useMemo , useState } from "react"
21+ import { executeCommandSequence } from "../../commands"
2122import { stringifyFunction } from "../../compilers/lexical2typst"
2223import { getFunctions } from "../../functions"
2324import { TyXValue } from "../../models"
25+ import { backupEditorSelection , restoreEditorSelection } from "../../utilities"
2426import TyXValueEditor from "../TyXValueEditor"
2527import CurrentEditorPlugin from "./CurrentEditorPlugin"
2628import {
@@ -77,17 +79,18 @@ export const FunctionCallEditModal = ({
7779 modals . closeAll ( )
7880 }
7981
80- const functions = getFunctions ( )
82+ const functions = useMemo ( ( ) => getFunctions ( ) , [ ] )
8183
8284 return (
8385 < >
84- < TextInput
86+ < Autocomplete
8587 autoCapitalize = "off"
8688 autoCorrect = "off"
8789 label = "Function"
8890 leftSection = { < IconFunction /> }
8991 value = { name }
90- onChange = { ( e ) => setName ( e . currentTarget . value ) }
92+ onChange = { setName }
93+ data = { Object . keys ( functions ) . sort ( ) }
9194 />
9295 { functions [ name ] ?. positional ?. map (
9396 ( parameterDescription , positionIndex ) => (
@@ -233,13 +236,58 @@ export const FunctionCallEditor = ({
233236 )
234237}
235238
239+ export const InsertFunctionCallModal = ( ) => {
240+ const [ name , setName ] = useState ( "" )
241+
242+ const functions = useMemo ( ( ) => getFunctions ( ) , [ ] )
243+
244+ const insert = ( ) => {
245+ restoreEditorSelection ( )
246+ executeCommandSequence ( `insertFunctionCall ${ name } ` )
247+ modals . closeAll ( )
248+ }
249+
250+ return (
251+ < >
252+ < Autocomplete
253+ data-autofocus
254+ autoCapitalize = "off"
255+ autoCorrect = "off"
256+ label = "Function"
257+ leftSection = { < IconFunction /> }
258+ value = { name }
259+ onChange = { setName }
260+ onKeyDown = { ( e ) => {
261+ if ( e . key === "Enter" ) {
262+ e . preventDefault ( )
263+ insert ( )
264+ }
265+ } }
266+ data = { Object . keys ( functions ) . sort ( ) }
267+ />
268+ < Button mt = "xs" fullWidth leftSection = { < IconPlus /> } onClick = { insert } >
269+ Insert
270+ </ Button >
271+ </ >
272+ )
273+ }
274+
236275const FunctionCallPlugin = ( ) => {
237276 const [ editor ] = useLexicalComposerContext ( )
238277
239278 useEffect ( ( ) => {
240279 return editor . registerCommand (
241280 INSERT_FUNCTION_CALL_COMMAND ,
242281 ( payload ) => {
282+ if ( payload === undefined ) {
283+ backupEditorSelection ( )
284+ modals . open ( {
285+ title : "Insert Function Call" ,
286+ children : < InsertFunctionCallModal /> ,
287+ } )
288+ return true
289+ }
290+
243291 const node =
244292 typeof payload === "string"
245293 ? $createFunctionCallNode ( payload , undefined , undefined )
0 commit comments