| 1 |
( function () { |
| 2 |
var el = React.createElement; |
| 3 |
var registerBlockType = wp.blocks.registerBlockType; |
| 4 |
var useBlockProps = wp.blockEditor.useBlockProps; |
| 5 |
var InspectorControls = wp.blockEditor.InspectorControls; |
| 6 |
var MediaUpload = wp.blockEditor.MediaUpload; |
| 7 |
var MediaUploadCheck = wp.blockEditor.MediaUploadCheck; |
| 8 |
var PanelBody = wp.components.PanelBody; |
| 9 |
var RangeControl = wp.components.RangeControl; |
| 10 |
var SelectControl = wp.components.SelectControl; |
| 11 |
var TextControl = wp.components.TextControl; |
| 12 |
var TextareaControl = wp.components.TextareaControl; |
| 13 |
var ToggleControl = wp.components.ToggleControl; |
| 14 |
var Button = wp.components.Button; |
| 15 |
var PanelColorSettings = wp.blockEditor.PanelColorSettings; |
| 16 |
|
| 17 |
var _csTC, _csTV; |
| 18 |
function _tc() { return _csTC || (_csTC = window.bkbgTypographyControl); } |
| 19 |
function _tv(typo, prefix) { return _csTV ? _csTV(typo, prefix) : ((_csTV = window.bkbgTypoCssVars) ? _csTV(typo, prefix) : {}); } |
| 20 |
|
| 21 |
var IDLE_MODES = [ |
| 22 |
{ value: 'center', label: 'Center of section' }, |
| 23 |
{ value: 'full', label: 'Reveal all (no dark)' }, |
| 24 |
{ value: 'dark', label: 'Fully dark' } |
| 25 |
]; |
| 26 |
|
| 27 |
registerBlockType('blockenberg/cursor-spotlight', { |
| 28 |
title: 'Cursor Spotlight', |
| 29 |
icon: 'visibility', |
| 30 |
category: 'bkbg-effects', |
| 31 |
|
| 32 |
edit: function (props) { |
| 33 |
var attr = props.attributes; var setAttr = props.setAttributes; |
| 34 |
|
| 35 |
// Idle "center" spotlight position for editor preview |
| 36 |
var spotR = attr.spotlightSize || 280; |
| 37 |
var blur = attr.spotlightBlur || 40; |
| 38 |
var mask = 'radial-gradient(circle ' + spotR + 'px at 50% 50%, ' + |
| 39 |
(attr.spotColor || '#fff') + ' 0%, transparent ' + (spotR + blur) + 'px)'; |
| 40 |
var dimRgb = hexToRgbStr(attr.dimColor || '#000'); |
| 41 |
var dimOverlay = 'rgba(' + dimRgb + ',' + (attr.dimOpacity || 0.92) + ')'; |
| 42 |
|
| 43 |
return el(React.Fragment, null, |
| 44 |
el(InspectorControls, null, |
| 45 |
el(PanelBody, { title: 'Content', initialOpen: true }, |
| 46 |
el(SelectControl, { __nextHasNoMarginBottom: true, label: 'Heading Tag', value: attr.tag, options: ['h1','h2','h3','h4','h5','h6'].map(function(t){return{value:t,label:t.toUpperCase()};}), onChange: function(v){ setAttr({tag:v}); } }), |
| 47 |
el(TextControl, { __nextHasNoMarginBottom: true, label: 'Heading', value: attr.heading, onChange: function(v){ setAttr({heading:v}); } }), |
| 48 |
el(TextareaControl,{ __nextHasNoMarginBottom: true, label: 'Subtext', value: attr.subtext, onChange: function(v){ setAttr({subtext:v}); } }), |
| 49 |
el(ToggleControl, { __nextHasNoMarginBottom: true, label: 'Show Hint Text', checked: attr.showHint, onChange: function(v){ setAttr({showHint:v}); } }), |
| 50 |
attr.showHint && el(TextControl, { __nextHasNoMarginBottom: true, label: 'Hint', value: attr.hintText, onChange: function(v){ setAttr({hintText:v}); } }) |
| 51 |
), |
| 52 |
el(PanelBody, { title: 'Spotlight', initialOpen: true }, |
| 53 |
el(RangeControl, { __nextHasNoMarginBottom: true, label: 'Spotlight Size (px)', value: attr.spotlightSize, min: 60, max: 800, onChange: function(v){ setAttr({spotlightSize:v}); } }), |
| 54 |
el(RangeControl, { __nextHasNoMarginBottom: true, label: 'Edge Blur (px)', value: attr.spotlightBlur, min: 0, max: 200, onChange: function(v){ setAttr({spotlightBlur:v}); } }), |
| 55 |
el(RangeControl, { __nextHasNoMarginBottom: true, label: 'Dim Opacity', value: attr.dimOpacity, min: 0.1, max: 1, step: 0.05, onChange: function(v){ setAttr({dimOpacity:v}); } }), |
| 56 |
el(SelectControl, { __nextHasNoMarginBottom: true, label: 'Idle Mode', value: attr.idleMode, options: IDLE_MODES, onChange: function(v){ setAttr({idleMode:v}); } }), |
| 57 |
el(ToggleControl, { __nextHasNoMarginBottom: true, label: 'Smooth Follow', checked: attr.followSmooth, onChange: function(v){ setAttr({followSmooth:v}); } }) |
| 58 |
), |
| 59 |
el(PanelBody, { title: 'Section Size', initialOpen: false }, |
| 60 |
el(RangeControl, { __nextHasNoMarginBottom: true, label: 'Section Height (px)', value: attr.sectionHeight, min: 200, max: 1200, onChange: function(v){ setAttr({sectionHeight:v}); } }), |
| 61 |
el(RangeControl, { __nextHasNoMarginBottom: true, label: 'Border Radius (px)', value: attr.borderRadius, min: 0, max: 48, onChange: function(v){ setAttr({borderRadius:v}); } }) |
| 62 |
), |
| 63 |
el(PanelBody, { title: 'Typography', initialOpen: false }, |
| 64 |
_tc() && el(_tc(), { label: 'Heading', typo: attr.typoHeading || {}, onChange: function(v) { setAttr({ typoHeading: v }); } }), |
| 65 |
_tc() && el(_tc(), { label: 'Subtext', typo: attr.typoSubtext || {}, onChange: function(v) { setAttr({ typoSubtext: v }); } }), |
| 66 |
el(SelectControl, { __nextHasNoMarginBottom: true, label: 'Text Align', value: attr.textAlign, options: [{value:'left',label:'Left'},{value:'center',label:'Center'},{value:'right',label:'Right'}], onChange: function(v){ setAttr({textAlign:v}); } }) |
| 67 |
), |
| 68 |
el(PanelBody, { title: 'Background Image', initialOpen: false }, |
| 69 |
el(MediaUploadCheck, null, |
| 70 |
el(MediaUpload, { |
| 71 |
onSelect: function(m){ setAttr({bgImage:m.url,bgImageId:m.id}); }, |
| 72 |
allowedTypes: ['image'], |
| 73 |
value: attr.bgImageId, |
| 74 |
render: function(r){ return el('div', null, |
| 75 |
attr.bgImage ? el(Button, {variant:'secondary',isSmall:true,onClick:r.open},'Change BG Image') : el(Button,{variant:'primary',onClick:r.open},'Select BG Image'), |
| 76 |
attr.bgImage && el(Button,{variant:'tertiary',isSmall:true,isDestructive:true,style:{marginLeft:8},onClick:function(){setAttr({bgImage:'',bgImageId:0});}},'Remove') |
| 77 |
); } |
| 78 |
}) |
| 79 |
), |
| 80 |
attr.bgImage && el(RangeControl, { __nextHasNoMarginBottom: true, label: 'BG Image Opacity', value: attr.bgImageOpacity, min: 0, max: 1, step: 0.05, onChange: function(v){ setAttr({bgImageOpacity:v}); } }) |
| 81 |
), |
| 82 |
el(PanelColorSettings, { |
| 83 |
title: 'Colors', initialOpen: false, |
| 84 |
colorSettings: [ |
| 85 |
{ value: attr.bgColor, onChange: function(v){ setAttr({bgColor: v||'#0c0a1e'}); }, label: 'Section Background' }, |
| 86 |
{ value: attr.dimColor, onChange: function(v){ setAttr({dimColor: v||'#000000'}); }, label: 'Dim Color' }, |
| 87 |
{ value: attr.spotColor, onChange: function(v){ setAttr({spotColor: v||'#ffffff'}); }, label: 'Spotlight Color' }, |
| 88 |
{ value: attr.textColor, onChange: function(v){ setAttr({textColor: v||'#ffffff'}); }, label: 'Text Color' }, |
| 89 |
{ value: attr.accentColor,onChange: function(v){ setAttr({accentColor:v||'#a78bfa'}); }, label: 'Accent Color' } |
| 90 |
] |
| 91 |
}) |
| 92 |
), |
| 93 |
|
| 94 |
el('div', useBlockProps(), |
| 95 |
el('div', { |
| 96 |
className: 'bkbg-cs-editor-preview', |
| 97 |
style: Object.assign({ |
| 98 |
position: 'relative', |
| 99 |
height: (attr.sectionHeight || 500) + 'px', |
| 100 |
borderRadius: (attr.borderRadius || 16) + 'px', |
| 101 |
overflow: 'hidden', |
| 102 |
backgroundColor: attr.bgColor || '#0c0a1e', |
| 103 |
display: 'flex', alignItems: 'center', justifyContent: 'center' |
| 104 |
}, |
| 105 |
{ '--bkbg-cs-hdg-fs': (attr.fontSize || 48) + 'px', '--bkbg-cs-hdg-fw': attr.fontWeight || '800', '--bkbg-cs-sub-fs': (attr.subtextSize || 18) + 'px' }, |
| 106 |
_tv(attr.typoHeading, '--bkbg-cs-hdg-'), |
| 107 |
_tv(attr.typoSubtext, '--bkbg-cs-sub-')) |
| 108 |
}, |
| 109 |
// BG image |
| 110 |
attr.bgImage && el('img', { src: attr.bgImage, style: { position:'absolute',inset:0,width:'100%',height:'100%',objectFit:'cover',opacity:attr.bgImageOpacity||0.5 } }), |
| 111 |
// Dark overlay |
| 112 |
el('div', { style: { position:'absolute',inset:0, background: dimOverlay, maskImage: mask, WebkitMaskImage: mask } }), |
| 113 |
// Content |
| 114 |
el('div', { |
| 115 |
style: { position:'relative', zIndex:2, textAlign:attr.textAlign||'center', padding:'32px', color: attr.textColor||'#fff' } |
| 116 |
}, |
| 117 |
el(attr.tag||'h2', { className: 'bkbg-cs-heading', style: { margin:0,color:attr.textColor||'#fff' } }, attr.heading), |
| 118 |
attr.subtext && el('p', { className: 'bkbg-cs-subtext', style: { marginTop:16,opacity:0.75,color:attr.textColor||'#fff' } }, attr.subtext), |
| 119 |
attr.showHint && el('p', { style: { marginTop:24,fontSize:13,color:attr.accentColor||'#a78bfa',opacity:0.8,letterSpacing:'0.1em',textTransform:'uppercase' } }, '↖ ' + (attr.hintText||'Move cursor to reveal') + ' ↗') |
| 120 |
) |
| 121 |
) |
| 122 |
) |
| 123 |
); |
| 124 |
}, |
| 125 |
|
| 126 |
save: function (props) { |
| 127 |
return el('div', useBlockProps.save(), |
| 128 |
el('div', { className:'bkbg-cs-app', 'data-opts':JSON.stringify(props.attributes) }) |
| 129 |
); |
| 130 |
} |
| 131 |
}); |
| 132 |
|
| 133 |
function hexToRgbStr(hex) { |
| 134 |
hex = hex.replace(/^#/, ''); |
| 135 |
if (hex.length === 3) hex = hex.split('').map(function(c){return c+c;}).join(''); |
| 136 |
var n = parseInt(hex, 16); |
| 137 |
return [(n>>16)&255,(n>>8)&255,n&255].join(','); |
| 138 |
} |
| 139 |
}() ); |
| 140 |
|