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 / content-outline / frontend.js

frontend.js in Blockenberg — 600+ Advanced Gutenberg Blocks & AI Agent for WordPress Block Editor 2.0.7, at blocks/content-outline/frontend.js

279 lines 14.6 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 (function () {
2 'use strict';
3
4 function typoCssVarsForEl(typo, prefix, el) {
5 if (!typo || typeof typo !== 'object') return;
6
7 // Non-responsive
8 if (typo.family) el.style.setProperty(prefix + 'font-family', "'" + typo.family + "', sans-serif");
9 if (typo.weight) el.style.setProperty(prefix + 'font-weight', typo.weight);
10 if (typo.transform) el.style.setProperty(prefix + 'text-transform', typo.transform);
11 if (typo.style) el.style.setProperty(prefix + 'font-style', typo.style);
12 if (typo.decoration) el.style.setProperty(prefix + 'text-decoration', typo.decoration);
13
14 // Responsive
15 var su = typo.sizeUnit || 'px';
16 if (typo.sizeDesktop !== '' && typo.sizeDesktop !== undefined && typo.sizeDesktop !== null) el.style.setProperty(prefix + 'font-size-d', typo.sizeDesktop + su);
17 if (typo.sizeTablet !== '' && typo.sizeTablet !== undefined && typo.sizeTablet !== null) el.style.setProperty(prefix + 'font-size-t', typo.sizeTablet + su);
18 if (typo.sizeMobile !== '' && typo.sizeMobile !== undefined && typo.sizeMobile !== null) el.style.setProperty(prefix + 'font-size-m', typo.sizeMobile + su);
19
20 var lhu = typo.lineHeightUnit || 'px';
21 if (typo.lineHeightDesktop !== '' && typo.lineHeightDesktop !== undefined && typo.lineHeightDesktop !== null) el.style.setProperty(prefix + 'line-height-d', typo.lineHeightDesktop + lhu);
22 if (typo.lineHeightTablet !== '' && typo.lineHeightTablet !== undefined && typo.lineHeightTablet !== null) el.style.setProperty(prefix + 'line-height-t', typo.lineHeightTablet + lhu);
23 if (typo.lineHeightMobile !== '' && typo.lineHeightMobile !== undefined && typo.lineHeightMobile !== null) el.style.setProperty(prefix + 'line-height-m', typo.lineHeightMobile + lhu);
24
25 var lsu = typo.letterSpacingUnit || 'px';
26 if (typo.letterSpacingDesktop !== '' && typo.letterSpacingDesktop !== undefined && typo.letterSpacingDesktop !== null) {
27 el.style.setProperty(prefix + 'letter-spacing-d', typo.letterSpacingDesktop + lsu);
28 el.style.setProperty(prefix + 'letter-spacing', typo.letterSpacingDesktop + lsu);
29 }
30 if (typo.letterSpacingTablet !== '' && typo.letterSpacingTablet !== undefined && typo.letterSpacingTablet !== null) el.style.setProperty(prefix + 'letter-spacing-t', typo.letterSpacingTablet + lsu);
31 if (typo.letterSpacingMobile !== '' && typo.letterSpacingMobile !== undefined && typo.letterSpacingMobile !== null) el.style.setProperty(prefix + 'letter-spacing-m', typo.letterSpacingMobile + lsu);
32
33 var wsu = typo.wordSpacingUnit || 'px';
34 if (typo.wordSpacingDesktop !== '' && typo.wordSpacingDesktop !== undefined && typo.wordSpacingDesktop !== null) {
35 el.style.setProperty(prefix + 'word-spacing-d', typo.wordSpacingDesktop + wsu);
36 el.style.setProperty(prefix + 'word-spacing', typo.wordSpacingDesktop + wsu);
37 }
38 if (typo.wordSpacingTablet !== '' && typo.wordSpacingTablet !== undefined && typo.wordSpacingTablet !== null) el.style.setProperty(prefix + 'word-spacing-t', typo.wordSpacingTablet + wsu);
39 if (typo.wordSpacingMobile !== '' && typo.wordSpacingMobile !== undefined && typo.wordSpacingMobile !== null) el.style.setProperty(prefix + 'word-spacing-m', typo.wordSpacingMobile + wsu);
40 }
41
42 function mk(tag, cls, styles) {
43 var d = document.createElement(tag);
44 if (cls) d.className = cls;
45 if (styles) Object.keys(styles).forEach(function (k) { d.style[k] = styles[k]; });
46 return d;
47 }
48 function mkText(tag, cls, text, styles) {
49 var d = mk(tag, cls, styles);
50 d.textContent = text;
51 return d;
52 }
53
54 function getStatusStyle(status, o) {
55 if (status === 'done') return { background: o.doneBg, color: o.doneColor };
56 if (status === 'in-progress') return { background: o.inProgressBg, color: o.inProgressColor };
57 if (status === 'planned') return { background: o.plannedBg, color: o.plannedColor };
58 return null;
59 }
60
61 function getStatusLabel(status) {
62 if (status === 'done') return '✓ Done';
63 if (status === 'in-progress') return '⟳ In Progress';
64 if (status === 'planned') return '○ Planned';
65 return '';
66 }
67
68 function init() {
69 document.querySelectorAll('.bkbg-content-outline-app').forEach(function (appEl) {
70 if (appEl.dataset.rendered) return;
71 appEl.dataset.rendered = '1';
72
73 var opts; try { opts = JSON.parse(appEl.dataset.opts || '{}'); } catch (e) { opts = {}; }
74
75 var o = {
76 outlineTitle: opts.outlineTitle || 'Article Outline',
77 showTitle: opts.showTitle !== false,
78 intro: opts.intro || '',
79 showIntro: opts.showIntro !== false,
80 sections: opts.sections || [],
81 style: opts.style || 'card',
82 showNumbers: opts.showNumbers !== false,
83 showStatus: opts.showStatus !== false,
84 showReadTime: opts.showReadTime !== false,
85 showDescription: opts.showDescription !== false,
86 showPoints: opts.showPoints !== false,
87 collapsible: opts.collapsible || false,
88 borderRadius: opts.borderRadius !== undefined ? opts.borderRadius : 12,
89 gap: opts.gap !== undefined ? opts.gap : 16,
90 fontSize: opts.fontSize !== undefined ? opts.fontSize : 14,
91 sectionTitleSize:opts.sectionTitleSize !== undefined ? opts.sectionTitleSize : 16,
92 titleFontSize: opts.titleFontSize !== undefined ? opts.titleFontSize : 22,
93 bgColor: opts.bgColor || '#f8fafc',
94 cardBg: opts.cardBg || '#ffffff',
95 borderColor: opts.borderColor || '#e2e8f0',
96 titleColor: opts.titleColor || '#0f172a',
97 introColor: opts.introColor || '#64748b',
98 numberBg: opts.numberBg || '#6366f1',
99 numberColor: opts.numberColor || '#ffffff',
100 sectionTitleColor:opts.sectionTitleColor || '#1e293b',
101 descriptionColor: opts.descriptionColor || '#64748b',
102 pointColor: opts.pointColor || '#374151',
103 accentColor: opts.accentColor || '#6366f1',
104 doneBg: opts.doneBg || '#dcfce7',
105 doneColor: opts.doneColor || '#166534',
106 inProgressBg: opts.inProgressBg || '#fef9c3',
107 inProgressColor: opts.inProgressColor || '#854d0e',
108 plannedBg: opts.plannedBg || '#f1f5f9',
109 plannedColor: opts.plannedColor || '#475569'
110 };
111
112 var isCard = o.style === 'card';
113 var isList = o.style === 'list';
114 var isCompact = o.style === 'compact';
115
116 /* ── Outer block ─────────────────────────────────── */
117 var block = mk('div', 'bkbg-co-block' + (o.collapsible ? ' bkbg-co-collapsible' : ''), {
118 background: o.bgColor,
119 borderRadius: o.borderRadius + 'px',
120 boxSizing: 'border-box'
121 });
122
123 /* ── Header ──────────────────────────────────────── */
124 if (o.showTitle || o.showIntro) {
125 var header = mk('div', 'bkbg-co-header', {
126 borderColor: o.borderColor,
127 marginBottom: o.gap + 'px',
128 paddingBottom: '16px'
129 });
130 if (o.showTitle && o.outlineTitle) {
131 var titleEl = mkText('h3', 'bkbg-co-title', o.outlineTitle, {
132 color: o.titleColor
133 });
134 header.appendChild(titleEl);
135 }
136 if (o.showIntro && o.intro) {
137 header.appendChild(mkText('p', 'bkbg-co-intro', o.intro, { color: o.introColor }));
138 }
139 block.appendChild(header);
140 }
141
142 /* ── Sections ────────────────────────────────────── */
143 var sectionsWrap = mk('div', 'bkbg-co-sections', { gap: o.gap + 'px' });
144
145 /* Progress tracking */
146 var totalPoints = 0, donePoints = 0;
147
148 o.sections.forEach(function (section, sIdx) {
149 var sectionEl = mk('div', 'bkbg-co-section' + (isCard ? ' is-card' : ''));
150
151 if (isCard) {
152 sectionEl.style.background = o.cardBg;
153 sectionEl.style.border = '1px solid ' + o.borderColor;
154 sectionEl.style.borderRadius = o.borderRadius + 'px';
155 } else {
156 sectionEl.style.borderBottom = '1px solid ' + o.borderColor;
157 sectionEl.style.paddingBottom = '12px';
158 }
159
160 /* Section head */
161 var headPad = isCard ? '16px 20px' : '12px 0';
162 var headBorderB = (o.showPoints && section.points && section.points.length > 0 && isCard)
163 ? '1px solid ' + o.borderColor : 'none';
164
165 var head = mk('div', 'bkbg-co-section-head', {
166 padding: headPad,
167 borderBottom: headBorderB
168 });
169
170 /* Number badge */
171 if (o.showNumbers) {
172 var numBadge = mkText('div', 'bkbg-co-number', String(sIdx + 1), {
173 background: o.numberBg,
174 color: o.numberColor
175 });
176 head.appendChild(numBadge);
177 }
178
179 /* Title + description */
180 var info = mk('div', 'bkbg-co-section-info');
181 info.appendChild(mkText('div', 'bkbg-co-section-title', section.title || '', {
182 color: o.sectionTitleColor
183 }));
184 if (o.showDescription && section.description) {
185 info.appendChild(mkText('div', 'bkbg-co-section-desc', section.description, { color: o.descriptionColor }));
186 }
187 head.appendChild(info);
188
189 /* Read time */
190 if (o.showReadTime && section.readTime > 0) {
191 head.appendChild(mkText('span', 'bkbg-co-read-time', section.readTime + ' min', { color: o.descriptionColor }));
192 }
193
194 /* Collapsible toggle */
195 if (o.collapsible) {
196 var toggleBtn = mkText('button', 'bkbg-co-toggle is-open', '');
197 head.appendChild(toggleBtn);
198 }
199
200 sectionEl.appendChild(head);
201
202 /* Points body */
203 if (o.showPoints && section.points && section.points.length) {
204 var bodyEl = mk('div', 'bkbg-co-body');
205 var ptsPad = isCard ? '10px 20px 16px 20px' : '8px 0 4px ' + (o.showNumbers ? '40px' : '0');
206 var ptsList = mk('ul', 'bkbg-co-points', { padding: ptsPad });
207
208 section.points.forEach(function (point) {
209 totalPoints++;
210 if (point.status === 'done') donePoints++;
211
212 var li = mk('li', 'bkbg-co-point', {
213 marginBottom: '7px',
214 fontSize: o.fontSize + 'px'
215 });
216
217 li.appendChild(mkText('span', 'bkbg-co-arrow', '', { color: o.accentColor }));
218 li.appendChild(mkText('span', 'bkbg-co-point-text', point.text || '', { color: o.pointColor }));
219
220 if (o.showStatus && point.status && point.status !== 'none') {
221 var stStyle = getStatusStyle(point.status, o);
222 if (stStyle) {
223 var badge = mkText('span', 'bkbg-co-status', getStatusLabel(point.status), stStyle);
224 li.appendChild(badge);
225 }
226 }
227
228 ptsList.appendChild(li);
229 });
230
231 bodyEl.appendChild(ptsList);
232 sectionEl.appendChild(bodyEl);
233
234 /* Wire up collapsible */
235 if (o.collapsible) {
236 var toggleBtnRef = head.querySelector('.bkbg-co-toggle');
237 bodyEl.style.maxHeight = bodyEl.scrollHeight + 'px';
238
239 toggleBtnRef.addEventListener('click', function () {
240 var isOpen = toggleBtnRef.classList.contains('is-open');
241 if (isOpen) {
242 bodyEl.style.maxHeight = '0';
243 toggleBtnRef.classList.remove('is-open');
244 } else {
245 bodyEl.style.maxHeight = bodyEl.scrollHeight + 'px';
246 toggleBtnRef.classList.add('is-open');
247 }
248 });
249 }
250 }
251
252 sectionsWrap.appendChild(sectionEl);
253 });
254
255 block.appendChild(sectionsWrap);
256 typoCssVarsForEl(opts.typoTitle, '--bkco-title-', block);
257 typoCssVarsForEl(opts.typoSection, '--bkco-sec-', block);
258 /* ── Overall progress bar ────────────────────────── */
259 if (totalPoints > 0) {
260 var pct = Math.round((donePoints / totalPoints) * 100);
261 var barWrap = mk('div', 'bkbg-co-progress-bar', { marginTop: o.gap + 'px' });
262 var fill = mk('div', 'bkbg-co-progress-fill', {
263 background: o.accentColor,
264 width: pct + '%'
265 });
266 barWrap.appendChild(fill);
267 block.appendChild(barWrap);
268 }
269
270 /* ── Insert ──────────────────────────────────────── */
271 appEl.parentNode.insertBefore(block, appEl);
272 appEl.style.display = 'none';
273 });
274 }
275
276 if (document.readyState !== 'loading') { init(); }
277 else { document.addEventListener('DOMContentLoaded', init); }
278 })();
279