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

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

372 lines 19.8 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 PanelBody = wp.components.PanelBody;
10 var PanelColorSettings = wp.blockEditor.PanelColorSettings;
11 var ToggleControl = wp.components.ToggleControl;
12 var RangeControl = wp.components.RangeControl;
13 var SelectControl = wp.components.SelectControl;
14 var TextControl = wp.components.TextControl;
15 var Button = wp.components.Button;
16
17 var _tc; function getTypoControl() { return _tc || (_tc = window.bkbgTypographyControl); }
18 var _tv; function getTypoCssVars() { return _tv || (_tv = window.bkbgTypoCssVars); }
19 var IP = function () { return window.bkbgIconPicker; };
20
21 function genId() {
22 return 'txl_' + Math.random().toString(36).substr(2, 9);
23 }
24
25 registerBlockType('blockenberg/taxonomy-list', {
26 title: __('Taxonomy List', 'blockenberg'),
27 icon: 'tag',
28 category: 'bkbg-blog',
29 description: __('Display categories, tags or custom taxonomy as a styled list, grid, chips or cards.', 'blockenberg'),
30
31 edit: function (props) {
32 var a = props.attributes;
33 var setAttributes = props.setAttributes;
34 var editState = useState(null);
35 var editing = editState[0];
36 var setEditing = editState[1];
37
38 function updateItem(id, field, value) {
39 setAttributes({
40 items: a.items.map(function (item) {
41 if (item.id === id) {
42 var updated = Object.assign({}, item);
43 updated[field] = value;
44 return updated;
45 }
46 return item;
47 })
48 });
49 }
50
51 function addItem() {
52 setAttributes({
53 items: a.items.concat([{ id: genId(), name: 'New Category', url: '#', icon: '📁', iconType: 'custom-char', iconDashicon: '', iconImageUrl: '', count: 0 }])
54 });
55 }
56
57 function removeItem(id) {
58 setAttributes({ items: a.items.filter(function (i) { return i.id !== id; }) });
59 }
60
61 function moveItem(index, dir) {
62 var items = a.items.slice();
63 var target = index + dir;
64 if (target < 0 || target >= items.length) return;
65 var temp = items[index];
66 items[index] = items[target];
67 items[target] = temp;
68 setAttributes({ items: items });
69 }
70
71 var layoutOptions = [
72 { label: __('List', 'blockenberg'), value: 'list' },
73 { label: __('Grid', 'blockenberg'), value: 'grid' },
74 { label: __('Chips', 'blockenberg'), value: 'chips' },
75 { label: __('Pills', 'blockenberg'), value: 'pills' },
76 { label: __('Cards', 'blockenberg'), value: 'cards' }
77 ];
78
79 var countPosOptions = [
80 { label: __('Badge (bubble)', 'blockenberg'), value: 'badge' },
81 { label: __('Inline', 'blockenberg'), value: 'inline' },
82 { label: __('Bracket (23)', 'blockenberg'), value: 'bracket' }
83 ];
84
85 var fontWeightOptions = [
86 { label: '300', value: 300 },
87 { label: '400 — Regular', value: 400 },
88 { label: '500 — Medium', value: 500 },
89 { label: '600 — Semi-bold', value: 600 },
90 { label: '700 — Bold', value: 700 }
91 ];
92
93 // Inspector
94 var inspector = el(InspectorControls, {},
95 el(PanelBody, { title: __('Items', 'blockenberg'), initialOpen: true },
96 a.items.map(function (item, index) {
97 var isEditing = editing === item.id;
98 return el('div', {
99 key: item.id,
100 style: { marginBottom: '8px', padding: '8px 10px', background: '#f8fafc', borderRadius: '6px', border: '1px solid #e2e8f0' }
101 },
102 el('div', { style: { display: 'flex', alignItems: 'center', justifyContent: 'space-between', gap: '6px' } },
103 el('span', { style: { display: 'flex', alignItems: 'center', gap: '5px', fontSize: '13px', fontWeight: 500, flex: 1, overflow: 'hidden' } },
104 el('span', { style: { flexShrink: 0 } }, (item.iconType || 'custom-char') !== 'custom-char' && IP() ? IP().buildEditorIcon(item.iconType, item.icon, item.iconDashicon, item.iconImageUrl, item.iconDashiconColor) : (item.icon || '📁')),
105 el('span', { style: { overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' } }, item.name)
106 ),
107 el('div', { style: { display: 'flex', gap: '2px', flexShrink: 0 } },
108 el(Button, { isSmall: true, variant: 'tertiary', onClick: function () { setEditing(isEditing ? null : item.id); } }, isEditing ? '' : ''),
109 el(Button, { isSmall: true, variant: 'tertiary', onClick: function () { moveItem(index, -1); }, disabled: index === 0 }, ''),
110 el(Button, { isSmall: true, variant: 'tertiary', onClick: function () { moveItem(index, 1); }, disabled: index === a.items.length - 1 }, ''),
111 el(Button, { isSmall: true, variant: 'tertiary', isDestructive: true, onClick: function () { removeItem(item.id); }, disabled: a.items.length <= 1 }, '')
112 )
113 ),
114 isEditing && el('div', { style: { marginTop: '8px', paddingTop: '8px', borderTop: '1px solid #e2e8f0' } },
115 el(TextControl, { label: __('Name', 'blockenberg'), value: item.name, onChange: function (v) { updateItem(item.id, 'name', v); }, __nextHasNoMarginBottom: true }),
116 el('div', { style: { marginTop: '8px' } },
117 el(TextControl, { label: __('URL', 'blockenberg'), value: item.url, onChange: function (v) { updateItem(item.id, 'url', v); }, __nextHasNoMarginBottom: true })
118 ),
119 el('div', { style: { marginTop: '8px' } },
120 el(IP().IconPickerControl, IP().iconPickerProps(item, function(patch) { setAttributes({ items: a.items.map(function(it) { return it.id === item.id ? Object.assign({}, it, patch) : it; }) }); }, { label: __('Icon', 'blockenberg'), charAttr: 'icon', typeAttr: 'iconType', dashiconAttr: 'iconDashicon', imageUrlAttr: 'iconImageUrl' }))
121 ),
122 el('div', { style: { marginTop: '8px' } },
123 el(TextControl, { label: __('Count', 'blockenberg'), value: String(item.count), type: 'number', onChange: function (v) { updateItem(item.id, 'count', parseInt(v, 10) || 0); }, __nextHasNoMarginBottom: true })
124 )
125 )
126 );
127 }),
128 el('div', { style: { marginTop: '8px' } },
129 el(Button, { variant: 'secondary', onClick: addItem, style: { width: '100%', justifyContent: 'center' } },
130 '+ ' + __('Add Item', 'blockenberg')
131 )
132 )
133 ),
134
135 el(PanelBody, { title: __('Layout', 'blockenberg'), initialOpen: false },
136 el(SelectControl, {
137 label: __('Style', 'blockenberg'),
138 value: a.layout,
139 options: layoutOptions,
140 onChange: function (v) { setAttributes({ layout: v }); }
141 }),
142 (a.layout === 'grid' || a.layout === 'cards') && el(RangeControl, {
143 label: __('Columns', 'blockenberg'),
144 value: a.columns,
145 min: 2, max: 6,
146 onChange: function (v) { setAttributes({ columns: v }); }
147 }),
148 el(ToggleControl, {
149 label: __('Show Icons', 'blockenberg'),
150 checked: a.showIcon,
151 __nextHasNoMarginBottom: true,
152 onChange: function (v) { setAttributes({ showIcon: v }); }
153 }),
154 el(ToggleControl, {
155 label: __('Show Count', 'blockenberg'),
156 checked: a.showCount,
157 __nextHasNoMarginBottom: true,
158 onChange: function (v) { setAttributes({ showCount: v }); }
159 }),
160 a.showCount && el(SelectControl, {
161 label: __('Count Position', 'blockenberg'),
162 value: a.countPosition,
163 options: countPosOptions,
164 onChange: function (v) { setAttributes({ countPosition: v }); }
165 }),
166 el(ToggleControl, {
167 label: __('Show Chevron Arrow', 'blockenberg'),
168 checked: a.showChevron,
169 __nextHasNoMarginBottom: true,
170 onChange: function (v) { setAttributes({ showChevron: v }); }
171 }),
172 el(ToggleControl, {
173 label: __('Link Items', 'blockenberg'),
174 checked: a.linkItems,
175 __nextHasNoMarginBottom: true,
176 onChange: function (v) { setAttributes({ linkItems: v }); }
177 }),
178 a.linkItems && el(SelectControl, {
179 label: __('Open Links In', 'blockenberg'),
180 value: a.linkTarget,
181 options: [
182 { label: __('Same Tab', 'blockenberg'), value: '_self' },
183 { label: __('New Tab', 'blockenberg'), value: '_blank' }
184 ],
185 onChange: function (v) { setAttributes({ linkTarget: v }); }
186 })
187 ),
188
189 el(PanelBody, { title: __('Spacing', 'blockenberg'), initialOpen: false },
190 el(RangeControl, {
191 label: __('Gap Between Items', 'blockenberg'),
192 value: a.gap, min: 0, max: 32,
193 onChange: function (v) { setAttributes({ gap: v }); }
194 }),
195 el(RangeControl, {
196 label: __('Item Padding', 'blockenberg'),
197 value: a.padding, min: 6, max: 40,
198 onChange: function (v) { setAttributes({ padding: v }); }
199 }),
200 el(RangeControl, {
201 label: __('Border Radius', 'blockenberg'),
202 value: a.borderRadius, min: 0, max: 50,
203 onChange: function (v) { setAttributes({ borderRadius: v }); }
204 }),
205 el(RangeControl, {
206 label: __('Max Width (0 = full)', 'blockenberg'),
207 value: a.maxWidth, min: 0, max: 800, step: 20,
208 onChange: function (v) { setAttributes({ maxWidth: v }); }
209 })
210 ),
211
212 el(PanelBody, { title: __('Typography', 'blockenberg'), initialOpen: false },
213 getTypoControl()({ label: __('Item', 'blockenberg'), value: a.itemTypo, onChange: function (v) { setAttributes({ itemTypo: v }); } })
214 ),
215
216 el(PanelColorSettings, {
217 title: __('Item Colors', 'blockenberg'),
218 initialOpen: false,
219 colorSettings: [
220 { value: a.itemBg, onChange: function (c) { setAttributes({ itemBg: c || '' }); }, label: __('Background', 'blockenberg') },
221 { value: a.itemBgHover, onChange: function (c) { setAttributes({ itemBgHover: c || '' }); }, label: __('Hover Background', 'blockenberg') },
222 { value: a.itemColor, onChange: function (c) { setAttributes({ itemColor: c || '' }); }, label: __('Text Color', 'blockenberg') },
223 { value: a.itemColorHover, onChange: function (c) { setAttributes({ itemColorHover: c || '' }); }, label: __('Hover Text', 'blockenberg') },
224 { value: a.borderColor, onChange: function (c) { setAttributes({ borderColor: c || '' }); }, label: __('Border', 'blockenberg') },
225 { value: a.accentColor, onChange: function (c) { setAttributes({ accentColor: c || '' }); }, label: __('Accent / Chevron', 'blockenberg') }
226 ]
227 }),
228
229 el(PanelColorSettings, {
230 title: __('Count & Icon', 'blockenberg'),
231 initialOpen: false,
232 colorSettings: [
233 { value: a.iconColor, onChange: function (c) { setAttributes({ iconColor: c || '' }); }, label: __('Icon Color', 'blockenberg') },
234 { value: a.countBg, onChange: function (c) { setAttributes({ countBg: c || '' }); }, label: __('Count Background', 'blockenberg') },
235 { value: a.countColor, onChange: function (c) { setAttributes({ countColor: c || '' }); }, label: __('Count Text', 'blockenberg') }
236 ]
237 })
238 );
239
240 // CSS variables
241 var wrapStyle = {
242 '--bkbg-txl-item-bg': a.itemBg,
243 '--bkbg-txl-item-bg-hover': a.itemBgHover,
244 '--bkbg-txl-item-color': a.itemColor,
245 '--bkbg-txl-item-color-hover': a.itemColorHover,
246 '--bkbg-txl-count-bg': a.countBg,
247 '--bkbg-txl-count-color': a.countColor,
248 '--bkbg-txl-icon-color': a.iconColor,
249 '--bkbg-txl-border-color': a.borderColor,
250 '--bkbg-txl-accent-color': a.accentColor,
251 '--bkbg-txl-radius': a.borderRadius + 'px',
252 '--bkbg-txl-gap': a.gap + 'px',
253 '--bkbg-txl-padding': a.padding + 'px',
254 '--bkbg-txl-cols': a.columns
255 };
256 var _tvf = getTypoCssVars();
257 if (_tvf) Object.assign(wrapStyle, _tvf(a.itemTypo, '--bktxl-it-'));
258 if (a.maxWidth > 0) wrapStyle.maxWidth = a.maxWidth + 'px';
259
260 function renderCount(count) {
261 if (!a.showCount) return null;
262 if (a.countPosition === 'bracket') {
263 return el('span', { className: 'bkbg-txl-count bkbg-txl-count--bracket' }, '(' + count + ')');
264 }
265 if (a.countPosition === 'inline') {
266 return el('span', { className: 'bkbg-txl-count bkbg-txl-count--inline' }, count);
267 }
268 return el('span', { className: 'bkbg-txl-count bkbg-txl-count--badge' }, count);
269 }
270
271 var listEls = a.items.map(function (item) {
272 var _iType = item.iconType || 'custom-char';
273 var _iconContent = (_iType !== 'custom-char' && IP()) ? IP().buildEditorIcon(_iType, item.icon, item.iconDashicon, item.iconImageUrl, item.iconDashiconColor) : item.icon;
274 return el('li', { key: item.id, className: 'bkbg-txl-item' },
275 el('a', {
276 className: 'bkbg-txl-link',
277 href: item.url,
278 onClick: function (e) { e.preventDefault(); }
279 },
280 a.showIcon && _iconContent && el('span', { className: 'bkbg-txl-icon' }, _iconContent),
281 el('span', { className: 'bkbg-txl-name' }, item.name),
282 renderCount(item.count),
283 a.showChevron && el('span', { className: 'bkbg-txl-chevron' }, '')
284 )
285 );
286 });
287
288 var blockProps = useBlockProps({
289 className: 'bkbg-editor-wrap',
290 'data-block-label': 'Taxonomy List'
291 });
292
293 return el('div', blockProps,
294 inspector,
295 el('div', {
296 className: 'bkbg-txl-wrap',
297 style: wrapStyle,
298 'data-layout': a.layout
299 },
300 el('ul', { className: 'bkbg-txl-list' }, listEls)
301 )
302 );
303 },
304
305 save: function (props) {
306 var a = props.attributes;
307
308 var wrapStyle = {
309 '--bkbg-txl-item-bg': a.itemBg,
310 '--bkbg-txl-item-bg-hover': a.itemBgHover,
311 '--bkbg-txl-item-color': a.itemColor,
312 '--bkbg-txl-item-color-hover': a.itemColorHover,
313 '--bkbg-txl-count-bg': a.countBg,
314 '--bkbg-txl-count-color': a.countColor,
315 '--bkbg-txl-icon-color': a.iconColor,
316 '--bkbg-txl-border-color': a.borderColor,
317 '--bkbg-txl-accent-color': a.accentColor,
318 '--bkbg-txl-radius': a.borderRadius + 'px',
319 '--bkbg-txl-gap': a.gap + 'px',
320 '--bkbg-txl-padding': a.padding + 'px',
321 '--bkbg-txl-cols': a.columns
322 };
323 var _tvf = getTypoCssVars();
324 if (_tvf) Object.assign(wrapStyle, _tvf(a.itemTypo, '--bktxl-it-'));
325 if (a.maxWidth > 0) wrapStyle.maxWidth = a.maxWidth + 'px';
326
327 function renderCount(count) {
328 if (!a.showCount) return null;
329 if (a.countPosition === 'bracket') {
330 return el('span', { className: 'bkbg-txl-count bkbg-txl-count--bracket' }, '(' + count + ')');
331 }
332 if (a.countPosition === 'inline') {
333 return el('span', { className: 'bkbg-txl-count bkbg-txl-count--inline' }, count);
334 }
335 return el('span', { className: 'bkbg-txl-count bkbg-txl-count--badge' }, count);
336 }
337
338 var listEls = a.items.map(function (item, idx) {
339 var Tag = a.linkItems ? 'a' : 'span';
340 var linkProps = {
341 className: 'bkbg-txl-link'
342 };
343 if (a.linkItems) {
344 linkProps.href = item.url;
345 if (a.linkTarget === '_blank') {
346 linkProps.target = '_blank';
347 linkProps.rel = 'noopener noreferrer';
348 }
349 }
350 var _iType = item.iconType || 'custom-char';
351 var _iconContent = (_iType !== 'custom-char' && IP()) ? IP().buildSaveIcon(_iType, item.icon, item.iconDashicon, item.iconImageUrl, item.iconDashiconColor) : item.icon;
352 return el('li', { key: idx, className: 'bkbg-txl-item' },
353 el(Tag, linkProps,
354 a.showIcon && _iconContent && el('span', { className: 'bkbg-txl-icon' }, _iconContent),
355 el('span', { className: 'bkbg-txl-name' }, item.name),
356 renderCount(item.count),
357 a.showChevron && el('span', { className: 'bkbg-txl-chevron' }, '')
358 )
359 );
360 });
361
362 return el('div', {
363 className: 'bkbg-txl-wrap',
364 style: wrapStyle,
365 'data-layout': a.layout
366 },
367 el('ul', { className: 'bkbg-txl-list' }, listEls)
368 );
369 }
370 });
371 }() );
372