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 / word-scramble / index.js

index.js in Blockenberg — 600+ Advanced Gutenberg Blocks & AI Agent for WordPress Block Editor 2.0.7, at blocks/word-scramble/index.js

232 lines 12.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 Fragment = wp.element.Fragment;
4 var registerBlockType = wp.blocks.registerBlockType;
5 var __ = wp.i18n.__;
6 var InspectorControls = wp.blockEditor.InspectorControls;
7 var PanelColorSettings = wp.blockEditor.PanelColorSettings;
8 var useBlockProps = wp.blockEditor.useBlockProps;
9 var RichText = wp.blockEditor.RichText;
10 var PanelBody = wp.components.PanelBody;
11 var RangeControl = wp.components.RangeControl;
12 var ToggleControl = wp.components.ToggleControl;
13 var SelectControl = wp.components.SelectControl;
14
15 /* ── Typography helpers (lazy) ───────────────────────────────── */
16 var _tc, _tvf;
17 Object.defineProperty(window, '__bkwsc_tc', { get: function () { return _tc || (_tc = window.bkbgTypographyControl); } });
18 Object.defineProperty(window, '__bkwsc_tvf', { get: function () { return _tvf || (_tvf = window.bkbgTypoCssVars); } });
19 function getTypoControl(label, typoObj, setAttributes, attrName) {
20 var fn = window.__bkwsc_tc;
21 return fn ? fn({ label: label, value: typoObj || {}, onChange: function (v) { var o = {}; o[attrName] = v; setAttributes(o); } }) : null;
22 }
23 function getTypoCssVars(a) {
24 var fn = window.__bkwsc_tvf;
25 var s = {};
26 if (fn) {
27 Object.assign(s, fn(a.titleTypo || {}, '--bkwsc-tt-'));
28 Object.assign(s, fn(a.subtitleTypo || {}, '--bkwsc-st-'));
29 }
30 return s;
31 }
32
33 var CATEGORIES = {
34 animals: 'Animals',
35 countries: 'Countries',
36 foods: 'Foods',
37 tech: 'Technology'
38 };
39
40 var DIFFICULTIES = { easy: 'Easy (4–5 letters)', medium: 'Medium (6–8)', hard: 'Hard (9+)' };
41
42 function sampleWords(cat, diff) {
43 var all = {
44 animals: { easy: ['BEAR','WOLF','FROG','DUCK','LION'], medium: ['PARROT','JAGUAR','DONKEY'], hard: ['ALLIGATOR','CHAMELEON'] },
45 countries: { easy: ['PERU','CUBA','IRAN','IRAQ','MALI'], medium: ['FRANCE','BRAZIL','CANADA'], hard: ['AUSTRALIA','INDONESIA'] },
46 foods: { easy: ['RICE','BEEF','CORN','MILK','CAKE'], medium: ['POTATO','CARROT','TOMATO'], hard: ['CROISSANT','STRAWBERRY'] },
47 tech: { easy: ['CODE','DATA','WIFI','BYTE','CHIP'], medium: ['PYTHON','DOCKER','GITHUB'], hard: ['ALGORITHM','JAVASCRIPT'] }
48 };
49 var pool = (all[cat] || all['animals'])[diff] || all['animals']['medium'];
50 return pool[0];
51 }
52
53 function scramble(word) {
54 var arr = word.split('');
55 for (var i = arr.length - 1; i > 0; i--) {
56 var j = Math.floor(Math.random() * (i + 1));
57 var tmp = arr[i]; arr[i] = arr[j]; arr[j] = tmp;
58 }
59 var s = arr.join('');
60 return s === word ? scramble(word) : s;
61 }
62
63 function EditorPreview(props) {
64 var a = props.attributes;
65 var setAttributes = props.setAttributes;
66 var blockProps = useBlockProps((function () {
67 var s = getTypoCssVars(a);
68 s.background = a.sectionBg;
69 s.borderRadius = 16;
70 s.padding = '28px 20px';
71 return { style: s };
72 })());
73
74 var word = sampleWords(a.defaultCategory, a.defaultDifficulty);
75 var scrambled = scramble(word);
76
77 return el(Fragment, null,
78 el(InspectorControls, null,
79 el(PanelBody, { title: __('Content', 'blockenberg'), initialOpen: true },
80 ),
81 el(PanelBody, { title: __('Game Settings', 'blockenberg'), initialOpen: false },
82 el(SelectControl, {
83 label: __('Default Category', 'blockenberg'),
84 value: a.defaultCategory,
85 options: Object.keys(CATEGORIES).map(function (k) { return { label: CATEGORIES[k], value: k }; }),
86 onChange: function (v) { setAttributes({ defaultCategory: v }); }
87 }),
88 el(SelectControl, {
89 label: __('Default Difficulty', 'blockenberg'),
90 value: a.defaultDifficulty,
91 options: Object.keys(DIFFICULTIES).map(function (k) { return { label: DIFFICULTIES[k], value: k }; }),
92 onChange: function (v) { setAttributes({ defaultDifficulty: v }); }
93 }),
94 el(RangeControl, {
95 label: __('Time Limit (seconds)', 'blockenberg'),
96 value: a.timeLimit, min: 20, max: 300,
97 onChange: function (v) { setAttributes({ timeLimit: v }); }
98 }),
99 el(RangeControl, {
100 label: __('Hints Allowed', 'blockenberg'),
101 value: a.hintsAllowed, min: 0, max: 10,
102 onChange: function (v) { setAttributes({ hintsAllowed: v }); }
103 }),
104 el(ToggleControl, {
105 __nextHasNoMarginBottom: true,
106 label: __('Show Timer', 'blockenberg'),
107 checked: a.showTimer,
108 onChange: function (v) { setAttributes({ showTimer: v }); }
109 }),
110 el(ToggleControl, {
111 __nextHasNoMarginBottom: true,
112 label: __('Show Score', 'blockenberg'),
113 checked: a.showScore,
114 onChange: function (v) { setAttributes({ showScore: v }); }
115 }),
116 el(ToggleControl, {
117 __nextHasNoMarginBottom: true,
118 label: __('Show Streak', 'blockenberg'),
119 checked: a.showStreak,
120 onChange: function (v) { setAttributes({ showStreak: v }); }
121 })
122 ),
123
124 el( PanelBody, { title: __( 'Typography', 'blockenberg' ), initialOpen: false },
125 getTypoControl( 'Title', a.titleTypo, setAttributes, 'titleTypo' ),
126 getTypoControl( 'Subtitle', a.subtitleTypo, setAttributes, 'subtitleTypo' )
127 ),
128 el(PanelColorSettings, {
129 title: __('Colors', 'blockenberg'),
130 initialOpen: false,
131 colorSettings: [
132 { label: __('Accent Color', 'blockenberg'), value: a.accentColor, onChange: function (v) { setAttributes({ accentColor: v || '#f59e0b' }); } },
133 { label: __('Correct Color', 'blockenberg'), value: a.correctColor, onChange: function (v) { setAttributes({ correctColor: v || '#22c55e' }); } },
134 { label: __('Wrong Color', 'blockenberg'), value: a.wrongColor, onChange: function (v) { setAttributes({ wrongColor: v || '#ef4444' }); } },
135 { label: __('Section Background', 'blockenberg'), value: a.sectionBg, onChange: function (v) { setAttributes({ sectionBg: v || '#fffbeb' }); } },
136 { label: __('Card Background', 'blockenberg'), value: a.cardBg, onChange: function (v) { setAttributes({ cardBg: v || '#ffffff' }); } },
137 { label: __('Title Color', 'blockenberg'), value: a.titleColor, onChange: function (v) { setAttributes({ titleColor: v || '#92400e' }); } }
138 ]
139 })
140 ),
141 el('div', blockProps,
142 el(RichText, {
143 tagName: 'h3', className: 'bkbg-wsc-title',
144 value: a.title,
145 onChange: function (v) { setAttributes({ title: v }); },
146 placeholder: __('Title', 'blockenberg'),
147 style: { color: a.titleColor, margin: '0 0 4px', textAlign: 'center' }
148 }),
149 el(RichText, {
150 tagName: 'p', className: 'bkbg-wsc-subtitle',
151 value: a.subtitle,
152 onChange: function (v) { setAttributes({ subtitle: v }); },
153 placeholder: __('Subtitle', 'blockenberg'),
154 style: { color: a.titleColor + 'bb', textAlign: 'center', margin: '0 0 16px' }
155 }),
156 // Stats bar
157 el('div', { style: { display: 'flex', justifyContent: 'center', gap: 14, marginBottom: 14, flexWrap: 'wrap' } },
158 a.showScore && el('div', {
159 style: { background: a.cardBg, borderRadius: 10, padding: '8px 18px', textAlign: 'center', borderTop: '4px solid ' + a.accentColor }
160 },
161 el('div', { style: { fontSize: 22, fontWeight: 900, color: a.accentColor } }, '0'),
162 el('div', { style: { fontSize: 12, color: a.titleColor } }, 'Score')
163 ),
164 a.showStreak && el('div', {
165 style: { background: a.cardBg, borderRadius: 10, padding: '8px 18px', textAlign: 'center', borderTop: '4px solid #f97316' }
166 },
167 el('div', { style: { fontSize: 22, fontWeight: 900, color: '#f97316' } }, '🔥 0'),
168 el('div', { style: { fontSize: 12, color: a.titleColor } }, 'Streak')
169 ),
170 a.showTimer && el('div', {
171 style: { background: a.cardBg, borderRadius: 10, padding: '8px 18px', textAlign: 'center', borderTop: '4px solid #6366f1' }
172 },
173 el('div', { style: { fontSize: 22, fontWeight: 900, color: '#6366f1' } }, a.timeLimit + 's'),
174 el('div', { style: { fontSize: 12, color: a.titleColor } }, 'Time')
175 )
176 ),
177 // Scrambled word display
178 el('div', {
179 style: {
180 background: a.cardBg, borderRadius: 14, padding: '20px 24px', marginBottom: 14,
181 boxShadow: '0 2px 12px rgba(0,0,0,0.06)'
182 }
183 },
184 el('div', { style: { fontSize: 11, textTransform: 'uppercase', letterSpacing: 2, color: a.titleColor + '88', marginBottom: 8 } }, CATEGORIES[a.defaultCategory] || 'Category'),
185 el('div', { style: { display: 'flex', justifyContent: 'center', gap: 8, flexWrap: 'wrap', marginBottom: 12 } },
186 scrambled.split('').map(function (ch, i) {
187 return el('div', {
188 key: i,
189 style: {
190 width: 38, height: 44, borderRadius: 8, border: '2px solid ' + a.accentColor,
191 display: 'flex', alignItems: 'center', justifyContent: 'center',
192 fontSize: 22, fontWeight: 900, color: a.accentColor, background: a.sectionBg
193 }
194 }, ch);
195 })
196 ),
197 el('input', {
198 type: 'text', readOnly: true, placeholder: 'Type your answer…',
199 style: {
200 width: '100%', padding: '10px 14px', borderRadius: 8,
201 border: '2px solid #e5e7eb', fontSize: 15, textAlign: 'center',
202 fontFamily: 'monospace', boxSizing: 'border-box'
203 }
204 })
205 ),
206 // Buttons
207 el('div', { style: { display: 'flex', gap: 10, justifyContent: 'center', flexWrap: 'wrap' } },
208 el('button', {
209 style: { background: a.accentColor, color: '#fff', border: 'none', borderRadius: 8, padding: '10px 24px', fontWeight: 700, cursor: 'default' }
210 }, 'Check'),
211 el('button', {
212 style: { background: 'transparent', color: a.accentColor, border: '2px solid ' + a.accentColor, borderRadius: 8, padding: '10px 18px', fontWeight: 700, cursor: 'default' }
213 }, '💡 Hint (' + a.hintsAllowed + ')')
214 )
215 )
216 );
217 }
218
219 registerBlockType('blockenberg/word-scramble', {
220 edit: EditorPreview,
221 save: function (props) {
222 var a = props.attributes;
223 return el('div', useBlockProps.save({ style: getTypoCssVars(a) }),
224 el('div', { className: 'bkbg-wsc-app', 'data-opts': JSON.stringify(a) },
225 el(RichText.Content, { tagName: 'h3', className: 'bkbg-wsc-title', value: a.title }),
226 el(RichText.Content, { tagName: 'p', className: 'bkbg-wsc-subtitle', value: a.subtitle })
227 )
228 );
229 }
230 });
231 }() );
232