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

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

195 lines 13.6 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 MediaUpload = wp.blockEditor.MediaUpload;
7 var MediaUploadCheck = wp.blockEditor.MediaUploadCheck;
8 var useBlockProps = wp.blockEditor.useBlockProps;
9 var RichText = wp.blockEditor.RichText;
10 var PanelColorSettings = wp.blockEditor.PanelColorSettings;
11 var PanelBody = wp.components.PanelBody;
12 var ToggleControl = wp.components.ToggleControl;
13 var RangeControl = wp.components.RangeControl;
14 var SelectControl = wp.components.SelectControl;
15 var TextControl = wp.components.TextControl;
16 var Button = wp.components.Button;
17 var _tc; function getTypoControl() { return _tc || (_tc = window.bkbgTypographyControl); }
18 var _tv; function getTypoCssVars() { return _tv || (_tv = window.bkbgTypoCssVars); }
19
20 var TYPE_ICONS = { book: '📚', article: '📄', podcast: '🎙️', course: '🎓', video: '🎬' };
21 var TYPE_LABELS = { book: 'Book', article: 'Article', podcast: 'Podcast', course: 'Course', video: 'Video' };
22
23 registerBlockType('blockenberg/reading-card', {
24 edit: function (props) {
25 var attr = props.attributes;
26 var setAttr = props.setAttributes;
27 var TC = getTypoControl();
28 var blockProps = useBlockProps((function() {
29 var _tvFn = getTypoCssVars();
30 var s = {};
31 if (_tvFn) {
32 Object.assign(s, _tvFn(attr.titleTypo || {}, '--bkrdc-tt-'));
33 Object.assign(s, _tvFn(attr.authorTypo || {}, '--bkrdc-at-'));
34 Object.assign(s, _tvFn(attr.descTypo || {}, '--bkrdc-dt-'));
35 }
36 return { className: 'bkbg-rdc-editor', style: s };
37 })());
38
39 var stars = Array.from({ length: 5 }, function (_, i) {
40 return el('span', { key: i, style: { color: i < attr.rating ? attr.ratingColor : '#d1d5db', fontSize: '18px' } }, '�
41 ');
42 });
43
44 var coverPlaceholder = el('div', {
45 style: {
46 width: (attr.layout === 'vertical' ? '100%' : attr.coverWidth) + 'px',
47 minWidth: attr.layout !== 'vertical' ? attr.coverWidth + 'px' : undefined,
48 height: attr.layout === 'vertical' ? '200px' : (attr.coverWidth * 1.4) + 'px',
49 background: '#f3f4f6', borderRadius: '8px', display: 'flex', alignItems: 'center', justifyContent: 'center', fontSize: '40px', flexShrink: 0
50 }
51 }, TYPE_ICONS[attr.contentType] || '📚');
52
53 var cover = attr.coverUrl
54 ? el('img', {
55 src: attr.coverUrl, alt: attr.coverAlt,
56 style: {
57 width: attr.layout === 'vertical' ? '100%' : attr.coverWidth + 'px',
58 minWidth: attr.layout !== 'vertical' ? attr.coverWidth + 'px' : undefined,
59 height: attr.layout === 'vertical' ? '200px' : 'auto',
60 objectFit: 'cover', borderRadius: '8px', flexShrink: 0, display: 'block'
61 }
62 })
63 : coverPlaceholder;
64
65 var typeBadge = el('div', { style: { display: 'flex', gap: '8px', alignItems: 'center', marginBottom: '8px', flexWrap: 'wrap' } },
66 el('span', {
67 style: { background: attr.badgeBg, color: attr.badgeColor, fontSize: '11px', fontWeight: '700', padding: '3px 10px', borderRadius: '999px', textTransform: 'uppercase', letterSpacing: '0.05em' }
68 }, (attr.badge || TYPE_LABELS[attr.contentType] || 'BOOK'))
69 );
70
71 var cardStyle = {
72 display: 'flex', flexDirection: attr.layout === 'vertical' ? 'column' : 'row',
73 gap: '24px', background: attr.bgColor,
74 border: '1px solid ' + attr.borderColor,
75 borderRadius: attr.borderRadius + 'px', padding: '24px',
76 maxWidth: attr.maxWidth + 'px', margin: '0 auto', alignItems: attr.layout === 'vertical' ? 'stretch' : 'flex-start'
77 };
78
79 if (attr.layout === 'minimal') {
80 cardStyle = { display: 'flex', flexDirection: 'row', gap: '16px', alignItems: 'center', background: 'transparent', borderBottom: '1px solid ' + attr.borderColor, padding: '16px 0', maxWidth: attr.maxWidth + 'px', margin: '0 auto' };
81 }
82
83 var content = el('div', { style: { flex: 1, minWidth: 0 } },
84 typeBadge,
85 el(RichText, {
86 tagName: 'h3', value: attr.title,
87 className: 'bkbg-rdc-title',
88 style: { margin: '0 0 6px', color: attr.titleColor },
89 onChange: function (v) { setAttr({ title: v }); }
90 }),
91 el(RichText, {
92 tagName: 'p', value: attr.author,
93 className: 'bkbg-rdc-author',
94 style: { margin: '0 0 12px', color: attr.authorColor },
95 onChange: function (v) { setAttr({ author: v }); }
96 }),
97 attr.showRating && el('div', { style: { display: 'flex', gap: '2px', marginBottom: '12px' } }, stars),
98 attr.layout !== 'minimal' && el(RichText, {
99 tagName: 'p', value: attr.description,
100 className: 'bkbg-rdc-desc',
101 style: { margin: '0 0 16px', color: attr.descColor },
102 onChange: function (v) { setAttr({ description: v }); }
103 }),
104 el('a', {
105 href: '#editor', style: { fontSize: '14px', fontWeight: '600', color: attr.ctaColor, textDecoration: 'none', display: 'inline-flex', alignItems: 'center', gap: '4px' }
106 }, attr.ctaLabel)
107 );
108
109 var controls = el(InspectorControls, {},
110 el(PanelBody, { title: __('Content', 'blockenberg'), initialOpen: true },
111 el('p', { style: { margin: '8px 0 4px', fontSize: '11px', textTransform: 'uppercase', fontWeight: 600, color: '#9ca3af' } }, __('Cover Image', 'blockenberg')),
112 el(MediaUploadCheck, {},
113 el(MediaUpload, {
114 onSelect: function (m) { setAttr({ coverUrl: m.url, coverId: m.id, coverAlt: m.alt || '' }); },
115 allowedTypes: ['image'], value: attr.coverId,
116 render: function (ref) {
117 return el('div', {},
118 attr.coverUrl ? el('div', { style: { display: 'flex', gap: '8px', alignItems: 'center', marginBottom: '8px' } },
119 el('img', { src: attr.coverUrl, style: { width: '48px', height: '64px', objectFit: 'cover', borderRadius: '4px' } }),
120 el(Button, { isSmall: true, isDestructive: true, onClick: function () { setAttr({ coverUrl: '', coverId: 0 }); } }, '')
121 ) : null,
122 el(Button, { isSecondary: true, isSmall: true, onClick: ref.open }, attr.coverUrl ? __('Replace', 'blockenberg') : __('Choose Cover', 'blockenberg'))
123 );
124 }
125 })
126 ),
127 el(SelectControl, {
128 label: __('Content Type', 'blockenberg'), value: attr.contentType,
129 options: [
130 { label: '📚 Book', value: 'book' }, { label: '📄 Article', value: 'article' },
131 { label: '🎙️ Podcast', value: 'podcast' }, { label: '🎓 Course', value: 'course' },
132 { label: '🎬 Video', value: 'video' }
133 ],
134 onChange: function (v) { setAttr({ contentType: v }); }, __nextHasNoMarginBottom: true
135 }),
136 el(TextControl, { label: __('Badge Label (override)', 'blockenberg'), value: attr.badge, onChange: function (v) { setAttr({ badge: v }); }, __nextHasNoMarginBottom: true }),
137 el(TextControl, { label: __('CTA Label', 'blockenberg'), value: attr.ctaLabel, onChange: function (v) { setAttr({ ctaLabel: v }); }, __nextHasNoMarginBottom: true }),
138 el(TextControl, { label: __('CTA URL', 'blockenberg'), value: attr.ctaUrl, onChange: function (v) { setAttr({ ctaUrl: v }); }, __nextHasNoMarginBottom: true }),
139 el(ToggleControl, { label: __('Open in New Tab', 'blockenberg'), checked: attr.ctaIsExternal, onChange: function (v) { setAttr({ ctaIsExternal: v }); }, __nextHasNoMarginBottom: true }),
140 el(ToggleControl, { label: __('Show Rating', 'blockenberg'), checked: attr.showRating, onChange: function (v) { setAttr({ showRating: v }); }, __nextHasNoMarginBottom: true }),
141 attr.showRating && el(RangeControl, { label: __('Rating (stars)', 'blockenberg'), value: attr.rating, min: 0, max: 5, onChange: function (v) { setAttr({ rating: v }); }, __nextHasNoMarginBottom: true })
142 ),
143 el(PanelBody, { title: __('Style & Layout', 'blockenberg'), initialOpen: false },
144 el(SelectControl, {
145 label: __('Card Layout', 'blockenberg'), value: attr.layout,
146 options: [
147 { label: 'Horizontal (cover left)', value: 'horizontal' },
148 { label: 'Vertical (cover top)', value: 'vertical' },
149 { label: 'Minimal (inline)', value: 'minimal' }
150 ],
151 onChange: function (v) { setAttr({ layout: v }); }, __nextHasNoMarginBottom: true
152 }),
153 el(RangeControl, { label: __('Cover Width (px; horizontal only)', 'blockenberg'), value: attr.coverWidth, min: 60, max: 280, onChange: function (v) { setAttr({ coverWidth: v }); }, __nextHasNoMarginBottom: true }),
154 el(RangeControl, { label: __('Border Radius (px)', 'blockenberg'), value: attr.borderRadius, min: 0, max: 32, onChange: function (v) { setAttr({ borderRadius: v }); }, __nextHasNoMarginBottom: true }),
155 el(RangeControl, { label: __('Max Width (px)', 'blockenberg'), value: attr.maxWidth, min: 300, max: 1200, onChange: function (v) { setAttr({ maxWidth: v }); }, __nextHasNoMarginBottom: true }),
156 el(RangeControl, { label: __('Padding Top (px)', 'blockenberg'), value: attr.paddingTop, min: 0, max: 120, onChange: function (v) { setAttr({ paddingTop: v }); }, __nextHasNoMarginBottom: true }),
157 el(RangeControl, { label: __('Padding Bottom (px)', 'blockenberg'), value: attr.paddingBottom, min: 0, max: 120, onChange: function (v) { setAttr({ paddingBottom: v }); }, __nextHasNoMarginBottom: true })
158 ),
159
160 el( PanelBody, { title: __( 'Typography', 'blockenberg' ), initialOpen: false },
161 TC && el(TC, { label: __('Title', 'blockenberg'), value: attr.titleTypo || {}, onChange: function(v) { setAttr({ titleTypo: v }); } }),
162 TC && el(TC, { label: __('Author', 'blockenberg'), value: attr.authorTypo || {}, onChange: function(v) { setAttr({ authorTypo: v }); } }),
163 TC && el(TC, { label: __('Description', 'blockenberg'), value: attr.descTypo || {}, onChange: function(v) { setAttr({ descTypo: v }); } })
164 ),
165 el(PanelColorSettings, {
166 title: __('Colors', 'blockenberg'), initialOpen: false,
167 colorSettings: [
168 { label: __('Background', 'blockenberg'), value: attr.bgColor, onChange: function (v) { setAttr({ bgColor: v || '#ffffff' }); } },
169 { label: __('Border', 'blockenberg'), value: attr.borderColor, onChange: function (v) { setAttr({ borderColor: v || '#e5e7eb' }); } },
170 { label: __('Badge BG', 'blockenberg'), value: attr.badgeBg, onChange: function (v) { setAttr({ badgeBg: v || '#7c3aed' }); } },
171 { label: __('Badge Text', 'blockenberg'), value: attr.badgeColor, onChange: function (v) { setAttr({ badgeColor: v || '#ffffff' }); } },
172 { label: __('Title', 'blockenberg'), value: attr.titleColor, onChange: function (v) { setAttr({ titleColor: v || '#111827' }); } },
173 { label: __('Author', 'blockenberg'), value: attr.authorColor, onChange: function (v) { setAttr({ authorColor: v || '#6b7280' }); } },
174 { label: __('Description', 'blockenberg'), value: attr.descColor, onChange: function (v) { setAttr({ descColor: v || '#374151' }); } },
175 { label: __('Stars', 'blockenberg'), value: attr.ratingColor, onChange: function (v) { setAttr({ ratingColor: v || '#f59e0b' }); } },
176 { label: __('CTA Link', 'blockenberg'), value: attr.ctaColor, onChange: function (v) { setAttr({ ctaColor: v || '#7c3aed' }); } }
177 ]
178 })
179 );
180
181 return el('div', blockProps, controls,
182 el('div', { style: { paddingTop: attr.paddingTop + 'px', paddingBottom: attr.paddingBottom + 'px' } },
183 el('div', { style: cardStyle }, cover, content)
184 )
185 );
186 },
187
188 save: function (props) {
189 return el('div', wp.blockEditor.useBlockProps.save(),
190 el('div', { className: 'bkbg-rdc-app', 'data-opts': JSON.stringify(props.attributes) })
191 );
192 }
193 });
194 }() );
195