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

index.js in Blockenberg — 600+ Advanced Gutenberg Blocks & AI Agent for WordPress Block Editor 2.0.10, at blocks/flashcard/index.js

288 lines 16.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 useState = wp.element.useState;
4 var Fragment = wp.element.Fragment;
5 var registerBlockType = wp.blocks.registerBlockType;
6 var __ = wp.i18n.__;
7 var InspectorControls = wp.blockEditor.InspectorControls;
8 var PanelColorSettings = wp.blockEditor.PanelColorSettings;
9 var useBlockProps = wp.blockEditor.useBlockProps;
10 var PanelBody = wp.components.PanelBody;
11 var RangeControl = wp.components.RangeControl;
12 var SelectControl = wp.components.SelectControl;
13 var TextControl = wp.components.TextControl;
14 var ToggleControl = wp.components.ToggleControl;
15 var Button = wp.components.Button;
16
17 var _flTC, _flTV;
18 function _tc() { return _flTC || (_flTC = window.bkbgTypographyControl); }
19 function _tv() { return _flTV || (_flTV = window.bkbgTypoCssVars); }
20
21 var DEFAULT_CARDS = [
22 { id: '1', front: 'What is the capital of France?', back: 'Paris', known: false },
23 { id: '2', front: 'What is 7 × 8?', back: '56', known: false },
24 { id: '3', front: 'Who wrote Romeo and Juliet?', back: 'William Shakespeare', known: false },
25 { id: '4', front: 'What is H₂O?', back: 'Water', known: false },
26 { id: '5', front: 'What year did WWII end?', back: '1945', known: false }
27 ];
28
29 registerBlockType('blockenberg/flashcard', {
30 edit: function (props) {
31 var a = props.attributes;
32 var setAttributes = props.setAttributes;
33 var keyboardShortcutsEnabled = a.enableKeyboardShortcuts !== false;
34 var wrapStyle = Object.assign({},
35 _tv()(a.typoTitle, '--bkbg-flash-tt-'),
36 _tv()(a.typoSubtitle, '--bkbg-flash-ts-'),
37 _tv()(a.typoCard, '--bkbg-flash-tc-')
38 );
39 var blockProps = useBlockProps({ className: 'bkbg-fc-editor-wrap', style: wrapStyle });
40
41 var cards;
42 try { cards = JSON.parse(a.cards); } catch (e) { cards = DEFAULT_CARDS; }
43
44 var containerStyle = {
45 background: a.sectionBg,
46 borderRadius: '12px',
47 padding: '28px',
48 maxWidth: a.contentMaxWidth + 'px',
49 margin: '0 auto'
50 };
51
52 var cardPreviewStyle = {
53 background: a.cardFrontBg,
54 borderRadius: '12px',
55 height: a.cardHeight + 'px',
56 display: 'flex',
57 alignItems: 'center',
58 justifyContent: 'center',
59 textAlign: 'center',
60 padding: '24px',
61 boxShadow: '0 8px 32px rgba(99,102,241,0.15)',
62 color: a.labelColor,
63 cursor: 'pointer',
64 position: 'relative'
65 };
66
67 function addCard() {
68 var newCards = cards.concat([{ id: Date.now().toString(), front: 'New question', back: 'Answer', known: false }]);
69 setAttributes({ cards: JSON.stringify(newCards) });
70 }
71
72 function removeCard(id) {
73 setAttributes({ cards: JSON.stringify(cards.filter(function (c) { return c.id !== id; })) });
74 }
75
76 function updateCard(id, field, value) {
77 var updated = cards.map(function (c) {
78 if (c.id !== id) return c;
79 var n = {}; Object.keys(c).forEach(function (k) { n[k] = c[k]; }); n[field] = value; return n;
80 });
81 setAttributes({ cards: JSON.stringify(updated) });
82 }
83
84 return el(
85 Fragment,
86 null,
87 el(
88 InspectorControls,
89 null,
90 el(
91 PanelBody,
92 { title: __('Content', 'blockenberg'), initialOpen: true },
93 el(TextControl, {
94 label: __('Title', 'blockenberg'),
95 value: a.title,
96 onChange: function (v) { setAttributes({ title: v }); }
97 }),
98 el(TextControl, {
99 label: __('Subtitle', 'blockenberg'),
100 value: a.subtitle,
101 onChange: function (v) { setAttributes({ subtitle: v }); }
102 }),
103 el(ToggleControl, {
104 label: __('Show Title', 'blockenberg'),
105 checked: a.showTitle,
106 onChange: function (v) { setAttributes({ showTitle: v }); },
107 __nextHasNoMarginBottom: true
108 }),
109 el(ToggleControl, {
110 label: __('Show Subtitle', 'blockenberg'),
111 checked: a.showSubtitle,
112 onChange: function (v) { setAttributes({ showSubtitle: v }); },
113 __nextHasNoMarginBottom: true
114 })
115 ),
116 el(
117 PanelBody,
118 { title: __('Cards', 'blockenberg'), initialOpen: true },
119 cards.map(function (card) {
120 return el(
121 'div',
122 { key: card.id, style: { background: '#f9f9f9', borderRadius: '8px', padding: '12px', marginBottom: '10px', border: '1px solid #e5e7eb' } },
123 el(TextControl, {
124 label: __('Front', 'blockenberg'),
125 value: card.front,
126 onChange: function (v) { updateCard(card.id, 'front', v); }
127 }),
128 el(TextControl, {
129 label: __('Back', 'blockenberg'),
130 value: card.back,
131 onChange: function (v) { updateCard(card.id, 'back', v); }
132 }),
133 el(
134 'button',
135 {
136 style: { background: '#fee2e2', color: '#991b1b', border: 'none', borderRadius: '4px', padding: '4px 10px', cursor: 'pointer', fontSize: '12px' },
137 onClick: function () { removeCard(card.id); }
138 },
139 __('Remove', 'blockenberg')
140 )
141 );
142 }),
143 el(
144 'button',
145 {
146 style: { background: a.accentColor, color: '#fff', border: 'none', borderRadius: '6px', padding: '8px 16px', cursor: 'pointer', width: '100%', fontWeight: '600' },
147 onClick: addCard
148 },
149 __('+ Add Card', 'blockenberg')
150 )
151 ),
152 el(
153 PanelBody,
154 { title: __('Options', 'blockenberg'), initialOpen: false },
155 el(ToggleControl, {
156 label: __('Show Progress Bar', 'blockenberg'),
157 checked: a.showProgress,
158 onChange: function (v) { setAttributes({ showProgress: v }); },
159 __nextHasNoMarginBottom: true
160 }),
161 el(ToggleControl, {
162 label: __('Show Shuffle Button', 'blockenberg'),
163 checked: a.showShuffleBtn,
164 onChange: function (v) { setAttributes({ showShuffleBtn: v }); },
165 __nextHasNoMarginBottom: true
166 }),
167 el(ToggleControl, {
168 label: __('Show "Mark Known" Button', 'blockenberg'),
169 checked: a.showKnownBtn,
170 onChange: function (v) { setAttributes({ showKnownBtn: v }); },
171 __nextHasNoMarginBottom: true
172 }),
173 el(ToggleControl, {
174 label: __('Enable keyboard shortcuts', 'blockenberg'),
175 checked: keyboardShortcutsEnabled,
176 onChange: function (v) { setAttributes({ enableKeyboardShortcuts: v }); },
177 __nextHasNoMarginBottom: true
178 }),
179 el(ToggleControl, {
180 label: __('Show Keyboard Hint', 'blockenberg'),
181 checked: a.showKeyboardHint,
182 onChange: function (v) { setAttributes({ showKeyboardHint: v }); },
183 __nextHasNoMarginBottom: true
184 }),
185 el(RangeControl, {
186 label: __('Card Height (px)', 'blockenberg'),
187 value: a.cardHeight,
188 min: 120,
189 max: 500,
190 onChange: function (v) { setAttributes({ cardHeight: v }); }
191 })
192 ),
193 el(
194 PanelBody,
195 { title: __('Typography', 'blockenberg'), initialOpen: false },
196 _tc() && _tc()({ label: __('Title', 'blockenberg'), typo: a.typoTitle, onChange: function (v) { setAttributes({ typoTitle: v }); } }),
197 _tc() && _tc()({ label: __('Subtitle', 'blockenberg'), typo: a.typoSubtitle, onChange: function (v) { setAttributes({ typoSubtitle: v }); } }),
198 _tc() && _tc()({ label: __('Card Text', 'blockenberg'), typo: a.typoCard, onChange: function (v) { setAttributes({ typoCard: v }); } })
199 ),
200 el(
201 PanelBody,
202 { title: __('Appearance', 'blockenberg'), initialOpen: false },
203 el(RangeControl, {
204 label: __('Max Width (px)', 'blockenberg'),
205 value: a.contentMaxWidth,
206 min: 320,
207 max: 1200,
208 onChange: function (v) { setAttributes({ contentMaxWidth: v }); }
209 })
210 ),
211 el(
212 PanelColorSettings,
213 {
214 title: __('Colors', 'blockenberg'),
215 initialOpen: false,
216 colorSettings: [
217 { value: a.accentColor, onChange: function (v) { setAttributes({ accentColor: v || '#6366f1' }); }, label: __('Accent Color', 'blockenberg') },
218 { value: a.cardFrontBg, onChange: function (v) { setAttributes({ cardFrontBg: v || '#ffffff' }); }, label: __('Card Front Background', 'blockenberg') },
219 { value: a.cardBackBg, onChange: function (v) { setAttributes({ cardBackBg: v || '#4f46e5' }); }, label: __('Card Back Background', 'blockenberg') },
220 { value: a.cardBackColor, onChange: function (v) { setAttributes({ cardBackColor: v || '#ffffff' }); }, label: __('Card Back Text', 'blockenberg') },
221 { value: a.knownColor, onChange: function (v) { setAttributes({ knownColor: v || '#22c55e' }); }, label: __('Known Color', 'blockenberg') },
222 { value: a.sectionBg, onChange: function (v) { setAttributes({ sectionBg: v || '#f5f3ff' }); }, label: __('Section Background', 'blockenberg') },
223 { value: a.cardBg, onChange: function (v) { setAttributes({ cardBg: v || '#ffffff' }); }, label: __('Controls Background', 'blockenberg') },
224 { value: a.titleColor, onChange: function (v) { setAttributes({ titleColor: v || '#3730a3' }); }, label: __('Title Color', 'blockenberg') },
225 { value: a.subtitleColor, onChange: function (v) { setAttributes({ subtitleColor: v || '#6b7280' }); }, label: __('Subtitle Color', 'blockenberg') },
226 { value: a.labelColor, onChange: function (v) { setAttributes({ labelColor: v || '#374151' }); }, label: __('Label Color', 'blockenberg') }
227 ]
228 }
229 )
230 ),
231 el(
232 'div',
233 blockProps,
234 el(
235 'div',
236 { style: containerStyle },
237 a.showTitle && el('div', {
238 className: 'bkbg-fc-title',
239 style: { color: a.titleColor, marginBottom: '6px' }
240 }, a.title),
241 a.showSubtitle && el('div', {
242 className: 'bkbg-fc-subtitle',
243 style: { color: a.subtitleColor, marginBottom: '20px' }
244 }, a.subtitle),
245 a.showProgress && el('div', {
246 style: { marginBottom: '16px' }
247 },
248 el('div', { style: { display: 'flex', justifyContent: 'space-between', fontSize: '13px', color: a.labelColor, marginBottom: '6px' } },
249 el('span', null, __('Progress', 'blockenberg')),
250 el('span', null, '0 / ' + cards.length + ' known')
251 ),
252 el('div', { style: { height: '8px', background: '#e5e7eb', borderRadius: '4px' } },
253 el('div', { style: { height: '100%', width: '0%', background: a.accentColor, borderRadius: '4px' } })
254 )
255 ),
256 el('div', { className: 'bkbg-fc-front', style: cardPreviewStyle },
257 el('span', null, cards[0] ? cards[0].front : 'No cards yet')
258 ),
259 el('div', { style: { display: 'flex', justifyContent: 'center', gap: '12px', marginTop: '16px', flexWrap: 'wrap' } },
260 el('button', { style: { background: '#e5e7eb', color: '#374151', border: 'none', borderRadius: '8px', padding: '10px 20px', cursor: 'pointer', fontSize: '20px' } }, '←'),
261 a.showKnownBtn && el('button', { style: { background: a.knownColor, color: '#fff', border: 'none', borderRadius: '8px', padding: '10px 18px', cursor: 'pointer', fontWeight: '600' } }, '✓ Know it'),
262 el('button', { style: { background: '#e5e7eb', color: '#374151', border: 'none', borderRadius: '8px', padding: '10px 20px', cursor: 'pointer', fontSize: '20px' } }, '→')
263 ),
264 el('div', { style: { textAlign: 'center', marginTop: '10px', display: 'flex', gap: '10px', justifyContent: 'center', flexWrap: 'wrap' } },
265 el('span', { style: { color: a.subtitleColor, fontSize: '13px' } }, '1 / ' + cards.length),
266 a.showShuffleBtn && el('button', { style: { background: 'transparent', border: '1px solid ' + a.accentColor, color: a.accentColor, borderRadius: '6px', padding: '4px 12px', cursor: 'pointer', fontSize: '12px' } }, '⇌ Shuffle'),
267 el('button', { style: { background: 'transparent', border: '1px solid #e5e7eb', color: a.subtitleColor, borderRadius: '6px', padding: '4px 12px', cursor: 'pointer', fontSize: '12px' } }, '↺ Reset')
268 ),
269 keyboardShortcutsEnabled && a.showKeyboardHint && el('div', { style: { textAlign: 'center', marginTop: '12px', color: a.subtitleColor, fontSize: '12px' } },
270 '← → Arrow keys to navigate • Space to flip'
271 )
272 )
273 )
274 );
275 },
276 save: function (props) {
277 var a = props.attributes;
278 var blockProps = wp.blockEditor.useBlockProps.save();
279 return el('div', blockProps,
280 el('div', {
281 className: 'bkbg-fc-app',
282 'data-opts': JSON.stringify(a)
283 })
284 );
285 }
286 });
287 }() );
288