| 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 |
/* ── lazy typography helpers ── */ |
| 16 |
function _tc() { return window.bkbgTypographyControl || null; } |
| 17 |
Object.defineProperty(window, '__bk3dt_tvf', { get: function () { delete window.__bk3dt_tvf; return (window.__bk3dt_tvf = window.bkbgTypoCssVars || function () { return {}; }); } }); |
| 18 |
function getTypoCssVars(a) { |
| 19 |
return window.__bk3dt_tvf(a.textTypo || {}, '--bk3dt-tx-'); |
| 20 |
} |
| 21 |
|
| 22 |
var STYLES_3D = [ |
| 23 |
{ label: 'Extrude (stacked shadow)', value: 'extrude' }, |
| 24 |
{ label: 'Long shadow', value: 'longshadow' }, |
| 25 |
{ label: 'Retro (outline + shadow)', value: 'retro' }, |
| 26 |
{ label: 'Isometric', value: 'isometric' }, |
| 27 |
{ label: 'Emboss', value: 'emboss' }, |
| 28 |
]; |
| 29 |
var ANIMATIONS = [ |
| 30 |
{ label: 'None', value: 'none' }, |
| 31 |
{ label: 'Float up/down', value: 'float' }, |
| 32 |
{ label: 'Pulse depth', value: 'pulse' }, |
| 33 |
{ label: 'Shimmer', value: 'shimmer' }, |
| 34 |
]; |
| 35 |
var HOVERS = [ |
| 36 |
{ label: 'Tilt (3D rotate)', value: 'tilt' }, |
| 37 |
{ label: 'Press (depth collapse)', value: 'press' }, |
| 38 |
{ label: 'Lift (shadow grows)', value: 'lift' }, |
| 39 |
{ label: 'None', value: 'none' }, |
| 40 |
]; |
| 41 |
var TAGS = [ |
| 42 |
{ label: 'H1', value: 'h1' }, { label: 'H2', value: 'h2' }, { label: 'H3', value: 'h3' }, |
| 43 |
{ label: 'H4', value: 'h4' }, { label: 'p', value: 'p' }, { label: 'div', value: 'div' }, |
| 44 |
]; |
| 45 |
var WEIGHTS = [ |
| 46 |
{ label: '400 Regular', value: '400' }, { label: '600 Semi-Bold', value: '600' }, |
| 47 |
{ label: '700 Bold', value: '700' }, { label: '800 Extra-Bold', value: '800' }, |
| 48 |
{ label: '900 Black', value: '900' }, |
| 49 |
]; |
| 50 |
var TRANSFORMS = [ |
| 51 |
{ label: 'UPPERCASE', value: 'uppercase' }, { label: 'lowercase', value: 'lowercase' }, |
| 52 |
{ label: 'Capitalize', value: 'capitalize' }, { label: 'None', value: 'none' }, |
| 53 |
]; |
| 54 |
var ALIGNS = [ |
| 55 |
{ label: 'Left', value: 'left' }, |
| 56 |
{ label: 'Center', value: 'center' }, |
| 57 |
{ label: 'Right', value: 'right' }, |
| 58 |
]; |
| 59 |
|
| 60 |
/* build CSS text-shadow string for the 3D effect */ |
| 61 |
function make3dShadow(a) { |
| 62 |
var depth = a.depth || 8; |
| 63 |
var angle = (a.angle || 45) * Math.PI / 180; |
| 64 |
var dx = Math.cos(angle); |
| 65 |
var dy = Math.sin(angle); |
| 66 |
var shadows = []; |
| 67 |
|
| 68 |
if (a.style3d === 'extrude') { |
| 69 |
for (var i = 1; i <= depth; i++) { |
| 70 |
shadows.push((dx * i).toFixed(1) + 'px ' + (dy * i).toFixed(1) + 'px 0 ' + a.depthColor); |
| 71 |
} |
| 72 |
shadows.push((dx * depth + 4).toFixed(1) + 'px ' + (dy * depth + 6).toFixed(1) + 'px 8px ' + a.shadowColor); |
| 73 |
} else if (a.style3d === 'longshadow') { |
| 74 |
var steps = depth * 4; |
| 75 |
for (var i = 1; i <= steps; i++) { |
| 76 |
shadows.push(i + 'px ' + i + 'px 0 ' + a.depthColor); |
| 77 |
} |
| 78 |
} else if (a.style3d === 'retro') { |
| 79 |
for (var i = 1; i <= depth; i++) { |
| 80 |
shadows.push(i + 'px ' + i + 'px 0 ' + a.depthColor); |
| 81 |
} |
| 82 |
shadows.push('0 0 0 3px ' + a.depthColor); |
| 83 |
shadows.push((depth + 4) + 'px ' + (depth + 6) + 'px 10px ' + a.shadowColor); |
| 84 |
} else if (a.style3d === 'isometric') { |
| 85 |
for (var i = 1; i <= depth; i++) { |
| 86 |
shadows.push(i + 'px ' + Math.round(i * 0.5) + 'px 0 ' + a.depthColor); |
| 87 |
} |
| 88 |
shadows.push((depth + 3) + 'px ' + Math.round(depth * 0.5 + 4) + 'px 8px ' + a.shadowColor); |
| 89 |
} else if (a.style3d === 'emboss') { |
| 90 |
shadows.push('-1px -1px 2px rgba(255,255,255,0.3)'); |
| 91 |
shadows.push('1px 1px 2px rgba(0,0,0,0.5)'); |
| 92 |
for (var i = 1; i <= depth; i++) { |
| 93 |
shadows.push(i + 'px ' + i + 'px 0 ' + a.depthColor); |
| 94 |
} |
| 95 |
} |
| 96 |
return shadows.join(', '); |
| 97 |
} |
| 98 |
|
| 99 |
function buildTextStyle(a) { |
| 100 |
var ts = make3dShadow(a); |
| 101 |
var style = { |
| 102 |
textAlign: a.textAlign, |
| 103 |
textShadow: ts, |
| 104 |
margin: 0, |
| 105 |
display: 'block', |
| 106 |
cursor: 'default', |
| 107 |
}; |
| 108 |
if (a.gradientText) { |
| 109 |
Object.assign(style, { |
| 110 |
background: 'linear-gradient(135deg, ' + a.gradientFrom + ' 0%, ' + a.gradientTo + ' 100%)', |
| 111 |
WebkitBackgroundClip: 'text', |
| 112 |
WebkitTextFillColor: 'transparent', |
| 113 |
backgroundClip: 'text', |
| 114 |
color: 'transparent', |
| 115 |
}); |
| 116 |
} else { |
| 117 |
style.color = a.textColor; |
| 118 |
} |
| 119 |
return style; |
| 120 |
} |
| 121 |
|
| 122 |
function buildWrapStyle(a) { |
| 123 |
return { |
| 124 |
background: a.showBg ? a.backgroundColor : 'transparent', |
| 125 |
padding: a.paddingV + 'px ' + a.paddingH + 'px', |
| 126 |
borderRadius: a.borderRadius + 'px', |
| 127 |
textAlign: a.textAlign, |
| 128 |
}; |
| 129 |
} |
| 130 |
|
| 131 |
registerBlockType('blockenberg/text-3d', { |
| 132 |
edit: function (props) { |
| 133 |
var a = props.attributes; |
| 134 |
var set = props.setAttributes; |
| 135 |
|
| 136 |
var Tag = a.tag || 'h2'; |
| 137 |
var textStyle = buildTextStyle(a); |
| 138 |
var wrapStyle = buildWrapStyle(a); |
| 139 |
|
| 140 |
var blockProps = useBlockProps((function () { |
| 141 |
var s = getTypoCssVars(a); |
| 142 |
return { style: s }; |
| 143 |
})()); |
| 144 |
|
| 145 |
return el(Fragment, null, |
| 146 |
el(InspectorControls, null, |
| 147 |
/* Text */ |
| 148 |
el(PanelBody, { title: 'Text', initialOpen: true }, |
| 149 |
el(TextControl, { __nextHasNoMarginBottom: true, label: 'Text', value: a.text, onChange: function (v) { set({ text: v }); } }), |
| 150 |
el(SelectControl, { __nextHasNoMarginBottom: true, label: 'HTML tag', value: a.tag, options: TAGS, onChange: function (v) { set({ tag: v }); } }), |
| 151 |
el(SelectControl, { __nextHasNoMarginBottom: true, label: 'Text transform', value: a.textTransform, options: TRANSFORMS, onChange: function (v) { set({ textTransform: v }); } }), |
| 152 |
el(SelectControl, { __nextHasNoMarginBottom: true, label: 'Alignment', value: a.textAlign, options: ALIGNS, onChange: function (v) { set({ textAlign: v }); } }), |
| 153 |
), |
| 154 |
/* 3D Effect */ |
| 155 |
el(PanelBody, { title: '3D Effect', initialOpen: false }, |
| 156 |
el(SelectControl, { __nextHasNoMarginBottom: true, label: '3D style', value: a.style3d, options: STYLES_3D, onChange: function (v) { set({ style3d: v }); } }), |
| 157 |
el(RangeControl, { __nextHasNoMarginBottom: true, label: 'Depth (px)', value: a.depth, min: 1, max: 40, onChange: function (v) { set({ depth: v }); } }), |
| 158 |
el(RangeControl, { __nextHasNoMarginBottom: true, label: 'Shadow angle (°)', value: a.angle, min: 0, max: 360, onChange: function (v) { set({ angle: v }); } }), |
| 159 |
el(ToggleControl, { __nextHasNoMarginBottom: true, label: 'Gradient text fill', checked: a.gradientText, onChange: function (v) { set({ gradientText: v }); } }), |
| 160 |
), |
| 161 |
/* Animation */ |
| 162 |
el(PanelBody, { title: 'Animation', initialOpen: false }, |
| 163 |
el(SelectControl, { __nextHasNoMarginBottom: true, label: 'Idle animation', value: a.animation, options: ANIMATIONS, onChange: function (v) { set({ animation: v }); } }), |
| 164 |
el(SelectControl, { __nextHasNoMarginBottom: true, label: 'Hover effect', value: a.hoverEffect, options: HOVERS, onChange: function (v) { set({ hoverEffect: v }); } }), |
| 165 |
el(ToggleControl, { __nextHasNoMarginBottom: true, label: 'Show reflection', checked: a.showReflection, onChange: function (v) { set({ showReflection: v }); } }), |
| 166 |
), |
| 167 |
/* Layout */ |
| 168 |
el(PanelBody, { title: 'Layout & Background', initialOpen: false }, |
| 169 |
el(ToggleControl, { __nextHasNoMarginBottom: true, label: 'Show background', checked: a.showBg, onChange: function (v) { set({ showBg: v }); } }), |
| 170 |
el(RangeControl, { __nextHasNoMarginBottom: true, label: 'Vertical padding (px)', value: a.paddingV, min: 0, max: 120, onChange: function (v) { set({ paddingV: v }); } }), |
| 171 |
el(RangeControl, { __nextHasNoMarginBottom: true, label: 'Horizontal padding (px)', value: a.paddingH, min: 0, max: 120, onChange: function (v) { set({ paddingH: v }); } }), |
| 172 |
el(RangeControl, { __nextHasNoMarginBottom: true, label: 'Border radius (px)', value: a.borderRadius, min: 0, max: 48, onChange: function (v) { set({ borderRadius: v }); } }), |
| 173 |
), |
| 174 |
/* Colors */ |
| 175 |
|
| 176 |
el( PanelBody, { title: __( 'Typography', 'blockenberg' ), initialOpen: false }, |
| 177 |
_tc() && el(_tc(), { label: __('Text', 'blockenberg'), value: a.textTypo || {}, onChange: function (v) { set({ textTypo: v }); } }) |
| 178 |
), |
| 179 |
el(PanelColorSettings, { |
| 180 |
title: 'Colors', |
| 181 |
initialOpen: false, |
| 182 |
colorSettings: [ |
| 183 |
{ value: a.textColor, onChange: function (v) { set({ textColor: v || '#6366f1' }); }, label: 'Text color' }, |
| 184 |
{ value: a.depthColor, onChange: function (v) { set({ depthColor: v || '#312e81' }); }, label: 'Depth / extrude color' }, |
| 185 |
{ value: a.shadowColor, onChange: function (v) { set({ shadowColor: v || 'rgba(0,0,0,0.25)' }); }, label: 'Drop shadow color' }, |
| 186 |
{ value: a.backgroundColor, onChange: function (v) { set({ backgroundColor: v || '#0f172a' }); }, label: 'Background' }, |
| 187 |
{ value: a.gradientFrom, onChange: function (v) { set({ gradientFrom: v || '#a78bfa' }); }, label: 'Gradient start' }, |
| 188 |
{ value: a.gradientTo, onChange: function (v) { set({ gradientTo: v || '#60a5fa' }); }, label: 'Gradient end' }, |
| 189 |
], |
| 190 |
}), |
| 191 |
), |
| 192 |
el('div', blockProps, |
| 193 |
el('div', { style: wrapStyle }, |
| 194 |
el(Tag, { className: 'bkbg-3dt-text', style: textStyle }, a.text || '3D TEXT'), |
| 195 |
a.showReflection && el(Tag, { |
| 196 |
className: 'bkbg-3dt-text bkbg-3dt-reflection', |
| 197 |
style: Object.assign({}, textStyle, { |
| 198 |
transform: 'scaleY(-1)', |
| 199 |
opacity: 0.18, |
| 200 |
marginTop: '4px', |
| 201 |
maskImage: 'linear-gradient(to bottom, rgba(0,0,0,0.5), transparent 70%)', |
| 202 |
WebkitMaskImage: 'linear-gradient(to bottom, rgba(0,0,0,0.5), transparent 70%)', |
| 203 |
display: 'block', |
| 204 |
pointerEvents: 'none', |
| 205 |
}), |
| 206 |
}, a.text || '3D TEXT') |
| 207 |
) |
| 208 |
) |
| 209 |
); |
| 210 |
}, |
| 211 |
save: function (props) { |
| 212 |
var a = props.attributes; |
| 213 |
var sv = getTypoCssVars(a); |
| 214 |
return el('div', useBlockProps.save(), |
| 215 |
el('div', { className: 'bkbg-3dt-app', 'data-opts': JSON.stringify(a), style: sv }) |
| 216 |
); |
| 217 |
}, |
| 218 |
}); |
| 219 |
}() ); |
| 220 |
|