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 / study-notes / index.js

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

286 lines 20.9 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 useState = wp.element.useState;
5 var registerBlockType = wp.blocks.registerBlockType;
6 var InspectorControls = wp.blockEditor.InspectorControls;
7 var useBlockProps = wp.blockEditor.useBlockProps;
8 var PanelBody = wp.components.PanelBody;
9 var PanelColorSettings = wp.blockEditor.PanelColorSettings;
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 TextareaControl = wp.components.TextareaControl;
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
20 // ── helpers ────────────────────────────────────────────────────
21 function updateNote(notes, idx, field, val) {
22 return notes.map(function (n, i) {
23 if (i !== idx) return n;
24 var u = {}; u[field] = val;
25 return Object.assign({}, n, u);
26 });
27 }
28 function addNote(notes) {
29 return notes.concat([{ cue: 'New cue / question', content: 'Notes for this cue…' }]);
30 }
31 function removeNote(notes, idx) {
32 return notes.filter(function (_, i) { return i !== idx; });
33 }
34 function updateTerm(terms, idx, field, val) {
35 return terms.map(function (t, i) {
36 if (i !== idx) return t;
37 var u = {}; u[field] = val;
38 return Object.assign({}, t, u);
39 });
40 }
41 function addTerm(terms) {
42 return terms.concat([{ term: 'New Term', definition: 'Definition goes here.' }]);
43 }
44 function removeTerm(terms, idx) {
45 return terms.filter(function (_, i) { return i !== idx; });
46 }
47
48 registerBlockType('blockenberg/study-notes', {
49 edit: function (props) {
50 var a = props.attributes;
51 var set = props.setAttributes;
52
53 var lhState = useState(null);
54 var lhIdx = lhState[0]; var setLhIdx = lhState[1];
55
56 var layoutOptions = [
57 { label: 'Cornell (Cue | Notes)', value: 'cornell' },
58 { label: 'Linear (stacked)', value: 'linear' },
59 { label: 'Cards', value: 'cards' }
60 ];
61
62 // preview row for cornell
63 function noteRow(note, idx) {
64 var isExpanded = lhIdx === idx;
65 var cueW = (a.cueWidth || 30) + '%';
66 return el('div', {
67 key: idx,
68 style: {
69 display: 'flex',
70 borderBottom: '1px solid ' + a.rowBorderColor,
71 fontSize: (a.fontSize || 14) + 'px'
72 }
73 },
74 // cue column
75 el('div', { style: { width: cueW, flexShrink: 0, padding: '12px 14px', background: a.cueBg, borderRight: '1px solid ' + a.cueBorderColor, color: a.cueColor, fontWeight: 600, lineHeight: 1.5, cursor: 'pointer' }, onClick: function () { setLhIdx(isExpanded ? null : idx); } },
76 el('div', { style: { marginBottom: 8 } }, note.cue),
77 el(TextareaControl, { value: note.cue, rows: 2, __nextHasNoMarginBottom: true, onChange: function (v) { set({ notes: updateNote(a.notes, idx, 'cue', v) }); } })
78 ),
79 // notes column
80 el('div', { style: { flex: 1, padding: '12px 14px', background: a.notesBg, color: a.notesColor } },
81 el(TextareaControl, { value: note.content, rows: 4, __nextHasNoMarginBottom: true, onChange: function (v) { set({ notes: updateNote(a.notes, idx, 'content', v) }); } }),
82 el(Button, { isDestructive: true, variant: 'link', style: { marginTop: 4, fontSize: 11 }, onClick: function () { set({ notes: removeNote(a.notes, idx) }); } }, '✕ Remove row')
83 )
84 );
85 }
86
87 function cardRow(note, idx) {
88 return el('div', {
89 key: idx,
90 style: {
91 background: a.notesBg,
92 border: '1px solid ' + a.rowBorderColor,
93 borderRadius: 8,
94 padding: '14px 16px',
95 fontSize: (a.fontSize || 14) + 'px'
96 }
97 },
98 el('div', { style: { fontWeight: 700, color: a.cueColor, marginBottom: 6 } }, note.cue),
99 el(TextControl, { label: 'Cue / Keyword', value: note.cue, __nextHasNoMarginBottom: true, onChange: function (v) { set({ notes: updateNote(a.notes, idx, 'cue', v) }); } }),
100 el('div', { style: { marginTop: 8 } },
101 el(TextareaControl, { label: 'Notes', value: note.content, rows: 3, __nextHasNoMarginBottom: true, onChange: function (v) { set({ notes: updateNote(a.notes, idx, 'content', v) }); } })
102 ),
103 el(Button, { isDestructive: true, variant: 'link', style: { fontSize: 11, marginTop: 6 }, onClick: function () { set({ notes: removeNote(a.notes, idx) }); } }, '✕ Remove')
104 );
105 }
106
107 var blockProps = useBlockProps((function () {
108 var _tvf = getTypoCssVars();
109 var s = {};
110 Object.assign(s, _tvf(a.titleTypo, '--bksn-tt-'));
111 Object.assign(s, _tvf(a.textTypo, '--bksn-tx-'));
112 return { className: 'bkbg-sn-editor-wrap', style: s };
113 })());
114
115 return el(Fragment, null,
116 el('div', blockProps,
117 // ── Header preview ─────────────────────────────
118 el('div', { style: { background: a.headerBg, color: a.headerColor, borderRadius: (a.borderRadius || 10) + 'px ' + (a.borderRadius || 10) + 'px 0 0', padding: '16px 20px' } },
119 el('div', { style: { display: 'flex', alignItems: 'baseline', flexWrap: 'wrap', gap: 12 } },
120 el('h3', { className: 'bkbg-sn-topic', style: { margin: 0, color: a.headerColor } }, a.topic || 'Topic'),
121 a.showSubject && el('span', { style: { background: 'rgba(255,255,255,.2)', padding: '2px 10px', borderRadius: 100, fontSize: 12, fontWeight: 600 } }, a.subject)
122 ),
123 el('div', { style: { display: 'flex', gap: 16, marginTop: 6, fontSize: 13, opacity: .8 } },
124 a.showSource && el('span', null, '📖 ' + a.source),
125 a.showDate && el('span', null, '�
126 ' + a.noteDate)
127 )
128 ),
129 // ── Cornell column headers ─────────────────────
130 a.layout === 'cornell' && el('div', { style: { display: 'flex', background: a.accentColor, color: '#fff', fontSize: 11, fontWeight: 700, letterSpacing: '0.06em', textTransform: 'uppercase' } },
131 el('div', { style: { width: (a.cueWidth || 30) + '%', padding: '6px 14px', borderRight: '1px solid rgba(255,255,255,.3)' } }, 'Cues / Questions'),
132 el('div', { style: { flex: 1, padding: '6px 14px' } }, 'Notes')
133 ),
134 // ── Notes rows ────────────────────────────────
135 el('div', { style: { border: '1px solid ' + a.borderColor, borderTop: 'none', background: a.layout === 'cards' ? 'transparent' : a.notesBg } },
136 a.layout === 'cards'
137 ? el('div', { style: { display: 'grid', gridTemplateColumns: 'repeat(auto-fill,minmax(280px,1fr))', gap: 12, padding: 14 } },
138 a.notes.map(function (n, i) { return cardRow(n, i); })
139 )
140 : a.notes.map(function (n, i) { return noteRow(n, i); })
141 ),
142 el('div', { style: { marginTop: 8 } },
143 el(Button, { variant: 'secondary', onClick: function () { set({ notes: addNote(a.notes) }); } }, '+ Add Row')
144 ),
145 // ── Summary ────────────────────────────────────
146 a.showSummary && el('div', { style: { marginTop: 12, background: a.summaryBg, border: '1px solid ' + a.summaryBorderColor, borderRadius: 8, padding: '14px 16px' } },
147 el('div', { style: { fontWeight: 700, fontSize: (a.summarySize || 12), textTransform: 'uppercase', letterSpacing: '0.06em', color: a.summaryColor, marginBottom: 6 } }, a.summaryLabel || 'Summary'),
148 el(TextareaControl, { value: a.summary, rows: 3, __nextHasNoMarginBottom: true, onChange: function (v) { set({ summary: v }); } })
149 ),
150 // ── Key Terms ──────────────────────────────────
151 a.showKeyTerms && el('div', { style: { marginTop: 12, background: a.keyTermsBg, border: '1px solid ' + a.keyTermsBorderColor, borderRadius: 8, padding: '14px 16px' } },
152 el('div', { style: { fontWeight: 700, fontSize: 12, textTransform: 'uppercase', letterSpacing: '0.06em', color: a.keyTermsColor, marginBottom: 10 } }, a.keyTermsLabel || 'Key Terms'),
153 a.keyTerms.map(function (t, i) {
154 return el('div', { key: i, style: { display: 'flex', gap: 8, marginBottom: 8, alignItems: 'flex-start' } },
155 el('div', { style: { flex: '0 0 36%' } },
156 el(TextControl, { placeholder: 'Term', value: t.term, __nextHasNoMarginBottom: true, onChange: function (v) { set({ keyTerms: updateTerm(a.keyTerms, i, 'term', v) }); } })
157 ),
158 el('div', { style: { flex: 1 } },
159 el(TextControl, { placeholder: 'Definition', value: t.definition, __nextHasNoMarginBottom: true, onChange: function (v) { set({ keyTerms: updateTerm(a.keyTerms, i, 'definition', v) }); } })
160 ),
161 el(Button, { isDestructive: true, variant: 'link', style: { fontSize: 11, paddingTop: 4 }, onClick: function () { set({ keyTerms: removeTerm(a.keyTerms, i) }); } }, '')
162 );
163 }),
164 el(Button, { variant: 'secondary', style: { marginTop: 4 }, onClick: function () { set({ keyTerms: addTerm(a.keyTerms) }); } }, '+ Add Term')
165 ),
166 // ── Tags ────────────────────────────────────────
167 a.showTags && a.tags.length > 0 && el('div', { style: { display: 'flex', flexWrap: 'wrap', gap: 6, marginTop: 10 } },
168 a.tags.map(function (tag, i) {
169 return el('span', { key: i, style: { background: a.tagBg, color: a.tagColor, padding: '3px 10px', borderRadius: 100, fontSize: 12, fontWeight: 600 } }, tag);
170 })
171 )
172 ),
173 // ── Inspector ──────────────────────────────────────
174 el(InspectorControls, null,
175 // Note Info
176 el(PanelBody, { title: 'Note Details', initialOpen: true },
177 el(TextControl, { label: 'Topic / Title', value: a.topic, __nextHasNoMarginBottom: true, onChange: function (v) { set({ topic: v }); } }),
178 el('div', { style: { marginTop: 8 } },
179 el(TextControl, { label: 'Subject', value: a.subject, __nextHasNoMarginBottom: true, onChange: function (v) { set({ subject: v }); } })
180 ),
181 el('div', { style: { marginTop: 8 } },
182 el(TextControl, { label: 'Source / Professor', value: a.source, __nextHasNoMarginBottom: true, onChange: function (v) { set({ source: v }); } })
183 ),
184 el('div', { style: { marginTop: 8 } },
185 el(TextControl, { label: 'Date', value: a.noteDate, __nextHasNoMarginBottom: true, onChange: function (v) { set({ noteDate: v }); } })
186 ),
187 el('div', { style: { marginTop: 8 } },
188 el(ToggleControl, { label: 'Show Subject Badge', checked: a.showSubject, __nextHasNoMarginBottom: true, onChange: function (v) { set({ showSubject: v }); } })
189 ),
190 el(ToggleControl, { label: 'Show Source', checked: a.showSource, __nextHasNoMarginBottom: true, onChange: function (v) { set({ showSource: v }); } }),
191 el(ToggleControl, { label: 'Show Date', checked: a.showDate, __nextHasNoMarginBottom: true, onChange: function (v) { set({ showDate: v }); } })
192 ),
193 // Layout
194 el(PanelBody, { title: 'Layout', initialOpen: false },
195 el(SelectControl, { label: 'Notes Layout', value: a.layout, options: layoutOptions, __nextHasNoMarginBottom: true, onChange: function (v) { set({ layout: v }); } }),
196 a.layout === 'cornell' && el('div', { style: { marginTop: 8 } },
197 el(RangeControl, { label: 'Cue Column Width (%)', value: a.cueWidth, min: 20, max: 45, __nextHasNoMarginBottom: true, onChange: function (v) { set({ cueWidth: v }); } })
198 )
199 ),
200 // Summary & Key Terms
201 el(PanelBody, { title: 'Summary & Key Terms', initialOpen: false },
202 el(ToggleControl, { label: 'Show Summary', checked: a.showSummary, __nextHasNoMarginBottom: true, onChange: function (v) { set({ showSummary: v }); } }),
203 el('div', { style: { marginTop: 6 } },
204 el(TextControl, { label: 'Summary Label', value: a.summaryLabel, __nextHasNoMarginBottom: true, onChange: function (v) { set({ summaryLabel: v }); } })
205 ),
206 el('div', { style: { marginTop: 8 } },
207 el(ToggleControl, { label: 'Show Key Terms', checked: a.showKeyTerms, __nextHasNoMarginBottom: true, onChange: function (v) { set({ showKeyTerms: v }); } })
208 ),
209 el('div', { style: { marginTop: 6 } },
210 el(TextControl, { label: 'Key Terms Label', value: a.keyTermsLabel, __nextHasNoMarginBottom: true, onChange: function (v) { set({ keyTermsLabel: v }); } })
211 ),
212 el('div', { style: { marginTop: 8 } },
213 el(ToggleControl, { label: 'Show Tags', checked: a.showTags, __nextHasNoMarginBottom: true, onChange: function (v) { set({ showTags: v }); } })
214 ),
215 a.showTags && el('div', { style: { marginTop: 8 } },
216 el(TextControl, { label: 'Tags (comma-separated)', value: a.tags.join(', '), __nextHasNoMarginBottom: true, onChange: function (v) { set({ tags: v.split(',').map(function (t) { return t.trim(); }).filter(Boolean) }); } })
217 )
218 ),
219 // Typography
220 el(PanelBody, { title: 'Typography', initialOpen: false },
221 getTypoControl()({ label: 'Title', value: a.titleTypo, onChange: function (v) { set({ titleTypo: v }); } }),
222 getTypoControl()({ label: 'Text / Notes', value: a.textTypo, onChange: function (v) { set({ textTypo: v }); } }),
223 el('div', { style: { marginTop: 8 } },
224 el(RangeControl, { label: 'Summary Size (px)', value: a.summarySize, min: 10, max: 24, __nextHasNoMarginBottom: true, onChange: function (v) { set({ summarySize: v }); } })
225 )
226 ),
227 // Colors — Header
228 el(PanelBody, { title: 'Spacing', initialOpen: false },
229 el(RangeControl, { label: 'Border Radius (px)', value: a.borderRadius, min: 0, max: 24, __nextHasNoMarginBottom: true, onChange: function (v) { set({ borderRadius: v }); } })
230 ),
231 el(PanelColorSettings, {
232 title: 'Header Colors',
233 initialOpen: false,
234 colorSettings: [
235 { label: 'Header Background', value: a.headerBg, onChange: function (v) { set({ headerBg: v || '#1e3a5f' }); } },
236 { label: 'Header Text', value: a.headerColor, onChange: function (v) { set({ headerColor: v || '#ffffff' }); } },
237 { label: 'Accent / Stripe', value: a.accentColor, onChange: function (v) { set({ accentColor: v || '#3b82f6' }); } }
238 ]
239 }),
240 // Colors — Notes
241 el(PanelColorSettings, {
242 title: 'Notes Area Colors',
243 initialOpen: false,
244 colorSettings: [
245 { label: 'Block Background', value: a.bgColor, onChange: function (v) { set({ bgColor: v || '#ffffff' }); } },
246 { label: 'Border', value: a.borderColor, onChange: function (v) { set({ borderColor: v || '#d1d5db' }); } },
247 { label: 'Cue Column BG', value: a.cueBg, onChange: function (v) { set({ cueBg: v || '#f8fafc' }); } },
248 { label: 'Cue Text / Keywords', value: a.cueColor, onChange: function (v) { set({ cueColor: v || '#1e40af' }); } },
249 { label: 'Cue Border', value: a.cueBorderColor, onChange: function (v) { set({ cueBorderColor: v || '#e2e8f0' }); } },
250 { label: 'Notes Background', value: a.notesBg, onChange: function (v) { set({ notesBg: v || '#ffffff' }); } },
251 { label: 'Notes Text', value: a.notesColor, onChange: function (v) { set({ notesColor: v || '#374151' }); } },
252 { label: 'Row Divider', value: a.rowBorderColor, onChange: function (v) { set({ rowBorderColor: v || '#e5e7eb' }); } }
253 ]
254 }),
255 // Colors — Summary & Terms
256 el(PanelColorSettings, {
257 title: 'Summary & Key Terms Colors',
258 initialOpen: false,
259 colorSettings: [
260 { label: 'Summary Background', value: a.summaryBg, onChange: function (v) { set({ summaryBg: v || '#fefce8' }); } },
261 { label: 'Summary Text', value: a.summaryColor, onChange: function (v) { set({ summaryColor: v || '#1c1917' }); } },
262 { label: 'Summary Border', value: a.summaryBorderColor, onChange: function (v) { set({ summaryBorderColor: v || '#fde68a' }); } },
263 { label: 'Key Terms Background', value: a.keyTermsBg, onChange: function (v) { set({ keyTermsBg: v || '#f0f9ff' }); } },
264 { label: 'Key Terms Text', value: a.keyTermsColor, onChange: function (v) { set({ keyTermsColor: v || '#0f172a' }); } },
265 { label: 'Key Terms Border', value: a.keyTermsBorderColor, onChange: function (v) { set({ keyTermsBorderColor: v || '#bae6fd' }); } },
266 { label: 'Term Word Color', value: a.termColor, onChange: function (v) { set({ termColor: v || '#0369a1' }); } },
267 { label: 'Tag Background', value: a.tagBg, onChange: function (v) { set({ tagBg: v || '#e0e7ff' }); } },
268 { label: 'Tag Text', value: a.tagColor, onChange: function (v) { set({ tagColor: v || '#3730a3' }); } }
269 ]
270 })
271 )
272 );
273 },
274
275 save: function (props) {
276 var useBlockProps = wp.blockEditor.useBlockProps;
277 return wp.element.createElement('div', useBlockProps.save(),
278 wp.element.createElement('div', {
279 className: 'bkbg-study-notes-app',
280 'data-opts': JSON.stringify(props.attributes)
281 })
282 );
283 }
284 });
285 }() );
286