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

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

245 lines 16.4 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 registerBlockType = wp.blocks.registerBlockType;
6 var InspectorControls = wp.blockEditor.InspectorControls;
7 var useBlockProps = wp.blockEditor.useBlockProps;
8 var PanelColorSettings = wp.blockEditor.PanelColorSettings;
9 var PanelBody = wp.components.PanelBody;
10 var ToggleControl = wp.components.ToggleControl;
11 var RangeControl = wp.components.RangeControl;
12 var SelectControl = wp.components.SelectControl;
13 var TextControl = wp.components.TextControl;
14 var Button = wp.components.Button;
15 var _tc; function getTypoControl() { return _tc || (_tc = window.bkbgTypographyControl); }
16 var _tv; function getTypoCssVars() { return _tv || (_tv = window.bkbgTypoCssVars); }
17 var IP = function () { return window.bkbgIconPicker; };
18
19 var NOTE_TYPES = [
20 { label: '💬 Quote', value: 'quote' },
21 { label: '💡 Insight', value: 'insight' },
22 { label: '❓ Question',value: 'question' },
23 { label: '📝 Summary', value: 'summary' }
24 ];
25
26 function noteIcon(type) {
27 if (type === 'quote') return '"';
28 if (type === 'insight') return '💡';
29 if (type === 'question') return '?';
30 return '📝';
31 }
32
33 function getNoteStyle(type, a) {
34 if (type === 'quote') return { bg: a.quoteBg, color: a.quoteColor, accent: a.quoteAccent };
35 if (type === 'insight') return { bg: a.insightBg, color: a.insightColor, accent: a.insightAccent };
36 if (type === 'question') return { bg: a.questionBg, color: a.questionColor, accent: a.questionAccent };
37 return { bg: a.summaryBg, color: a.summaryColor, accent: a.summaryAccent };
38 }
39
40 function renderStars(rating, starColor) {
41 var stars = '';
42 for (var i = 1; i <= 5; i++) { stars += i <= rating ? '�
43 ' : ''; }
44 return el('span', { style: { color: starColor, fontSize: '18px', letterSpacing: 2 } }, stars);
45 }
46
47 /* ── ES5 update helpers ──────────────────────────────── */
48 function updateNote(notes, idx, field, val) {
49 return notes.map(function (n, i) {
50 if (i !== idx) return n;
51 var u = {}; u[field] = val;
52 return Object.assign({}, n, u);
53 });
54 }
55 function addNote(notes) {
56 return notes.concat([{ type: 'insight', text: 'New note', source: '' }]);
57 }
58 function removeNote(notes, idx) {
59 return notes.filter(function (_, i) { return i !== idx; });
60 }
61
62 registerBlockType('blockenberg/reading-notes', {
63 edit: function (props) {
64 var a = props.attributes;
65 var set = props.setAttributes;
66 var TC = getTypoControl();
67 var blockProps = useBlockProps((function() {
68 var _tvFn = getTypoCssVars();
69 var s = {};
70 if (_tvFn) {
71 Object.assign(s, _tvFn(a.titleTypo || {}, '--bkrn-tt-'));
72 Object.assign(s, _tvFn(a.noteTypo || {}, '--bkrn-nt-'));
73 }
74 return { className: 'bkbg-rn-editor', style: s };
75 })());
76
77 function renderPreview() {
78 return el('div', {
79 className: 'bkbg-rn-block',
80 style: { background: a.bgColor || undefined, boxSizing: 'border-box' }
81 },
82 /* Header */
83 a.showHeader && el('div', {
84 className: 'bkbg-rn-header',
85 style: {
86 background: a.headerBg, color: a.headerColor,
87 padding: '24px 28px', borderRadius: a.borderRadius + 'px',
88 marginBottom: a.gap + 'px', display: 'flex', alignItems: 'center', gap: '20px'
89 }
90 },
91 el('div', { className: 'bkbg-rn-cover-emoji', style: { fontSize: '48px', lineHeight: 1 } }, (a.coverEmojiType || 'custom-char') !== 'custom-char' ? IP().buildEditorIcon(a.coverEmojiType, a.coverEmoji, a.coverEmojiDashicon, a.coverEmojiImageUrl, a.coverEmojiDashiconColor) : a.coverEmoji),
92 el('div', { style: { flex: 1 } },
93 el('h3', { className: 'bkbg-rn-book-title', style: { margin: '0 0 4px', color: a.headerColor } }, a.bookTitle),
94 a.showAuthor && a.author && el('div', { style: { fontSize: '14px', opacity: '.8', marginBottom: '6px' } }, 'by ' + a.author),
95 el('div', { style: { display: 'flex', flexWrap: 'wrap', gap: '10px', alignItems: 'center' } },
96 a.showGenre && a.genre && el('span', {
97 style: {
98 fontSize: '11px', padding: '3px 10px', borderRadius: '100px',
99 background: 'rgba(255,255,255,.15)', color: a.headerColor
100 }
101 }, a.genre),
102 a.showRating && renderStars(a.rating, a.starColor),
103 a.showDateRead && a.dateRead && el('span', { style: { fontSize: '12px', opacity: '.7' } }, a.dateRead)
104 )
105 )
106 ),
107 /* Notes list */
108 el('div', {
109 className: 'bkbg-rn-notes',
110 style: { display: 'flex', flexDirection: 'column', gap: a.gap + 'px' }
111 },
112 a.notes.map(function (note, idx) {
113 var ns = getNoteStyle(note.type, a);
114 return el('div', {
115 key: idx,
116 className: 'bkbg-rn-note bkbg-rn-note--' + note.type,
117 style: {
118 background: ns.bg, borderLeft: '4px solid ' + ns.accent,
119 borderRadius: a.borderRadius + 'px',
120 padding: '14px 18px',
121 display: 'flex', gap: '14px', alignItems: 'flex-start'
122 }
123 },
124 el('span', {
125 style: {
126 fontSize: note.type === 'quote' ? '28px' : '18px',
127 color: ns.accent, lineHeight: 1, flexShrink: 0, fontFamily: 'Georgia, serif',
128 marginTop: note.type === 'quote' ? '-4px' : 0
129 }
130 }, noteIcon(note.type)),
131 el('div', { style: { flex: 1 } },
132 el('span', {
133 style: {
134 display: 'inline-block', marginBottom: '6px', fontSize: '10px',
135 fontWeight: 700, textTransform: 'uppercase', letterSpacing: '.07em',
136 color: ns.accent
137 }
138 }, note.type),
139 el('p', { className: 'bkbg-rn-note-text', style: { margin: 0, color: ns.color } }, note.text),
140 note.source && el('span', { style: { fontSize: '12px', color: ns.accent, marginTop: '6px', display: 'block', opacity: '.8' } }, '' + note.source)
141 )
142 );
143 })
144 )
145 );
146 }
147
148 var inspector = el(InspectorControls, {},
149 /* Book Details */
150 el(PanelBody, { title: 'Book / Article Details', initialOpen: true },
151 el(TextControl, { __nextHasNoMarginBottom: true, label: 'Title', value: a.bookTitle, onChange: function (v) { set({ bookTitle: v }); } }),
152 el(TextControl, { __nextHasNoMarginBottom: true, label: 'Author', value: a.author, onChange: function (v) { set({ author: v }); } }),
153 el(TextControl, { __nextHasNoMarginBottom: true, label: 'Genre / Category', value: a.genre, onChange: function (v) { set({ genre: v }); } }),
154 el(IP().IconPickerControl, IP().iconPickerProps(a, set, { charAttr: 'coverEmoji', typeAttr: 'coverEmojiType', dashiconAttr: 'coverEmojiDashicon', imageUrlAttr: 'coverEmojiImageUrl', colorAttr: 'coverEmojiDashiconColor' })),
155 el(TextControl, { __nextHasNoMarginBottom: true, label: 'Date Read', value: a.dateRead, onChange: function (v) { set({ dateRead: v }); } }),
156 el(RangeControl, { __nextHasNoMarginBottom: true, label: 'Rating (stars)', value: a.rating, min: 0, max: 5, step: 1, onChange: function (v) { set({ rating: v }); } })
157 ),
158 /* Display Toggles */
159 el(PanelBody, { title: 'Display', initialOpen: false },
160 el(ToggleControl, { __nextHasNoMarginBottom: true, label: 'Show Header', checked: a.showHeader, onChange: function (v) { set({ showHeader: v }); } }),
161 el(ToggleControl, { __nextHasNoMarginBottom: true, label: 'Show Author', checked: a.showAuthor, onChange: function (v) { set({ showAuthor: v }); } }),
162 el(ToggleControl, { __nextHasNoMarginBottom: true, label: 'Show Genre', checked: a.showGenre, onChange: function (v) { set({ showGenre: v }); } }),
163 el(ToggleControl, { __nextHasNoMarginBottom: true, label: 'Show Rating', checked: a.showRating, onChange: function (v) { set({ showRating: v }); } }),
164 el(ToggleControl, { __nextHasNoMarginBottom: true, label: 'Show Date Read', checked: a.showDateRead, onChange: function (v) { set({ showDateRead: v }); } }),
165 el(SelectControl, { __nextHasNoMarginBottom: true, label: 'Layout', value: a.layout, options: [{ label: 'List', value: 'list' }, { label: 'Masonry Grid', value: 'grid' }], onChange: function (v) { set({ layout: v }); } })
166 ),
167 /* Notes Manager */
168 el(PanelBody, { title: 'Notes (' + a.notes.length + ')', initialOpen: true },
169 a.notes.map(function (note, idx) {
170 return el('div', {
171 key: idx,
172 style: { border: '1px solid #e2e8f0', borderRadius: 8, padding: 10, marginBottom: 10, background: '#f8fafc' }
173 },
174 el('div', { style: { display: 'flex', justifyContent: 'space-between', alignItems: 'center', marginBottom: 6 } },
175 el('strong', { style: { fontSize: 12 } }, '#' + (idx + 1) + ' ' + note.type),
176 el(Button, { isSmall: true, isDestructive: true, onClick: function () { set({ notes: removeNote(a.notes, idx) }); } }, '')
177 ),
178 el(SelectControl, { __nextHasNoMarginBottom: true, label: 'Type', value: note.type, options: NOTE_TYPES, onChange: function (v) { set({ notes: updateNote(a.notes, idx, 'type', v) }); } }),
179 el('div', { style: { marginBottom: 6 } },
180 el('label', { style: { fontSize: 11, fontWeight: 600, display: 'block', marginBottom: 4 } }, 'Text'),
181 el('textarea', {
182 value: note.text, rows: 3,
183 style: { width: '100%', fontSize: 12, padding: '5px 7px', border: '1px solid #ddd', borderRadius: 4, boxSizing: 'border-box', fontFamily: 'inherit' },
184 onChange: function (e) { set({ notes: updateNote(a.notes, idx, 'text', e.target.value) }); }
185 })
186 ),
187 el(TextControl, { __nextHasNoMarginBottom: true, label: 'Source / Page (optional)', value: note.source || '', onChange: function (v) { set({ notes: updateNote(a.notes, idx, 'source', v) }); } })
188 );
189 }),
190 el(Button, { variant: 'secondary', style: { width: '100%', justifyContent: 'center', marginTop: 4 }, onClick: function () { set({ notes: addNote(a.notes) }); } }, '+ Add Note')
191 ),
192 /* Spacing */
193 el(PanelBody, { title: 'Spacing & Shape', initialOpen: false },
194 el(RangeControl, { __nextHasNoMarginBottom: true, label: 'Gap', value: a.gap, min: 4, max: 32, onChange: function (v) { set({ gap: v }); } }),
195 el(RangeControl, { __nextHasNoMarginBottom: true, label: 'Border Radius', value: a.borderRadius, min: 0, max: 24, onChange: function (v) { set({ borderRadius: v }); } }),
196 ),
197 /* Colors */
198
199 el( PanelBody, { title: __( 'Typography', 'blockenberg' ), initialOpen: false },
200 TC && el(TC, { label: __('Title', 'blockenberg'), value: a.titleTypo || {}, onChange: function(v) { set({ titleTypo: v }); } }),
201 TC && el(TC, { label: __('Note Text', 'blockenberg'), value: a.noteTypo || {}, onChange: function(v) { set({ noteTypo: v }); } })
202 ),
203 el(PanelColorSettings, {
204 title: 'Header Colors', initialOpen: false,
205 colorSettings: [
206 { label: 'Header Background', value: a.headerBg, onChange: function (v) { set({ headerBg: v || '#1e293b' }); } },
207 { label: 'Header Text', value: a.headerColor, onChange: function (v) { set({ headerColor: v || '#ffffff' }); } },
208 { label: 'Star Color', value: a.starColor, onChange: function (v) { set({ starColor: v || '#f59e0b' }); } },
209 { label: 'Block Background', value: a.bgColor, onChange: function (v) { set({ bgColor: v || '' }); } }
210 ]
211 }),
212 el(PanelColorSettings, {
213 title: 'Note Type Colors', initialOpen: false,
214 colorSettings: [
215 { label: 'Quote Background', value: a.quoteBg, onChange: function (v) { set({ quoteBg: v || '#fdf2f8' }); } },
216 { label: 'Quote Text Color', value: a.quoteColor, onChange: function (v) { set({ quoteColor: v || '#86198f' }); } },
217 { label: 'Quote Accent', value: a.quoteAccent, onChange: function (v) { set({ quoteAccent: v || '#d946ef' }); } },
218 { label: 'Insight Background', value: a.insightBg, onChange: function (v) { set({ insightBg: v || '#eff6ff' }); } },
219 { label: 'Insight Text Color', value: a.insightColor, onChange: function (v) { set({ insightColor: v || '#1d4ed8' }); } },
220 { label: 'Insight Accent', value: a.insightAccent, onChange: function (v) { set({ insightAccent: v || '#3b82f6' }); } },
221 { label: 'Question Background', value: a.questionBg, onChange: function (v) { set({ questionBg: v || '#fffbeb' }); } },
222 { label: 'Question Text Color', value: a.questionColor, onChange: function (v) { set({ questionColor: v || '#92400e' }); } },
223 { label: 'Question Accent', value: a.questionAccent, onChange: function (v) { set({ questionAccent: v || '#f59e0b' }); } },
224 { label: 'Summary Background', value: a.summaryBg, onChange: function (v) { set({ summaryBg: v || '#f0fdf4' }); } },
225 { label: 'Summary Text Color', value: a.summaryColor, onChange: function (v) { set({ summaryColor: v || '#14532d' }); } },
226 { label: 'Summary Accent', value: a.summaryAccent, onChange: function (v) { set({ summaryAccent: v || '#22c55e' }); } }
227 ]
228 })
229 );
230
231 return el(Fragment, {}, inspector, el('div', blockProps, renderPreview()));
232 },
233
234 save: function (props) {
235 var useBlockProps = wp.blockEditor.useBlockProps;
236 return el('div', useBlockProps.save(),
237 el('div', {
238 className: 'bkbg-reading-notes-app',
239 'data-opts': JSON.stringify(props.attributes)
240 })
241 );
242 }
243 });
244 }() );
245