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 / tooltip / index.js

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

315 lines 19.3 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 Fragment = wp.element.Fragment;
4 var useState = wp.element.useState;
5 var __ = wp.i18n.__;
6 var registerBlockType = wp.blocks.registerBlockType;
7 var InspectorControls = wp.blockEditor.InspectorControls;
8 var useBlockProps = wp.blockEditor.useBlockProps;
9 var RichText = wp.blockEditor.RichText;
10 var PanelColorSettings = wp.blockEditor.PanelColorSettings;
11 var PanelBody = wp.components.PanelBody;
12 var ToggleControl = wp.components.ToggleControl;
13 var RangeControl = wp.components.RangeControl;
14 var SelectControl = wp.components.SelectControl;
15 var TextControl = wp.components.TextControl;
16 var TextareaControl = wp.components.TextareaControl;
17
18 var _tc, _tvf;
19 Object.defineProperty(window, '_bkbgTypoCtrlCache', { get: function () { if (!_tc) { _tc = window.bkbgTypographyControl; } return _tc; } });
20 Object.defineProperty(window, '_bkbgTypoVarsCache', { get: function () { if (!_tvf) { _tvf = window.bkbgTypoCssVars; } return _tvf; } });
21 function getTypoControl(props, attrName, label) { return window._bkbgTypoCtrlCache(props, attrName, label); }
22
23 var POSITION_OPTIONS = [
24 { label: 'Top', value: 'top' },
25 { label: 'Bottom', value: 'bottom' },
26 { label: 'Left', value: 'left' },
27 { label: 'Right', value: 'right' },
28 ];
29
30 var STYLE_OPTIONS = [
31 { label: 'Dotted underline', value: 'underline-dotted' },
32 { label: 'Solid underline', value: 'underline-solid' },
33 { label: 'Dashed underline', value: 'underline-dashed' },
34 { label: 'Highlight', value: 'highlight' },
35 { label: 'Bold', value: 'bold' },
36 { label: 'Italic', value: 'italic' },
37 { label: 'None', value: 'none' },
38 ];
39
40 var ANIM_OPTIONS = [
41 { label: 'Fade', value: 'fade' },
42 { label: 'Scale up', value: 'scale' },
43 { label: 'Bounce', value: 'bounce' },
44 { label: 'Zoom out', value: 'zoom-out' },
45 { label: 'Slide down', value: 'slide-down' },
46 { label: 'Slide up', value: 'slide-up' },
47 { label: 'Slide left', value: 'slide-left' },
48 { label: 'Slide right', value: 'slide-right' },
49 { label: 'Blur', value: 'blur' },
50 { label: 'Flip', value: 'flip' },
51 { label: 'Rotate', value: 'rotate' },
52 { label: 'None', value: 'none' },
53 ];
54
55 var WEIGHT_OPTIONS = [
56 { label: 'Normal (400)', value: '400' },
57 { label: 'Medium (500)', value: '500' },
58 { label: 'Semi-bold (600)', value: '600' },
59 { label: 'Bold (700)', value: '700' },
60 ];
61
62 var ALIGN_OPTIONS = [
63 { label: 'Left', value: 'left' },
64 { label: 'Center', value: 'center' },
65 { label: 'Right', value: 'right' },
66 ];
67
68 function getTriggerStyle(a) {
69 var style = {
70 color: a.triggerColor,
71 cursor: 'help',
72 display: 'inline-block',
73 };
74 if (a.triggerStyle === 'underline-dotted') {
75 style.textDecoration = 'underline';
76 style.textDecorationStyle = 'dotted';
77 style.textDecorationColor = a.underlineColor;
78 } else if (a.triggerStyle === 'underline-solid') {
79 style.textDecoration = 'underline';
80 style.textDecorationColor = a.underlineColor;
81 } else if (a.triggerStyle === 'underline-dashed') {
82 style.textDecoration = 'underline';
83 style.textDecorationStyle = 'dashed';
84 style.textDecorationColor = a.underlineColor;
85 } else if (a.triggerStyle === 'highlight') {
86 style.background = a.highlightBg;
87 style.borderRadius = '4px';
88 style.padding = '0 4px';
89 } else if (a.triggerStyle === 'bold') {
90 style.fontWeight = '700';
91 } else if (a.triggerStyle === 'italic') {
92 style.fontStyle = 'italic';
93 }
94 return style;
95 }
96
97 registerBlockType('blockenberg/tooltip', {
98 title: __('Tooltip', 'blockenberg'),
99 icon: 'info',
100 category: 'bkbg-content',
101 description: __('Hover tooltip with trigger text and informational popup.', 'blockenberg'),
102
103 edit: function (props) {
104 var a = props.attributes;
105 var set = props.setAttributes;
106 var showPreview = useState(false);
107 var isPreviewOpen = showPreview[0];
108 var setPreviewOpen = showPreview[1];
109
110 var blockProps = (function () {
111 var s = { textAlign: a.align };
112 Object.assign(s, window._bkbgTypoVarsCache(a.triggerTypo, '--bkttp-tr-'), window._bkbgTypoVarsCache(a.tooltipTypo, '--bkttp-tp-'));
113 return useBlockProps({ style: s });
114 })();
115
116 return el(Fragment, null,
117 el(InspectorControls, null,
118 // Content
119 el(PanelBody, { title: 'Content', initialOpen: true },
120 el(TextControl, {
121 label: 'Trigger Text (visible)',
122 value: a.triggerText,
123 onChange: function (v) { set({ triggerText: v }); },
124 __nextHasNoMarginBottom: true,
125 }),
126 el('div', { style: { height: 10 } }),
127 el(TextareaControl, {
128 label: 'Tooltip Content (popup)',
129 value: a.tooltipContent,
130 rows: 4,
131 onChange: function (v) { set({ tooltipContent: v }); },
132 __nextHasNoMarginBottom: true,
133 })
134 ),
135
136 // Appearance
137 el(PanelBody, { title: 'Trigger Style', initialOpen: false },
138 el(SelectControl, { label: 'Trigger style', value: a.triggerStyle, options: STYLE_OPTIONS, onChange: function (v) { set({ triggerStyle: v }); }, __nextHasNoMarginBottom: true }),
139 el('div', { style: { height: 10 } }),
140 el(SelectControl, { label: 'Text alignment', value: a.align, options: ALIGN_OPTIONS, onChange: function (v) { set({ align: v }); }, __nextHasNoMarginBottom: true }),
141 el('div', { style: { height: 10 } }),
142 el('div', { style: { height: 10 } }),
143 ),
144
145 // Tooltip popup
146 el(PanelBody, { title: 'Tooltip Popup', initialOpen: false },
147 el(SelectControl, { label: 'Position', value: a.position, options: POSITION_OPTIONS, onChange: function (v) { set({ position: v }); }, __nextHasNoMarginBottom: true }),
148 el('div', { style: { height: 10 } }),
149 el(SelectControl, { label: 'Animation', value: a.animationType, options: ANIM_OPTIONS, onChange: function (v) { set({ animationType: v }); }, __nextHasNoMarginBottom: true }),
150 el('div', { style: { height: 10 } }),
151 el(RangeControl, { label: 'Max width (px)', value: a.maxWidth, min: 150, max: 480, onChange: function (v) { set({ maxWidth: v }); }, __nextHasNoMarginBottom: true }),
152 el('div', { style: { height: 10 } }),
153 el(RangeControl, { label: 'Padding (px)', value: a.tooltipPadding, min: 6, max: 24, onChange: function (v) { set({ tooltipPadding: v }); }, __nextHasNoMarginBottom: true }),
154 el('div', { style: { height: 10 } }),
155 el(RangeControl, { label: 'Border radius (px)', value: a.tooltipRadius, min: 0, max: 24, onChange: function (v) { set({ tooltipRadius: v }); }, __nextHasNoMarginBottom: true }),
156 el('div', { style: { height: 10 } }),
157 el('div', { style: { height: 10 } }),
158 el(ToggleControl, { label: 'Show arrow', checked: a.showArrow, onChange: function (v) { set({ showArrow: v }); }, __nextHasNoMarginBottom: true })
159 ),
160
161 // Colors
162
163 el( PanelBody, { title: __( 'Typography', 'blockenberg' ), initialOpen: false },
164 getTypoControl(props, 'triggerTypo', __('Trigger', 'blockenberg')),
165 getTypoControl(props, 'tooltipTypo', __('Tooltip', 'blockenberg'))
166 ),
167 el(PanelColorSettings, {
168 title: 'Colors',
169 initialOpen: false,
170 colorSettings: [
171 { label: 'Trigger Text Color', value: a.triggerColor, onChange: function (v) { set({ triggerColor: v || '#6366f1' }); } },
172 { label: 'Underline / Accent Color', value: a.underlineColor, onChange: function (v) { set({ underlineColor: v || '#6366f1' }); } },
173 { label: 'Highlight Background', value: a.highlightBg, onChange: function (v) { set({ highlightBg: v || '#ede9fe' }); } },
174 { label: 'Tooltip Background', value: a.tooltipBg, onChange: function (v) { set({ tooltipBg: v || '#1e293b' }); } },
175 { label: 'Tooltip Text Color', value: a.tooltipColor, onChange: function (v) { set({ tooltipColor: v || '#f8fafc' }); } },
176 ]
177 })
178 ),
179
180 // ── Editor Preview ──
181 el('div', blockProps,
182 el('div', {
183 style: { display: 'inline-block', position: 'relative' },
184 onMouseEnter: function () { setPreviewOpen(true); },
185 onMouseLeave: function () { setPreviewOpen(false); },
186 },
187 el('span', { style: getTriggerStyle(a) }, a.triggerText),
188 // Always in DOM so CSS transition works (same as frontend)
189 el('div', {
190 style: (function () {
191 var isLR = a.position === 'left' || a.position === 'right';
192 var anim = a.animationType || 'fade';
193 // Base transform (hidden state offset)
194 var hiddenTransform;
195 if (a.position === 'top') hiddenTransform = 'translateX(-50%) translateY(4px)';
196 else if (a.position === 'bottom') hiddenTransform = 'translateX(-50%) translateY(-4px)';
197 else if (a.position === 'left') hiddenTransform = 'translateY(-50%) translateX(4px)';
198 else hiddenTransform = 'translateY(-50%) translateX(-4px)';
199
200 var visibleTransform;
201 if (a.position === 'top' || a.position === 'bottom') visibleTransform = 'translateX(-50%) translateY(0)';
202 else visibleTransform = 'translateY(-50%) translateX(0)';
203
204 var customTransition = null;
205 var hiddenFilter = null;
206 var visibleFilter = null;
207
208 if (anim === 'scale') {
209 hiddenTransform = isLR ? 'translateY(-50%) scale(0.9)' : 'translateX(-50%) scale(0.9)';
210 visibleTransform = isLR ? 'translateY(-50%) scale(1)' : 'translateX(-50%) scale(1)';
211 } else if (anim === 'bounce') {
212 hiddenTransform = isLR ? 'translateY(-50%) scale(0.6)' : 'translateX(-50%) scale(0.6)';
213 visibleTransform = isLR ? 'translateY(-50%) scale(1)' : 'translateX(-50%) scale(1)';
214 customTransition = 'opacity 0.4s cubic-bezier(0.34,1.56,0.64,1), transform 0.4s cubic-bezier(0.34,1.56,0.64,1), visibility 0.4s';
215 } else if (anim === 'zoom-out') {
216 hiddenTransform = isLR ? 'translateY(-50%) scale(1.25)' : 'translateX(-50%) scale(1.25)';
217 visibleTransform = isLR ? 'translateY(-50%) scale(1)' : 'translateX(-50%) scale(1)';
218 } else if (anim === 'slide-down') {
219 hiddenTransform = isLR ? hiddenTransform : 'translateX(-50%) translateY(-8px)';
220 visibleTransform = isLR ? visibleTransform : 'translateX(-50%) translateY(0)';
221 } else if (anim === 'slide-up') {
222 hiddenTransform = isLR ? hiddenTransform : 'translateX(-50%) translateY(8px)';
223 visibleTransform = isLR ? visibleTransform : 'translateX(-50%) translateY(0)';
224 } else if (anim === 'slide-left') {
225 hiddenTransform = isLR ? hiddenTransform : 'translateX(calc(-50% + 12px))';
226 visibleTransform = isLR ? visibleTransform : 'translateX(-50%)';
227 } else if (anim === 'slide-right') {
228 hiddenTransform = isLR ? hiddenTransform : 'translateX(calc(-50% - 12px))';
229 visibleTransform = isLR ? visibleTransform : 'translateX(-50%)';
230 } else if (anim === 'blur') {
231 hiddenTransform = isLR ? 'translateY(-50%)' : 'translateX(-50%)';
232 visibleTransform = isLR ? 'translateY(-50%)' : 'translateX(-50%)';
233 hiddenFilter = 'blur(6px)';
234 visibleFilter = 'blur(0px)';
235 customTransition = 'opacity 0.25s ease, transform 0.25s ease, filter 0.25s ease, visibility 0.25s';
236 } else if (anim === 'flip') {
237 hiddenTransform = isLR ? 'translateY(-50%) perspective(400px) rotateY(-90deg)' : 'translateX(-50%) perspective(400px) rotateX(-80deg)';
238 visibleTransform = isLR ? 'translateY(-50%) perspective(400px) rotateY(0deg)' : 'translateX(-50%) perspective(400px) rotateX(0deg)';
239 customTransition = 'opacity 0.3s ease, transform 0.3s ease, visibility 0.3s';
240 } else if (anim === 'rotate') {
241 hiddenTransform = isLR ? 'translateY(-50%) rotate(-10deg) scale(0.88)' : 'translateX(-50%) rotate(-10deg) scale(0.88)';
242 visibleTransform = isLR ? 'translateY(-50%) rotate(0deg) scale(1)' : 'translateX(-50%) rotate(0deg) scale(1)';
243 } else if (anim === 'none') {
244 hiddenTransform = isLR ? 'translateY(-50%)' : 'translateX(-50%)';
245 visibleTransform = isLR ? 'translateY(-50%)' : 'translateX(-50%)';
246 }
247
248 var baseStyle = {
249 position: 'absolute',
250 bottom: a.position === 'bottom' ? 'auto' : (isLR ? 'auto' : 'calc(100% + 10px)'),
251 top: a.position === 'bottom' ? 'calc(100% + 10px)' : (isLR ? '50%' : 'auto'),
252 left: a.position === 'right' ? 'calc(100% + 10px)' : (isLR ? 'auto' : '50%'),
253 right: a.position === 'left' ? 'calc(100% + 10px)' : 'auto',
254 maxWidth: a.maxWidth + 'px',
255 minWidth: 140,
256 background: a.tooltipBg,
257 color: a.tooltipColor,
258 fontSize: undefined,
259 lineHeight: undefined,
260 padding: a.tooltipPadding + 'px',
261 borderRadius: a.tooltipRadius + 'px',
262 zIndex: 9999,
263 boxShadow: '0 8px 24px rgba(0,0,0,0.18)',
264 pointerEvents: 'none',
265 whiteSpace: 'normal',
266 opacity: isPreviewOpen ? 1 : 0,
267 visibility: isPreviewOpen ? 'visible' : 'hidden',
268 transform: isPreviewOpen ? visibleTransform : hiddenTransform,
269 transition: customTransition || (anim === 'none'
270 ? 'opacity 0s, visibility 0s'
271 : 'opacity 0.22s ease, transform 0.22s ease, visibility 0.22s'),
272 };
273 if (hiddenFilter !== null) {
274 baseStyle.filter = isPreviewOpen ? visibleFilter : hiddenFilter;
275 }
276 return baseStyle;
277 }())
278 },
279 a.tooltipContent,
280 a.showArrow && el('div', {
281 style: {
282 position: 'absolute',
283 width: 0, height: 0,
284 bottom: a.position !== 'bottom' ? -6 : 'auto',
285 top: a.position === 'bottom' ? -6 : 'auto',
286 left: (a.position === 'top' || a.position === 'bottom') ? '50%' : 'auto',
287 transform: (a.position === 'top' || a.position === 'bottom') ? 'translateX(-50%)' : undefined,
288 borderLeft: (a.position === 'top' || a.position === 'bottom') ? '6px solid transparent' : 'none',
289 borderRight: (a.position === 'top' || a.position === 'bottom') ? '6px solid transparent' : 'none',
290 borderTop: a.position === 'top' ? '6px solid ' + a.tooltipBg : 'none',
291 borderBottom: a.position === 'bottom' ? '6px solid ' + a.tooltipBg : 'none',
292 }
293 })
294 )
295 ),
296 el('p', { style: { fontSize: 11, color: '#9ca3af', margin: '8px 0 0' } },
297 '💡 Hover the text above to preview the tooltip.'
298 )
299 )
300 );
301 },
302
303 save: function (props) {
304 var bp = (function () {
305 var tv = Object.assign({}, window._bkbgTypoVarsCache(props.attributes.triggerTypo, '--bkttp-tr-'), window._bkbgTypoVarsCache(props.attributes.tooltipTypo, '--bkttp-tp-'));
306 var parts = []; Object.keys(tv).forEach(function (k) { parts.push(k + ':' + tv[k]); });
307 return useBlockProps.save(parts.length ? { style: parts.join(';') } : {});
308 })();
309 return el('div', bp,
310 el('div', { className: 'bkbg-tt-app', 'data-opts': JSON.stringify(props.attributes) })
311 );
312 }
313 });
314 }() );
315