diff --git a/projects/js-packages/ai-client/changelog/add-ai-suggestions-actions b/projects/js-packages/ai-client/changelog/add-ai-suggestions-actions new file mode 100644 index 0000000000000..34aa993ec4f86 --- /dev/null +++ b/projects/js-packages/ai-client/changelog/add-ai-suggestions-actions @@ -0,0 +1,4 @@ +Significance: minor +Type: added + +AI Client: add internal state management to toggle editing last prompt. Add discard handler prop diff --git a/projects/js-packages/ai-client/src/components/ai-control/index.tsx b/projects/js-packages/ai-client/src/components/ai-control/index.tsx index 373a418b5e357..72c092df8bded 100644 --- a/projects/js-packages/ai-client/src/components/ai-control/index.tsx +++ b/projects/js-packages/ai-client/src/components/ai-control/index.tsx @@ -4,9 +4,23 @@ import { PlainText } from '@wordpress/block-editor'; import { Button } from '@wordpress/components'; import { useKeyboardShortcut } from '@wordpress/compose'; -import { forwardRef, useImperativeHandle, useRef } from '@wordpress/element'; +import { + forwardRef, + useImperativeHandle, + useRef, + useEffect, + useCallback, +} from '@wordpress/element'; import { __ } from '@wordpress/i18n'; -import { Icon, closeSmall, check, arrowUp } from '@wordpress/icons'; +import { + Icon, + closeSmall, + check, + arrowUp, + arrowLeft, + trash, + reusableBlock, +} from '@wordpress/icons'; import classNames from 'classnames'; import React from 'react'; /** @@ -60,6 +74,7 @@ export function AIControl( onSend = noop, onStop = noop, onAccept = noop, + onDiscard = noop, }: { disabled?: boolean; value: string; @@ -75,11 +90,43 @@ export function AIControl( onSend?: ( currentValue: string ) => void; onStop?: () => void; onAccept?: () => void; + onDiscard?: () => void; }, ref: React.MutableRefObject< null > // eslint-disable-line @typescript-eslint/ban-types ): React.ReactElement { const promptUserInputRef = useRef( null ); const loading = state === 'requesting' || state === 'suggesting'; + const [ editRequest, setEditRequest ] = React.useState( false ); + const [ lastValue, setLastValue ] = React.useState( '' ); + + useEffect( () => { + if ( editRequest ) { + promptUserInputRef?.current?.focus(); + } + + if ( ! editRequest && lastValue && value !== lastValue ) { + onChange?.( lastValue ); + } + }, [ editRequest, lastValue ] ); + + const sendRequest = useCallback( () => { + setLastValue( value ); + setEditRequest( false ); + onSend?.( value ); + }, [ value ] ); + + const changeHandler = useCallback( + ( newValue: string ) => { + onChange?.( newValue ); + setEditRequest( state !== 'init' && lastValue && lastValue !== newValue ); + }, + [ lastValue, state ] + ); + + const discardHandler = useCallback( () => { + onDiscard?.(); + onAccept?.(); + }, [] ); // Pass the ref to forwardRef. useImperativeHandle( ref, () => promptUserInputRef.current ); @@ -100,7 +147,7 @@ export function AIControl( 'enter', e => { e.preventDefault(); - onSend?.( value ); + sendRequest(); }, { target: promptUserInputRef, @@ -119,7 +166,7 @@ export function AIControl(
/g, '