block_editor 0.1.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.
- checksums.yaml +7 -0
- data/MIT-LICENSE +20 -0
- data/README.md +147 -0
- data/Rakefile +18 -0
- data/app/assets/config/block_editor_manifest.js +1 -0
- data/app/assets/stylesheets/block_editor/backend.scss +4 -0
- data/app/assets/stylesheets/block_editor/backend/blocks.scss +0 -0
- data/app/assets/stylesheets/block_editor/frontend.scss +1 -0
- data/app/assets/stylesheets/block_editor/frontend/blocks.scss +0 -0
- data/app/controllers/block_editor/application_controller.rb +4 -0
- data/app/helpers/block_editor/application_helper.rb +11 -0
- data/app/javascript/block_editor/blocks/button/edit.js +240 -0
- data/app/javascript/block_editor/blocks/column/edit.js +93 -0
- data/app/javascript/block_editor/blocks/image/edit.js +656 -0
- data/app/javascript/block_editor/blocks/index.js +263 -0
- data/app/javascript/block_editor/components/block-editor/index.js +88 -0
- data/app/javascript/block_editor/components/block-editor/styles.scss +39 -0
- data/app/javascript/block_editor/components/header/index.js +45 -0
- data/app/javascript/block_editor/components/header/redo.js +36 -0
- data/app/javascript/block_editor/components/header/styles.scss +14 -0
- data/app/javascript/block_editor/components/header/undo.js +36 -0
- data/app/javascript/block_editor/components/media-upload/index.js +37 -0
- data/app/javascript/block_editor/components/notices/index.js +26 -0
- data/app/javascript/block_editor/components/notices/styles.scss +9 -0
- data/app/javascript/block_editor/components/sidebar/index.js +31 -0
- data/app/javascript/block_editor/components/sidebar/styles.scss +43 -0
- data/app/javascript/block_editor/stores/action-types.js +4 -0
- data/app/javascript/block_editor/stores/actions.js +41 -0
- data/app/javascript/block_editor/stores/controls.js +21 -0
- data/app/javascript/block_editor/stores/index.js +30 -0
- data/app/javascript/block_editor/stores/reducer.js +20 -0
- data/app/javascript/block_editor/stores/resolvers.js +10 -0
- data/app/javascript/block_editor/stores/selectors.js +13 -0
- data/app/javascript/controllers/block_editor_controller.jsx +42 -0
- data/app/javascript/controllers/index.js +6 -0
- data/app/javascript/packs/block_editor/application.js +2 -0
- data/app/javascript/packs/block_editor/application.scss +108 -0
- data/app/jobs/block_editor/application_job.rb +4 -0
- data/app/mailers/block_editor/application_mailer.rb +6 -0
- data/app/models/block_editor/application_record.rb +5 -0
- data/app/models/block_editor/block_list.rb +7 -0
- data/app/models/concerns/block_editor/listable.rb +24 -0
- data/app/views/layouts/block_editor/application.html.erb +15 -0
- data/config/initializers/webpacker_extension.rb +12 -0
- data/config/routes.rb +2 -0
- data/config/webpack/development.js +5 -0
- data/config/webpack/environment.js +3 -0
- data/config/webpack/production.js +5 -0
- data/config/webpack/test.js +5 -0
- data/config/webpacker.yml +92 -0
- data/db/migrate/20210312032114_create_block_lists.rb +11 -0
- data/lib/block_editor.rb +26 -0
- data/lib/block_editor/block_list_renderer.rb +43 -0
- data/lib/block_editor/blocks/base.rb +32 -0
- data/lib/block_editor/engine.rb +34 -0
- data/lib/block_editor/instance.rb +19 -0
- data/lib/block_editor/version.rb +3 -0
- data/lib/tasks/block_editor_tasks.rake +59 -0
- metadata +131 -0
@@ -0,0 +1,263 @@
|
|
1
|
+
/**
|
2
|
+
* External dependencies
|
3
|
+
*/
|
4
|
+
import React from 'react';
|
5
|
+
import ReactDOM from 'react-dom';
|
6
|
+
import classnames from 'classnames';
|
7
|
+
import { assign } from 'lodash';
|
8
|
+
|
9
|
+
/**
|
10
|
+
* WordPress dependencies
|
11
|
+
*/
|
12
|
+
import '@wordpress/core-data';
|
13
|
+
import { registerCoreBlocks } from '@wordpress/block-library'
|
14
|
+
import '@wordpress/block-editor';
|
15
|
+
import {
|
16
|
+
registerBlockType,
|
17
|
+
unregisterBlockType,
|
18
|
+
registerBlockStyle,
|
19
|
+
unregisterBlockStyle,
|
20
|
+
unregisterBlockVariation
|
21
|
+
} from '@wordpress/blocks';
|
22
|
+
import { createHigherOrderComponent } from '@wordpress/compose'
|
23
|
+
import { addFilter } from '@wordpress/hooks';
|
24
|
+
|
25
|
+
/**
|
26
|
+
* Internal dependencies
|
27
|
+
*/
|
28
|
+
import ColumnEdit from './column/edit';
|
29
|
+
import ButtonEdit from './button/edit';
|
30
|
+
import ImageEdit from './image/edit';
|
31
|
+
import MediaUpload from '../components/media-upload';
|
32
|
+
|
33
|
+
export const registerBlocks = () => {
|
34
|
+
const replaceButtonBlockEdit = ( settings, name ) => {
|
35
|
+
if ( name !== 'core/button' ) {
|
36
|
+
return settings;
|
37
|
+
}
|
38
|
+
|
39
|
+
return assign( {}, settings, {
|
40
|
+
edit: ButtonEdit, // Removes & replaces some styling options
|
41
|
+
attributes: assign( {}, settings.attributes, {
|
42
|
+
hasHollowStyle: {
|
43
|
+
type: 'boolean',
|
44
|
+
default: false
|
45
|
+
},
|
46
|
+
hasLargeStyle: {
|
47
|
+
type: 'boolean',
|
48
|
+
default: false
|
49
|
+
}
|
50
|
+
})
|
51
|
+
} );
|
52
|
+
}
|
53
|
+
|
54
|
+
const replaceColumnBlockEdit = ( settings, name ) => {
|
55
|
+
if ( name !== 'core/column' ) {
|
56
|
+
return settings;
|
57
|
+
}
|
58
|
+
|
59
|
+
return assign( {}, settings, {
|
60
|
+
edit: ColumnEdit // Removes column width options
|
61
|
+
} );
|
62
|
+
}
|
63
|
+
|
64
|
+
const replaceImageBlockEdit = ( settings, name ) => {
|
65
|
+
if ( name !== 'core/image' ) {
|
66
|
+
return settings;
|
67
|
+
}
|
68
|
+
|
69
|
+
return assign( {}, settings, {
|
70
|
+
edit: ImageEdit // Removes ImageSizeControl options
|
71
|
+
} );
|
72
|
+
}
|
73
|
+
|
74
|
+
const applyExtraClass = ( extraProps, blockType, attributes ) => {
|
75
|
+
if ( blockType.name !== 'core/button' ) {
|
76
|
+
return extraProps;
|
77
|
+
}
|
78
|
+
|
79
|
+
if (attributes.hasLargeStyle) {
|
80
|
+
extraProps.className = classnames( extraProps.className, 'large' );
|
81
|
+
}
|
82
|
+
|
83
|
+
if (attributes.hasHollowStyle) {
|
84
|
+
extraProps.className = classnames( extraProps.className, 'is-style-hollow' );
|
85
|
+
}
|
86
|
+
|
87
|
+
return extraProps;
|
88
|
+
}
|
89
|
+
|
90
|
+
const withClientIdClassName = createHigherOrderComponent( ( BlockListBlock ) => {
|
91
|
+
return ( props ) => {
|
92
|
+
if ( props.name !== 'core/button' ) {
|
93
|
+
return <BlockListBlock { ...props } />;
|
94
|
+
}
|
95
|
+
|
96
|
+
let classNames = '';
|
97
|
+
if (props.attributes.hasLargeStyle) {
|
98
|
+
classNames = classnames( classNames, 'large' );
|
99
|
+
}
|
100
|
+
|
101
|
+
if (props.attributes.hasHollowStyle) {
|
102
|
+
classNames = classnames( classNames, 'is-style-hollow' );
|
103
|
+
}
|
104
|
+
|
105
|
+
return <BlockListBlock { ...props } className={ classNames } />;
|
106
|
+
};
|
107
|
+
}, 'withClientIdClassName' );
|
108
|
+
|
109
|
+
const replaceMediaUpload = () => MediaUpload;
|
110
|
+
|
111
|
+
addFilter(
|
112
|
+
'editor.BlockListBlock',
|
113
|
+
'block-editor/filters/core-button-block-list',
|
114
|
+
withClientIdClassName
|
115
|
+
);
|
116
|
+
|
117
|
+
addFilter(
|
118
|
+
'blocks.registerBlockType',
|
119
|
+
'block-editor/filters/core-button',
|
120
|
+
replaceButtonBlockEdit
|
121
|
+
);
|
122
|
+
|
123
|
+
addFilter(
|
124
|
+
'blocks.getSaveContent.extraProps',
|
125
|
+
'block-editor/filters/core-button-classes',
|
126
|
+
applyExtraClass
|
127
|
+
);
|
128
|
+
|
129
|
+
addFilter(
|
130
|
+
'blocks.registerBlockType',
|
131
|
+
'block-editor/filters/core-column',
|
132
|
+
replaceColumnBlockEdit
|
133
|
+
);
|
134
|
+
|
135
|
+
addFilter(
|
136
|
+
'blocks.registerBlockType',
|
137
|
+
'block-editor/filters/core-image',
|
138
|
+
replaceImageBlockEdit
|
139
|
+
);
|
140
|
+
|
141
|
+
addFilter(
|
142
|
+
'editor.MediaUpload',
|
143
|
+
'block-editor/filters/media-upload',
|
144
|
+
replaceMediaUpload
|
145
|
+
);
|
146
|
+
|
147
|
+
// Register WP blocks
|
148
|
+
registerCoreBlocks();
|
149
|
+
|
150
|
+
// Unregister WP blocks which are not supported
|
151
|
+
unregisterBlockType('core/gallery');
|
152
|
+
unregisterBlockType('core/quote');
|
153
|
+
unregisterBlockType('core/shortcode');
|
154
|
+
unregisterBlockType('core/archives');
|
155
|
+
unregisterBlockType('core/audio');
|
156
|
+
unregisterBlockType('core/calendar');
|
157
|
+
unregisterBlockType('core/categories');
|
158
|
+
unregisterBlockType('core/code');
|
159
|
+
unregisterBlockType('core/cover');
|
160
|
+
unregisterBlockType('core/embed');
|
161
|
+
unregisterBlockType('core-embed/twitter');
|
162
|
+
unregisterBlockType('core-embed/youtube');
|
163
|
+
unregisterBlockType('core-embed/facebook');
|
164
|
+
unregisterBlockType('core-embed/instagram');
|
165
|
+
unregisterBlockType('core-embed/wordpress');
|
166
|
+
unregisterBlockType('core-embed/soundcloud');
|
167
|
+
unregisterBlockType('core-embed/spotify');
|
168
|
+
unregisterBlockType('core-embed/flickr');
|
169
|
+
unregisterBlockType('core-embed/vimeo');
|
170
|
+
unregisterBlockType('core-embed/animoto');
|
171
|
+
unregisterBlockType('core-embed/cloudup');
|
172
|
+
unregisterBlockType('core-embed/collegehumor');
|
173
|
+
unregisterBlockType('core-embed/crowdsignal');
|
174
|
+
unregisterBlockType('core-embed/dailymotion');
|
175
|
+
unregisterBlockType('core-embed/hulu');
|
176
|
+
unregisterBlockType('core-embed/imgur');
|
177
|
+
unregisterBlockType('core-embed/issuu');
|
178
|
+
unregisterBlockType('core-embed/kickstarter');
|
179
|
+
unregisterBlockType('core-embed/meetup-com');
|
180
|
+
unregisterBlockType('core-embed/mixcloud');
|
181
|
+
unregisterBlockType('core-embed/polldaddy');
|
182
|
+
unregisterBlockType('core-embed/reddit');
|
183
|
+
unregisterBlockType('core-embed/reverbnation');
|
184
|
+
unregisterBlockType('core-embed/screencast');
|
185
|
+
unregisterBlockType('core-embed/scribd');
|
186
|
+
unregisterBlockType('core-embed/slideshare');
|
187
|
+
unregisterBlockType('core-embed/smugmug');
|
188
|
+
unregisterBlockType('core-embed/speaker');
|
189
|
+
unregisterBlockType('core-embed/speaker-deck');
|
190
|
+
unregisterBlockType('core-embed/tiktok');
|
191
|
+
unregisterBlockType('core-embed/ted');
|
192
|
+
unregisterBlockType('core-embed/tumblr');
|
193
|
+
unregisterBlockType('core-embed/videopress');
|
194
|
+
unregisterBlockType('core-embed/wordpress-tv');
|
195
|
+
unregisterBlockType('core-embed/amazon-kindle');
|
196
|
+
unregisterBlockType('core/file');
|
197
|
+
unregisterBlockType('core/media-text');
|
198
|
+
unregisterBlockType('core/latest-comments');
|
199
|
+
unregisterBlockType('core/latest-posts');
|
200
|
+
unregisterBlockType('core/more');
|
201
|
+
unregisterBlockType('core/nextpage');
|
202
|
+
unregisterBlockType('core/preformatted');
|
203
|
+
unregisterBlockType('core/pullquote');
|
204
|
+
unregisterBlockType('core/rss');
|
205
|
+
unregisterBlockType('core/search');
|
206
|
+
// unregisterBlockType('core/reusable-block'); // ?
|
207
|
+
// unregisterBlockType('core/reusable'); // ?
|
208
|
+
unregisterBlockType('core/social-links');
|
209
|
+
unregisterBlockType('core/social-link');
|
210
|
+
unregisterBlockType('core/spacer');
|
211
|
+
unregisterBlockType('core/subhead');
|
212
|
+
unregisterBlockType('core/tag-cloud');
|
213
|
+
unregisterBlockType('core/text-columns');
|
214
|
+
unregisterBlockType('core/verse');
|
215
|
+
unregisterBlockType('core/video');
|
216
|
+
|
217
|
+
// Unregister WP block styles
|
218
|
+
unregisterBlockStyle('core/separator', 'wide');
|
219
|
+
unregisterBlockStyle('core/button', 'fill');
|
220
|
+
unregisterBlockStyle('core/button', 'outline');
|
221
|
+
unregisterBlockStyle('core/image', 'default');
|
222
|
+
unregisterBlockStyle('core/image', 'rounded');
|
223
|
+
unregisterBlockStyle('core/table', 'regular');
|
224
|
+
unregisterBlockStyle('core/table', 'stripes');
|
225
|
+
|
226
|
+
// Unregister WP block variations
|
227
|
+
unregisterBlockVariation('core/columns', 'two-columns-one-third-two-thirds');
|
228
|
+
unregisterBlockVariation('core/columns', 'two-columns-two-thirds-one-third');
|
229
|
+
unregisterBlockVariation('core/columns', 'three-columns-wider-center');
|
230
|
+
|
231
|
+
// Register custom block styles
|
232
|
+
registerBlockStyle( 'core/button', {
|
233
|
+
name: 'primary',
|
234
|
+
label: 'Primary',
|
235
|
+
isDefault: true
|
236
|
+
} );
|
237
|
+
registerBlockStyle( 'core/button', {
|
238
|
+
name: 'secondary',
|
239
|
+
label: 'Secondary'
|
240
|
+
} );
|
241
|
+
registerBlockStyle( 'core/table', {
|
242
|
+
name: 'striped',
|
243
|
+
label: 'Striped',
|
244
|
+
isDefault: true
|
245
|
+
} );
|
246
|
+
registerBlockStyle( 'core/table', {
|
247
|
+
name: 'unstriped',
|
248
|
+
label: 'Unstriped'
|
249
|
+
} );
|
250
|
+
registerBlockStyle( 'core/image', {
|
251
|
+
name: 'default',
|
252
|
+
label: 'Default',
|
253
|
+
isDefault: true
|
254
|
+
} );
|
255
|
+
registerBlockStyle( 'core/image', {
|
256
|
+
name: 'padded',
|
257
|
+
label: 'Padded'
|
258
|
+
} );
|
259
|
+
registerBlockStyle( 'core/columns', {
|
260
|
+
name: 'no-stack',
|
261
|
+
label: 'No Stacking'
|
262
|
+
} );
|
263
|
+
};
|
@@ -0,0 +1,88 @@
|
|
1
|
+
import React from 'react'
|
2
|
+
import ReactDOM from 'react-dom'
|
3
|
+
/**
|
4
|
+
* WordPress dependencies
|
5
|
+
*/
|
6
|
+
import '@wordpress/editor'; // This shouldn't be necessary - currently required otherwise notices fails to initialized, think the data store is being registered
|
7
|
+
import '@wordpress/format-library';
|
8
|
+
import { useSelect, useDispatch } from '@wordpress/data';
|
9
|
+
import { useEffect, useState, useMemo } from '@wordpress/element';
|
10
|
+
import { serialize, parse } from '@wordpress/blocks';
|
11
|
+
import { InterfaceSkeleton as EditorSkeleton } from '@wordpress/interface';
|
12
|
+
import {
|
13
|
+
BlockEditorKeyboardShortcuts,
|
14
|
+
BlockEditorProvider,
|
15
|
+
BlockList,
|
16
|
+
BlockInspector,
|
17
|
+
WritingFlow,
|
18
|
+
ObserveTyping,
|
19
|
+
BlockBreadcrumb,
|
20
|
+
} from '@wordpress/block-editor';
|
21
|
+
import {
|
22
|
+
Popover,
|
23
|
+
SlotFillProvider,
|
24
|
+
DropZoneProvider,
|
25
|
+
} from '@wordpress/components';
|
26
|
+
|
27
|
+
/**
|
28
|
+
* Internal dependencies
|
29
|
+
*/
|
30
|
+
import Sidebar from '../sidebar';
|
31
|
+
import Header from '../header';
|
32
|
+
import Notices from '../notices';
|
33
|
+
import '../../stores'; // TODO: Think this store registering needs to be moved somewhere else so that it happens everytime a BlockEditor is initialized
|
34
|
+
|
35
|
+
function BlockEditor( { input, settings: _settings } ) {
|
36
|
+
const blocks = useSelect((select) => select("block-editor").getBlocks());
|
37
|
+
const { updateBlocks } = useDispatch("block-editor");
|
38
|
+
|
39
|
+
function handleInput(newBlocks, persist) {
|
40
|
+
updateBlocks(newBlocks);
|
41
|
+
input.value = serialize(newBlocks);
|
42
|
+
}
|
43
|
+
|
44
|
+
function handleChange(newBlocks) {
|
45
|
+
updateBlocks(newBlocks, true);
|
46
|
+
input.value = serialize(newBlocks);
|
47
|
+
}
|
48
|
+
|
49
|
+
return (
|
50
|
+
<SlotFillProvider>
|
51
|
+
<DropZoneProvider>
|
52
|
+
<EditorSkeleton
|
53
|
+
sidebar={<Sidebar />}
|
54
|
+
content={
|
55
|
+
<>
|
56
|
+
<Notices />
|
57
|
+
<BlockEditorProvider
|
58
|
+
value={ blocks }
|
59
|
+
onInput={ handleInput }
|
60
|
+
onChange={ handleChange }
|
61
|
+
settings={ _settings }
|
62
|
+
>
|
63
|
+
<Header />
|
64
|
+
<BlockBreadcrumb />
|
65
|
+
<Sidebar.InspectorFill>
|
66
|
+
<BlockInspector />
|
67
|
+
</Sidebar.InspectorFill>
|
68
|
+
<div className="block-editor__inner-wrapper">
|
69
|
+
<BlockEditorKeyboardShortcuts.Register />
|
70
|
+
<BlockEditorKeyboardShortcuts />
|
71
|
+
<WritingFlow>
|
72
|
+
<ObserveTyping>
|
73
|
+
<BlockList className="editor-styles-wrapper" />
|
74
|
+
</ObserveTyping>
|
75
|
+
</WritingFlow>
|
76
|
+
</div>
|
77
|
+
</BlockEditorProvider>
|
78
|
+
</>
|
79
|
+
}
|
80
|
+
/>
|
81
|
+
<Popover.Slot />
|
82
|
+
</DropZoneProvider>
|
83
|
+
</SlotFillProvider>
|
84
|
+
);
|
85
|
+
}
|
86
|
+
|
87
|
+
export default BlockEditor;
|
88
|
+
|
@@ -0,0 +1,39 @@
|
|
1
|
+
.block-editor__block-list {
|
2
|
+
padding-bottom: $grid-unit-30;
|
3
|
+
padding-top: $grid-unit-30 + 5;
|
4
|
+
margin-left: auto;
|
5
|
+
margin-right: auto;
|
6
|
+
}
|
7
|
+
|
8
|
+
.block-editor-block-list__layout {
|
9
|
+
margin-bottom: 50px;
|
10
|
+
}
|
11
|
+
|
12
|
+
.block-editor__inner-wrapper {
|
13
|
+
-webkit-overflow-scrolling: touch;
|
14
|
+
background: $white;
|
15
|
+
height: calc(100% - #{$header-height});
|
16
|
+
left: 0;
|
17
|
+
overflow: auto;
|
18
|
+
position: absolute;
|
19
|
+
top: $header-height;
|
20
|
+
width: 100%;
|
21
|
+
|
22
|
+
@include break-small {
|
23
|
+
width: calc(100% - #{$sidebar-width});
|
24
|
+
}
|
25
|
+
}
|
26
|
+
|
27
|
+
// Grab the default Editor styles for visual consistency with WP
|
28
|
+
.editor-styles-wrapper {
|
29
|
+
// We need the styles scoped to "body" to be added to the
|
30
|
+
// div.editor-styles wrapper
|
31
|
+
font-family: $editor-font;
|
32
|
+
font-size: $editor-font-size;
|
33
|
+
line-height: $editor-line-height;
|
34
|
+
color: #555;
|
35
|
+
|
36
|
+
// Important all other selectors scoped underneath
|
37
|
+
// `div.editor-styles-wrapper`
|
38
|
+
@import "~@wordpress/editor/src/editor-styles.scss";
|
39
|
+
}
|
@@ -0,0 +1,45 @@
|
|
1
|
+
import React from 'react'
|
2
|
+
import ReactDOM from 'react-dom'
|
3
|
+
|
4
|
+
/**
|
5
|
+
* WordPress dependencies
|
6
|
+
*/
|
7
|
+
import { NavigableToolbar } from '@wordpress/block-editor';
|
8
|
+
import { Button } from '@wordpress/components';
|
9
|
+
import { minus as minimizeIcon } from '@wordpress/icons';
|
10
|
+
import { plus as maximizeIcon } from '@wordpress/icons';
|
11
|
+
|
12
|
+
import HistoryUndo from './undo';
|
13
|
+
import HistoryRedo from './redo';
|
14
|
+
|
15
|
+
export default function Header() {
|
16
|
+
return (
|
17
|
+
<div
|
18
|
+
className="block-editor__header"
|
19
|
+
role="region"
|
20
|
+
tabIndex="-1"
|
21
|
+
>
|
22
|
+
<NavigableToolbar
|
23
|
+
className="edit-post-header-toolbar"
|
24
|
+
>
|
25
|
+
<HistoryUndo />
|
26
|
+
<HistoryRedo />
|
27
|
+
<Button
|
28
|
+
icon={ maximizeIcon }
|
29
|
+
label={ 'Fullscreen' }
|
30
|
+
// shortcut={ displayShortcut.primary( 'x' ) }
|
31
|
+
className="block-editor__size-toggle-button block-editor__size-toggle-button__maximize"
|
32
|
+
onClick={() => document.querySelector('.block-editor').classList.add('block-editor__fullscreen')}
|
33
|
+
/>
|
34
|
+
<Button
|
35
|
+
icon={ minimizeIcon }
|
36
|
+
label={ 'Minimize' }
|
37
|
+
// shortcut={ displayShortcut.primary( 'x' ) }
|
38
|
+
className="block-editor__size-toggle-button block-editor__size-toggle-button__minimize"
|
39
|
+
onClick={() => document.querySelector('.block-editor').classList.remove('block-editor__fullscreen')}
|
40
|
+
/>
|
41
|
+
|
42
|
+
</NavigableToolbar>
|
43
|
+
</div>
|
44
|
+
);
|
45
|
+
}
|
@@ -0,0 +1,36 @@
|
|
1
|
+
import React from 'react';
|
2
|
+
import ReactDOM from 'react-dom';
|
3
|
+
import { __ } from '@wordpress/i18n';
|
4
|
+
import { Button } from '@wordpress/components';
|
5
|
+
import { withSelect, withDispatch } from '@wordpress/data';
|
6
|
+
import { compose } from '@wordpress/compose';
|
7
|
+
import { displayShortcut } from '@wordpress/keycodes';
|
8
|
+
import { redo as redoIcon } from '@wordpress/icons';
|
9
|
+
|
10
|
+
function HistoryRedo( { hasRedo, redo, ...props } ) {
|
11
|
+
return (
|
12
|
+
<Button
|
13
|
+
{ ...props }
|
14
|
+
icon={ redoIcon }
|
15
|
+
label={ __( 'Redo' ) }
|
16
|
+
shortcut={ displayShortcut.primary( 'x' ) }
|
17
|
+
// If there are no redo levels we don't want to actually disable this
|
18
|
+
// button, because it will remove focus for keyboard users.
|
19
|
+
// See: https://github.com/WordPress/gutenberg/issues/3486
|
20
|
+
aria-disabled={ ! hasRedo }
|
21
|
+
onClick={ hasRedo ? redo : undefined }
|
22
|
+
className="editor-history__redo"
|
23
|
+
/>
|
24
|
+
);
|
25
|
+
}
|
26
|
+
|
27
|
+
const EnhancedHistoryRedo = compose( [
|
28
|
+
withSelect( ( select ) => ( {
|
29
|
+
hasRedo: select( 'block-editor' ).hasRedo(),
|
30
|
+
} ) ),
|
31
|
+
withDispatch( ( dispatch ) => ( {
|
32
|
+
redo: dispatch( 'block-editor' ).redo,
|
33
|
+
} ) ),
|
34
|
+
] )( HistoryRedo );
|
35
|
+
|
36
|
+
export default EnhancedHistoryRedo;
|