@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.
Files changed (132) hide show
  1. package/.husky/pre-commit +40 -0
  2. package/.prettierrc.js +5 -0
  3. package/CHANGELOG.md +88 -0
  4. package/LICENCE.md +7 -0
  5. package/README.md +26 -0
  6. package/core-js/_alpine.ts +20 -0
  7. package/core-js/_slider.ts +232 -0
  8. package/core-js/_utils.ts +126 -0
  9. package/core-js/blocks-components/block-appender.tsx +36 -0
  10. package/core-js/blocks-components/button.tsx +424 -0
  11. package/core-js/blocks-components/custom-image-sizes-panel.tsx +197 -0
  12. package/core-js/blocks-components/index.ts +4 -0
  13. package/core-js/blocks-components/typography-picker-select.tsx +31 -0
  14. package/core-js/blocks-filters/_filter-core-typography.tsx +108 -0
  15. package/core-js/blocks-filters/_slider-settings.tsx +283 -0
  16. package/core-js/blocks-filters/index.ts +3 -0
  17. package/core-js/blocks-filters/responsive-settings/components/DisabledSliderInfo.tsx +10 -0
  18. package/core-js/blocks-filters/responsive-settings/constants.ts +11 -0
  19. package/core-js/blocks-filters/responsive-settings/index.tsx +196 -0
  20. package/core-js/blocks-filters/responsive-settings/settings/block-link/index.ts +1 -0
  21. package/core-js/blocks-filters/responsive-settings/settings/block-link/panel.tsx +47 -0
  22. package/core-js/blocks-filters/responsive-settings/settings/border/border/index.tsx +1 -0
  23. package/core-js/blocks-filters/responsive-settings/settings/border/border/properties.ts +27 -0
  24. package/core-js/blocks-filters/responsive-settings/settings/border/border/settings.tsx +310 -0
  25. package/core-js/blocks-filters/responsive-settings/settings/border/border-radius/index.tsx +1 -0
  26. package/core-js/blocks-filters/responsive-settings/settings/border/border-radius/properties.ts +31 -0
  27. package/core-js/blocks-filters/responsive-settings/settings/border/border-radius/settings.tsx +211 -0
  28. package/core-js/blocks-filters/responsive-settings/settings/border/index.ts +1 -0
  29. package/core-js/blocks-filters/responsive-settings/settings/border/panel.tsx +54 -0
  30. package/core-js/blocks-filters/responsive-settings/settings/container/display/index.ts +2 -0
  31. package/core-js/blocks-filters/responsive-settings/settings/container/display/properties.ts +167 -0
  32. package/core-js/blocks-filters/responsive-settings/settings/container/display/settings.tsx +73 -0
  33. package/core-js/blocks-filters/responsive-settings/settings/container/flexbox/index.ts +2 -0
  34. package/core-js/blocks-filters/responsive-settings/settings/container/flexbox/properties.ts +187 -0
  35. package/core-js/blocks-filters/responsive-settings/settings/container/flexbox/settings.tsx +131 -0
  36. package/core-js/blocks-filters/responsive-settings/settings/container/grid/index.ts +2 -0
  37. package/core-js/blocks-filters/responsive-settings/settings/container/grid/properties.ts +187 -0
  38. package/core-js/blocks-filters/responsive-settings/settings/container/grid/settings.tsx +132 -0
  39. package/core-js/blocks-filters/responsive-settings/settings/container/index.ts +4 -0
  40. package/core-js/blocks-filters/responsive-settings/settings/container/panel.tsx +92 -0
  41. package/core-js/blocks-filters/responsive-settings/settings/spacing/index.ts +3 -0
  42. package/core-js/blocks-filters/responsive-settings/settings/spacing/panel.tsx +45 -0
  43. package/core-js/blocks-filters/responsive-settings/settings/spacing/properties.ts +74 -0
  44. package/core-js/blocks-filters/responsive-settings/settings/spacing/settings.tsx +85 -0
  45. package/core-js/blocks-filters/responsive-settings/types/index.ts +68 -0
  46. package/core-js/blocks-filters/responsive-settings/utils.ts +321 -0
  47. package/core-js/blocks-utils/_use-block-parent.ts +27 -0
  48. package/core-js/blocks-utils/_use-post-types.ts +43 -0
  49. package/core-js/blocks-utils/_use-taxonomies.ts +29 -0
  50. package/core-js/blocks-utils/index.ts +3 -0
  51. package/core-js/config/webentor-config.ts +718 -0
  52. package/core-js/index.ts +14 -0
  53. package/core-js/types/_block-components.ts +7 -0
  54. package/core-js/types/_webentor-config.ts +182 -0
  55. package/package.json +98 -0
  56. package/resources/blocks/e-accordion/block.json +34 -0
  57. package/resources/blocks/e-accordion/e-accordion.block.tsx +125 -0
  58. package/resources/blocks/e-accordion/script.ts +1 -0
  59. package/resources/blocks/e-accordion/style.css +8 -0
  60. package/resources/blocks/e-accordion-group/block.json +56 -0
  61. package/resources/blocks/e-accordion-group/e-accordion-group.block.tsx +99 -0
  62. package/resources/blocks/e-breadcrumbs/block.json +41 -0
  63. package/resources/blocks/e-breadcrumbs/e-breadcrumbs.block.tsx +53 -0
  64. package/resources/blocks/e-button/block.json +32 -0
  65. package/resources/blocks/e-button/e-button.block.tsx +55 -0
  66. package/resources/blocks/e-gallery/block.json +90 -0
  67. package/resources/blocks/e-gallery/e-gallery.block.tsx +316 -0
  68. package/resources/blocks/e-icon-picker/block.json +37 -0
  69. package/resources/blocks/e-icon-picker/e-icon-picker.block.tsx +230 -0
  70. package/resources/blocks/e-icon-picker/style.css +17 -0
  71. package/resources/blocks/e-image/block.json +78 -0
  72. package/resources/blocks/e-image/e-image.block.tsx +331 -0
  73. package/resources/blocks/e-picker-query-loop/block.json +25 -0
  74. package/resources/blocks/e-picker-query-loop/e-picker-query-loop.block.tsx +189 -0
  75. package/resources/blocks/e-post-template/block.json +25 -0
  76. package/resources/blocks/e-post-template/e-post-template.block.tsx +100 -0
  77. package/resources/blocks/e-query-loop/block.json +36 -0
  78. package/resources/blocks/e-query-loop/constants.tsx +8 -0
  79. package/resources/blocks/e-query-loop/e-query-loop.block.tsx +270 -0
  80. package/resources/blocks/e-query-loop/taxonomy-controls.tsx +184 -0
  81. package/resources/blocks/e-slider/block.json +42 -0
  82. package/resources/blocks/e-slider/e-slider.block.tsx +100 -0
  83. package/resources/blocks/e-svg/block.json +37 -0
  84. package/resources/blocks/e-svg/e-svg.block.tsx +156 -0
  85. package/resources/blocks/e-tab-container/block.json +49 -0
  86. package/resources/blocks/e-tab-container/e-tab-container.block.tsx +123 -0
  87. package/resources/blocks/e-table/block.json +30 -0
  88. package/resources/blocks/e-table/e-table.block.tsx +120 -0
  89. package/resources/blocks/e-table/script.ts +48 -0
  90. package/resources/blocks/e-table-cell/block.json +40 -0
  91. package/resources/blocks/e-table-cell/e-table-cell.block.tsx +180 -0
  92. package/resources/blocks/e-table-row/block.json +28 -0
  93. package/resources/blocks/e-table-row/e-table-row.block.tsx +118 -0
  94. package/resources/blocks/e-tabs/block.json +27 -0
  95. package/resources/blocks/e-tabs/e-tabs.block.tsx +90 -0
  96. package/resources/blocks/l-404/block.json +51 -0
  97. package/resources/blocks/l-404/l-404.block.tsx +75 -0
  98. package/resources/blocks/l-flexible-container/block.json +34 -0
  99. package/resources/blocks/l-flexible-container/l-flexible-container.block.tsx +97 -0
  100. package/resources/blocks/l-footer/block.json +23 -0
  101. package/resources/blocks/l-footer/l-footer.block.tsx +51 -0
  102. package/resources/blocks/l-formatted-content/block.json +28 -0
  103. package/resources/blocks/l-formatted-content/l-formatted-content.block.tsx +97 -0
  104. package/resources/blocks/l-header/block.json +26 -0
  105. package/resources/blocks/l-header/l-header.block.tsx +100 -0
  106. package/resources/blocks/l-mobile-nav/block.json +15 -0
  107. package/resources/blocks/l-mobile-nav/l-mobile-nav.block.tsx +56 -0
  108. package/resources/blocks/l-mobile-nav/style.css +54 -0
  109. package/resources/blocks/l-nav-menu/block.json +27 -0
  110. package/resources/blocks/l-nav-menu/l-nav-menu.block.tsx +109 -0
  111. package/resources/blocks/l-nav-menu/style.css +134 -0
  112. package/resources/blocks/l-post-card/block.json +13 -0
  113. package/resources/blocks/l-post-card/l-post-card.block.tsx +52 -0
  114. package/resources/blocks/l-section/block.json +89 -0
  115. package/resources/blocks/l-section/l-section.block.tsx +316 -0
  116. package/resources/blocks/l-site-logo/block.json +15 -0
  117. package/resources/blocks/l-site-logo/l-site-logo.block.tsx +54 -0
  118. package/resources/core-components/slider/slider.script.ts +11 -0
  119. package/resources/core-components/slider/slider.style.css +134 -0
  120. package/resources/scripts/editor.ts +29 -0
  121. package/resources/styles/app.css +21 -0
  122. package/resources/styles/common/_editor.css +86 -0
  123. package/resources/styles/common/_form.css +83 -0
  124. package/resources/styles/common/_global.css +73 -0
  125. package/resources/styles/common/_theme.css +75 -0
  126. package/resources/styles/common/_utilities.css +33 -0
  127. package/resources/styles/common/_wordpress.css +110 -0
  128. package/resources/styles/components/_table.css +102 -0
  129. package/resources/styles/editor.css +16 -0
  130. package/resources/styles/partials/.gitkeep +0 -0
  131. package/resources/styles/partials/_header.css +21 -0
  132. package/resources/styles/partials/_pagination.css +35 -0
