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

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

157 lines 13.1 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, useBlockProps, PanelColorSettings } = window.wp.blockEditor;
5 const { PanelBody, RangeControl, ToggleControl, TextControl, Button, SelectControl } = window.wp.components;
6 const { __ } = window.wp.i18n;
7
8 /* ── Typography lazy getters ──────────────────────────────── */
9 var _ttTC, _ttTV;
10 function _tc() { return _ttTC || (_ttTC = window.bkbgTypographyControl); }
11 function _tv() { return _ttTV || (_ttTV = window.bkbgTypoCssVars); } var IP = function () { return window.bkbgIconPicker; };
12 // ── Card renderer ─────────────────────────────────────────────────────────
13 function HighlightCard( props ) {
14 const { item, a } = props;
15 const accentClr = item.accentColor || '#6366f1';
16
17 const cardStyle = {
18 background: a.cardBg,
19 borderRadius: a.borderRadius + 'px',
20 padding: a.cardPadding + 'px',
21 boxSizing: 'border-box',
22 display: 'flex',
23 flexDirection: 'column',
24 gap: 10,
25 overflow: 'hidden',
26 position: 'relative',
27 };
28
29 return el( 'div', { className: 'bkbg-hr-card', style: cardStyle },
30 // Accent bar at top
31 a.accentLine && el( 'div', { className: 'bkbg-hr-accent', style: { position: 'absolute', top: 0, left: 0, right: 0, height: a.accentHeight + 'px', background: accentClr } } ),
32
33 // Icon
34 a.showIcon && item.icon && el( 'div', { className: 'bkbg-hr-icon', style: { fontSize: a.iconSize + 'px', lineHeight: 1, paddingTop: a.accentLine ? ( a.accentHeight + 4 ) + 'px' : 0 } }, (item.iconType || 'custom-char') !== 'custom-char' && IP() ? IP().buildSaveIcon(el, item.iconType, item.icon, item.iconDashicon, item.iconImageUrl, item.iconDashiconColor) : item.icon ),
35
36 // Tag
37 a.showTag && item.tag && el( 'span', { className: 'bkbg-hr-tag', style: { color: a.tagColor, background: a.tagBg, borderRadius: 99 + 'px', padding: '3px 10px', alignSelf: 'flex-start' } }, item.tag ),
38
39 // Title
40 el( 'div', { className: 'bkbg-hr-item-title', style: { color: a.headingColor } }, item.title ),
41
42 // Description
43 a.showDesc && item.description && el( 'p', { className: 'bkbg-hr-desc', style: { color: a.textColor, margin: 0 } }, item.description ),
44 );
45 }
46
47 function renderReel( a ) {
48 const items = a.items || [];
49 return el( 'div', { className: 'bkbg-hr-grid', style: { display: 'grid', gridTemplateColumns: `repeat(${ a.columns }, 1fr)`, gap: 20 } },
50 items.map( ( item, i ) => el( HighlightCard, { key: i, item, a } ) )
51 );
52 }
53
54 function updItem( setAttributes, items, ii, field, val ) {
55 setAttributes( { items: items.map( ( m, i ) => i === ii ? { ...m, [field]: val } : m ) } );
56 }
57
58 // ── Block ─────────────────────────────────────────────────────────────────
59 registerBlockType( 'blockenberg/highlight-reel', {
60 edit: function ( props ) {
61 const { attributes: a, setAttributes } = props;
62 const blockProps = useBlockProps( { className: 'bkbg-hr-wrap', style: Object.assign( { background: a.bgColor, boxSizing: 'border-box' }, _tv() && _tv()( a.typoHeading, '--bkbg-hr-hl-' ), _tv() && _tv()( a.typoCardTitle, '--bkbg-hr-ct-' ), _tv() && _tv()( a.typoBody, '--bkbg-hr-bd-' ) ) } );
63
64 return el( 'div', blockProps,
65 el( InspectorControls, {},
66
67 el( PanelBody, { title: __( 'Settings', 'blockenberg' ), initialOpen: true },
68 el( TextControl, { label: __( 'Title', 'blockenberg' ), value: a.title, onChange: v => setAttributes( { title: v } ) } ),
69 el( ToggleControl, { label: __( 'Show Title', 'blockenberg' ), checked: a.showTitle, onChange: v => setAttributes( { showTitle: v } ) } ),
70 el( TextControl, { label: __( 'Subtitle', 'blockenberg' ), value: a.subtitle, onChange: v => setAttributes( { subtitle: v } ) } ),
71 el( ToggleControl, { label: __( 'Show Subtitle', 'blockenberg' ), checked: a.showSubtitle, onChange: v => setAttributes( { showSubtitle: v } ) } ),
72 el( RangeControl, { label: __( 'Columns', 'blockenberg' ), value: a.columns, onChange: v => setAttributes( { columns: v } ), min: 1, max: 6 } ),
73 el( ToggleControl, { label: __( 'Show Icons', 'blockenberg' ), checked: a.showIcon, onChange: v => setAttributes( { showIcon: v } ) } ),
74 el( ToggleControl, { label: __( 'Show Tags', 'blockenberg' ), checked: a.showTag, onChange: v => setAttributes( { showTag: v } ) } ),
75 el( ToggleControl, { label: __( 'Show Descriptions', 'blockenberg' ),checked: a.showDesc, onChange: v => setAttributes( { showDesc: v } ) } ),
76 el( ToggleControl, { label: __( 'Accent Line', 'blockenberg' ), checked: a.accentLine, onChange: v => setAttributes( { accentLine: v } ) } ),
77 ),
78
79 el( PanelBody, { title: __( 'Style', 'blockenberg' ), initialOpen: false },
80 el( RangeControl, { label: __( 'Icon Size', 'blockenberg' ), value: a.iconSize, onChange: v => setAttributes( { iconSize: v } ), min: 18, max: 72 } ),
81 el( RangeControl, { label: __( 'Border Radius', 'blockenberg' ), value: a.borderRadius, onChange: v => setAttributes( { borderRadius: v } ), min: 0, max: 32 } ),
82 el( RangeControl, { label: __( 'Card Padding', 'blockenberg' ), value: a.cardPadding, onChange: v => setAttributes( { cardPadding: v } ), min: 8, max: 48 } ),
83 a.accentLine && el( RangeControl, { label: __( 'Accent Height', 'blockenberg' ), value: a.accentHeight, onChange: v => setAttributes( { accentHeight: v } ), min: 2, max: 12 } ),
84 ),
85
86 el( PanelBody, { title: __( 'Typography', 'blockenberg' ), initialOpen: false },
87 _tc() && _tc()({ label: __('Section Heading','blockenberg'), value: a.typoHeading, onChange: v => setAttributes({ typoHeading: v }) }),
88 _tc() && _tc()({ label: __('Card Title','blockenberg'), value: a.typoCardTitle, onChange: v => setAttributes({ typoCardTitle: v }) }),
89 _tc() && _tc()({ label: __('Body / Subtitle','blockenberg'), value: a.typoBody, onChange: v => setAttributes({ typoBody: v }) })
90 ),
91 el( PanelColorSettings, {
92 title: __( 'Colors', 'blockenberg' ), initialOpen: false,
93 colorSettings: [
94 { label: __( 'Wrapper BG', 'blockenberg' ), value: a.bgColor, onChange: v => setAttributes( { bgColor: v || '#ffffff' } ) },
95 { label: __( 'Card BG', 'blockenberg' ), value: a.cardBg, onChange: v => setAttributes( { cardBg: v || '#f9fafb' } ) },
96 { label: __( 'Heading', 'blockenberg' ), value: a.headingColor, onChange: v => setAttributes( { headingColor: v || '#111827' } ) },
97 { label: __( 'Subtitle', 'blockenberg' ), value: a.subtitleColor,onChange: v => setAttributes( { subtitleColor:v || '#6b7280' } ) },
98 { label: __( 'Body Text', 'blockenberg' ), value: a.textColor, onChange: v => setAttributes( { textColor: v || '#374151' } ) },
99 { label: __( 'Tag BG', 'blockenberg' ), value: a.tagBg, onChange: v => setAttributes( { tagBg: v || '#ede9fe' } ) },
100 { label: __( 'Tag Text', 'blockenberg' ), value: a.tagColor, onChange: v => setAttributes( { tagColor: v || '#6d28d9' } ) },
101 ]
102 } ),
103
104 el( PanelBody, { title: __( 'Items', 'blockenberg' ), initialOpen: false },
105 el( Button, { variant: 'secondary', style: { marginBottom: 10 }, onClick: () => setAttributes( { items: [ ...( a.items || [] ), { icon: '', iconType: 'custom-char', iconDashicon: '', iconImageUrl: '', accentColor: '#6366f1', tag: 'Highlight', title: 'New Highlight', description: 'Describe this moment or achievement.' } ] } ) }, __( '+ Add Item', 'blockenberg' ) ),
106 a.items.map( ( item, ii ) =>
107 el( PanelBody, { key: ii, title: item.title.length > 28 ? item.title.slice( 0, 26 ) + '' : item.title, initialOpen: false },
108 IP() ? el( IP().IconPickerControl, {
109 iconType: item.iconType || 'custom-char',
110 customChar: item.icon || '',
111 dashicon: item.iconDashicon || '',
112 imageUrl: item.iconImageUrl || '',
113 onChangeType: v => updItem( setAttributes, a.items, ii, 'iconType', v ),
114 onChangeChar: v => updItem( setAttributes, a.items, ii, 'icon', v ),
115 onChangeDashicon: v => updItem( setAttributes, a.items, ii, 'iconDashicon', v ),
116 onChangeImageUrl: v => updItem( setAttributes, a.items, ii, 'iconImageUrl', v ),
117 label: __( 'Icon', 'blockenberg' )
118 } ) : el( TextControl, { label: __( 'Icon (emoji or text)', 'blockenberg' ), value: item.icon, onChange: v => updItem( setAttributes, a.items, ii, 'icon', v ) } ),
119 el( TextControl, { label: __( 'Tag', 'blockenberg' ), value: item.tag, onChange: v => updItem( setAttributes, a.items, ii, 'tag', v ) } ),
120 el( TextControl, { label: __( 'Title', 'blockenberg' ), value: item.title, onChange: v => updItem( setAttributes, a.items, ii, 'title', v ) } ),
121 el( 'div', { style: { marginBottom: 8 } },
122 el( 'label', { style: { fontSize: 12, fontWeight: 600, display: 'block', marginBottom: 4 } }, __( 'Description', 'blockenberg' ) ),
123 el( 'textarea', { value: item.description, rows: 3, onChange: e => updItem( setAttributes, a.items, ii, 'description', e.target.value ), style: { width: '100%', fontSize: 12, padding: '6px 8px', borderRadius: 4, border: '1px solid #d1d5db', resize: 'vertical', boxSizing: 'border-box' } } ),
124 ),
125 el( 'div', { style: { display: 'flex', alignItems: 'center', gap: 8, marginBottom: 8 } },
126 el( 'label', { style: { fontSize: 12 } }, __( 'Accent Color', 'blockenberg' ) ),
127 el( 'input', { type: 'color', value: item.accentColor || '#6366f1', style: { width: 40, height: 28, border: 'none', borderRadius: 4, cursor: 'pointer' }, onChange: e => updItem( setAttributes, a.items, ii, 'accentColor', e.target.value ) } ),
128 ),
129 el( Button, { isDestructive: true, isSmall: true, onClick: () => setAttributes( { items: a.items.filter( ( _, x ) => x !== ii ) } ) }, __( 'Remove', 'blockenberg' ) ),
130 )
131 ),
132 ),
133 ),
134
135 // Header
136 el( 'div', { className: 'bkbg-hr-header', style: { marginBottom: 28 } },
137 a.showTitle && a.title && el( 'h2', { className: 'bkbg-hr-title', style: { color: a.headingColor, margin: '0 0 6px' } }, a.title ),
138 a.showSubtitle && a.subtitle && el( 'p', { className: 'bkbg-hr-subtitle', style: { color: a.subtitleColor, margin: 0 } }, a.subtitle ),
139 ),
140
141 renderReel( a ),
142 );
143 },
144
145 save: function ( { attributes: a } ) {
146 const blockProps = useBlockProps.save( { className: 'bkbg-hr-wrap', style: Object.assign( { background: a.bgColor, boxSizing: 'border-box' }, _tv() && _tv()( a.typoHeading, '--bkbg-hr-hl-' ), _tv() && _tv()( a.typoCardTitle, '--bkbg-hr-ct-' ), _tv() && _tv()( a.typoBody, '--bkbg-hr-bd-' ) ) } );
147 return el( 'div', blockProps,
148 el( 'div', { className: 'bkbg-hr-header', style: { marginBottom: 28 } },
149 a.showTitle && a.title ? el( 'h2', { className: 'bkbg-hr-title', style: { color: a.headingColor, margin: '0 0 6px' } }, a.title ) : null,
150 a.showSubtitle && a.subtitle ? el( 'p', { className: 'bkbg-hr-subtitle', style: { color: a.subtitleColor, margin: 0 } }, a.subtitle ) : null,
151 ),
152 renderReel( a ),
153 );
154 },
155 } );
156 }() );
157