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

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

172 lines 8.2 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 ( function () {
2 const el = window.wp.element.createElement;
3 const { registerBlockType } = window.wp.blocks;
4 const { InspectorControls, MediaUpload, MediaUploadCheck, PanelColorSettings } = window.wp.blockEditor;
5 const { PanelBody, RangeControl, SelectControl, TextControl, ToggleControl, Button } = window.wp.components;
6 const { __ } = window.wp.i18n;
7
8 var _fgTC, _fgTV;
9 function _tc() { return (_fgTC = _fgTC || window.bkbgTypographyControl); }
10 function _tv() { return (_fgTV = _fgTV || window.bkbgTypoCssVars); }
11
12 function ItemEditor({ item, index, onChange, onRemove }) {
13 function upd(k,v){ onChange(index, Object.assign({},item,{[k]:v})); }
14 return el('div',{style:{border:'1px solid #ddd',borderRadius:'8px',padding:'10px',marginBottom:'8px',background:'#fafafa'}},
15 item.imageUrl
16 ? el('div',{style:{marginBottom:'6px'}},
17 el('img',{src:item.imageUrl,style:{width:'100%',height:'80px',objectFit:'cover',borderRadius:'6px'}}),
18 el(Button,{isDestructive:true,isSmall:true,onClick:()=>{upd('imageUrl','');upd('imageId',0);}},__('Remove'))
19 )
20 : el(MediaUploadCheck,null,
21 el(MediaUpload,{
22 onSelect:m=>{upd('imageUrl',m.url);upd('imageId',m.id);upd('alt',m.alt||'');},
23 allowedTypes:['image'],value:item.imageId,
24 render:({open})=>el(Button,{onClick:open,isSmall:true,variant:'secondary'},__('Upload Image'))
25 })
26 ),
27 el(TextControl,{label:__('Title'),value:item.title,onChange:v=>upd('title',v)}),
28 el(TextControl,{label:__('Tags (comma separated)'),value:item.tags,onChange:v=>upd('tags',v)}),
29 el(Button,{isDestructive:true,isSmall:true,onClick:()=>onRemove(index)},__('Remove'))
30 );
31 }
32
33 // Collect unique tags from all items
34 function collectTags(items) {
35 const tags = new Set();
36 items.forEach(item => {
37 (item.tags||'').split(',').map(t=>t.trim()).filter(Boolean).forEach(t=>tags.add(t));
38 });
39 return Array.from(tags);
40 }
41
42 registerBlockType('blockenberg/filter-gallery', {
43 edit: function(props) {
44 const { attributes: attr, setAttributes } = props;
45
46 function updateItem(idx,next){ const it=attr.items.slice(); it[idx]=next; setAttributes({items:it}); }
47 function removeItem(idx){ setAttributes({items:attr.items.filter((_,i)=>i!==idx)}); }
48
49 const tags = collectTags(attr.items);
50
51 const wrapStyle = Object.assign({
52 '--bkfg-cols': attr.columns,
53 '--bkfg-gap': attr.gap + 'px',
54 '--bkfg-ratio': attr.imageRatio,
55 '--bkfg-radius': attr.borderRadius + 'px',
56 '--bkfg-accent': attr.accentColor,
57 '--bkfg-bg': attr.bgColor,
58 '--bkfg-text': attr.textColor,
59 background: attr.bgColor,
60 },
61 _tv()(attr.typoTitle, '--bkfg-tt-'),
62 _tv()(attr.typoFilter, '--bkfg-tf-')
63 );
64
65 return el('div', {className:'bkfg-wrap', style:wrapStyle},
66
67 el(InspectorControls, null,
68 el(PanelBody,{title:__('Items'),initialOpen:true},
69 attr.items.map((item,i)=>el(ItemEditor,{key:i,item,index:i,onChange:updateItem,onRemove:removeItem})),
70 el(Button,{variant:'secondary',onClick:()=>setAttributes({items:[...attr.items,{imageUrl:'',imageId:0,alt:'',title:'New Item',tags:''}]}),
71 style:{width:'100%',justifyContent:'center',marginTop:'8px'}},__('+ Add Item'))
72 ),
73 el(PanelBody,{title:__('Layout'),initialOpen:false},
74 el(RangeControl,{label:__('Columns'),value:attr.columns,min:1,max:6,onChange:v=>setAttributes({columns:v})}),
75 el(RangeControl,{label:__('Gap (px)'),value:attr.gap,min:0,max:48,onChange:v=>setAttributes({gap:v})}),
76 el(RangeControl,{label:__('Border Radius'),value:attr.borderRadius,min:0,max:40,onChange:v=>setAttributes({borderRadius:v})}),
77 el(SelectControl,{label:__('Image Ratio'),value:attr.imageRatio,
78 options:[{label:'Square 1:1',value:'1/1'},{label:'4:3',value:'4/3'},{label:'16:9',value:'16/9'},{label:'3:4 Portrait',value:'3/4'}],
79 onChange:v=>setAttributes({imageRatio:v})}),
80 el(ToggleControl,{label:__('Show Titles'),checked:attr.showTitle,onChange:v=>setAttributes({showTitle:v}),__nextHasNoMarginBottom:true})
81 ),
82 el(PanelBody,{title:__('Filter Bar'),initialOpen:false},
83 el(TextControl,{label:__('Show All Label'),value:attr.showAllLabel,onChange:v=>setAttributes({showAllLabel:v})}),
84 el(SelectControl,{label:__('Filter Style'),value:attr.filterStyle,
85 options:[{label:'Pills',value:'pills'},{label:'Tabs',value:'tabs'},{label:'Underline',value:'underline'}],
86 onChange:v=>setAttributes({filterStyle:v})}),
87 el(SelectControl,{label:__('Animation'),value:attr.animation,
88 options:[{label:'Fade',value:'fade'},{label:'Scale',value:'scale'}],
89 onChange:v=>setAttributes({animation:v})})
90 ),
91 el(PanelBody,{title:__('Typography'),initialOpen:false},
92 _tc() && el(_tc(), { label: __('Item Title', 'blockenberg'), value: attr.typoTitle, onChange: function (v) { setAttributes({ typoTitle: v }); } }),
93 _tc() && el(_tc(), { label: __('Filter Button', 'blockenberg'), value: attr.typoFilter, onChange: function (v) { setAttributes({ typoFilter: v }); } }),
94 ),
95 el(PanelColorSettings,{
96 initialOpen: false, colorSettings:[
97 {label:__('Accent Color'),value:attr.accentColor,onChange:v=>setAttributes({accentColor:v||'#6c3fb5'})},
98 {label:__('Background'),value:attr.bgColor,onChange:v=>setAttributes({bgColor:v||'#ffffff'})},
99 {label:__('Text Color'),value:attr.textColor,onChange:v=>setAttributes({textColor:v||'#333333'})},
100 ]
101 })
102 ),
103
104 /* Filter bar preview */
105 el('div',{className:'bkfg-filters bkfg-style-'+attr.filterStyle},
106 el('button',{className:'bkfg-btn bkfg-active'},attr.showAllLabel),
107 tags.map((t,i)=>el('button',{key:i,className:'bkfg-btn'},t))
108 ),
109
110 /* Grid preview */
111 el('div',{className:'bkfg-grid'},
112 attr.items.map((item,i)=>
113 el('div',{key:i,className:'bkfg-item'},
114 el('div',{className:'bkfg-thumb'},
115 item.imageUrl
116 ? el('img',{src:item.imageUrl,alt:item.alt})
117 : el('div',{className:'bkfg-thumb-placeholder'},el('span',{className:'dashicons dashicons-format-image'}))
118 ),
119 attr.showTitle && item.title && el('p',{className:'bkfg-item-title'},item.title)
120 )
121 )
122 )
123 );
124 },
125
126 save: function({attributes:attr}) {
127 const tags = collectTags(attr.items);
128 const wrapStyle = Object.assign({
129 '--bkfg-cols': attr.columns,
130 '--bkfg-gap': attr.gap + 'px',
131 '--bkfg-ratio': attr.imageRatio,
132 '--bkfg-radius': attr.borderRadius + 'px',
133 '--bkfg-accent': attr.accentColor,
134 '--bkfg-bg': attr.bgColor,
135 '--bkfg-text': attr.textColor,
136 background: attr.bgColor,
137 },
138 _tv()(attr.typoTitle, '--bkfg-tt-'),
139 _tv()(attr.typoFilter, '--bkfg-tf-')
140 );
141 return el('div',{
142 className:'bkfg-wrap bkfg-anim-'+attr.animation,
143 style:wrapStyle,
144 'data-filter':'1'
145 },
146 el('div',{className:'bkfg-filters bkfg-style-'+attr.filterStyle},
147 el('button',{className:'bkfg-btn bkfg-active','data-filter':'*'},attr.showAllLabel),
148 tags.map((t,i)=>el('button',{key:i,className:'bkfg-btn','data-filter':t},t))
149 ),
150 el('div',{className:'bkfg-grid'},
151 attr.items.map((item,i)=>
152 el('div',{key:i,className:'bkfg-item','data-tags':item.tags},
153 el('div',{className:'bkfg-thumb'},
154 item.imageUrl
155 ? el('img',{src:item.imageUrl,alt:item.alt,loading:'lazy'})
156 : null
157 ),
158 attr.showTitle && item.title && el('p',{className:'bkfg-item-title'},item.title)
159 )
160 )
161 )
162 );
163 }
164 });
165
166 function collectTags(items) {
167 const tags = new Set();
168 items.forEach(item=>{(item.tags||'').split(',').map(t=>t.trim()).filter(Boolean).forEach(t=>tags.add(t));});
169 return Array.from(tags);
170 }
171 }() );
172