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 / neon-text / index.js

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

209 lines 12.7 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 __ = wp.i18n.__;
5 var registerBlockType = wp.blocks.registerBlockType;
6 var InspectorControls = wp.blockEditor.InspectorControls;
7 var useBlockProps = wp.blockEditor.useBlockProps;
8 var PanelColorSettings = wp.blockEditor.PanelColorSettings;
9 var PanelBody = wp.components.PanelBody;
10 var TextControl = wp.components.TextControl;
11 var ToggleControl = wp.components.ToggleControl;
12 var RangeControl = wp.components.RangeControl;
13 var SelectControl = wp.components.SelectControl;
14
15 var _tc, _tv;
16 function getTypoControl() { return _tc || (_tc = window.bkbgTypographyControl); }
17 function getTypoCssVars() { return _tv || (_tv = window.bkbgTypoCssVars); }
18
19 var PRESETS = [
20 { label: '⚡ Electric Blue', value: 'electric-blue', tube: '#00d4ff', glow: '#00d4ff', second: '#0055ff', bg: '#0a0a12' },
21 { label: '🔴 Hot Pink', value: 'hot-pink', tube: '#ff0080', glow: '#ff0080', second: '#ff4000', bg: '#0d000a' },
22 { label: '🟢 Matrix Green', value: 'matrix-green', tube: '#00ff41', glow: '#00ff41', second: '#00aa00', bg: '#000d03' },
23 { label: '🟡 Golden Amber', value: 'golden-amber', tube: '#ffaa00', glow: '#ffaa00', second: '#ff5500', bg: '#0d0800' },
24 { label: '🟣 Purple Haze', value: 'purple-haze', tube: '#c800ff', glow: '#c800ff', second: '#6600ff', bg: '#08000d' },
25 { label: '🔵 Ocean Teal', value: 'ocean-teal', tube: '#00ffcc', glow: '#00ffcc', second: '#0066ff', bg: '#000d0a' },
26 { label: '🌹 Rose Gold', value: 'rose-gold', tube: '#ff6b9d', glow: '#ff3366', second: '#c0392b', bg: '#0d0205' },
27 { label: '🟠 Toxic Orange', value: 'toxic-orange', tube: '#ff6600', glow: '#ff8800', second: '#ffcc00', bg: '#0d0400' },
28 ];
29
30 var FLICKER_MODES = [
31 { label: 'Soft (gentle breathe)', value: 'soft' },
32 { label: 'Classic (on/off blink)', value: 'classic' },
33 { label: 'Broken (random stutter)', value: 'broken' },
34 { label: 'None', value: 'none' },
35 ];
36
37 var TAGS = [
38 { label: 'H1', value: 'h1' }, { label: 'H2', value: 'h2' }, { label: 'H3', value: 'h3' },
39 { label: 'H4', value: 'h4' }, { label: 'p', value: 'p' }, { label: 'div', value: 'div' },
40 ];
41 var WEIGHTS = [
42 { label: '300 Light', value: '300' }, { label: '400 Regular', value: '400' },
43 { label: '600 Semi-Bold', value: '600' }, { label: '700 Bold', value: '700' },
44 { label: '800 Extra-Bold', value: '800' },
45 ];
46 var TRANSFORMS = [
47 { label: 'UPPERCASE', value: 'uppercase' }, { label: 'lowercase', value: 'lowercase' },
48 { label: 'Capitalize', value: 'capitalize' }, { label: 'None', value: 'none' },
49 ];
50
51 function makeNeonShadow(a, boost) {
52 var tube = a.tubeColor || '#00d4ff';
53 var glow = a.glowColor || '#00d4ff';
54 var second = a.secondGlow || '#0055ff';
55 var int = (a.glowIntensity || 3) * (boost || 1);
56 var spread = a.glowSpread || 40;
57
58 var layers = [
59 '0 0 ' + Math.round(spread * 0.1) + 'px ' + tube,
60 '0 0 ' + Math.round(spread * 0.3) + 'px ' + tube,
61 '0 0 ' + Math.round(spread * 0.6 * int) + 'px ' + glow,
62 '0 0 ' + Math.round(spread * 1.0 * int) + 'px ' + glow,
63 '0 0 ' + Math.round(spread * 2.0 * int) + 'px ' + second,
64 '0 0 ' + Math.round(spread * 3.0 * int) + 'px ' + second,
65 ];
66 return layers.join(', ');
67 }
68
69 function applyPreset(preset, set) {
70 var p = PRESETS.find(function (x) { return x.value === preset; });
71 if (!p) return;
72 set({ preset: p.value, tubeColor: p.tube, glowColor: p.glow, secondGlow: p.second, backgroundColor: p.bg });
73 }
74
75 function NeonPreview(props) {
76 var a = props.attributes;
77
78 var wrapStyle = {
79 background: a.backgroundColor,
80 padding: a.paddingV + 'px ' + a.paddingH + 'px',
81 borderRadius: a.borderRadius + 'px',
82 textAlign: a.textAlign,
83 position: 'relative',
84 overflow: 'hidden',
85 };
86 var textStyle = {
87 color: a.tubeColor,
88 textShadow: makeNeonShadow(a),
89 margin: 0,
90 display: 'block',
91 };
92
93 var Tag = a.tag || 'h2';
94
95 return el('div', { className: 'bkbg-nt-wrap', style: wrapStyle },
96 a.showBorderSign && el('div', { style: {
97 position: 'absolute', inset: '12px',
98 border: '3px solid ' + a.borderSignColor,
99 borderRadius: Math.max(0, a.borderRadius - 6) + 'px',
100 boxShadow: '0 0 12px ' + a.borderSignColor + ', inset 0 0 12px ' + a.borderSignColor + '22',
101 pointerEvents: 'none',
102 }}),
103 a.showScanlines && el('div', { style: {
104 position: 'absolute', inset: 0,
105 background: 'repeating-linear-gradient(0deg, transparent, transparent 2px, rgba(0,0,0,0.08) 2px, rgba(0,0,0,0.08) 4px)',
106 pointerEvents: 'none',
107 borderRadius: 'inherit',
108 }}),
109 el(Tag, { className: 'bkbg-nt-text', style: textStyle }, a.text || 'NEON SIGN'),
110 a.showSubText && a.subText && el('p', { className: 'bkbg-nt-sub', style: { color: a.tubeColor, textShadow: makeNeonShadow(a, 0.6), marginTop: '12px', position: 'relative', zIndex: 2 } }, a.subText),
111 a.showGlowFloor && el('div', { style: {
112 position: 'absolute', bottom: 0, left: '10%', right: '10%', height: '2px',
113 background: 'radial-gradient(ellipse at center, ' + a.glowColor + '55 0%, transparent 70%)',
114 filter: 'blur(8px)',
115 pointerEvents: 'none',
116 }})
117 );
118 }
119
120 registerBlockType('blockenberg/neon-text', {
121 edit: function (props) {
122 var a = props.attributes;
123 var set = props.setAttributes;
124
125 return el(Fragment, null,
126 el(InspectorControls, null,
127 /* Text */
128 el(PanelBody, { title: 'Text', initialOpen: true },
129 el(TextControl, { __nextHasNoMarginBottom: true, label: 'Main text', value: a.text, onChange: function (v) { set({ text: v }); } }),
130 el(ToggleControl, { __nextHasNoMarginBottom: true, label: 'Show subtitle', checked: a.showSubText, onChange: function (v) { set({ showSubText: v }); } }),
131 a.showSubText && el(TextControl, { __nextHasNoMarginBottom: true, label: 'Subtitle', value: a.subText, onChange: function (v) { set({ subText: v }); } }),
132 el(SelectControl, { __nextHasNoMarginBottom: true, label: 'HTML tag', value: a.tag, options: TAGS, onChange: function (v) { set({ tag: v }); } }),
133 ),
134 /* Colors & Preset */
135
136 el( PanelBody, { title: __( 'Typography', 'blockenberg' ), initialOpen: false },
137 el(getTypoControl(), { label: __('Heading', 'blockenberg'), value: a.headingTypo, onChange: function (v) { set({ headingTypo: v }); } }),
138 el(getTypoControl(), { label: __('Subtitle', 'blockenberg'), value: a.subtitleTypo, onChange: function (v) { set({ subtitleTypo: v }); } })
139 ),
140 el(PanelBody, { title: 'Neon Color', initialOpen: false },
141 el(SelectControl, { __nextHasNoMarginBottom: true, label: 'Color preset', value: a.preset, options: PRESETS.map(function (p) { return { label: p.label, value: p.value }; }), onChange: function (v) { applyPreset(v, set); } }),
142 el('p', { style: { fontSize: '12px', color: '#888', margin: '4px 0 12px' } }, 'Or customize colors below:'),
143 ),
144 el(PanelColorSettings, {
145 title: 'Custom Colors',
146 initialOpen: false,
147 colorSettings: [
148 { value: a.tubeColor, onChange: function (v) { set({ tubeColor: v || '#00d4ff', preset: 'custom' }); }, label: 'Tube / text color' },
149 { value: a.glowColor, onChange: function (v) { set({ glowColor: v || '#00d4ff', preset: 'custom' }); }, label: 'Inner glow color' },
150 { value: a.secondGlow, onChange: function (v) { set({ secondGlow: v || '#0055ff', preset: 'custom' }); }, label: 'Outer glow color' },
151 { value: a.backgroundColor, onChange: function (v) { set({ backgroundColor: v || '#0a0a12' }); }, label: 'Background' },
152 { value: a.borderSignColor, onChange: function (v) { set({ borderSignColor: v || '#ff0080' }); }, label: 'Sign border color' },
153 ],
154 }),
155 /* Glow */
156 el(PanelBody, { title: 'Glow Settings', initialOpen: false },
157 el(RangeControl, { __nextHasNoMarginBottom: true, label: 'Glow intensity', value: a.glowIntensity, min: 0.5, max: 8, step: 0.5, onChange: function (v) { set({ glowIntensity: v }); } }),
158 el(RangeControl, { __nextHasNoMarginBottom: true, label: 'Glow spread (px)', value: a.glowSpread, min: 5, max: 120, step: 5, onChange: function (v) { set({ glowSpread: v }); } }),
159 el(ToggleControl, { __nextHasNoMarginBottom: true, label: 'Show glow floor reflection', checked: a.showGlowFloor, onChange: function (v) { set({ showGlowFloor: v }); } }),
160 el(ToggleControl, { __nextHasNoMarginBottom: true, label: 'Show CRT scanlines overlay', checked: a.showScanlines, onChange: function (v) { set({ showScanlines: v }); } }),
161 el(ToggleControl, { __nextHasNoMarginBottom: true, label: 'Show neon sign border', checked: a.showBorderSign, onChange: function (v) { set({ showBorderSign: v }); } }),
162 ),
163 /* Animation */
164 el(PanelBody, { title: 'Animation', initialOpen: false },
165 el(SelectControl, { __nextHasNoMarginBottom: true, label: 'Flicker mode', value: a.flickerMode, options: FLICKER_MODES, onChange: function (v) { set({ flickerMode: v }); } }),
166 el(RangeControl, { __nextHasNoMarginBottom: true, label: 'Broken letter index (-1 = random)', value: a.flickerLetter, min: -1, max: 20, onChange: function (v) { set({ flickerLetter: v }); }, help: 'For "broken" mode: which character appears faulty (-1 = random)' }),
167 ),
168 /* Layout */
169 el(PanelBody, { title: 'Layout', initialOpen: false },
170 el(RangeControl, { __nextHasNoMarginBottom: true, label: 'Vertical padding (px)', value: a.paddingV, min: 0, max: 160, onChange: function (v) { set({ paddingV: v }); } }),
171 el(RangeControl, { __nextHasNoMarginBottom: true, label: 'Horizontal padding (px)', value: a.paddingH, min: 0, max: 160, onChange: function (v) { set({ paddingH: v }); } }),
172 el(RangeControl, { __nextHasNoMarginBottom: true, label: 'Border radius (px)', value: a.borderRadius, min: 0, max: 64, onChange: function (v) { set({ borderRadius: v }); } }),
173 ),
174 ),
175 el('div', useBlockProps((function () {
176 var _tvf = getTypoCssVars();
177 var s = {};
178 Object.assign(s, _tvf(a.headingTypo, '--bkbg-nt-hd-'));
179 Object.assign(s, _tvf(a.subtitleTypo, '--bkbg-nt-sb-'));
180 return { style: s };
181 })()),
182 el(NeonPreview, { attributes: a })
183 )
184 );
185 },
186 deprecated: [{
187 save: function (props) {
188 var a = props.attributes;
189 return el('div', wp.blockEditor.useBlockProps.save(),
190 el('div', { className: 'bkbg-nt-app', 'data-opts': JSON.stringify(a) })
191 );
192 }
193 }],
194 save: function (props) {
195 var a = props.attributes;
196 var blockProps = wp.blockEditor.useBlockProps.save((function () {
197 var _tvf = getTypoCssVars();
198 var s = {};
199 Object.assign(s, _tvf(a.headingTypo, '--bkbg-nt-hd-'));
200 Object.assign(s, _tvf(a.subtitleTypo, '--bkbg-nt-sb-'));
201 return { style: s };
202 })());
203 return el('div', blockProps,
204 el('div', { className: 'bkbg-nt-app', 'data-opts': JSON.stringify(a) })
205 );
206 },
207 });
208 }() );
209