-
Notifications
You must be signed in to change notification settings - Fork 887
Content Guidelines: Add AI-powered generate/improve UI via Jetpack #47959
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
aagam-shah
merged 111 commits into
trunk
from
add/content-guidelines-plugin-extensibility
Jun 17, 2026
Merged
Changes from all commits
Commits
Show all changes
111 commits
Select commit
Hold shift + click to select a range
3e19659
Jetpack AI: Add suggest-guidelines proxy endpoint (FORNO-186)
aagam-shah e9f9eb6
Add content filters support (authors, categories) to suggest-guidelin…
aagam-shah fb20ab7
Add "Generate with Jetpack" button to Content Guidelines admin page
aagam-shah 676fb4f
Refine Generate with Jetpack button: availability checks and upgrade UX
aagam-shah e746d2e
Add @since annotation and gate admin-only include behind is_admin()
aagam-shah 6abbb9a
Fix hook suffix to match Gutenberg's registered page slug
aagam-shah e62ff96
Refactor content-guidelines-ai into component structure
aagam-shah 9cf2b26
Add 'Suggest All' button in Guidelines page header
aagam-shah f22ec91
Add empty state banner for guideline generation
aagam-shah 329f1c2
Add styles for content guidelines AI components
aagam-shah 4126425
Update changelog for content guidelines AI feature
aagam-shah 24f67d7
Fix header button positioning
aagam-shah ce21431
Remove per-section generate buttons
aagam-shah 815df29
Clean up PHP docblock
aagam-shah 9f8130c
Add suggestion preview with Accept/Dismiss flow
aagam-shah f0939cc
Align with exploration-b prototype patterns
aagam-shah f959b13
Code review fixes and rich empty state banner
aagam-shah 8d16b09
Fix CSS filename — build outputs .css not .min.css
aagam-shah 12dbf80
Use inline Jetpack icon SVG with white fill
aagam-shah 9060c02
Use shared JetpackLogo from jetpack-shared-extension-utils
aagam-shah 16f4b4d
Polish UI: shimmer effect, badge, banner, button visibility
aagam-shah 9c995c2
Use CSS logical properties for RTL support
aagam-shah db58e49
Add word-level diff view for suggestion review
aagam-shah 7a2f879
Use static import for @wordpress/api-fetch
aagam-shah 5ac59cd
Extract useGenerateAll hook to deduplicate batch generation
aagam-shah 585f805
Add comment explaining DOM class manipulation in suggestion-actions
aagam-shah eee6def
Document why React roots don't need cleanup in inject.js
aagam-shah 822b184
Add aria-hidden when SuggestAllButton is visually hidden
aagam-shah 4244642
Fix re-injection after Navigator screen transitions
aagam-shah 311841a
Improve injection: unmount old roots, debounce observer
aagam-shah 9b20706
Use top-level diff import instead of deep path
aagam-shah 537282f
Add screen reader context to diff view
aagam-shah 2fee0f5
Fix stylelint errors in style.scss
aagam-shah b1b8bea
Fix i18n extraction: assign translated strings before ternary
aagam-shah 00050b4
Fix stylelint rule-empty-line-before in @keyframes
aagam-shah 69b2b94
Fix prettier formatting and import order for CI
aagam-shah 606dadc
Fix banner dismiss: persist in localStorage, ignore per-section gener…
aagam-shah 67617bc
Add Close button and X icon to banner
aagam-shah f0b22db
Improve suggestion UX: green border, click-to-accept, hide badge
aagam-shah dfe68df
Overlay diff on textarea instead of hiding DataForm
aagam-shah 65af91d
Revert to hiding DataForm approach with better selectors
aagam-shah bb9fa9b
Match diff container to Gutenberg textarea styling
aagam-shah 7f07ddf
Share banner dismiss state via wp.data store
aagam-shah 0c70895
Update pnpm-lock.yaml after rebase
aagam-shah dc44b50
Fix banner disappearing on accept + reverse Jetpack logo
aagam-shah 9c49fbe
Make logo triangles transparent so button color shows through
aagam-shah 538033e
Set logo triangles to button accent color
aagam-shah 3b5fe65
Use JetpackLogo from jetpack-components with logoColor="#fff"
aagam-shah 827d332
Diff against current textarea draft, not persisted value
aagam-shah f3f8659
Fix layout shift when textarea is resized
aagam-shah 1ab60ff
Simplify layout: remove dynamic height sync
aagam-shah ceb1457
Track textarea height via ResizeObserver for diff container
aagam-shah 7e636d7
Drop ResizeObserver, add resize:vertical to diff container
aagam-shah 2d6cb16
Capture textarea height via useState before hiding
aagam-shah 9ea4169
Update API format to match wpcom endpoint
aagam-shah 9144352
Replace snackbar with persistent upgrade Notice
aagam-shah 427e1b0
Fix upgrade notice width to match accordion cards
aagam-shah 4e65efd
Update pnpm-lock.yaml
aagam-shah 9b3b41f
Hide header button whenever banner is not dismissed
aagam-shah 08ad759
feat: add BlockGenerateButton component
aagam-shah 213ab78
feat: add BlockSuggestionActions component
aagam-shah 33315e3
feat: add block suggestion injection points
aagam-shah bc125c8
feat: add CSS for block modal suggestion and injected containers
aagam-shah edf93c4
feat: add block-level Improve guidelines with shared DiffView
aagam-shah 2fce542
chore: update pnpm-lock.yaml
aagam-shah 4877523
Merge remote-tracking branch 'origin/trunk' into add/content-guidelin…
aagam-shah 4884008
fix: separate i18n calls to prevent minifier inlining
aagam-shah f7fdbd4
Merge remote-tracking branch 'origin/forno-186-build-site-content-agg…
aagam-shah ab6fe0b
fix: align proxy and JS API with wpcom categories format
aagam-shah 390c775
fix: use text cursor on diff view
aagam-shah 22b77d6
fix: resolve phan errors in suggest-guidelines proxy
aagam-shah f023527
feat: gate AI guidelines to Automatticians during internal rollout
aagam-shah 216bb1b
fix: fallback diff height when textarea is hidden
aagam-shah 6ed332a
feat: use useAiFeature hook for plan gating
aagam-shah 6217069
Allow content guidelines AI access via enable_ai_generation query param
fd5e3b8
Allow content guidelines AI access via enable_ai_generation query param
aagam-shah 6865aa2
fix: remove requireUpgrade hack in UpgradeNotice
aagam-shah a1070b2
Merge remote-tracking branch 'origin/trunk' into add/content-guidelin…
aagam-shah 016c688
feat: add Tracks events for content guidelines AI
aagam-shah af3c61f
chore: remove mock API, use real suggest-guidelines endpoint
aagam-shah 0b29879
debug: add console logs to UpgradeNotice for plan gating
aagam-shah 9ba0e80
feat: gate AI guidelines to paid plans via hasFeature
aagam-shah 57a0a29
fix: hide banner and header button when user lacks AI plan
aagam-shah 0d30d07
chore: pin diff library to 8.0.4
aagam-shah cce69dd
fix: update upgrade notice text, style, and make dismissible
aagam-shah 6bc6bc0
fix: guard localStorage access with try/catch
aagam-shah 3d7a0a9
fix: record Tracks event when accepting via diff click
aagam-shah 8a13179
docs: explain why MutationObserver watches document.body
aagam-shah 30ad236
docs: explain intentional Simple/Atomic-only gating
aagam-shah 07a8f7e
Merge remote-tracking branch 'origin/trunk' into add/content-guidelin…
aagam-shah 0fbc5aa
refactor: pass blockModal element as prop instead of re-querying
aagam-shah bc9a0d0
fix: migrate Badge from jetpack-components to @wordpress/ui
aagam-shah 60ead07
fix: guard startInjection against being called twice
aagam-shah b8bf9df
fix: unmount block modal slot roots when modal closes
aagam-shah 42c9abf
Merge remote-tracking branch 'origin/trunk' into add/content-guidelin…
aagam-shah 9437768
Merge remote-tracking branch 'origin/add/content-guidelines-plugin-ex…
aagam-shah 85fcad5
fix: add deprecated annotations to pnpm-lock.yaml
aagam-shah 92ff40a
Merge origin/trunk; regenerate pnpm-lock.yaml cleanly
aagam-shah 2a52db0
Content Guidelines AI: update injection selectors for latest Gutenber…
aagam-shah 60edab7
Content Guidelines AI: fix data store name for latest Gutenberg
aagam-shah 7c3c46c
Content Guidelines AI: fix remaining renamed-Gutenberg references
aagam-shah b52bd5b
Content Guidelines AI: right-align the header Generate button
aagam-shah 8d18381
Content Guidelines AI: optimize injection observer and use imported s…
aagam-shah 21861cd
Content Guidelines AI: fix header button label flicker on load
aagam-shah e66278f
Merge remote-tracking branch 'origin/trunk' into add/content-guidelin…
aagam-shah 48900b9
Content Guidelines AI: address PR review (empty result + malformed JSON)
aagam-shah fc8d4b7
Content Guidelines AI: remove enable_ai_generation query-param bypass
aagam-shah 5ead501
Merge remote-tracking branch 'origin/trunk' into add/content-guidelin…
aagam-shah 4edbfb3
Content Guidelines AI: re-resolve block name when the modal combobox …
aagam-shah 45a868d
Content Guidelines AI: wire up JS translations and the Tracks client
aagam-shah a56a122
Merge remote-tracking branch 'origin/trunk' into add/content-guidelin…
aagam-shah File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,16 @@ | ||
| /** | ||
| * Content Guidelines AI — Entry point. | ||
| * | ||
| * Injects Jetpack AI-powered generate/improve buttons into the | ||
| * Content Guidelines admin page (Gutenberg experimental feature). | ||
| */ | ||
| import '@automattic/jetpack-shared-extension-utils/store/wordpress-com'; | ||
| import './content-guidelines-ai/store'; | ||
| import './content-guidelines-ai/style.scss'; | ||
| import { startInjection } from './content-guidelines-ai/lib/inject'; | ||
|
|
||
| if ( document.readyState === 'loading' ) { | ||
| document.addEventListener( 'DOMContentLoaded', startInjection ); | ||
| } else { | ||
| startInjection(); | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,86 @@ | ||
| <?php | ||
| /** | ||
| * Content Guidelines AI — Jetpack AI integration. | ||
| * | ||
| * Enqueues a standalone JS bundle on the Content Guidelines admin page | ||
| * that adds AI-powered guideline generation via Jetpack. | ||
| * | ||
| * @package automattic/jetpack | ||
| */ | ||
|
|
||
| use Automattic\Jetpack\Assets; | ||
| use Automattic\Jetpack\Status\Visitor; | ||
| use Automattic\Jetpack\Tracking; | ||
|
|
||
| if ( ! defined( 'ABSPATH' ) ) { | ||
| exit( 0 ); | ||
| } | ||
|
|
||
| /** | ||
| * Check if the current user is an Automattician. | ||
| * | ||
| * - Simple sites: wpcom_is_proxied_request() + is_automattician() | ||
| * - Atomic sites: Visitor::is_automattician_feature_flags_only() | ||
| * | ||
| * @return bool | ||
| */ | ||
| function jetpack_content_guidelines_ai_is_automattician() { | ||
| // Simple sites. | ||
| if ( function_exists( 'wpcom_is_proxied_request' ) | ||
| && wpcom_is_proxied_request() | ||
| && function_exists( 'is_automattician' ) | ||
| && is_automattician() | ||
| ) { | ||
| return true; | ||
| } | ||
|
|
||
| // Atomic sites. | ||
| return ( new Visitor() )->is_automattician_feature_flags_only(); | ||
| } | ||
|
|
||
| /** | ||
| * Enqueue content-guidelines-ai script on the Content Guidelines admin page. | ||
| * | ||
| * @since $$next-version$$ | ||
| * | ||
| * @param string $hook_suffix The current admin page hook suffix. | ||
| */ | ||
| function jetpack_content_guidelines_ai_enqueue_scripts( $hook_suffix ) { | ||
| if ( 'settings_page_guidelines-wp-admin' !== $hook_suffix ) { | ||
| return; | ||
| } | ||
|
|
||
| // Temporarily gate to Automatticians only during internal rollout. | ||
| if ( ! jetpack_content_guidelines_ai_is_automattician() ) { | ||
| return; | ||
| } | ||
|
|
||
| // Bail when build artifacts are missing rather than enqueueing a script | ||
| // with guessed (and likely wrong) dependencies. | ||
| if ( ! file_exists( JETPACK__PLUGIN_DIR . '_inc/build/content-guidelines-ai.min.asset.php' ) ) { | ||
| return; | ||
| } | ||
|
|
||
| // The bundle records Tracks events via @automattic/jetpack-analytics, | ||
| // which only queues into window._tkq. Enqueue the Tracks client (w.js) | ||
| // so events send without relying on whichever platform widgets happen | ||
| // to load it. | ||
| Tracking::register_tracks_functions_scripts( true ); | ||
|
|
||
| // Handles dependencies/version from the asset file, JS translations for | ||
| // the text domain, the CSS (including the .rtl.css variant), and style | ||
| // dependencies derived from the script's. | ||
| Assets::register_script( | ||
| 'jetpack-content-guidelines-ai', | ||
| '_inc/build/content-guidelines-ai.min.js', | ||
| JETPACK__PLUGIN_FILE, | ||
| array( | ||
| 'in_footer' => true, | ||
| 'textdomain' => 'jetpack', | ||
| 'css_path' => '_inc/build/content-guidelines-ai.css', | ||
| 'enqueue' => true, | ||
| ) | ||
| ); | ||
| } | ||
|
|
||
| add_action( 'admin_enqueue_scripts', 'jetpack_content_guidelines_ai_enqueue_scripts' ); |
73 changes: 73 additions & 0 deletions
73
projects/plugins/jetpack/_inc/content-guidelines-ai/components/block-suggestion-actions.jsx
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,73 @@ | ||
| import { useDispatch, useSelect } from '@wordpress/data'; | ||
| import { useCallback, useEffect, useState } from '@wordpress/element'; | ||
| import { acceptBlockSuggestion } from '../lib/dom'; | ||
| import { recordGuidelinesEvent } from '../lib/tracks'; | ||
| import { AI_STORE_NAME } from '../store'; | ||
| import DiffView from './diff-view'; | ||
|
|
||
| // Renders only the diff view. Accept/Dismiss and Improve buttons live in | ||
| // BlockSuggestionButtons, injected as a separate row above the modal action bar. | ||
| export default function BlockSuggestionActions( { blockName, blockModal } ) { | ||
| const suggestion = useSelect( | ||
| select => select( AI_STORE_NAME ).getSuggestion( blockName ), | ||
| [ blockName ] | ||
| ); | ||
| const blockLoading = useSelect( | ||
| select => select( AI_STORE_NAME ).isSectionLoading( blockName ), | ||
| [ blockName ] | ||
| ); | ||
| const { clearSuggestion } = useDispatch( AI_STORE_NAME ); | ||
|
|
||
| const [ original, setOriginal ] = useState( '' ); | ||
| const [ textareaHeight, setTextareaHeight ] = useState( null ); | ||
|
|
||
| // Clear stale suggestion when the modal closes (component unmounts). | ||
| useEffect( () => { | ||
| return () => clearSuggestion( blockName ); | ||
| }, [ blockName, clearSuggestion ] ); | ||
|
|
||
| // Toggle shimmer and suggestion classes on the modal. | ||
| useEffect( () => { | ||
| if ( ! blockModal ) { | ||
| return; | ||
| } | ||
|
|
||
| // Capture textarea content and height before hiding it. | ||
| if ( suggestion && ! blockModal.classList.contains( 'has-jetpack-suggestion' ) ) { | ||
| const textarea = blockModal.querySelector( '.components-textarea-control__input' ); | ||
| if ( textarea ) { | ||
| setOriginal( textarea.value || '' ); | ||
| if ( textarea.offsetHeight > 0 ) { | ||
| setTextareaHeight( textarea.offsetHeight ); | ||
| } else { | ||
| const rows = parseInt( textarea.getAttribute( 'rows' ), 10 ) || 6; | ||
| setTextareaHeight( rows * 20 + 20 ); | ||
| } | ||
| } | ||
| } | ||
|
|
||
| blockModal.classList.toggle( 'has-jetpack-suggestion', !! suggestion ); | ||
| blockModal.classList.toggle( 'is-jetpack-loading', blockLoading && ! suggestion ); | ||
| return () => { | ||
| blockModal.classList.remove( 'has-jetpack-suggestion', 'is-jetpack-loading' ); | ||
| }; | ||
| }, [ blockModal, suggestion, blockLoading ] ); | ||
|
|
||
| const handleAccept = useCallback( () => { | ||
| recordGuidelinesEvent( 'accept', { type: 'block', slug: blockName } ); | ||
| acceptBlockSuggestion( blockModal, blockName, suggestion, clearSuggestion ); | ||
| }, [ blockModal, blockName, suggestion, clearSuggestion ] ); | ||
|
|
||
| if ( ! suggestion ) { | ||
| return null; | ||
| } | ||
|
|
||
| return ( | ||
| <DiffView | ||
| original={ original } | ||
| suggestion={ suggestion } | ||
| onAccept={ handleAccept } | ||
| height={ textareaHeight } | ||
| /> | ||
| ); | ||
| } |
107 changes: 107 additions & 0 deletions
107
projects/plugins/jetpack/_inc/content-guidelines-ai/components/block-suggestion-buttons.jsx
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,107 @@ | ||
| import { useAiFeature } from '@automattic/jetpack-ai-client'; | ||
| import { Button } from '@wordpress/components'; | ||
| import { useDispatch, useSelect } from '@wordpress/data'; | ||
| import { useCallback } from '@wordpress/element'; | ||
| import { __ } from '@wordpress/i18n'; | ||
| import { store as noticesStore } from '@wordpress/notices'; | ||
| import { STORE_NAME } from '../constants'; | ||
| import { suggestGuidelines } from '../lib/api'; | ||
| import { acceptBlockSuggestion } from '../lib/dom'; | ||
| import { recordGuidelinesEvent } from '../lib/tracks'; | ||
| import { AI_STORE_NAME } from '../store'; | ||
|
|
||
| export default function BlockSuggestionButtons( { blockName, blockModal } ) { | ||
| const { createErrorNotice } = useDispatch( noticesStore ); | ||
| const { startSectionLoading, stopSectionLoading, setSuggestion, clearSuggestion } = | ||
| useDispatch( AI_STORE_NAME ); | ||
| const { hasFeature } = useAiFeature(); | ||
|
|
||
| const blockLoading = useSelect( | ||
| select => select( AI_STORE_NAME ).isSectionLoading( blockName ), | ||
| [ blockName ] | ||
| ); | ||
|
|
||
| const suggestion = useSelect( | ||
| select => select( AI_STORE_NAME ).getSuggestion( blockName ), | ||
| [ blockName ] | ||
| ); | ||
|
|
||
| const saved = useSelect( | ||
| select => select( STORE_NAME ).getBlockGuideline( blockName ), | ||
| [ blockName ] | ||
| ); | ||
|
|
||
| const handleGenerate = useCallback( async () => { | ||
| const action = saved ? 'improve' : 'generate'; | ||
| recordGuidelinesEvent( 'generate', { type: 'block', slug: blockName, action } ); | ||
|
|
||
| const textarea = blockModal?.querySelector( '.components-textarea-control__input' ); | ||
| const currentText = textarea?.value || ''; | ||
|
|
||
| startSectionLoading( blockName ); | ||
| try { | ||
| const existingContent = currentText ? { [ blockName ]: currentText } : {}; | ||
| const response = await suggestGuidelines( [ blockName ], existingContent ); | ||
| const text = response?.suggestions?.[ blockName ]; | ||
| if ( ! text ) { | ||
| throw new Error( 'No suggestion returned.' ); | ||
| } | ||
| setSuggestion( blockName, text ); | ||
| } catch { | ||
| createErrorNotice( __( 'Failed to generate guidelines. Please try again.', 'jetpack' ), { | ||
| type: 'snackbar', | ||
| } ); | ||
| } finally { | ||
| stopSectionLoading( blockName ); | ||
| } | ||
| }, [ | ||
| blockModal, | ||
| blockName, | ||
| saved, | ||
| startSectionLoading, | ||
| stopSectionLoading, | ||
| setSuggestion, | ||
| createErrorNotice, | ||
| ] ); | ||
|
|
||
| const handleAccept = useCallback( () => { | ||
| recordGuidelinesEvent( 'accept', { type: 'block', slug: blockName } ); | ||
| acceptBlockSuggestion( blockModal, blockName, suggestion, clearSuggestion ); | ||
| }, [ blockModal, blockName, suggestion, clearSuggestion ] ); | ||
|
|
||
| const handleDismiss = useCallback( () => { | ||
| recordGuidelinesEvent( 'dismiss', { type: 'block', slug: blockName } ); | ||
| clearSuggestion( blockName ); | ||
| }, [ blockName, clearSuggestion ] ); | ||
|
|
||
| if ( suggestion ) { | ||
| return ( | ||
| <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> | ||
| ); | ||
| } | ||
|
|
||
| const generateLabel = __( 'Generate guidelines', 'jetpack' ); | ||
| const improveLabel = __( 'Improve guidelines', 'jetpack' ); | ||
| const label = saved ? improveLabel : generateLabel; | ||
|
|
||
| return ( | ||
| <div className="jetpack-content-guidelines-ai__suggestion-actions"> | ||
| <Button | ||
| variant="secondary" | ||
| onClick={ handleGenerate } | ||
| disabled={ blockLoading || ! hasFeature } | ||
| accessibleWhenDisabled | ||
| className="jetpack-content-guidelines-ai__section-generate-button" | ||
| > | ||
| { label } | ||
| </Button> | ||
| </div> | ||
| ); | ||
| } |
55 changes: 55 additions & 0 deletions
55
projects/plugins/jetpack/_inc/content-guidelines-ai/components/diff-view.jsx
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,55 @@ | ||
| import { useCallback, useMemo } from '@wordpress/element'; | ||
| import { __ } from '@wordpress/i18n'; | ||
| import { diffWords } from 'diff'; | ||
|
|
||
| export default function DiffView( { original, suggestion, onAccept, height } ) { | ||
| const diff = useMemo( () => { | ||
| if ( ! suggestion ) { | ||
| return []; | ||
| } | ||
| return diffWords( original, suggestion ); | ||
| }, [ original, suggestion ] ); | ||
|
|
||
| const handleKeyDown = useCallback( | ||
| e => { | ||
| if ( e.key === 'Enter' || e.key === ' ' ) { | ||
| e.preventDefault(); | ||
| onAccept(); | ||
| } | ||
| }, | ||
| [ onAccept ] | ||
| ); | ||
|
|
||
| return ( | ||
| <div | ||
| className="jetpack-content-guidelines-ai__diff" | ||
| style={ height ? { height } : undefined } | ||
| role="button" | ||
| tabIndex={ 0 } | ||
| aria-label={ __( 'Click to accept suggested changes', 'jetpack' ) } | ||
| onClick={ onAccept } | ||
| onKeyDown={ handleKeyDown } | ||
| > | ||
| <span className="screen-reader-text"> | ||
| { __( 'Changes from current to suggested guidelines:', 'jetpack' ) } | ||
| </span> | ||
| { diff.map( ( part, i ) => { | ||
| if ( part.added ) { | ||
| return ( | ||
| <ins key={ i } className="jetpack-content-guidelines-ai__diff-added"> | ||
| { part.value } | ||
| </ins> | ||
| ); | ||
| } | ||
| if ( part.removed ) { | ||
| return ( | ||
| <del key={ i } className="jetpack-content-guidelines-ai__diff-removed"> | ||
| { part.value } | ||
| </del> | ||
| ); | ||
| } | ||
| return <span key={ i }>{ part.value }</span>; | ||
| } ) } | ||
| </div> | ||
| ); | ||
| } | ||
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.