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 / spoiler / index.js

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

218 lines 13.1 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 useState = wp.element.useState;
4 var Fragment = wp.element.Fragment;
5 var registerBlockType = wp.blocks.registerBlockType;
6 var __ = wp.i18n.__;
7 var InspectorControls = wp.blockEditor.InspectorControls;
8 var PanelColorSettings = wp.blockEditor.PanelColorSettings;
9 var useBlockProps = wp.blockEditor.useBlockProps;
10 var PanelBody = wp.components.PanelBody;
11 var RangeControl = wp.components.RangeControl;
12 var SelectControl = wp.components.SelectControl;
13 var TextControl = wp.components.TextControl;
14 var ToggleControl = wp.components.ToggleControl;
15
16 var _tc; function getTypoControl() { return _tc || (_tc = window.bkbgTypographyControl); }
17 var _tv; function getTypoCssVars() { return _tv || (_tv = window.bkbgTypoCssVars); }
18 var IP = function () { return window.bkbgIconPicker; };
19
20 function buildWrapStyle(a) {
21 var s = {
22 '--bksp-lb-sz': (a.labelSize || 16) + 'px',
23 '--bksp-lb-w': a.labelFontWeight || '700',
24 '--bksp-lb-lh': String(a.labelLineHeight || 1.4),
25 '--bksp-ct-sz': (a.contentSize || 16) + 'px',
26 '--bksp-ct-w': a.contentFontWeight || '400',
27 '--bksp-ct-lh': String(a.contentLineHeight || 1.7),
28 };
29 var fn = getTypoCssVars();
30 if (fn) {
31 Object.assign(s, fn(a.labelTypo, '--bksp-lb'));
32 Object.assign(s, fn(a.contentTypo, '--bksp-ct'));
33 }
34 return s;
35 }
36
37 var SPOILER_TYPES = [
38 { label: 'Warning (amber)', value: 'warning' },
39 { label: 'Info (blue)', value: 'info' },
40 { label: 'Danger (red)', value: 'danger' },
41 { label: 'Success (green)', value: 'success' },
42 { label: 'Neutral (gray)', value: 'neutral' },
43 { label: 'Custom colors', value: 'custom' },
44 ];
45
46 var TYPE_DEFAULTS = {
47 warning: { accent:'#f59e0b', labelBg:'#fffbeb', labelColor:'#92400e', border:'#f59e0b', btn:'#f59e0b', btnTxt:'#ffffff' },
48 info: { accent:'#3b82f6', labelBg:'#eff6ff', labelColor:'#1e40af', border:'#3b82f6', btn:'#3b82f6', btnTxt:'#ffffff' },
49 danger: { accent:'#ef4444', labelBg:'#fef2f2', labelColor:'#991b1b', border:'#ef4444', btn:'#ef4444', btnTxt:'#ffffff' },
50 success: { accent:'#10b981', labelBg:'#f0fdf4', labelColor:'#065f46', border:'#10b981', btn:'#10b981', btnTxt:'#ffffff' },
51 neutral: { accent:'#6b7280', labelBg:'#f9fafb', labelColor:'#374151', border:'#d1d5db', btn:'#6b7280', btnTxt:'#ffffff' },
52 custom: { accent:'#6c3fb5', labelBg:'#f5f3ff', labelColor:'#4c1d95', border:'#6c3fb5', btn:'#6c3fb5', btnTxt:'#ffffff' },
53 };
54
55 function getColors(a) {
56 if (a.spoilerType !== 'custom') {
57 var d = TYPE_DEFAULTS[a.spoilerType] || TYPE_DEFAULTS.warning;
58 return { accent: d.accent, labelBg: d.labelBg, labelColor: d.labelColor, border: d.border, btn: d.btn, btnColor: d.btnTxt };
59 }
60 return { accent: a.accentColor, labelBg: a.labelBg, labelColor: a.labelColor, border: a.borderColor, btn: a.btnBg, btnColor: a.btnColor };
61 }
62
63 function SpoilerPreview(props) {
64 var a = props.attributes;
65 var setAttr = props.setAttributes;
66 var c = getColors(a);
67 var open = a.startOpen;
68
69 var cRadius = (a.cardRadius || 12) + 'px';
70 var bRadius = (a.btnRadius || 8) + 'px';
71 var pV = (a.paddingV || 20) + 'px';
72 var pH = (a.paddingH || 24) + 'px';
73 var maxW = (a.maxWidth || 720) + 'px';
74
75 /* Header bar */
76 var header = el('div', {
77 className: 'bkbg-sp-header',
78 style: {
79 background: c.labelBg,
80 borderBottom: open ? '1px solid ' + c.border : 'none',
81 padding: pV + ' ' + pH,
82 display: 'flex',
83 alignItems: 'center',
84 justifyContent: 'space-between',
85 gap: '12px',
86 cursor: 'default',
87 },
88 },
89 el('div', { style: { display:'flex', alignItems:'center', gap:'10px' } },
90 el('span', {
91 className: 'bkbg-sp-label',
92 style: { color: c.labelColor },
93 contentEditable: true,
94 suppressContentEditableWarning: true,
95 onBlur: function (e) { setAttr({ label: e.target.innerText.trim() }); },
96 dangerouslySetInnerHTML: { __html: a.label },
97 }),
98 a.showSubLabel && el('span', {
99 style: { color: c.labelColor, opacity: 0.7, fontSize: '13px', fontStyle: 'italic' },
100 contentEditable: true,
101 suppressContentEditableWarning: true,
102 onBlur: function (e) { setAttr({ subLabel: e.target.innerText.trim() }); },
103 dangerouslySetInnerHTML: { __html: a.subLabel },
104 })
105 ),
106 el('span', {
107 className: 'bkbg-sp-icon',
108 style: { color: c.labelColor, fontSize: '13px', opacity: 0.7 },
109 }, a.showIcon ? (function() { var _t = open ? (a.iconOpenType || 'custom-char') : (a.iconClosedType || 'custom-char'); return _t !== 'custom-char' ? IP().buildEditorIcon(_t, open ? a.iconOpen : a.iconClosed, open ? a.iconOpenDashicon : a.iconClosedDashicon, open ? a.iconOpenImageUrl : a.iconClosedImageUrl, open ? a.iconOpenDashiconColor : a.iconClosedDashiconColor) : (open ? a.iconOpen : a.iconClosed); })() : null)
110 );
111
112 /* Hidden content */
113 var content = open
114 ? el('div', { className: 'bkbg-sp-content', style: { padding: pV + ' ' + pH, background: a.contentBg || '#ffffff' } },
115 el('div', {
116 className: 'bkbg-sp-text',
117 style: { color: a.contentColor || '#374151' },
118 contentEditable: true,
119 suppressContentEditableWarning: true,
120 onBlur: function (e) { setAttr({ content: e.target.innerHTML }); },
121 dangerouslySetInnerHTML: { __html: a.content },
122 })
123 )
124 : el('div', {
125 className: 'bkbg-sp-reveal-wrap',
126 style: { padding: pV + ' ' + pH, background: a.contentBg || '#ffffff', textAlign: 'center' },
127 },
128 el('button', {
129 className: 'bkbg-sp-btn',
130 style: { background: c.btn, color: c.btnColor, borderRadius: bRadius, padding: '10px 28px', border: 'none', fontWeight: 600, fontSize: '15px', cursor: 'pointer' },
131 }, a.showIcon ? ((a.iconClosedType || 'custom-char') !== 'custom-char' ? IP().buildEditorIcon(a.iconClosedType, a.iconClosed, a.iconClosedDashicon, a.iconClosedImageUrl, a.iconClosedDashiconColor) : a.iconClosed) : null, a.showIcon ? ' ' : null, a.revealBtnText)
132 );
133
134 return el(Fragment, null,
135 el('div', {
136 className: 'bkbg-sp-wrap',
137 style: {
138 maxWidth: maxW,
139 margin: '0 auto',
140 border: '2px solid ' + c.border,
141 borderRadius: cRadius,
142 overflow: 'hidden',
143 },
144 },
145 header,
146 content
147 ),
148 el('p', { style: { textAlign: 'center', color: '#6b7280', fontSize: '12px', marginTop: '6px' } },
149 '[ Editor preview — toggle "Start open" in settings to see the other state ]'
150 )
151 );
152 }
153
154 registerBlockType('blockenberg/spoiler', {
155 edit: function (props) {
156 var a = props.attributes;
157 var setAttr = props.setAttributes;
158 var blockProps = useBlockProps({ className: 'bkbg-spoiler-block', style: buildWrapStyle(a) });
159
160 var customColorPanels = a.spoilerType === 'custom'
161 ? el(PanelColorSettings, {
162 title: __('Colors', 'blockenberg'),
163 initialOpen: false, colorSettings: [
164 { label: 'Header Background', value: a.labelBg, onChange: function (v) { setAttr({ labelBg: v }); } },
165 { label: 'Header Text', value: a.labelColor, onChange: function (v) { setAttr({ labelColor: v }); } },
166 { label: 'Border', value: a.borderColor, onChange: function (v) { setAttr({ borderColor: v }); } },
167 { label: 'Button Background', value: a.btnBg, onChange: function (v) { setAttr({ btnBg: v }); } },
168 { label: 'Button Text', value: a.btnColor, onChange: function (v) { setAttr({ btnColor: v }); } },
169 { label: 'Content Background',value: a.contentBg, onChange: function (v) { setAttr({ contentBg: v }); } },
170 { label: 'Content Text', value: a.contentColor, onChange: function (v) { setAttr({ contentColor: v }); } },
171 ],
172 })
173 : null;
174
175 return el('div', blockProps,
176 el(InspectorControls, null,
177 el(PanelBody, { title: __('Content', 'blockenberg'), initialOpen: true },
178 el(TextControl, { label: 'Header Label', value: a.label, onChange: function (v) { setAttr({ label: v }); } }),
179 el(ToggleControl, { label: 'Show Sub-label', checked: a.showSubLabel, onChange: function (v) { setAttr({ showSubLabel: v }); }, __nextHasNoMarginBottom: true }),
180 a.showSubLabel && el(TextControl, { label: 'Sub-label text', value: a.subLabel, onChange: function (v) { setAttr({ subLabel: v }); } }),
181 el(TextControl, { label: 'Reveal button text', value: a.revealBtnText, onChange: function (v) { setAttr({ revealBtnText: v }); } }),
182 el(TextControl, { label: 'Hide button text', value: a.hideBtnText, onChange: function (v) { setAttr({ hideBtnText: v }); } }),
183 ),
184 el(PanelBody, { title: __('Display', 'blockenberg'), initialOpen: false },
185 el(SelectControl, { label: 'Spoiler type (preset colors)', value: a.spoilerType, options: SPOILER_TYPES, onChange: function (v) { setAttr({ spoilerType: v }); } }),
186 el(ToggleControl, { label: 'Show icon', checked: a.showIcon, onChange: function (v) { setAttr({ showIcon: v }); }, __nextHasNoMarginBottom: true }),
187 a.showIcon && el(IP().IconPickerControl, IP().iconPickerProps(a, setAttr, { charAttr: 'iconClosed', typeAttr: 'iconClosedType', dashiconAttr: 'iconClosedDashicon', imageUrlAttr: 'iconClosedImageUrl', colorAttr: 'iconClosedDashiconColor' })),
188 a.showIcon && el(IP().IconPickerControl, IP().iconPickerProps(a, setAttr, { charAttr: 'iconOpen', typeAttr: 'iconOpenType', dashiconAttr: 'iconOpenDashicon', imageUrlAttr: 'iconOpenImageUrl', colorAttr: 'iconOpenDashiconColor' })),
189 el(ToggleControl, { label: '☛ Start open in editor', checked: a.startOpen, onChange: function (v) { setAttr({ startOpen: v }); }, __nextHasNoMarginBottom: true }),
190 ),
191 el(PanelBody, { title: __('Typography', 'blockenberg'), initialOpen: false },
192 getTypoControl() ? el(getTypoControl(), { label:__('Label','blockenberg'), value:a.labelTypo, onChange:function(v){ setAttr({labelTypo:v}); } }) : null,
193 getTypoControl() ? el(getTypoControl(), { label:__('Content','blockenberg'), value:a.contentTypo, onChange:function(v){ setAttr({contentTypo:v}); } }) : null
194 ),
195 customColorPanels,
196 el(PanelBody, { title: __('Sizing', 'blockenberg'), initialOpen: false },
197 el(RangeControl, { label: 'Max width (px)', value: a.maxWidth, min: 300, max: 1200, step: 10, onChange: function (v) { setAttr({ maxWidth: v }); } }),
198 el(RangeControl, { label: 'Padding V (px)', value: a.paddingV, min: 8, max: 60, onChange: function (v) { setAttr({ paddingV: v }); } }),
199 el(RangeControl, { label: 'Padding H (px)', value: a.paddingH, min: 8, max: 80, onChange: function (v) { setAttr({ paddingH: v }); } }),
200 el(RangeControl, { label: 'Card radius (px)', value: a.cardRadius, min: 0, max: 32, onChange: function (v) { setAttr({ cardRadius: v }); } }),
201 el(RangeControl, { label: 'Button radius (px)', value: a.btnRadius, min: 0, max: 50, onChange: function (v) { setAttr({ btnRadius: v }); } }),
202 )
203 ),
204 el(SpoilerPreview, { attributes: a, setAttributes: setAttr })
205 );
206 },
207
208 save: function (props) {
209 var a = props.attributes;
210 var blockProps = wp.blockEditor.useBlockProps.save({ className: 'bkbg-spoiler-block' });
211 return el('div', Object.assign({}, blockProps, {
212 className: (blockProps.className || '') + ' bkbg-sp-app',
213 'data-opts': JSON.stringify(a),
214 }));
215 },
216 });
217 }() );
218