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 / book-shelf / frontend.js

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

256 lines 12.5 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 mk(tag, cls, styles) {
5 var d = document.createElement(tag);
6 if (cls) d.className = cls;
7 if (styles) Object.keys(styles).forEach(function (k) { d.style[k] = styles[k]; });
8 return d;
9 }
10 function tx(tag, cls, text, styles) {
11 var d = mk(tag, cls, styles);
12 d.textContent = text;
13 return d;
14 }
15 function ap(p) {
16 Array.prototype.slice.call(arguments, 1).forEach(function (c) { if (c) p.appendChild(c); });
17 return p;
18 }
19
20 function typoCssVarsForEl(typo, prefix, el) {
21 if (!typo) return;
22 if (typo.family) el.style.setProperty(prefix + 'font-family', "'" + typo.family + "', sans-serif");
23 if (typo.weight) el.style.setProperty(prefix + 'font-weight', typo.weight);
24 if (typo.transform) el.style.setProperty(prefix + 'text-transform', typo.transform);
25 if (typo.style) el.style.setProperty(prefix + 'font-style', typo.style);
26 if (typo.decoration) el.style.setProperty(prefix + 'text-decoration', typo.decoration);
27 var su = typo.sizeUnit || 'px';
28 if (typo.sizeDesktop !== '' && typo.sizeDesktop != null) el.style.setProperty(prefix + 'font-size-d', typo.sizeDesktop + su);
29 if (typo.sizeTablet !== '' && typo.sizeTablet != null) el.style.setProperty(prefix + 'font-size-t', typo.sizeTablet + su);
30 if (typo.sizeMobile !== '' && typo.sizeMobile != null) el.style.setProperty(prefix + 'font-size-m', typo.sizeMobile + su);
31 var lhu = typo.lineHeightUnit || '';
32 if (typo.lineHeightDesktop !== '' && typo.lineHeightDesktop != null) el.style.setProperty(prefix + 'line-height-d', typo.lineHeightDesktop + lhu);
33 if (typo.lineHeightTablet !== '' && typo.lineHeightTablet != null) el.style.setProperty(prefix + 'line-height-t', typo.lineHeightTablet + lhu);
34 if (typo.lineHeightMobile !== '' && typo.lineHeightMobile != null) el.style.setProperty(prefix + 'line-height-m', typo.lineHeightMobile + lhu);
35 var lsu = typo.letterSpacingUnit || 'px';
36 if (typo.letterSpacingDesktop !== '' && typo.letterSpacingDesktop != null) el.style.setProperty(prefix + 'letter-spacing-d', typo.letterSpacingDesktop + lsu);
37 if (typo.letterSpacingTablet !== '' && typo.letterSpacingTablet != null) el.style.setProperty(prefix + 'letter-spacing-t', typo.letterSpacingTablet + lsu);
38 if (typo.letterSpacingMobile !== '' && typo.letterSpacingMobile != null) el.style.setProperty(prefix + 'letter-spacing-m', typo.letterSpacingMobile + lsu);
39 var wsu = typo.wordSpacingUnit || 'px';
40 if (typo.wordSpacingDesktop !== '' && typo.wordSpacingDesktop != null) el.style.setProperty(prefix + 'word-spacing-d', typo.wordSpacingDesktop + wsu);
41 if (typo.wordSpacingTablet !== '' && typo.wordSpacingTablet != null) el.style.setProperty(prefix + 'word-spacing-t', typo.wordSpacingTablet + wsu);
42 if (typo.wordSpacingMobile !== '' && typo.wordSpacingMobile != null) el.style.setProperty(prefix + 'word-spacing-m', typo.wordSpacingMobile + wsu);
43 }
44
45 // ── helpers ──────────────────────────────────────────────────────
46 function renderStars(rating, color, size) {
47 var wrap = mk('span', '');
48 for (var i = 1; i <= 5; i++) {
49 ap(wrap, tx('span', '', '\u2605', { color: i <= rating ? (color || '#f59e0b') : '#334155', fontSize: (size || 12) + 'px' }));
50 }
51 return wrap;
52 }
53
54 function statusBadge(status, a) {
55 var bg = status === 'read' ? (a.statusReadBg || '#166534')
56 : status === 'reading' ? (a.statusReadingBg || '#1e40af')
57 : (a.statusWantBg || '#78350f');
58 var label = status === 'read' ? '\u2713 Read' : status === 'reading' ? '\u25B6 Reading' : '\u25CB Want';
59 return tx('span', '', label, {
60 background: bg, color: '#fff', borderRadius: '4px',
61 padding: '1px 7px', fontSize: '10px', fontWeight: '700', letterSpacing: '.04em'
62 });
63 }
64
65 // ── Shelf layout ─────────────────────────────────────────────────
66 function buildShelf(appEl, a) {
67 var sw = a.spineWidth || 46;
68 var sh = a.spineHeight || 190;
69
70 var bookRow = mk('div', 'bkbg-bs-row', {
71 display: 'flex', alignItems: 'flex-end', gap: '3px',
72 padding: '12px 20px 0', flexWrap: 'nowrap',
73 overflowX: 'auto'
74 });
75
76 (a.books || []).forEach(function (b) {
77 var spine = mk('div', '', {
78 width: sw + 'px', height: sh + 'px',
79 background: b.coverColor || '#334155',
80 borderRadius: '3px', flexShrink: '0', position: 'relative',
81 boxShadow: '-2px 2px 4px rgba(0,0,0,.4), inset 2px 0 4px rgba(255,255,255,.15)',
82 display: 'flex', alignItems: 'center', justifyContent: 'center',
83 overflow: 'hidden', cursor: 'default'
84 });
85 spine.title = b.title + (b.author ? ' \u2014 ' + b.author : '');
86
87 var titleDiv = tx('div', '', b.title, {
88 writingMode: 'vertical-rl',
89 textOrientation: 'mixed',
90 color: a.spineTextColor || '#ffffff',
91 fontSize: (a.spineFontSize || 11) + 'px',
92 fontWeight: '700', letterSpacing: '0.04em',
93 padding: '8px 4px',
94 maxHeight: (sh - 16) + 'px',
95 overflow: 'hidden', textOverflow: 'ellipsis',
96 lineHeight: '1.2', textShadow: '0 1px 2px rgba(0,0,0,.5)'
97 });
98
99 var dot = mk('div', '', {
100 position: 'absolute', top: '5px', right: '4px',
101 width: '6px', height: '6px', borderRadius: '50%',
102 background: b.status === 'read' ? '#4ade80' : b.status === 'reading' ? '#60a5fa' : '#fbbf24'
103 });
104
105 ap(spine, titleDiv, dot);
106 ap(bookRow, spine);
107 });
108
109 var plank = mk('div', '', {
110 height: '16px', background: a.shelfColor || '#8B5E3C',
111 boxShadow: '0 4px 8px ' + (a.shelfShadow || '#5c3d1e'),
112 margin: '0 8px', borderRadius: '2px'
113 });
114
115 ap(appEl, bookRow, plank);
116 }
117
118 // ── Cards layout ─────────────────────────────────────────────────
119 function buildCards(appEl, a) {
120 var grid = mk('div', '', {
121 display: 'grid',
122 gridTemplateColumns: 'repeat(auto-fill, minmax(130px, 1fr))',
123 gap: '16px', padding: '20px'
124 });
125
126 (a.books || []).forEach(function (b) {
127 var card = mk('div', '', {
128 background: a.cardBg || '#1e293b',
129 border: '1px solid ' + (a.cardBorderColor || '#334155'),
130 borderRadius: '10px', padding: '10px'
131 });
132
133 var coverWrap = mk('div', '', { position: 'relative', width: '100%', paddingTop: '140%', marginBottom: '10px' });
134 var cover = mk('div', '', {
135 position: 'absolute', inset: '0',
136 background: b.coverColor || '#334155',
137 borderRadius: '4px 8px 8px 4px',
138 display: 'flex', flexDirection: 'column',
139 alignItems: 'center', justifyContent: 'center',
140 padding: '12px', gap: '6px',
141 boxShadow: '-3px 3px 6px rgba(0,0,0,.4), inset 3px 0 6px rgba(255,255,255,.1)'
142 });
143 var coverTitle = tx('div', '', b.title, {
144 color: '#fff', fontSize: '10px', fontWeight: '700',
145 textAlign: 'center', lineHeight: '1.3',
146 textShadow: '0 1px 3px rgba(0,0,0,.5)', overflow: 'hidden'
147 });
148 var coverAuthor = tx('div', '', b.author || '', {
149 color: 'rgba(255,255,255,.7)', fontSize: '9px', textAlign: 'center'
150 });
151 ap(cover, coverTitle, coverAuthor);
152 ap(coverWrap, cover);
153
154 var meta = mk('div', '', { display: 'flex', flexDirection: 'column', gap: '6px' });
155 if (a.showRating) ap(meta, renderStars(b.rating, a.ratingColor, 12));
156 if (a.showGenre && b.genre) {
157 ap(meta, tx('span', '', b.genre, {
158 background: a.genreBg || '#1e293b', color: a.genreColor || '#94a3b8',
159 borderRadius: '4px', padding: '1px 6px', fontSize: '10px', fontWeight: '600',
160 display: 'inline-block'
161 }));
162 }
163 if (a.showStatus) ap(meta, statusBadge(b.status, a));
164 ap(card, coverWrap, meta);
165 ap(grid, card);
166 });
167 ap(appEl, grid);
168 }
169
170 // ── List layout ──────────────────────────────────────────────────
171 function buildList(appEl, a) {
172 var list = mk('div', '', { padding: '16px 20px', display: 'flex', flexDirection: 'column', gap: '8px' });
173 var fontSize = a.fontSize || 13;
174
175 (a.books || []).forEach(function (b) {
176 var row = mk('div', '', { display: 'flex', gap: '12px', alignItems: 'center' });
177 var spine = mk('div', '', {
178 width: '36px', height: '52px', background: b.coverColor || '#334155',
179 borderRadius: '2px 4px 4px 2px', flexShrink: '0',
180 boxShadow: 'inset 2px 0 4px rgba(255,255,255,.1)'
181 });
182 var meta = mk('div', '', { flex: '1', minWidth: '0' });
183
184 var titleEl = tx('div', 'bkbg-bsh-body', b.title, {
185 color: a.titleColor || '#f5deb3',
186 marginBottom: '2px'
187 });
188 ap(meta, titleEl);
189
190 if (a.showAuthor && b.author) {
191 ap(meta, tx('div', 'bkbg-bsh-body-author', b.author, {
192 color: a.authorColor || '#94a3b8', marginBottom: '4px'
193 }));
194 }
195
196 var tagRow = mk('div', '', { display: 'flex', alignItems: 'center', gap: '6px', flexWrap: 'wrap' });
197 if (a.showRating) ap(tagRow, renderStars(b.rating, a.ratingColor, 12));
198 if (a.showGenre && b.genre) {
199 ap(tagRow, tx('span', '', b.genre, {
200 background: a.genreBg || '#1e293b', color: a.genreColor || '#94a3b8',
201 borderRadius: '4px', padding: '1px 6px', fontSize: '10px', display: 'inline-block'
202 }));
203 }
204 if (a.showStatus) ap(tagRow, statusBadge(b.status, a));
205 if (a.showYear && b.year) {
206 ap(tagRow, tx('span', '', String(b.year), { color: a.authorColor || '#94a3b8', fontSize: '11px' }));
207 }
208 ap(meta, tagRow);
209 ap(row, spine, meta);
210 ap(list, row);
211 });
212 ap(appEl, list);
213 }
214
215 // ── Build block ──────────────────────────────────────────────────
216 function buildBlock(appEl) {
217 if (appEl.dataset.rendered) return;
218 appEl.dataset.rendered = '1';
219
220 var a;
221 try { a = JSON.parse(appEl.dataset.opts || '{}'); } catch (e) { a = {}; }
222
223 appEl.style.background = a.bgColor || '#1c1410';
224 appEl.style.borderRadius = (a.borderRadius || 14) + 'px';
225 appEl.style.overflow = 'hidden';
226 appEl.style.fontFamily = '-apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif';
227
228 // Header
229 if (a.showTitle && a.shelfTitle) {
230 var header = mk('div', '', { padding: '20px 20px 10px', background: a.headerBg || '#2d1f14' });
231 var titleEl = tx('h2', 'bkbg-bsh-title', a.shelfTitle, {
232 color: a.titleColor || '#f5deb3',
233 margin: '0', padding: '0'
234 });
235 ap(header, titleEl);
236 ap(appEl, header);
237 }
238
239 typoCssVarsForEl(a.typoTitle, '--bkbg-bsh-title-', appEl);
240 typoCssVarsForEl(a.typoBody, '--bkbg-bsh-body-', appEl);
241
242 if (a.layout === 'shelf' || !a.layout) {
243 buildShelf(appEl, a);
244 } else if (a.layout === 'cards') {
245 buildCards(appEl, a);
246 } else {
247 buildList(appEl, a);
248 }
249 }
250
251 function init() {
252 document.querySelectorAll('.bkbg-book-shelf-app').forEach(buildBlock);
253 }
254 if (document.readyState !== 'loading') { init(); } else { document.addEventListener('DOMContentLoaded', init); }
255 })();
256