Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 | import { Button } from '@wordpress/components';
import { useDispatch, useSelect } from '@wordpress/data';
import { useCallback, useEffect, useState } from '@wordpress/element';
import { __ } from '@wordpress/i18n';
import { acceptSectionSuggestion } from '../lib/dom';
import { recordGuidelinesEvent } from '../lib/tracks';
import { AI_STORE_NAME } from '../store';
import DiffView from './diff-view';
export default function SuggestionActions( { slug } ) {
const suggestion = useSelect( select => select( AI_STORE_NAME ).getSuggestion( slug ), [ slug ] );
const sectionLoading = useSelect(
select => select( AI_STORE_NAME ).isSectionLoading( slug ),
[ slug ]
);
const { clearSuggestion } = useDispatch( AI_STORE_NAME );
const [ original, setOriginal ] = useState( '' );
const [ textareaHeight, setTextareaHeight ] = useState( null );
// Direct DOM class manipulation is necessary because this component is rendered in
// a separate React root injected into Gutenberg's page — we can't control classes
// on Gutenberg-owned elements through React props.
useEffect( () => {
const item = document.querySelector( `.guidelines__list-item[data-slug="${ slug }"]` );
const form = item?.querySelector( 'form' );
if ( ! form ) {
return;
}
// Capture textarea draft and height before hiding it.
if ( suggestion && ! form.classList.contains( 'has-jetpack-suggestion' ) ) {
const textarea = form.querySelector( 'textarea' );
if ( textarea ) {
setOriginal( textarea.value || '' );
if ( textarea.offsetHeight > 0 ) {
setTextareaHeight( textarea.offsetHeight );
} else {
// Fallback when textarea is hidden (e.g. collapsed accordion).
// Compute height from rows attribute to match the textarea.
const rows = parseInt( textarea.getAttribute( 'rows' ), 10 ) || 4;
// line-height: 20px, padding: 9px top + 9px bottom, border: 1px + 1px.
setTextareaHeight( rows * 20 + 20 );
}
}
}
form.classList.toggle( 'has-jetpack-suggestion', !! suggestion );
form.classList.toggle( 'is-jetpack-loading', sectionLoading && ! suggestion );
return () => {
form.classList.remove( 'has-jetpack-suggestion', 'is-jetpack-loading' );
};
}, [ slug, suggestion, sectionLoading ] );
const handleAccept = useCallback( () => {
recordGuidelinesEvent( 'accept', { type: 'section', slug } );
acceptSectionSuggestion( slug, suggestion, clearSuggestion );
}, [ slug, suggestion, clearSuggestion ] );
const handleDismiss = useCallback( () => {
recordGuidelinesEvent( 'dismiss', { type: 'section', slug } );
clearSuggestion( slug );
}, [ slug, clearSuggestion ] );
if ( ! suggestion ) {
return null;
}
return (
<div className="jetpack-content-guidelines-ai__suggestion">
<DiffView
original={ original }
suggestion={ suggestion }
onAccept={ handleAccept }
height={ textareaHeight }
/>
<div className="jetpack-content-guidelines-ai__suggestion-actions">
<Button variant="primary" onClick={ handleAccept }>
{ __( 'Accept suggestion', 'jetpack' ) }
</Button>
<Button variant="tertiary" onClick={ handleDismiss }>
{ __( 'Dismiss', 'jetpack' ) }
</Button>
</div>
</div>
);
}
|