@@ -0,0 +1,230 @@
1
+ import { Icon, IconPicker, Link } from '@10up/block-components';
2
+ import {
3
+ ColorPalette,
4
+ InspectorControls,
5
+ useBlockProps,
6
+ } from '@wordpress/block-editor';
7
+ import { BlockEditProps, registerBlockType } from '@wordpress/blocks';
8
+ import {
9
+ __experimentalNumberControl as NumberControl,
10
+ PanelBody,
11
+ PanelRow,
12
+ ToggleControl,
13
+ } from '@wordpress/components';
14
+ import { applyFilters } from '@wordpress/hooks';
15
+ import { __ } from '@wordpress/i18n';
16
+
17
+ import { getColorBySlug, getColorSlugByColor } from '@webentorCore/_utils';
18
+ import { WebentorConfig } from '@webentorCore/types/_webentor-config';
19
+
20
+ import block from './block.json';
21
+
22
+ /**
23
+ * Edit component.
24
+ * See https://wordpress.org/gutenberg/handbook/designers-developers/developers/block-api/block-edit-save/#edit
25
+ *
26
+ * @param {object} props The block props.
27
+ * @returns {Function} Render the edit screen
28
+ */
29
+
30
+ type AttributesType = {
31
+ coverImage: string;
32
+ link: {
33
+ title: string;
34
+ url: string;
35
+ opensInNewTab: boolean;
36
+ };
37
+ inheritSize?: boolean;
38
+ width: string;
39
+ height: string;
40
+ color: string;
41
+ icon: {
42
+ name: string;
43
+ iconSet: string;
44
+ };
45
+ };
46
+
47
+ const BlockEdit: React.FC<BlockEditProps<AttributesType>> = (props) => {
48
+ const { attributes, setAttributes } = props;
49
+
50
+ const blockProps = useBlockProps();
51
+
52
+ // Preview image for block inserter
53
+ if (attributes.coverImage) {
54
+ return <img src={attributes.coverImage} width="468" />;
55
+ }
56
+
57
+ const twTheme: WebentorConfig['theme'] = applyFilters(
58
+ 'webentor.core.twTheme',
59
+ {},
60
+ );
61
+
62
+ const themeColors = applyFilters(
63
+ 'webentor.core.e-icon-picker.colors',
64
+ twTheme?.colors || {},
65
+ );
66
+
67
+ const paletteColors = Object.entries(themeColors).map(([key, value]) => ({
68
+ name: key,
69
+ color: value,
70
+ slug: `text-${key}`, // Color slug is TW class name
71
+ }));
72
+
73
+ const handleLinkTextChange = (value) =>
74
+ setAttributes({
75
+ link: {
76
+ ...attributes.link,
77
+ title: value,
78
+ },
79
+ });
80
+
81
+ const handleLinkChange = (value) =>
82
+ setAttributes({
83
+ link: {
84
+ url: value?.url,
85
+ opensInNewTab: value?.opensInNewTab,
86
+ title: value?.title ?? attributes?.link?.title,
87
+ },
88
+ });
89
+
90
+ const handleLinkRemove = () => {
91
+ setAttributes({ link: null });
92
+ };
93
+
94
+ const handleIconSelection = (value) =>
95
+ setAttributes({ icon: { name: value.name, iconSet: value.iconSet } });
96
+
97
+ return (
98
+ <>
99
+ <InspectorControls>
100
+ <PanelBody title="Block Settings" initialOpen={true}>
101
+ <IconPicker value={attributes?.icon} onChange={handleIconSelection} />
102
+ {/* <InlineIconPicker
103
+ value={null}
104
+ onChange={handleIconSelection}
105
+ className="icon-picker-preview"
106
+ style={{
107
+ width: attributes?.inheritSize
108
+ ? 'auto'
109
+ : attributes?.width
110
+ ? `${attributes?.width}px`
111
+ : '24px',
112
+ height: attributes?.inheritSize
113
+ ? 'auto'
114
+ : attributes?.height
115
+ ? `${attributes?.height}px`
116
+ : '24px',
117
+ }}
118
+ /> */}
119
+
120
+ <div className="wbtr:mt-4">
121
+ <p className="components-base-control__label wbtr:mb-2">
122
+ {__('Icon Color', 'webentor')}
123
+ </p>
124
+ <ColorPalette
125
+ colors={paletteColors}
126
+ value={getColorBySlug(paletteColors, attributes?.color)}
127
+ disableCustomColors
128
+ onChange={(color) => {
129
+ setAttributes({
130
+ color: getColorSlugByColor(paletteColors, color),
131
+ });
132
+ }}
133
+ />
134
+ </div>
135
+
136
+ <PanelRow>
137
+ {/* External link */}
138
+ <div className="wbtr:w-full wbtr:border wbtr:border-editor-border wbtr:p-2">
139
+ <p>{__('Link Icon to URL', 'webentor')}</p>
140
+
141
+ <div className="wbtr:flex wbtr:gap-2">
142
+ <Link
143
+ value={attributes?.link?.title}
144
+ url={attributes?.link?.url}
145
+ opensInNewTab={attributes?.link?.opensInNewTab}
146
+ onTextChange={handleLinkTextChange}
147
+ onLinkChange={handleLinkChange}
148
+ onLinkRemove={handleLinkRemove}
149
+ placeholder="Enter Link Text here..."
150
+ />
151
+ </div>
152
+ </div>
153
+ </PanelRow>
154
+
155
+ <PanelRow>
156
+ {/* Custom image size with with, heigh and crop */}
157
+ <div className="wbtr:flex wbtr:gap-2">
158
+ <NumberControl
159
+ label={__('Width', 'webentor')}
160
+ value={attributes?.width || ''}
161
+ onChange={(width) => setAttributes({ width })}
162
+ required
163
+ disabled={attributes?.inheritSize}
164
+ />
165
+
166
+ <NumberControl
167
+ label={__('Height', 'webentor')}
168
+ value={attributes?.height || ''}
169
+ onChange={(height) => setAttributes({ height })}
170
+ required
171
+ disabled={attributes?.inheritSize}
172
+ />
173
+ </div>
174
+ </PanelRow>
175
+
176
+ <PanelRow>
177
+ <ToggleControl
178
+ label={__('Inherit size from SVG', 'webentor')}
179
+ checked={attributes?.inheritSize}
180
+ onChange={(inheritSize) => setAttributes({ inheritSize })}
181
+ help={__(
182
+ "Use only when SVG have properly defined width and height and you don't want to set custom size.",
183
+ 'webentor',
184
+ )}
185
+ />
186
+ </PanelRow>
187
+ </PanelBody>
188
+ </InspectorControls>
189
+
190
+ <div {...blockProps} className={blockProps.className}>
191
+ {attributes?.icon?.name ? (
192
+ <Icon
193
+ name={attributes?.icon?.name}
194
+ iconSet={attributes?.icon?.iconSet}
195
+ className={`icon-picker-preview ${attributes?.color}`}
196
+ style={{
197
+ width: attributes?.inheritSize
198
+ ? 'auto'
199
+ : attributes?.width
200
+ ? `${attributes?.width}px`
201
+ : '24px',
202
+ height: attributes?.inheritSize
203
+ ? 'auto'
204
+ : attributes?.height
205
+ ? `${attributes?.height}px`
206
+ : '24px',
207
+ }}
208
+ />
209
+ ) : (
210
+ <span className="wbtr:text-10">{__('Pick icon', 'webentor')}</span>
211
+ )}
212
+ </div>
213
+ </>
214
+ );
215
+ };
216
+
217
+ /**
218
+ * See https://wordpress.org/gutenberg/handbook/designers-developers/developers/block-api/block-edit-save/#save
219
+ *
220
+ * @return {null} Dynamic blocks do not save the HTML.
221
+ */
222
+ const BlockSave = () => null;
223
+
224
+ /**
225
+ * Register block.
226
+ */
227
+ registerBlockType(block, {
228
+ edit: BlockEdit,
229
+ save: BlockSave,
230
+ });
@@ -0,0 +1,17 @@
1
+ /* Icon Picker in admin */
2
+ .icon-picker-preview svg {
3
+ max-height: 100%;
4
+ max-width: 100%;
5
+ height: auto;
6
+ width: 100%;
7
+ object-fit: contain;
8
+ }
9
+
10
+ /* Icon on frontend */
11
+ .e-svg-icon {
12
+ max-height: 100%;
13
+ max-width: 100%;
14
+ height: auto;
15
+ width: 100%;
16
+ object-fit: contain;
17
+ }
@@ -0,0 +1,78 @@
1
+ {
2
+ "$schema": "../../../schemas/webentor-block.json",
3
+ "name": "webentor/e-image",
4
+ "apiVersion": 3,
5
+ "title": "Custom Responsive Image",
6
+ "description": "Responsive image block.",
7
+ "category": "webentor-elements",
8
+ "icon": "format-image",
9
+ "keywords": ["image"],
10
+ "example": {
11
+ "attributes": {
12
+ "mode": "preview",
13
+ "data": {
14
+ "preview_image_help": true
15
+ }
16
+ }
17
+ },
18
+ "attributes": {
19
+ "imgId": {
20
+ "type": "number",
21
+ "default": 0
22
+ },
23
+ "focalPoint": {
24
+ "type": "object",
25
+ "default": {
26
+ "x": 0.5,
27
+ "y": 0.5
28
+ }
29
+ },
30
+ "lazyload": {
31
+ "type": "boolean",
32
+ "default": true
33
+ },
34
+ "openInLightbox": {
35
+ "type": "boolean",
36
+ "default": false
37
+ },
38
+ "link": {
39
+ "type": "object",
40
+ "default": {}
41
+ },
42
+ "fullWidth": {
43
+ "type": "boolean",
44
+ "default": false
45
+ },
46
+ "aspectRatio": {
47
+ "type": "string",
48
+ "default": "auto"
49
+ },
50
+ "objectFit": {
51
+ "type": "string",
52
+ "default": "fill"
53
+ },
54
+ "objectPosition": {
55
+ "type": "string",
56
+ "default": "center"
57
+ },
58
+ "imageSize": {
59
+ "type": "string",
60
+ "default": "large"
61
+ },
62
+ "customSizeEnabled": {
63
+ "type": "boolean",
64
+ "default": false
65
+ },
66
+ "customSize": {
67
+ "type": "object",
68
+ "default": {}
69
+ }
70
+ },
71
+ "supports": {
72
+ "webentor": {
73
+ "spacing": true,
74
+ "border": true,
75
+ "borderRadius": true
76
+ }
77
+ }
78
+ }
@@ -0,0 +1,331 @@
1
+ import { Image, Link, MediaToolbar } from '@10up/block-components';
2
+ import {
3
+ BlockControls,
4
+ store as blockEditorStore,
5
+ InspectorControls,
6
+ useBlockProps,
7
+ } from '@wordpress/block-editor';
8
+ import { BlockEditProps, registerBlockType } from '@wordpress/blocks';
9
+ import {
10
+ PanelBody,
11
+ PanelRow,
12
+ SelectControl,
13
+ ToggleControl,
14
+ } from '@wordpress/components';
15
+ import { useSelect } from '@wordpress/data';
16
+ import { __ } from '@wordpress/i18n';
17
+
18
+ import { setImmutably } from '@webentorCore/_utils';
19
+ import { CustomImageSizesPanel } from '@webentorCore/blocks-components';
20
+
21
+ import block from './block.json';
22
+
23
+ /**
24
+ * Edit component.
25
+ * See https://wordpress.org/gutenberg/handbook/designers-developers/developers/block-api/block-edit-save/#edit
26
+ *
27
+ * @param {object} props The block props.
28
+ * @returns {Function} Render the edit screen
29
+ */
30
+
31
+ type AttributesType = {
32
+ coverImage: string;
33
+ lazyload: boolean;
34
+ openInLightbox: boolean;
35
+ fullWidth: boolean;
36
+ aspectRatio: string;
37
+ objectFit: string;
38
+ objectPosition: string;
39
+ imageSize: string;
40
+ customSize: {
41
+ enabled: {
42
+ [key: string]: boolean;
43
+ };
44
+ width: {
45
+ [key: string]: string;
46
+ };
47
+ height: {
48
+ [key: string]: string;
49
+ };
50
+ crop: {
51
+ [key: string]: boolean;
52
+ };
53
+ };
54
+ imgId: number;
55
+ focalPoint: {
56
+ x: number;
57
+ y: number;
58
+ };
59
+ link: {
60
+ url: string;
61
+ title: string;
62
+ opensInNewTab: boolean;
63
+ };
64
+ };
65
+
66
+ const BlockEdit: React.FC<BlockEditProps<AttributesType>> = (props) => {
67
+ const { attributes, setAttributes } = props;
68
+
69
+ const blockProps = useBlockProps();
70
+
71
+ const imageWidth = 600;
72
+ const imageHeight = 600;
73
+
74
+ // Preview image for block inserter
75
+ if (attributes.coverImage) {
76
+ return <img src={attributes.coverImage} width="468" />;
77
+ }
78
+
79
+ const handleLinkTextChange = (value: string) =>
80
+ setAttributes({
81
+ link: {
82
+ ...attributes.link,
83
+ title: value,
84
+ },
85
+ });
86
+
87
+ const handleLinkChange = (value: unknown) =>
88
+ setAttributes({
89
+ link: {
90
+ url: value?.url,
91
+ opensInNewTab: value?.opensInNewTab,
92
+ title: value?.title ?? attributes?.link?.title,
93
+ },
94
+ });
95
+
96
+ const handleLinkRemove = () => {
97
+ setAttributes({ link: null });
98
+ };
99
+
100
+ const handleImageSelect = (image: unknown) => {
101
+ setAttributes({ imgId: image?.id });
102
+ };
103
+ const handleImageRemove = () => {
104
+ setAttributes({ imgId: null });
105
+ };
106
+
107
+ const handleEnabledChange = (enabled: boolean, breakpoint: string) => {
108
+ // Set custom size enabled/disabled
109
+ // For some reason, this doesn't work with setImmutably
110
+ setAttributes({
111
+ customSize: {
112
+ ...attributes.customSize,
113
+ enabled: {
114
+ ...attributes.customSize?.enabled,
115
+ [breakpoint]: enabled,
116
+ },
117
+ },
118
+ });
119
+ };
120
+
121
+ const handleWidthChange = (width: number, breakpoint: string) => {
122
+ setAttributes(
123
+ setImmutably(attributes, ['customSize', 'width', breakpoint], width),
124
+ );
125
+ };
126
+
127
+ const handleHeightChange = (height: number, breakpoint: string) => {
128
+ setAttributes(
129
+ setImmutably(attributes, ['customSize', 'height', breakpoint], height),
130
+ );
131
+ };
132
+
133
+ const handleCropChange = (crop: boolean, breakpoint: string) => {
134
+ setAttributes(
135
+ setImmutably(attributes, ['customSize', 'crop', breakpoint], crop),
136
+ );
137
+ };
138
+
139
+ // const handleFocalPointChange = (value) => {
140
+ // setAttributes({ focalPoint: value });
141
+ // };
142
+
143
+ const { clientId } = props;
144
+ const { getSettings } = useSelect(blockEditorStore, []);
145
+ const { imageSizes } = useSelect(() => {
146
+ const settings = getSettings();
147
+
148
+ return {
149
+ imageSizes: settings.imageSizes,
150
+ };
151
+ }, [clientId]);
152
+
153
+ const imageSizeOptions = imageSizes.map(({ name, slug }) => ({
154
+ value: slug,
155
+ label: name,
156
+ }));
157
+
158
+ return (
159
+ <>
160
+ <InspectorControls>
161
+ <PanelBody title="Block Settings" initialOpen={true}>
162
+ <PanelRow>
163
+ <ToggleControl
164
+ label={__('Lazyload', 'webentor')}
165
+ checked={attributes.lazyload}
166
+ onChange={(lazyload) => setAttributes({ lazyload })}
167
+ />
168
+ </PanelRow>
169
+
170
+ <PanelRow>
171
+ {/* Open in lightbox */}
172
+ <ToggleControl
173
+ label={__('Open in lightbox', 'webentor')}
174
+ checked={attributes.openInLightbox}
175
+ onChange={(openInLightbox) => setAttributes({ openInLightbox })}
176
+ />
177
+ </PanelRow>
178
+
179
+ {/* TODO maybe move to BlockControls toolbar */}
180
+ {!attributes.openInLightbox && (
181
+ <PanelRow>
182
+ <div className="wbtr:w-full wbtr:border wbtr:border-editor-border wbtr:p-2">
183
+ <p>{__('Link Image to URL', 'webentor')}</p>
184
+
185
+ <div className="wbtr:flex wbtr:gap-2">
186
+ {/* External link */}
187
+ <Link
188
+ value={attributes?.link?.title}
189
+ url={attributes?.link?.url}
190
+ opensInNewTab={attributes?.link?.opensInNewTab}
191
+ onTextChange={handleLinkTextChange}
192
+ onLinkChange={handleLinkChange}
193
+ onLinkRemove={handleLinkRemove}
194
+ placeholder="Enter Link Text here..."
195
+ />
196
+ </div>
197
+ </div>
198
+ </PanelRow>
199
+ )}
200
+
201
+ {/* Full width */}
202
+ <PanelRow>
203
+ <ToggleControl
204
+ label={__('Make image full width', 'webentor')}
205
+ checked={attributes.fullWidth}
206
+ onChange={(fullWidth) => setAttributes({ fullWidth })}
207
+ />
208
+ </PanelRow>
209
+
210
+ {/* Aspect ratio select */}
211
+ <PanelRow>
212
+ <SelectControl
213
+ label={__('Aspect Ratio', 'webentor')}
214
+ value={attributes.aspectRatio}
215
+ options={[
216
+ { label: 'Auto', value: 'auto' },
217
+ { label: 'Square', value: 'square' },
218
+ { label: 'Video (16:9)', value: 'video' },
219
+ ]}
220
+ onChange={(aspectRatio) => setAttributes({ aspectRatio })}
221
+ />
222
+ </PanelRow>
223
+
224
+ {/* Object fit select */}
225
+ <PanelRow>
226
+ <SelectControl
227
+ label={__('Object Fit', 'webentor')}
228
+ value={attributes.objectFit}
229
+ options={[
230
+ { label: 'None', value: 'none' },
231
+ { label: 'Fill', value: 'fill' },
232
+ { label: 'Contain', value: 'contain' },
233
+ { label: 'Cover', value: 'cover' },
234
+ { label: 'Scale down', value: 'scale-down' },
235
+ ]}
236
+ onChange={(objectFit) => setAttributes({ objectFit })}
237
+ />
238
+ </PanelRow>
239
+
240
+ {/* Object position select */}
241
+ {attributes.objectFit && attributes.objectFit !== 'none' && (
242
+ <PanelRow>
243
+ <SelectControl
244
+ label={__('Object Position', 'webentor')}
245
+ value={attributes.objectPosition}
246
+ options={[
247
+ { label: 'Top', value: 'top' },
248
+ { label: 'Right Top', value: 'right-top' },
249
+ { label: 'Right', value: 'right' },
250
+ { label: 'Right Bottom', value: 'right-bottom' },
251
+ { label: 'Bottom', value: 'bottom' },
252
+ { label: 'Left Top', value: 'left-top' },
253
+ { label: 'Left', value: 'left' },
254
+ { label: 'Left Bottom', value: 'left-bottom' },
255
+ { label: 'Center', value: 'center' },
256
+ ]}
257
+ onChange={(objectPosition) => setAttributes({ objectPosition })}
258
+ />
259
+ </PanelRow>
260
+ )}
261
+
262
+ {/* Image size select with fetch for image sizes get_intermediate_image_sizes() */}
263
+ <PanelRow>
264
+ <SelectControl
265
+ label={__('Image Size', 'webentor')}
266
+ value={attributes.imageSize}
267
+ options={imageSizeOptions}
268
+ onChange={(imageSize) => setAttributes({ imageSize })}
269
+ help={__(
270
+ 'These sizes are automatically generated by WordPress. If you want to use custom image sizes, you can do so by enabling them below.',
271
+ 'webentor',
272
+ )}
273
+ />
274
+ </PanelRow>
275
+
276
+ <PanelRow>
277
+ <CustomImageSizesPanel
278
+ attributes={attributes}
279
+ imgSizeAttribute="customSize"
280
+ onEnabledChange={handleEnabledChange}
281
+ onWidthChange={handleWidthChange}
282
+ onHeightChange={handleHeightChange}
283
+ onCropChange={handleCropChange}
284
+ />
285
+ </PanelRow>
286
+ </PanelBody>
287
+ </InspectorControls>
288
+
289
+ <BlockControls>
290
+ <MediaToolbar
291
+ isOptional
292
+ id={attributes.imgId}
293
+ onSelect={handleImageSelect}
294
+ onRemove={handleImageRemove}
295
+ />
296
+ </BlockControls>
297
+
298
+ <div {...blockProps} className={blockProps.className}>
299
+ <Image
300
+ id={attributes.imgId}
301
+ size={attributes.imageSize}
302
+ onSelect={handleImageSelect}
303
+ className={`wbtr:rounded-[inherit] object-${attributes.objectFit} object-${attributes.objectPosition} aspect-${attributes.aspectRatio}`}
304
+ // focalPoint={attributes.focalPoint}
305
+ // onChangeFocalPoint={handleFocalPointChange}
306
+ labels={{
307
+ title: 'Select Image',
308
+ instructions: 'Upload or pick one from your media library.',
309
+ }}
310
+ width={attributes.customSize?.width?.basic || imageWidth}
311
+ height={attributes.customSize?.height?.basic || imageHeight}
312
+ />
313
+ </div>
314
+ </>
315
+ );
316
+ };
317
+
318
+ /**
319
+ * See https://wordpress.org/gutenberg/handbook/designers-developers/developers/block-api/block-edit-save/#save
320
+ *
321
+ * @return {null} Dynamic blocks do not save the HTML.
322
+ */
323
+ const BlockSave = () => null;
324
+
325
+ /**
326
+ * Register block.
327
+ */
328
+ registerBlockType(block, {
329
+ edit: BlockEdit,
330
+ save: BlockSave,
331
+ });
@@ -0,0 +1,25 @@
1
+ {
2
+ "$schema": "../../../schemas/webentor-block.json",
3
+ "apiVersion": 3,
4
+ "name": "webentor/e-picker-query-loop",
5
+ "title": "Posts Picker Query Loop",
6
+ "description": "Display selected posts in a loop.",
7
+ "category": "webentor-elements",
8
+ "icon": "update",
9
+ "keywords": ["loop", "query", "picker"],
10
+ "attributes": {
11
+ "query": {
12
+ "type": "object",
13
+ "default": {
14
+ "postType": ["post"],
15
+ "posts": [],
16
+ "queryId": ""
17
+ }
18
+ },
19
+ "template": {
20
+ "type": "array",
21
+ "default": null
22
+ }
23
+ },
24
+ "supports": {}
25
+ }