block_editor 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 1fda7547fb328d71e8b9f4e43468bd68e2ca8acdc75056560bc8715cf7933a65
|
4
|
+
data.tar.gz: 0c9fd03776fd0db0e25d9270f52657331301597bbc4a1556ccf03ab7e6a656cd
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 4c9429b1a4fc27208fdd543a96973268650986cfd3a15a867b8917152e0f25bfa21aecd6755932c86c21a8ecd432920f6e9778fdd06f97fa550f9cdce8edfcdd
|
7
|
+
data.tar.gz: 63a53bf700739464fc6d00e5b75a1cee393199e0d7ae8a5c215719acf50d42f65b2df201db551d2c0dcee21bdcdd05c208f1c58154dee18e761af413dc8f8f61
|
data/MIT-LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright 2021 Patrick Lindsay
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,147 @@
|
|
1
|
+
# Block Editor for Ruby on Rails
|
2
|
+
This editor uses packages from the [Wordpress Gutenberg project](https://github.com/WordPress/gutenberg) to build a standalone block editor for Rails. This editor has been extracted from [Integral CMS](https://github.com/yamasolutions/integral) where it was built following the [Wordpress custom block editor tutorial](https://developer.wordpress.org/block-editor/how-to-guides/platform/custom-block-editor/).
|
3
|
+
|
4
|
+
More information;
|
5
|
+
|
6
|
+
* [Gutenberg Demo](https://wordpress.org/gutenberg/)
|
7
|
+
* [Gutenberg Block Editor Developer Documentation](https://developer.wordpress.org/block-editor/)
|
8
|
+
|
9
|
+
## Installation
|
10
|
+
Add this line to your application's Gemfile:
|
11
|
+
|
12
|
+
```ruby
|
13
|
+
gem 'block_editor'
|
14
|
+
```
|
15
|
+
|
16
|
+
And then execute:
|
17
|
+
```bash
|
18
|
+
$ bundle
|
19
|
+
```
|
20
|
+
|
21
|
+
Or install it yourself as:
|
22
|
+
```bash
|
23
|
+
$ gem install block_editor
|
24
|
+
```
|
25
|
+
|
26
|
+
## Usage
|
27
|
+
|
28
|
+
* Grab the required migrations and migrate;
|
29
|
+
```
|
30
|
+
rails block_editor:install:migrations
|
31
|
+
rails db:migrate
|
32
|
+
```
|
33
|
+
* Add `include BlockEditor::Listable` to any model you wish to associate the block editor with, i.e.
|
34
|
+
|
35
|
+
```
|
36
|
+
class Post < ApplicationRecord
|
37
|
+
include BlockEditor::Listable
|
38
|
+
end
|
39
|
+
```
|
40
|
+
* Add the block editor to your model form;
|
41
|
+
```
|
42
|
+
<%= form.fields_for :active_block_list do |block_list| %>
|
43
|
+
<%= BlockEditor::Instance.render(block_list) %>
|
44
|
+
<% end %>
|
45
|
+
```
|
46
|
+
* Add the block editor Javascript and styles within your `HEAD` tag
|
47
|
+
```
|
48
|
+
<%= javascript_pack_tag 'block_editor/application', 'data-turbolinks-track': 'reload', webpacker: 'BlockEditor' %>
|
49
|
+
<%= stylesheet_pack_tag 'block_editor/application', 'data-turbolinks-track': 'reload', webpacker: 'BlockEditor' %>
|
50
|
+
```
|
51
|
+
* Boom! You have a Block Editor linked to your model
|
52
|
+
|
53
|
+
### Strong Parameters
|
54
|
+
Remember to permit the block list attributes if you're using Strong Parameters (you should be), i.e;
|
55
|
+
```
|
56
|
+
# Only allow a list of trusted parameters through.
|
57
|
+
def post_params
|
58
|
+
params.require(:post).permit(:title, active_block_list_attributes: [ :id, :content ])
|
59
|
+
end
|
60
|
+
```
|
61
|
+
|
62
|
+
Note: You may also need to specifically set the listable attribute within your controller before saving, i.e. -
|
63
|
+
```
|
64
|
+
@post.active_block_list.listable = @post
|
65
|
+
```
|
66
|
+
|
67
|
+
### Styling
|
68
|
+
|
69
|
+
Add the frontend stylesheet where you are displaying the user created block lists;
|
70
|
+
```
|
71
|
+
<%= stylesheet_link_tag 'block_editor/backend', media: 'all', 'data-turbolinks-track': 'reload' %>
|
72
|
+
```
|
73
|
+
|
74
|
+
Add the backend stylesheet where you are rendering the block editor, for example admin dashboard;
|
75
|
+
```
|
76
|
+
<%= stylesheet_link_tag 'block_editor/backend', media: 'all', 'data-turbolinks-track': 'reload' %>
|
77
|
+
```
|
78
|
+
|
79
|
+
The below files should be overridden within your application in order to style your blocks;
|
80
|
+
* `app/assets/stylesheets/block_editor/frontend/blocks.scss` - Any styles that should be displayed within the frontend and backend
|
81
|
+
* `app/assets/stylesheets/block_editor/backend/blocks.scss` - Any styles that should _only_ be displayed within the block editor itself, i.e when creating or editing the blocks
|
82
|
+
|
83
|
+
|
84
|
+
### Turbolinks
|
85
|
+
Currently Block Editor is not compatible with Turbolinks as history is only being reset on full page loads. To disable Turbolinks per page add the following in your layout view file within your `<HEAD>`;;
|
86
|
+
```
|
87
|
+
<meta name="turbolinks-visit-control" content="reload">
|
88
|
+
```
|
89
|
+
|
90
|
+
### Adding/Removing blocks
|
91
|
+
*Currently there isn't a way of adding or removing blocks without forking the gem.*
|
92
|
+
|
93
|
+
* Fork the gem
|
94
|
+
* Edit `app/javascript/block_editor/blocks/index.js` where all blocks are registered
|
95
|
+
|
96
|
+
|
97
|
+
### Dynamic blocks
|
98
|
+
Dynamic blocks are useful for non-static content such as a recent posts block or more complex blocks like a contact form block.
|
99
|
+
|
100
|
+
*Currently the gem needs to be forked in order to create a dynamic block*
|
101
|
+
|
102
|
+
A dynamic block is made up of 4 components;
|
103
|
+
* Ruby class to handle frontend rendering
|
104
|
+
* Partial to be rendered on the frontend
|
105
|
+
* Frontend and backend styling
|
106
|
+
* JS file to manage how the block behaves within the block editor itself (This part currently is not possible without forking the gem) [Read More](https://developer.wordpress.org/block-editor/how-to-guides/block-tutorial/writing-your-first-block-type)
|
107
|
+
|
108
|
+
1. Create block class which can be as simple as;
|
109
|
+
```
|
110
|
+
class ContactForm < BlockEditor::Base
|
111
|
+
def self.name
|
112
|
+
'block-editor/contact-form'
|
113
|
+
end
|
114
|
+
end
|
115
|
+
```
|
116
|
+
2. Add block class to ```BlockEditor.dynamic_blocks``` config;
|
117
|
+
```
|
118
|
+
// application.rb
|
119
|
+
|
120
|
+
BlockEditor.dynamic_blocks = [ContactForm]
|
121
|
+
```
|
122
|
+
3. Create the view partial you want to be rendered as the block;
|
123
|
+
```
|
124
|
+
// app/views/block_editor/blocks/block-editor/contact-form/_block.html.erb
|
125
|
+
|
126
|
+
My Recent Posts
|
127
|
+
<%= @posts %>
|
128
|
+
```
|
129
|
+
4. Add any required styling to the frontend and backend stylesheets;
|
130
|
+
|
131
|
+
```
|
132
|
+
app/assets/stylesheets/block_editor/backend/blocks.scss
|
133
|
+
```
|
134
|
+
|
135
|
+
```
|
136
|
+
app/assets/stylesheets/block_editor/frontend/blocks.scss
|
137
|
+
```
|
138
|
+
5. Add the block to the block editor
|
139
|
+
* Fork the gem
|
140
|
+
* Create the block JS file i.e. `app/javascript/block_editor/blocks/contact_form/index.js`
|
141
|
+
* Edit `app/javascript/block_editor/blocks/index.js` to register the block
|
142
|
+
|
143
|
+
## Contributing
|
144
|
+
Contribution are very welcome! Currently the biggest issue that needs to be solved is extensibility. There is no way to modify and configure the editor behaviour (such as blocks to display, block output etc) without forking the engine.
|
145
|
+
|
146
|
+
## License
|
147
|
+
The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
|
data/Rakefile
ADDED
@@ -0,0 +1,18 @@
|
|
1
|
+
require "bundler/setup"
|
2
|
+
|
3
|
+
APP_RAKEFILE = File.expand_path("test/dummy/Rakefile", __dir__)
|
4
|
+
load "rails/tasks/engine.rake"
|
5
|
+
|
6
|
+
load "rails/tasks/statistics.rake"
|
7
|
+
|
8
|
+
require "bundler/gem_tasks"
|
9
|
+
|
10
|
+
require "rake/testtask"
|
11
|
+
|
12
|
+
Rake::TestTask.new(:test) do |t|
|
13
|
+
t.libs << 'test'
|
14
|
+
t.pattern = 'test/**/*_test.rb'
|
15
|
+
t.verbose = false
|
16
|
+
end
|
17
|
+
|
18
|
+
task default: :test
|
@@ -0,0 +1 @@
|
|
1
|
+
//= link_directory ../stylesheets/block_editor .css
|
File without changes
|
@@ -0,0 +1 @@
|
|
1
|
+
@import "block_editor/frontend/blocks";
|
File without changes
|
@@ -0,0 +1,240 @@
|
|
1
|
+
import React from 'react'
|
2
|
+
import ReactDOM from 'react-dom'
|
3
|
+
import PropTypes from 'prop-types'
|
4
|
+
|
5
|
+
/**
|
6
|
+
* External dependencies
|
7
|
+
*/
|
8
|
+
import classnames from 'classnames';
|
9
|
+
|
10
|
+
/**
|
11
|
+
* WordPress dependencies
|
12
|
+
*/
|
13
|
+
import { __ } from '@wordpress/i18n';
|
14
|
+
import { useCallback, useState } from '@wordpress/element';
|
15
|
+
import {
|
16
|
+
KeyboardShortcuts,
|
17
|
+
PanelBody,
|
18
|
+
RangeControl,
|
19
|
+
TextControl,
|
20
|
+
ToggleControl,
|
21
|
+
ToolbarButton,
|
22
|
+
ToolbarGroup,
|
23
|
+
Popover,
|
24
|
+
} from '@wordpress/components';
|
25
|
+
import {
|
26
|
+
BlockControls,
|
27
|
+
InspectorControls,
|
28
|
+
RichText,
|
29
|
+
__experimentalBlock as Block,
|
30
|
+
__experimentalLinkControl as LinkControl,
|
31
|
+
} from '@wordpress/block-editor';
|
32
|
+
import { rawShortcut, displayShortcut } from '@wordpress/keycodes';
|
33
|
+
import { link } from '@wordpress/icons';
|
34
|
+
import { createBlock } from '@wordpress/blocks';
|
35
|
+
|
36
|
+
// #<{(|*
|
37
|
+
// * Internal dependencies
|
38
|
+
// |)}>#
|
39
|
+
// import ColorEdit from './color-edit';
|
40
|
+
// import getColorAndStyleProps from './color-props';
|
41
|
+
|
42
|
+
const NEW_TAB_REL = 'noreferrer noopener';
|
43
|
+
const MIN_BORDER_RADIUS_VALUE = 0;
|
44
|
+
const MAX_BORDER_RADIUS_VALUE = 50;
|
45
|
+
const INITIAL_BORDER_RADIUS_POSITION = 5;
|
46
|
+
|
47
|
+
function BorderPanel( { borderRadius = '', setAttributes } ) {
|
48
|
+
const setBorderRadius = useCallback(
|
49
|
+
( newBorderRadius ) => {
|
50
|
+
setAttributes( { borderRadius: newBorderRadius } );
|
51
|
+
},
|
52
|
+
[ setAttributes ]
|
53
|
+
);
|
54
|
+
return (
|
55
|
+
<PanelBody title={ __( 'Border settings' ) }>
|
56
|
+
<RangeControl
|
57
|
+
value={ borderRadius }
|
58
|
+
label={ __( 'Border radius' ) }
|
59
|
+
min={ MIN_BORDER_RADIUS_VALUE }
|
60
|
+
max={ MAX_BORDER_RADIUS_VALUE }
|
61
|
+
initialPosition={ INITIAL_BORDER_RADIUS_POSITION }
|
62
|
+
allowReset
|
63
|
+
onChange={ setBorderRadius }
|
64
|
+
/>
|
65
|
+
</PanelBody>
|
66
|
+
);
|
67
|
+
}
|
68
|
+
|
69
|
+
function URLPicker( {
|
70
|
+
isSelected,
|
71
|
+
url,
|
72
|
+
setAttributes,
|
73
|
+
opensInNewTab,
|
74
|
+
onToggleOpenInNewTab,
|
75
|
+
} ) {
|
76
|
+
const [ isURLPickerOpen, setIsURLPickerOpen ] = useState( false );
|
77
|
+
const openLinkControl = () => {
|
78
|
+
setIsURLPickerOpen( true );
|
79
|
+
|
80
|
+
// prevents default behaviour for event
|
81
|
+
return false;
|
82
|
+
};
|
83
|
+
const linkControl = isURLPickerOpen && (
|
84
|
+
<Popover
|
85
|
+
position="bottom center"
|
86
|
+
onClose={ () => setIsURLPickerOpen( false ) }
|
87
|
+
>
|
88
|
+
<LinkControl
|
89
|
+
className="wp-block-navigation-link__inline-link-input"
|
90
|
+
value={ { url, opensInNewTab } }
|
91
|
+
onChange={ ( {
|
92
|
+
url: newURL = '',
|
93
|
+
opensInNewTab: newOpensInNewTab,
|
94
|
+
} ) => {
|
95
|
+
setAttributes( { url: newURL } );
|
96
|
+
|
97
|
+
if ( opensInNewTab !== newOpensInNewTab ) {
|
98
|
+
onToggleOpenInNewTab( newOpensInNewTab );
|
99
|
+
}
|
100
|
+
} }
|
101
|
+
/>
|
102
|
+
</Popover>
|
103
|
+
);
|
104
|
+
return (
|
105
|
+
<>
|
106
|
+
<BlockControls>
|
107
|
+
<ToolbarGroup>
|
108
|
+
<ToolbarButton
|
109
|
+
name="link"
|
110
|
+
icon={ link }
|
111
|
+
title={ __( 'Link' ) }
|
112
|
+
shortcut={ displayShortcut.primary( 'k' ) }
|
113
|
+
onClick={ openLinkControl }
|
114
|
+
/>
|
115
|
+
</ToolbarGroup>
|
116
|
+
</BlockControls>
|
117
|
+
{ isSelected && (
|
118
|
+
<KeyboardShortcuts
|
119
|
+
bindGlobal
|
120
|
+
shortcuts={ {
|
121
|
+
[ rawShortcut.primary( 'k' ) ]: openLinkControl,
|
122
|
+
} }
|
123
|
+
/>
|
124
|
+
) }
|
125
|
+
{ linkControl }
|
126
|
+
</>
|
127
|
+
);
|
128
|
+
}
|
129
|
+
|
130
|
+
function ButtonEdit( props ) {
|
131
|
+
const {
|
132
|
+
attributes,
|
133
|
+
setAttributes,
|
134
|
+
className,
|
135
|
+
isSelected,
|
136
|
+
onReplace,
|
137
|
+
mergeBlocks,
|
138
|
+
} = props;
|
139
|
+
const {
|
140
|
+
borderRadius,
|
141
|
+
linkTarget,
|
142
|
+
placeholder,
|
143
|
+
rel,
|
144
|
+
text,
|
145
|
+
url,
|
146
|
+
} = attributes;
|
147
|
+
const onSetLinkRel = useCallback(
|
148
|
+
( value ) => {
|
149
|
+
setAttributes( { rel: value } );
|
150
|
+
},
|
151
|
+
[ setAttributes ]
|
152
|
+
);
|
153
|
+
|
154
|
+
const onToggleOpenInNewTab = useCallback(
|
155
|
+
( value ) => {
|
156
|
+
const newLinkTarget = value ? '_blank' : undefined;
|
157
|
+
|
158
|
+
let updatedRel = rel;
|
159
|
+
if ( newLinkTarget && ! rel ) {
|
160
|
+
updatedRel = NEW_TAB_REL;
|
161
|
+
} else if ( ! newLinkTarget && rel === NEW_TAB_REL ) {
|
162
|
+
updatedRel = undefined;
|
163
|
+
}
|
164
|
+
|
165
|
+
setAttributes( {
|
166
|
+
linkTarget: newLinkTarget,
|
167
|
+
rel: updatedRel,
|
168
|
+
} );
|
169
|
+
},
|
170
|
+
[ rel, setAttributes ]
|
171
|
+
);
|
172
|
+
|
173
|
+
// const colorProps = getColorAndStyleProps( attributes );
|
174
|
+
|
175
|
+
return (
|
176
|
+
<>
|
177
|
+
<Block.div>
|
178
|
+
<RichText
|
179
|
+
placeholder={ placeholder || __( 'Add text…' ) }
|
180
|
+
value={ text }
|
181
|
+
onChange={ ( value ) => setAttributes( { text: value } ) }
|
182
|
+
withoutInteractiveFormatting
|
183
|
+
className={ classnames(
|
184
|
+
className,
|
185
|
+
'wp-block-button__link',
|
186
|
+
// colorProps.className,
|
187
|
+
// {
|
188
|
+
// 'no-border-radius': borderRadius === 0,
|
189
|
+
// }
|
190
|
+
) }
|
191
|
+
onSplit={ ( value ) =>
|
192
|
+
createBlock( 'core/button', {
|
193
|
+
...attributes,
|
194
|
+
text: value,
|
195
|
+
} )
|
196
|
+
}
|
197
|
+
onReplace={ onReplace }
|
198
|
+
onMerge={ mergeBlocks }
|
199
|
+
identifier="text"
|
200
|
+
/>
|
201
|
+
</Block.div>
|
202
|
+
<URLPicker
|
203
|
+
url={ url }
|
204
|
+
setAttributes={ setAttributes }
|
205
|
+
isSelected={ isSelected }
|
206
|
+
opensInNewTab={ linkTarget === '_blank' }
|
207
|
+
onToggleOpenInNewTab={ onToggleOpenInNewTab }
|
208
|
+
/>
|
209
|
+
<InspectorControls>
|
210
|
+
<PanelBody title={ 'Additional styles' }>
|
211
|
+
<ToggleControl
|
212
|
+
label={ 'Hollow' }
|
213
|
+
onChange={ content => setAttributes({ hasHollowStyle: content }) }
|
214
|
+
checked={ attributes.hasHollowStyle }
|
215
|
+
/>
|
216
|
+
<ToggleControl
|
217
|
+
label={ 'Large' }
|
218
|
+
onChange={ content => setAttributes({ hasLargeStyle: content }) }
|
219
|
+
checked={ attributes.hasLargeStyle }
|
220
|
+
/>
|
221
|
+
</PanelBody>
|
222
|
+
|
223
|
+
<PanelBody title={ __( 'Link settings' ) }>
|
224
|
+
<ToggleControl
|
225
|
+
label={ __( 'Open in new tab' ) }
|
226
|
+
onChange={ onToggleOpenInNewTab }
|
227
|
+
checked={ linkTarget === '_blank' }
|
228
|
+
/>
|
229
|
+
<TextControl
|
230
|
+
label={ __( 'Link rel' ) }
|
231
|
+
value={ rel || '' }
|
232
|
+
onChange={ onSetLinkRel }
|
233
|
+
/>
|
234
|
+
</PanelBody>
|
235
|
+
</InspectorControls>
|
236
|
+
</>
|
237
|
+
);
|
238
|
+
}
|
239
|
+
|
240
|
+
export default ButtonEdit;
|