@webikon/webentor-core 0.9.12
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/.husky/pre-commit +40 -0
- package/.prettierrc.js +5 -0
- package/CHANGELOG.md +88 -0
- package/LICENCE.md +7 -0
- package/README.md +26 -0
- package/core-js/_alpine.ts +20 -0
- package/core-js/_slider.ts +232 -0
- package/core-js/_utils.ts +126 -0
- package/core-js/blocks-components/block-appender.tsx +36 -0
- package/core-js/blocks-components/button.tsx +424 -0
- package/core-js/blocks-components/custom-image-sizes-panel.tsx +197 -0
- package/core-js/blocks-components/index.ts +4 -0
- package/core-js/blocks-components/typography-picker-select.tsx +31 -0
- package/core-js/blocks-filters/_filter-core-typography.tsx +108 -0
- package/core-js/blocks-filters/_slider-settings.tsx +283 -0
- package/core-js/blocks-filters/index.ts +3 -0
- package/core-js/blocks-filters/responsive-settings/components/DisabledSliderInfo.tsx +10 -0
- package/core-js/blocks-filters/responsive-settings/constants.ts +11 -0
- package/core-js/blocks-filters/responsive-settings/index.tsx +196 -0
- package/core-js/blocks-filters/responsive-settings/settings/block-link/index.ts +1 -0
- package/core-js/blocks-filters/responsive-settings/settings/block-link/panel.tsx +47 -0
- package/core-js/blocks-filters/responsive-settings/settings/border/border/index.tsx +1 -0
- package/core-js/blocks-filters/responsive-settings/settings/border/border/properties.ts +27 -0
- package/core-js/blocks-filters/responsive-settings/settings/border/border/settings.tsx +310 -0
- package/core-js/blocks-filters/responsive-settings/settings/border/border-radius/index.tsx +1 -0
- package/core-js/blocks-filters/responsive-settings/settings/border/border-radius/properties.ts +31 -0
- package/core-js/blocks-filters/responsive-settings/settings/border/border-radius/settings.tsx +211 -0
- package/core-js/blocks-filters/responsive-settings/settings/border/index.ts +1 -0
- package/core-js/blocks-filters/responsive-settings/settings/border/panel.tsx +54 -0
- package/core-js/blocks-filters/responsive-settings/settings/container/display/index.ts +2 -0
- package/core-js/blocks-filters/responsive-settings/settings/container/display/properties.ts +167 -0
- package/core-js/blocks-filters/responsive-settings/settings/container/display/settings.tsx +73 -0
- package/core-js/blocks-filters/responsive-settings/settings/container/flexbox/index.ts +2 -0
- package/core-js/blocks-filters/responsive-settings/settings/container/flexbox/properties.ts +187 -0
- package/core-js/blocks-filters/responsive-settings/settings/container/flexbox/settings.tsx +131 -0
- package/core-js/blocks-filters/responsive-settings/settings/container/grid/index.ts +2 -0
- package/core-js/blocks-filters/responsive-settings/settings/container/grid/properties.ts +187 -0
- package/core-js/blocks-filters/responsive-settings/settings/container/grid/settings.tsx +132 -0
- package/core-js/blocks-filters/responsive-settings/settings/container/index.ts +4 -0
- package/core-js/blocks-filters/responsive-settings/settings/container/panel.tsx +92 -0
- package/core-js/blocks-filters/responsive-settings/settings/spacing/index.ts +3 -0
- package/core-js/blocks-filters/responsive-settings/settings/spacing/panel.tsx +45 -0
- package/core-js/blocks-filters/responsive-settings/settings/spacing/properties.ts +74 -0
- package/core-js/blocks-filters/responsive-settings/settings/spacing/settings.tsx +85 -0
- package/core-js/blocks-filters/responsive-settings/types/index.ts +68 -0
- package/core-js/blocks-filters/responsive-settings/utils.ts +321 -0
- package/core-js/blocks-utils/_use-block-parent.ts +27 -0
- package/core-js/blocks-utils/_use-post-types.ts +43 -0
- package/core-js/blocks-utils/_use-taxonomies.ts +29 -0
- package/core-js/blocks-utils/index.ts +3 -0
- package/core-js/config/webentor-config.ts +718 -0
- package/core-js/index.ts +14 -0
- package/core-js/types/_block-components.ts +7 -0
- package/core-js/types/_webentor-config.ts +182 -0
- package/package.json +98 -0
- package/resources/blocks/e-accordion/block.json +34 -0
- package/resources/blocks/e-accordion/e-accordion.block.tsx +125 -0
- package/resources/blocks/e-accordion/script.ts +1 -0
- package/resources/blocks/e-accordion/style.css +8 -0
- package/resources/blocks/e-accordion-group/block.json +56 -0
- package/resources/blocks/e-accordion-group/e-accordion-group.block.tsx +99 -0
- package/resources/blocks/e-breadcrumbs/block.json +41 -0
- package/resources/blocks/e-breadcrumbs/e-breadcrumbs.block.tsx +53 -0
- package/resources/blocks/e-button/block.json +32 -0
- package/resources/blocks/e-button/e-button.block.tsx +55 -0
- package/resources/blocks/e-gallery/block.json +90 -0
- package/resources/blocks/e-gallery/e-gallery.block.tsx +316 -0
- package/resources/blocks/e-icon-picker/block.json +37 -0
- package/resources/blocks/e-icon-picker/e-icon-picker.block.tsx +230 -0
- package/resources/blocks/e-icon-picker/style.css +17 -0
- package/resources/blocks/e-image/block.json +78 -0
- package/resources/blocks/e-image/e-image.block.tsx +331 -0
- package/resources/blocks/e-picker-query-loop/block.json +25 -0
- package/resources/blocks/e-picker-query-loop/e-picker-query-loop.block.tsx +189 -0
- package/resources/blocks/e-post-template/block.json +25 -0
- package/resources/blocks/e-post-template/e-post-template.block.tsx +100 -0
- package/resources/blocks/e-query-loop/block.json +36 -0
- package/resources/blocks/e-query-loop/constants.tsx +8 -0
- package/resources/blocks/e-query-loop/e-query-loop.block.tsx +270 -0
- package/resources/blocks/e-query-loop/taxonomy-controls.tsx +184 -0
- package/resources/blocks/e-slider/block.json +42 -0
- package/resources/blocks/e-slider/e-slider.block.tsx +100 -0
- package/resources/blocks/e-svg/block.json +37 -0
- package/resources/blocks/e-svg/e-svg.block.tsx +156 -0
- package/resources/blocks/e-tab-container/block.json +49 -0
- package/resources/blocks/e-tab-container/e-tab-container.block.tsx +123 -0
- package/resources/blocks/e-table/block.json +30 -0
- package/resources/blocks/e-table/e-table.block.tsx +120 -0
- package/resources/blocks/e-table/script.ts +48 -0
- package/resources/blocks/e-table-cell/block.json +40 -0
- package/resources/blocks/e-table-cell/e-table-cell.block.tsx +180 -0
- package/resources/blocks/e-table-row/block.json +28 -0
- package/resources/blocks/e-table-row/e-table-row.block.tsx +118 -0
- package/resources/blocks/e-tabs/block.json +27 -0
- package/resources/blocks/e-tabs/e-tabs.block.tsx +90 -0
- package/resources/blocks/l-404/block.json +51 -0
- package/resources/blocks/l-404/l-404.block.tsx +75 -0
- package/resources/blocks/l-flexible-container/block.json +34 -0
- package/resources/blocks/l-flexible-container/l-flexible-container.block.tsx +97 -0
- package/resources/blocks/l-footer/block.json +23 -0
- package/resources/blocks/l-footer/l-footer.block.tsx +51 -0
- package/resources/blocks/l-formatted-content/block.json +28 -0
- package/resources/blocks/l-formatted-content/l-formatted-content.block.tsx +97 -0
- package/resources/blocks/l-header/block.json +26 -0
- package/resources/blocks/l-header/l-header.block.tsx +100 -0
- package/resources/blocks/l-mobile-nav/block.json +15 -0
- package/resources/blocks/l-mobile-nav/l-mobile-nav.block.tsx +56 -0
- package/resources/blocks/l-mobile-nav/style.css +54 -0
- package/resources/blocks/l-nav-menu/block.json +27 -0
- package/resources/blocks/l-nav-menu/l-nav-menu.block.tsx +109 -0
- package/resources/blocks/l-nav-menu/style.css +134 -0
- package/resources/blocks/l-post-card/block.json +13 -0
- package/resources/blocks/l-post-card/l-post-card.block.tsx +52 -0
- package/resources/blocks/l-section/block.json +89 -0
- package/resources/blocks/l-section/l-section.block.tsx +316 -0
- package/resources/blocks/l-site-logo/block.json +15 -0
- package/resources/blocks/l-site-logo/l-site-logo.block.tsx +54 -0
- package/resources/core-components/slider/slider.script.ts +11 -0
- package/resources/core-components/slider/slider.style.css +134 -0
- package/resources/scripts/editor.ts +29 -0
- package/resources/styles/app.css +21 -0
- package/resources/styles/common/_editor.css +86 -0
- package/resources/styles/common/_form.css +83 -0
- package/resources/styles/common/_global.css +73 -0
- package/resources/styles/common/_theme.css +75 -0
- package/resources/styles/common/_utilities.css +33 -0
- package/resources/styles/common/_wordpress.css +110 -0
- package/resources/styles/components/_table.css +102 -0
- package/resources/styles/editor.css +16 -0
- package/resources/styles/partials/.gitkeep +0 -0
- package/resources/styles/partials/_header.css +21 -0
- package/resources/styles/partials/_pagination.css +35 -0
|
@@ -0,0 +1,189 @@
|
|
|
1
|
+
import { ContentPicker } from '@10up/block-components';
|
|
2
|
+
import {
|
|
3
|
+
InnerBlocks,
|
|
4
|
+
InspectorControls,
|
|
5
|
+
useBlockProps,
|
|
6
|
+
useInnerBlocksProps,
|
|
7
|
+
} from '@wordpress/block-editor';
|
|
8
|
+
import {
|
|
9
|
+
BlockEditProps,
|
|
10
|
+
registerBlockType,
|
|
11
|
+
TemplateArray,
|
|
12
|
+
} from '@wordpress/blocks';
|
|
13
|
+
import {
|
|
14
|
+
Notice,
|
|
15
|
+
PanelBody,
|
|
16
|
+
SelectControl,
|
|
17
|
+
TextControl,
|
|
18
|
+
} from '@wordpress/components';
|
|
19
|
+
import { applyFilters } from '@wordpress/hooks';
|
|
20
|
+
import { __ } from '@wordpress/i18n';
|
|
21
|
+
|
|
22
|
+
import { useBlockParent } from '@webentorCore/blocks-utils/_use-block-parent';
|
|
23
|
+
import { usePostTypes } from '@webentorCore/blocks-utils/_use-post-types';
|
|
24
|
+
|
|
25
|
+
import block from './block.json';
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Edit component.
|
|
29
|
+
* See https://wordpress.org/gutenberg/handbook/designers-developers/developers/block-api/block-edit-save/#edit
|
|
30
|
+
*
|
|
31
|
+
* @param {object} props The block props.
|
|
32
|
+
* @returns {Function} Render the edit screen
|
|
33
|
+
*/
|
|
34
|
+
|
|
35
|
+
type AttributesType = {
|
|
36
|
+
coverImage: string;
|
|
37
|
+
query: {
|
|
38
|
+
postType: string[];
|
|
39
|
+
posts: [];
|
|
40
|
+
queryId: string;
|
|
41
|
+
};
|
|
42
|
+
template?: TemplateArray;
|
|
43
|
+
};
|
|
44
|
+
|
|
45
|
+
const BlockEdit: React.FC<BlockEditProps<AttributesType>> = (props) => {
|
|
46
|
+
const { attributes, setAttributes } = props;
|
|
47
|
+
const { query } = attributes;
|
|
48
|
+
const { postType, posts, queryId } = query;
|
|
49
|
+
|
|
50
|
+
const blockProps = useBlockProps();
|
|
51
|
+
const parentBlockProps = useBlockParent();
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* Filter allowed blocks used in webentor/e-query-loop inner block
|
|
55
|
+
*/
|
|
56
|
+
const allowedBlocks = applyFilters(
|
|
57
|
+
'webentor.core.e-picker-query-loop.allowedBlocks',
|
|
58
|
+
// Allow only singular 'e-post-template' block to be added as child.
|
|
59
|
+
['webentor/e-post-template'],
|
|
60
|
+
blockProps,
|
|
61
|
+
parentBlockProps,
|
|
62
|
+
) as string[];
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* Filter template used in webentor/e-query-loop inner block
|
|
66
|
+
*/
|
|
67
|
+
const defaultTemplate: TemplateArray = attributes?.template ?? [
|
|
68
|
+
['webentor/e-post-template', ['webentor/l-post-card']],
|
|
69
|
+
];
|
|
70
|
+
const template = applyFilters(
|
|
71
|
+
'webentor.core.e-picker-query-loop.template',
|
|
72
|
+
defaultTemplate,
|
|
73
|
+
blockProps,
|
|
74
|
+
parentBlockProps,
|
|
75
|
+
) as TemplateArray;
|
|
76
|
+
|
|
77
|
+
const { children, ...innerBlocksProps } = useInnerBlocksProps(blockProps, {
|
|
78
|
+
allowedBlocks,
|
|
79
|
+
template,
|
|
80
|
+
templateLock: 'all',
|
|
81
|
+
});
|
|
82
|
+
|
|
83
|
+
const { postTypesSelectOptions } = usePostTypes();
|
|
84
|
+
|
|
85
|
+
const setQuery = (newQuery) =>
|
|
86
|
+
setAttributes({ query: { ...query, ...newQuery } });
|
|
87
|
+
|
|
88
|
+
const onPostTypeChange = (newValue) => {
|
|
89
|
+
const updateQuery = { postType: newValue };
|
|
90
|
+
|
|
91
|
+
setQuery(updateQuery);
|
|
92
|
+
};
|
|
93
|
+
|
|
94
|
+
// Preview image for block inserter
|
|
95
|
+
if (attributes.coverImage) {
|
|
96
|
+
return <img src={attributes.coverImage} width="468" />;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
return (
|
|
100
|
+
<>
|
|
101
|
+
<InspectorControls>
|
|
102
|
+
<PanelBody title="Loop Settings" initialOpen={true}>
|
|
103
|
+
{/* TODO: Maybe rework to nicer UI */}
|
|
104
|
+
<SelectControl
|
|
105
|
+
__nextHasNoMarginBottom
|
|
106
|
+
options={postTypesSelectOptions}
|
|
107
|
+
value={Array.isArray(postType) ? postType : [postType]}
|
|
108
|
+
label={__('Post type')}
|
|
109
|
+
multiple
|
|
110
|
+
onChange={onPostTypeChange}
|
|
111
|
+
help={__(
|
|
112
|
+
'First select post type(s) from which you would be able to pick posts',
|
|
113
|
+
'webentor',
|
|
114
|
+
)}
|
|
115
|
+
/>
|
|
116
|
+
|
|
117
|
+
<div className="wbtr:mb-3 wbtr:w-full wbtr:border wbtr:border-editor-border wbtr:p-2">
|
|
118
|
+
<p>
|
|
119
|
+
{__('Posts which would be displayed in the loop', 'webentor')}
|
|
120
|
+
</p>
|
|
121
|
+
{postType?.length > 0 ? (
|
|
122
|
+
<ContentPicker
|
|
123
|
+
onPickChange={(pickedContent) => {
|
|
124
|
+
setQuery({
|
|
125
|
+
posts: pickedContent,
|
|
126
|
+
});
|
|
127
|
+
}}
|
|
128
|
+
content={posts || []}
|
|
129
|
+
mode="post"
|
|
130
|
+
maxContentItems={20}
|
|
131
|
+
isOrderable
|
|
132
|
+
label={__('Select posts', 'webentor')}
|
|
133
|
+
contentTypes={Array.isArray(postType) ? postType : [postType]}
|
|
134
|
+
/>
|
|
135
|
+
) : (
|
|
136
|
+
<Notice status="error" isDismissible={false}>
|
|
137
|
+
{__(
|
|
138
|
+
'Post type selection is required to select posts',
|
|
139
|
+
'webentor',
|
|
140
|
+
)}
|
|
141
|
+
</Notice>
|
|
142
|
+
)}
|
|
143
|
+
</div>
|
|
144
|
+
|
|
145
|
+
<TextControl
|
|
146
|
+
label={__('Query ID', 'webentor')}
|
|
147
|
+
value={queryId}
|
|
148
|
+
onChange={(value) => {
|
|
149
|
+
setQuery({
|
|
150
|
+
queryId: value,
|
|
151
|
+
});
|
|
152
|
+
}}
|
|
153
|
+
help={__(
|
|
154
|
+
'This can be used to filter query params via `webentor/query_loop_args` hook.',
|
|
155
|
+
)}
|
|
156
|
+
/>
|
|
157
|
+
</PanelBody>
|
|
158
|
+
</InspectorControls>
|
|
159
|
+
|
|
160
|
+
<div
|
|
161
|
+
{...innerBlocksProps}
|
|
162
|
+
className={`${innerBlocksProps.className} wbtr:relative wbtr:p-2 wbtr:pt-4`}
|
|
163
|
+
>
|
|
164
|
+
<div className="wbtr:pointer-events-none wbtr:absolute wbtr:inset-0 wbtr:h-full wbtr:w-full wbtr:border wbtr:border-editor-border wbtr:p-2 wbtr:pt-4"></div>
|
|
165
|
+
|
|
166
|
+
<div className="wbtr:absolute wbtr:top-[2px] wbtr:left-2 wbtr:mb-1 wbtr:text-10 wbtr:opacity-50">
|
|
167
|
+
{__('Picker Query Loop', 'webentor')}
|
|
168
|
+
</div>
|
|
169
|
+
|
|
170
|
+
{children}
|
|
171
|
+
</div>
|
|
172
|
+
</>
|
|
173
|
+
);
|
|
174
|
+
};
|
|
175
|
+
|
|
176
|
+
/**
|
|
177
|
+
* See https://wordpress.org/gutenberg/handbook/designers-developers/developers/block-api/block-edit-save/#save
|
|
178
|
+
*
|
|
179
|
+
* @return {null} Dynamic blocks do not save the HTML.
|
|
180
|
+
*/
|
|
181
|
+
const BlockSave = () => <InnerBlocks.Content />;
|
|
182
|
+
|
|
183
|
+
/**
|
|
184
|
+
* Register block.
|
|
185
|
+
*/
|
|
186
|
+
registerBlockType(block, {
|
|
187
|
+
edit: BlockEdit,
|
|
188
|
+
save: BlockSave,
|
|
189
|
+
});
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "../../../schemas/webentor-block.json",
|
|
3
|
+
"apiVersion": 3,
|
|
4
|
+
"name": "webentor/e-post-template",
|
|
5
|
+
"title": "Webentor Post Template",
|
|
6
|
+
"description": "Post template used in Webentor Query Loop.",
|
|
7
|
+
"category": "webentor-elements",
|
|
8
|
+
"icon": "layout",
|
|
9
|
+
"keywords": ["query"],
|
|
10
|
+
"attributes": {
|
|
11
|
+
"template": {
|
|
12
|
+
"type": "array",
|
|
13
|
+
"default": null
|
|
14
|
+
}
|
|
15
|
+
},
|
|
16
|
+
"example": {
|
|
17
|
+
"attributes": {
|
|
18
|
+
"mode": "preview",
|
|
19
|
+
"data": {
|
|
20
|
+
"preview_image_help": true
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
},
|
|
24
|
+
"supports": {}
|
|
25
|
+
}
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
import {
|
|
2
|
+
InnerBlocks,
|
|
3
|
+
useBlockProps,
|
|
4
|
+
useInnerBlocksProps,
|
|
5
|
+
} from '@wordpress/block-editor';
|
|
6
|
+
import {
|
|
7
|
+
BlockEditProps,
|
|
8
|
+
registerBlockType,
|
|
9
|
+
TemplateArray,
|
|
10
|
+
} from '@wordpress/blocks';
|
|
11
|
+
import { applyFilters } from '@wordpress/hooks';
|
|
12
|
+
import { __ } from '@wordpress/i18n';
|
|
13
|
+
|
|
14
|
+
import { useBlockParent } from '@webentorCore/blocks-utils/_use-block-parent';
|
|
15
|
+
|
|
16
|
+
import block from './block.json';
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* Edit component.
|
|
20
|
+
* See https://wordpress.org/gutenberg/handbook/designers-developers/developers/block-api/block-edit-save/#edit
|
|
21
|
+
*
|
|
22
|
+
* @param {object} props The block props.
|
|
23
|
+
* @returns {Function} Render the edit screen
|
|
24
|
+
*/
|
|
25
|
+
|
|
26
|
+
type AttributesType = {
|
|
27
|
+
coverImage: string;
|
|
28
|
+
template?: TemplateArray;
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
const BlockEdit: React.FC<BlockEditProps<AttributesType>> = (props) => {
|
|
32
|
+
const { attributes } = props;
|
|
33
|
+
|
|
34
|
+
const blockProps = useBlockProps();
|
|
35
|
+
const parentBlockProps = useBlockParent();
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* Filter allowed blocks used in webentor/e-post-template inner block
|
|
39
|
+
*/
|
|
40
|
+
const allowedBlocks: string[] = applyFilters(
|
|
41
|
+
'webentor.core.e-post-template.allowedBlocks',
|
|
42
|
+
['webentor/l-post-card'],
|
|
43
|
+
blockProps,
|
|
44
|
+
parentBlockProps,
|
|
45
|
+
);
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* Filter template used in webentor/e-post-template inner block
|
|
49
|
+
*/
|
|
50
|
+
const defaultTemplate: TemplateArray = attributes?.template ?? [
|
|
51
|
+
['webentor/l-post-card'],
|
|
52
|
+
];
|
|
53
|
+
const template: TemplateArray = applyFilters(
|
|
54
|
+
'webentor.core.e-post-template.template',
|
|
55
|
+
defaultTemplate,
|
|
56
|
+
blockProps,
|
|
57
|
+
parentBlockProps,
|
|
58
|
+
);
|
|
59
|
+
|
|
60
|
+
const { children, ...innerBlocksProps } = useInnerBlocksProps(blockProps, {
|
|
61
|
+
allowedBlocks,
|
|
62
|
+
template,
|
|
63
|
+
templateLock: false,
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
// Preview image for block inserter
|
|
67
|
+
if (attributes.coverImage) {
|
|
68
|
+
return <img src={attributes.coverImage} width="468" />;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
return (
|
|
72
|
+
<div
|
|
73
|
+
{...innerBlocksProps}
|
|
74
|
+
className={`${innerBlocksProps.className} wbtr:relative wbtr:p-2 wbtr:pt-4`}
|
|
75
|
+
>
|
|
76
|
+
<div className="wbtr:pointer-events-none wbtr:absolute wbtr:inset-0 wbtr:h-full wbtr:w-full wbtr:border wbtr:border-editor-border wbtr:p-2 wbtr:pt-4"></div>
|
|
77
|
+
|
|
78
|
+
<div className="wbtr:absolute wbtr:top-[2px] wbtr:left-2 wbtr:mb-1 wbtr:text-10 wbtr:opacity-50">
|
|
79
|
+
{__('Post Template', 'webentor')}
|
|
80
|
+
</div>
|
|
81
|
+
|
|
82
|
+
{children}
|
|
83
|
+
</div>
|
|
84
|
+
);
|
|
85
|
+
};
|
|
86
|
+
|
|
87
|
+
/**
|
|
88
|
+
* See https://wordpress.org/gutenberg/handbook/designers-developers/developers/block-api/block-edit-save/#save
|
|
89
|
+
*
|
|
90
|
+
* @return {null} Dynamic blocks do not save the HTML.
|
|
91
|
+
*/
|
|
92
|
+
const BlockSave = () => <InnerBlocks.Content />;
|
|
93
|
+
|
|
94
|
+
/**
|
|
95
|
+
* Register block.
|
|
96
|
+
*/
|
|
97
|
+
registerBlockType(block, {
|
|
98
|
+
edit: BlockEdit,
|
|
99
|
+
save: BlockSave,
|
|
100
|
+
});
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "../../../schemas/webentor-block.json",
|
|
3
|
+
"apiVersion": 3,
|
|
4
|
+
"name": "webentor/e-query-loop",
|
|
5
|
+
"title": "Webentor Query Loop",
|
|
6
|
+
"description": "Display posts in a loop with various query configuration. Don't work with pagination yet!",
|
|
7
|
+
"category": "webentor-elements",
|
|
8
|
+
"icon": "update",
|
|
9
|
+
"keywords": ["loop", "query", "slider"],
|
|
10
|
+
"attributes": {
|
|
11
|
+
"query": {
|
|
12
|
+
"type": "object",
|
|
13
|
+
"default": {
|
|
14
|
+
"perPage": null,
|
|
15
|
+
"pages": 0,
|
|
16
|
+
"offset": 0,
|
|
17
|
+
"postType": ["post"],
|
|
18
|
+
"order": "desc",
|
|
19
|
+
"orderBy": "date",
|
|
20
|
+
"author": "",
|
|
21
|
+
"search": "",
|
|
22
|
+
"exclude": [],
|
|
23
|
+
"sticky": "",
|
|
24
|
+
"inherit": true,
|
|
25
|
+
"taxQuery": null,
|
|
26
|
+
"parents": [],
|
|
27
|
+
"queryId": ""
|
|
28
|
+
}
|
|
29
|
+
},
|
|
30
|
+
"template": {
|
|
31
|
+
"type": "array",
|
|
32
|
+
"default": null
|
|
33
|
+
}
|
|
34
|
+
},
|
|
35
|
+
"supports": {}
|
|
36
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
// The following dropdown menu props aim to provide a consistent offset and
|
|
2
|
+
// placement for ToolsPanel menus for block controls to match color popovers.
|
|
3
|
+
export const TOOLSPANEL_DROPDOWNMENU_PROPS = {
|
|
4
|
+
popoverProps: {
|
|
5
|
+
placement: 'left-start',
|
|
6
|
+
offset: 259, // Inner sidebar width (248px) - button width (24px) - border (1px) + padding (16px) + spacing (20px)
|
|
7
|
+
},
|
|
8
|
+
};
|
|
@@ -0,0 +1,270 @@
|
|
|
1
|
+
import {
|
|
2
|
+
InnerBlocks,
|
|
3
|
+
InspectorControls,
|
|
4
|
+
useBlockProps,
|
|
5
|
+
useInnerBlocksProps,
|
|
6
|
+
} from '@wordpress/block-editor';
|
|
7
|
+
import {
|
|
8
|
+
BlockEditProps,
|
|
9
|
+
registerBlockType,
|
|
10
|
+
TemplateArray,
|
|
11
|
+
} from '@wordpress/blocks';
|
|
12
|
+
import {
|
|
13
|
+
__experimentalNumberControl as NumberControl,
|
|
14
|
+
PanelBody,
|
|
15
|
+
SelectControl,
|
|
16
|
+
TextControl,
|
|
17
|
+
__experimentalToolsPanel as ToolsPanel,
|
|
18
|
+
__experimentalToolsPanelItem as ToolsPanelItem,
|
|
19
|
+
} from '@wordpress/components';
|
|
20
|
+
import { applyFilters } from '@wordpress/hooks';
|
|
21
|
+
import { __ } from '@wordpress/i18n';
|
|
22
|
+
|
|
23
|
+
import { useBlockParent } from '@webentorCore/blocks-utils/_use-block-parent';
|
|
24
|
+
import { usePostTypes } from '@webentorCore/blocks-utils/_use-post-types';
|
|
25
|
+
|
|
26
|
+
import block from './block.json';
|
|
27
|
+
import { TOOLSPANEL_DROPDOWNMENU_PROPS } from './constants';
|
|
28
|
+
import { TaxonomyControls } from './taxonomy-controls';
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* Edit component.
|
|
32
|
+
* See https://wordpress.org/gutenberg/handbook/designers-developers/developers/block-api/block-edit-save/#edit
|
|
33
|
+
*
|
|
34
|
+
* @param {object} props The block props.
|
|
35
|
+
* @returns {Function} Render the edit screen
|
|
36
|
+
*/
|
|
37
|
+
|
|
38
|
+
type AttributesType = {
|
|
39
|
+
coverImage: string;
|
|
40
|
+
query: {
|
|
41
|
+
perPage: number;
|
|
42
|
+
postType: string[];
|
|
43
|
+
queryId: string;
|
|
44
|
+
taxQuery: Record<string, string[]>;
|
|
45
|
+
parents: number[];
|
|
46
|
+
};
|
|
47
|
+
template?: TemplateArray;
|
|
48
|
+
};
|
|
49
|
+
|
|
50
|
+
const BlockEdit: React.FC<BlockEditProps<AttributesType>> = (props) => {
|
|
51
|
+
const { attributes, setAttributes } = props;
|
|
52
|
+
const { query } = attributes;
|
|
53
|
+
const {
|
|
54
|
+
// order,
|
|
55
|
+
// orderBy,
|
|
56
|
+
// author: authorIds,
|
|
57
|
+
postType,
|
|
58
|
+
// sticky,
|
|
59
|
+
// inherit,
|
|
60
|
+
taxQuery,
|
|
61
|
+
// parents,
|
|
62
|
+
} = query;
|
|
63
|
+
|
|
64
|
+
const blockProps = useBlockProps();
|
|
65
|
+
const parentBlockProps = useBlockParent();
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* Filter allowed blocks used in webentor/e-query-loop inner block
|
|
69
|
+
*/
|
|
70
|
+
const allowedBlocks: string[] = applyFilters(
|
|
71
|
+
'webentor.core.e-query-loop.allowedBlocks',
|
|
72
|
+
// Allow only singular 'e-post-template' block to be added as child.
|
|
73
|
+
['webentor/e-post-template'],
|
|
74
|
+
blockProps,
|
|
75
|
+
parentBlockProps,
|
|
76
|
+
);
|
|
77
|
+
|
|
78
|
+
/**
|
|
79
|
+
* Filter template used in webentor/e-query-loop inner block
|
|
80
|
+
*/
|
|
81
|
+
const defaultTemplate: TemplateArray = attributes?.template ?? [
|
|
82
|
+
['webentor/e-post-template', ['webentor/l-post-card']],
|
|
83
|
+
];
|
|
84
|
+
const template: TemplateArray = applyFilters(
|
|
85
|
+
'webentor.core.e-query-loop.template',
|
|
86
|
+
defaultTemplate,
|
|
87
|
+
blockProps,
|
|
88
|
+
parentBlockProps,
|
|
89
|
+
);
|
|
90
|
+
|
|
91
|
+
const { children, ...innerBlocksProps } = useInnerBlocksProps(blockProps, {
|
|
92
|
+
allowedBlocks,
|
|
93
|
+
template,
|
|
94
|
+
templateLock: 'all',
|
|
95
|
+
});
|
|
96
|
+
|
|
97
|
+
const { postTypesTaxonomiesMap, postTypesSelectOptions } = usePostTypes();
|
|
98
|
+
|
|
99
|
+
// TODO: add settings for these
|
|
100
|
+
const showTaxControl = true;
|
|
101
|
+
// const showAuthorControl = false;
|
|
102
|
+
// const showSearchControl = false;
|
|
103
|
+
|
|
104
|
+
const setQuery = (newQuery) =>
|
|
105
|
+
setAttributes({ query: { ...query, ...newQuery } });
|
|
106
|
+
|
|
107
|
+
const onPostTypeChange = (newValue) => {
|
|
108
|
+
// Taxonomies are supported only for single post type, so we need to handle that
|
|
109
|
+
const singlePostType =
|
|
110
|
+
Array.isArray(newValue) && newValue.length === 1 ? newValue[0] : newValue;
|
|
111
|
+
|
|
112
|
+
const updateQuery = { postType: singlePostType };
|
|
113
|
+
// We need to dynamically update the `taxQuery` property,
|
|
114
|
+
// by removing any not supported taxonomy from the query.
|
|
115
|
+
const supportedTaxonomies = postTypesTaxonomiesMap[singlePostType];
|
|
116
|
+
const updatedTaxQuery = Object.entries(taxQuery || {}).reduce(
|
|
117
|
+
(accumulator, [taxonomySlug, terms]) => {
|
|
118
|
+
if (supportedTaxonomies.includes(taxonomySlug)) {
|
|
119
|
+
accumulator[taxonomySlug] = terms;
|
|
120
|
+
}
|
|
121
|
+
return accumulator;
|
|
122
|
+
},
|
|
123
|
+
{},
|
|
124
|
+
);
|
|
125
|
+
updateQuery.taxQuery = Object.keys(updatedTaxQuery).length
|
|
126
|
+
? updatedTaxQuery
|
|
127
|
+
: undefined;
|
|
128
|
+
|
|
129
|
+
if (singlePostType !== 'post') {
|
|
130
|
+
updateQuery.sticky = '';
|
|
131
|
+
}
|
|
132
|
+
// We need to reset `parents` because they are tied to each post type.
|
|
133
|
+
updateQuery.parents = [];
|
|
134
|
+
setQuery(updateQuery);
|
|
135
|
+
};
|
|
136
|
+
|
|
137
|
+
// Preview image for block inserter
|
|
138
|
+
if (attributes.coverImage) {
|
|
139
|
+
return <img src={attributes.coverImage} width="468" />;
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
return (
|
|
143
|
+
<>
|
|
144
|
+
<InspectorControls>
|
|
145
|
+
<PanelBody title="Loop Settings" initialOpen={true}>
|
|
146
|
+
<NumberControl
|
|
147
|
+
label={__('Posts Per Page', 'webentor')}
|
|
148
|
+
min={1}
|
|
149
|
+
max={20}
|
|
150
|
+
step="1"
|
|
151
|
+
value={query.perPage}
|
|
152
|
+
onChange={(value) => {
|
|
153
|
+
if (isNaN(value) || value < 1 || value > 100) {
|
|
154
|
+
return;
|
|
155
|
+
}
|
|
156
|
+
setQuery({
|
|
157
|
+
perPage: value,
|
|
158
|
+
});
|
|
159
|
+
}}
|
|
160
|
+
/>
|
|
161
|
+
|
|
162
|
+
<SelectControl
|
|
163
|
+
__nextHasNoMarginBottom
|
|
164
|
+
options={postTypesSelectOptions}
|
|
165
|
+
value={Array.isArray(postType) ? postType : [postType]}
|
|
166
|
+
label={__('Post type')}
|
|
167
|
+
multiple
|
|
168
|
+
onChange={onPostTypeChange}
|
|
169
|
+
help={__(
|
|
170
|
+
'WordPress contains different types of content and they are divided into collections called “Post types”. By default there are a few different ones such as blog posts and pages, but plugins could add more.',
|
|
171
|
+
)}
|
|
172
|
+
/>
|
|
173
|
+
|
|
174
|
+
<TextControl
|
|
175
|
+
label={__('Query ID', 'webentor')}
|
|
176
|
+
value={query.queryId}
|
|
177
|
+
onChange={(value) => {
|
|
178
|
+
setQuery({
|
|
179
|
+
queryId: value,
|
|
180
|
+
});
|
|
181
|
+
}}
|
|
182
|
+
help={__(
|
|
183
|
+
'This can be used to filter query params via `webentor/query_loop_args` hook.',
|
|
184
|
+
)}
|
|
185
|
+
/>
|
|
186
|
+
</PanelBody>
|
|
187
|
+
|
|
188
|
+
<ToolsPanel
|
|
189
|
+
className="block-library-query-toolspanel__filters"
|
|
190
|
+
label={__('Filters')}
|
|
191
|
+
resetAll={() => {
|
|
192
|
+
setQuery({
|
|
193
|
+
author: '',
|
|
194
|
+
parents: [],
|
|
195
|
+
search: '',
|
|
196
|
+
taxQuery: null,
|
|
197
|
+
});
|
|
198
|
+
// setQuerySearch('');
|
|
199
|
+
}}
|
|
200
|
+
dropdownMenuProps={TOOLSPANEL_DROPDOWNMENU_PROPS}
|
|
201
|
+
>
|
|
202
|
+
{showTaxControl && !Array.isArray(query.postType) && (
|
|
203
|
+
<ToolsPanelItem
|
|
204
|
+
label={__('Taxonomies')}
|
|
205
|
+
hasValue={() =>
|
|
206
|
+
Object.values(taxQuery || {}).some((terms) => !!terms.length)
|
|
207
|
+
}
|
|
208
|
+
onDeselect={() => setQuery({ taxQuery: null })}
|
|
209
|
+
>
|
|
210
|
+
<TaxonomyControls onChange={setQuery} query={query} />
|
|
211
|
+
</ToolsPanelItem>
|
|
212
|
+
)}
|
|
213
|
+
|
|
214
|
+
{/* {showAuthorControl && (
|
|
215
|
+
<ToolsPanelItem
|
|
216
|
+
hasValue={() => !!authorIds}
|
|
217
|
+
label={__('Authors')}
|
|
218
|
+
onDeselect={() => setQuery({ author: '' })}
|
|
219
|
+
>
|
|
220
|
+
<AuthorControl value={authorIds} onChange={setQuery} />
|
|
221
|
+
</ToolsPanelItem>
|
|
222
|
+
)} */}
|
|
223
|
+
|
|
224
|
+
{/* {showSearchControl && (
|
|
225
|
+
<ToolsPanelItem
|
|
226
|
+
hasValue={() => !!querySearch}
|
|
227
|
+
label={__('Keyword')}
|
|
228
|
+
onDeselect={() => setQuerySearch('')}
|
|
229
|
+
>
|
|
230
|
+
<TextControl
|
|
231
|
+
__nextHasNoMarginBottom
|
|
232
|
+
label={__('Keyword')}
|
|
233
|
+
value={querySearch}
|
|
234
|
+
onChange={setQuerySearch}
|
|
235
|
+
/>
|
|
236
|
+
</ToolsPanelItem>
|
|
237
|
+
)} */}
|
|
238
|
+
</ToolsPanel>
|
|
239
|
+
</InspectorControls>
|
|
240
|
+
|
|
241
|
+
<div
|
|
242
|
+
{...innerBlocksProps}
|
|
243
|
+
className={`${innerBlocksProps.className} wbtr:relative wbtr:p-2 wbtr:pt-4`}
|
|
244
|
+
>
|
|
245
|
+
<div className="wbtr:pointer-events-none wbtr:absolute wbtr:inset-0 wbtr:h-full wbtr:w-full wbtr:border wbtr:border-editor-border wbtr:p-2 wbtr:pt-4"></div>
|
|
246
|
+
|
|
247
|
+
<div className="wbtr:absolute wbtr:top-[2px] wbtr:left-2 wbtr:mb-1 wbtr:text-10 wbtr:opacity-50">
|
|
248
|
+
{__('Query Loop', 'webentor')}
|
|
249
|
+
</div>
|
|
250
|
+
|
|
251
|
+
{children}
|
|
252
|
+
</div>
|
|
253
|
+
</>
|
|
254
|
+
);
|
|
255
|
+
};
|
|
256
|
+
|
|
257
|
+
/**
|
|
258
|
+
* See https://wordpress.org/gutenberg/handbook/designers-developers/developers/block-api/block-edit-save/#save
|
|
259
|
+
*
|
|
260
|
+
* @return {null} Dynamic blocks do not save the HTML.
|
|
261
|
+
*/
|
|
262
|
+
const BlockSave = () => <InnerBlocks.Content />;
|
|
263
|
+
|
|
264
|
+
/**
|
|
265
|
+
* Register block.
|
|
266
|
+
*/
|
|
267
|
+
registerBlockType(block, {
|
|
268
|
+
edit: BlockEdit,
|
|
269
|
+
save: BlockSave,
|
|
270
|
+
});
|