block_editor 0.1.3 → 1.0.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.
Files changed (68) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +35 -14
  3. data/app/assets/images/block_editor/contact-form-block.svg +1 -0
  4. data/app/assets/stylesheets/block_editor/_utilities.scss +16 -0
  5. data/app/assets/stylesheets/block_editor/backend.scss +70 -2
  6. data/app/assets/stylesheets/block_editor/blocks/_backend.scss +7 -0
  7. data/app/assets/stylesheets/block_editor/blocks/_frontend.scss +11 -0
  8. data/app/assets/stylesheets/block_editor/blocks/be-accordion/_frontend.scss +3 -0
  9. data/app/assets/stylesheets/block_editor/blocks/be-alert/_frontend.scss +13 -0
  10. data/app/assets/stylesheets/block_editor/blocks/be-card/_backend.scss +7 -0
  11. data/app/assets/stylesheets/block_editor/{backend/blocks.scss → blocks/be-card/_frontend.scss} +0 -0
  12. data/app/assets/stylesheets/block_editor/blocks/be-contact-form/_backend.scss +22 -0
  13. data/app/assets/stylesheets/block_editor/blocks/be-cover/_backend.scss +8 -0
  14. data/app/assets/stylesheets/block_editor/blocks/be-cover/_frontend.scss +37 -0
  15. data/app/assets/stylesheets/block_editor/blocks/block/_backend.scss +11 -0
  16. data/app/assets/stylesheets/block_editor/blocks/button/_frontend.scss +46 -0
  17. data/app/assets/stylesheets/block_editor/blocks/buttons/_backend.scss +10 -0
  18. data/app/assets/stylesheets/block_editor/blocks/buttons/_frontend.scss +3 -0
  19. data/app/assets/stylesheets/block_editor/blocks/column/_frontend.scss +18 -0
  20. data/app/assets/stylesheets/block_editor/blocks/columns/_backend.scss +8 -0
  21. data/app/assets/stylesheets/block_editor/blocks/columns/_frontend.scss +14 -0
  22. data/app/assets/stylesheets/block_editor/blocks/image/_backend.scss +10 -0
  23. data/app/assets/stylesheets/block_editor/blocks/image/_frontend.scss +21 -0
  24. data/app/assets/stylesheets/block_editor/blocks/seperator/_frontend.scss +19 -0
  25. data/app/assets/stylesheets/block_editor/blocks/table/_frontend.scss +67 -0
  26. data/app/assets/stylesheets/block_editor/host_app/_variables.scss +1 -0
  27. data/app/assets/stylesheets/block_editor/host_app/blocks/_backend.scss +1 -0
  28. data/app/assets/stylesheets/block_editor/host_app/blocks/_frontend.scss +1 -0
  29. data/app/javascript/block_editor/blocks/be-accordion/index.js +108 -0
  30. data/app/javascript/block_editor/blocks/be-alert/index.js +51 -0
  31. data/app/javascript/block_editor/blocks/be-card/index.js +205 -0
  32. data/app/javascript/block_editor/blocks/be-contact-form/index.js +24 -0
  33. data/app/javascript/block_editor/blocks/be-cover/index.js +135 -0
  34. data/app/javascript/block_editor/blocks/block/edit-panel/index.js +132 -0
  35. data/app/javascript/block_editor/blocks/block/edit.js +163 -0
  36. data/app/javascript/block_editor/blocks/button/edit.js +0 -13
  37. data/app/javascript/block_editor/blocks/index.js +51 -102
  38. data/app/javascript/block_editor/components/block-editor/index.js +107 -36
  39. data/app/javascript/block_editor/components/block-editor/popover-wrapper.js +60 -0
  40. data/app/javascript/block_editor/components/block-editor/styles.scss +0 -11
  41. data/app/javascript/block_editor/components/header/index.js +28 -6
  42. data/app/javascript/block_editor/components/header/redo.js +1 -1
  43. data/app/javascript/block_editor/components/header/styles.scss +12 -11
  44. data/app/javascript/block_editor/components/media-upload/index.js +3 -3
  45. data/app/javascript/block_editor/components/sidebar/index.js +1 -3
  46. data/app/javascript/block_editor/components/sidebar/styles.scss +35 -35
  47. data/app/javascript/block_editor/stores/actions.js +12 -0
  48. data/app/javascript/block_editor/stores/reducer.js +23 -3
  49. data/app/javascript/block_editor/stores/selectors.js +14 -3
  50. data/app/javascript/controllers/block_editor_controller.jsx +15 -8
  51. data/app/javascript/controllers/index.js +2 -0
  52. data/app/javascript/packs/block_editor/application.scss +70 -26
  53. data/app/models/block_editor/block_list.rb +45 -1
  54. data/app/models/block_editor/block_list_connection.rb +6 -0
  55. data/app/views/block_editor/blocks/be/contact-form/_block.html +3 -0
  56. data/db/migrate/20210506220328_create_block_list_connections.rb +8 -0
  57. data/lib/block_editor.rb +3 -1
  58. data/lib/block_editor/block_list_renderer.rb +12 -6
  59. data/lib/block_editor/blocks/base.rb +1 -1
  60. data/lib/block_editor/blocks/contact_form.rb +11 -0
  61. data/lib/block_editor/blocks/reusable.rb +16 -0
  62. data/lib/block_editor/version.rb +1 -1
  63. data/package.json +16 -7
  64. data/yarn.lock +727 -530
  65. metadata +42 -8
  66. data/app/assets/stylesheets/block_editor/frontend.scss +0 -1
  67. data/app/assets/stylesheets/block_editor/frontend/blocks.scss +0 -0
  68. data/app/javascript/block_editor/blocks/image/edit.js +0 -656
