@mytechtoday/augment-extensions 0.1.1 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/augment-extensions/domain-rules/wordpress/README.md +163 -0
- package/augment-extensions/domain-rules/wordpress/module.json +32 -0
- package/augment-extensions/domain-rules/wordpress/rules/coding-standards.md +617 -0
- package/augment-extensions/domain-rules/wordpress/rules/directory-structure.md +270 -0
- package/augment-extensions/domain-rules/wordpress/rules/file-patterns.md +423 -0
- package/augment-extensions/domain-rules/wordpress/rules/gutenberg-blocks.md +493 -0
- package/augment-extensions/domain-rules/wordpress/rules/performance.md +568 -0
- package/augment-extensions/domain-rules/wordpress/rules/plugin-development.md +510 -0
- package/augment-extensions/domain-rules/wordpress/rules/project-detection.md +251 -0
- package/augment-extensions/domain-rules/wordpress/rules/rest-api.md +501 -0
- package/augment-extensions/domain-rules/wordpress/rules/security.md +564 -0
- package/augment-extensions/domain-rules/wordpress/rules/theme-development.md +388 -0
- package/augment-extensions/domain-rules/wordpress/rules/woocommerce.md +441 -0
- package/augment-extensions/domain-rules/wordpress-plugin/README.md +139 -0
- package/augment-extensions/domain-rules/wordpress-plugin/examples/ajax-plugin.md +1599 -0
- package/augment-extensions/domain-rules/wordpress-plugin/examples/custom-post-type-plugin.md +1727 -0
- package/augment-extensions/domain-rules/wordpress-plugin/examples/gutenberg-block-plugin.md +428 -0
- package/augment-extensions/domain-rules/wordpress-plugin/examples/gutenberg-block.md +422 -0
- package/augment-extensions/domain-rules/wordpress-plugin/examples/mvc-plugin.md +1623 -0
- package/augment-extensions/domain-rules/wordpress-plugin/examples/object-oriented-plugin.md +1343 -0
- package/augment-extensions/domain-rules/wordpress-plugin/examples/rest-endpoint.md +734 -0
- package/augment-extensions/domain-rules/wordpress-plugin/examples/settings-page-plugin.md +1350 -0
- package/augment-extensions/domain-rules/wordpress-plugin/examples/simple-procedural-plugin.md +503 -0
- package/augment-extensions/domain-rules/wordpress-plugin/examples/singleton-plugin.md +971 -0
- package/augment-extensions/domain-rules/wordpress-plugin/module.json +53 -0
- package/augment-extensions/domain-rules/wordpress-plugin/rules/activation-hooks.md +770 -0
- package/augment-extensions/domain-rules/wordpress-plugin/rules/admin-interface.md +874 -0
- package/augment-extensions/domain-rules/wordpress-plugin/rules/ajax-handlers.md +629 -0
- package/augment-extensions/domain-rules/wordpress-plugin/rules/asset-management.md +559 -0
- package/augment-extensions/domain-rules/wordpress-plugin/rules/context-providers.md +709 -0
- package/augment-extensions/domain-rules/wordpress-plugin/rules/cron-jobs.md +736 -0
- package/augment-extensions/domain-rules/wordpress-plugin/rules/database-management.md +1057 -0
- package/augment-extensions/domain-rules/wordpress-plugin/rules/documentation-standards.md +463 -0
- package/augment-extensions/domain-rules/wordpress-plugin/rules/frontend-functionality.md +478 -0
- package/augment-extensions/domain-rules/wordpress-plugin/rules/gutenberg-blocks.md +818 -0
- package/augment-extensions/domain-rules/wordpress-plugin/rules/internationalization.md +416 -0
- package/augment-extensions/domain-rules/wordpress-plugin/rules/migration.md +667 -0
- package/augment-extensions/domain-rules/wordpress-plugin/rules/performance-optimization.md +878 -0
- package/augment-extensions/domain-rules/wordpress-plugin/rules/plugin-architecture.md +693 -0
- package/augment-extensions/domain-rules/wordpress-plugin/rules/plugin-structure.md +352 -0
- package/augment-extensions/domain-rules/wordpress-plugin/rules/rest-api.md +818 -0
- package/augment-extensions/domain-rules/wordpress-plugin/rules/scaffolding-workflow.md +624 -0
- package/augment-extensions/domain-rules/wordpress-plugin/rules/security-best-practices.md +866 -0
- package/augment-extensions/domain-rules/wordpress-plugin/rules/testing-patterns.md +1165 -0
- package/augment-extensions/domain-rules/wordpress-plugin/rules/testing.md +414 -0
- package/augment-extensions/domain-rules/wordpress-plugin/rules/vscode-integration.md +751 -0
- package/augment-extensions/domain-rules/wordpress-plugin/rules/woocommerce-integration.md +949 -0
- package/augment-extensions/domain-rules/wordpress-plugin/rules/wordpress-org-submission.md +458 -0
- package/augment-extensions/examples/gutenberg-block-plugin/README.md +101 -0
- package/augment-extensions/examples/gutenberg-block-plugin/examples/testimonial-block.md +428 -0
- package/augment-extensions/examples/gutenberg-block-plugin/module.json +40 -0
- package/augment-extensions/examples/rest-api-plugin/README.md +98 -0
- package/augment-extensions/examples/rest-api-plugin/examples/task-manager-api.md +1299 -0
- package/augment-extensions/examples/rest-api-plugin/module.json +40 -0
- package/augment-extensions/examples/woocommerce-extension/README.md +98 -0
- package/augment-extensions/examples/woocommerce-extension/examples/product-customizer.md +763 -0
- package/augment-extensions/examples/woocommerce-extension/module.json +40 -0
- package/augment-extensions/workflows/wordpress-plugin/README.md +232 -0
- package/augment-extensions/workflows/wordpress-plugin/ai-prompts.md +839 -0
- package/augment-extensions/workflows/wordpress-plugin/bead-decomposition-patterns.md +854 -0
- package/augment-extensions/workflows/wordpress-plugin/examples/complete-plugin-example.md +540 -0
- package/augment-extensions/workflows/wordpress-plugin/examples/custom-post-type-example.md +1083 -0
- package/augment-extensions/workflows/wordpress-plugin/examples/feature-addition-workflow.md +669 -0
- package/augment-extensions/workflows/wordpress-plugin/examples/plugin-creation-workflow.md +597 -0
- package/augment-extensions/workflows/wordpress-plugin/examples/secure-form-handler-example.md +925 -0
- package/augment-extensions/workflows/wordpress-plugin/examples/security-audit-workflow.md +752 -0
- package/augment-extensions/workflows/wordpress-plugin/examples/wordpress-org-submission-workflow.md +773 -0
- package/augment-extensions/workflows/wordpress-plugin/module.json +49 -0
- package/augment-extensions/workflows/wordpress-plugin/rules/best-practices.md +942 -0
- package/augment-extensions/workflows/wordpress-plugin/rules/development-workflow.md +702 -0
- package/augment-extensions/workflows/wordpress-plugin/rules/submission-workflow.md +728 -0
- package/augment-extensions/workflows/wordpress-plugin/rules/testing-workflow.md +775 -0
- package/cli/dist/cli.js +5 -1
- package/cli/dist/cli.js.map +1 -1
- package/cli/dist/commands/show.d.ts.map +1 -1
- package/cli/dist/commands/show.js +41 -0
- package/cli/dist/commands/show.js.map +1 -1
- package/modules.md +52 -0
- package/package.json +1 -1
|
@@ -0,0 +1,428 @@
|
|
|
1
|
+
# Gutenberg Block Plugin Example
|
|
2
|
+
|
|
3
|
+
## Overview
|
|
4
|
+
|
|
5
|
+
This example demonstrates a complete **Gutenberg Block Plugin** with block.json, edit.js, save.js, PHP registration, styles, and build process using modern WordPress block development practices.
|
|
6
|
+
|
|
7
|
+
**Complexity**: Medium-High
|
|
8
|
+
**File Count**: 10-15 files
|
|
9
|
+
**Team Size**: 1-3 developers
|
|
10
|
+
**Use Case**: Custom Gutenberg blocks, content components, interactive elements
|
|
11
|
+
|
|
12
|
+
---
|
|
13
|
+
|
|
14
|
+
## Complete Plugin: "Testimonial Block"
|
|
15
|
+
|
|
16
|
+
A comprehensive Gutenberg block plugin demonstrating modern block development with block.json, React components, InspectorControls, RichText, MediaUpload, and proper build process.
|
|
17
|
+
|
|
18
|
+
---
|
|
19
|
+
|
|
20
|
+
## Directory Structure
|
|
21
|
+
|
|
22
|
+
```
|
|
23
|
+
testimonial-block/
|
|
24
|
+
├── testimonial-block.php # Main plugin file
|
|
25
|
+
├── package.json # NPM dependencies
|
|
26
|
+
├── webpack.config.js # Webpack configuration
|
|
27
|
+
├── .babelrc # Babel configuration
|
|
28
|
+
├── readme.txt # WordPress.org readme
|
|
29
|
+
├── src/
|
|
30
|
+
│ ├── block.json # Block metadata
|
|
31
|
+
│ ├── index.js # Block registration
|
|
32
|
+
│ ├── edit.js # Edit component
|
|
33
|
+
│ ├── save.js # Save component
|
|
34
|
+
│ ├── editor.scss # Editor styles
|
|
35
|
+
│ └── style.scss # Frontend styles
|
|
36
|
+
├── build/ # Compiled files (generated)
|
|
37
|
+
│ ├── index.js
|
|
38
|
+
│ ├── index.asset.php
|
|
39
|
+
│ ├── editor.css
|
|
40
|
+
│ └── style.css
|
|
41
|
+
└── languages/ # Translation files
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
---
|
|
45
|
+
|
|
46
|
+
## Main Plugin File
|
|
47
|
+
|
|
48
|
+
### File: `testimonial-block.php`
|
|
49
|
+
|
|
50
|
+
```php
|
|
51
|
+
<?php
|
|
52
|
+
/**
|
|
53
|
+
* Plugin Name: Testimonial Block
|
|
54
|
+
* Plugin URI: https://example.com/testimonial-block
|
|
55
|
+
* Description: Custom Gutenberg block for displaying testimonials
|
|
56
|
+
* Version: 1.0.0
|
|
57
|
+
* Requires at least: 6.0
|
|
58
|
+
* Requires PHP: 7.4
|
|
59
|
+
* Author: Your Name
|
|
60
|
+
* Author URI: https://example.com
|
|
61
|
+
* License: GPL-2.0+
|
|
62
|
+
* License URI: http://www.gnu.org/licenses/gpl-2.0.txt
|
|
63
|
+
* Text Domain: testimonial-block
|
|
64
|
+
* Domain Path: /languages
|
|
65
|
+
*
|
|
66
|
+
* @package Testimonial_Block
|
|
67
|
+
*/
|
|
68
|
+
|
|
69
|
+
// Exit if accessed directly
|
|
70
|
+
if (!defined('ABSPATH')) {
|
|
71
|
+
exit;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
// Define plugin constants
|
|
75
|
+
define('TESTIMONIAL_BLOCK_VERSION', '1.0.0');
|
|
76
|
+
define('TESTIMONIAL_BLOCK_PLUGIN_DIR', plugin_dir_path(__FILE__));
|
|
77
|
+
define('TESTIMONIAL_BLOCK_PLUGIN_URL', plugin_dir_url(__FILE__));
|
|
78
|
+
|
|
79
|
+
/**
|
|
80
|
+
* Register the block
|
|
81
|
+
*/
|
|
82
|
+
function testimonial_block_register() {
|
|
83
|
+
// Register the block
|
|
84
|
+
register_block_type(TESTIMONIAL_BLOCK_PLUGIN_DIR . 'build');
|
|
85
|
+
}
|
|
86
|
+
add_action('init', 'testimonial_block_register');
|
|
87
|
+
|
|
88
|
+
/**
|
|
89
|
+
* Load plugin text domain
|
|
90
|
+
*/
|
|
91
|
+
function testimonial_block_load_textdomain() {
|
|
92
|
+
load_plugin_textdomain(
|
|
93
|
+
'testimonial-block',
|
|
94
|
+
false,
|
|
95
|
+
dirname(plugin_basename(__FILE__)) . '/languages'
|
|
96
|
+
);
|
|
97
|
+
}
|
|
98
|
+
add_action('init', 'testimonial_block_load_textdomain');
|
|
99
|
+
|
|
100
|
+
/**
|
|
101
|
+
* Add block category (optional)
|
|
102
|
+
*/
|
|
103
|
+
function testimonial_block_add_category($categories) {
|
|
104
|
+
return array_merge(
|
|
105
|
+
$categories,
|
|
106
|
+
array(
|
|
107
|
+
array(
|
|
108
|
+
'slug' => 'testimonials',
|
|
109
|
+
'title' => __('Testimonials', 'testimonial-block'),
|
|
110
|
+
'icon' => 'star-filled',
|
|
111
|
+
),
|
|
112
|
+
)
|
|
113
|
+
);
|
|
114
|
+
}
|
|
115
|
+
add_filter('block_categories_all', 'testimonial_block_add_category');
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
---
|
|
119
|
+
|
|
120
|
+
## Block Configuration
|
|
121
|
+
|
|
122
|
+
### File: `src/block.json`
|
|
123
|
+
|
|
124
|
+
```json
|
|
125
|
+
{
|
|
126
|
+
"$schema": "https://schemas.wp.org/trunk/block.json",
|
|
127
|
+
"apiVersion": 3,
|
|
128
|
+
"name": "testimonial-block/testimonial",
|
|
129
|
+
"version": "1.0.0",
|
|
130
|
+
"title": "Testimonial",
|
|
131
|
+
"category": "testimonials",
|
|
132
|
+
"icon": "format-quote",
|
|
133
|
+
"description": "Display a testimonial with author information and photo.",
|
|
134
|
+
"keywords": ["testimonial", "review", "quote"],
|
|
135
|
+
"textdomain": "testimonial-block",
|
|
136
|
+
"attributes": {
|
|
137
|
+
"content": {
|
|
138
|
+
"type": "string",
|
|
139
|
+
"source": "html",
|
|
140
|
+
"selector": ".testimonial-content"
|
|
141
|
+
},
|
|
142
|
+
"authorName": {
|
|
143
|
+
"type": "string",
|
|
144
|
+
"source": "html",
|
|
145
|
+
"selector": ".testimonial-author-name"
|
|
146
|
+
},
|
|
147
|
+
"authorTitle": {
|
|
148
|
+
"type": "string",
|
|
149
|
+
"source": "html",
|
|
150
|
+
"selector": ".testimonial-author-title"
|
|
151
|
+
},
|
|
152
|
+
"authorImage": {
|
|
153
|
+
"type": "object",
|
|
154
|
+
"default": {
|
|
155
|
+
"url": "",
|
|
156
|
+
"alt": "",
|
|
157
|
+
"id": null
|
|
158
|
+
}
|
|
159
|
+
},
|
|
160
|
+
"rating": {
|
|
161
|
+
"type": "number",
|
|
162
|
+
"default": 5
|
|
163
|
+
},
|
|
164
|
+
"alignment": {
|
|
165
|
+
"type": "string",
|
|
166
|
+
"default": "left"
|
|
167
|
+
},
|
|
168
|
+
"backgroundColor": {
|
|
169
|
+
"type": "string",
|
|
170
|
+
"default": "#f9f9f9"
|
|
171
|
+
},
|
|
172
|
+
"textColor": {
|
|
173
|
+
"type": "string",
|
|
174
|
+
"default": "#333333"
|
|
175
|
+
}
|
|
176
|
+
},
|
|
177
|
+
"supports": {
|
|
178
|
+
"html": false,
|
|
179
|
+
"align": ["wide", "full"],
|
|
180
|
+
"spacing": {
|
|
181
|
+
"margin": true,
|
|
182
|
+
"padding": true
|
|
183
|
+
}
|
|
184
|
+
},
|
|
185
|
+
"editorScript": "file:./index.js",
|
|
186
|
+
"editorStyle": "file:./editor.css",
|
|
187
|
+
"style": "file:./style.css"
|
|
188
|
+
}
|
|
189
|
+
```
|
|
190
|
+
|
|
191
|
+
---
|
|
192
|
+
|
|
193
|
+
## Block Registration
|
|
194
|
+
|
|
195
|
+
### File: `src/index.js`
|
|
196
|
+
|
|
197
|
+
```javascript
|
|
198
|
+
import { registerBlockType } from '@wordpress/blocks';
|
|
199
|
+
import Edit from './edit';
|
|
200
|
+
import save from './save';
|
|
201
|
+
import metadata from './block.json';
|
|
202
|
+
import './editor.scss';
|
|
203
|
+
import './style.scss';
|
|
204
|
+
|
|
205
|
+
/**
|
|
206
|
+
* Register the block
|
|
207
|
+
*/
|
|
208
|
+
registerBlockType(metadata.name, {
|
|
209
|
+
edit: Edit,
|
|
210
|
+
save,
|
|
211
|
+
});
|
|
212
|
+
```
|
|
213
|
+
|
|
214
|
+
---
|
|
215
|
+
|
|
216
|
+
## Edit Component
|
|
217
|
+
|
|
218
|
+
### File: `src/edit.js`
|
|
219
|
+
|
|
220
|
+
```javascript
|
|
221
|
+
import { __ } from '@wordpress/i18n';
|
|
222
|
+
import {
|
|
223
|
+
useBlockProps,
|
|
224
|
+
InspectorControls,
|
|
225
|
+
RichText,
|
|
226
|
+
MediaUpload,
|
|
227
|
+
MediaUploadCheck,
|
|
228
|
+
BlockControls,
|
|
229
|
+
AlignmentToolbar,
|
|
230
|
+
} from '@wordpress/block-editor';
|
|
231
|
+
import {
|
|
232
|
+
PanelBody,
|
|
233
|
+
RangeControl,
|
|
234
|
+
Button,
|
|
235
|
+
ColorPicker,
|
|
236
|
+
} from '@wordpress/components';
|
|
237
|
+
import { Fragment } from '@wordpress/element';
|
|
238
|
+
|
|
239
|
+
/**
|
|
240
|
+
* Edit component
|
|
241
|
+
*/
|
|
242
|
+
export default function Edit({ attributes, setAttributes }) {
|
|
243
|
+
const {
|
|
244
|
+
content,
|
|
245
|
+
authorName,
|
|
246
|
+
authorTitle,
|
|
247
|
+
authorImage,
|
|
248
|
+
rating,
|
|
249
|
+
alignment,
|
|
250
|
+
backgroundColor,
|
|
251
|
+
textColor,
|
|
252
|
+
} = attributes;
|
|
253
|
+
|
|
254
|
+
const blockProps = useBlockProps({
|
|
255
|
+
className: `testimonial-block align-${alignment}`,
|
|
256
|
+
style: {
|
|
257
|
+
backgroundColor,
|
|
258
|
+
color: textColor,
|
|
259
|
+
},
|
|
260
|
+
});
|
|
261
|
+
|
|
262
|
+
const onSelectImage = (media) => {
|
|
263
|
+
setAttributes({
|
|
264
|
+
authorImage: {
|
|
265
|
+
url: media.url,
|
|
266
|
+
alt: media.alt,
|
|
267
|
+
id: media.id,
|
|
268
|
+
},
|
|
269
|
+
});
|
|
270
|
+
};
|
|
271
|
+
|
|
272
|
+
const removeImage = () => {
|
|
273
|
+
setAttributes({
|
|
274
|
+
authorImage: {
|
|
275
|
+
url: '',
|
|
276
|
+
alt: '',
|
|
277
|
+
id: null,
|
|
278
|
+
},
|
|
279
|
+
});
|
|
280
|
+
};
|
|
281
|
+
|
|
282
|
+
const renderStars = (count) => {
|
|
283
|
+
const stars = [];
|
|
284
|
+
for (let i = 0; i < 5; i++) {
|
|
285
|
+
stars.push(
|
|
286
|
+
<span
|
|
287
|
+
key={i}
|
|
288
|
+
className={`star ${i < count ? 'filled' : ''}`}
|
|
289
|
+
>
|
|
290
|
+
★
|
|
291
|
+
</span>
|
|
292
|
+
);
|
|
293
|
+
}
|
|
294
|
+
return stars;
|
|
295
|
+
};
|
|
296
|
+
|
|
297
|
+
return (
|
|
298
|
+
<Fragment>
|
|
299
|
+
<BlockControls>
|
|
300
|
+
<AlignmentToolbar
|
|
301
|
+
value={alignment}
|
|
302
|
+
onChange={(newAlignment) =>
|
|
303
|
+
setAttributes({ alignment: newAlignment })
|
|
304
|
+
}
|
|
305
|
+
/>
|
|
306
|
+
</BlockControls>
|
|
307
|
+
|
|
308
|
+
<InspectorControls>
|
|
309
|
+
<PanelBody title={__('Testimonial Settings', 'testimonial-block')}>
|
|
310
|
+
<RangeControl
|
|
311
|
+
label={__('Rating', 'testimonial-block')}
|
|
312
|
+
value={rating}
|
|
313
|
+
onChange={(value) => setAttributes({ rating: value })}
|
|
314
|
+
min={1}
|
|
315
|
+
max={5}
|
|
316
|
+
step={1}
|
|
317
|
+
/>
|
|
318
|
+
</PanelBody>
|
|
319
|
+
|
|
320
|
+
<PanelBody title={__('Color Settings', 'testimonial-block')}>
|
|
321
|
+
<p>{__('Background Color', 'testimonial-block')}</p>
|
|
322
|
+
<ColorPicker
|
|
323
|
+
color={backgroundColor}
|
|
324
|
+
onChangeComplete={(value) =>
|
|
325
|
+
setAttributes({ backgroundColor: value.hex })
|
|
326
|
+
}
|
|
327
|
+
/>
|
|
328
|
+
|
|
329
|
+
<p style={{ marginTop: '20px' }}>
|
|
330
|
+
{__('Text Color', 'testimonial-block')}
|
|
331
|
+
</p>
|
|
332
|
+
<ColorPicker
|
|
333
|
+
color={textColor}
|
|
334
|
+
onChangeComplete={(value) =>
|
|
335
|
+
setAttributes({ textColor: value.hex })
|
|
336
|
+
}
|
|
337
|
+
/>
|
|
338
|
+
</PanelBody>
|
|
339
|
+
|
|
340
|
+
<PanelBody title={__('Author Image', 'testimonial-block')}>
|
|
341
|
+
<MediaUploadCheck>
|
|
342
|
+
<MediaUpload
|
|
343
|
+
onSelect={onSelectImage}
|
|
344
|
+
allowedTypes={['image']}
|
|
345
|
+
value={authorImage.id}
|
|
346
|
+
render={({ open }) => (
|
|
347
|
+
<div>
|
|
348
|
+
{authorImage.url ? (
|
|
349
|
+
<div>
|
|
350
|
+
<img
|
|
351
|
+
src={authorImage.url}
|
|
352
|
+
alt={authorImage.alt}
|
|
353
|
+
style={{
|
|
354
|
+
width: '100%',
|
|
355
|
+
marginBottom: '10px',
|
|
356
|
+
}}
|
|
357
|
+
/>
|
|
358
|
+
<Button
|
|
359
|
+
onClick={removeImage}
|
|
360
|
+
isDestructive
|
|
361
|
+
>
|
|
362
|
+
{__('Remove Image', 'testimonial-block')}
|
|
363
|
+
</Button>
|
|
364
|
+
</div>
|
|
365
|
+
) : (
|
|
366
|
+
<Button onClick={open} isPrimary>
|
|
367
|
+
{__('Select Image', 'testimonial-block')}
|
|
368
|
+
</Button>
|
|
369
|
+
)}
|
|
370
|
+
</div>
|
|
371
|
+
)}
|
|
372
|
+
/>
|
|
373
|
+
</MediaUploadCheck>
|
|
374
|
+
</PanelBody>
|
|
375
|
+
</InspectorControls>
|
|
376
|
+
|
|
377
|
+
<div {...blockProps}>
|
|
378
|
+
<div className="testimonial-content-wrapper">
|
|
379
|
+
<div className="testimonial-quote-icon">❝</div>
|
|
380
|
+
<RichText
|
|
381
|
+
tagName="p"
|
|
382
|
+
className="testimonial-content"
|
|
383
|
+
value={content}
|
|
384
|
+
onChange={(value) => setAttributes({ content: value })}
|
|
385
|
+
placeholder={__(
|
|
386
|
+
'Enter testimonial content...',
|
|
387
|
+
'testimonial-block'
|
|
388
|
+
)}
|
|
389
|
+
/>
|
|
390
|
+
</div>
|
|
391
|
+
|
|
392
|
+
<div className="testimonial-rating">{renderStars(rating)}</div>
|
|
393
|
+
|
|
394
|
+
<div className="testimonial-author">
|
|
395
|
+
{authorImage.url && (
|
|
396
|
+
<img
|
|
397
|
+
src={authorImage.url}
|
|
398
|
+
alt={authorImage.alt}
|
|
399
|
+
className="testimonial-author-image"
|
|
400
|
+
/>
|
|
401
|
+
)}
|
|
402
|
+
<div className="testimonial-author-info">
|
|
403
|
+
<RichText
|
|
404
|
+
tagName="p"
|
|
405
|
+
className="testimonial-author-name"
|
|
406
|
+
value={authorName}
|
|
407
|
+
onChange={(value) =>
|
|
408
|
+
setAttributes({ authorName: value })
|
|
409
|
+
}
|
|
410
|
+
placeholder={__('Author Name', 'testimonial-block')}
|
|
411
|
+
/>
|
|
412
|
+
<RichText
|
|
413
|
+
tagName="p"
|
|
414
|
+
className="testimonial-author-title"
|
|
415
|
+
value={authorTitle}
|
|
416
|
+
onChange={(value) =>
|
|
417
|
+
setAttributes({ authorTitle: value })
|
|
418
|
+
}
|
|
419
|
+
placeholder={__('Author Title', 'testimonial-block')}
|
|
420
|
+
/>
|
|
421
|
+
</div>
|
|
422
|
+
</div>
|
|
423
|
+
</div>
|
|
424
|
+
</Fragment>
|
|
425
|
+
);
|
|
426
|
+
}
|
|
427
|
+
```
|
|
428
|
+
|