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

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

166 lines 10.4 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 var _tc; function getTypoControl() { return _tc || (_tc = window.bkbgTypographyControl); }
15 var _tv; function getTypoCssVars() { return _tv || (_tv = window.bkbgTypoCssVars); }
16
17 function EditorPreview(props) {
18 var a = props.attributes;
19 var setAttributes = props.setAttributes;
20 var TC = getTypoControl();
21 var blockProps = useBlockProps((function () {
22 var _tvFn = getTypoCssVars();
23 var s = { background: a.sectionBg, borderRadius: 16, padding: '28px 20px', textAlign: 'center' };
24 if (_tvFn) {
25 Object.assign(s, _tvFn(a.titleTypo || {}, '--bksnk-tt-'));
26 Object.assign(s, _tvFn(a.subtitleTypo || {}, '--bksnk-st-'));
27 }
28 return { style: s };
29 })());
30
31 var sz = Math.min(a.canvasSize || 400, 400);
32 var gs = a.gridSize || 20;
33 var cell = sz / gs;
34
35 // Demo snake: a small snake in the center
36 var demoSnake = [[10,10],[9,10],[8,10],[7,10]];
37 var demoFood = [14, 7];
38
39 return el(Fragment, null,
40 el(InspectorControls, null,
41 el(PanelBody, { title: __('Content', 'blockenberg'), initialOpen: true },
42 ),
43 el(PanelBody, { title: __('Game Settings', 'blockenberg'), initialOpen: false },
44 el(RangeControl, {
45 label: __('Grid Size (cells)', 'blockenberg'),
46 value: a.gridSize, min: 10, max: 30,
47 onChange: function (v) { setAttributes({ gridSize: v }); }
48 }),
49 el(RangeControl, {
50 label: __('Canvas Size (px)', 'blockenberg'),
51 value: a.canvasSize, min: 280, max: 600,
52 onChange: function (v) { setAttributes({ canvasSize: v }); }
53 }),
54 el(SelectControl, {
55 label: __('Default Speed', 'blockenberg'),
56 value: a.defaultSpeed,
57 options: [
58 { label: 'Slow', value: 'slow' },
59 { label: 'Medium', value: 'medium' },
60 { label: 'Fast', value: 'fast' },
61 { label: 'Insane', value: 'insane' }
62 ],
63 onChange: function (v) { setAttributes({ defaultSpeed: v }); }
64 }),
65 el(ToggleControl, { __nextHasNoMarginBottom: true, label: __('Wall Kills Snake', 'blockenberg'), checked: a.wallsKill, onChange: function (v) { setAttributes({ wallsKill: v }); } }),
66 el(ToggleControl, { __nextHasNoMarginBottom: true, label: __('Show High Score', 'blockenberg'), checked: a.showHighScore, onChange: function (v) { setAttributes({ showHighScore: v }); } }),
67 el(ToggleControl, { __nextHasNoMarginBottom: true, label: __('Show Touch Controls', 'blockenberg'), checked: a.showControls, onChange: function (v) { setAttributes({ showControls: v }); } })
68 ),
69
70 el( PanelBody, { title: __( 'Typography', 'blockenberg' ), initialOpen: false },
71 TC && el(TC, {
72 label: __('Title', 'blockenberg'),
73 value: a.titleTypo || {},
74 onChange: function (v) { setAttributes({ titleTypo: v }); }
75 }),
76 TC && el(TC, {
77 label: __('Subtitle', 'blockenberg'),
78 value: a.subtitleTypo || {},
79 onChange: function (v) { setAttributes({ subtitleTypo: v }); }
80 })
81 ),
82 el(PanelColorSettings, {
83 title: __('Colors', 'blockenberg'), initialOpen: false,
84 colorSettings: [
85 { label: __('Snake Body', 'blockenberg'), value: a.snakeColor, onChange: function (v) { setAttributes({ snakeColor: v || '#22c55e' }); } },
86 { label: __('Snake Head', 'blockenberg'), value: a.snakeHeadColor, onChange: function (v) { setAttributes({ snakeHeadColor: v || '#16a34a' }); } },
87 { label: __('Food', 'blockenberg'), value: a.foodColor, onChange: function (v) { setAttributes({ foodColor: v || '#ef4444' }); } },
88 { label: __('Grid Lines', 'blockenberg'), value: a.gridColor, onChange: function (v) { setAttributes({ gridColor: v || '#f3f4f6' }); } },
89 { label: __('Board Background', 'blockenberg'), value: a.boardBg, onChange: function (v) { setAttributes({ boardBg: v || '#ffffff' }); } },
90 { label: __('Section Background', 'blockenberg'), value: a.sectionBg, onChange: function (v) { setAttributes({ sectionBg: v || '#f0fdf4' }); } },
91 { label: __('Accent Color', 'blockenberg'), value: a.accentColor, onChange: function (v) { setAttributes({ accentColor: v || '#22c55e' }); } },
92 { label: __('Title Color', 'blockenberg'), value: a.titleColor, onChange: function (v) { setAttributes({ titleColor: v || '#14532d' }); } }
93 ]
94 })
95 ),
96 el('div', blockProps,
97 el(RichText, {
98 tagName: 'h3', className: 'bkbg-snk-title',
99 value: a.title, onChange: function (v) { setAttributes({ title: v }); },
100 placeholder: __('Snake', 'blockenberg'),
101 style: { color: a.titleColor, margin: '0 0 4px' }
102 }),
103 el(RichText, {
104 tagName: 'p', className: 'bkbg-snk-subtitle',
105 value: a.subtitle, onChange: function (v) { setAttributes({ subtitle: v }); },
106 placeholder: __('Subtitle', 'blockenberg'),
107 style: { color: a.titleColor + 'bb', margin: '0 0 14px' }
108 }),
109 // Score/high-score bar
110 el('div', { style: { display: 'flex', justifyContent: 'center', gap: 20, marginBottom: 12 } },
111 el('div', { style: { fontWeight: 700, color: a.titleColor } }, 'Score: 0'),
112 a.showHighScore && el('div', { style: { fontWeight: 700, color: a.accentColor } }, 'Best: 0')
113 ),
114 // Canvas preview (SVG)
115 el('div', { style: { display: 'flex', justifyContent: 'center', marginBottom: 12 } },
116 el('svg', {
117 width: sz, height: sz,
118 style: { border: '2px solid ' + a.accentColor, borderRadius: 10, background: a.boardBg, display: 'block' }
119 },
120 // Grid lines
121 Array.from({ length: gs + 1 }, function (_, i) {
122 return el('g', { key: 'g' + i },
123 el('line', { x1: i * cell, y1: 0, x2: i * cell, y2: sz, stroke: a.gridColor, strokeWidth: 0.5 }),
124 el('line', { x1: 0, y1: i * cell, x2: sz, y2: i * cell, stroke: a.gridColor, strokeWidth: 0.5 })
125 );
126 }),
127 // Snake body
128 demoSnake.slice(1).map(function (s, i) {
129 return el('rect', { key: 'b' + i, x: s[0]*cell+1, y: s[1]*cell+1, width: cell-2, height: cell-2, rx: 3, fill: a.snakeColor });
130 }),
131 // Snake head
132 el('rect', { x: demoSnake[0][0]*cell+1, y: demoSnake[0][1]*cell+1, width: cell-2, height: cell-2, rx: 4, fill: a.snakeHeadColor }),
133 // Food
134 el('circle', { cx: demoFood[0]*cell+cell/2, cy: demoFood[1]*cell+cell/2, r: cell/2 - 2, fill: a.foodColor }),
135 // Start text overlay
136 el('rect', { x: sz/2-60, y: sz/2-18, width: 120, height: 36, rx: 8, fill: 'rgba(0,0,0,0.5)' }),
137 el('text', { x: sz/2, y: sz/2+6, textAnchor: 'middle', fill: '#fff', fontSize: 14, fontFamily: 'system-ui', fontWeight: 700 }, 'Press SPACE to Start')
138 )
139 ),
140 // Touch controls preview
141 a.showControls && el('div', { style: { display: 'flex', flexDirection: 'column', alignItems: 'center', gap: 6 } },
142 el('button', { style: { width: 48, height: 48, fontSize: 20, borderRadius: 8, border: '2px solid ' + a.accentColor, background: 'transparent', color: a.accentColor, cursor: 'default' } }, ''),
143 el('div', { style: { display: 'flex', gap: 6 } },
144 el('button', { style: { width: 48, height: 48, fontSize: 20, borderRadius: 8, border: '2px solid ' + a.accentColor, background: 'transparent', color: a.accentColor, cursor: 'default' } }, ''),
145 el('button', { style: { width: 48, height: 48, fontSize: 20, borderRadius: 8, border: '2px solid ' + a.accentColor, background: 'transparent', color: a.accentColor, cursor: 'default' } }, ''),
146 el('button', { style: { width: 48, height: 48, fontSize: 20, borderRadius: 8, border: '2px solid ' + a.accentColor, background: 'transparent', color: a.accentColor, cursor: 'default' } }, '')
147 )
148 )
149 )
150 );
151 }
152
153 registerBlockType('blockenberg/snake-game', {
154 edit: EditorPreview,
155 save: function (props) {
156 var a = props.attributes;
157 return el('div', useBlockProps.save(),
158 el('div', { className: 'bkbg-snk-app', 'data-opts': JSON.stringify(a) },
159 el(RichText.Content, { tagName: 'h3', className: 'bkbg-snk-title', value: a.title }),
160 el(RichText.Content, { tagName: 'p', className: 'bkbg-snk-subtitle', value: a.subtitle })
161 )
162 );
163 }
164 });
165 }() );
166