@@ -0,0 +1,14 @@
1
+ .wp-block-columns {
2
+ --#{$variable-prefix}gutter-x: #{$grid-gutter-width};
3
+ --#{$variable-prefix}gutter-y: 0;
4
+ display: flex;
5
+ margin-top: calc(var(--#{$variable-prefix}gutter-y) * -1); // stylelint-disable-line function-disallowed-list
6
+ margin-right: calc(var(--#{$variable-prefix}gutter-x) / -2); // stylelint-disable-line function-disallowed-list
7
+ margin-left: calc(var(--#{$variable-prefix}gutter-x) / -2); // stylelint-disable-line function-disallowed-list
8
+
9
+ &:not(.is-style-no-stack) {
10
+ @include media-breakpoint-down(lg) {
11
+ display: block;
12
+ }
13
+ }
14
+ }
@@ -0,0 +1,10 @@
1
+ .block-editor-block-list__block[data-type="core/image"] {
2
+ .block-editor-media-placeholder__url-input-container,
3
+ .components-form-file-upload {
4
+ display: none;
5
+ }
6
+ }
7
+ .components-dropdown-menu__toggle[aria-label="Change alignment"] {
8
+ display: none !important;
9
+ }
10
+
@@ -0,0 +1,21 @@
1
+ .wp-block-image {
2
+ margin-bottom: $paragraph-margin-bottom;
3
+
4
+ img {
5
+ max-width: 100%;
6
+ }
7
+ figcaption {
8
+ margin-top: 5px;
9
+ font-size: 0.9rem;
10
+ }
11
+ &.is-style-padded {
12
+ max-width: 75%;
13
+ margin-left: auto;
14
+ margin-right: auto;
15
+ }
16
+ &.is-style-rounded {
17
+ img {
18
+ border-radius: $border-radius;
19
+ }
20
+ }
21
+ }
@@ -0,0 +1,19 @@
1
+ .wp-block-separator {
2
+ &.is-style-dots {
3
+ background: none !important;
4
+ border: none;
5
+ text-align: center;
6
+ max-width: none;
7
+ line-height: 1;
8
+ height: 1.2*$spacer !important;
9
+ opacity: 1;
10
+ &:before{
11
+ content: "\00b7 \00b7 \00b7";
12
+ font-size: 1.2*$spacer;
13
+ letter-spacing: 2em;
14
+ padding-left: 2em;
15
+ font-family: serif;
16
+ color: $black;
17
+ }
18
+ }
19
+ }
@@ -0,0 +1,67 @@
1
+ .wp-block-table{
2
+ margin-bottom: $paragraph-margin-bottom;
3
+ overflow-x: auto;
4
+ table {
5
+ --#{$variable-prefix}table-bg: #{$table-bg};
6
+ --#{$variable-prefix}table-striped-color: #{$table-striped-color};
7
+ --#{$variable-prefix}table-striped-bg: #{$table-striped-bg};
8
+ --#{$variable-prefix}table-active-color: #{$table-active-color};
9
+ --#{$variable-prefix}table-active-bg: #{$table-active-bg};
10
+ --#{$variable-prefix}table-hover-color: #{$table-hover-color};
11
+ --#{$variable-prefix}table-hover-bg: #{$table-hover-bg};
12
+
13
+ width: 100%;
14
+ color: $table-color;
15
+ vertical-align: $table-cell-vertical-align;
16
+ border-color: $table-border-color;
17
+ overflow-x: auto;
18
+ -webkit-overflow-scrolling: touch;
19
+ > :not(caption) > * > * {
20
+ padding: $table-cell-padding-y $table-cell-padding-x;
21
+ background-color: var(--#{$variable-prefix}table-bg);
22
+ border-bottom-width: $table-border-width;
23
+ box-shadow: inset 0 0 0 9999px var(--#{$variable-prefix}table-accent-bg);
24
+ }
25
+
26
+ > tbody {
27
+ vertical-align: inherit;
28
+ }
29
+ > tbody > tr > th {
30
+ text-align: center;
31
+ }
32
+
33
+ > thead {
34
+ vertical-align: bottom;
35
+ background: $secondary;
36
+ color: $white;
37
+ }
38
+ > thead > tr > th:first-child{
39
+ text-align: center;
40
+ }
41
+
42
+ // Highlight border color between thead, tbody and tfoot.
43
+ > :not(:last-child) > :last-child > * {
44
+ border-bottom-color: $table-group-separator-color;
45
+ }
46
+ //border
47
+ > :not(caption) > * {
48
+ border-width: $table-border-width 0;
49
+
50
+ // stylelint-disable-next-line selector-max-universal
51
+ > * {
52
+ border-width: 0 $table-border-width;
53
+ }
54
+ }
55
+ }
56
+
57
+ > figcaption {
58
+ margin-top: $paragraph-margin-bottom / 4;
59
+ }
60
+
61
+ &.is-style-striped {
62
+ table > tbody > tr:nth-of-type(#{$table-striped-order}) {
63
+ --#{$variable-prefix}table-accent-bg: var(--#{$variable-prefix}table-striped-bg);
64
+ color: var(--#{$variable-prefix}table-striped-color);
65
+ }
66
+ }
67
+ }
@@ -0,0 +1 @@
1
+ // Override this file if you want to include any styling before default Block Editor styles are loaded. This would be a good place to add variables to customise Bootstrap
@@ -0,0 +1 @@
1
+ // Override this file if you want to include backend block styles to the Block Editor and not have to worry about losing any base styles
@@ -0,0 +1 @@
1
+ // Override this file if you want to include frontend block styles to the Block Editor and not have to worry about losing any base styles
@@ -0,0 +1,108 @@
1
+ import React from 'react';
2
+ import ReactDOM from 'react-dom';
3
+ import classnames from 'classnames';
4
+
5
+ import { PanelBody, ToggleControl } from '@wordpress/components';
6
+ import { InnerBlocks, InspectorControls, PlainText } from '@wordpress/block-editor'
7
+ import { box as icon } from '@wordpress/icons';
8
+
9
+ const name = 'be/accordion';
10
+
11
+ export { name };
12
+
13
+ export const settings = {
14
+ title: 'Accordion',
15
+ description: 'Accordions are elements that help you organize and navigate multiple documents in a single container.',
16
+ icon,
17
+ category: 'layout',
18
+ attributes: {
19
+ blockId: {
20
+ type: 'string'
21
+ },
22
+ title: {
23
+ source: 'text',
24
+ selector: '.accordion-button'
25
+ },
26
+ isOpenByDefault: {
27
+ type: 'boolean',
28
+ default: true
29
+ }
30
+ },
31
+ example: {
32
+ attributes: {
33
+ title: 'Open by default accordion'
34
+ },
35
+ innerBlocks: [
36
+ {
37
+ name: 'core/paragraph',
38
+ attributes: {
39
+ content: 'Use an accordion to structure and optionally collapse content'
40
+ }
41
+ }
42
+ ]
43
+ },
44
+ edit({clientId, attributes, className, setAttributes, isSelected}) {
45
+ const { blockId } = attributes;
46
+ if ( ! blockId ) {
47
+ setAttributes( { blockId: `id-${clientId}` } );
48
+ } else if ( blockId != clientId ) {
49
+ setAttributes( { blockId: `id-${clientId}` } );
50
+ }
51
+
52
+ // TODO: Update this to check if this OR any of the innerblocks are selected
53
+ // let inlineStyle = (isSelected || attributes.isOpenByDefault) ? { display: 'block' } : {};
54
+ let inlineStyle = { display: 'block' };
55
+
56
+ return [
57
+ <InspectorControls>
58
+ <PanelBody title={ 'Accordion settings' }>
59
+ <ToggleControl
60
+ label={ 'Open by default' }
61
+ onChange={ content => setAttributes({ isOpenByDefault: content }) }
62
+ checked={ attributes.isOpenByDefault }
63
+ />
64
+
65
+ </PanelBody>
66
+ </InspectorControls>,
67
+
68
+ <div className="wp-block-be-accordion accordion">
69
+ <div className="accordion-item">
70
+ <h2 className="accordion-header">
71
+ <PlainText
72
+ onChange={ content => setAttributes({ title: content }) }
73
+ value={ attributes.title }
74
+ placeholder="Your accordion title"
75
+ className="accordion-button"
76
+ />
77
+ </h2>
78
+ <div className="accordion-collapse collapse show">
79
+ <div className="accordion-body" style={ inlineStyle }>
80
+ <InnerBlocks/>
81
+ </div>
82
+ </div>
83
+ </div>
84
+ </div>
85
+ ];
86
+ },
87
+ save({ attributes }) {
88
+ let buttonVisibilityClass = attributes.isOpenByDefault ? "collapsed" : "";
89
+ let accordionVisibilityClass = attributes.isOpenByDefault ? "show" : "";
90
+
91
+ return (
92
+ <div className="wp-block-be-accordion accordion">
93
+ <div className="accordion-item">
94
+ <h2 className="accordion-header">
95
+ <button className={ "accordion-button " + buttonVisibilityClass } type="button" data-bs-toggle="collapse" data-bs-target={ "#" + attributes.blockId }>
96
+ { attributes.title }
97
+ </button>
98
+ </h2>
99
+ <div id={attributes.blockId} className={ "accordion-collapse collapse " + accordionVisibilityClass }>
100
+ <div className="accordion-body">
101
+ <InnerBlocks.Content />
102
+ </div>
103
+ </div>
104
+ </div>
105
+ </div>
106
+ );
107
+ }
108
+ };
@@ -0,0 +1,51 @@
1
+ import React from 'react'
2
+ import ReactDOM from 'react-dom'
3
+
4
+ import {
5
+ InnerBlocks
6
+ } from '@wordpress/block-editor';
7
+ import { registerBlockStyle } from '@wordpress/blocks';
8
+ import { createBlock } from '@wordpress/blocks';
9
+ import { rawHandler } from '@wordpress/blocks';
10
+ import { box as icon } from '@wordpress/icons';
11
+
12
+ const name = 'be/alert';
13
+
14
+ export { name };
15
+
16
+ export const settings = {
17
+ title: 'Callout (Alert)',
18
+ description: 'Container to help draw attention to content.',
19
+ icon,
20
+ category: 'formatting',
21
+ styles: [
22
+ { name: 'primary', label: 'Primary', isDefault: true },
23
+ { name: 'secondary', label: 'Secondary' },
24
+ { name: 'success', label: 'Success' },
25
+ { name: 'danger', label: 'Danger' },
26
+ { name: 'warning', label: 'Warning' },
27
+ { name: 'info', label: 'Info' },
28
+ { name: 'light', label: 'Light' },
29
+ { name: 'dark', label: 'Dark' }
30
+ ],
31
+ example: {
32
+ innerBlocks: [
33
+ {
34
+ name: 'core/paragraph',
35
+ attributes: {
36
+ content: 'Use a callout to grab the users attention.'
37
+ }
38
+ }
39
+ ]
40
+ },
41
+ edit(props) {
42
+ return (
43
+ <div role="alert" className={ 'alert ' + props.className }>
44
+ <InnerBlocks/>
45
+ </div>
46
+ );
47
+ },
48
+ save() {
49
+ return <div role="alert" className='alert'><InnerBlocks.Content /></div>;
50
+ }
51
+ };
@@ -0,0 +1,205 @@
1
+ import React from 'react';
2
+ import ReactDOM from 'react-dom';
3
+
4
+ import {
5
+ InnerBlocks
6
+ } from '@wordpress/block-editor';
7
+ import { registerBlockStyle } from '@wordpress/blocks';
8
+ import { createBlock } from '@wordpress/blocks';
9
+ import { rawHandler } from '@wordpress/blocks';
10
+
11
+ import { TextControl, PanelBody, ToggleControl, Button } from '@wordpress/components';
12
+ import { InspectorControls, RichText, MediaUpload, PlainText } from '@wordpress/block-editor'
13
+ import { box as icon } from '@wordpress/icons';
14
+
15
+ const name = 'be/card';
16
+
17
+ export { name };
18
+
19
+ export const settings = {
20
+ title: 'Card',
21
+ description: 'Group a piece of content in an eye catching container.',
22
+ icon,
23
+ category: 'formatting',
24
+ example: {
25
+ attributes: {
26
+ title: 'Container example',
27
+ imageUrl: 'https://s.w.org/images/core/5.3/MtBlanc1.jpg',
28
+ }
29
+ },
30
+ attributes: {
31
+ title: {
32
+ source: 'text',
33
+ selector: '.card-title'
34
+ },
35
+ body: {
36
+ type: 'array',
37
+ source: 'children',
38
+ selector: '.card-content'
39
+ },
40
+ imageAlt: {
41
+ attribute: 'alt',
42
+ selector: '.card-img-top'
43
+ },
44
+ imageUrl: {
45
+ attribute: 'src',
46
+ selector: '.card-img-top'
47
+ },
48
+ hasCallToAction: {
49
+ type: 'boolean'
50
+ },
51
+ callToAction: {
52
+ type: 'text'
53
+ },
54
+ url: {
55
+ type: 'text'
56
+ },
57
+ openInNewTab: {
58
+ type: 'boolean'
59
+ }
60
+ },
61
+ edit({attributes, className, setAttributes, isSelected}) {
62
+ const getImageButton = (openEvent) => {
63
+ if(attributes.imageUrl) {
64
+ return (
65
+ <>
66
+ { isSelected &&
67
+ <Button
68
+ onClick={ openEvent }
69
+ className="button"
70
+ >
71
+ Edit
72
+ </Button>
73
+ }
74
+ <img
75
+ src={ attributes.imageUrl }
76
+ className="card-img-top"
77
+ />
78
+ </>
79
+ );
80
+ }
81
+ else {
82
+ return (
83
+ <div className="block-editor-image-placeholder">
84
+ <Button
85
+ onClick={ openEvent }
86
+ className="button button-large"
87
+ >
88
+ Pick an image
89
+ </Button>
90
+ </div>
91
+ );
92
+ }
93
+ };
94
+ return ([
95
+ <InspectorControls>
96
+ <PanelBody title='Card settings'>
97
+ <TextControl
98
+ label="URL"
99
+ value={ attributes.url }
100
+ onChange={ content => setAttributes({ url: content }) }
101
+ />
102
+ { attributes.url && (
103
+ <ToggleControl
104
+ label="Display Call To Action"
105
+ checked={ attributes.hasCallToAction }
106
+ onChange={ content => setAttributes({ hasCallToAction: content }) }
107
+ />
108
+ )}
109
+ { attributes.url && (
110
+ <ToggleControl
111
+ label="Open in new Tab?"
112
+ checked={ attributes.openInNewTab }
113
+ onChange={ content => setAttributes({ openInNewTab: content }) }
114
+ />
115
+ )}
116
+ </PanelBody>
117
+ </InspectorControls>,
118
+ <div className={ 'card ' + className }>
119
+ <MediaUpload
120
+ onSelect={ media => { setAttributes({ imageAlt: media.alt, imageUrl: media.url }); } }
121
+ type="image"
122
+ value={ attributes.imageID }
123
+ render={ ({ open }) => getImageButton(open) }
124
+ />
125
+ <div className='card-body'>
126
+ <PlainText
127
+ onChange={ content => setAttributes({ title: content }) }
128
+ value={ attributes.title }
129
+ placeholder="Your card title"
130
+ className="card-title h2"
131
+ />
132
+ <RichText
133
+ onChange={ content => setAttributes({ body: content }) }
134
+ value={ attributes.body }
135
+ multiline="p"
136
+ placeholder="Your card text"
137
+ />
138
+ </div>
139
+ { attributes.hasCallToAction && attributes.url &&
140
+ <PlainText
141
+ onChange={ content => setAttributes({ callToAction: content }) }
142
+ value={ attributes.callToAction }
143
+ placeholder="Your Call To Action"
144
+ className="card-link"
145
+ />
146
+ }
147
+ </div>
148
+ ]);
149
+ },
150
+ save({ attributes }) {
151
+ const linkTarget = (attributes.openInNewTab) ? '_blank' : '_self';
152
+ const cardImage = (src, alt) => {
153
+ if(!src) return null;
154
+
155
+ return (
156
+ <img
157
+ className="card-img-top"
158
+ src={ src }
159
+ alt={ alt }
160
+ />
161
+ );
162
+ }
163
+
164
+ return (
165
+ <div className="card">
166
+ { attributes.url ? (
167
+ <a
168
+ href={ attributes.url }
169
+ target= { linkTarget }
170
+ >
171
+ { cardImage(attributes.imageUrl, attributes.imageAlt) }
172
+ </a>
173
+ ) : (
174
+ cardImage(attributes.imageUrl, attributes.imageAlt)
175
+ )}
176
+ <div className="card-body">
177
+ <h3 className="card-title">
178
+ { attributes.url ? (
179
+ <a
180
+ href={ attributes.url }
181
+ target= { linkTarget }
182
+ >
183
+ { attributes.title }
184
+ </a>
185
+ ) : (
186
+ attributes.title
187
+ )}
188
+ </h3>
189
+ <div className='card-content'>
190
+ { attributes.body }
191
+ </div>
192
+ </div>
193
+ { attributes.hasCallToAction && attributes.url &&
194
+ <RichText.Content
195
+ tagName="a"
196
+ className='card-link'
197
+ href={ attributes.url }
198
+ target= { linkTarget }
199
+ value={ attributes.callToAction }
200
+ />
201
+ }
202
+ </div>
203
+ );
204
+ }
205
+ };