PluginProbe
Blockenberg — 600+ Advanced Gutenberg Blocks & AI Agent for WordPress Block Editor / 2.0.11
Blockenberg — 600+ Advanced Gutenberg Blocks & AI Agent for WordPress Block Editor v2.0.11
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 / analog-clock / index.js

index.js in Blockenberg — 600+ Advanced Gutenberg Blocks & AI Agent for WordPress Block Editor 2.0.11, at blocks/analog-clock/index.js

235 lines 12.9 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 useState = wp.element.useState;
4 var useEffect = wp.element.useEffect;
5 var Fragment = wp.element.Fragment;
6 var registerBlockType = wp.blocks.registerBlockType;
7 var __ = wp.i18n.__;
8 var InspectorControls = wp.blockEditor.InspectorControls;
9 var PanelColorSettings = wp.blockEditor.PanelColorSettings;
10 var useBlockProps = wp.blockEditor.useBlockProps;
11 var RichText = wp.blockEditor.RichText;
12 var PanelBody = wp.components.PanelBody;
13 var RangeControl = wp.components.RangeControl;
14 var ToggleControl = wp.components.ToggleControl;
15 var SelectControl = wp.components.SelectControl;
16
17 var _TypographyControl, _typoCssVars;
18 function getTypographyControl() { return _TypographyControl || (_TypographyControl = window.bkbgTypographyControl); }
19 function getTypoCssVars() { return _typoCssVars || (_typoCssVars = window.bkbgTypoCssVars); }
20
21 var TIMEZONES = [
22 { label: 'Local (device)', value: 'local' },
23 { label: 'UTC', value: 'UTC' },
24 { label: 'New York (ET)', value: 'America/New_York' },
25 { label: 'Chicago (CT)', value: 'America/Chicago' },
26 { label: 'Los Angeles (PT)', value: 'America/Los_Angeles' },
27 { label: 'London (GMT/BST)', value: 'Europe/London' },
28 { label: 'Paris (CET)', value: 'Europe/Paris' },
29 { label: 'Berlin (CET)', value: 'Europe/Berlin' },
30 { label: 'Moscow (MSK)', value: 'Europe/Moscow' },
31 { label: 'Dubai (GST)', value: 'Asia/Dubai' },
32 { label: 'Mumbai (IST)', value: 'Asia/Kolkata' },
33 { label: 'Bangkok (ICT)', value: 'Asia/Bangkok' },
34 { label: 'Singapore (SGT)', value: 'Asia/Singapore' },
35 { label: 'Tokyo (JST)', value: 'Asia/Tokyo' },
36 { label: 'Sydney (AEST)', value: 'Australia/Sydney' }
37 ];
38
39 function ClockFace(props) {
40 var a = props;
41 var now = new Date();
42 var h = now.getHours() % 12;
43 var m = now.getMinutes();
44 var s = now.getSeconds();
45
46 var r = 46; // radius within 100-unit viewBox
47 var cx = 50, cy = 50;
48
49 var hAngle = (h * 30) + (m * 0.5); // degrees, 0 at top
50 var mAngle = m * 6;
51 var sAngle = s * 6;
52
53 function toRad(deg) { return (deg - 90) * Math.PI / 180; }
54 function handEnd(angle, length) {
55 return { x: cx + length * Math.cos(toRad(angle)), y: cy + length * Math.sin(toRad(angle)) };
56 }
57
58 var hEnd = handEnd(hAngle, 28);
59 var mEnd = handEnd(mAngle, 36);
60 var sEnd = handEnd(sAngle, 40);
61
62 // Tick marks
63 var ticks = [];
64 for (var i = 0; i < 60; i++) {
65 var isBig = i % 5 === 0;
66 var ang = (i * 6 - 90) * Math.PI / 180;
67 var innerR = isBig ? r - 8 : r - 5;
68 ticks.push(el('line', {
69 key: i,
70 x1: cx + innerR * Math.cos(ang), y1: cy + innerR * Math.sin(ang),
71 x2: cx + r * Math.cos(ang), y2: cy + r * Math.sin(ang),
72 stroke: a.tickColor, strokeWidth: isBig ? 2 : 0.8,
73 strokeLinecap: 'round'
74 }));
75 }
76
77 // Hour numbers
78 var numbers = [];
79 if (a.showNumbers) {
80 for (var j = 1; j <= 12; j++) {
81 var nAng = ((j * 30) - 90) * Math.PI / 180;
82 numbers.push(el('text', {
83 key: 'n' + j,
84 x: cx + (r - 15) * Math.cos(nAng),
85 y: cy + (r - 15) * Math.sin(nAng),
86 textAnchor: 'middle', dominantBaseline: 'middle',
87 fontSize: 7, fontWeight: 700, fill: a.numberColor,
88 fontFamily: 'system-ui'
89 }, j));
90 }
91 }
92
93 var sz = a.clockSize || 240;
94 var borderW = a.clockStyle === 'minimal' ? 2 : a.clockStyle === 'bold' ? 8 : 4;
95
96 return el('svg', {
97 width: sz, height: sz,
98 viewBox: '0 0 100 100',
99 style: { display: 'block', maxWidth: '100%' }
100 },
101 // Face
102 el('circle', { cx: cx, cy: cy, r: 49, fill: a.clockBorder }),
103 el('circle', { cx: cx, cy: cy, r: 49 - borderW, fill: a.clockFace }),
104
105 // Ticks
106 a.showTicks && ticks,
107
108 // Numbers
109 numbers,
110
111 // Hour hand
112 el('line', { x1: cx, y1: cy, x2: hEnd.x, y2: hEnd.y, stroke: a.hourHandColor, strokeWidth: 3.5, strokeLinecap: 'round' }),
113 // Minute hand
114 el('line', { x1: cx, y1: cy, x2: mEnd.x, y2: mEnd.y, stroke: a.minuteHandColor, strokeWidth: 2.5, strokeLinecap: 'round' }),
115 // Second hand
116 a.showSecondHand && el('line', { x1: cx, y1: cy, x2: sEnd.x, y2: sEnd.y, stroke: a.secondHandColor, strokeWidth: 1.5, strokeLinecap: 'round' }),
117 // Counter weight
118 a.showSecondHand && el('line', { x1: cx, y1: cy, x2: cx + (-sEnd.x + cx)*0.25, y2: cy + (-sEnd.y + cy)*0.25, stroke: a.secondHandColor, strokeWidth: 1.5, strokeLinecap: 'round' }),
119 // Center dot
120 el('circle', { cx: cx, cy: cy, r: 3, fill: a.centerDotColor }),
121 el('circle', { cx: cx, cy: cy, r: 1.5, fill: '#fff' })
122 );
123 }
124
125 function EditorPreview(props) {
126 var a = props.attributes;
127 var setAttributes = props.setAttributes;
128 var blockProps = useBlockProps({ style: { background: a.sectionBg || 'transparent', padding: '28px 20px', textAlign: 'center' } });
129 var state = useState(0);
130 var tick = state[1];
131
132 useEffect(function () {
133 var t = setInterval(function () { tick(function (n) { return n + 1; }); }, 1000);
134 return function () { clearInterval(t); };
135 }, []);
136
137 return el(Fragment, null,
138 el(InspectorControls, null,
139 el(PanelBody, { title: __('Content', 'blockenberg'), initialOpen: true },
140 ),
141 el(PanelBody, { title: __('Clock Settings', 'blockenberg'), initialOpen: false },
142 el(RangeControl, {
143 label: __('Clock Size (px)', 'blockenberg'),
144 value: a.clockSize, min: 100, max: 500,
145 onChange: function (v) { setAttributes({ clockSize: v }); }
146 }),
147 el(SelectControl, {
148 label: __('Clock Style', 'blockenberg'),
149 value: a.clockStyle,
150 options: [
151 { label: 'Classic', value: 'classic' },
152 { label: 'Minimal', value: 'minimal' },
153 { label: 'Bold', value: 'bold' }
154 ],
155 onChange: function (v) { setAttributes({ clockStyle: v }); }
156 }),
157 el(SelectControl, {
158 label: __('Timezone', 'blockenberg'),
159 value: a.timezone,
160 options: TIMEZONES,
161 onChange: function (v) { setAttributes({ timezone: v }); }
162 }),
163 el(ToggleControl, { __nextHasNoMarginBottom: true, label: __('Show Numbers', 'blockenberg'), checked: a.showNumbers, onChange: function (v) { setAttributes({ showNumbers: v }); } }),
164 el(ToggleControl, { __nextHasNoMarginBottom: true, label: __('Show Tick Marks', 'blockenberg'), checked: a.showTicks, onChange: function (v) { setAttributes({ showTicks: v }); } }),
165 el(ToggleControl, { __nextHasNoMarginBottom: true, label: __('Show Second Hand', 'blockenberg'), checked: a.showSecondHand, onChange: function (v) { setAttributes({ showSecondHand: v }); } }),
166 el(ToggleControl, { __nextHasNoMarginBottom: true, label: __('Show Date Below', 'blockenberg'), checked: a.showDate, onChange: function (v) { setAttributes({ showDate: v }); } }),
167 el(ToggleControl, { __nextHasNoMarginBottom: true, label: __('Show Digital Time', 'blockenberg'), checked: a.showDigitalTime, onChange: function (v) { setAttributes({ showDigitalTime: v }); } })
168 ),
169
170 el( PanelBody, { title: __( 'Typography', 'blockenberg' ), initialOpen: false },
171 el(getTypographyControl(), { label: __('Title Typography', 'blockenberg'), value: a.titleTypo || {}, onChange: function (v) { setAttributes({ titleTypo: v }); } }),
172 el(getTypographyControl(), { label: __('Subtitle Typography', 'blockenberg'), value: a.subtitleTypo || {}, onChange: function (v) { setAttributes({ subtitleTypo: v }); } })
173 ),
174 el(PanelColorSettings, {
175 title: __('Colors', 'blockenberg'), initialOpen: false,
176 colorSettings: [
177 { label: __('Clock Face', 'blockenberg'), value: a.clockFace, onChange: function (v) { setAttributes({ clockFace: v || '#ffffff' }); } },
178 { label: __('Clock Border', 'blockenberg'), value: a.clockBorder, onChange: function (v) { setAttributes({ clockBorder: v || '#1e1b4b' }); } },
179 { label: __('Hour Hand', 'blockenberg'), value: a.hourHandColor, onChange: function (v) { setAttributes({ hourHandColor: v || '#1e1b4b' }); } },
180 { label: __('Minute Hand', 'blockenberg'), value: a.minuteHandColor, onChange: function (v) { setAttributes({ minuteHandColor: v || '#374151' }); } },
181 { label: __('Second Hand', 'blockenberg'), value: a.secondHandColor, onChange: function (v) { setAttributes({ secondHandColor: v || '#ef4444' }); } },
182 { label: __('Tick Marks', 'blockenberg'), value: a.tickColor, onChange: function (v) { setAttributes({ tickColor: v || '#374151' }); } },
183 { label: __('Numbers', 'blockenberg'), value: a.numberColor, onChange: function (v) { setAttributes({ numberColor: v || '#1e1b4b' }); } },
184 { label: __('Center Dot', 'blockenberg'), value: a.centerDotColor, onChange: function (v) { setAttributes({ centerDotColor: v || '#ef4444' }); } },
185 { label: __('Section Background', 'blockenberg'), value: a.sectionBg, onChange: function (v) { setAttributes({ sectionBg: v || '' }); } },
186 { label: __('Title Color', 'blockenberg'), value: a.titleColor, onChange: function (v) { setAttributes({ titleColor: v || '#1e1b4b' }); } }
187 ]
188 })
189 ),
190 el('div', (function () { var p = blockProps; var _tv = getTypoCssVars(); var s = Object.assign({}, p.style || {}); Object.assign(s, _tv(a.titleTypo || {}, '--bkbg-clk-title-')); Object.assign(s, _tv(a.subtitleTypo || {}, '--bkbg-clk-subtitle-')); p.style = s; return p; })(),
191 a.title && el(RichText, {
192 tagName: 'h3', className: 'bkbg-clk-title',
193 value: a.title, onChange: function (v) { setAttributes({ title: v }); },
194 placeholder: __('Clock Title (optional)', 'blockenberg'),
195 style: { color: a.titleColor, margin: '0 0 4px' }
196 }),
197 (!a.title) && el(RichText, {
198 tagName: 'h3', className: 'bkbg-clk-title',
199 value: a.title, onChange: function (v) { setAttributes({ title: v }); },
200 placeholder: __('Clock Title (optional)', 'blockenberg'),
201 style: { color: a.titleColor, margin: '0 0 4px' }
202 }),
203 a.subtitle && el(RichText, {
204 tagName: 'p', className: 'bkbg-clk-subtitle',
205 value: a.subtitle, onChange: function (v) { setAttributes({ subtitle: v }); },
206 placeholder: __('Subtitle (optional)', 'blockenberg'),
207 style: { color: a.titleColor + 'bb', margin: '0 0 12px' }
208 }),
209 el('div', { style: { display: 'flex', justifyContent: 'center' } },
210 el(ClockFace, a)
211 ),
212 a.showDate && el('div', { style: { marginTop: 10, fontSize: 15, fontWeight: 600, color: a.titleColor } },
213 new Date().toLocaleDateString(undefined, { weekday: 'long', year: 'numeric', month: 'long', day: 'numeric' })
214 ),
215 a.showDigitalTime && el('div', { style: { marginTop: 6, fontSize: 22, fontWeight: 700, fontFamily: 'monospace', color: a.titleColor } },
216 new Date().toLocaleTimeString()
217 )
218 )
219 );
220 }
221
222 registerBlockType('blockenberg/analog-clock', {
223 edit: EditorPreview,
224 save: function (props) {
225 var a = props.attributes;
226 return el('div', useBlockProps.save(),
227 el('div', { className: 'bkbg-clk-app', 'data-opts': JSON.stringify(a) },
228 el(RichText.Content, { tagName: 'h3', className: 'bkbg-clk-title', value: a.title }),
229 el(RichText.Content, { tagName: 'p', className: 'bkbg-clk-subtitle', value: a.subtitle })
230 )
231 );
232 }
233 });
234 }() );
235