PluginProbe
NotificationX – FOMO, Live Sales Notification, WooCommerce Sales Popup, GDPR, Social Proof, Announcement Banner & Floating Notification Bar / 3.2.7
NotificationX – FOMO, Live Sales Notification, WooCommerce Sales Popup, GDPR, Social Proof, Announcement Banner & Floating Notification Bar v3.2.7
3.3.3 3.3.2 3.3.1 3.3.0 3.2.14 3.2.13 3.2.12 3.2.11 3.2.10 3.2.9 3.2.8 3.2.7 trunk 0.2.5.5 0.2.5.6 0.2.5.7 1.0.0 1.0.1 1.0.2 1.0.3 1.1.0 1.1.1 1.1.2 1.1.3 1.1.4 All 158 releases
notificationx / includes / Extensions / Elementor / CountdownWidget.php

CountdownWidget.php in NotificationX – FOMO, Live Sales Notification, WooCommerce Sales Popup, GDPR, Social Proof, Announcement Banner & Floating Notification Bar 3.2.7, at includes/Extensions/Elementor/CountdownWidget.php

951 lines 38.4 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * NotificationX Elementor Countdown Timer Widget
4 *
5 * @package NotificationX\Extensions\Elementor
6 */
7
8 namespace NotificationX\Extensions\Elementor;
9
10 use Elementor\Controls_Manager;
11 use Elementor\Group_Control_Background;
12 use Elementor\Group_Control_Border;
13 use Elementor\Group_Control_Box_Shadow;
14 use Elementor\Group_Control_Typography;
15 use Elementor\Core\Kits\Documents\Tabs\Global_Typography;
16 use Elementor\Widget_Base;
17
18 if ( ! defined( 'ABSPATH' ) ) {
19 exit;
20 }
21
22 /**
23 * Countdown Timer widget for Elementor.
24 */
25 class CountdownWidget extends Widget_Base {
26
27 public function get_name() {
28 return 'nx-countdown-timer';
29 }
30
31 public function get_title() {
32 return esc_html__( 'NotificationX Countdown Timer', 'notificationx' );
33 }
34
35 public function get_icon() {
36 return 'eicon-countdown';
37 }
38
39 public function get_categories() {
40 return [ 'notificationx' ];
41 }
42
43 public function get_keywords() {
44 return [ 'countdown', 'timer', 'notificationx', 'nx', 'sale', 'offer' ];
45 }
46
47 public function get_script_depends() {
48 return [ 'nx-countdown' ];
49 }
50
51 public function get_style_depends() {
52 return [ 'nx-countdown' ];
53 }
54
55 // ── Controls ──────────────────────────────────────────────────────────
56
57 protected function register_controls() {
58
59 // ── Timer Settings ────────────────────────────────────────────────
60 $this->start_controls_section(
61 'section_timer_settings',
62 [
63 'label' => esc_html__( 'Timer Settings', 'notificationx' ),
64 ]
65 );
66
67 $this->add_control(
68 'nx_countdown_type',
69 [
70 'label' => esc_html__( 'Type', 'notificationx' ),
71 'type' => Controls_Manager::SELECT,
72 'options' => [
73 'due_date' => esc_html__( 'Default (Due Date)', 'notificationx' ),
74 'evergreen' => esc_html__( 'Evergreen Timer', 'notificationx' ),
75 ],
76 'default' => 'due_date',
77 ]
78 );
79
80 $this->add_control(
81 'nx_countdown_due_time',
82 [
83 'label' => esc_html__( 'Countdown Due Date', 'notificationx' ),
84 'type' => Controls_Manager::DATE_TIME,
85 'default' => gmdate( 'Y-m-d', strtotime( '+7 days' ) ),
86 'description' => esc_html__( 'Set the due date and time.', 'notificationx' ),
87 'condition' => [ 'nx_countdown_type' => 'due_date' ],
88 ]
89 );
90
91 $this->add_control(
92 'nx_evergreen_hours',
93 [
94 'label' => esc_html__( 'Hours', 'notificationx' ),
95 'type' => Controls_Manager::NUMBER,
96 'default' => 11,
97 'placeholder' => esc_html__( 'Hours', 'notificationx' ),
98 'condition' => [ 'nx_countdown_type' => 'evergreen' ],
99 ]
100 );
101
102 $this->add_control(
103 'nx_evergreen_minutes',
104 [
105 'label' => esc_html__( 'Minutes', 'notificationx' ),
106 'type' => Controls_Manager::NUMBER,
107 'default' => 59,
108 'placeholder' => esc_html__( 'Minutes', 'notificationx' ),
109 'condition' => [ 'nx_countdown_type' => 'evergreen' ],
110 ]
111 );
112
113 $this->add_control(
114 'nx_evergreen_recurring',
115 [
116 'label' => esc_html__( 'Recurring Countdown', 'notificationx' ),
117 'type' => Controls_Manager::SWITCHER,
118 'return_value' => 'yes',
119 'default' => '',
120 'condition' => [ 'nx_countdown_type' => 'evergreen' ],
121 ]
122 );
123
124 $this->add_control(
125 'nx_evergreen_recurring_restart_after',
126 [
127 'label' => esc_html__( 'Restart After (Hours)', 'notificationx' ),
128 'type' => Controls_Manager::NUMBER,
129 'default' => 0,
130 'description' => esc_html__( 'How long to wait before restarting. 0 = restart immediately.', 'notificationx' ),
131 'condition' => [
132 'nx_countdown_type' => 'evergreen',
133 'nx_evergreen_recurring' => 'yes',
134 ],
135 ]
136 );
137
138 $this->add_control(
139 'nx_evergreen_recurring_stop_time',
140 [
141 'label' => esc_html__( 'Recurring End Date', 'notificationx' ),
142 'type' => Controls_Manager::DATE_TIME,
143 'default' => gmdate( 'Y-m-d', strtotime( '+7 days' ) ),
144 'description' => esc_html__( 'The absolute end date for the recurring countdown.', 'notificationx' ),
145 'condition' => [
146 'nx_countdown_type' => 'evergreen',
147 'nx_evergreen_recurring' => 'yes',
148 ],
149 ]
150 );
151
152 $this->end_controls_section();
153
154 // ── Content Settings ──────────────────────────────────────────────
155 $this->start_controls_section(
156 'section_content_settings',
157 [
158 'label' => esc_html__( 'Content Settings', 'notificationx' ),
159 ]
160 );
161
162 $this->add_control(
163 'nx_layout_heading',
164 [
165 'label' => esc_html__( 'Layout', 'notificationx' ),
166 'type' => Controls_Manager::HEADING,
167 ]
168 );
169
170 $this->add_control(
171 'nx_countdown_layout',
172 [
173 'label' => esc_html__( 'View', 'notificationx' ),
174 'type' => Controls_Manager::CHOOSE,
175 'options' => [
176 'grid' => [
177 'title' => esc_html__( 'Grid View', 'notificationx' ),
178 'icon' => 'eicon-columns',
179 ],
180 'list' => [
181 'title' => esc_html__( 'List View', 'notificationx' ),
182 'icon' => 'eicon-editor-list-ul',
183 ],
184 ],
185 'default' => 'grid',
186 'toggle' => false,
187 ]
188 );
189
190 $this->add_responsive_control(
191 'nx_countdown_label_view',
192 [
193 'label' => esc_html__( 'Label Position', 'notificationx' ),
194 'type' => Controls_Manager::SELECT,
195 'default' => 'nx-countdown-label-block',
196 'options' => [
197 'nx-countdown-label-block' => esc_html__( 'Block', 'notificationx' ),
198 'nx-countdown-label-inline' => esc_html__( 'Inline', 'notificationx' ),
199 ],
200 ]
201 );
202
203 $this->add_responsive_control(
204 'nx_countdown_alignment',
205 [
206 'label' => esc_html__( 'Alignment', 'notificationx' ),
207 'type' => Controls_Manager::CHOOSE,
208 'options' => [
209 'left' => [ 'title' => esc_html__( 'Left', 'notificationx' ), 'icon' => 'eicon-text-align-left' ],
210 'center' => [ 'title' => esc_html__( 'Center', 'notificationx' ), 'icon' => 'eicon-text-align-center' ],
211 'right' => [ 'title' => esc_html__( 'Right', 'notificationx' ), 'icon' => 'eicon-text-align-right' ],
212 ],
213 'default' => 'center',
214 'selectors' => [
215 '{{WRAPPER}} .nx-countdown-item > div' => 'text-align: {{VALUE}};',
216 ],
217 ]
218 );
219
220 $this->add_control(
221 'nx_divider_after_layout',
222 [
223 'type' => Controls_Manager::DIVIDER,
224 ]
225 );
226
227 $this->add_control(
228 'nx_show_days',
229 [
230 'label' => esc_html__( 'Display Days', 'notificationx' ),
231 'type' => Controls_Manager::SWITCHER,
232 'return_value' => 'yes',
233 'default' => 'yes',
234 ]
235 );
236
237 $this->add_control(
238 'nx_days_label',
239 [
240 'label' => esc_html__( 'Days Label', 'notificationx' ),
241 'type' => Controls_Manager::TEXT,
242 'default' => esc_html__( 'Days', 'notificationx' ),
243 'description' => esc_html__( 'Leave blank to hide.', 'notificationx' ),
244 'condition' => [ 'nx_show_days' => 'yes' ],
245 'dynamic' => [ 'active' => true ],
246 ]
247 );
248
249 $this->add_control(
250 'nx_show_hours',
251 [
252 'label' => esc_html__( 'Display Hours', 'notificationx' ),
253 'type' => Controls_Manager::SWITCHER,
254 'return_value' => 'yes',
255 'default' => 'yes',
256 ]
257 );
258
259 $this->add_control(
260 'nx_hours_label',
261 [
262 'label' => esc_html__( 'Hours Label', 'notificationx' ),
263 'type' => Controls_Manager::TEXT,
264 'default' => esc_html__( 'Hours', 'notificationx' ),
265 'description' => esc_html__( 'Leave blank to hide.', 'notificationx' ),
266 'condition' => [ 'nx_show_hours' => 'yes' ],
267 'dynamic' => [ 'active' => true ],
268 ]
269 );
270
271 $this->add_control(
272 'nx_show_minutes',
273 [
274 'label' => esc_html__( 'Display Minutes', 'notificationx' ),
275 'type' => Controls_Manager::SWITCHER,
276 'return_value' => 'yes',
277 'default' => 'yes',
278 ]
279 );
280
281 $this->add_control(
282 'nx_minutes_label',
283 [
284 'label' => esc_html__( 'Minutes Label', 'notificationx' ),
285 'type' => Controls_Manager::TEXT,
286 'default' => esc_html__( 'Minutes', 'notificationx' ),
287 'description' => esc_html__( 'Leave blank to hide.', 'notificationx' ),
288 'condition' => [ 'nx_show_minutes' => 'yes' ],
289 'dynamic' => [ 'active' => true ],
290 ]
291 );
292
293 $this->add_control(
294 'nx_show_seconds',
295 [
296 'label' => esc_html__( 'Display Seconds', 'notificationx' ),
297 'type' => Controls_Manager::SWITCHER,
298 'return_value' => 'yes',
299 'default' => 'yes',
300 ]
301 );
302
303 $this->add_control(
304 'nx_seconds_label',
305 [
306 'label' => esc_html__( 'Seconds Label', 'notificationx' ),
307 'type' => Controls_Manager::TEXT,
308 'default' => esc_html__( 'Seconds', 'notificationx' ),
309 'description' => esc_html__( 'Leave blank to hide.', 'notificationx' ),
310 'condition' => [ 'nx_show_seconds' => 'yes' ],
311 'dynamic' => [ 'active' => true ],
312 ]
313 );
314
315 $this->add_control(
316 'nx_separator_heading',
317 [
318 'label' => esc_html__( 'Separator', 'notificationx' ),
319 'type' => Controls_Manager::HEADING,
320 ]
321 );
322
323 $this->add_control(
324 'nx_show_separator',
325 [
326 'label' => esc_html__( 'Display Separator', 'notificationx' ),
327 'type' => Controls_Manager::SWITCHER,
328 'return_value' => 'nx-countdown-show-separator',
329 'default' => '',
330 ]
331 );
332
333 $this->add_control(
334 'nx_separator_style',
335 [
336 'label' => esc_html__( 'Separator Style', 'notificationx' ),
337 'type' => Controls_Manager::SELECT,
338 'default' => 'dotted',
339 'options' => [
340 'solid' => esc_html__( 'Solid ( : )', 'notificationx' ),
341 'dotted' => esc_html__( 'Dotted ( · )', 'notificationx' ),
342 ],
343 'condition' => [ 'nx_show_separator' => 'nx-countdown-show-separator' ],
344 ]
345 );
346
347 $this->add_control(
348 'nx_separator_color',
349 [
350 'label' => esc_html__( 'Separator Color', 'notificationx' ),
351 'type' => Controls_Manager::COLOR,
352 'selectors' => [
353 '{{WRAPPER}} .nx-countdown-digits::after' => 'color: {{VALUE}};',
354 ],
355 'condition' => [ 'nx_show_separator' => 'nx-countdown-show-separator' ],
356 ]
357 );
358
359 $this->end_controls_section();
360
361 // ── Expire Action ─────────────────────────────────────────────────
362 $this->start_controls_section(
363 'section_expire_action',
364 [
365 'label' => esc_html__( 'Expire Action', 'notificationx' ),
366 ]
367 );
368
369 $this->add_control(
370 'nx_expire_type',
371 [
372 'label' => esc_html__( 'On Expire', 'notificationx' ),
373 'type' => Controls_Manager::SELECT,
374 'description' => esc_html__( 'Action to take when the countdown reaches zero.', 'notificationx' ),
375 'options' => [
376 'none' => esc_html__( 'None', 'notificationx' ),
377 'text' => esc_html__( 'Show Message', 'notificationx' ),
378 'url' => esc_html__( 'Redirect to URL', 'notificationx' ),
379 ],
380 'default' => 'none',
381 ]
382 );
383
384 $this->add_control(
385 'nx_expiry_text_title',
386 [
387 'label' => esc_html__( 'Expiry Title', 'notificationx' ),
388 'type' => Controls_Manager::TEXTAREA,
389 'default' => esc_html__( 'The countdown is finished!', 'notificationx' ),
390 'condition' => [ 'nx_expire_type' => 'text' ],
391 'dynamic' => [ 'active' => true ],
392 ]
393 );
394
395 $this->add_control(
396 'nx_expiry_text',
397 [
398 'label' => esc_html__( 'Expiry Content', 'notificationx' ),
399 'type' => Controls_Manager::WYSIWYG,
400 'default' => esc_html__( 'Thank you for being part of this event.', 'notificationx' ),
401 'condition' => [ 'nx_expire_type' => 'text' ],
402 ]
403 );
404
405 $this->add_control(
406 'nx_expiry_redirect_url',
407 [
408 'label' => esc_html__( 'Redirect URL', 'notificationx' ),
409 'type' => Controls_Manager::TEXT,
410 'default' => '#',
411 'condition' => [ 'nx_expire_type' => 'url' ],
412 'dynamic' => [ 'active' => true ],
413 ]
414 );
415
416 $this->end_controls_section();
417
418 // ═══════════════════════════════════════════════════════════════════
419 // STYLE TABS
420 // ═══════════════════════════════════════════════════════════════════
421
422 // ── Countdown Box Styles ──────────────────────────────────────────
423 $this->start_controls_section(
424 'section_style_box',
425 [
426 'label' => esc_html__( 'Countdown Box', 'notificationx' ),
427 'tab' => Controls_Manager::TAB_STYLE,
428 ]
429 );
430
431 $this->add_control(
432 'nx_box_use_gradient',
433 [
434 'label' => esc_html__( 'Use Gradient Background?', 'notificationx' ),
435 'type' => Controls_Manager::SWITCHER,
436 'return_value' => 'yes',
437 ]
438 );
439
440 $this->add_group_control(
441 Group_Control_Background::get_type(),
442 [
443 'name' => 'nx_box_bg_gradient',
444 'label' => esc_html__( 'Box Background', 'notificationx' ),
445 'types' => [ 'classic', 'gradient' ],
446 'selector' => '{{WRAPPER}} .nx-countdown-item > div',
447 'condition' => [ 'nx_box_use_gradient' => 'yes' ],
448 ]
449 );
450
451 $this->add_control(
452 'nx_box_bg_color',
453 [
454 'label' => esc_html__( 'Box Background Color', 'notificationx' ),
455 'type' => Controls_Manager::COLOR,
456 'selectors' => [
457 '{{WRAPPER}} .nx-countdown-item > div' => 'background-color: {{VALUE}};',
458 ],
459 'condition' => [ 'nx_box_use_gradient' => '' ],
460 ]
461 );
462
463 $this->add_responsive_control(
464 'nx_box_spacing',
465 [
466 'label' => esc_html__( 'Space Between Boxes', 'notificationx' ),
467 'type' => Controls_Manager::SLIDER,
468 'default' => [ 'size' => 15 ],
469 'range' => [ 'px' => [ 'min' => 0, 'max' => 100 ] ],
470 'selectors' => [
471 '{{WRAPPER}} .nx-countdown-item > div' => 'margin-right:{{SIZE}}px; margin-left:{{SIZE}}px;',
472 '{{WRAPPER}} .nx-countdown-container' => 'margin-right:-{{SIZE}}px; margin-left:-{{SIZE}}px;',
473 ],
474 ]
475 );
476
477 $this->add_responsive_control(
478 'nx_box_padding',
479 [
480 'label' => esc_html__( 'Padding', 'notificationx' ),
481 'type' => Controls_Manager::DIMENSIONS,
482 'size_units' => [ 'px', '%', 'em' ],
483 'selectors' => [
484 '{{WRAPPER}} .nx-countdown-item > div' => 'padding: {{TOP}}{{UNIT}} {{RIGHT}}{{UNIT}} {{BOTTOM}}{{UNIT}} {{LEFT}}{{UNIT}};',
485 ],
486 ]
487 );
488
489 $this->add_group_control(
490 Group_Control_Border::get_type(),
491 [
492 'name' => 'nx_box_border',
493 'label' => esc_html__( 'Border', 'notificationx' ),
494 'selector' => '{{WRAPPER}} .nx-countdown-item > div',
495 ]
496 );
497
498 $this->add_control(
499 'nx_box_border_radius',
500 [
501 'label' => esc_html__( 'Border Radius', 'notificationx' ),
502 'type' => Controls_Manager::DIMENSIONS,
503 'selectors' => [
504 '{{WRAPPER}} .nx-countdown-item > div' => 'border-radius: {{TOP}}px {{RIGHT}}px {{BOTTOM}}px {{LEFT}}px;',
505 ],
506 ]
507 );
508
509 $this->add_group_control(
510 Group_Control_Box_Shadow::get_type(),
511 [
512 'name' => 'nx_box_shadow',
513 'selector' => '{{WRAPPER}} .nx-countdown-item > div',
514 ]
515 );
516
517 $this->end_controls_section();
518
519 // ── Color & Typography ────────────────────────────────────────────
520 $this->start_controls_section(
521 'section_style_typography',
522 [
523 'label' => esc_html__( 'Color &amp; Typography', 'notificationx' ),
524 'tab' => Controls_Manager::TAB_STYLE,
525 ]
526 );
527
528 $this->add_control(
529 'nx_digits_heading',
530 [
531 'label' => esc_html__( 'Digits', 'notificationx' ),
532 'type' => Controls_Manager::HEADING,
533 ]
534 );
535
536 $this->add_control(
537 'nx_digits_color',
538 [
539 'label' => esc_html__( 'Digits Color', 'notificationx' ),
540 'type' => Controls_Manager::COLOR,
541 'default' => '#fec503',
542 'selectors' => [
543 '{{WRAPPER}} .nx-countdown-digits' => 'color: {{VALUE}};',
544 ],
545 ]
546 );
547
548 $this->add_group_control(
549 Group_Control_Typography::get_type(),
550 [
551 'name' => 'nx_digits_typography',
552 'global' => [ 'default' => Global_Typography::TYPOGRAPHY_SECONDARY ],
553 'selector' => '{{WRAPPER}} .nx-countdown-digits',
554 ]
555 );
556
557 $this->add_control(
558 'nx_labels_heading',
559 [
560 'label' => esc_html__( 'Labels', 'notificationx' ),
561 'type' => Controls_Manager::HEADING,
562 ]
563 );
564
565 $this->add_control(
566 'nx_label_color',
567 [
568 'label' => esc_html__( 'Label Color', 'notificationx' ),
569 'type' => Controls_Manager::COLOR,
570 'default' => '#aaaaaa',
571 'selectors' => [
572 '{{WRAPPER}} .nx-countdown-label' => 'color: {{VALUE}};',
573 ],
574 ]
575 );
576
577 $this->add_group_control(
578 Group_Control_Typography::get_type(),
579 [
580 'name' => 'nx_label_typography',
581 'global' => [ 'default' => Global_Typography::TYPOGRAPHY_SECONDARY ],
582 'selector' => '{{WRAPPER}} .nx-countdown-label',
583 ]
584 );
585
586 $this->end_controls_section();
587
588 // ── Individual Box Styling ────────────────────────────────────────
589 $this->start_controls_section(
590 'section_style_individual',
591 [
592 'label' => esc_html__( 'Individual Box Styling', 'notificationx' ),
593 'tab' => Controls_Manager::TAB_STYLE,
594 ]
595 );
596
597 $unit_labels = [
598 'days' => esc_html__( 'Days', 'notificationx' ),
599 'hours' => esc_html__( 'Hours', 'notificationx' ),
600 'minutes' => esc_html__( 'Minutes', 'notificationx' ),
601 'seconds' => esc_html__( 'Seconds', 'notificationx' ),
602 ];
603
604 foreach ( $unit_labels as $unit => $label ) {
605 $this->add_control(
606 "nx_{$unit}_heading",
607 [
608 'label' => $label,
609 'type' => Controls_Manager::HEADING,
610 ]
611 );
612
613 $this->add_control(
614 "nx_{$unit}_bg_color",
615 [
616 'label' => esc_html__( 'Background Color', 'notificationx' ),
617 'type' => Controls_Manager::COLOR,
618 'selectors' => [
619 "{{WRAPPER}} .nx-countdown-item > div.nx-countdown-{$unit}" => 'background-color: {{VALUE}};',
620 ],
621 ]
622 );
623
624 $this->add_control(
625 "nx_{$unit}_digit_color",
626 [
627 'label' => esc_html__( 'Digit Color', 'notificationx' ),
628 'type' => Controls_Manager::COLOR,
629 'selectors' => [
630 "{{WRAPPER}} .nx-countdown-item > div.nx-countdown-{$unit} .nx-countdown-digits" => 'color: {{VALUE}};',
631 ],
632 ]
633 );
634
635 $this->add_control(
636 "nx_{$unit}_label_color",
637 [
638 'label' => esc_html__( 'Label Color', 'notificationx' ),
639 'type' => Controls_Manager::COLOR,
640 'selectors' => [
641 "{{WRAPPER}} .nx-countdown-item > div.nx-countdown-{$unit} .nx-countdown-label" => 'color: {{VALUE}};',
642 ],
643 ]
644 );
645
646 $this->add_control(
647 "nx_{$unit}_border_color",
648 [
649 'label' => esc_html__( 'Border Color', 'notificationx' ),
650 'type' => Controls_Manager::COLOR,
651 'selectors' => [
652 "{{WRAPPER}} .nx-countdown-item > div.nx-countdown-{$unit}" => 'border-color: {{VALUE}};',
653 ],
654 ]
655 );
656 }
657
658 $this->end_controls_section();
659
660 // ── Expire Message Style ──────────────────────────────────────────
661 $this->start_controls_section(
662 'section_style_expire',
663 [
664 'label' => esc_html__( 'Expire Message', 'notificationx' ),
665 'tab' => Controls_Manager::TAB_STYLE,
666 'condition' => [ 'nx_expire_type' => 'text' ],
667 ]
668 );
669
670 $this->add_responsive_control(
671 'nx_expire_alignment',
672 [
673 'label' => esc_html__( 'Alignment', 'notificationx' ),
674 'type' => Controls_Manager::CHOOSE,
675 'options' => [
676 'left' => [ 'title' => esc_html__( 'Left', 'notificationx' ), 'icon' => 'eicon-text-align-left' ],
677 'center' => [ 'title' => esc_html__( 'Center', 'notificationx' ), 'icon' => 'eicon-text-align-center' ],
678 'right' => [ 'title' => esc_html__( 'Right', 'notificationx' ), 'icon' => 'eicon-text-align-right' ],
679 ],
680 'selectors' => [
681 '{{WRAPPER}} .nx-countdown-finish-message' => 'text-align: {{VALUE}};',
682 ],
683 ]
684 );
685
686 $this->add_control(
687 'nx_expire_title_color',
688 [
689 'label' => esc_html__( 'Title Color', 'notificationx' ),
690 'type' => Controls_Manager::COLOR,
691 'selectors' => [
692 '{{WRAPPER}} .nx-countdown-finish-message .nx-expiry-title' => 'color: {{VALUE}};',
693 ],
694 ]
695 );
696
697 $this->add_group_control(
698 Group_Control_Typography::get_type(),
699 [
700 'name' => 'nx_expire_title_typography',
701 'global' => [ 'default' => Global_Typography::TYPOGRAPHY_SECONDARY ],
702 'selector' => '{{WRAPPER}} .nx-countdown-finish-message .nx-expiry-title',
703 ]
704 );
705
706 $this->add_control(
707 'nx_expire_text_color',
708 [
709 'label' => esc_html__( 'Text Color', 'notificationx' ),
710 'type' => Controls_Manager::COLOR,
711 'selectors' => [
712 '{{WRAPPER}} .nx-expiry-text' => 'color: {{VALUE}};',
713 ],
714 ]
715 );
716
717 $this->add_group_control(
718 Group_Control_Typography::get_type(),
719 [
720 'name' => 'nx_expire_text_typography',
721 'global' => [ 'default' => Global_Typography::TYPOGRAPHY_SECONDARY ],
722 'selector' => '{{WRAPPER}} .nx-expiry-text',
723 ]
724 );
725
726 $this->end_controls_section();
727 }
728
729 // ── Render ────────────────────────────────────────────────────────────
730
731 protected function render() {
732 $settings = $this->get_settings_for_display();
733
734 // Build target date string with GMT offset (matches the JS `new Date(dateStr)` parsing)
735 $gmt_offset = get_option( 'gmt_offset' );
736 $offset_str = ( $gmt_offset < 0 ? '' : '+' ) . str_replace(
737 [ '.25', '.5', '.75' ],
738 [ ':15', ':30', ':45' ],
739 (string) $gmt_offset
740 );
741
742 $due_date_str = '';
743 if ( $settings['nx_countdown_type'] === 'due_date' && ! empty( $settings['nx_countdown_due_time'] ) ) {
744 $due_date_str = gmdate( 'M d Y G:i:s', strtotime( $settings['nx_countdown_due_time'] ) ) . ' ' . $offset_str;
745 }
746
747 // Evergreen time in seconds
748 $evergreen_seconds = 0;
749 if ( $settings['nx_countdown_type'] === 'evergreen' ) {
750 $evergreen_seconds = absint( $settings['nx_evergreen_hours'] ?? 0 ) * HOUR_IN_SECONDS;
751 $evergreen_seconds += absint( $settings['nx_evergreen_minutes'] ?? 0 ) * MINUTE_IN_SECONDS;
752 }
753
754 // Separator class
755 $separator_class = '';
756 if ( ! empty( $settings['nx_show_separator'] ) ) {
757 $separator_class = 'nx-countdown-show-separator nx-countdown-separator-' . esc_attr( $settings['nx_separator_style'] );
758 }
759
760 // ── Wrapper attributes ────────────────────────────────────────────
761 $this->add_render_attribute( 'nx-countdown', [
762 'class' => 'nx-countdown-wrapper',
763 'data-countdown-id' => esc_attr( $this->get_id() ),
764 'data-countdown-type' => esc_attr( $settings['nx_countdown_type'] ),
765 'data-expire-type' => esc_attr( $settings['nx_expire_type'] ),
766 ] );
767
768 if ( $settings['nx_expire_type'] === 'text' ) {
769 $this->add_render_attribute( 'nx-countdown', [
770 'data-expiry-title' => wp_kses_post( $settings['nx_expiry_text_title'] ?? '' ),
771 'data-expiry-text' => wp_kses_post( $settings['nx_expiry_text'] ?? '' ),
772 ] );
773 } elseif ( $settings['nx_expire_type'] === 'url' ) {
774 $this->add_render_attribute( 'nx-countdown', 'data-redirect-url', esc_url( $settings['nx_expiry_redirect_url'] ?? '' ) );
775 }
776
777 if ( $settings['nx_countdown_type'] === 'evergreen' ) {
778 $this->add_render_attribute( 'nx-countdown', 'data-evergreen-time', absint( $evergreen_seconds ) );
779 if ( $settings['nx_evergreen_recurring'] === 'yes' ) {
780 $restart_after = isset( $settings['nx_evergreen_recurring_restart_after'] ) ? $settings['nx_evergreen_recurring_restart_after'] : 0;
781 $stop_time = isset( $settings['nx_evergreen_recurring_stop_time'] )
782 ? gmdate( 'M d Y G:i:s', strtotime( $settings['nx_evergreen_recurring_stop_time'] ) ) . ' ' . $offset_str
783 : '';
784 $this->add_render_attribute( 'nx-countdown', [
785 'data-evergreen-recurring' => absint( $restart_after ),
786 'data-evergreen-recurring-stop' => esc_attr( $stop_time ),
787 ] );
788 }
789 }
790
791 // ── List attributes ───────────────────────────────────────────────
792 $label_view = $settings['nx_countdown_label_view'] ?? 'nx-countdown-label-block';
793 $layout_class = 'nx-countdown-layout-' . ( ! empty( $settings['nx_countdown_layout'] ) ? esc_attr( $settings['nx_countdown_layout'] ) : 'grid' );
794
795 $this->add_render_attribute( 'nx-countdown-list', [
796 'id' => 'nx-countdown-' . esc_attr( $this->get_id() ),
797 'class' => [ 'nx-countdown-container', esc_attr( $layout_class ), esc_attr( $label_view ), esc_attr( $separator_class ) ],
798 'data-date' => esc_attr( $due_date_str ),
799 ] );
800 ?>
801
802 <div <?php $this->print_render_attribute_string( 'nx-countdown' ); ?>>
803
804 <ul <?php $this->print_render_attribute_string( 'nx-countdown-list' ); ?>>
805
806 <?php if ( ! empty( $settings['nx_show_days'] ) ) : ?>
807 <li class="nx-countdown-item">
808 <div class="nx-countdown-days">
809 <span data-days class="nx-countdown-digits">00</span>
810 <?php if ( ! empty( $settings['nx_days_label'] ) ) : ?>
811 <span class="nx-countdown-label"><?php echo esc_html( $settings['nx_days_label'] ); ?></span>
812 <?php endif; ?>
813 </div>
814 </li>
815 <?php endif; ?>
816
817 <?php if ( ! empty( $settings['nx_show_hours'] ) ) : ?>
818 <li class="nx-countdown-item">
819 <div class="nx-countdown-hours">
820 <span data-hours class="nx-countdown-digits">00</span>
821 <?php if ( ! empty( $settings['nx_hours_label'] ) ) : ?>
822 <span class="nx-countdown-label"><?php echo esc_html( $settings['nx_hours_label'] ); ?></span>
823 <?php endif; ?>
824 </div>
825 </li>
826 <?php endif; ?>
827
828 <?php if ( ! empty( $settings['nx_show_minutes'] ) ) : ?>
829 <li class="nx-countdown-item">
830 <div class="nx-countdown-minutes">
831 <span data-minutes class="nx-countdown-digits">00</span>
832 <?php if ( ! empty( $settings['nx_minutes_label'] ) ) : ?>
833 <span class="nx-countdown-label"><?php echo esc_html( $settings['nx_minutes_label'] ); ?></span>
834 <?php endif; ?>
835 </div>
836 </li>
837 <?php endif; ?>
838
839 <?php if ( ! empty( $settings['nx_show_seconds'] ) ) : ?>
840 <li class="nx-countdown-item">
841 <div class="nx-countdown-seconds">
842 <span data-seconds class="nx-countdown-digits">00</span>
843 <?php if ( ! empty( $settings['nx_seconds_label'] ) ) : ?>
844 <span class="nx-countdown-label"><?php echo esc_html( $settings['nx_seconds_label'] ); ?></span>
845 <?php endif; ?>
846 </div>
847 </li>
848 <?php endif; ?>
849
850 </ul>
851
852 </div>
853
854 <?php
855 }
856
857 // ── Editor live-preview JS template ──────────────────────────────────
858
859 protected function content_template() {
860 ?>
861 <#
862 var widgetId = view.getID();
863
864 var layoutClass = 'nx-countdown-layout-' + ( settings.nx_countdown_layout || 'grid' );
865 var listClasses = 'nx-countdown-container ' + layoutClass + ' ' + ( settings.nx_countdown_label_view || 'nx-countdown-label-block' );
866 if ( settings.nx_show_separator ) {
867 listClasses += ' nx-countdown-show-separator nx-countdown-separator-' + settings.nx_separator_style;
868 }
869
870 // Evergreen duration in seconds
871 var evergreenSeconds = ( parseInt( settings.nx_evergreen_hours || 0, 10 ) * 3600 )
872 + ( parseInt( settings.nx_evergreen_minutes || 0, 10 ) * 60 );
873
874 // Build data attrs for the wrapper (mirroring render())
875 var wrapperData = ' data-countdown-id="' + widgetId + '"'
876 + ' data-countdown-type="' + settings.nx_countdown_type + '"'
877 + ' data-expire-type="' + settings.nx_expire_type + '"';
878
879 if ( settings.nx_countdown_type === 'evergreen' ) {
880 wrapperData += ' data-evergreen-time="' + evergreenSeconds + '"';
881 if ( settings.nx_evergreen_recurring === 'yes' ) {
882 wrapperData += ' data-evergreen-recurring="' + ( settings.nx_evergreen_recurring_restart_after || 0 ) + '"';
883 wrapperData += ' data-evergreen-recurring-stop="' + ( settings.nx_evergreen_recurring_stop_time || '' ) + '"';
884 }
885 }
886
887 if ( settings.nx_expire_type === 'text' ) {
888 wrapperData += ' data-expiry-title="' + ( settings.nx_expiry_text_title || '' ) + '"';
889 wrapperData += ' data-expiry-text="' + ( settings.nx_expiry_text || '' ) + '"';
890 } else if ( settings.nx_expire_type === 'url' ) {
891 wrapperData += ' data-redirect-url="' + ( settings.nx_expiry_redirect_url || '' ) + '"';
892 }
893
894 // For due_date, pass the raw ISO string — the JS does new Date(dateStr).getTime()
895 var dateStr = ( settings.nx_countdown_type === 'due_date' )
896 ? ( settings.nx_countdown_due_time || '' ).replace( ' ', 'T' )
897 : '';
898 #>
899 <div class="nx-countdown-wrapper"{{{ wrapperData }}}>
900 <ul id="nx-countdown-{{ widgetId }}" class="{{ listClasses }}" data-date="{{ dateStr }}">
901
902 <# if ( settings.nx_show_days ) { #>
903 <li class="nx-countdown-item">
904 <div class="nx-countdown-days">
905 <span data-days class="nx-countdown-digits">00</span>
906 <# if ( settings.nx_days_label ) { #>
907 <span class="nx-countdown-label">{{{ settings.nx_days_label }}}</span>
908 <# } #>
909 </div>
910 </li>
911 <# } #>
912
913 <# if ( settings.nx_show_hours ) { #>
914 <li class="nx-countdown-item">
915 <div class="nx-countdown-hours">
916 <span data-hours class="nx-countdown-digits">00</span>
917 <# if ( settings.nx_hours_label ) { #>
918 <span class="nx-countdown-label">{{{ settings.nx_hours_label }}}</span>
919 <# } #>
920 </div>
921 </li>
922 <# } #>
923
924 <# if ( settings.nx_show_minutes ) { #>
925 <li class="nx-countdown-item">
926 <div class="nx-countdown-minutes">
927 <span data-minutes class="nx-countdown-digits">00</span>
928 <# if ( settings.nx_minutes_label ) { #>
929 <span class="nx-countdown-label">{{{ settings.nx_minutes_label }}}</span>
930 <# } #>
931 </div>
932 </li>
933 <# } #>
934
935 <# if ( settings.nx_show_seconds ) { #>
936 <li class="nx-countdown-item">
937 <div class="nx-countdown-seconds">
938 <span data-seconds class="nx-countdown-digits">00</span>
939 <# if ( settings.nx_seconds_label ) { #>
940 <span class="nx-countdown-label">{{{ settings.nx_seconds_label }}}</span>
941 <# } #>
942 </div>
943 </li>
944 <# } #>
945
946 </ul>
947 </div>
948 <?php
949 }
950 }
951