PluginProbe
Blockenberg — 600+ Advanced Gutenberg Blocks & AI Agent for WordPress Block Editor / 2.0.7
Blockenberg — 600+ Advanced Gutenberg Blocks & AI Agent for WordPress Block Editor v2.0.7
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 / handwriting-text / index.js

index.js in Blockenberg — 600+ Advanced Gutenberg Blocks & AI Agent for WordPress Block Editor 2.0.7, at blocks/handwriting-text/index.js

218 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 __ = wp.i18n.__;
4 var registerBlockType = wp.blocks.registerBlockType;
5 var useBlockProps = wp.blockEditor.useBlockProps;
6 var InspectorControls = wp.blockEditor.InspectorControls;
7 var PanelColorSettings = wp.blockEditor.PanelColorSettings;
8 var PanelBody = wp.components.PanelBody;
9 var TextControl = wp.components.TextControl;
10 var ToggleControl = wp.components.ToggleControl;
11 var RangeControl = wp.components.RangeControl;
12 var SelectControl = wp.components.SelectControl;
13
14 /* ── typography lazy-getters ── */
15 function _tc() { return window.bkbgTypographyControl || null; }
16 function _tv() { return window.bkbgTypoCssVars || function () { return {}; }; }
17
18 /* ── Build editor SVG preview ── */
19 function buildEditorSVG(attr) {
20 var W = attr.svgWidth, H = attr.svgHeight;
21 var pathId = 'bkbg-hw-ul-' + Math.random().toString(36).slice(2, 5);
22
23 return el('svg', {
24 viewBox: '0 0 ' + W + ' ' + H,
25 width: '100%',
26 height: H,
27 xmlns: 'http://www.w3.org/2000/svg',
28 style: { display: 'block', overflow: 'visible', maxWidth: W + 'px',
29 margin: attr.align2 === 'center' ? '0 auto' : attr.align2 === 'right' ? '0 0 0 auto' : '0' }
30 },
31 el('text', {
32 className: 'bkbg-hw-text',
33 x: attr.textX + '%',
34 y: attr.textY,
35 textAnchor: attr.textAnchor,
36 fill: 'none',
37 stroke: attr.strokeColor,
38 strokeWidth: attr.strokeWidth,
39 strokeDasharray: '8 4',
40 style: { opacity: 0.85 }
41 }, attr.text),
42 /* Show fill text underneath to approximate "drawn" look in editor */
43 el('text', {
44 className: 'bkbg-hw-text',
45 x: attr.textX + '%',
46 y: attr.textY,
47 textAnchor: attr.textAnchor,
48 style: { opacity: 0.35, fill: attr.textColor }
49 }, attr.text),
50 attr.showUnderline && el('path', {
51 id: pathId,
52 d: 'M ' + (attr.textX - 30) + ' ' + (attr.textY + attr.underlineOffsetY) + ' L ' + (attr.textX + 30) + ' ' + (attr.textY + attr.underlineOffsetY),
53 fill: 'none',
54 stroke: attr.underlineColor,
55 strokeWidth: attr.underlineWidth,
56 strokeLinecap: 'round',
57 strokeDasharray: '6 4'
58 })
59 );
60 }
61
62 var FONT_PRESETS = [
63 { label: 'Dancing Script (cursive)', value: "'Dancing Script', cursive" },
64 { label: 'Caveat (casual)', value: "'Caveat', cursive" },
65 { label: 'Pacifico (rounded)', value: "'Pacifico', cursive" },
66 { label: 'Satisfy (elegant)', value: "'Satisfy', cursive" },
67 { label: 'Sacramento (thin cursive)', value: "'Sacramento', cursive" },
68 { label: 'Inherit (theme font)', value: 'inherit' },
69 { label: 'Custom (type below)', value: 'custom' }
70 ];
71
72 registerBlockType('blockenberg/handwriting-text', {
73 edit: function (props) {
74 var attr = props.attributes;
75 var setAttr = props.setAttributes;
76 var blockProps = useBlockProps({
77 style: Object.assign({ background: attr.sectionBg || undefined, padding: '40px 20px', textAlign: attr.align2 }, _tv()(attr.typoText, '--bkbg-hw-tt-'))
78 });
79
80 var inspector = el(InspectorControls, {},
81 /* Text Content */
82 el(PanelBody, { title: __('Text', 'blockenberg'), initialOpen: true },
83 el(TextControl, {
84 label: __('Text to Handwrite', 'blockenberg'),
85 value: attr.text,
86 onChange: function (v) { setAttr({ text: v }); },
87 help: __('Cursive/script fonts work best for the handwriting effect.', 'blockenberg'),
88 __nextHasNoMarginBottom: true
89 }),
90 el('div', { style: { marginTop: '12px' } }),
91 el(SelectControl, {
92 label: __('Font Preset', 'blockenberg'),
93 value: (function () {
94 var fam = (attr.typoText || {}).family || attr.fontFamily;
95 return FONT_PRESETS.some(function (f) { return f.value === fam; }) ? fam : 'custom';
96 })(),
97 options: FONT_PRESETS,
98 onChange: function (v) {
99 if (v !== 'custom') {
100 var t = Object.assign({}, attr.typoText || {}, { family: v });
101 setAttr({ typoText: t });
102 }
103 },
104 help: __('Google Fonts must be loaded separately via "Additional CSS" or your theme.', 'blockenberg'),
105 __nextHasNoMarginBottom: true
106 }),
107 el('div', { style: { marginTop: '8px' } }),
108 el('div', { style: { marginTop: '8px' } }),
109 el('div', { style: { marginTop: '8px' } }),
110 el('div', { style: { marginTop: '8px' } }),
111 el(SelectControl, {
112 label: __('Text Alignment', 'blockenberg'),
113 value: attr.align2,
114 options: [{ label: 'Left', value: 'left' }, { label: 'Center', value: 'center' }, { label: 'Right', value: 'right' }],
115 onChange: function (v) {
116 var anchor = v === 'center' ? 'middle' : v === 'right' ? 'end' : 'start';
117 var x = v === 'center' ? 50 : v === 'right' ? 95 : 5;
118 setAttr({ align2: v, textAnchor: anchor, textX: x });
119 },
120 __nextHasNoMarginBottom: true
121 })
122 ),
123 /* SVG canvas */
124 el(PanelBody, { title: __('Canvas', 'blockenberg'), initialOpen: false },
125 el(RangeControl, { label: __('SVG Width (px)', 'blockenberg'), value: attr.svgWidth, min: 300, max: 1400, onChange: function (v) { setAttr({ svgWidth: v }); }, __nextHasNoMarginBottom: true }),
126 el('div', { style: { marginTop: '8px' } }),
127 el(RangeControl, { label: __('SVG Height (px)', 'blockenberg'), value: attr.svgHeight, min: 60, max: 400, onChange: function (v) { setAttr({ svgHeight: v }); }, __nextHasNoMarginBottom: true }),
128 el('div', { style: { marginTop: '8px' } }),
129 el(RangeControl, { label: __('Text Y Position (px)', 'blockenberg'), value: attr.textY, min: 20, max: 380, onChange: function (v) { setAttr({ textY: v }); }, __nextHasNoMarginBottom: true }),
130 el('div', { style: { marginTop: '8px' } }),
131 el(RangeControl, { label: __('Stroke Width (px)', 'blockenberg'), value: attr.strokeWidth, min: 1, max: 8, onChange: function (v) { setAttr({ strokeWidth: v }); }, __nextHasNoMarginBottom: true })
132 ),
133 /* Underline */
134 el(PanelBody, { title: __('Underline', 'blockenberg'), initialOpen: false },
135 el(ToggleControl, { label: __('Show Underline', 'blockenberg'), checked: attr.showUnderline, onChange: function (v) { setAttr({ showUnderline: v }); }, __nextHasNoMarginBottom: true }),
136 attr.showUnderline && el('div', {},
137 el('div', { style: { marginTop: '8px' } }),
138 el(RangeControl, { label: __('Underline Width (px)', 'blockenberg'), value: attr.underlineWidth, min: 1, max: 12, onChange: function (v) { setAttr({ underlineWidth: v }); }, __nextHasNoMarginBottom: true }),
139 el('div', { style: { marginTop: '8px' } }),
140 el(RangeControl, { label: __('Underline Gap (px)', 'blockenberg'), value: attr.underlineOffsetY, min: 0, max: 40, onChange: function (v) { setAttr({ underlineOffsetY: v }); }, __nextHasNoMarginBottom: true }),
141 el('div', { style: { marginTop: '8px' } }),
142 el(RangeControl, { label: __('Underline Animate Duration (s)', 'blockenberg'), value: attr.underlineDuration, min: 0.2, max: 3, step: 0.1, onChange: function (v) { setAttr({ underlineDuration: v }); }, __nextHasNoMarginBottom: true })
143 )
144 ),
145 /* Animation */
146 el(PanelBody, { title: __('Animation', 'blockenberg'), initialOpen: false },
147 el(SelectControl, {
148 label: __('Trigger', 'blockenberg'),
149 value: attr.trigger,
150 options: [
151 { label: 'On Scroll (IntersectionObserver)', value: 'scroll' },
152 { label: 'On Page Load', value: 'load' },
153 { label: 'On Click', value: 'click' }
154 ],
155 onChange: function (v) { setAttr({ trigger: v }); },
156 __nextHasNoMarginBottom: true
157 }),
158 el('div', { style: { marginTop: '8px' } }),
159 el(RangeControl, { label: __('Draw Duration (s)', 'blockenberg'), value: attr.duration, min: 0.5, max: 12, step: 0.1, onChange: function (v) { setAttr({ duration: v }); }, __nextHasNoMarginBottom: true }),
160 el('div', { style: { marginTop: '8px' } }),
161 el(RangeControl, { label: __('Start Delay (s)', 'blockenberg'), value: attr.delay, min: 0, max: 5, step: 0.1, onChange: function (v) { setAttr({ delay: v }); }, __nextHasNoMarginBottom: true }),
162 el('div', { style: { marginTop: '8px' } }),
163 el(SelectControl, {
164 label: __('Easing', 'blockenberg'),
165 value: attr.easing,
166 options: [
167 { label: 'Ease In Out', value: 'ease-in-out' },
168 { label: 'Ease In', value: 'ease-in' },
169 { label: 'Ease Out', value: 'ease-out' },
170 { label: 'Linear', value: 'linear' }
171 ],
172 onChange: function (v) { setAttr({ easing: v }); },
173 __nextHasNoMarginBottom: true
174 }),
175 el('div', { style: { marginTop: '8px' } }),
176 el(ToggleControl, { label: __('Fill Text After Drawing', 'blockenberg'), checked: attr.fillOnComplete, onChange: function (v) { setAttr({ fillOnComplete: v }); }, __nextHasNoMarginBottom: true }),
177 attr.fillOnComplete && el(RangeControl, { label: __('Fill Transition Duration (s)', 'blockenberg'), value: attr.fillDuration, min: 0.1, max: 3, step: 0.1, onChange: function (v) { setAttr({ fillDuration: v }); }, __nextHasNoMarginBottom: true }),
178 el('div', { style: { marginTop: '8px' } }),
179 el(ToggleControl, { label: __('Repeat Animation on Re-enter', 'blockenberg'), checked: attr.repeatAnimation, onChange: function (v) { setAttr({ repeatAnimation: v }); }, __nextHasNoMarginBottom: true })
180 ),
181 /* Colors */
182
183 el( PanelBody, { title: __( 'Typography', 'blockenberg' ), initialOpen: false },
184 _tc() && el(_tc(), { label:__('Text','blockenberg'), value:attr.typoText, onChange:function(v){ setAttr({typoText:v}); } })
185 ),
186 el(PanelColorSettings, {
187 title: __('Colors', 'blockenberg'),
188 initialOpen: false,
189 colorSettings: [
190 { label: __('Text Fill Color', 'blockenberg'), value: attr.textColor, onChange: function (v) { setAttr({ textColor: v || '#0f172a' }); } },
191 { label: __('Drawing Stroke Color', 'blockenberg'), value: attr.strokeColor, onChange: function (v) { setAttr({ strokeColor: v || '#6366f1' }); } },
192 { label: __('Underline Color', 'blockenberg'), value: attr.underlineColor, onChange: function (v) { setAttr({ underlineColor: v || '#6366f1' }); } },
193 { label: __('Section Background', 'blockenberg'), value: attr.sectionBg, onChange: function (v) { setAttr({ sectionBg: v || '' }); } }
194 ]
195 })
196 );
197
198 return el('div', blockProps,
199 inspector,
200 el('div', { style: { textAlign: attr.align2 } },
201 buildEditorSVG(attr)
202 )
203 );
204 },
205
206 save: function (props) {
207 var attr = props.attributes;
208 var blockProps = useBlockProps.save();
209 return el('div', blockProps,
210 el('div', {
211 className: 'bkbg-hw-app',
212 'data-opts': JSON.stringify(attr)
213 })
214 );
215 }
216 });
217 }() );
218