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 / dark-mode-toggle / index.js

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

384 lines 19.1 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 useState = wp.element.useState;
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 ToggleControl = wp.components.ToggleControl;
11 var RangeControl = wp.components.RangeControl;
12 var SelectControl = wp.components.SelectControl;
13 var TextControl = wp.components.TextControl;
14
15 var _dmTC, _dmTV;
16 function _tc() { return _dmTC || (_dmTC = window.bkbgTypographyControl); }
17 function _tv(obj, prefix) { var fn = _dmTV || (_dmTV = window.bkbgTypoCssVars); return fn ? fn(obj, prefix) : {}; }
18
19 /* ── Preview component ─────────────────────────────────────────────────── */
20 function TogglePreview(props) {
21 var a = props.attrs;
22 var isDark = props.isDark;
23
24 var wrapStyle = {
25 display: 'flex',
26 alignItems: 'center',
27 justifyContent:
28 props.align === 'right' ? 'flex-end' :
29 props.align === 'center' ? 'center' : 'flex-start',
30 };
31
32 var btnStyle = {
33 display: 'inline-flex',
34 alignItems: 'center',
35 gap: '8px',
36 minWidth: a.buttonSize + 'px',
37 height: a.buttonSize + 'px',
38 padding: '0 12px',
39 borderRadius: a.borderRadius + 'px',
40 border: 'none',
41 cursor: 'pointer',
42 fontSize: Math.round(a.buttonSize * 0.4) + 'px',
43 background: isDark ? a.darkBg : a.lightBg,
44 color: isDark ? a.darkColor : a.lightColor,
45 boxShadow: a.shadow ? '0 2px 8px rgba(0,0,0,0.18)' : 'none',
46 transition: 'transform ' + a.transitionDuration + 'ms ease',
47 transform: 'scale(1)',
48 };
49
50 if (a.toggleStyle === 'switch') {
51 var trackStyle = {
52 display: 'inline-flex',
53 alignItems: 'center',
54 width: '48px',
55 height: '26px',
56 borderRadius: '13px',
57 background: isDark ? a.switchTrackDark : a.switchTrackLight,
58 padding: '2px',
59 boxSizing: 'border-box',
60 transition: 'background ' + a.transitionDuration + 'ms ease',
61 flexShrink: 0,
62 };
63 var thumbStyle = {
64 width: '22px',
65 height: '22px',
66 borderRadius: '50%',
67 background: a.switchThumbColor,
68 boxShadow: '0 1px 4px rgba(0,0,0,0.25)',
69 transition: 'transform ' + a.transitionDuration + 'ms ease',
70 transform: isDark ? 'translateX(22px)' : 'translateX(0)',
71 };
72 return el('div', { style: wrapStyle },
73 el('button', {
74 'aria-label': 'Toggle dark mode',
75 style: {
76 display: 'inline-flex',
77 alignItems: 'center',
78 gap: '8px',
79 background: 'none',
80 border: 'none',
81 cursor: 'pointer',
82 padding: '0',
83 fontSize: '18px',
84 }
85 },
86 a.showIcon ? el('span', null, isDark ? a.darkIcon : a.lightIcon) : null,
87 el('div', { style: trackStyle },
88 el('div', { style: thumbStyle })
89 ),
90 a.showLabel ? el('span', {
91 className: 'bkdm-label', style: { color: '#374151' }
92 }, isDark ? a.darkLabel : a.lightLabel) : null
93 )
94 );
95 }
96
97 // icon or button style
98 return el('div', { style: wrapStyle },
99 el('button', { 'aria-label': 'Toggle dark mode', style: btnStyle },
100 a.showIcon ? el('span', null, isDark ? a.darkIcon : a.lightIcon) : null,
101 a.showLabel ? el('span', {
102 className: 'bkdm-label'
103 }, isDark ? a.darkLabel : a.lightLabel) : null
104 )
105 );
106 }
107
108 /* ── Register ──────────────────────────────────────────────────────────── */
109 registerBlockType('blockenberg/dark-mode-toggle', {
110 edit: function (props) {
111 var a = props.attributes;
112 var set = props.setAttributes;
113 var align = props.attributes.align;
114
115 var isDark = useState(false);
116 var previewDark = isDark[0];
117 var setPreviewDark = isDark[1];
118
119 var blockProps = useBlockProps({
120 className: 'bkdm-wrap',
121 style: Object.assign(
122 { '--bkdm-lbl-fs': (a.labelFontSize || 14) + 'px' },
123 _tv(a.typoLabel || {}, '--bkdm-lbl-')
124 )
125 });
126
127 return el(wp.element.Fragment, null,
128
129 /* Inspector */
130 el(InspectorControls, null,
131
132 /* Appearance */
133 el(PanelBody, { title: __('Appearance', 'blockenberg'), initialOpen: true },
134 el(SelectControl, {
135 label: __('Toggle Style', 'blockenberg'),
136 value: a.toggleStyle,
137 options: [
138 { label: __('Switch (track + thumb)', 'blockenberg'), value: 'switch' },
139 { label: __('Icon Button', 'blockenberg'), value: 'icon' },
140 ],
141 onChange: function (v) { set({ toggleStyle: v }); }
142 }),
143 el(SelectControl, {
144 label: __('Position', 'blockenberg'),
145 value: a.position,
146 options: [
147 { label: __('Inline (in flow)', 'blockenberg'), value: 'inline' },
148 { label: __('Floating (fixed corner)', 'blockenberg'), value: 'floating' },
149 ],
150 onChange: function (v) { set({ position: v }); }
151 }),
152 a.position === 'floating' ? el(SelectControl, {
153 label: __('Corner', 'blockenberg'),
154 value: a.floatCorner,
155 options: [
156 { label: __('Bottom Right', 'blockenberg'), value: 'bottom-right' },
157 { label: __('Bottom Left', 'blockenberg'), value: 'bottom-left' },
158 { label: __('Top Right', 'blockenberg'), value: 'top-right' },
159 { label: __('Top Left', 'blockenberg'), value: 'top-left' },
160 ],
161 onChange: function (v) { set({ floatCorner: v }); }
162 }) : null,
163 a.position === 'floating' ? el(RangeControl, {
164 label: __('Offset X (px)', 'blockenberg'),
165 value: a.floatOffsetX,
166 min: 0, max: 120,
167 onChange: function (v) { set({ floatOffsetX: v }); }
168 }) : null,
169 a.position === 'floating' ? el(RangeControl, {
170 label: __('Offset Y (px)', 'blockenberg'),
171 value: a.floatOffsetY,
172 min: 0, max: 120,
173 onChange: function (v) { set({ floatOffsetY: v }); }
174 }) : null,
175 el(RangeControl, {
176 label: __('Button Size (px)', 'blockenberg'),
177 value: a.buttonSize,
178 min: 28, max: 80,
179 onChange: function (v) { set({ buttonSize: v }); }
180 }),
181 el(RangeControl, {
182 label: __('Border Radius (px)', 'blockenberg'),
183 value: a.borderRadius,
184 min: 0, max: 50,
185 onChange: function (v) { set({ borderRadius: v }); }
186 }),
187 el(RangeControl, {
188 label: __('Transition Duration (ms)', 'blockenberg'),
189 value: a.transitionDuration,
190 min: 0, max: 1000, step: 50,
191 onChange: function (v) { set({ transitionDuration: v }); }
192 }),
193 el(ToggleControl, {
194 label: __('Show Icon', 'blockenberg'),
195 checked: a.showIcon,
196 onChange: function (v) { set({ showIcon: v }); },
197 __nextHasNoMarginBottom: true
198 }),
199 el(ToggleControl, {
200 label: __('Show Label', 'blockenberg'),
201 checked: a.showLabel,
202 onChange: function (v) { set({ showLabel: v }); },
203 __nextHasNoMarginBottom: true
204 }),
205 el(ToggleControl, {
206 label: __('Hover Scale', 'blockenberg'),
207 checked: a.hoverScale,
208 onChange: function (v) { set({ hoverScale: v }); },
209 __nextHasNoMarginBottom: true
210 }),
211 el(ToggleControl, {
212 label: __('Drop Shadow', 'blockenberg'),
213 checked: a.shadow,
214 onChange: function (v) { set({ shadow: v }); },
215 __nextHasNoMarginBottom: true
216 })
217 ),
218
219 /* Icons & Labels */
220 el(PanelBody, { title: __('Icons & Labels', 'blockenberg'), initialOpen: false },
221 el(TextControl, {
222 label: __('Light Mode Icon', 'blockenberg'),
223 value: a.lightIcon,
224 onChange: function (v) { set({ lightIcon: v }); }
225 }),
226 el(TextControl, {
227 label: __('Dark Mode Icon', 'blockenberg'),
228 value: a.darkIcon,
229 onChange: function (v) { set({ darkIcon: v }); }
230 }),
231 el(TextControl, {
232 label: __('Light Label Text', 'blockenberg'),
233 value: a.lightLabel,
234 onChange: function (v) { set({ lightLabel: v }); }
235 }),
236 el(TextControl, {
237 label: __('Dark Label Text', 'blockenberg'),
238 value: a.darkLabel,
239 onChange: function (v) { set({ darkLabel: v }); }
240 })
241 ),
242
243 /* Behaviour */
244 el(PanelBody, { title: __('Behaviour', 'blockenberg'), initialOpen: false },
245 el(SelectControl, {
246 label: __('Default Theme', 'blockenberg'),
247 value: a.defaultTheme,
248 options: [
249 { label: __('Light', 'blockenberg'), value: 'light' },
250 { label: __('Dark', 'blockenberg'), value: 'dark' },
251 ],
252 onChange: function (v) { set({ defaultTheme: v }); }
253 }),
254 el(ToggleControl, {
255 label: __('Respect System Preference', 'blockenberg'),
256 help: __('If enabled, auto-applies dark mode when the OS is in dark mode (unless user overrides).', 'blockenberg'),
257 checked: a.respectSystemPref,
258 onChange: function (v) { set({ respectSystemPref: v }); },
259 __nextHasNoMarginBottom: true
260 }),
261 el(TextControl, {
262 label: __('localStorage Key', 'blockenberg'),
263 value: a.storageKey,
264 onChange: function (v) { set({ storageKey: v }); }
265 }),
266 el(TextControl, {
267 label: __('HTML Attribute Name', 'blockenberg'),
268 value: a.dataAttribute,
269 onChange: function (v) { set({ dataAttribute: v }); }
270 }),
271 el(TextControl, {
272 label: __('Dark Value', 'blockenberg'),
273 value: a.darkValue,
274 onChange: function (v) { set({ darkValue: v }); }
275 }),
276 el(TextControl, {
277 label: __('Light Value', 'blockenberg'),
278 value: a.lightValue,
279 onChange: function (v) { set({ lightValue: v }); }
280 })
281 ),
282
283 /* Colors */
284 el(PanelBody, { title: __('Typography', 'blockenberg'), initialOpen: false },
285 _tc() && el(_tc(), { label: __('Label', 'blockenberg'), value: a.typoLabel, onChange: function (v) { set({ typoLabel: v }); } })
286 ),
287 el(PanelColorSettings, {
288 title: __('Colors', 'blockenberg'),
289 initialOpen: false,
290 colorSettings: [
291 { value: a.lightBg, onChange: function (v) { set({ lightBg: v || '#f3f4f6' }); }, label: __('Light Mode Background', 'blockenberg') },
292 { value: a.lightColor, onChange: function (v) { set({ lightColor: v || '#111827' }); }, label: __('Light Mode Icon/Text', 'blockenberg') },
293 { value: a.darkBg, onChange: function (v) { set({ darkBg: v || '#1f2937' }); }, label: __('Dark Mode Background', 'blockenberg') },
294 { value: a.darkColor, onChange: function (v) { set({ darkColor: v || '#f9fafb' }); }, label: __('Dark Mode Icon/Text', 'blockenberg') },
295 { value: a.switchTrackLight, onChange: function (v) { set({ switchTrackLight: v || '#d1d5db' }); }, label: __('Switch Track (Light)', 'blockenberg') },
296 { value: a.switchTrackDark, onChange: function (v) { set({ switchTrackDark: v || '#4f46e5' }); }, label: __('Switch Track (Dark)', 'blockenberg') },
297 { value: a.switchThumbColor, onChange: function (v) { set({ switchThumbColor: v || '#ffffff' }); }, label: __('Switch Thumb', 'blockenberg') },
298 ]
299 })
300 ),
301
302 /* Canvas */
303 el('div', blockProps,
304 el('div', {
305 style: { padding: '8px 0' }
306 },
307 el('p', {
308 style: { fontSize: '11px', color: '#6b7280', marginBottom: '10px', textAlign: 'center' }
309 }, __('Preview — click to toggle', 'blockenberg')),
310 el(TogglePreview, {
311 attrs: a,
312 isDark: previewDark,
313 align: align,
314 }),
315 el('button', {
316 style: {
317 display: 'block',
318 margin: '12px auto 0',
319 padding: '4px 12px',
320 fontSize: '12px',
321 cursor: 'pointer',
322 borderRadius: '4px',
323 border: '1px solid #d1d5db',
324 background: '#fff',
325 },
326 onClick: function () { setPreviewDark(!previewDark); }
327 }, __('Toggle Preview', 'blockenberg'))
328 )
329 )
330 );
331 },
332
333 save: function (props) {
334 var a = props.attributes;
335 var blockProps = wp.blockEditor.useBlockProps.save({
336 className: 'bkdm-wrap',
337 style: Object.assign(
338 { '--bkdm-lbl-fs': (a.labelFontSize || 14) + 'px' },
339 _tv(a.typoLabel || {}, '--bkdm-lbl-')
340 )
341 });
342
343 return el('div', Object.assign({}, blockProps, {
344 'data-toggle-style': a.toggleStyle,
345 'data-position': a.position,
346 'data-float-corner': a.floatCorner,
347 'data-float-x': a.floatOffsetX,
348 'data-float-y': a.floatOffsetY,
349 'data-storage-key': a.storageKey,
350 'data-attr': a.dataAttribute,
351 'data-dark-val': a.darkValue,
352 'data-light-val': a.lightValue,
353 'data-default': a.defaultTheme,
354 'data-respect-system': String(a.respectSystemPref),
355 'data-button-size': a.buttonSize,
356 'data-border-radius': a.borderRadius,
357 'data-duration': a.transitionDuration,
358 'data-show-icon': String(a.showIcon),
359 'data-show-label': String(a.showLabel),
360 'data-light-icon': a.lightIcon,
361 'data-dark-icon': a.darkIcon,
362 'data-light-label': a.lightLabel,
363 'data-dark-label': a.darkLabel,
364 'data-hover-scale': String(a.hoverScale),
365 'data-shadow': String(a.shadow),
366 'data-light-bg': a.lightBg,
367 'data-light-color': a.lightColor,
368 'data-dark-bg': a.darkBg,
369 'data-dark-color': a.darkColor,
370 'data-track-light': a.switchTrackLight,
371 'data-track-dark': a.switchTrackDark,
372 'data-thumb': a.switchThumbColor,
373 }),
374 el('button', {
375 className: 'bkdm-btn',
376 'aria-label': 'Toggle dark mode',
377 'aria-pressed': 'false',
378 type: 'button',
379 })
380 );
381 }
382 });
383 }() );
384