PluginProbe
NotificationX – FOMO, Live Sales Notification, WooCommerce Sales Popup, GDPR, Social Proof, Announcement Banner & Floating Notification Bar / trunk
NotificationX – FOMO, Live Sales Notification, WooCommerce Sales Popup, GDPR, Social Proof, Announcement Banner & Floating Notification Bar vtrunk
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 1.2.0 1.2.1 All 156 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 trunk, at includes/Extensions/Elementor/CountdownWidget.php

1,002 lines 40.2 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; --nx-countdown-box-spacing:{{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_digits_bg_color',
559 [
560 'label' => esc_html__( 'Background Color', 'notificationx' ),
561 'type' => Controls_Manager::COLOR,
562 'selectors' => [
563 '{{WRAPPER}} .nx-countdown-digits' => 'background-color: {{VALUE}};',
564 ],
565 ]
566 );
567
568 $this->add_responsive_control(
569 'nx_digits_padding',
570 [
571 'label' => esc_html__( 'Padding', 'notificationx' ),
572 'type' => Controls_Manager::DIMENSIONS,
573 'size_units' => [ 'px', 'em', '%' ],
574 'selectors' => [
575 '{{WRAPPER}} .nx-countdown-digits' => 'padding: {{TOP}}{{UNIT}} {{RIGHT}}{{UNIT}} {{BOTTOM}}{{UNIT}} {{LEFT}}{{UNIT}};',
576 ],
577 ]
578 );
579
580 $this->add_group_control(
581 Group_Control_Border::get_type(),
582 [
583 'name' => 'nx_digits_border',
584 'selector' => '{{WRAPPER}} .nx-countdown-digits',
585 ]
586 );
587
588 $this->add_responsive_control(
589 'nx_digits_border_radius',
590 [
591 'label' => esc_html__( 'Border Radius', 'notificationx' ),
592 'type' => Controls_Manager::DIMENSIONS,
593 'size_units' => [ 'px', '%' ],
594 'selectors' => [
595 '{{WRAPPER}} .nx-countdown-digits' => 'border-radius: {{TOP}}{{UNIT}} {{RIGHT}}{{UNIT}} {{BOTTOM}}{{UNIT}} {{LEFT}}{{UNIT}};',
596 ],
597 ]
598 );
599
600 $this->add_group_control(
601 Group_Control_Box_Shadow::get_type(),
602 [
603 'name' => 'nx_digits_box_shadow',
604 'selector' => '{{WRAPPER}} .nx-countdown-digits',
605 ]
606 );
607
608 $this->add_control(
609 'nx_labels_heading',
610 [
611 'label' => esc_html__( 'Labels', 'notificationx' ),
612 'type' => Controls_Manager::HEADING,
613 ]
614 );
615
616 $this->add_control(
617 'nx_label_color',
618 [
619 'label' => esc_html__( 'Label Color', 'notificationx' ),
620 'type' => Controls_Manager::COLOR,
621 'default' => '#aaaaaa',
622 'selectors' => [
623 '{{WRAPPER}} .nx-countdown-label' => 'color: {{VALUE}};',
624 ],
625 ]
626 );
627
628 $this->add_group_control(
629 Group_Control_Typography::get_type(),
630 [
631 'name' => 'nx_label_typography',
632 'global' => [ 'default' => Global_Typography::TYPOGRAPHY_SECONDARY ],
633 'selector' => '{{WRAPPER}} .nx-countdown-label',
634 ]
635 );
636
637 $this->end_controls_section();
638
639 // ── Individual Box Styling ────────────────────────────────────────
640 $this->start_controls_section(
641 'section_style_individual',
642 [
643 'label' => esc_html__( 'Individual Box Styling', 'notificationx' ),
644 'tab' => Controls_Manager::TAB_STYLE,
645 ]
646 );
647
648 $unit_labels = [
649 'days' => esc_html__( 'Days', 'notificationx' ),
650 'hours' => esc_html__( 'Hours', 'notificationx' ),
651 'minutes' => esc_html__( 'Minutes', 'notificationx' ),
652 'seconds' => esc_html__( 'Seconds', 'notificationx' ),
653 ];
654
655 foreach ( $unit_labels as $unit => $label ) {
656 $this->add_control(
657 "nx_{$unit}_heading",
658 [
659 'label' => $label,
660 'type' => Controls_Manager::HEADING,
661 ]
662 );
663
664 $this->add_control(
665 "nx_{$unit}_bg_color",
666 [
667 'label' => esc_html__( 'Background Color', 'notificationx' ),
668 'type' => Controls_Manager::COLOR,
669 'selectors' => [
670 "{{WRAPPER}} .nx-countdown-item > div.nx-countdown-{$unit}" => 'background-color: {{VALUE}};',
671 ],
672 ]
673 );
674
675 $this->add_control(
676 "nx_{$unit}_digit_color",
677 [
678 'label' => esc_html__( 'Digit Color', 'notificationx' ),
679 'type' => Controls_Manager::COLOR,
680 'selectors' => [
681 "{{WRAPPER}} .nx-countdown-item > div.nx-countdown-{$unit} .nx-countdown-digits" => 'color: {{VALUE}};',
682 ],
683 ]
684 );
685
686 $this->add_control(
687 "nx_{$unit}_label_color",
688 [
689 'label' => esc_html__( 'Label Color', 'notificationx' ),
690 'type' => Controls_Manager::COLOR,
691 'selectors' => [
692 "{{WRAPPER}} .nx-countdown-item > div.nx-countdown-{$unit} .nx-countdown-label" => 'color: {{VALUE}};',
693 ],
694 ]
695 );
696
697 $this->add_control(
698 "nx_{$unit}_border_color",
699 [
700 'label' => esc_html__( 'Border Color', 'notificationx' ),
701 'type' => Controls_Manager::COLOR,
702 'selectors' => [
703 "{{WRAPPER}} .nx-countdown-item > div.nx-countdown-{$unit}" => 'border-color: {{VALUE}};',
704 ],
705 ]
706 );
707 }
708
709 $this->end_controls_section();
710
711 // ── Expire Message Style ──────────────────────────────────────────
712 $this->start_controls_section(
713 'section_style_expire',
714 [
715 'label' => esc_html__( 'Expire Message', 'notificationx' ),
716 'tab' => Controls_Manager::TAB_STYLE,
717 'condition' => [ 'nx_expire_type' => 'text' ],
718 ]
719 );
720
721 $this->add_responsive_control(
722 'nx_expire_alignment',
723 [
724 'label' => esc_html__( 'Alignment', 'notificationx' ),
725 'type' => Controls_Manager::CHOOSE,
726 'options' => [
727 'left' => [ 'title' => esc_html__( 'Left', 'notificationx' ), 'icon' => 'eicon-text-align-left' ],
728 'center' => [ 'title' => esc_html__( 'Center', 'notificationx' ), 'icon' => 'eicon-text-align-center' ],
729 'right' => [ 'title' => esc_html__( 'Right', 'notificationx' ), 'icon' => 'eicon-text-align-right' ],
730 ],
731 'selectors' => [
732 '{{WRAPPER}} .nx-countdown-finish-message' => 'text-align: {{VALUE}};',
733 ],
734 ]
735 );
736
737 $this->add_control(
738 'nx_expire_title_color',
739 [
740 'label' => esc_html__( 'Title Color', 'notificationx' ),
741 'type' => Controls_Manager::COLOR,
742 'selectors' => [
743 '{{WRAPPER}} .nx-countdown-finish-message .nx-expiry-title' => 'color: {{VALUE}};',
744 ],
745 ]
746 );
747
748 $this->add_group_control(
749 Group_Control_Typography::get_type(),
750 [
751 'name' => 'nx_expire_title_typography',
752 'global' => [ 'default' => Global_Typography::TYPOGRAPHY_SECONDARY ],
753 'selector' => '{{WRAPPER}} .nx-countdown-finish-message .nx-expiry-title',
754 ]
755 );
756
757 $this->add_control(
758 'nx_expire_text_color',
759 [
760 'label' => esc_html__( 'Text Color', 'notificationx' ),
761 'type' => Controls_Manager::COLOR,
762 'selectors' => [
763 '{{WRAPPER}} .nx-expiry-text' => 'color: {{VALUE}};',
764 ],
765 ]
766 );
767
768 $this->add_group_control(
769 Group_Control_Typography::get_type(),
770 [
771 'name' => 'nx_expire_text_typography',
772 'global' => [ 'default' => Global_Typography::TYPOGRAPHY_SECONDARY ],
773 'selector' => '{{WRAPPER}} .nx-expiry-text',
774 ]
775 );
776
777 $this->end_controls_section();
778 }
779
780 // ── Render ────────────────────────────────────────────────────────────
781
782 protected function render() {
783 $settings = $this->get_settings_for_display();
784
785 // Build target date string with GMT offset (matches the JS `new Date(dateStr)` parsing)
786 $gmt_offset = get_option( 'gmt_offset' );
787 $offset_str = ( $gmt_offset < 0 ? '' : '+' ) . str_replace(
788 [ '.25', '.5', '.75' ],
789 [ ':15', ':30', ':45' ],
790 (string) $gmt_offset
791 );
792
793 $due_date_str = '';
794 if ( $settings['nx_countdown_type'] === 'due_date' && ! empty( $settings['nx_countdown_due_time'] ) ) {
795 $due_date_str = gmdate( 'M d Y G:i:s', strtotime( $settings['nx_countdown_due_time'] ) ) . ' ' . $offset_str;
796 }
797
798 // Evergreen time in seconds
799 $evergreen_seconds = 0;
800 if ( $settings['nx_countdown_type'] === 'evergreen' ) {
801 $evergreen_seconds = absint( $settings['nx_evergreen_hours'] ?? 0 ) * HOUR_IN_SECONDS;
802 $evergreen_seconds += absint( $settings['nx_evergreen_minutes'] ?? 0 ) * MINUTE_IN_SECONDS;
803 }
804
805 // Separator class
806 $separator_class = '';
807 if ( ! empty( $settings['nx_show_separator'] ) ) {
808 $separator_class = 'nx-countdown-show-separator nx-countdown-separator-' . esc_attr( $settings['nx_separator_style'] );
809 }
810
811 // ── Wrapper attributes ────────────────────────────────────────────
812 $this->add_render_attribute( 'nx-countdown', [
813 'class' => 'nx-countdown-wrapper',
814 'data-countdown-id' => esc_attr( $this->get_id() ),
815 'data-countdown-type' => esc_attr( $settings['nx_countdown_type'] ),
816 'data-expire-type' => esc_attr( $settings['nx_expire_type'] ),
817 ] );
818
819 if ( $settings['nx_expire_type'] === 'text' ) {
820 $this->add_render_attribute( 'nx-countdown', [
821 'data-expiry-title' => wp_kses_post( $settings['nx_expiry_text_title'] ?? '' ),
822 'data-expiry-text' => wp_kses_post( $settings['nx_expiry_text'] ?? '' ),
823 ] );
824 } elseif ( $settings['nx_expire_type'] === 'url' ) {
825 $this->add_render_attribute( 'nx-countdown', 'data-redirect-url', esc_url( $settings['nx_expiry_redirect_url'] ?? '' ) );
826 }
827
828 if ( $settings['nx_countdown_type'] === 'evergreen' ) {
829 $this->add_render_attribute( 'nx-countdown', 'data-evergreen-time', absint( $evergreen_seconds ) );
830 if ( $settings['nx_evergreen_recurring'] === 'yes' ) {
831 $restart_after = isset( $settings['nx_evergreen_recurring_restart_after'] ) ? $settings['nx_evergreen_recurring_restart_after'] : 0;
832 $stop_time = isset( $settings['nx_evergreen_recurring_stop_time'] )
833 ? gmdate( 'M d Y G:i:s', strtotime( $settings['nx_evergreen_recurring_stop_time'] ) ) . ' ' . $offset_str
834 : '';
835 $this->add_render_attribute( 'nx-countdown', [
836 'data-evergreen-recurring' => absint( $restart_after ),
837 'data-evergreen-recurring-stop' => esc_attr( $stop_time ),
838 ] );
839 }
840 }
841
842 // ── List attributes ───────────────────────────────────────────────
843 $label_view = $settings['nx_countdown_label_view'] ?? 'nx-countdown-label-block';
844 $layout_class = 'nx-countdown-layout-' . ( ! empty( $settings['nx_countdown_layout'] ) ? esc_attr( $settings['nx_countdown_layout'] ) : 'grid' );
845
846 $this->add_render_attribute( 'nx-countdown-list', [
847 'id' => 'nx-countdown-' . esc_attr( $this->get_id() ),
848 'class' => [ 'nx-countdown-container', esc_attr( $layout_class ), esc_attr( $label_view ), esc_attr( $separator_class ) ],
849 'data-date' => esc_attr( $due_date_str ),
850 ] );
851 ?>
852
853 <div <?php $this->print_render_attribute_string( 'nx-countdown' ); ?>>
854
855 <ul <?php $this->print_render_attribute_string( 'nx-countdown-list' ); ?>>
856
857 <?php if ( ! empty( $settings['nx_show_days'] ) ) : ?>
858 <li class="nx-countdown-item">
859 <div class="nx-countdown-days">
860 <span data-days class="nx-countdown-digits">00</span>
861 <?php if ( ! empty( $settings['nx_days_label'] ) ) : ?>
862 <span class="nx-countdown-label"><?php echo esc_html( $settings['nx_days_label'] ); ?></span>
863 <?php endif; ?>
864 </div>
865 </li>
866 <?php endif; ?>
867
868 <?php if ( ! empty( $settings['nx_show_hours'] ) ) : ?>
869 <li class="nx-countdown-item">
870 <div class="nx-countdown-hours">
871 <span data-hours class="nx-countdown-digits">00</span>
872 <?php if ( ! empty( $settings['nx_hours_label'] ) ) : ?>
873 <span class="nx-countdown-label"><?php echo esc_html( $settings['nx_hours_label'] ); ?></span>
874 <?php endif; ?>
875 </div>
876 </li>
877 <?php endif; ?>
878
879 <?php if ( ! empty( $settings['nx_show_minutes'] ) ) : ?>
880 <li class="nx-countdown-item">
881 <div class="nx-countdown-minutes">
882 <span data-minutes class="nx-countdown-digits">00</span>
883 <?php if ( ! empty( $settings['nx_minutes_label'] ) ) : ?>
884 <span class="nx-countdown-label"><?php echo esc_html( $settings['nx_minutes_label'] ); ?></span>
885 <?php endif; ?>
886 </div>
887 </li>
888 <?php endif; ?>
889
890 <?php if ( ! empty( $settings['nx_show_seconds'] ) ) : ?>
891 <li class="nx-countdown-item">
892 <div class="nx-countdown-seconds">
893 <span data-seconds class="nx-countdown-digits">00</span>
894 <?php if ( ! empty( $settings['nx_seconds_label'] ) ) : ?>
895 <span class="nx-countdown-label"><?php echo esc_html( $settings['nx_seconds_label'] ); ?></span>
896 <?php endif; ?>
897 </div>
898 </li>
899 <?php endif; ?>
900
901 </ul>
902
903 </div>
904
905 <?php
906 }
907
908 // ── Editor live-preview JS template ──────────────────────────────────
909
910 protected function content_template() {
911 ?>
912 <#
913 var widgetId = view.getID();
914
915 var layoutClass = 'nx-countdown-layout-' + ( settings.nx_countdown_layout || 'grid' );
916 var listClasses = 'nx-countdown-container ' + layoutClass + ' ' + ( settings.nx_countdown_label_view || 'nx-countdown-label-block' );
917 if ( settings.nx_show_separator ) {
918 listClasses += ' nx-countdown-show-separator nx-countdown-separator-' + settings.nx_separator_style;
919 }
920
921 // Evergreen duration in seconds
922 var evergreenSeconds = ( parseInt( settings.nx_evergreen_hours || 0, 10 ) * 3600 )
923 + ( parseInt( settings.nx_evergreen_minutes || 0, 10 ) * 60 );
924
925 // Build data attrs for the wrapper (mirroring render())
926 var wrapperData = ' data-countdown-id="' + widgetId + '"'
927 + ' data-countdown-type="' + settings.nx_countdown_type + '"'
928 + ' data-expire-type="' + settings.nx_expire_type + '"';
929
930 if ( settings.nx_countdown_type === 'evergreen' ) {
931 wrapperData += ' data-evergreen-time="' + evergreenSeconds + '"';
932 if ( settings.nx_evergreen_recurring === 'yes' ) {
933 wrapperData += ' data-evergreen-recurring="' + ( settings.nx_evergreen_recurring_restart_after || 0 ) + '"';
934 wrapperData += ' data-evergreen-recurring-stop="' + ( settings.nx_evergreen_recurring_stop_time || '' ) + '"';
935 }
936 }
937
938 if ( settings.nx_expire_type === 'text' ) {
939 wrapperData += ' data-expiry-title="' + ( settings.nx_expiry_text_title || '' ) + '"';
940 wrapperData += ' data-expiry-text="' + ( settings.nx_expiry_text || '' ) + '"';
941 } else if ( settings.nx_expire_type === 'url' ) {
942 wrapperData += ' data-redirect-url="' + ( settings.nx_expiry_redirect_url || '' ) + '"';
943 }
944
945 // For due_date, pass the raw ISO string — the JS does new Date(dateStr).getTime()
946 var dateStr = ( settings.nx_countdown_type === 'due_date' )
947 ? ( settings.nx_countdown_due_time || '' ).replace( ' ', 'T' )
948 : '';
949 #>
950 <div class="nx-countdown-wrapper"{{{ wrapperData }}}>
951 <ul id="nx-countdown-{{ widgetId }}" class="{{ listClasses }}" data-date="{{ dateStr }}">
952
953 <# if ( settings.nx_show_days ) { #>
954 <li class="nx-countdown-item">
955 <div class="nx-countdown-days">
956 <span data-days class="nx-countdown-digits">00</span>
957 <# if ( settings.nx_days_label ) { #>
958 <span class="nx-countdown-label">{{{ settings.nx_days_label }}}</span>
959 <# } #>
960 </div>
961 </li>
962 <# } #>
963
964 <# if ( settings.nx_show_hours ) { #>
965 <li class="nx-countdown-item">
966 <div class="nx-countdown-hours">
967 <span data-hours class="nx-countdown-digits">00</span>
968 <# if ( settings.nx_hours_label ) { #>
969 <span class="nx-countdown-label">{{{ settings.nx_hours_label }}}</span>
970 <# } #>
971 </div>
972 </li>
973 <# } #>
974
975 <# if ( settings.nx_show_minutes ) { #>
976 <li class="nx-countdown-item">
977 <div class="nx-countdown-minutes">
978 <span data-minutes class="nx-countdown-digits">00</span>
979 <# if ( settings.nx_minutes_label ) { #>
980 <span class="nx-countdown-label">{{{ settings.nx_minutes_label }}}</span>
981 <# } #>
982 </div>
983 </li>
984 <# } #>
985
986 <# if ( settings.nx_show_seconds ) { #>
987 <li class="nx-countdown-item">
988 <div class="nx-countdown-seconds">
989 <span data-seconds class="nx-countdown-digits">00</span>
990 <# if ( settings.nx_seconds_label ) { #>
991 <span class="nx-countdown-label">{{{ settings.nx_seconds_label }}}</span>
992 <# } #>
993 </div>
994 </li>
995 <# } #>
996
997 </ul>
998 </div>
999 <?php
1000 }
1001 }
1002