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

index.js in Blockenberg — 600+ Advanced Gutenberg Blocks & AI Agent for WordPress Block Editor 2.0.14, at blocks/weather-widget/index.js

248 lines 15.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 __ = 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 // Resolve the shared components lazily without defining globals for each block.
16 function _tc(label, key, attrs, setA) {
17 var Control = window.bkbgTypographyControl;
18 return Control ? el(Control, {
19 label: label,
20 value: attrs[key] || {},
21 onChange: function (value) { var update = {}; update[key] = value; setA(update); }
22 }) : null;
23 }
24 function _tvf(vars, key, attrs, prefix) {
25 var cssVars = window.bkbgTypoCssVars;
26 if (cssVars) Object.assign(vars, cssVars(attrs[key] || {}, prefix));
27 return vars;
28 }
29 function getTypoControl(label, key, attrs, setA) { return _tc(label, key, attrs, setA); }
30 function getTypoCssVars(attrs) {
31 var v = {};
32 _tvf(v, 'tempTypo', attrs, '--bkww-tp-');
33 _tvf(v, 'cityTypo', attrs, '--bkww-ct-');
34 _tvf(v, 'metaTypo', attrs, '--bkww-mt-');
35 return v;
36 }
37
38 var UNITS = [
39 { label: 'Celsius (°C)', value: 'metric' },
40 { label: 'Fahrenheit (°F)', value: 'imperial' },
41 { label: 'Kelvin (K)', value: 'standard' },
42 ];
43
44 var LAYOUTS = [
45 { label: 'Card (centered)', value: 'card' },
46 { label: 'Wide (full-width)', value: 'wide' },
47 { label: 'Minimal (compact)', value: 'minimal' },
48 ];
49
50 var BG_STYLES = [
51 { label: 'Gradient (auto by weather)', value: 'gradient' },
52 { label: 'Custom color', value: 'custom' },
53 { label: 'Transparent', value: 'transparent' },
54 ];
55
56 var LANGS = [
57 { label: 'English', value: 'en' },
58 { label: 'Russian', value: 'ru' },
59 { label: 'German', value: 'de' },
60 { label: 'French', value: 'fr' },
61 { label: 'Spanish', value: 'es' },
62 { label: 'Japanese', value: 'ja' },
63 ];
64
65 /* weather icon emoji map for editor preview */
66 function weatherIcon(code) {
67 if (!code) return '🌤';
68 var c = String(code);
69 if (c.startsWith('01')) return '☀️';
70 if (c.startsWith('02')) return '�
71 ';
72 if (c.startsWith('03') || c.startsWith('04')) return '☁️';
73 if (c.startsWith('09') || c.startsWith('10')) return '🌧';
74 if (c.startsWith('11')) return '⛈';
75 if (c.startsWith('13')) return '❄️';
76 if (c.startsWith('50')) return '🌫';
77 return '🌤';
78 }
79
80 function unitLabel(units) {
81 if (units === 'imperial') return '°F';
82 if (units === 'standard') return 'K';
83 return '°C';
84 }
85
86 /* demo forecast data for editor preview */
87 var DEMO_FORECAST = [
88 { day: 'Mon', icon: '☀️', hi: 22, lo: 14 },
89 { day: 'Tue', icon: '�
90 ', hi: 19, lo: 12 },
91 { day: 'Wed', icon: '🌧', hi: 15, lo: 10 },
92 { day: 'Thu', icon: '☁️', hi: 17, lo: 11 },
93 { day: 'Fri', icon: '☀️', hi: 24, lo: 16 },
94 ];
95
96 function WeatherPreview(props) {
97 var a = props.attributes;
98 var deg = unitLabel(a.units);
99 var wrapStyle = {
100 background: a.backgroundStyle === 'gradient'
101 ? 'linear-gradient(135deg, #1e3a5f 0%, #2563eb 50%, #0f172a 100%)'
102 : a.backgroundStyle === 'custom' ? a.customBg : 'transparent',
103 borderRadius: a.borderRadius + 'px',
104 padding: a.padding + 'px',
105 maxWidth: a.layout === 'card' ? a.maxWidth + 'px' : '100%',
106 margin: a.layout === 'card' ? '0 auto' : '0',
107 color: a.textColor,
108 fontFamily: 'inherit',
109 };
110 var cardStyle = {
111 background: a.cardBg,
112 backdropFilter: 'blur(16px)',
113 borderRadius: a.cardRadius + 'px',
114 padding: '24px',
115 border: '1px solid rgba(255,255,255,0.2)',
116 };
117
118 return el('div', { style: wrapStyle },
119 el('div', { style: cardStyle },
120 /* top row: city + icon */
121 el('div', { style: { display: 'flex', justifyContent: 'space-between', alignItems: 'flex-start', marginBottom: '12px' } },
122 el('div', null,
123 el('div', { className: 'bkbg-ww-city-label', style: { opacity: 0.75, marginBottom: '4px' } },
124 '📍 ' + (a.city || 'Your City')),
125 el('div', { className: 'bkbg-ww-temp' }, '22' + deg),
126 el('div', { style: { fontSize: '15px', opacity: 0.85, marginTop: '4px' } }, 'Partly Cloudy'),
127 ),
128 el('div', { style: { fontSize: '72px', lineHeight: 1 } }, '�
129 ')
130 ),
131 /* feels like / hi-lo */
132 a.showFeelsLike && el('div', { style: { fontSize: '13px', opacity: 0.7, marginBottom: '16px' } },
133 'Feels like 20' + deg + ' · H: 25' + deg + ' L: 14' + deg),
134 /* stats row */
135 el('div', { style: { display: 'flex', gap: '16px', flexWrap: 'wrap', marginBottom: a.showForecast ? '24px' : '0' } },
136 a.showHumidity && el('div', { style: { background: 'rgba(255,255,255,0.1)', borderRadius: '10px', padding: '10px 14px', flex: '1', minWidth: '80px', textAlign: 'center' } },
137 el('div', { style: { fontSize: '18px' } }, '💧'),
138 el('div', { style: { fontSize: '14px', fontWeight: 600 } }, '68%'),
139 el('div', { className: 'bkbg-ww-stat-lbl', style: { opacity: 0.7 } }, 'Humidity'),
140 ),
141 a.showWind && el('div', { style: { background: 'rgba(255,255,255,0.1)', borderRadius: '10px', padding: '10px 14px', flex: '1', minWidth: '80px', textAlign: 'center' } },
142 el('div', { style: { fontSize: '18px' } }, '💨'),
143 el('div', { style: { fontSize: '14px', fontWeight: 600 } }, '14 km/h'),
144 el('div', { className: 'bkbg-ww-stat-lbl', style: { opacity: 0.7 } }, 'Wind'),
145 ),
146 a.showPressure && el('div', { style: { background: 'rgba(255,255,255,0.1)', borderRadius: '10px', padding: '10px 14px', flex: '1', minWidth: '80px', textAlign: 'center' } },
147 el('div', { style: { fontSize: '18px' } }, '🌡'),
148 el('div', { style: { fontSize: '14px', fontWeight: 600 } }, '1013 hPa'),
149 el('div', { className: 'bkbg-ww-stat-lbl', style: { opacity: 0.7 } }, 'Pressure'),
150 ),
151 ),
152 /* forecast */
153 a.showForecast && el('div', null,
154 el('div', { style: { fontSize: '12px', fontWeight: 600, opacity: 0.7, textTransform: 'uppercase', letterSpacing: '1px', marginBottom: '10px' } }, '5-Day Forecast'),
155 el('div', { style: { display: 'flex', gap: '8px' } },
156 DEMO_FORECAST.slice(0, a.forecastDays).map(function (f) {
157 return el('div', {
158 key: f.day,
159 style: { background: a.forecastBg, borderRadius: '10px', padding: '10px 8px', flex: 1, textAlign: 'center' },
160 },
161 el('div', { style: { fontSize: '11px', opacity: 0.7, marginBottom: '4px' } }, f.day),
162 el('div', { style: { fontSize: '20px', marginBottom: '4px' } }, f.icon),
163 el('div', { style: { fontSize: '12px', fontWeight: 600 } }, f.hi + deg),
164 el('div', { style: { fontSize: '11px', opacity: 0.6 } }, f.lo + deg),
165 );
166 })
167 )
168 )
169 ),
170 !a.apiKey && el('div', { style: { marginTop: '10px', padding: '8px 12px', background: 'rgba(255,165,0,0.2)', borderRadius: '8px', fontSize: '12px', color: '#fbbf24', border: '1px solid rgba(251,191,36,0.4)' } },
171 '⚠️ Add your OpenWeatherMap API key in the block settings to fetch live data.')
172 );
173 }
174
175 registerBlockType('blockenberg/weather-widget', {
176 edit: function (props) {
177 var a = props.attributes;
178 var set = props.setAttributes;
179
180 return el(Fragment, null,
181 el(InspectorControls, null,
182 /* API */
183 el(PanelBody, { title: 'API & Location', initialOpen: true },
184 el(TextControl, { __nextHasNoMarginBottom: true, label: 'OpenWeatherMap API Key', value: a.apiKey, onChange: function (v) { set({ apiKey: v }); }, help: 'Free key from openweathermap.org' }),
185 el(TextControl, { __nextHasNoMarginBottom: true, label: 'Default City', value: a.city, onChange: function (v) { set({ city: v }); }, help: 'e.g. London, New York, Tokyo' }),
186 el(ToggleControl, { __nextHasNoMarginBottom: true, label: 'Auto-detect visitor location (Geolocation)', checked: a.autoLocation, onChange: function (v) { set({ autoLocation: v }); } }),
187 el(SelectControl, { __nextHasNoMarginBottom: true, label: 'Units', value: a.units, options: UNITS, onChange: function (v) { set({ units: v }); } }),
188 el(SelectControl, { __nextHasNoMarginBottom: true, label: 'Language', value: a.lang, options: LANGS, onChange: function (v) { set({ lang: v }); } }),
189 el(RangeControl, { __nextHasNoMarginBottom: true, label: 'Auto-refresh interval (minutes)', value: a.refreshInterval, min: 0, max: 60, step: 5, onChange: function (v) { set({ refreshInterval: v }); }, help: '0 = no refresh' }),
190 ),
191 /* Display */
192 el(PanelBody, { title: 'Display Options', initialOpen: false },
193 el(ToggleControl, { __nextHasNoMarginBottom: true, label: 'Show feels-like temperature', checked: a.showFeelsLike, onChange: function (v) { set({ showFeelsLike: v }); } }),
194 el(ToggleControl, { __nextHasNoMarginBottom: true, label: 'Show humidity', checked: a.showHumidity, onChange: function (v) { set({ showHumidity: v }); } }),
195 el(ToggleControl, { __nextHasNoMarginBottom: true, label: 'Show wind speed', checked: a.showWind, onChange: function (v) { set({ showWind: v }); } }),
196 el(ToggleControl, { __nextHasNoMarginBottom: true, label: 'Show pressure', checked: a.showPressure, onChange: function (v) { set({ showPressure: v }); } }),
197 el(ToggleControl, { __nextHasNoMarginBottom: true, label: 'Show visibility', checked: a.showVisibility, onChange: function (v) { set({ showVisibility: v }); } }),
198 el(ToggleControl, { __nextHasNoMarginBottom: true, label: 'Show animated weather icon', checked: a.showAnimatedIcon, onChange: function (v) { set({ showAnimatedIcon: v }); } }),
199 el(ToggleControl, { __nextHasNoMarginBottom: true, label: 'Show 5-day forecast', checked: a.showForecast, onChange: function (v) { set({ showForecast: v }); } }),
200 a.showForecast && el(RangeControl, { __nextHasNoMarginBottom: true, label: 'Forecast days', value: a.forecastDays, min: 2, max: 5, onChange: function (v) { set({ forecastDays: v }); } }),
201 ),
202 /* Layout */
203 el(PanelBody, { title: 'Layout', initialOpen: false },
204 el(SelectControl, { __nextHasNoMarginBottom: true, label: 'Layout', value: a.layout, options: LAYOUTS, onChange: function (v) { set({ layout: v }); } }),
205 a.layout === 'card' && el(RangeControl, { __nextHasNoMarginBottom: true, label: 'Max width (px)', value: a.maxWidth, min: 280, max: 800, step: 10, onChange: function (v) { set({ maxWidth: v }); } }),
206 el(RangeControl, { __nextHasNoMarginBottom: true, label: 'Padding (px)', value: a.padding, min: 8, max: 64, onChange: function (v) { set({ padding: v }); } }),
207 el(RangeControl, { __nextHasNoMarginBottom: true, label: 'Outer radius (px)', value: a.borderRadius, min: 0, max: 48, onChange: function (v) { set({ borderRadius: v }); } }),
208 el(RangeControl, { __nextHasNoMarginBottom: true, label: 'Card radius (px)', value: a.cardRadius, min: 0, max: 32, onChange: function (v) { set({ cardRadius: v }); } }),
209 ),
210 /* Typography */
211 el(PanelBody, { title: 'Typography', initialOpen: false },
212 getTypoControl( __( 'Temperature', 'blockenberg' ), 'tempTypo', a, set ),
213 getTypoControl( __( 'City Label', 'blockenberg' ), 'cityTypo', a, set ),
214 getTypoControl( __( 'Stat Labels', 'blockenberg' ), 'metaTypo', a, set ),
215 ),
216 /* Colors */
217 el(PanelBody, { title: 'Background', initialOpen: false },
218 el(SelectControl, { __nextHasNoMarginBottom: true, label: 'Background style', value: a.backgroundStyle, options: BG_STYLES, onChange: function (v) { set({ backgroundStyle: v }); } }),
219 a.backgroundStyle === 'custom' && el('div', { style: { marginTop: '8px' } },
220 el('label', { style: { display: 'block', fontSize: '12px', marginBottom: '4px' } }, 'Background color'),
221 el('input', { type: 'color', value: a.customBg, onChange: function (e) { set({ customBg: e.target.value }); }, style: { width: '100%', height: '36px', border: 'none', borderRadius: '4px', cursor: 'pointer' } })
222 ),
223 ),
224 el(PanelColorSettings, {
225 title: 'Colors',
226 initialOpen: false,
227 colorSettings: [
228 { value: a.textColor, onChange: function (v) { set({ textColor: v || '#ffffff' }); }, label: 'Text color' },
229 { value: a.accentColor, onChange: function (v) { set({ accentColor: v || '#60a5fa' }); }, label: 'Accent color' },
230 { value: a.cardBg, onChange: function (v) { set({ cardBg: v || 'rgba(255,255,255,0.12)' }); }, label: 'Card background' },
231 { value: a.forecastBg, onChange: function (v) { set({ forecastBg: v || 'rgba(255,255,255,0.08)' }); }, label: 'Forecast day background' },
232 ],
233 }),
234 ),
235 el('div', useBlockProps({ style: getTypoCssVars(a) }),
236 el(WeatherPreview, { attributes: a })
237 )
238 );
239 },
240 save: function (props) {
241 var a = props.attributes;
242 return el('div', useBlockProps.save({ style: getTypoCssVars(a) }),
243 el('div', { className: 'bkbg-ww-app', 'data-opts': JSON.stringify(a) })
244 );
245 },
246 });
247 }() );
248