PluginProbe
Blockenberg — 600+ Advanced Gutenberg Blocks & AI Agent for WordPress Block Editor / 2.0.7
Blockenberg — 600+ Advanced Gutenberg Blocks & AI Agent for WordPress Block Editor v2.0.7
2.0.13 2.0.12 2.0.11 2.0.10 2.0.9 trunk 2.0.2 2.0.3 2.0.4 2.0.5 2.0.6 2.0.7 2.0.8
blockenberg / blocks / modal / index.js

index.js in Blockenberg — 600+ Advanced Gutenberg Blocks & AI Agent for WordPress Block Editor 2.0.7, at blocks/modal/index.js

461 lines 23.3 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 ( function () {
2 var el = wp.element.createElement;
3 var Fragment = wp.element.Fragment;
4 var __ = wp.i18n.__;
5 var useState = wp.element.useState;
6 var registerBlockType = wp.blocks.registerBlockType;
7 var InspectorControls = wp.blockEditor.InspectorControls;
8 var useBlockProps = wp.blockEditor.useBlockProps;
9 var RichText = wp.blockEditor.RichText;
10 var PanelBody = wp.components.PanelBody;
11 var PanelColorSettings = wp.blockEditor.PanelColorSettings;
12 var ToggleControl = wp.components.ToggleControl;
13 var RangeControl = wp.components.RangeControl;
14 var SelectControl = wp.components.SelectControl;
15 var TextControl = wp.components.TextControl;
16 var Button = wp.components.Button;
17
18 var _tc, _tv;
19 function getTypoControl() { return _tc || (_tc = window.bkbgTypographyControl); }
20 function getTypoCssVars() { return _tv || (_tv = window.bkbgTypoCssVars); }
21
22 var sizeOptions = [
23 { label: __('Small (480px)', 'blockenberg'), value: 'sm' },
24 { label: __('Medium (640px)', 'blockenberg'), value: 'md' },
25 { label: __('Large (800px)', 'blockenberg'), value: 'lg' },
26 { label: __('Extra Large (1100px)', 'blockenberg'), value: 'xl' },
27 { label: __('Full Screen', 'blockenberg'), value: 'full' }
28 ];
29
30 var animationOptions = [
31 { label: __('Zoom In', 'blockenberg'), value: 'zoom' },
32 { label: __('Slide Up', 'blockenberg'), value: 'slide-up' },
33 { label: __('Slide Down', 'blockenberg'), value: 'slide-down' },
34 { label: __('Fade', 'blockenberg'), value: 'fade' },
35 { label: __('None', 'blockenberg'), value: 'none' }
36 ];
37
38 var triggerModeOptions = [
39 { label: __('Click (manual)', 'blockenberg'), value: 'click' },
40 { label: __('Auto (after delay)', 'blockenberg'), value: 'auto' }
41 ];
42
43 var btnStyleOptions = [
44 { label: __('Primary (filled)', 'blockenberg'), value: 'primary' },
45 { label: __('Outline', 'blockenberg'), value: 'outline' },
46 { label: __('Ghost / Text', 'blockenberg'), value: 'ghost' }
47 ];
48
49 var btnSizeOptions = [
50 { label: __('Small', 'blockenberg'), value: 'sm' },
51 { label: __('Medium', 'blockenberg'), value: 'md' },
52 { label: __('Large', 'blockenberg'), value: 'lg' }
53 ];
54
55 var alignOptions = [
56 { label: __('Left', 'blockenberg'), value: 'left' },
57 { label: __('Center', 'blockenberg'), value: 'center' },
58 { label: __('Right', 'blockenberg'), value: 'right' }
59 ];
60
61 registerBlockType('blockenberg/modal', {
62 edit: function (props) {
63 var a = props.attributes;
64 var setAttributes = props.setAttributes;
65 var previewOpen = useState(false);
66 var isPreviewOpen = previewOpen[0];
67 var setPreviewOpen = previewOpen[1];
68
69 var blockProps = useBlockProps((function () {
70 var _tvf = getTypoCssVars();
71 var s = {
72 '--bkbg-modal-bg': a.modalBg,
73 '--bkbg-modal-radius': a.modalRadius + 'px',
74 '--bkbg-modal-padding': a.modalPadding + 'px',
75 '--bkbg-modal-title-size': a.titleSize + 'px',
76 '--bkbg-modal-title-weight': a.titleWeight,
77 '--bkbg-modal-title-color': a.titleColor,
78 '--bkbg-modal-content-size': a.contentSize + 'px',
79 '--bkbg-modal-content-color': a.contentColor,
80 '--bkbg-modal-content-lh': a.contentLineHeight,
81 '--bkbg-modal-title-lh': a.titleLineHeight,
82 '--bkbg-modal-close-color': a.closeBtnColor,
83 '--bkbg-modal-close-hover': a.closeBtnHoverColor,
84 '--bkbg-modal-overlay-bg': a.overlayBg,
85 '--bkbg-modal-btn-bg': a.triggerBtnBg,
86 '--bkbg-modal-btn-color': a.triggerBtnColor,
87 '--bkbg-modal-btn-radius': a.triggerBtnRadius + 'px'
88 };
89 Object.assign(s, _tvf(a.titleTypo, '--bkbg-modal-tt-'));
90 Object.assign(s, _tvf(a.bodyTypo, '--bkbg-modal-bd-'));
91 return { className: 'bkbg-modal-block', style: s, 'data-trigger-align': a.triggerAlignment };
92 })());
93
94 var inspector = el(InspectorControls, {},
95
96 el(PanelBody, { title: __('Trigger Button', 'blockenberg'), initialOpen: true },
97 el(TextControl, {
98 label: __('Button Label', 'blockenberg'),
99 value: a.triggerLabel,
100 onChange: function (v) { setAttributes({ triggerLabel: v }); }
101 }),
102 el(SelectControl, {
103 label: __('Button Style', 'blockenberg'),
104 value: a.triggerBtnStyle,
105 options: btnStyleOptions,
106 onChange: function (v) { setAttributes({ triggerBtnStyle: v }); }
107 }),
108 el(SelectControl, {
109 label: __('Button Size', 'blockenberg'),
110 value: a.triggerBtnSize,
111 options: btnSizeOptions,
112 onChange: function (v) { setAttributes({ triggerBtnSize: v }); }
113 }),
114 el(SelectControl, {
115 label: __('Alignment', 'blockenberg'),
116 value: a.triggerAlignment,
117 options: alignOptions,
118 onChange: function (v) { setAttributes({ triggerAlignment: v }); }
119 }),
120 el(RangeControl, {
121 label: __('Border Radius (px)', 'blockenberg'),
122 value: a.triggerBtnRadius,
123 min: 0, max: 50,
124 onChange: function (v) { setAttributes({ triggerBtnRadius: v }); }
125 })
126 ),
127
128 el(PanelBody, { title: __('Modal Content', 'blockenberg'), initialOpen: false },
129 el(TextControl, {
130 label: __('Modal Title', 'blockenberg'),
131 value: a.modalTitle,
132 onChange: function (v) { setAttributes({ modalTitle: v }); }
133 }),
134 el(ToggleControl, {
135 label: __('Show Header', 'blockenberg'),
136 checked: a.showHeader,
137 __nextHasNoMarginBottom: true,
138 onChange: function (v) { setAttributes({ showHeader: v }); }
139 })
140 ),
141
142 el(PanelBody, { title: __('Modal Style', 'blockenberg'), initialOpen: false },
143 el(SelectControl, {
144 label: __('Modal Size', 'blockenberg'),
145 value: a.modalSize,
146 options: sizeOptions,
147 onChange: function (v) { setAttributes({ modalSize: v }); }
148 }),
149 el(SelectControl, {
150 label: __('Open Animation', 'blockenberg'),
151 value: a.animation,
152 options: animationOptions,
153 onChange: function (v) { setAttributes({ animation: v }); }
154 }),
155 el(RangeControl, {
156 label: __('Modal Border Radius (px)', 'blockenberg'),
157 value: a.modalRadius, min: 0, max: 32,
158 onChange: function (v) { setAttributes({ modalRadius: v }); }
159 }),
160 el(RangeControl, {
161 label: __('Modal Padding (px)', 'blockenberg'),
162 value: a.modalPadding, min: 12, max: 64,
163 onChange: function (v) { setAttributes({ modalPadding: v }); }
164 }),
165 el(ToggleControl, {
166 label: __('Blur Overlay Background', 'blockenberg'),
167 checked: a.overlayBlur,
168 __nextHasNoMarginBottom: true,
169 onChange: function (v) { setAttributes({ overlayBlur: v }); }
170 })
171 ),
172
173 el(PanelBody, { title: __('Behavior', 'blockenberg'), initialOpen: false },
174 el(SelectControl, {
175 label: __('Trigger Mode', 'blockenberg'),
176 value: a.triggerMode,
177 options: triggerModeOptions,
178 onChange: function (v) { setAttributes({ triggerMode: v }); }
179 }),
180 a.triggerMode === 'auto' && el(RangeControl, {
181 label: __('Auto Open Delay (ms)', 'blockenberg'),
182 value: a.autoDelay, min: 0, max: 15000, step: 500,
183 onChange: function (v) { setAttributes({ autoDelay: v }); }
184 }),
185 el(ToggleControl, {
186 label: __('Show Close Button', 'blockenberg'),
187 checked: a.showCloseBtn,
188 __nextHasNoMarginBottom: true,
189 onChange: function (v) { setAttributes({ showCloseBtn: v }); }
190 }),
191 el(ToggleControl, {
192 label: __('Close on Overlay Click', 'blockenberg'),
193 checked: a.closeOnOverlay,
194 __nextHasNoMarginBottom: true,
195 onChange: function (v) { setAttributes({ closeOnOverlay: v }); }
196 }),
197 el(ToggleControl, {
198 label: __('Close on Escape Key', 'blockenberg'),
199 checked: a.closeOnEsc,
200 __nextHasNoMarginBottom: true,
201 onChange: function (v) { setAttributes({ closeOnEsc: v }); }
202 })
203 ),
204
205 el(PanelBody, { title: __('Typography', 'blockenberg'), initialOpen: false },
206 el(getTypoControl(), {
207 label: __('Title', 'blockenberg'),
208 value: a.titleTypo,
209 onChange: function (v) { setAttributes({ titleTypo: v }); }
210 }),
211 el(getTypoControl(), {
212 label: __('Body', 'blockenberg'),
213 value: a.bodyTypo,
214 onChange: function (v) { setAttributes({ bodyTypo: v }); }
215 })
216 ),
217
218 el(PanelBody, { title: __('Colors', 'blockenberg'), initialOpen: false },
219 el(PanelColorSettings, {
220 title: __('Button Colors', 'blockenberg'),
221 initialOpen: false,
222 colorSettings: [
223 { value: a.triggerBtnBg, onChange: function (c) { setAttributes({ triggerBtnBg: c || '#2563eb' }); }, label: __('Button Background', 'blockenberg') },
224 { value: a.triggerBtnColor, onChange: function (c) { setAttributes({ triggerBtnColor: c || '#ffffff' }); }, label: __('Button Text', 'blockenberg') }
225 ]
226 }),
227 el(PanelColorSettings, {
228 title: __('Modal Colors', 'blockenberg'),
229 initialOpen: false,
230 colorSettings: [
231 { value: a.modalBg, onChange: function (c) { setAttributes({ modalBg: c || '#ffffff' }); }, label: __('Modal Background', 'blockenberg') },
232 { value: a.titleColor, onChange: function (c) { setAttributes({ titleColor: c || '#111827' }); }, label: __('Title', 'blockenberg') },
233 { value: a.contentColor, onChange: function (c) { setAttributes({ contentColor: c || '#374151' }); }, label: __('Content Text', 'blockenberg') },
234 { value: a.closeBtnColor, onChange: function (c) { setAttributes({ closeBtnColor: c || '#6b7280' }); }, label: __('Close Button', 'blockenberg') }
235 ]
236 })
237 )
238 );
239
240 // Trigger button preview
241 var triggerBtnClass = 'bkbg-modal-trigger bkbg-modal-btn-' + a.triggerBtnStyle + ' bkbg-modal-btn-' + a.triggerBtnSize;
242
243 return el(Fragment, {},
244 inspector,
245 el('div', blockProps,
246 // Trigger area
247 el('div', { className: 'bkbg-modal-trigger-wrap', style: { textAlign: a.triggerAlignment } },
248 el('button', {
249 className: triggerBtnClass,
250 onClick: function () { setPreviewOpen(!isPreviewOpen); },
251 type: 'button'
252 }, a.triggerLabel),
253 a.triggerMode === 'auto' && el('span', {
254 className: 'bkbg-modal-auto-badge'
255 }, __('Auto-opens after', 'blockenberg') + ' ' + (a.autoDelay / 1000).toFixed(1) + 's')
256 ),
257
258 // Editor preview modal (inline)
259 isPreviewOpen && el('div', {
260 className: 'bkbg-modal-editor-preview',
261 'data-size': a.modalSize,
262 'data-animation': a.animation
263 },
264 el('div', { className: 'bkbg-modal-dialog' },
265 a.showHeader && el('div', { className: 'bkbg-modal-header' },
266 el('h2', { className: 'bkbg-modal-title' },
267 el(TextControl, {
268 value: a.modalTitle,
269 onChange: function (v) { setAttributes({ modalTitle: v }); },
270 hideLabelFromVision: true,
271 label: __('Modal Title', 'blockenberg')
272 })
273 ),
274 a.showCloseBtn && el('button', {
275 className: 'bkbg-modal-close',
276 type: 'button',
277 onClick: function () { setPreviewOpen(false); }
278 }, '')
279 ),
280 el('div', { className: 'bkbg-modal-content' },
281 el(RichText, {
282 tagName: 'div',
283 className: 'bkbg-modal-body',
284 value: a.modalContent,
285 onChange: function (v) { setAttributes({ modalContent: v }); },
286 placeholder: __('Add modal content here...', 'blockenberg')
287 })
288 )
289 )
290 )
291 )
292 );
293 },
294
295 deprecated: [{
296 save: function (props) {
297 var a = props.attributes;
298 var RichTextContent = wp.blockEditor.RichText.Content;
299 var modalId = 'bkbg-modal-' + (Math.random().toString(36).substr(2, 9));
300
301 var svgs = {
302 chevron: '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="18" height="18" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="6 9 12 15 18 9"/></svg>'
303 };
304
305 var wrapStyle = [
306 '--bkbg-modal-bg:' + a.modalBg,
307 '--bkbg-modal-radius:' + a.modalRadius + 'px',
308 '--bkbg-modal-padding:' + a.modalPadding + 'px',
309 '--bkbg-modal-title-size:' + a.titleSize + 'px',
310 '--bkbg-modal-title-weight:' + a.titleWeight,
311 '--bkbg-modal-title-color:' + a.titleColor,
312 '--bkbg-modal-content-size:' + a.contentSize + 'px',
313 '--bkbg-modal-content-color:' + a.contentColor,
314 '--bkbg-modal-content-lh:' + a.contentLineHeight,
315 '--bkbg-modal-title-lh:' + a.titleLineHeight,
316 '--bkbg-modal-close-color:' + a.closeBtnColor,
317 '--bkbg-modal-close-hover:' + a.closeBtnHoverColor,
318 '--bkbg-modal-overlay-bg:' + a.overlayBg,
319 '--bkbg-modal-btn-bg:' + a.triggerBtnBg,
320 '--bkbg-modal-btn-color:' + a.triggerBtnColor,
321 '--bkbg-modal-btn-radius:' + a.triggerBtnRadius + 'px'
322 ].join(';');
323
324 var blockProps = wp.blockEditor.useBlockProps.save({
325 className: 'bkbg-modal-block',
326 style: wrapStyle,
327 'data-trigger-align': a.triggerAlignment,
328 'data-modal-id': modalId
329 });
330
331 var triggerBtnClass = 'bkbg-modal-trigger bkbg-modal-btn-' + a.triggerBtnStyle + ' bkbg-modal-btn-' + a.triggerBtnSize;
332
333 return el('div', blockProps,
334 el('div', { className: 'bkbg-modal-trigger-wrap', style: { textAlign: a.triggerAlignment } },
335 el('button', {
336 className: triggerBtnClass,
337 'aria-haspopup': 'dialog',
338 'aria-controls': modalId,
339 'data-bkbg-modal-open': modalId,
340 type: 'button'
341 }, a.triggerLabel)
342 ),
343 el('div', {
344 className: 'bkbg-modal-overlay',
345 id: modalId,
346 role: 'dialog',
347 'aria-modal': 'true',
348 'aria-labelledby': modalId + '-title',
349 'aria-hidden': 'true',
350 'data-size': a.modalSize,
351 'data-animation': a.animation,
352 'data-close-overlay': a.closeOnOverlay ? '1' : '0',
353 'data-close-esc': a.closeOnEsc ? '1' : '0',
354 'data-trigger-mode': a.triggerMode,
355 'data-auto-delay': a.autoDelay,
356 'data-overlay-blur': a.overlayBlur ? '1' : '0'
357 },
358 el('div', { className: 'bkbg-modal-dialog' },
359 a.showHeader && el('div', { className: 'bkbg-modal-header' },
360 el('h2', { className: 'bkbg-modal-title', id: modalId + '-title' }, a.modalTitle),
361 a.showCloseBtn && el('button', {
362 className: 'bkbg-modal-close',
363 type: 'button',
364 'aria-label': 'Close modal',
365 'data-bkbg-modal-close': modalId
366 }, '')
367 ),
368 el('div', { className: 'bkbg-modal-content' },
369 el(RichTextContent, { tagName: 'div', className: 'bkbg-modal-body', value: a.modalContent })
370 )
371 )
372 )
373 );
374 }
375 }],
376
377 save: function (props) {
378 var a = props.attributes;
379 var RichTextContent = wp.blockEditor.RichText.Content;
380 var modalId = 'bkbg-modal-' + (Math.random().toString(36).substr(2, 9));
381
382 var blockProps = wp.blockEditor.useBlockProps.save((function () {
383 var _tvf = getTypoCssVars();
384 var s = {
385 '--bkbg-modal-bg': a.modalBg,
386 '--bkbg-modal-radius': a.modalRadius + 'px',
387 '--bkbg-modal-padding': a.modalPadding + 'px',
388 '--bkbg-modal-title-size': a.titleSize + 'px',
389 '--bkbg-modal-title-weight': a.titleWeight,
390 '--bkbg-modal-title-color': a.titleColor,
391 '--bkbg-modal-content-size': a.contentSize + 'px',
392 '--bkbg-modal-content-color': a.contentColor,
393 '--bkbg-modal-content-lh': a.contentLineHeight,
394 '--bkbg-modal-title-lh': a.titleLineHeight,
395 '--bkbg-modal-close-color': a.closeBtnColor,
396 '--bkbg-modal-close-hover': a.closeBtnHoverColor,
397 '--bkbg-modal-overlay-bg': a.overlayBg,
398 '--bkbg-modal-btn-bg': a.triggerBtnBg,
399 '--bkbg-modal-btn-color': a.triggerBtnColor,
400 '--bkbg-modal-btn-radius': a.triggerBtnRadius + 'px'
401 };
402 Object.assign(s, _tvf(a.titleTypo, '--bkbg-modal-tt-'));
403 Object.assign(s, _tvf(a.bodyTypo, '--bkbg-modal-bd-'));
404 return {
405 className: 'bkbg-modal-block',
406 style: s,
407 'data-trigger-align': a.triggerAlignment,
408 'data-modal-id': modalId
409 };
410 })());
411
412 var triggerBtnClass = 'bkbg-modal-trigger bkbg-modal-btn-' + a.triggerBtnStyle + ' bkbg-modal-btn-' + a.triggerBtnSize;
413
414 return el('div', blockProps,
415 // Trigger
416 el('div', { className: 'bkbg-modal-trigger-wrap', style: { textAlign: a.triggerAlignment } },
417 el('button', {
418 className: triggerBtnClass,
419 'aria-haspopup': 'dialog',
420 'aria-controls': modalId,
421 'data-bkbg-modal-open': modalId,
422 type: 'button'
423 }, a.triggerLabel)
424 ),
425
426 // Modal overlay + dialog
427 el('div', {
428 className: 'bkbg-modal-overlay',
429 id: modalId,
430 role: 'dialog',
431 'aria-modal': 'true',
432 'aria-labelledby': modalId + '-title',
433 'aria-hidden': 'true',
434 'data-size': a.modalSize,
435 'data-animation': a.animation,
436 'data-close-overlay': a.closeOnOverlay ? '1' : '0',
437 'data-close-esc': a.closeOnEsc ? '1' : '0',
438 'data-trigger-mode': a.triggerMode,
439 'data-auto-delay': a.autoDelay,
440 'data-overlay-blur': a.overlayBlur ? '1' : '0'
441 },
442 el('div', { className: 'bkbg-modal-dialog' },
443 a.showHeader && el('div', { className: 'bkbg-modal-header' },
444 el('h2', { className: 'bkbg-modal-title', id: modalId + '-title' }, a.modalTitle),
445 a.showCloseBtn && el('button', {
446 className: 'bkbg-modal-close',
447 type: 'button',
448 'aria-label': 'Close modal',
449 'data-bkbg-modal-close': modalId
450 }, '')
451 ),
452 el('div', { className: 'bkbg-modal-content' },
453 el(RichTextContent, { tagName: 'div', className: 'bkbg-modal-body', value: a.modalContent })
454 )
455 )
456 )
457 );
458 }
459 });
460 }() );
461