PluginProbe
Blockenberg — 600+ Advanced Gutenberg Blocks & AI Agent for WordPress Block Editor / 2.0.11
Blockenberg — 600+ Advanced Gutenberg Blocks & AI Agent for WordPress Block Editor v2.0.11
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 / faq-search / index.js

index.js in Blockenberg — 600+ Advanced Gutenberg Blocks & AI Agent for WordPress Block Editor 2.0.11, at blocks/faq-search/index.js

281 lines 13.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 __ = wp.i18n.__;
4 var registerBlockType = wp.blocks.registerBlockType;
5 var InspectorControls = wp.blockEditor.InspectorControls;
6 var useBlockProps = wp.blockEditor.useBlockProps;
7 var PanelColorSettings = wp.blockEditor.PanelColorSettings;
8 var PanelBody = wp.components.PanelBody;
9 var ToggleControl = wp.components.ToggleControl;
10 var RangeControl = wp.components.RangeControl;
11 var SelectControl = wp.components.SelectControl;
12 var TextControl = wp.components.TextControl;
13 var TextareaControl = wp.components.TextareaControl;
14 var Button = wp.components.Button;
15
16 var _fsTC, _fsTV;
17 function _tc() { return _fsTC || (_fsTC = window.bkbgTypographyControl); }
18 function _tv() { return _fsTV || (_fsTV = window.bkbgTypoCssVars); }
19
20 function defaultItem() {
21 return { question: 'New question?', answer: 'Answer goes here.' };
22 }
23
24 registerBlockType('blockenberg/faq-search', {
25 edit: function (props) {
26 var attr = props.attributes;
27 var setAttr = props.setAttributes;
28 var items = attr.items || [];
29
30 var blockProps = useBlockProps({ className: 'bkbg-fs-editor', style: Object.assign({}, _tv()(attr.typoQuestion, '--bkbg-fsrch-qt-'), _tv()(attr.typoAnswer, '--bkbg-fsrch-an-')) });
31
32 function updateItem(i, key, value) {
33 var updated = items.map(function (it, idx) {
34 if (idx !== i) return it;
35 var copy = Object.assign({}, it);
36 copy[key] = value;
37 return copy;
38 });
39 setAttr({ items: updated });
40 }
41
42 function removeItem(i) {
43 setAttr({ items: items.filter(function (_, idx) { return idx !== i; }) });
44 }
45
46 var itemControls = items.map(function (item, i) {
47 return el('div', {
48 key: i,
49 style: { borderLeft: '3px solid #7c3aed', paddingLeft: '12px', marginBottom: '20px' }
50 },
51 el('div', { style: { display: 'flex', justifyContent: 'space-between', alignItems: 'center', marginBottom: '8px' } },
52 el('strong', {}, 'Q' + (i + 1)),
53 el(Button, { isSmall: true, isDestructive: true, onClick: function () { removeItem(i); } }, '')
54 ),
55 el(TextControl, {
56 label: __('Question', 'blockenberg'),
57 value: item.question,
58 onChange: function (v) { updateItem(i, 'question', v); },
59 __nextHasNoMarginBottom: true
60 }),
61 el(TextareaControl, {
62 label: __('Answer', 'blockenberg'),
63 value: item.answer,
64 rows: 3,
65 onChange: function (v) { updateItem(i, 'answer', v); },
66 __nextHasNoMarginBottom: true
67 })
68 );
69 });
70
71 // Preview of items in editor
72 var wrapStyle = {
73 background: attr.bgColor || 'transparent',
74 paddingTop: attr.paddingTop + 'px',
75 paddingBottom: attr.paddingBottom + 'px'
76 };
77
78 var innerStyle = {
79 maxWidth: attr.maxWidth + 'px',
80 margin: '0 auto'
81 };
82
83 var previewItems = items.map(function (item, i) {
84 var itemStyle = {};
85 if (attr.itemStyle === 'bordered') {
86 itemStyle = {
87 border: '1px solid ' + attr.borderColor,
88 borderRadius: attr.borderRadius + 'px',
89 padding: '16px 20px',
90 marginBottom: '8px',
91 background: attr.itemBg || '#fff'
92 };
93 } else if (attr.itemStyle === 'boxed') {
94 itemStyle = {
95 background: attr.itemBg || '#f9fafb',
96 borderRadius: attr.borderRadius + 'px',
97 padding: '16px 20px',
98 marginBottom: '8px'
99 };
100 } else {
101 itemStyle = {
102 borderBottom: '1px solid ' + attr.borderColor,
103 padding: '16px 0',
104 marginBottom: '0'
105 };
106 }
107
108 return el('div', { key: i, style: itemStyle },
109 el('div', {
110 style: {
111 display: 'flex',
112 justifyContent: 'space-between',
113 alignItems: 'center',
114 cursor: 'default'
115 }
116 },
117 el('span', {
118 className: 'bkbg-fs-question-text',
119 style: { color: attr.questionColor }
120 }, item.question),
121 el('span', {
122 style: {
123 color: attr.accentColor,
124 fontSize: '20px',
125 lineHeight: 1
126 }
127 }, '+')
128 )
129 );
130 });
131
132 var controls = el(InspectorControls, {},
133 el(PanelBody, { title: __('FAQ Items', 'blockenberg'), initialOpen: true },
134 itemControls,
135 el(Button, { isPrimary: true, isSmall: true, onClick: function () { setAttr({ items: items.concat(defaultItem()) }); }, style: { marginTop: '8px' } }, '+ Add FAQ')
136 ),
137 el(PanelBody, { title: __('Search Settings', 'blockenberg'), initialOpen: false },
138 el(ToggleControl, {
139 label: __('Show Search Bar', 'blockenberg'),
140 checked: attr.showSearch,
141 onChange: function (v) { setAttr({ showSearch: v }); },
142 __nextHasNoMarginBottom: true
143 }),
144 el(TextControl, {
145 label: __('Search Placeholder', 'blockenberg'),
146 value: attr.searchPlaceholder,
147 onChange: function (v) { setAttr({ searchPlaceholder: v }); },
148 __nextHasNoMarginBottom: true
149 }),
150 el(TextControl, {
151 label: __('No Results Text', 'blockenberg'),
152 value: attr.noResultsText,
153 onChange: function (v) { setAttr({ noResultsText: v }); },
154 __nextHasNoMarginBottom: true
155 })
156 ),
157 el(PanelBody, { title: __('Accordion Behaviour', 'blockenberg'), initialOpen: false },
158 el(ToggleControl, {
159 label: __('Open First Item by Default', 'blockenberg'),
160 checked: attr.openFirst,
161 onChange: function (v) { setAttr({ openFirst: v }); },
162 __nextHasNoMarginBottom: true
163 }),
164 el(ToggleControl, {
165 label: __('Allow Multiple Open', 'blockenberg'),
166 checked: attr.allowMultiple,
167 onChange: function (v) { setAttr({ allowMultiple: v }); },
168 __nextHasNoMarginBottom: true
169 }),
170 el(SelectControl, {
171 label: __('Item Style', 'blockenberg'),
172 value: attr.itemStyle,
173 options: [
174 { label: 'Bordered', value: 'bordered' },
175 { label: 'Boxed', value: 'boxed' },
176 { label: 'Plain (dividers)', value: 'plain' }
177 ],
178 onChange: function (v) { setAttr({ itemStyle: v }); },
179 __nextHasNoMarginBottom: true
180 }),
181 el(RangeControl, {
182 label: __('Border Radius (px)', 'blockenberg'),
183 value: attr.borderRadius,
184 min: 0, max: 30,
185 onChange: function (v) { setAttr({ borderRadius: v }); },
186 __nextHasNoMarginBottom: true
187 })
188 ),
189 el(PanelBody, { title: __('Typography', 'blockenberg'), initialOpen: false },
190 _tc() && el(_tc(), { label: __('Question', 'blockenberg'), value: attr.typoQuestion, onChange: function (v) { setAttr({ typoQuestion: v }); } }),
191 _tc() && el(_tc(), { label: __('Answer', 'blockenberg'), value: attr.typoAnswer, onChange: function (v) { setAttr({ typoAnswer: v }); } })
192 ),
193 el(PanelColorSettings, {
194 title: __('Colors', 'blockenberg'),
195 initialOpen: false,
196 colorSettings: [
197 { label: __('Question Text', 'blockenberg'), value: attr.questionColor, onChange: function (v) { setAttr({ questionColor: v || '#111827' }); } },
198 { label: __('Answer Text', 'blockenberg'), value: attr.answerColor, onChange: function (v) { setAttr({ answerColor: v || '#4b5563' }); } },
199 { label: __('Accent / Icon', 'blockenberg'), value: attr.accentColor, onChange: function (v) { setAttr({ accentColor: v || '#7c3aed' }); } },
200 { label: __('Border', 'blockenberg'), value: attr.borderColor, onChange: function (v) { setAttr({ borderColor: v || '#e5e7eb' }); } },
201 { label: __('Item Background', 'blockenberg'), value: attr.itemBg, onChange: function (v) { setAttr({ itemBg: v || '#ffffff' }); } },
202 { label: __('Section Background', 'blockenberg'), value: attr.bgColor, onChange: function (v) { setAttr({ bgColor: v || '' }); } }
203 ]
204 }),
205 el(PanelBody, { title: __('Layout', 'blockenberg'), initialOpen: false },
206 el(RangeControl, {
207 label: __('Max Width (px)', 'blockenberg'),
208 value: attr.maxWidth,
209 min: 400, max: 1200,
210 onChange: function (v) { setAttr({ maxWidth: v }); },
211 __nextHasNoMarginBottom: true
212 }),
213 el(RangeControl, {
214 label: __('Padding Top (px)', 'blockenberg'),
215 value: attr.paddingTop,
216 min: 0, max: 200,
217 onChange: function (v) { setAttr({ paddingTop: v }); },
218 __nextHasNoMarginBottom: true
219 }),
220 el(RangeControl, {
221 label: __('Padding Bottom (px)', 'blockenberg'),
222 value: attr.paddingBottom,
223 min: 0, max: 200,
224 onChange: function (v) { setAttr({ paddingBottom: v }); },
225 __nextHasNoMarginBottom: true
226 })
227 )
228 );
229
230 return el('div', blockProps, controls,
231 el('div', { style: wrapStyle },
232 el('div', { style: innerStyle },
233 attr.showSearch && el('div', {
234 style: {
235 marginBottom: '24px',
236 position: 'relative'
237 }
238 },
239 el('input', {
240 type: 'text',
241 placeholder: attr.searchPlaceholder,
242 readOnly: true,
243 style: {
244 width: '100%',
245 padding: '12px 16px 12px 40px',
246 border: '1px solid ' + attr.searchBorderColor,
247 borderRadius: '8px',
248 fontSize: '15px',
249 boxSizing: 'border-box',
250 background: attr.searchBg || '#fff'
251 }
252 }),
253 el('span', {
254 style: {
255 position: 'absolute',
256 left: '14px',
257 top: '50%',
258 transform: 'translateY(-50%)',
259 color: '#9ca3af'
260 }
261 }, '🔍')
262 ),
263 el('div', {}, previewItems)
264 )
265 )
266 );
267 },
268
269 save: function (props) {
270 var attr = props.attributes;
271 var blockProps = wp.blockEditor.useBlockProps.save();
272 return el('div', blockProps,
273 el('div', {
274 className: 'bkbg-fs-app',
275 'data-opts': JSON.stringify(attr)
276 })
277 );
278 }
279 });
280 }() );
281