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 / 2048-game / index.js

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

187 lines 9.8 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
14 /* ── lazy typography helpers ── */
15 function _tc() { return window.bkbgTypographyControl || null; }
16 Object.defineProperty(window, '__bkG48_tvf', { get: function () { delete window.__bkG48_tvf; return (window.__bkG48_tvf = window.bkbgTypoCssVars || function () { return {}; }); } });
17 function getTypoCssVars(a) {
18 var o = {};
19 Object.assign(o, window.__bkG48_tvf(a.titleTypo || {}, '--bkg48-tt-'));
20 Object.assign(o, window.__bkG48_tvf(a.subtitleTypo || {}, '--bkg48-st-'));
21 return o;
22 }
23
24 var TILE_COLORS = {
25 0: { bg: '#cdc1b4', text: '#776e65' },
26 2: { bg: '#eee4da', text: '#776e65' },
27 4: { bg: '#ede0c8', text: '#776e65' },
28 8: { bg: '#f2b179', text: '#f9f6f2' },
29 16: { bg: '#f59563', text: '#f9f6f2' },
30 32: { bg: '#f67c5f', text: '#f9f6f2' },
31 64: { bg: '#f65e3b', text: '#f9f6f2' },
32 128: { bg: '#edcf72', text: '#f9f6f2' },
33 256: { bg: '#edcc61', text: '#f9f6f2' },
34 512: { bg: '#edc850', text: '#f9f6f2' },
35 1024: { bg: '#edc53f', text: '#f9f6f2' },
36 2048: { bg: '#edc22e', text: '#f9f6f2' }
37 };
38
39 var DEMO = [
40 [2, 4, 8, 16 ],
41 [32, 64, 128, 256 ],
42 [0, 0, 512, 1024 ],
43 [0, 0, 0, 2048 ]
44 ];
45
46 function TileGrid(props) {
47 var a = props;
48 var sz = a.boardSize || 380;
49 var gap = a.gridGap || 10;
50 var rad = a.tileRadius || 8;
51 var cells = [];
52
53 for (var r = 0; r < 4; r++) {
54 for (var c = 0; c < 4; c++) {
55 var val = DEMO[r][c];
56 var tc = TILE_COLORS[val] || { bg: '#3c3a32', text: '#f9f6f2' };
57 var fs = val < 100 ? 36 : val < 1000 ? 26 : val < 10000 ? 20 : 16;
58 cells.push(el('div', {
59 key: r + '_' + c,
60 style: {
61 background: tc.bg,
62 color: tc.text,
63 borderRadius: rad,
64 display: 'flex', alignItems: 'center', justifyContent: 'center',
65 fontSize: fs, fontWeight: 700,
66 fontFamily: "'Helvetica Neue', Arial, sans-serif"
67 }
68 }, val > 0 ? val : null));
69 }
70 }
71
72 return el('div', { style: {
73 display: 'grid',
74 gridTemplateColumns: 'repeat(4,1fr)',
75 gap: gap,
76 background: a.gridBg || '#bbada0',
77 padding: gap,
78 borderRadius: rad + gap,
79 width: sz, height: sz, boxSizing: 'border-box',
80 userSelect: 'none'
81 } }, cells);
82 }
83
84 function ScoreBox(label, value, bg) {
85 return el('div', { style: { background: bg || '#bbada0', borderRadius: 6, padding: '6px 14px', textAlign: 'center', minWidth: 70 } },
86 el('div', { style: { fontSize: 11, fontWeight: 700, color: '#eee4da', letterSpacing: 1, textTransform: 'uppercase' } }, label),
87 el('div', { style: { fontSize: 22, fontWeight: 700, color: '#fff' } }, value)
88 );
89 }
90
91 function EditorPreview(props) {
92 var a = props.attributes;
93 var setAttributes = props.setAttributes;
94 var blockProps = useBlockProps((function () {
95 var s = getTypoCssVars(a);
96 s.background = a.sectionBg || '#fef9ee';
97 s.padding = '28px 20px';
98 return { style: s };
99 })());
100
101 return el(Fragment, null,
102 el(InspectorControls, null,
103 el(PanelBody, { title: __('Content', 'blockenberg'), initialOpen: true },
104 ),
105 el(PanelBody, { title: __('Board Settings', 'blockenberg'), initialOpen: false },
106 el(RangeControl, {
107 label: __('Board Size (px)', 'blockenberg'), value: a.boardSize, min: 260, max: 560,
108 onChange: function (v) { setAttributes({ boardSize: v }); }
109 }),
110 el(RangeControl, {
111 label: __('Tile Radius (px)', 'blockenberg'), value: a.tileRadius, min: 0, max: 24,
112 onChange: function (v) { setAttributes({ tileRadius: v }); }
113 }),
114 el(RangeControl, {
115 label: __('Grid Gap (px)', 'blockenberg'), value: a.gridGap, min: 4, max: 20,
116 onChange: function (v) { setAttributes({ gridGap: v }); }
117 }),
118 el(ToggleControl, { __nextHasNoMarginBottom: true, label: __('Show Score', 'blockenberg'), checked: a.showScore, onChange: function (v) { setAttributes({ showScore: v }); } }),
119 el(ToggleControl, { __nextHasNoMarginBottom: true, label: __('Show Best Score', 'blockenberg'), checked: a.showBestScore, onChange: function (v) { setAttributes({ showBestScore: v }); } }),
120 el(ToggleControl, { __nextHasNoMarginBottom: true, label: __('Animate Tiles', 'blockenberg'), checked: a.animateTiles, onChange: function (v) { setAttributes({ animateTiles: v }); } })
121 ),
122
123 el( PanelBody, { title: __( 'Typography', 'blockenberg' ), initialOpen: false },
124 _tc() && el(_tc(), { label: __('Title', 'blockenberg'), value: a.titleTypo || {}, onChange: function (v) { setAttributes({ titleTypo: v }); } }),
125 _tc() && el(_tc(), { label: __('Subtitle', 'blockenberg'), value: a.subtitleTypo || {}, onChange: function (v) { setAttributes({ subtitleTypo: v }); } })
126 ),
127 el(PanelColorSettings, {
128 title: __('Colors', 'blockenberg'), initialOpen: false,
129 colorSettings: [
130 { label: __('Grid Background', 'blockenberg'), value: a.gridBg, onChange: function (v) { setAttributes({ gridBg: v || '#bbada0' }); } },
131 { label: __('Empty Tile', 'blockenberg'), value: a.tileBg, onChange: function (v) { setAttributes({ tileBg: v || '#cdc1b4' }); } },
132 { label: __('Section Background', 'blockenberg'), value: a.sectionBg, onChange: function (v) { setAttributes({ sectionBg: v || '#fef9ee' }); } },
133 { label: __('Title / Text', 'blockenberg'), value: a.titleColor, onChange: function (v) { setAttributes({ titleColor: v || '#776e65' }); } },
134 { label: __('Score Header', 'blockenberg'), value: a.scoreHeaderBg,onChange: function (v) { setAttributes({ scoreHeaderBg: v || '#bbada0' }); } },
135 { label: __('New Game Button', 'blockenberg'), value: a.newGameBg, onChange: function (v) { setAttributes({ newGameBg: v || '#8f7a66' }); } }
136 ]
137 })
138 ),
139 el('div', blockProps,
140 // Header row
141 el('div', { style: { display: 'flex', alignItems: 'center', justifyContent: 'space-between', marginBottom: 12, flexWrap: 'wrap', gap: 8 } },
142 el('div', null,
143 el(RichText, {
144 tagName: 'h2', className: 'bkbg-g48-title', value: a.title,
145 onChange: function (v) { setAttributes({ title: v }); },
146 placeholder: '2048',
147 style: { color: a.titleColor, margin: 0 }
148 }),
149 el(RichText, {
150 tagName: 'p', className: 'bkbg-g48-subtitle', value: a.subtitle,
151 onChange: function (v) { setAttributes({ subtitle: v }); },
152 placeholder: 'Combine tiles to reach 2048!',
153 style: { color: a.titleColor, margin: '2px 0 0', opacity: 0.75 }
154 })
155 ),
156 el('div', { style: { display: 'flex', gap: 8, alignItems: 'center', flexWrap: 'wrap' } },
157 a.showScore && ScoreBox('Score', '0', a.scoreHeaderBg),
158 a.showBestScore && ScoreBox('Best', '0', a.scoreHeaderBg),
159 el('button', { style: { background: a.newGameBg, color: '#fff', border: 'none', borderRadius: 6, padding: '8px 14px', fontWeight: 700, fontSize: 14, cursor: 'pointer' } }, 'New Game')
160 )
161 ),
162 // Board preview
163 el('div', { style: { display: 'flex', justifyContent: 'center' } },
164 el(TileGrid, a)
165 ),
166 el('p', { style: { textAlign: 'center', fontSize: 13, color: a.titleColor, opacity: 0.6, marginTop: 10 } },
167 '← → ↑ ↓ arrow keys or swipe to play'
168 )
169 )
170 );
171 }
172
173 registerBlockType('blockenberg/game-2048', {
174 edit: EditorPreview,
175 save: function (props) {
176 var a = props.attributes;
177 var sv = getTypoCssVars(a);
178 return el('div', useBlockProps.save(),
179 el('div', { className: 'bkbg-g48-app', 'data-opts': JSON.stringify(a), style: sv },
180 el(RichText.Content, { tagName: 'h2', className: 'bkbg-g48-title', value: a.title }),
181 el(RichText.Content, { tagName: 'p', className: 'bkbg-g48-subtitle', value: a.subtitle })
182 )
183 );
184 }
185 });
186 }() );
187