-
Notifications
You must be signed in to change notification settings - Fork 88
Expand file tree
/
Copy pathinline.tsx
More file actions
125 lines (110 loc) · 3.06 KB
/
inline.tsx
File metadata and controls
125 lines (110 loc) · 3.06 KB
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
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
/**
* Inline image generation.
*
* Registers block filters that add a "Generate Image" toolbar
* button and inline button to supported core blocks. Clicking the
* button opens a modal where the user can generate an image, preview
* it, refine it, and insert it into the block with a single click.
*/
/**
* WordPress dependencies
*/
import { useState } from '@wordpress/element';
import { dispatch } from '@wordpress/data';
import { addFilter } from '@wordpress/hooks';
import { createHigherOrderComponent } from '@wordpress/compose';
import {
store as blockEditorStore,
useBlockProps,
} from '@wordpress/block-editor';
import { Button, MenuItem } from '@wordpress/components';
import { __ } from '@wordpress/i18n';
import { create } from '@wordpress/icons';
/**
* Internal dependencies
*/
import { GenerateImageInlineModal } from './components/GenerateImageInlineModal';
import './index.scss';
const { aiImageGenerationData } = window as any;
const TARGET_BLOCKS = [
'core/image',
'core/cover',
'core/media-text',
'core/gallery',
];
/**
* Higher-order component that wraps the MediaUpload component for targeted
* blocks and injects the inline/toolbar button + modal.
*/
const withGenerateImageInlineButton = createHigherOrderComponent(
( Component ) => {
// Don't render if disabled.
if ( ! aiImageGenerationData?.enabled ) {
return Component;
}
return ( props: any ) => {
const [ isModalOpen, setModalOpen ] = useState( false );
const { render, mode, ...rest } = props;
let blockProps;
try {
blockProps = useBlockProps();
} catch ( e ) {
return <Component { ...props } />;
}
const { 'data-type': blockName, 'data-block': blockClientId } =
blockProps;
if ( ! TARGET_BLOCKS.includes( blockName ) ) {
return <Component { ...props } />;
}
const setAttributes = ( attrs: Record< string, unknown > ) =>
( dispatch( blockEditorStore ) as any ).updateBlockAttributes(
blockClientId,
attrs
);
// MediaPlaceholder uses mode="browse" and expects Buttons. MediaReplaceFlow
// (toolbar Add/Replace dropdown) uses no mode and expects MenuItems.
const isToolbarContext = mode !== 'browse';
return (
<>
<Component
{ ...rest }
mode="generate"
render={ () =>
isToolbarContext ? (
<MenuItem
icon={ create }
onClick={ () => setModalOpen( true ) }
>
{ __( 'Generate Image', 'ai' ) }
</MenuItem>
) : (
<Button
variant="secondary"
onClick={ () => setModalOpen( true ) }
__next40pxDefaultSize
>
{ __( 'Generate Image', 'ai' ) }
</Button>
)
}
/>
<Component { ...props } />
{ isModalOpen && (
<GenerateImageInlineModal
blockName={ blockName }
clientId={ blockClientId }
setAttributes={ setAttributes }
onClose={ () => setModalOpen( false ) }
/>
) }
</>
);
};
},
'withGenerateImageInlineButton'
);
addFilter(
'editor.MediaUpload',
'ai/image-generation-inline-button',
withGenerateImageInlineButton
);