@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,424 @@
1
+ import { useState } from 'react';
2
+ import {
3
+ Icon as Icon10up,
4
+ IconPickerToolbarButton,
5
+ } from '@10up/block-components';
6
+ import { URLInput } from '@wordpress/block-editor';
7
+ import {
8
+ Icon,
9
+ Popover,
10
+ SelectControl,
11
+ TextControl,
12
+ ToggleControl,
13
+ } from '@wordpress/components';
14
+ import { applyFilters } from '@wordpress/hooks';
15
+ import { __ } from '@wordpress/i18n';
16
+
17
+ /**
18
+ * Button component.
19
+ *
20
+ * @param {object} props
21
+ * @param {string} props.attributeName Attribute name for button object, e.g. "button".
22
+ * @param {string} props.placement Popover placement
23
+ * @param {boolean} props.hideVariant Whether variants select should be displayed.
24
+ * @param {boolean} props.hideAction Whether action select should be displayed.
25
+ * @param {boolean} props.hideLink Whether url and open in new tab toggle should be displayed.
26
+ * @param {boolean} props.hidePopup Whether popup select should be displayed.
27
+ * @param {string} props.className Classes.
28
+ * @param {string} props.innerClassName Inner classes.
29
+ * @param {string} props.buttonClassName Button classes.
30
+ * @returns {Function} Render the component.
31
+ */
32
+
33
+ /**
34
+ * Button attributes in block.json
35
+ *
36
+ "button": {
37
+ "type": "object",
38
+ "properties": {
39
+ "showButton": {
40
+ "type": "boolean"
41
+ }
42
+ "title": {
43
+ "type": "string"
44
+ },
45
+ "variant": {
46
+ "type": "string",
47
+ enum: [ "primary", "secondary", "tertiary" ],
48
+ },
49
+ "size": {
50
+ "type": "string",
51
+ enum: [ "small", "medium", "large" ],
52
+ },
53
+ "url": {
54
+ "type": "string"
55
+ },
56
+ "newTab": {
57
+ "type": "boolean"
58
+ },
59
+ "showIcon": {
60
+ "type": "boolean"
61
+ },
62
+ "icon": {
63
+ "type": "object",
64
+ "properties": {
65
+ "name": { "type": "string" },
66
+ "iconSet": { "type": "string" }
67
+ }
68
+ },
69
+ "iconPosition": {
70
+ "type": "string",
71
+ }
72
+ "htmlElement": {
73
+ "type": "string"
74
+ }
75
+ },
76
+ "default": {
77
+ "showButton": true,
78
+ "title": "Button",
79
+ "variant": "primary"
80
+ "url": "#",
81
+ "newTab": false,
82
+ "showIcon": false,
83
+ "icon": null,
84
+ "iconPosition": "right",
85
+ "htmlElement": "a"
86
+ }
87
+ }
88
+ */
89
+
90
+ export const WebentorButton = (props) => {
91
+ const {
92
+ placement,
93
+ className,
94
+ innerClassName,
95
+ hideVariant,
96
+ hideSize,
97
+ hideLink,
98
+ attributeName,
99
+ attributes,
100
+ setAttributes,
101
+ } = props;
102
+
103
+ const [visible, setVisible] = useState(false);
104
+
105
+ function updateObjectAttribute(obj, attr, value) {
106
+ const tempObj = { ...attributes[obj] };
107
+ tempObj[attr] = value;
108
+ setAttributes({ [obj]: tempObj });
109
+ }
110
+
111
+ const buttonClassName = applyFilters(
112
+ 'webentor.core.button.className',
113
+ props.buttonClassName,
114
+ props,
115
+ ) as string;
116
+
117
+ const variants = applyFilters('webentor.core.button.variants', [
118
+ {
119
+ slug: 'primary',
120
+ label: __('Primary', 'webentor'),
121
+ },
122
+ {
123
+ slug: 'secondary',
124
+ label: __('Secondary', 'webentor'),
125
+ },
126
+ {
127
+ slug: 'tertiary',
128
+ label: __('Tertiary', 'webentor'),
129
+ },
130
+ ]) as { slug: string; label: string }[];
131
+
132
+ const sizes = applyFilters('webentor.core.button.sizes', [
133
+ {
134
+ slug: 'small',
135
+ label: __('Small', 'webentor'),
136
+ },
137
+ {
138
+ slug: 'medium',
139
+ label: __('Medium', 'webentor'),
140
+ },
141
+ {
142
+ slug: 'large',
143
+ label: __('Large', 'webentor'),
144
+ },
145
+ ]) as { slug: string; label: string }[];
146
+
147
+ const iconPositions = applyFilters('webentor.core.button.iconPositions', [
148
+ { label: 'Left', value: 'left' },
149
+ { label: 'Right', value: 'right' },
150
+ { label: 'Alone', value: 'alone' },
151
+ ]) as { label: string; value: string }[];
152
+
153
+ // This hook allows us to extend button with additional components, settings, etc.
154
+ const ExtensionComponent = applyFilters(
155
+ 'webentor.core.button.extensionComponent',
156
+ <></>,
157
+ props,
158
+ ) as React.ReactNode;
159
+
160
+ const variant = attributes[attributeName]?.variant
161
+ ? attributes[attributeName]?.variant
162
+ : 'primary';
163
+
164
+ const size = attributes[attributeName]?.size
165
+ ? attributes[attributeName]?.size
166
+ : 'medium';
167
+
168
+ const handleTogglePopover = () => {
169
+ setVisible(!visible);
170
+ };
171
+
172
+ const handleIconSelection = (value) =>
173
+ updateObjectAttribute(attributeName, 'icon', {
174
+ name: value.name,
175
+ iconSet: value.iconSet,
176
+ });
177
+
178
+ const ButtonOutput = applyFilters(
179
+ 'webentor.core.button.output',
180
+ <button
181
+ type="button"
182
+ className={`btn btn--${variant} btn--size-${size} ${buttonClassName ?? ''} wbtr:prevent-hover ${attributes[attributeName]?.showIcon && attributes[attributeName]?.icon?.name ? 'btn--icon' : ''} ${attributes[attributeName]?.iconPosition ? `btn--icon-${attributes[attributeName]?.iconPosition}` : ''} ${!attributes[attributeName]?.showButton ? 'wbtr:opacity-40' : ''}`}
183
+ >
184
+ <span className="btn__text">
185
+ {attributes[attributeName] && attributes[attributeName]?.title
186
+ ? attributes[attributeName]?.title
187
+ : ''}
188
+ </span>
189
+
190
+ {attributes[attributeName]?.showIcon &&
191
+ attributes[attributeName]?.icon?.name && (
192
+ <span className="btn__icon svg-icon">
193
+ <Icon10up
194
+ name={attributes[attributeName]?.icon.name}
195
+ iconSet={attributes[attributeName]?.icon.iconSet}
196
+ />
197
+ </span>
198
+ )}
199
+ </button>,
200
+ props,
201
+ buttonClassName,
202
+ );
203
+
204
+ return (
205
+ <span className={`${className ?? ''} wbtr:relative wbtr:inline-block`}>
206
+ {visible && (
207
+ <Popover
208
+ placement={placement ?? 'bottom'}
209
+ shift
210
+ onFocusOutside={handleTogglePopover}
211
+ >
212
+ <div className="wbtr:w-[320px] wbtr:p-2">
213
+ <h4 className="wbtr:flex wbtr:text-14 wbtr:uppercase">
214
+ {__('Button Settings', 'webentor')}
215
+ <button className="wbtr:ml-auto" onClick={handleTogglePopover}>
216
+ <Icon icon="no-alt" />
217
+ </button>
218
+ </h4>
219
+
220
+ <hr className="wbtr:mt-2 wbtr:mb-3" />
221
+
222
+ <ToggleControl
223
+ label={__('Show button', 'webentor')}
224
+ checked={
225
+ attributes[attributeName] &&
226
+ attributes[attributeName]?.showButton
227
+ ? attributes[attributeName]?.showButton
228
+ : false
229
+ }
230
+ onChange={(value) =>
231
+ updateObjectAttribute(attributeName, 'showButton', value)
232
+ }
233
+ />
234
+
235
+ <TextControl
236
+ label={__('Button Title', 'webentor')}
237
+ value={
238
+ attributes[attributeName] && attributes[attributeName]?.title
239
+ ? attributes[attributeName]?.title
240
+ : ''
241
+ }
242
+ onChange={(value) =>
243
+ updateObjectAttribute(attributeName, 'title', value)
244
+ }
245
+ className="wbtr:mb-3"
246
+ />
247
+
248
+ {!hideVariant && (
249
+ <div className="wbtr:mb-3">
250
+ <div className="wbtr:mt-0 wbtr:mb-2 wbtr:text-[11px] wbtr:uppercase">
251
+ {__('Button Variant', 'webentor')}
252
+ </div>
253
+ {variants.map((item) => {
254
+ return (
255
+ <button
256
+ key={item.slug}
257
+ onClick={() =>
258
+ updateObjectAttribute(
259
+ attributeName,
260
+ 'variant',
261
+ item.slug,
262
+ )
263
+ }
264
+ className={`wbtr:pr-2 ${variant === item.slug ? 'wbtr:font-bold!' : ''}`}
265
+ >
266
+ {item.label}
267
+ </button>
268
+ );
269
+ })}
270
+ </div>
271
+ )}
272
+
273
+ {!hideSize && (
274
+ <div className="wbtr:mb-3">
275
+ <div className="wbtr:mt-0 wbtr:mb-2 wbtr:text-[11px] wbtr:uppercase">
276
+ {__('Button Size', 'webentor')}
277
+ </div>
278
+ {sizes.map((item) => {
279
+ return (
280
+ <button
281
+ key={item.slug}
282
+ onClick={() =>
283
+ updateObjectAttribute(attributeName, 'size', item.slug)
284
+ }
285
+ className={`wbtr:pr-2 ${
286
+ attributes[attributeName]?.size === item.slug
287
+ ? 'wbtr:font-bold!'
288
+ : ''
289
+ }`}
290
+ >
291
+ {item.label}
292
+ </button>
293
+ );
294
+ })}
295
+ </div>
296
+ )}
297
+
298
+ {ExtensionComponent}
299
+
300
+ <SelectControl
301
+ label={__('Button HTML Element', 'webentor')}
302
+ value={attributes[attributeName]?.htmlElement}
303
+ options={[
304
+ { label: __('Link (<a>)', 'webentor'), value: 'a' },
305
+ { label: __('Button (<button>)', 'webentor'), value: 'button' },
306
+ ]}
307
+ onChange={(value) =>
308
+ updateObjectAttribute(attributeName, 'htmlElement', value)
309
+ }
310
+ />
311
+
312
+ {!hideLink && attributes[attributeName]?.htmlElement === 'a' && (
313
+ <>
314
+ <div className="wbtr:mt-0 wbtr:mb-2 wbtr:text-[11px] wbtr:uppercase">
315
+ {__('Button URL', 'webentor')}
316
+ </div>
317
+ <URLInput
318
+ // label={__('Button URL', 'webentor')}
319
+ value={
320
+ attributes[attributeName] && attributes[attributeName]?.url
321
+ ? attributes[attributeName]?.url
322
+ : ''
323
+ }
324
+ onChange={(value) =>
325
+ updateObjectAttribute(attributeName, 'url', value)
326
+ }
327
+ className="wbtr:mb-2"
328
+ />
329
+
330
+ <ToggleControl
331
+ label={__('Open in new tab', 'webentor')}
332
+ checked={
333
+ attributes[attributeName] &&
334
+ attributes[attributeName]?.newTab
335
+ ? attributes[attributeName]?.newTab
336
+ : false
337
+ }
338
+ onChange={(value) =>
339
+ updateObjectAttribute(attributeName, 'newTab', value)
340
+ }
341
+ />
342
+ </>
343
+ )}
344
+
345
+ <div className="wbtr:border wbtr:border-editor-border wbtr:p-2">
346
+ <div className="wbtr:my-2">
347
+ <ToggleControl
348
+ label="Show Button Icon"
349
+ checked={attributes[attributeName]?.showIcon}
350
+ onChange={(value) =>
351
+ updateObjectAttribute(attributeName, 'showIcon', value)
352
+ }
353
+ />
354
+ </div>
355
+
356
+ {attributes[attributeName]?.showIcon && (
357
+ <div>
358
+ <div className="wbtr:mb-2 wbtr:flex wbtr:items-center wbtr:gap-4">
359
+ <IconPickerToolbarButton
360
+ label="Icon"
361
+ value={attributes[attributeName]?.icon}
362
+ onChange={handleIconSelection}
363
+ />
364
+ {attributes[attributeName]?.icon?.name ? (
365
+ <div className="wbtr:size-10">
366
+ <Icon10up
367
+ name={attributes[attributeName]?.icon.name}
368
+ iconSet={attributes[attributeName]?.icon.iconSet}
369
+ />
370
+ </div>
371
+ ) : (
372
+ 'No icon selected'
373
+ )}
374
+ </div>
375
+ <div className="wbtr:mb-2">
376
+ <SelectControl
377
+ label="Icon Position"
378
+ value={attributes[attributeName]?.iconPosition}
379
+ options={iconPositions}
380
+ onChange={(value) =>
381
+ updateObjectAttribute(
382
+ attributeName,
383
+ 'iconPosition',
384
+ value,
385
+ )
386
+ }
387
+ />
388
+ </div>
389
+ </div>
390
+ )}
391
+ </div>
392
+ </div>
393
+ </Popover>
394
+ )}
395
+
396
+ <span
397
+ className={`${innerClassName ?? ''} wbtr:inline-block`}
398
+ onClick={handleTogglePopover}
399
+ >
400
+ {!attributes[attributeName]?.showButton && (
401
+ <span className="wbtr:rounded wbtr:absolute wbtr:-top-1 wbtr:-right-1 wbtr:z-10 wbtr:flex wbtr:h-4 wbtr:w-6 wbtr:items-center wbtr:justify-center wbtr:bg-white wbtr:shadow">
402
+ <svg
403
+ viewBox="0 0 24 24"
404
+ xmlns="http://www.w3.org/2000/svg"
405
+ className="wbtr:h-4 wbtr:w-5"
406
+ >
407
+ <rect
408
+ x="18.364"
409
+ y="4.22183"
410
+ width="2"
411
+ height="20"
412
+ rx="1"
413
+ transform="rotate(45 18.364 4.22183)"
414
+ />
415
+ <path d="M14.7716 6.40004C13.8862 6.149 12.9574 6 12 6C5.92487 6 1 12 1 12C1 12 2.71502 14.0894 5.36939 15.8023L6.82033 14.3513C6.33195 14.0549 5.86521 13.7341 5.42544 13.4027C4.77864 12.9153 4.2185 12.4263 3.76677 12C4.2185 11.5737 4.77864 11.0847 5.42544 10.5973C7.27304 9.20505 9.59678 8 12 8C12.3661 8 12.7303 8.02796 13.0914 8.0803L14.7716 6.40004ZM12.1671 9.00457C12.1118 9.00154 12.0561 9 12 9C10.3431 9 9 10.3431 9 12C9 12.0561 9.00154 12.1118 9.00457 12.1671L12.1671 9.00457ZM11.8331 14.9954L14.9954 11.8331C14.9985 11.8883 15 11.944 15 12C15 13.6569 13.6569 15 12 15C11.944 15 11.8883 14.9985 11.8331 14.9954ZM10.9088 15.9197C11.2697 15.972 11.6339 16 12 16C14.4032 16 16.727 14.795 18.5746 13.4027C19.2214 12.9153 19.7815 12.4263 20.2332 12C19.7815 11.5737 19.2214 11.0847 18.5746 10.5973C18.1348 10.2659 17.6681 9.94516 17.1798 9.64873L18.6307 8.1978C21.285 9.91063 23 12 23 12C23 12 18.0751 18 12 18C11.0427 18 10.1139 17.851 9.22851 17.6L10.9088 15.9197Z" />
416
+ </svg>
417
+ </span>
418
+ )}
419
+
420
+ {ButtonOutput}
421
+ </span>
422
+ </span>
423
+ );
424
+ };
@@ -0,0 +1,197 @@
1
+ import { BlockEditProps } from '@wordpress/blocks';
2
+ import {
3
+ __experimentalNumberControl as NumberControl,
4
+ TabPanel,
5
+ ToggleControl,
6
+ } from '@wordpress/components';
7
+ import { applyFilters } from '@wordpress/hooks';
8
+ import { __ } from '@wordpress/i18n';
9
+
10
+ type Props = {
11
+ attributes: BlockEditProps['attributes'];
12
+ imgSizeAttribute: string;
13
+ onEnabledChange: (enabled: boolean, breakpoint: string) => void;
14
+ onWidthChange?: (width: number, breakpoint: string) => void;
15
+ onHeightChange?: (height: number, breakpoint: string) => void;
16
+ onCropChange?: (crop: boolean, breakpoint: string) => void;
17
+ alwaysEnabled?: boolean;
18
+ hideHeight?: boolean;
19
+ hideWidth?: boolean;
20
+ hideCrop?: boolean;
21
+ noticeBefore?: () => React.ReactNode;
22
+ noticeAfter?: () => React.ReactNode;
23
+ };
24
+
25
+ /**
26
+ * Display the custom image sizes tabs.
27
+ *
28
+ * Used in blocks like e-gallery and e-image.
29
+ */
30
+ export const CustomImageSizesPanel: React.FC<Props> = (props: Props) => {
31
+ const {
32
+ attributes,
33
+ imgSizeAttribute,
34
+ onEnabledChange,
35
+ onWidthChange,
36
+ onHeightChange,
37
+ onCropChange,
38
+ alwaysEnabled,
39
+ hideHeight,
40
+ hideWidth,
41
+ hideCrop,
42
+ noticeBefore,
43
+ noticeAfter,
44
+ } = props;
45
+
46
+ const breakpoints = applyFilters('webentor.core.twBreakpoints', ['basic']);
47
+
48
+ const hasSizeSettingsForBreakpoint = (attributes, breakpoint) => {
49
+ return (
50
+ attributes?.[imgSizeAttribute]?.enabled?.[breakpoint] ||
51
+ attributes?.[imgSizeAttribute]?.width?.[breakpoint] ||
52
+ attributes?.[imgSizeAttribute]?.height?.[breakpoint]
53
+ );
54
+ };
55
+
56
+ return (
57
+ <div>
58
+ <p className="wbtr:uppercase">{__('Custom Image sizes', 'webentor')}</p>
59
+
60
+ {noticeBefore && noticeBefore()}
61
+
62
+ <div>
63
+ Help: These sizes are defined <strong>UP TO</strong> specific
64
+ breakpoint, e.g. if you define sizes for `sm`, it means image would be
65
+ displayed on screens up to `sm` (max-width:480px). Always define{' '}
66
+ <strong>basic</strong> breakpoint first as it would be used as default
67
+ image size.
68
+ </div>
69
+
70
+ {noticeAfter && noticeAfter()}
71
+
72
+ <TabPanel
73
+ activeClass="is-active"
74
+ className="w-responsive-settings-tabs"
75
+ initialTabName={breakpoints[0]}
76
+ tabs={
77
+ breakpoints.map((breakpoint) => ({
78
+ name: breakpoint,
79
+ title: `${breakpoint}${hasSizeSettingsForBreakpoint(attributes, breakpoint) ? '*' : ''}`, // Add * if spacing is set on this breakpoint
80
+ })) || []
81
+ }
82
+ >
83
+ {(tab) => (
84
+ <div
85
+ className="wbtr:mt-4 wbtr:flex wbtr:flex-wrap wbtr:justify-center wbtr:gap-x-4"
86
+ key={tab.name}
87
+ >
88
+ {/* <Button
89
+ onClick={() => {
90
+ setAttributes(
91
+ setImmutably(
92
+ attributes,
93
+ [imgSizeAttribute, 'width', tab.name],
94
+ '0',
95
+ ),
96
+ );
97
+ setAttributes(
98
+ setImmutably(
99
+ attributes,
100
+ [imgSizeAttribute, 'height', tab.name],
101
+ '0',
102
+ ),
103
+ );
104
+ setAttributes(
105
+ setImmutably(
106
+ attributes,
107
+ [imgSizeAttribute, 'crop', tab.name],
108
+ false,
109
+ ),
110
+ );
111
+ }}
112
+ >
113
+ Reset sizes
114
+ </Button> */}
115
+
116
+ {/* Enable custom size */}
117
+ {!alwaysEnabled && (
118
+ <ToggleControl
119
+ label={__('Enable custom sizes', 'webentor')}
120
+ checked={
121
+ attributes?.[imgSizeAttribute]?.enabled?.[tab.name] || false
122
+ }
123
+ className="wbtr:mb-2!"
124
+ onChange={(enabled) =>
125
+ onEnabledChange && onEnabledChange(enabled, tab.name)
126
+ }
127
+ />
128
+ )}
129
+
130
+ {(attributes?.[imgSizeAttribute]?.enabled?.[tab.name] ||
131
+ alwaysEnabled) && (
132
+ <>
133
+ <div className="wbtr:mb-2">
134
+ If only one of the sizes is set and <strong>Crop</strong> is
135
+ disabled, the image will resize, but also keep its aspect
136
+ ratio.
137
+ </div>
138
+
139
+ {/* Custom image size with with, heigh and crop */}
140
+ <div className="wbtr:flex wbtr:gap-2">
141
+ {/* Width number control */}
142
+ {!hideWidth && (
143
+ <NumberControl
144
+ label={__('Width', 'webentor')}
145
+ value={
146
+ attributes?.[imgSizeAttribute]?.width?.[tab.name] || '0'
147
+ }
148
+ min={0}
149
+ onChange={(width: string) =>
150
+ onWidthChange && onWidthChange(Number(width), tab.name)
151
+ }
152
+ className="wbtr:mb-2!"
153
+ />
154
+ )}
155
+
156
+ {/* Height number control */}
157
+ {!hideHeight && (
158
+ <NumberControl
159
+ label={__('Height', 'webentor')}
160
+ value={
161
+ attributes?.[imgSizeAttribute]?.height?.[tab.name] ||
162
+ '0'
163
+ }
164
+ min={0}
165
+ onChange={(height: string) =>
166
+ onHeightChange &&
167
+ onHeightChange(Number(height), tab.name)
168
+ }
169
+ className="wbtr:mb-2!"
170
+ />
171
+ )}
172
+ </div>
173
+
174
+ {/* Toggle crop */}
175
+ {!hideCrop && (
176
+ <ToggleControl
177
+ label={__('Crop', 'webentor')}
178
+ help={__(
179
+ 'Only if both width and height are set, the image will be cropped to the specified size.',
180
+ 'webentor',
181
+ )}
182
+ checked={
183
+ attributes?.[imgSizeAttribute]?.crop?.[tab.name] || false
184
+ }
185
+ onChange={(crop) =>
186
+ onCropChange && onCropChange(crop, tab.name)
187
+ }
188
+ />
189
+ )}
190
+ </>
191
+ )}
192
+ </div>
193
+ )}
194
+ </TabPanel>
195
+ </div>
196
+ );
197
+ };
@@ -0,0 +1,4 @@
1
+ export { WebentorBlockAppender } from './block-appender';
2
+ export { WebentorButton } from './button';
3
+ export { WebentorTypographyPickerSelect } from './typography-picker-select';
4
+ export { CustomImageSizesPanel } from './custom-image-sizes-panel';
@@ -0,0 +1,31 @@
1
+ import { CustomSelectControl } from '@wordpress/components';
2
+ import { __, sprintf } from '@wordpress/i18n';
3
+
4
+ export const WebentorTypographyPickerSelect = (props) => {
5
+ const { __next40pxDefaultSize, value, onChange, options } = props;
6
+
7
+ const selectedOption = value
8
+ ? options.find((option) => option.value === value)
9
+ : null;
10
+
11
+ return (
12
+ <div className="wbtr:w-full">
13
+ <CustomSelectControl
14
+ __next40pxDefaultSize={__next40pxDefaultSize}
15
+ className="components-typography-picker__select"
16
+ label={__('Custom Typography')}
17
+ describedBy={sprintf(
18
+ // translators: %s: Currently selected typography.
19
+ __('Currently selected typography: %s'),
20
+ selectedOption?.name,
21
+ )}
22
+ options={options}
23
+ value={selectedOption}
24
+ showSelectedHint
25
+ onChange={({ selectedItem }) => {
26
+ onChange(selectedItem.value);
27
+ }}
28
+ />
29
+ </div>
30
+ );
31
+ };