# blockenberg/2.0.7/blocks/analog-clock/index.js

Blockenberg — 600+ Advanced Gutenberg Blocks &amp; AI Agent for WordPress Block Editor, version 2.0.7. 235 lines.

- Page: https://pluginprobe.com/plugins/blockenberg/2.0.7/code/blocks/analog-clock/index.js
- Raw: https://pluginprobe.com/plugins/blockenberg/2.0.7/raw/blocks/analog-clock/index.js
- Modified: 2026-03-06T12:32:40+00:00

Line numbers below start at 1. Link to a line or a range by appending a fragment to the
page URL, for example `https://pluginprobe.com/plugins/blockenberg/2.0.7/code/blocks/analog-clock/index.js#L10-L20`.

```javascript
( function () {
    var el = wp.element.createElement;
    var useState = wp.element.useState;
    var useEffect = wp.element.useEffect;
    var Fragment = wp.element.Fragment;
    var registerBlockType = wp.blocks.registerBlockType;
    var __ = wp.i18n.__;
    var InspectorControls = wp.blockEditor.InspectorControls;
    var PanelColorSettings = wp.blockEditor.PanelColorSettings;
    var useBlockProps = wp.blockEditor.useBlockProps;
    var RichText = wp.blockEditor.RichText;
    var PanelBody = wp.components.PanelBody;
    var RangeControl = wp.components.RangeControl;
    var ToggleControl = wp.components.ToggleControl;
    var SelectControl = wp.components.SelectControl;

    var _TypographyControl, _typoCssVars;
    function getTypographyControl() { return _TypographyControl || (_TypographyControl = window.bkbgTypographyControl); }
    function getTypoCssVars() { return _typoCssVars || (_typoCssVars = window.bkbgTypoCssVars); }

    var TIMEZONES = [
        { label: 'Local (device)', value: 'local' },
        { label: 'UTC', value: 'UTC' },
        { label: 'New York (ET)', value: 'America/New_York' },
        { label: 'Chicago (CT)', value: 'America/Chicago' },
        { label: 'Los Angeles (PT)', value: 'America/Los_Angeles' },
        { label: 'London (GMT/BST)', value: 'Europe/London' },
        { label: 'Paris (CET)', value: 'Europe/Paris' },
        { label: 'Berlin (CET)', value: 'Europe/Berlin' },
        { label: 'Moscow (MSK)', value: 'Europe/Moscow' },
        { label: 'Dubai (GST)', value: 'Asia/Dubai' },
        { label: 'Mumbai (IST)', value: 'Asia/Kolkata' },
        { label: 'Bangkok (ICT)', value: 'Asia/Bangkok' },
        { label: 'Singapore (SGT)', value: 'Asia/Singapore' },
        { label: 'Tokyo (JST)', value: 'Asia/Tokyo' },
        { label: 'Sydney (AEST)', value: 'Australia/Sydney' }
    ];

    function ClockFace(props) {
        var a = props;
        var now = new Date();
        var h  = now.getHours()   % 12;
        var m  = now.getMinutes();
        var s  = now.getSeconds();

        var r  = 46; // radius within 100-unit viewBox
        var cx = 50, cy = 50;

        var hAngle   = (h * 30) + (m * 0.5); // degrees, 0 at top
        var mAngle   = m * 6;
        var sAngle   = s * 6;

        function toRad(deg) { return (deg - 90) * Math.PI / 180; }
        function handEnd(angle, length) {
            return { x: cx + length * Math.cos(toRad(angle)), y: cy + length * Math.sin(toRad(angle)) };
        }

        var hEnd = handEnd(hAngle, 28);
        var mEnd = handEnd(mAngle, 36);
        var sEnd = handEnd(sAngle, 40);

        // Tick marks
        var ticks = [];
        for (var i = 0; i < 60; i++) {
            var isBig = i % 5 === 0;
            var ang = (i * 6 - 90) * Math.PI / 180;
            var innerR = isBig ? r - 8 : r - 5;
            ticks.push(el('line', {
                key: i,
                x1: cx + innerR * Math.cos(ang), y1: cy + innerR * Math.sin(ang),
                x2: cx + r  * Math.cos(ang),     y2: cy + r  * Math.sin(ang),
                stroke: a.tickColor, strokeWidth: isBig ? 2 : 0.8,
                strokeLinecap: 'round'
            }));
        }

        // Hour numbers
        var numbers = [];
        if (a.showNumbers) {
            for (var j = 1; j <= 12; j++) {
                var nAng = ((j * 30) - 90) * Math.PI / 180;
                numbers.push(el('text', {
                    key: 'n' + j,
                    x: cx + (r - 15) * Math.cos(nAng),
                    y: cy + (r - 15) * Math.sin(nAng),
                    textAnchor: 'middle', dominantBaseline: 'middle',
                    fontSize: 7, fontWeight: 700, fill: a.numberColor,
                    fontFamily: 'system-ui'
                }, j));
            }
        }

        var sz = a.clockSize || 240;
        var borderW = a.clockStyle === 'minimal' ? 2 : a.clockStyle === 'bold' ? 8 : 4;

        return el('svg', {
            width: sz, height: sz,
            viewBox: '0 0 100 100',
            style: { display: 'block', maxWidth: '100%' }
        },
            // Face
            el('circle', { cx: cx, cy: cy, r: 49, fill: a.clockBorder }),
            el('circle', { cx: cx, cy: cy, r: 49 - borderW, fill: a.clockFace }),

            // Ticks
            a.showTicks && ticks,

            // Numbers
            numbers,

            // Hour hand
            el('line', { x1: cx, y1: cy, x2: hEnd.x, y2: hEnd.y, stroke: a.hourHandColor, strokeWidth: 3.5, strokeLinecap: 'round' }),
            // Minute hand
            el('line', { x1: cx, y1: cy, x2: mEnd.x, y2: mEnd.y, stroke: a.minuteHandColor, strokeWidth: 2.5, strokeLinecap: 'round' }),
            // Second hand
            a.showSecondHand && el('line', { x1: cx, y1: cy, x2: sEnd.x, y2: sEnd.y, stroke: a.secondHandColor, strokeWidth: 1.5, strokeLinecap: 'round' }),
            // Counter weight
            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' }),
            // Center dot
            el('circle', { cx: cx, cy: cy, r: 3, fill: a.centerDotColor }),
            el('circle', { cx: cx, cy: cy, r: 1.5, fill: '#fff' })
        );
    }

    function EditorPreview(props) {
        var a = props.attributes;
        var setAttributes = props.setAttributes;
        var blockProps = useBlockProps({ style: { background: a.sectionBg || 'transparent', padding: '28px 20px', textAlign: 'center' } });
        var state = useState(0);
        var tick  = state[1];

        useEffect(function () {
            var t = setInterval(function () { tick(function (n) { return n + 1; }); }, 1000);
            return function () { clearInterval(t); };
        }, []);

        return el(Fragment, null,
            el(InspectorControls, null,
                el(PanelBody, { title: __('Content', 'blockenberg'), initialOpen: true },
                    ),
                el(PanelBody, { title: __('Clock Settings', 'blockenberg'), initialOpen: false },
                    el(RangeControl, {
                        label: __('Clock Size (px)', 'blockenberg'),
                        value: a.clockSize, min: 100, max: 500,
                        onChange: function (v) { setAttributes({ clockSize: v }); }
                    }),
                    el(SelectControl, {
                        label: __('Clock Style', 'blockenberg'),
                        value: a.clockStyle,
                        options: [
                            { label: 'Classic', value: 'classic' },
                            { label: 'Minimal', value: 'minimal' },
                            { label: 'Bold', value: 'bold' }
                        ],
                        onChange: function (v) { setAttributes({ clockStyle: v }); }
                    }),
                    el(SelectControl, {
                        label: __('Timezone', 'blockenberg'),
                        value: a.timezone,
                        options: TIMEZONES,
                        onChange: function (v) { setAttributes({ timezone: v }); }
                    }),
                    el(ToggleControl, { __nextHasNoMarginBottom: true, label: __('Show Numbers', 'blockenberg'), checked: a.showNumbers, onChange: function (v) { setAttributes({ showNumbers: v }); } }),
                    el(ToggleControl, { __nextHasNoMarginBottom: true, label: __('Show Tick Marks', 'blockenberg'), checked: a.showTicks, onChange: function (v) { setAttributes({ showTicks: v }); } }),
                    el(ToggleControl, { __nextHasNoMarginBottom: true, label: __('Show Second Hand', 'blockenberg'), checked: a.showSecondHand, onChange: function (v) { setAttributes({ showSecondHand: v }); } }),
                    el(ToggleControl, { __nextHasNoMarginBottom: true, label: __('Show Date Below', 'blockenberg'), checked: a.showDate, onChange: function (v) { setAttributes({ showDate: v }); } }),
                    el(ToggleControl, { __nextHasNoMarginBottom: true, label: __('Show Digital Time', 'blockenberg'), checked: a.showDigitalTime, onChange: function (v) { setAttributes({ showDigitalTime: v }); } })
                ),
                
                el( PanelBody, { title: __( 'Typography', 'blockenberg' ), initialOpen: false },
                    el(getTypographyControl(), { label: __('Title Typography', 'blockenberg'), value: a.titleTypo || {}, onChange: function (v) { setAttributes({ titleTypo: v }); } }),
                    el(getTypographyControl(), { label: __('Subtitle Typography', 'blockenberg'), value: a.subtitleTypo || {}, onChange: function (v) { setAttributes({ subtitleTypo: v }); } })
                ),
el(PanelColorSettings, {
                    title: __('Colors', 'blockenberg'), initialOpen: false,
                    colorSettings: [
                        { label: __('Clock Face', 'blockenberg'), value: a.clockFace, onChange: function (v) { setAttributes({ clockFace: v || '#ffffff' }); } },
                        { label: __('Clock Border', 'blockenberg'), value: a.clockBorder, onChange: function (v) { setAttributes({ clockBorder: v || '#1e1b4b' }); } },
                        { label: __('Hour Hand', 'blockenberg'), value: a.hourHandColor, onChange: function (v) { setAttributes({ hourHandColor: v || '#1e1b4b' }); } },
                        { label: __('Minute Hand', 'blockenberg'), value: a.minuteHandColor, onChange: function (v) { setAttributes({ minuteHandColor: v || '#374151' }); } },
                        { label: __('Second Hand', 'blockenberg'), value: a.secondHandColor, onChange: function (v) { setAttributes({ secondHandColor: v || '#ef4444' }); } },
                        { label: __('Tick Marks', 'blockenberg'), value: a.tickColor, onChange: function (v) { setAttributes({ tickColor: v || '#374151' }); } },
                        { label: __('Numbers', 'blockenberg'), value: a.numberColor, onChange: function (v) { setAttributes({ numberColor: v || '#1e1b4b' }); } },
                        { label: __('Center Dot', 'blockenberg'), value: a.centerDotColor, onChange: function (v) { setAttributes({ centerDotColor: v || '#ef4444' }); } },
                        { label: __('Section Background', 'blockenberg'), value: a.sectionBg, onChange: function (v) { setAttributes({ sectionBg: v || '' }); } },
                        { label: __('Title Color', 'blockenberg'), value: a.titleColor, onChange: function (v) { setAttributes({ titleColor: v || '#1e1b4b' }); } }
                    ]
                })
            ),
            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; })(),
                a.title && el(RichText, {
                    tagName: 'h3', className: 'bkbg-clk-title',
                    value: a.title, onChange: function (v) { setAttributes({ title: v }); },
                    placeholder: __('Clock Title (optional)', 'blockenberg'),
                    style: { color: a.titleColor, margin: '0 0 4px' }
                }),
                (!a.title) && el(RichText, {
                    tagName: 'h3', className: 'bkbg-clk-title',
                    value: a.title, onChange: function (v) { setAttributes({ title: v }); },
                    placeholder: __('Clock Title (optional)', 'blockenberg'),
                    style: { color: a.titleColor, margin: '0 0 4px' }
                }),
                a.subtitle && el(RichText, {
                    tagName: 'p', className: 'bkbg-clk-subtitle',
                    value: a.subtitle, onChange: function (v) { setAttributes({ subtitle: v }); },
                    placeholder: __('Subtitle (optional)', 'blockenberg'),
                    style: { color: a.titleColor + 'bb', margin: '0 0 12px' }
                }),
                el('div', { style: { display: 'flex', justifyContent: 'center' } },
                    el(ClockFace, a)
                ),
                a.showDate && el('div', { style: { marginTop: 10, fontSize: 15, fontWeight: 600, color: a.titleColor } },
                    new Date().toLocaleDateString(undefined, { weekday: 'long', year: 'numeric', month: 'long', day: 'numeric' })
                ),
                a.showDigitalTime && el('div', { style: { marginTop: 6, fontSize: 22, fontWeight: 700, fontFamily: 'monospace', color: a.titleColor } },
                    new Date().toLocaleTimeString()
                )
            )
        );
    }

    registerBlockType('blockenberg/analog-clock', {
        edit: EditorPreview,
        save: function (props) {
            var a = props.attributes;
            return el('div', useBlockProps.save(),
                el('div', { className: 'bkbg-clk-app', 'data-opts': JSON.stringify(a) },
                    el(RichText.Content, { tagName: 'h3', className: 'bkbg-clk-title', value: a.title }),
                    el(RichText.Content, { tagName: 'p', className: 'bkbg-clk-subtitle', value: a.subtitle })
                )
            );
        }
    });
}() );

```
