*/
public $elementor_themes = [];
public function __construct() {
parent::__construct();
add_action( 'init', [ $this, 'register_post_type' ] );
add_filter( 'get_edit_post_link', [ $this, 'filter_edit_post_link' ], 10, 3 );
add_filter( 'nx_filtered_post', [ $this, 'inject_elementor_html' ], 10, 2 );
add_action( 'wp_enqueue_scripts', [ $this, 'enqueue_elementor_assets' ], 20 );
add_action( 'wp_head', [ $this, 'print_section_constraint_css' ], 99 );
add_action( 'elementor/documents/register_controls', [ $this, 'register_popup_layout_controls' ] );
add_action( 'elementor/editor/after_enqueue_scripts', [ $this, 'enqueue_editor_live_preview' ] );
}
/**
* Print the popup section's width constraint inline in
.
*
* Two cases:
* 1. Sections that have the `nx-exit-intent-section` class baked in via the
* seed JSON's css_classes setting — constrained by the first rule.
* 2. The Elementor editor preview iframe loads the nx_exit_intent post
* directly as its own page (body.single-nx_exit_intent). The second
* rule constrains ANY section on that page, including legacy imports
* made before css_classes was added to the seed JSON.
*/
public function print_section_constraint_css() {
// Width is governed by the Layout panel's Width control via the
// `--nx-exit-width` CSS variable; fall back to the historical 540px cap
// when it is unset (older popups / default).
$vars = '';
if ( is_singular( 'nx_exit_intent' ) ) {
// Editor preview / direct view: resolve the variable from the saved
// Layout-panel settings on this document.
$layout = $this->get_popup_layout_settings( get_the_ID() );
if ( ! empty( $layout['width'] ) ) {
$vars .= '--nx-exit-width:' . $layout['width'] . ';';
}
if ( ! empty( $layout['height'] ) ) {
$vars .= '--nx-exit-height:' . $layout['height'] . ';';
}
}
echo "\n";
}
/**
* Server-side: inject the Elementor-rendered HTML + a `mode` flag into the
* REST payload so the React popup shell can render it.
*
* Runs for every campaign settings array via the `nx_filtered_post` filter;
* scoped to Exit Intent campaigns that have a linked, published nx_exit_intent.
*/
public function inject_elementor_html( $settings, $params ) {
if ( empty( $settings['source'] ) || $settings['source'] !== $this->id ) {
return $settings;
}
$elementor_id = isset( $settings['elementor_id'] ) ? (int) $settings['elementor_id'] : 0;
if ( ! $elementor_id || ! class_exists( '\\Elementor\\Plugin' ) ) {
$settings['mode'] = 'built_in';
return $settings;
}
if ( get_post_status( $elementor_id ) !== 'publish' ) {
$settings['mode'] = 'built_in';
return $settings;
}
// phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedHooknameFound -- Reviewed for the NotificationX codebase: acceptable in this context.
$resolved_id = apply_filters( 'wpml_object_id', $elementor_id, 'nx_exit_intent', true );
$html = \Elementor\Plugin::$instance->frontend->get_builder_content_for_display( $resolved_id, false );
// Surface the Layout-panel settings (registered in register_popup_layout_controls)
// so the popup runtime can honour them, and set --nx-exit-width on a wrapper so
// the section width constraint reflects the configured Width on the frontend.
$layout = $this->get_popup_layout_settings( $resolved_id );
$wrapper_vars = '';
if ( ! empty( $layout['width'] ) ) {
$wrapper_vars .= '--nx-exit-width:' . $layout['width'] . ';';
}
if ( ! empty( $layout['height'] ) ) {
$wrapper_vars .= '--nx-exit-height:' . $layout['height'] . ';';
}
if ( '' !== $wrapper_vars ) {
$html = '' . $html . '
';
}
$settings['mode'] = 'elementor';
$settings['elementor_html'] = $html;
$settings['popup_layout'] = $layout;
return $settings;
}
/**
* Read the Layout-panel settings off an nx_exit_intent Elementor document and
* normalise them into a flat array the popup runtime can consume.
*
* @param int $elementor_id
* @return array
*/
protected function get_popup_layout_settings( $elementor_id ) {
$defaults = [
'width' => '',
'height_mode' => 'fit',
'height' => '',
'horizontal' => 'center',
'vertical' => 'center',
'overlay' => true,
'close_button' => true,
'entrance_animation' => '',
'exit_animation' => '',
];
if ( ! class_exists( '\\Elementor\\Plugin' ) ) {
return $defaults;
}
$document = \Elementor\Plugin::$instance->documents->get( $elementor_id );
if ( ! $document ) {
return $defaults;
}
$size = static function ( $value ) {
if ( is_array( $value ) && isset( $value['size'] ) && '' !== $value['size'] ) {
return $value['size'] . ( isset( $value['unit'] ) ? $value['unit'] : 'px' );
}
return '';
};
$height_mode = $document->get_settings( 'nx_popup_height' );
// Width precedence: the Layout-panel Width control if the user set one,
// otherwise the design's own top-level container width (boxed_width).
// Without this, every popup falls back to the CSS 540px default, which
// crushes wider designs (e.g. the two-column 896px themes).
$width = $size( $document->get_settings( 'nx_popup_width' ) );
if ( '' === $width ) {
$width = $this->resolve_design_width( $document );
}
return [
'width' => $width,
'height_mode' => $height_mode ? $height_mode : 'fit',
'height' => 'custom' === $height_mode ? $size( $document->get_settings( 'nx_popup_custom_height' ) ) : '',
'horizontal' => $document->get_settings( 'nx_popup_horizontal' ) ?: 'center',
'vertical' => $document->get_settings( 'nx_popup_vertical' ) ?: 'center',
'overlay' => 'yes' === $document->get_settings( 'nx_popup_overlay' ),
'close_button' => 'yes' === $document->get_settings( 'nx_popup_close_button' ),
'entrance_animation' => (string) $document->get_settings( 'nx_popup_entrance_animation' ),
'exit_animation' => (string) $document->get_settings( 'nx_popup_exit_animation' ),
];
}
/**
* Derive the popup's intended width from its Elementor design — the widest
* px width among the top-level elements (boxed_width / width / content_width).
* Used as the default popup width when no Layout-panel Width is configured,
* so each design keeps its own width instead of the 540px CSS fallback.
* Only top-level elements are inspected so inner column widths are ignored.
*
* @param \Elementor\Core\Base\Document $document
* @return string e.g. "896px", or '' when no explicit px width is defined.
*/
protected function resolve_design_width( $document ) {
if ( ! $document || ! method_exists( $document, 'get_elements_data' ) ) {
return '';
}
$data = $document->get_elements_data();
if ( empty( $data ) || ! is_array( $data ) ) {
return '';
}
$max = 0;
foreach ( $data as $element ) {
if ( empty( $element['settings'] ) || ! is_array( $element['settings'] ) ) {
continue;
}
foreach ( [ 'boxed_width', 'width', 'content_width' ] as $key ) {
$val = isset( $element['settings'][ $key ] ) ? $element['settings'][ $key ] : null;
if ( is_array( $val ) && isset( $val['size'] ) && is_numeric( $val['size'] )
&& ( ! isset( $val['unit'] ) || 'px' === $val['unit'] ) ) {
$max = max( $max, (float) $val['size'] );
}
}
}
return $max > 0 ? $max . 'px' : '';
}
/**
* Make sure Elementor's per-document CSS/JS is enqueued on every page where
* an Exit Intent campaign can fire — get_builder_content_for_display alone
* registers some assets, but not on pages other than the document's own URL.
*/
public function enqueue_elementor_assets() {
if ( ! class_exists( '\\Elementor\\Core\\Files\\CSS\\Post' ) ) {
return;
}
$ids = [];
try {
$posts = \NotificationX\Core\PostType::get_instance()->get_posts( [ 'source' => $this->id ] );
foreach ( $posts as $post ) {
if ( ! empty( $post['elementor_id'] ) && empty( $post['enabled'] ) === false ) {
$ids[] = (int) $post['elementor_id'];
}
}
} catch ( \Exception $e ) {
return;
}
foreach ( $ids as $id ) {
try {
$css = \Elementor\Core\Files\CSS\Post::create( $id );
if ( $css ) {
$css->enqueue();
}
} catch ( \Exception $e ) {
// swallow — one broken doc shouldn't break the rest.
}
}
}
/**
* Register the post type that backs Elementor-designed Exit Intent popups.
*
* Mirrors PressBar's `nx_bar`: not public, but publicly_queryable so Elementor's
* preview routes resolve. `supports[]` must include `elementor` for Elementor's
* documents API to treat this as a first-class document.
*
* @return void
*/
public static function register_post_type() {
register_post_type( 'nx_exit_intent', [
'label' => __( 'NotificationX Exit Intent', 'notificationx' ),
'public' => false,
'publicly_queryable' => true,
'show_ui' => false,
'show_in_menu' => true,
'show_in_nav_menus' => false,
'exclude_from_search' => true,
'rewrite' => false,
'capability_type' => 'post',
'hierarchical' => false,
'menu_icon' => 'dashicons-admin-page',
'supports' => [ 'title', 'content', 'author', 'elementor' ],
] );
}
/**
* Add a "Layout" section to the Elementor document-settings panel, but ONLY
* for nx_exit_intent documents. Mirrors Elementor Pro's Popup → Layout panel
* (Width / Height / Position / Overlay / Close Button / Animations).
*
* Hooked on `elementor/documents/register_controls`, which fires for every
* document right after its built-in controls register. We bail for any other
* post type so these controls never leak into normal pages/posts.
*
* Width is wired live via the `--nx-exit-width` CSS variable that
* print_section_constraint_css()/inject_elementor_html() read; the remaining
* controls persist into the document's page settings (`_elementor_page_settings`)
* so the popup runtime can consume them.
*
* @param \Elementor\Core\Base\Document $document
* @return void
*/
public function register_popup_layout_controls( $document ) {
if ( ! is_object( $document ) || ! method_exists( $document, 'get_post' ) ) {
return;
}
$post = $document->get_post();
if ( ! $post || 'nx_exit_intent' !== $post->post_type ) {
return;
}
$cm = '\Elementor\Controls_Manager';
$document->start_controls_section(
'nx_popup_layout',
[
'label' => __( 'Layout', 'notificationx' ),
'tab' => $cm::TAB_SETTINGS,
]
);
$document->add_responsive_control(
'nx_popup_width',
[
'label' => __( 'Width', 'notificationx' ),
'type' => $cm::SLIDER,
'size_units' => [ 'px', '%', 'vw' ],
'range' => [
'px' => [ 'min' => 100, 'max' => 1140 ],
'%' => [ 'min' => 10, 'max' => 100 ],
'vw' => [ 'min' => 10, 'max' => 100 ],
],
// No default: when the user hasn't set a Width, the popup falls back
// to the design's own container width (resolve_design_width()), not a
// fixed 540px — otherwise wider designs (e.g. the 896px two-column
// themes) get crushed. An explicit value here still wins.
//
// NOTE: no `selectors` key — Elementor silently drops document-level
// controls that carry `selectors`. The value is applied server-side
// via the --nx-exit-width variable in print_section_constraint_css()
// (preview) and inject_elementor_html() (frontend) instead.
'default' => [ 'unit' => 'px', 'size' => '' ],
]
);
$document->add_control(
'nx_popup_height',
[
'label' => __( 'Height', 'notificationx' ),
'type' => $cm::SELECT,
'default' => 'fit',
'options' => [
'fit' => __( 'Fit To Content', 'notificationx' ),
'custom' => __( 'Custom Height', 'notificationx' ),
],
]
);
$document->add_responsive_control(
'nx_popup_custom_height',
[
'label' => __( 'Custom Height', 'notificationx' ),
'type' => $cm::SLIDER,
'size_units' => [ 'px', 'vh' ],
'range' => [
'px' => [ 'min' => 100, 'max' => 1000 ],
'vh' => [ 'min' => 10, 'max' => 100 ],
],
'default' => [ 'unit' => 'px', 'size' => 480 ],
'condition' => [ 'nx_popup_height' => 'custom' ],
// No `selectors` (see nx_popup_width note); applied via --nx-exit-height.
]
);
$document->add_control(
'nx_popup_position_heading',
[
'label' => __( 'Position', 'notificationx' ),
'type' => $cm::HEADING,
'separator' => 'before',
]
);
$document->add_responsive_control(
'nx_popup_horizontal',
[
'label' => __( 'Horizontal', 'notificationx' ),
'type' => $cm::CHOOSE,
'default' => 'center',
'options' => [
'start' => [ 'title' => __( 'Start', 'notificationx' ), 'icon' => 'eicon-h-align-left' ],
'center' => [ 'title' => __( 'Center', 'notificationx' ), 'icon' => 'eicon-h-align-center' ],
'end' => [ 'title' => __( 'End', 'notificationx' ), 'icon' => 'eicon-h-align-right' ],
],
]
);
$document->add_responsive_control(
'nx_popup_vertical',
[
'label' => __( 'Vertical', 'notificationx' ),
'type' => $cm::CHOOSE,
'default' => 'center',
'options' => [
'start' => [ 'title' => __( 'Top', 'notificationx' ), 'icon' => 'eicon-v-align-top' ],
'center' => [ 'title' => __( 'Middle', 'notificationx' ), 'icon' => 'eicon-v-align-middle' ],
'end' => [ 'title' => __( 'Bottom', 'notificationx' ), 'icon' => 'eicon-v-align-bottom' ],
],
]
);
$document->add_control(
'nx_popup_overlay',
[
'label' => __( 'Overlay', 'notificationx' ),
'type' => $cm::SWITCHER,
'label_on' => __( 'Show', 'notificationx' ),
'label_off' => __( 'Hide', 'notificationx' ),
'return_value' => 'yes',
'default' => 'yes',
'separator' => 'before',
]
);
$document->add_control(
'nx_popup_close_button',
[
'label' => __( 'Close Button', 'notificationx' ),
'type' => $cm::SWITCHER,
'label_on' => __( 'Show', 'notificationx' ),
'label_off' => __( 'Hide', 'notificationx' ),
'return_value' => 'yes',
'default' => 'yes',
]
);
$document->add_control(
'nx_popup_entrance_animation',
[
'label' => __( 'Entrance Animation', 'notificationx' ),
'type' => $cm::ANIMATION,
'separator' => 'before',
]
);
$document->add_control(
'nx_popup_exit_animation',
[
'label' => __( 'Exit Animation', 'notificationx' ),
'type' => $cm::EXIT_ANIMATION,
]
);
$document->end_controls_section();
}
/**
* Live-preview bridge for the Layout panel inside the Elementor editor.
*
* Document-level controls can't carry a `selectors` key (Elementor drops
* them), so Width/Height don't get Elementor's built-in live CSS injection.
* This registers page-settings change callbacks that write the
* `--nx-exit-width` / `--nx-exit-height` variables straight onto the preview
* iframe's as the slider moves — so changes reflect instantly instead
* of only after a reload.
*
* Scoped to nx_exit_intent documents only.
*
* @return void
*/
public function enqueue_editor_live_preview() {
if ( ! class_exists( '\\Elementor\\Plugin' ) ) {
return;
}
$post_id = \Elementor\Plugin::$instance->editor->get_post_id();
if ( ! $post_id || 'nx_exit_intent' !== get_post_type( $post_id ) ) {
return;
}
$js = <<<'JS'
( function ( $ ) {
function toCss( value ) {
if ( value && '' !== value.size && null != value.size ) {
return value.size + ( value.unit || 'px' );
}
return '';
}
function previewBody() {
var frame = elementor.$preview && elementor.$preview[0];
var win = frame && frame.contentWindow;
return win && win.document ? win.document.body : null;
}
function applyVar( name, value ) {
var body = previewBody();
if ( ! body ) { return; }
var css = toCss( value );
if ( css ) { body.style.setProperty( name, css ); }
else { body.style.removeProperty( name ); }
}
$( window ).on( 'elementor:init', function () {
if ( 'undefined' === typeof elementor || ! elementor.settings || ! elementor.settings.page ) {
return;
}
elementor.settings.page.addChangeCallback( 'nx_popup_width', function ( value ) {
applyVar( '--nx-exit-width', value );
} );
elementor.settings.page.addChangeCallback( 'nx_popup_custom_height', function ( value ) {
applyVar( '--nx-exit-height', value );
} );
} );
} )( jQuery );
JS;
wp_add_inline_script( 'elementor-editor', $js );
}
/**
* Create a new `nx_exit_intent` Elementor document from a seed theme and
* respond to the admin with the new post ID + Elementor edit URL.
*
* Counterpart of PressBar::create_bar_of_type_bar_with_elementor().
*
* @param array $params { theme_id: string }
* @return void Always responds via wp_send_json_{success,error}.
*/
public function create_exit_intent_with_elementor( $params ) {
if ( empty( $params['theme_id'] ) ) {
wp_send_json_error( 'missing_theme_id' );
}
$theme = sanitize_text_field( $params['theme_id'] );
$importer = new Importer();
$ID = $importer->create_nx( [
'theme' => $theme,
'post_title' => 'Design for NotificationX Exit Intent - ',
] );
if ( $ID && ! is_wp_error( $ID ) ) {
// Strip theme chrome — popup HTML inlines into the host page.
update_post_meta( $ID, '_wp_page_template', 'elementor_canvas' );
wp_send_json_success( [
'context' => [
'themes' => null,
'elementor_id' => $ID,
'elementor_edit_link' => \Elementor\Plugin::$instance->documents->get( $ID )->get_edit_url(),
],
] );
} else {
wp_send_json_error( is_wp_error( $ID ) ? $ID->get_error_message() : 'failed' );
}
}
/**
* Delete the linked `nx_exit_intent` Elementor post (and its WPML translations).
*
* @param int|string $elementor_id
* @return void
*/
public function delete_elementor_post( $elementor_id ) {
if ( empty( $elementor_id ) ) {
return;
}
// phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedHooknameFound -- Reviewed for the NotificationX codebase: acceptable in this context.
$languages = apply_filters( 'wpml_active_languages', null );
if ( is_array( $languages ) ) {
foreach ( $languages as $lang => $val ) {
// phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedHooknameFound -- Reviewed for the NotificationX codebase: acceptable in this context.
$translated_id = apply_filters( 'wpml_object_id', $elementor_id, 'nx_exit_intent', false, $lang );
if ( $translated_id ) {
Helper::delete_owned_post( $translated_id, 'nx_exit_intent' );
}
}
return;
}
Helper::delete_owned_post( $elementor_id, 'nx_exit_intent' );
}
/**
* Redirect WP "Edit" links for nx_exit_intent posts straight into the Elementor editor.
*
* @param string $link
* @param int $id
* @param string $context
* @return string
*/
public function filter_edit_post_link( $link, $id, $context ) {
$post = get_post( $id );
if ( $post && 'nx_exit_intent' === $post->post_type && class_exists( '\\Elementor\\Plugin' ) ) {
return \Elementor\Plugin::$instance->documents->get( $id )->get_edit_url();
}
return $link;
}
public function init_extension() {
$this->title = __( 'Exit Intent Popup', 'notificationx' );
$this->module_title = __( 'Exit Intent Popup', 'notificationx' );
$this->themes = [
'theme-one' => [
'source' => NOTIFICATIONX_ADMIN_URL . 'images/extensions/themes/exit-intent/exit-intent-theme-one.png',
'defaults' => [
'exit_intent_title' => __( 'Wait! Before You Go……', 'notificationx' ),
'exit_intent_subtitle' => __( "We'd love to get your feedback and help us make this better for everyone.", 'notificationx' ),
'exit_intent_button_text' => __( 'SUBMIT', 'notificationx' ),
// 'exit_intent_show_name' => true,
// 'exit_intent_show_email' => true,
'exit_intent_name_label' => __( 'Name *', 'notificationx' ),
'exit_intent_email_label' => __( 'Enter Your Email *', 'notificationx' ),
// 'exit_intent_show_message' => false,
'exit_intent_message_placeholder' => __( 'Your message...', 'notificationx' ),
'position' => 'center',
],
'column' => '5',
],
'theme-four' => [
'source' => NOTIFICATIONX_ADMIN_URL . 'images/extensions/themes/exit-intent/exit-intent-theme-four.png',
'defaults' => [
'exit_intent_t4_badge' => __( 'Before you go...', 'notificationx' ),
'exit_intent_t4_title' => __( 'Watch this short demo video', 'notificationx' ),
'exit_intent_t4_subtitle' => __( 'See how our product simplifies your workflow.', 'notificationx' ),
'exit_intent_image_url' => [ 'url' => 'https://notificationx.com/wp-content/uploads/2026/05/exit-intend-theme-four.jpg' ],
'exit_intent_t4_video_url' => '',
'position' => 'center',
],
'column' => '5',
],
'theme-three' => [
'source' => NOTIFICATIONX_ADMIN_URL . 'images/extensions/themes/exit-intent/exit-intent-theme-three.png',
'defaults' => [
'exit_intent_t3_title' => __( "Wait, don't go!", 'notificationx' ),
'exit_intent_t3_subtitle' => __( 'Before you leave, we have a special offer just for you!', 'notificationx' ),
'exit_intent_t3_offer' => __( 'Get 15% off your next purchase!', 'notificationx' ),
'exit_intent_t3_coupon_text' => __( "Use code STAY15 at checkout. Don't miss out on this limited-time offer.", 'notificationx' ),
'exit_intent_button_text' => __( 'Claim Offer', 'notificationx' ),
'exit_intent_dismiss_text' => __( 'No, thanks!', 'notificationx' ),
'exit_intent_image_url' => [ 'url' => 'https://notificationx.com/wp-content/uploads/2026/05/exit-intend-theme-three.png' ],
'position' => 'center',
],
'column' => '5',
],
'theme-six' => [
'source' => NOTIFICATIONX_ADMIN_URL . 'images/extensions/themes/exit-intent/exit-intent-theme-seven.png',
'defaults' => [
'exit_intent_t6_title' => __( 'Limited Edition Bass Boost Headphones', 'notificationx' ),
// 'exit_intent_t6_show_timer' => true,
'exit_intent_t6_countdown_label' => __( 'Offer Ends In', 'notificationx' ),
'exit_intent_countdown_end' => '',
'exit_intent_t6_days_label' => __( 'DAYS', 'notificationx' ),
'exit_intent_t6_hours_label' => __( 'HOURS', 'notificationx' ),
'exit_intent_t6_minutes_label' => __( 'MIN', 'notificationx' ),
'exit_intent_t6_seconds_label' => __( 'SEC', 'notificationx' ),
'exit_intent_button_text' => __( 'Grab Now', 'notificationx' ),
'exit_intent_image_url' => [ 'url' => 'https://notificationx.com/wp-content/uploads/2026/05/exit-intend-theme-six.png' ],
'position' => 'center',
],
'column' => '5',
'is_pro' => true,
],
'theme-two' => [
'source' => NOTIFICATIONX_ADMIN_URL . 'images/extensions/themes/exit-intent/exit-intent-theme-two.png',
'defaults' => [
'exit_intent_sale_badge' => __( 'Flash Sale', 'notificationx' ),
'exit_intent_sale_headline' => __( '50% OFF', 'notificationx' ),
'exit_intent_sale_desc' => __( 'ON ENTIRE ORDER', 'notificationx' ),
'exit_intent_button_text' => __( 'Shop The Flash Sale Now', 'notificationx' ),
'exit_intent_dismiss_text' => __( 'NO, THANKS!', 'notificationx' ),
'exit_intent_image_url' => [ 'url' => 'https://notificationx.com/wp-content/uploads/2026/05/exit-intend-theme-two.jpg' ],
'position' => 'center',
],
'column' => '5',
'is_pro' => true,
],
'theme-seven' => [
'source' => NOTIFICATIONX_ADMIN_URL . 'images/extensions/themes/exit-intent/exit-intent-theme-six.png',
'defaults' => [
'exit_intent_t7_headline' => __( 'Turn Your House Into a Home', 'notificationx' ),
'exit_intent_t7_discount_text' => __( 'Your First Order Comes With a Surprise Deal!', 'notificationx' ),
'exit_intent_t7_description' => __( 'Handpicked decor that feels like home the moment it arrives.', 'notificationx' ),
'exit_intent_t7_email_placeholder' => __( 'Enter your email', 'notificationx' ),
'exit_intent_button_text' => __( 'SEND COUPON', 'notificationx' ),
'exit_intent_image_url' => [ 'url' => 'https://notificationx.com/wp-content/uploads/2026/05/exit-intend-theme-five.png' ],
'position' => 'center',
],
'column' => '5',
'is_pro' => true,
],
'theme-five' => [
'source' => NOTIFICATIONX_ADMIN_URL . 'images/extensions/themes/exit-intent/exit-intent-theme-five.png',
'defaults' => [
'exit_intent_t5_title' => __( 'Flash Sale', 'notificationx' ),
'exit_intent_t5_headline' => __( '50% OFF', 'notificationx' ),
'exit_intent_t5_desc' => __( 'ON ENTIRE ORDER', 'notificationx' ),
'exit_intent_t5_countdown_label' => __( 'LIMITED-TIME OFFER! SALE ENDS IN', 'notificationx' ),
'exit_intent_countdown_end' => '',
'exit_intent_t5_days_label' => __( 'DAYS', 'notificationx' ),
'exit_intent_t5_hours_label' => __( 'HRS', 'notificationx' ),
'exit_intent_t5_minutes_label' => __( 'MIN', 'notificationx' ),
'exit_intent_t5_seconds_label' => __( 'SEC', 'notificationx' ),
'exit_intent_t5_timer_bg' => '#fff0f5',
'exit_intent_t5_timer_color' => '#e91e63',
'exit_intent_button_text' => __( 'Shop The Flash Sale Now', 'notificationx' ),
'exit_intent_dismiss_text' => __( 'NO, THANKS!', 'notificationx' ),
'exit_intent_image_url' => [ 'url' => 'https://notificationx.com/wp-content/uploads/2026/05/exit-intend-theme-six.jpg' ],
'position' => 'center',
],
'column' => '5',
'is_pro' => true,
],
];
// Elementor seed themes for the "Build With Elementor" modal.
// Each entry has a matching JSON file under jsons/{value}.json (Task 07).
// Preview images live under assets/admin/images/extensions/themes/exit-intent-elementor/.
// Until per-theme Elementor previews are rendered, we fall back to the existing
// built-in screenshots so the modal renders with a real image.
// Order intentionally mirrors the built-in $themes preset order above
// (one, four, three, six, two, seven, five) so the Elementor modal lists
// the same designs in the same sequence as the Default-theme picker.
//
// Unlike $themes (processed by Extension::__nx_themes), this array is fed
// straight to the radio-card field, so we must resolve the pro badge here:
// only flag a theme as pro when the Pro plugin is NOT active.
$is_pro_badge = ! NotificationX::is_pro();
$this->elementor_themes = [
'theme-one' => [
'label' => 'theme-one',
'value' => 'theme-one',
'icon' => NOTIFICATIONX_ADMIN_URL . 'images/extensions/themes/exit-intent/exit-intent-theme-one.png',
'column' => '6',
'title' => 'Exit Intent Theme One',
],
'theme-four' => [
'label' => 'theme-four',
'value' => 'theme-four',
'icon' => NOTIFICATIONX_ADMIN_URL . 'images/extensions/themes/exit-intent/exit-intent-theme-four.png',
'column' => '6',
'title' => 'Exit Intent Theme Four',
],
'theme-three' => [
'label' => 'theme-three',
'value' => 'theme-three',
'icon' => NOTIFICATIONX_ADMIN_URL . 'images/extensions/themes/exit-intent/exit-intent-theme-three.png',
'column' => '6',
'title' => 'Exit Intent Theme Three',
],
'theme-six' => [
'label' => 'theme-six',
'value' => 'theme-six',
'icon' => NOTIFICATIONX_ADMIN_URL . 'images/extensions/themes/exit-intent/exit-intent-theme-six.png',
'column' => '6',
'title' => 'Exit Intent Theme Six',
'is_pro' => $is_pro_badge,
],
'theme-two' => [
'label' => 'theme-two',
'value' => 'theme-two',
'icon' => NOTIFICATIONX_ADMIN_URL . 'images/extensions/themes/exit-intent/exit-intent-theme-two.png',
'column' => '6',
'title' => 'Exit Intent Theme Two',
'is_pro' => $is_pro_badge,
],
'theme-seven' => [
'label' => 'theme-seven',
'value' => 'theme-seven',
'icon' => NOTIFICATIONX_ADMIN_URL . 'images/extensions/themes/exit-intent/exit-intent-theme-seven.png',
'column' => '6',
'title' => 'Exit Intent Theme Seven',
'is_pro' => $is_pro_badge,
],
'theme-five' => [
'label' => 'theme-five',
'value' => 'theme-five',
'icon' => NOTIFICATIONX_ADMIN_URL . 'images/extensions/themes/exit-intent/exit-intent-theme-five.png',
'column' => '6',
'title' => 'Exit Intent Theme Five',
'is_pro' => $is_pro_badge,
],
];
}
public function init_fields() {
parent::init_fields();
add_filter( 'nx_content_fields', [ $this, 'content_fields' ], 999 );
add_filter( 'nx_design_tab_fields', [ $this, 'design_fields' ], 99 );
add_filter( 'nx_design_tab_fields', [ $this, 'builder_tabs_fields' ], 100 );
add_filter( 'nx_customize_fields', [ $this, 'customize_fields' ], 999 );
add_filter( 'nx_display_fields', [ $this, 'display_fields' ], 999 );
// Hide per-theme content sections when an Elementor doc is linked (Task 06).
// We deliberately do NOT hide the themes radio-card itself — keeping it
// visible on the Default tab lets users switch back to a built-in theme
// after they've imported an Elementor design.
add_filter( 'nx_content_fields', [ $this, 'suppress_when_elementor' ], 1001 );
// Hide the whole Content wizard step when an Elementor design is linked —
// suppress_when_elementor() empties every content section in that case, so
// the step would otherwise render as a blank tab.
add_filter( 'nx_metabox_tabs', [ $this, 'hide_content_tab_for_elementor' ] );
}
/**
* Remove the Content step from the wizard for Exit Intent campaigns that are
* built with Elementor. Elementor owns all of the popup's content there (every
* `exit_intent_*_section` is suppressed by suppress_when_elementor()), leaving
* the Content tab empty. Built-in themes keep the Content step, and all other
* sources are untouched.
*
* The tab stays visible UNLESS (source is Exit Intent AND elementor_id is a
* number), expressed below as the OR'd "show when" rule.
*/
public function hide_content_tab_for_elementor( $tabs ) {
if ( empty( $tabs['content_tab'] ) ) {
return $tabs;
}
$show_rule = Rules::_logicalRule( [
Rules::_is( 'source', $this->id, true ),
Rules::_isOfType( 'elementor_id', 'number', true ),
], 'or' );
$tabs['content_tab'] = Rules::add( $show_rule, $tabs['content_tab'] );
return $tabs;
}
/**
* Hide every per-theme content section once an Elementor design is linked.
* Elementor owns all of these fields; showing them would let users edit
* values with no visible effect on the rendered popup.
*/
public function suppress_when_elementor( $fields ) {
foreach ( $fields as $key => $field ) {
if ( strpos( $key, 'exit_intent_' ) === 0 && substr( $key, -8 ) === '_section' ) {
$fields[ $key ] = Rules::isOfType( 'elementor_id', 'number', true, $field );
}
}
return $fields;
}
/**
* @deprecated Kept for back-compat only; the filter that called this has
* been removed so the themes radio stays visible on the Default tab even
* when an Elementor design is linked (lets users switch back).
*/
public function suppress_themes_radio( $fields ) {
if ( ! isset( $fields['themes']['fields']['themes']['rules'] ) ) {
return $fields;
}
$existing = $fields['themes']['fields']['themes']['rules'];
// Additional clause: either we're NOT on Exit Intent (so this rule
// shouldn't change anything for other sources), OR elementor_id is
// not yet set. Combined via AND with the existing tab-gate so other
// sources (e.g. PressBar) keep their tab-based hiding intact.
$additional = Rules::logicalRule( [
Rules::is( 'source', $this->id, true ),
Rules::isOfType( 'elementor_id', 'number', true ),
], 'or' );
$fields['themes']['fields']['themes']['rules'] = Rules::logicalRule( [
$existing,
$additional,
], 'and' );
return $fields;
}
/**
* Restructures the Themes section into two tabs:
* 1. Default — original 7 React themes grid (the `themes` radio-card,
* already gated to themes_tab='for_desktop' in GlobalFields).
* 2. Custom — Build With Elementor button + modal, plus Edit/Remove
* and Install fallback after a doc is linked.
*
* Matches Notification Bar's Default/Custom tab structure.
*/
public function builder_tabs_fields( $fields ) {
if ( empty( $fields['themes']['fields']['themes_section']['fields']['themes_tab']['fields'] ) ) {
return $fields;
}
$tab =& $fields['themes']['fields']['themes_section']['fields']['themes_tab']['fields'];
// Hide the global "For Desktop" / "For Mobile" tabs for Exit Intent only — we
// ship our own Default + Custom tabs below.
foreach ( [ 'for_desktop', 'for_mobile' ] as $key ) {
if ( isset( $tab[ $key ] ) ) {
$tab[ $key ] = Rules::is( 'source', $this->id, true, $tab[ $key ] );
}
}
// Expand the global themes radio-card so it ALSO renders when our new
// Default tab is active. Without this, the radio would never appear for
// Exit Intent — its existing rule is hard-coded to themes_tab='for_desktop'.
if ( isset( $fields['themes']['fields']['themes'] ) ) {
$fields['themes']['fields']['themes']['rules'] = Rules::logicalRule( [
Rules::is( 'themes_tab', 'for_desktop' ),
Rules::is( 'themes_tab', 'exit_intent_default_tab' ),
], 'or' );
}
$is_installed = Helper::is_plugin_installed( 'elementor/elementor.php' );
$install_activate_text = $is_installed
? __( 'Activate Elementor', 'notificationx' )
: __( 'Install Elementor', 'notificationx' );
// Default tab — unique name (no collision with global for_desktop).
$tab[] = [
'label' => __( 'Default', 'notificationx' ),
'name' => 'exit_intent_default_tab',
'id' => 'exit_intent_default_tab',
'type' => 'section',
'icon' => NOTIFICATIONX_ADMIN_URL . 'images/icons/nxbar-presets-icon.svg',
'rules' => Rules::is( 'source', $this->id ),
];
// The Custom tab — only renders for Exit Intent campaigns.
$tab[] = [
'label' => __( 'Custom', 'notificationx' ),
'name' => 'exit_intent_custom_tab',
'id' => 'exit_intent_custom_tab',
'type' => 'section',
'icon' => NOTIFICATIONX_ADMIN_URL . 'images/icons/nxbar-custom-tab.svg',
'rules' => Rules::is( 'source', $this->id ),
'fields' => [
// Preview image / empty-state illustration (reuses NxBarPresets).
'exit_intent_custom_preview' => [
'name' => 'exit_intent_custom_preview',
'type' => 'exit-intent-custom',
'label' => __( 'Exit Intent', 'notificationx' ),
'priority' => 5,
],
// Edit With Elementor — shown when an Elementor doc is linked.
'elementor_edit_link' => [
'name' => 'elementor_edit_link',
'type' => 'button',
'text' => __( 'Edit With Elementor', 'notificationx' ),
'href' => -1,
'priority' => 10,
'target' => '_blank',
'rules' => Rules::logicalRule( [
Rules::is( 'elementor_edit_link', false, true ),
Rules::isOfType( 'elementor_edit_link', 'string' ),
Rules::is( 'elementor_id', false, true ),
] ),
],
// Remove — deletes the Elementor doc and resets state.
'nx-exit-intent_with_elementor-remove' => [
'name' => 'nx-exit-intent_with_elementor-remove',
'type' => 'button',
'text' => __( 'Remove', 'notificationx' ),
'priority' => 15,
'rules' => Rules::logicalRule( [
Rules::is( 'elementor_id', false, true ),
Rules::is( 'is_elementor', true ),
Rules::is( 'source', $this->id ),
] ),
'ajax' => [
'on' => 'click',
'api' => '/notificationx/v1/exit-intent/elementor/remove',
'data' => [ 'elementor_id' => '@elementor_id' ],
'hideSwal' => true,
],
'trigger' => [
[
'type' => 'setFieldValue',
'action' => [
'elementor_id' => false,
'elementor_edit_link' => '',
'elementor_exit_theme' => 'theme-one',
'is_confirmed' => false,
'themes' => $this->id . '_theme-one',
],
],
],
],
// Build With Elementor — modal with seed-theme picker.
'nx-exit-intent_with_elementor' => [
'name' => 'nx-exit-intent_with_elementor',
'type' => 'modal',
'priority' => 20,
'button' => [
'name' => 'build_with_elementor',
'text' => __( 'Build With Elementor', 'notificationx' ),
'trigger' => [
[
'type' => 'setFieldValue',
'action' => [ 'import_elementor_theme' => false ],
],
],
],
'confirm_button' => [
'type' => 'button',
'name' => 'import_elementor_theme',
'group' => true,
'fields' => [
[
'type' => 'button',
'name' => 'import_elementor_theme',
'default' => false,
'text' => [
'normal' => __( 'Import', 'notificationx' ),
'saved' => __( 'Import', 'notificationx' ),
'loading' => __( 'Importing...', 'notificationx' ),
],
'ajax' => [
'on' => 'click',
'api' => '/notificationx/v1/exit-intent/elementor/import',
'data' => [ 'theme_id' => '@elementor_exit_theme' ],
'trigger' => '@is_confirmed:true',
'hideSwal' => true,
],
'rules' => Rules::is( 'is_confirmed', true, true ),
],
[
'type' => 'button',
'name' => 'import_elementor_theme_next',
'default' => false,
'text' => __( 'Next', 'notificationx' ),
'rules' => Rules::is( 'is_confirmed', true ),
'trigger' => [
[
'type' => 'setContext',
'action' => [ 'config.active' => 'display_tab' ],
],
[
'type' => 'setFieldValue',
'action' => [ 'import_elementor_theme_next' => true ],
],
],
],
],
],
'cancel' => 'import_elementor_theme_next',
'body' => [
'header' => __( 'Choose Your ', 'notificationx' ),
'fields' => [
'themes' => [
'type' => 'radio-card',
'name' => 'elementor_exit_theme',
'style' => [ 'label' => [ 'position' => 'top' ] ],
'rules' => Rules::is( 'is_confirmed', true, true ),
'default' => 'theme-one',
'options' => $this->elementor_themes,
],
],
],
'rules' => Rules::logicalRule( [
Rules::is( 'elementor_id', false ),
Rules::is( 'is_elementor', true ),
Rules::is( 'is_confirmed', true, true ),
Rules::is( 'source', $this->id ),
] ),
],
// Install / Activate Elementor — fallback when Elementor isn't active.
'nx-exit-intent_with_elementor_install' => [
'name' => 'nx-exit-intent_with_elementor_install',
'type' => 'button',
'priority' => 25,
'text' => [
'normal' => $install_activate_text,
'saved' => $is_installed ? __( 'Activated Elementor', 'notificationx' ) : __( 'Installed Elementor', 'notificationx' ),
'loading' => $is_installed ? __( 'Activating Elementor...', 'notificationx' ) : __( 'Installing Elementor...', 'notificationx' ),
],
'rules' => Rules::logicalRule( [
Rules::is( 'is_elementor', false ),
Rules::is( 'source', $this->id ),
] ),
'ajax' => [
'on' => 'click',
'api' => '/notificationx/v1/core-install',
'data' => [
'source' => $this->id,
'slug' => 'elementor',
'file' => 'elementor.php',
'is_installed' => $is_installed,
],
'swal' => [
'icon' => 'success',
'text' => __( 'Successfully Activated', 'notificationx' ),
],
'trigger' => '@is_elementor:true',
],
],
// Hidden state fields (Task 05).
'is_elementor' => [
'name' => 'is_elementor',
'type' => 'hidden',
'default' => class_exists( '\\Elementor\\Plugin' ),
'rules' => Rules::is( 'source', $this->id ),
],
'elementor_id' => [
'name' => 'elementor_id',
'type' => 'hidden',
'default' => false,
'rules' => Rules::is( 'source', $this->id ),
],
'is_confirmed' => [
'name' => 'is_confirmed',
'type' => 'hidden',
'default' => false,
],
],
];
// Build With AI tab — Pro feature. Free plugin only registers the tab
// shell + field type; the Pro plugin supplies the actual builder via
// the `nx_build_ai_render` filter (see PressBar's `nxbar_build_with_ai`
// for the same pattern already shipped for Notification Bar).
$tab[] = [
'label' => __( 'Build With AI', 'notificationx' ),
'name' => 'exit_intent_ai_tab',
'id' => 'exit_intent_ai_tab',
'type' => 'section',
'icon' => NOTIFICATIONX_ADMIN_URL . 'images/icons/build-with-ai-icon.svg',
'rules' => Rules::is( 'source', $this->id ),
'fields' => [
'exit_intent_ai_tab' => [
'label' => __( 'Build With AI', 'notificationx' ),
'name' => 'exit_intent_ai_tab',
'id' => 'exit_intent_ai_tab',
'type' => 'section',
'icon' => NOTIFICATIONX_ADMIN_URL . 'images/responsive/desktop.svg',
'fields' => [
'exit_intent_ai_tab_fields' => [
'name' => 'exit_intent_ai_tab_fields',
'type' => 'exit-intent-build_with_ai',
'label' => __( 'Exit Intent', 'notificationx' ),
'priority' => 10,
],
],
],
],
];
return $fields;
}
public function display_fields( $fields ) {
if ( isset( $fields['image-section'] ) ) {
$fields['image-section'] = Rules::is( 'source', $this->id, true, $fields['image-section'] );
}
return $fields;
}
public function content_fields( $fields ) {
// Hide standard content fields for this source
if ( isset( $fields['utm_options'] ) ) {
$fields['utm_options'] = Rules::is( 'source', $this->id, true, $fields['utm_options'] );
}
if ( isset( $fields['content'] ) ) {
$fields['content'] = Rules::is( 'source', $this->id, true, $fields['content'] );
}
if ( isset( $fields['link_options'] ) ) {
$fields['link_options'] = Rules::is( 'source', $this->id, true, $fields['link_options'] );
}
// ── Theme Two content fields ─────────────────────────────────────────────
$fields['exit_intent_theme_two_section'] = [
'label' => __( 'Exit Intent Content', 'notificationx' ),
'name' => 'exit_intent_theme_two_section',
'type' => 'section',
'priority' => 5,
'rules' => Rules::logicalRule( [
Rules::is( 'source', $this->id ),
Rules::is( 'themes', $this->id . '_theme-two' ),
] ),
'fields' => [
[
'label' => __( 'Right Panel Image', 'notificationx' ),
'name' => 'exit_intent_image_url',
'type' => 'media',
'priority' => 5,
'default' => [
'url' => 'https://notificationx.com/wp-content/uploads/2026/05/exit-intend-theme-two-five-seven.jpg',
],
'help' => __( 'Upload or select the image to display in the right panel.', 'notificationx' ),
],
[
'label' => __( 'Sale Badge Text', 'notificationx' ),
'name' => 'exit_intent_sale_badge',
'type' => 'text',
'priority' => 10,
'default' => __( 'Flash Sale', 'notificationx' ),
],
[
'label' => __( 'Sale Headline', 'notificationx' ),
'name' => 'exit_intent_sale_headline',
'type' => 'text',
'priority' => 20,
'default' => __( '50% OFF', 'notificationx' ),
],
[
'label' => __( 'Sale Description', 'notificationx' ),
'name' => 'exit_intent_sale_desc',
'type' => 'text',
'priority' => 30,
'default' => __( 'ON ENTIRE ORDER', 'notificationx' ),
],
[
'label' => __( 'Button Text', 'notificationx' ),
'name' => 'exit_intent_button_text',
'type' => 'text',
'priority' => 60,
'default' => __( 'Shop The Flash Sale Now', 'notificationx' ),
],
[
'label' => __( 'Button URL', 'notificationx' ),
'name' => 'exit_intent_button_url',
'type' => 'text',
'priority' => 61,
'default' => '',
'help' => __( 'Where the CTA button sends visitors. Leave empty to just dismiss the popup.', 'notificationx' ),
],
[
'label' => __( 'Open in New Tab', 'notificationx' ),
'name' => 'exit_intent_button_new_tab',
'type' => 'toggle',
'priority' => 62,
'default' => true,
],
[
'label' => __( 'Dismiss Link Text', 'notificationx' ),
'name' => 'exit_intent_dismiss_text',
'type' => 'text',
'priority' => 70,
'default' => __( 'NO, THANKS!', 'notificationx' ),
],
],
];
// ── Theme Three content fields ────────────────────────────────────────────
$fields['exit_intent_theme_three_section'] = [
'label' => __( 'Exit Intent Content', 'notificationx' ),
'name' => 'exit_intent_theme_three_section',
'type' => 'section',
'priority' => 5,
'rules' => Rules::logicalRule( [
Rules::is( 'source', $this->id ),
Rules::is( 'themes', $this->id . '_theme-three' ),
] ),
'fields' => [
[
'label' => __( 'Character Image', 'notificationx' ),
'name' => 'exit_intent_image_url',
'type' => 'media',
'priority' => 5,
'default' => [
'url' => 'https://notificationx.com/wp-content/uploads/2026/05/exit-intend-theme-three.png',
],
'help' => __( 'Upload or select a character/illustration image. It will appear above the popup card.', 'notificationx' ),
],
[
'label' => __( 'Headline', 'notificationx' ),
'name' => 'exit_intent_t3_title',
'type' => 'text',
'priority' => 10,
'default' => __( "Wait, don't go!", 'notificationx' ),
],
[
'label' => __( 'Subtitle', 'notificationx' ),
'name' => 'exit_intent_t3_subtitle',
'type' => 'text',
'priority' => 20,
'default' => __( 'Before you leave, we have a special offer just for you!', 'notificationx' ),
],
[
'label' => __( 'Offer Text', 'notificationx' ),
'name' => 'exit_intent_t3_offer',
'type' => 'text',
'priority' => 30,
'default' => __( 'Get 15% off your next purchase!', 'notificationx' ),
],
[
'label' => __( 'Coupon / Details Text', 'notificationx' ),
'name' => 'exit_intent_t3_coupon_text',
'type' => 'text',
'priority' => 40,
'default' => __( "Use code STAY15 at checkout. Don't miss out on this limited-time offer.", 'notificationx' ),
],
[
'label' => __( 'Button Text', 'notificationx' ),
'name' => 'exit_intent_button_text',
'type' => 'text',
'priority' => 50,
'default' => __( 'Claim Offer', 'notificationx' ),
],
[
'label' => __( 'Button URL', 'notificationx' ),
'name' => 'exit_intent_button_url',
'type' => 'text',
'priority' => 51,
'default' => '',
'help' => __( 'Where the CTA button sends visitors. Leave empty to just dismiss the popup.', 'notificationx' ),
],
[
'label' => __( 'Open in New Tab', 'notificationx' ),
'name' => 'exit_intent_button_new_tab',
'type' => 'toggle',
'priority' => 52,
'default' => true,
],
[
'label' => __( 'Dismiss Link Text', 'notificationx' ),
'name' => 'exit_intent_dismiss_text',
'type' => 'text',
'priority' => 60,
'default' => __( 'No, thanks!', 'notificationx' ),
],
],
];
// ── Theme Four content fields ─────────────────────────────────────────────
$fields['exit_intent_theme_four_section'] = [
'label' => __( 'Exit Intent Content', 'notificationx' ),
'name' => 'exit_intent_theme_four_section',
'type' => 'section',
'priority' => 5,
'rules' => Rules::logicalRule( [
Rules::is( 'source', $this->id ),
Rules::is( 'themes', $this->id . '_theme-four' ),
] ),
'fields' => [
[
'label' => __( 'Video Thumbnail', 'notificationx' ),
'name' => 'exit_intent_image_url',
'type' => 'media',
'priority' => 5,
'default' => [
'url' => 'https://notificationx.com/wp-content/uploads/2026/05/exit-intend-theme-four.jpg',
],
'help' => __( 'Upload or select the video thumbnail/preview image.', 'notificationx' ),
],
[
'label' => __( 'Badge Text', 'notificationx' ),
'name' => 'exit_intent_t4_badge',
'type' => 'text',
'priority' => 10,
'default' => __( 'Before you go...', 'notificationx' ),
],
[
'label' => __( 'Headline', 'notificationx' ),
'name' => 'exit_intent_t4_title',
'type' => 'text',
'priority' => 20,
'default' => __( 'Watch this short demo video', 'notificationx' ),
],
[
'label' => __( 'Subtitle', 'notificationx' ),
'name' => 'exit_intent_t4_subtitle',
'type' => 'text',
'priority' => 30,
'default' => __( 'See how our product simplifies your workflow.', 'notificationx' ),
],
[
'label' => __( 'Video URL', 'notificationx' ),
'name' => 'exit_intent_t4_video_url',
'type' => 'text',
'priority' => 40,
'default' => '',
'placeholder' => 'https://www.youtube.com/watch?v=...',
'help' => __( 'Paste a YouTube, Vimeo, or other video platform URL.', 'notificationx' ),
],
],
];
// ── Theme Five content fields ────────────────────────────────────────────
$fields['exit_intent_theme_five_section'] = [
'label' => __( 'Exit Intent Content', 'notificationx' ),
'name' => 'exit_intent_theme_five_section',
'type' => 'section',
'priority' => 5,
'rules' => Rules::logicalRule( [
Rules::is( 'source', $this->id ),
Rules::is( 'themes', $this->id . '_theme-five' ),
] ),
'fields' => [
[
'label' => __( 'Right Panel Image', 'notificationx' ),
'name' => 'exit_intent_image_url',
'type' => 'media',
'priority' => 5,
'default' => [
'url' => 'https://notificationx.com/wp-content/uploads/2026/05/exit-intend-theme-two-five-seven.jpg',
],
'help' => __( 'Upload or select the image to display in the right panel.', 'notificationx' ),
],
[
'label' => __( 'Title', 'notificationx' ),
'name' => 'exit_intent_t5_title',
'type' => 'text',
'priority' => 10,
'default' => __( 'Flash Sale', 'notificationx' ),
],
[
'label' => __( 'Headline', 'notificationx' ),
'name' => 'exit_intent_t5_headline',
'type' => 'text',
'priority' => 20,
'default' => __( '50% OFF', 'notificationx' ),
],
[
'label' => __( 'Description', 'notificationx' ),
'name' => 'exit_intent_t5_desc',
'type' => 'text',
'priority' => 30,
'default' => __( 'ON ENTIRE ORDER', 'notificationx' ),
],
[
'label' => __( 'Button Text', 'notificationx' ),
'name' => 'exit_intent_button_text',
'type' => 'text',
'priority' => 60,
'default' => __( 'Shop The Flash Sale Now', 'notificationx' ),
],
[
'label' => __( 'Button URL', 'notificationx' ),
'name' => 'exit_intent_button_url',
'type' => 'text',
'priority' => 61,
'default' => '',
'help' => __( 'Where the CTA button sends visitors. Leave empty to just dismiss the popup.', 'notificationx' ),
],
[
'label' => __( 'Open in New Tab', 'notificationx' ),
'name' => 'exit_intent_button_new_tab',
'type' => 'toggle',
'priority' => 62,
'default' => true,
],
[
'label' => __( 'Dismiss Link Text', 'notificationx' ),
'name' => 'exit_intent_dismiss_text',
'type' => 'text',
'priority' => 70,
'default' => __( 'NO, THANKS!', 'notificationx' ),
],
],
];
// ── Theme Five Timer Settings ────────────────────────────────────────────
$fields['exit_intent_theme_five_timer_section'] = [
'label' => __( 'Timer Settings', 'notificationx' ),
'name' => 'exit_intent_theme_five_timer_section',
'type' => 'section',
'priority' => 6,
'rules' => Rules::logicalRule( [
Rules::is( 'source', $this->id ),
Rules::is( 'themes', $this->id . '_theme-five' ),
] ),
'fields' => [
[
'label' => __( 'Show Countdown Timer', 'notificationx' ),
'name' => 'exit_intent_t5_show_timer',
'type' => 'toggle',
'priority' => 5,
'default' => true,
],
[
'label' => __( 'Countdown Label', 'notificationx' ),
'name' => 'exit_intent_t5_countdown_label',
'type' => 'text',
'priority' => 10,
'default' => __( 'LIMITED-TIME OFFER! SALE ENDS IN', 'notificationx' ),
'rules' => Rules::is( 'exit_intent_t5_show_timer', true ),
],
[
'label' => __( 'Sale End Date & Time', 'notificationx' ),
'name' => 'exit_intent_countdown_end',
'type' => 'date',
'priority' => 20,
'default' => '',
'help' => __( 'Pick the date and time when the sale ends. Leave empty to display static demo numbers.', 'notificationx' ),
'rules' => Rules::is( 'exit_intent_t5_show_timer', true ),
],
[
'label' => __( 'Days Label', 'notificationx' ),
'name' => 'exit_intent_t5_days_label',
'type' => 'text',
'priority' => 30,
'default' => __( 'DAYS', 'notificationx' ),
'rules' => Rules::is( 'exit_intent_t5_show_timer', true ),
],
[
'label' => __( 'Hours Label', 'notificationx' ),
'name' => 'exit_intent_t5_hours_label',
'type' => 'text',
'priority' => 40,
'default' => __( 'HRS', 'notificationx' ),
'rules' => Rules::is( 'exit_intent_t5_show_timer', true ),
],
[
'label' => __( 'Minutes Label', 'notificationx' ),
'name' => 'exit_intent_t5_minutes_label',
'type' => 'text',
'priority' => 50,
'default' => __( 'MIN', 'notificationx' ),
'rules' => Rules::is( 'exit_intent_t5_show_timer', true ),
],
[
'label' => __( 'Seconds Label', 'notificationx' ),
'name' => 'exit_intent_t5_seconds_label',
'type' => 'text',
'priority' => 60,
'default' => __( 'SEC', 'notificationx' ),
'rules' => Rules::is( 'exit_intent_t5_show_timer', true ),
],
[
'label' => __( 'Timer Box Background', 'notificationx' ),
'name' => 'exit_intent_t5_timer_bg',
'type' => 'colorpicker',
'priority' => 70,
'default' => '#fff0f5',
'rules' => Rules::is( 'exit_intent_t5_show_timer', true ),
],
[
'label' => __( 'Timer Number Color', 'notificationx' ),
'name' => 'exit_intent_t5_timer_color',
'type' => 'colorpicker',
'priority' => 80,
'default' => '#e91e63',
'rules' => Rules::is( 'exit_intent_t5_show_timer', true ),
],
],
];
// ── Theme Seven content fields ───────────────────────────────────────────
$fields['exit_intent_theme_seven_section'] = [
'label' => __( 'Exit Intent Content', 'notificationx' ),
'name' => 'exit_intent_theme_seven_section',
'type' => 'section',
'priority' => 5,
'rules' => Rules::logicalRule( [
Rules::is( 'source', $this->id ),
Rules::is( 'themes', $this->id . '_theme-seven' ),
] ),
'fields' => [
[
'label' => __( 'Left Panel Image', 'notificationx' ),
'name' => 'exit_intent_image_url',
'type' => 'media',
'priority' => 5,
'default' => [
'url' => 'https://notificationx.com/wp-content/uploads/2026/05/exit-intend-theme-two-five-seven.jpg',
],
'help' => __( 'Upload or select the image to display in the left panel.', 'notificationx' ),
],
[
'label' => __( 'Headline', 'notificationx' ),
'name' => 'exit_intent_t7_headline',
'type' => 'text',
'priority' => 10,
'default' => __( 'Home Is Where Your Story Begins', 'notificationx' ),
],
[
'label' => __( 'Discount Banner Text', 'notificationx' ),
'name' => 'exit_intent_t7_discount_text',
'type' => 'text',
'priority' => 20,
'default' => __( 'Get 15% Off Your First Order!', 'notificationx' ),
],
[
'label' => __( 'Description', 'notificationx' ),
'name' => 'exit_intent_t7_description',
'type' => 'text',
'priority' => 30,
'default' => __( 'Discover timeless pieces that turn any space into a sanctuary.', 'notificationx' ),
],
[
'label' => __( 'Email Placeholder', 'notificationx' ),
'name' => 'exit_intent_t7_email_placeholder',
'type' => 'text',
'priority' => 40,
'default' => __( 'Enter your email', 'notificationx' ),
],
[
'label' => __( 'Button Text', 'notificationx' ),
'name' => 'exit_intent_button_text',
'type' => 'text',
'priority' => 50,
'default' => __( 'SEND COUPON', 'notificationx' ),
],
],
];
// ── Theme Six content fields ─────────────────────────────────────────────
$fields['exit_intent_theme_six_section'] = [
'label' => __( 'Exit Intent Content', 'notificationx' ),
'name' => 'exit_intent_theme_six_section',
'type' => 'section',
'priority' => 5,
'rules' => Rules::logicalRule( [
Rules::is( 'source', $this->id ),
Rules::is( 'themes', $this->id . '_theme-six' ),
] ),
'fields' => [
[
'label' => __( 'Product Image', 'notificationx' ),
'name' => 'exit_intent_image_url',
'type' => 'media',
'priority' => 5,
'default' => [
'url' => 'https://notificationx.com/wp-content/uploads/2026/05/exit-intend-theme-six.png',
],
'help' => __( 'Upload or select the product image to display at the top of the popup.', 'notificationx' ),
],
[
'label' => __( 'Headline', 'notificationx' ),
'name' => 'exit_intent_t6_title',
'type' => 'text',
'priority' => 10,
'default' => __( 'Limited Edition Bass Boost Headphones', 'notificationx' ),
],
[
'label' => __( 'Button Text', 'notificationx' ),
'name' => 'exit_intent_button_text',
'type' => 'text',
'priority' => 60,
'default' => __( 'Grab Now', 'notificationx' ),
],
[
'label' => __( 'Button URL', 'notificationx' ),
'name' => 'exit_intent_button_url',
'type' => 'text',
'priority' => 61,
'default' => '',
'help' => __( 'Where the CTA button sends visitors. Leave empty to just dismiss the popup.', 'notificationx' ),
],
[
'label' => __( 'Open in New Tab', 'notificationx' ),
'name' => 'exit_intent_button_new_tab',
'type' => 'toggle',
'priority' => 62,
'default' => true,
],
],
];
// ── Theme Six Timer Settings ─────────────────────────────────────────────
$fields['exit_intent_theme_six_timer_section'] = [
'label' => __( 'Timer Settings', 'notificationx' ),
'name' => 'exit_intent_theme_six_timer_section',
'type' => 'section',
'priority' => 6,
'rules' => Rules::logicalRule( [
Rules::is( 'source', $this->id ),
Rules::is( 'themes', $this->id . '_theme-six' ),
] ),
'fields' => [
[
'label' => __( 'Show Countdown Timer', 'notificationx' ),
'name' => 'exit_intent_t6_show_timer',
'type' => 'toggle',
'priority' => 5,
'default' => true,
],
[
'label' => __( 'Countdown Label', 'notificationx' ),
'name' => 'exit_intent_t6_countdown_label',
'type' => 'text',
'priority' => 10,
'default' => __( 'Offer Ends In', 'notificationx' ),
'rules' => Rules::is( 'exit_intent_t6_show_timer', true ),
],
[
'label' => __( 'Sale End Date & Time', 'notificationx' ),
'name' => 'exit_intent_countdown_end',
'type' => 'date',
'priority' => 20,
'default' => '',
'help' => __( 'Pick the date and time when the sale ends. Leave empty to display static demo numbers.', 'notificationx' ),
'rules' => Rules::is( 'exit_intent_t6_show_timer', true ),
],
[
'label' => __( 'Days Label', 'notificationx' ),
'name' => 'exit_intent_t6_days_label',
'type' => 'text',
'priority' => 30,
'default' => __( 'DAYS', 'notificationx' ),
'rules' => Rules::is( 'exit_intent_t6_show_timer', true ),
],
[
'label' => __( 'Hours Label', 'notificationx' ),
'name' => 'exit_intent_t6_hours_label',
'type' => 'text',
'priority' => 40,
'default' => __( 'HOURS', 'notificationx' ),
'rules' => Rules::is( 'exit_intent_t6_show_timer', true ),
],
[
'label' => __( 'Minutes Label', 'notificationx' ),
'name' => 'exit_intent_t6_minutes_label',
'type' => 'text',
'priority' => 50,
'default' => __( 'MIN', 'notificationx' ),
'rules' => Rules::is( 'exit_intent_t6_show_timer', true ),
],
[
'label' => __( 'Seconds Label', 'notificationx' ),
'name' => 'exit_intent_t6_seconds_label',
'type' => 'text',
'priority' => 60,
'default' => __( 'SEC', 'notificationx' ),
'rules' => Rules::is( 'exit_intent_t6_show_timer', true ),
],
],
];
// ── Theme One content fields ─────────────────────────────────────────────
$fields['exit_intent_content_section'] = [
'label' => __( 'Exit Intent Content', 'notificationx' ),
'name' => 'exit_intent_content_section',
'type' => 'section',
'priority' => 5,
'rules' => Rules::logicalRule( [
Rules::is( 'source', $this->id ),
Rules::is( 'themes', $this->id . '_theme-two', true ),
Rules::is( 'themes', $this->id . '_theme-three', true ),
Rules::is( 'themes', $this->id . '_theme-four', true ),
Rules::is( 'themes', $this->id . '_theme-five', true ),
Rules::is( 'themes', $this->id . '_theme-six', true ),
Rules::is( 'themes', $this->id . '_theme-seven', true ),
] ),
'fields' => [
// ── Main copy ────────────────────────────────────────────
[
'label' => __( 'Title', 'notificationx' ),
'name' => 'exit_intent_title',
'type' => 'text',
'priority' => 10,
'default' => __( 'Wait! Before You Go...', 'notificationx' ),
],
[
'label' => __( 'Subtitle', 'notificationx' ),
'name' => 'exit_intent_subtitle',
'type' => 'text',
'priority' => 20,
'default' => __( "We'd love to understand what's holding you back", 'notificationx' ),
],
// ── Form fields ──────────────────────────────────────────
[
'label' => __( 'Show Name Field', 'notificationx' ),
'name' => 'exit_intent_show_name',
'type' => 'toggle',
'default' => true,
'priority' => 70,
'is_pro' => true,
],
[
'label' => __( 'Name Placeholder', 'notificationx' ),
'name' => 'exit_intent_name_label',
'type' => 'text',
'default' => __( 'Name *', 'notificationx' ),
'priority' => 75,
'is_pro' => true,
'rules' => Rules::is( 'exit_intent_show_name', true ),
],
[
'label' => __( 'Show Email Field', 'notificationx' ),
'name' => 'exit_intent_show_email',
'type' => 'toggle',
'default' => true,
'priority' => 80,
'is_pro' => true,
],
[
'label' => __( 'Email Placeholder', 'notificationx' ),
'name' => 'exit_intent_email_label',
'type' => 'text',
'default' => __( 'Enter Your Email *', 'notificationx' ),
'priority' => 85,
'is_pro' => true,
'rules' => Rules::is( 'exit_intent_show_email', true ),
],
[
'label' => __( 'Show Message Field', 'notificationx' ),
'name' => 'exit_intent_show_message',
'type' => 'toggle',
'default' => true,
'priority' => 87,
],
[
'label' => __( 'Message Placeholder', 'notificationx' ),
'name' => 'exit_intent_message_placeholder',
'type' => 'text',
'default' => __( 'Your message...', 'notificationx' ),
'priority' => 88,
'rules' => Rules::is( 'exit_intent_show_message', true ),
],
// ── Button ───────────────────────────────────────────────
[
'label' => __( 'Button Text', 'notificationx' ),
'name' => 'exit_intent_button_text',
'type' => 'text',
'default' => __( 'SUBMIT', 'notificationx' ),
'priority' => 90,
],
],
];
return $fields;
}
public function design_fields( $fields ) {
// Hide the inner sub-sections of the global advance_design_section for this source,
// but keep advance_design_section itself visible so its `advance_edit` toggle renders.
foreach ( [ 'design', 'typography', 'image-appearance', 'link_button_design' ] as $key ) {
if ( isset( $fields['advance_design_section']['fields'][ $key ] ) ) {
$fields['advance_design_section']['fields'][ $key ] = Rules::is(
'source', $this->id, true, $fields['advance_design_section']['fields'][ $key ]
);
}
}
// Inline every theme's design fields directly into advance_design_section so they appear
// flat under the existing "Advanced Design" heading — no per-theme sub-headers.
// Priorities are auto-assigned starting at 20 so all theme controls sort BEFORE the
// global Custom CSS section (priority 150).
$design = &$fields['advance_design_section']['fields'];
$priority = 20;
$merge = function( $theme_slug, $list ) use ( &$design, &$priority ) {
$rule = $this->theme_design_rules( $theme_slug );
foreach ( $list as $field ) {
if ( ! empty( $field['rules'] ) ) {
$field['rules'] = Rules::logicalRule( [ $rule, $field['rules'] ] );
} else {
$field['rules'] = $rule;
}
if ( ! isset( $field['priority'] ) ) {
$field['priority'] = $priority;
}
$priority++;
$design[ $field['name'] ] = $field;
}
};
$merge( 'theme-one', $this->theme_one_design_fields() );
$merge( 'theme-two', $this->theme_two_design_fields() );
$merge( 'theme-three', $this->theme_three_design_fields() );
$merge( 'theme-four', $this->theme_four_design_fields() );
$merge( 'theme-five', $this->theme_five_design_fields() );
$merge( 'theme-six', $this->theme_six_design_fields() );
$merge( 'theme-seven', $this->theme_seven_design_fields() );
return $fields;
}
/** Build a rule scoped to source + advance_edit + a specific theme. */
private function theme_design_rules( $theme_slug ) {
return Rules::logicalRule( [
Rules::is( 'source', $this->id ),
Rules::is( 'advance_edit', true ),
Rules::is( 'themes', $this->id . '_' . $theme_slug ),
] );
}
private function font_weight_options() {
return GlobalFields::get_instance()->normalize_fields( [
'400' => __( 'Normal (400)', 'notificationx' ),
'500' => __( 'Medium (500)', 'notificationx' ),
'600' => __( 'Semi Bold (600)', 'notificationx' ),
'700' => __( 'Bold (700)', 'notificationx' ),
'800' => __( 'Extra Bold (800)', 'notificationx' ),
] );
}
/** ───────────────────────── Theme One — Feedback Form ───────────────────────── */
private function theme_one_design_fields() {
return [
// Container
[ 'label' => __( 'Popup Max Width', 'notificationx' ), 'name' => 'exit_intent_max_width', 'type' => 'number', 'default' => 540, 'description' => 'px' ],
[ 'label' => __( 'Border Radius', 'notificationx' ), 'name' => 'exit_intent_border_radius', 'type' => 'number', 'default' => 12, 'description' => 'px' ],
[ 'label' => __( 'Background Color', 'notificationx' ), 'name' => 'exit_intent_bg_color', 'type' => 'colorpicker', 'default' => '#EDE7FF' ],
[ 'label' => __( 'Overlay Background Color', 'notificationx' ),'name' => 'exit_intent_overlay_color', 'type' => 'colorpicker', 'default' => 'rgba(0,0,0,0.5)',
'help' => __( 'Color of the backdrop behind the popup.', 'notificationx' ) ],
[ 'label' => __( 'Show Background Pattern', 'notificationx' ), 'name' => 'exit_intent_show_pattern', 'type' => 'toggle', 'default' => true ],
[ 'label' => __( 'Pattern Color', 'notificationx' ), 'name' => 'exit_intent_pattern_color', 'type' => 'colorpicker', 'default' => '#D4C3FF',
'rules' => Rules::is( 'exit_intent_show_pattern', true ) ],
// Title
[ 'label' => __( 'Title Color', 'notificationx' ), 'name' => 'exit_intent_title_color', 'type' => 'colorpicker', 'default' => '#1a1a2e' ],
[ 'label' => __( 'Title Font Size', 'notificationx' ), 'name' => 'exit_intent_title_font_size', 'type' => 'number', 'default' => 26, 'description' => 'px' ],
[ 'label' => __( 'Title Font Weight', 'notificationx' ), 'name' => 'exit_intent_title_font_weight', 'type' => 'select', 'default' => '700',
'options' => $this->font_weight_options() ],
// Subtitle
[ 'label' => __( 'Subtitle Color', 'notificationx' ), 'name' => 'exit_intent_subtitle_color', 'type' => 'colorpicker', 'default' => '#4a4a6a' ],
[ 'label' => __( 'Subtitle Font Size', 'notificationx' ), 'name' => 'exit_intent_subtitle_font_size', 'type' => 'number', 'default' => 14, 'description' => 'px' ],
// Inputs
[ 'label' => __( 'Input Background Color', 'notificationx' ), 'name' => 'exit_intent_input_bg', 'type' => 'colorpicker', 'default' => '#ffffff' ],
[ 'label' => __( 'Input Border Color', 'notificationx' ), 'name' => 'exit_intent_input_border_color', 'type' => 'colorpicker', 'default' => '#dddddd' ],
[ 'label' => __( 'Input Border Radius', 'notificationx' ), 'name' => 'exit_intent_input_border_radius', 'type' => 'number', 'default' => 6, 'description' => 'px' ],
[ 'label' => __( 'Input Text Color', 'notificationx' ), 'name' => 'exit_intent_input_text_color', 'type' => 'colorpicker', 'default' => '#333333' ],
// Button
[ 'label' => __( 'Button Background Color', 'notificationx' ), 'name' => 'exit_intent_btn_bg', 'type' => 'colorpicker', 'default' => '#6B21A8' ],
[ 'label' => __( 'Button Text Color', 'notificationx' ), 'name' => 'exit_intent_btn_color', 'type' => 'colorpicker', 'default' => '#ffffff' ],
[ 'label' => __( 'Button Border Radius', 'notificationx' ), 'name' => 'exit_intent_btn_border_radius', 'type' => 'number', 'default' => 6, 'description' => 'px' ],
[ 'label' => __( 'Button Font Size', 'notificationx' ), 'name' => 'exit_intent_btn_font_size', 'type' => 'number', 'default' => 14, 'description' => 'px' ],
[ 'label' => __( 'Button Font Weight', 'notificationx' ), 'name' => 'exit_intent_btn_font_weight', 'type' => 'select', 'default' => '700',
'options' => $this->font_weight_options() ],
// Close button
[ 'label' => __( 'Close Button Color', 'notificationx' ), 'name' => 'exit_intent_close_color', 'type' => 'colorpicker', 'default' => '#666666' ],
[ 'label' => __( 'Close Button Size', 'notificationx' ), 'name' => 'exit_intent_close_size', 'type' => 'number', 'default' => 20, 'description' => 'px' ],
];
}
/** ───────────────────────── Theme Two — Flash Sale w/ Countdown ───────────────────────── */
private function theme_two_design_fields() {
return [
// Container / overlay / close
[ 'label' => __( 'Popup Max Width', 'notificationx' ), 'name' => 'exit_intent_t2_max_width', 'type' => 'number', 'default' => 760, 'description' => 'px' ],
[ 'label' => __( 'Border Radius', 'notificationx' ), 'name' => 'exit_intent_t2_border_radius', 'type' => 'number', 'default' => 12, 'description' => 'px' ],
[ 'label' => __( 'Left Panel Background', 'notificationx' ), 'name' => 'exit_intent_t2_bg_color', 'type' => 'colorpicker', 'default' => '#ffffff' ],
[ 'label' => __( 'Overlay Background Color', 'notificationx' ), 'name' => 'exit_intent_overlay_color', 'type' => 'colorpicker', 'default' => 'rgba(0,0,0,0.5)' ],
[ 'label' => __( 'Close Button Color', 'notificationx' ), 'name' => 'exit_intent_close_color', 'type' => 'colorpicker', 'default' => '#666666' ],
[ 'label' => __( 'Close Button Size', 'notificationx' ), 'name' => 'exit_intent_close_size', 'type' => 'number', 'default' => 20, 'description' => 'px' ],
// Sale badge
[ 'label' => __( 'Badge Background', 'notificationx' ), 'name' => 'exit_intent_t2_badge_bg', 'type' => 'colorpicker', 'default' => '#ffe4ec' ],
[ 'label' => __( 'Badge Text Color', 'notificationx' ),'name' => 'exit_intent_t2_badge_color', 'type' => 'colorpicker', 'default' => '#e91e63' ],
[ 'label' => __( 'Badge Font Size', 'notificationx' ), 'name' => 'exit_intent_t2_badge_font_size', 'type' => 'number', 'default' => 12, 'description' => 'px' ],
// Headline
[ 'label' => __( 'Headline Color', 'notificationx' ), 'name' => 'exit_intent_t2_headline_color', 'type' => 'colorpicker', 'default' => '#1a1a2e' ],
[ 'label' => __( 'Headline Font Size', 'notificationx' ), 'name' => 'exit_intent_t2_headline_font_size', 'type' => 'number', 'default' => 56, 'description' => 'px' ],
[ 'label' => __( 'Headline Font Weight', 'notificationx' ), 'name' => 'exit_intent_t2_headline_font_weight', 'type' => 'select', 'default' => '800',
'options' => $this->font_weight_options() ],
// Description
[ 'label' => __( 'Description Color', 'notificationx' ), 'name' => 'exit_intent_t2_desc_color', 'type' => 'colorpicker', 'default' => '#4a4a6a' ],
[ 'label' => __( 'Description Font Size', 'notificationx' ), 'name' => 'exit_intent_t2_desc_font_size', 'type' => 'number', 'default' => 14, 'description' => 'px' ],
// CTA button
[ 'label' => __( 'Button Background', 'notificationx' ), 'name' => 'exit_intent_t2_btn_bg', 'type' => 'colorpicker', 'default' => '#e91e63' ],
[ 'label' => __( 'Button Text Color', 'notificationx' ), 'name' => 'exit_intent_t2_btn_color', 'type' => 'colorpicker', 'default' => '#ffffff' ],
[ 'label' => __( 'Button Border Radius', 'notificationx' ), 'name' => 'exit_intent_t2_btn_border_radius', 'type' => 'number', 'default' => 6, 'description' => 'px' ],
[ 'label' => __( 'Button Font Size', 'notificationx' ), 'name' => 'exit_intent_t2_btn_font_size', 'type' => 'number', 'default' => 14, 'description' => 'px' ],
[ 'label' => __( 'Button Font Weight', 'notificationx' ), 'name' => 'exit_intent_t2_btn_font_weight', 'type' => 'select', 'default' => '700',
'options' => $this->font_weight_options() ],
// Dismiss link
[ 'label' => __( 'Dismiss Text Color', 'notificationx' ), 'name' => 'exit_intent_t2_dismiss_color', 'type' => 'colorpicker', 'default' => '#9a9aa8' ],
[ 'label' => __( 'Dismiss Font Size', 'notificationx' ), 'name' => 'exit_intent_t2_dismiss_font_size', 'type' => 'number', 'default' => 12, 'description' => 'px' ],
];
}
/** ───────────────────────── Theme Three — Coupon Offer ───────────────────────── */
private function theme_three_design_fields() {
return [
// Container / overlay / close
[ 'label' => __( 'Popup Max Width', 'notificationx' ), 'name' => 'exit_intent_t3_max_width', 'type' => 'number', 'default' => 460, 'description' => 'px' ],
[ 'label' => __( 'Border Radius', 'notificationx' ), 'name' => 'exit_intent_t3_border_radius', 'type' => 'number', 'default' => 16, 'description' => 'px' ],
[ 'label' => __( 'Background Color', 'notificationx' ), 'name' => 'exit_intent_t3_bg_color', 'type' => 'colorpicker', 'default' => '#ffffff' ],
[ 'label' => __( 'Overlay Background Color', 'notificationx' ), 'name' => 'exit_intent_overlay_color', 'type' => 'colorpicker', 'default' => 'rgba(0,0,0,0.5)' ],
[ 'label' => __( 'Close Button Color', 'notificationx' ), 'name' => 'exit_intent_close_color', 'type' => 'colorpicker', 'default' => '#666666' ],
[ 'label' => __( 'Close Button Size', 'notificationx' ), 'name' => 'exit_intent_close_size', 'type' => 'number', 'default' => 20, 'description' => 'px' ],
// Title
[ 'label' => __( 'Title Color', 'notificationx' ), 'name' => 'exit_intent_t3_title_color', 'type' => 'colorpicker', 'default' => '#1a1a2e' ],
[ 'label' => __( 'Title Font Size', 'notificationx' ), 'name' => 'exit_intent_t3_title_font_size', 'type' => 'number', 'default' => 26, 'description' => 'px' ],
[ 'label' => __( 'Title Font Weight', 'notificationx' ), 'name' => 'exit_intent_t3_title_font_weight', 'type' => 'select', 'default' => '700',
'options' => $this->font_weight_options() ],
// Subtitle
[ 'label' => __( 'Subtitle Color', 'notificationx' ), 'name' => 'exit_intent_t3_subtitle_color', 'type' => 'colorpicker', 'default' => '#4a4a6a' ],
[ 'label' => __( 'Subtitle Font Size', 'notificationx' ), 'name' => 'exit_intent_t3_subtitle_font_size', 'type' => 'number', 'default' => 14, 'description' => 'px' ],
// Offer line
[ 'label' => __( 'Offer Color', 'notificationx' ), 'name' => 'exit_intent_t3_offer_color', 'type' => 'colorpicker', 'default' => '#e91e63' ],
[ 'label' => __( 'Offer Font Size', 'notificationx' ), 'name' => 'exit_intent_t3_offer_font_size', 'type' => 'number', 'default' => 18, 'description' => 'px' ],
[ 'label' => __( 'Offer Font Weight', 'notificationx' ), 'name' => 'exit_intent_t3_offer_font_weight', 'type' => 'select', 'default' => '700',
'options' => $this->font_weight_options() ],
// Coupon block
[ 'label' => __( 'Coupon Block Background', 'notificationx' ), 'name' => 'exit_intent_t3_coupon_bg', 'type' => 'colorpicker', 'default' => '#fff7fb' ],
[ 'label' => __( 'Coupon Text Color', 'notificationx' ), 'name' => 'exit_intent_t3_coupon_color', 'type' => 'colorpicker', 'default' => '#1a1a2e' ],
[ 'label' => __( 'Coupon Font Size', 'notificationx' ), 'name' => 'exit_intent_t3_coupon_font_size', 'type' => 'number', 'default' => 14, 'description' => 'px' ],
[ 'label' => __( 'Coupon Block Border Radius', 'notificationx' ), 'name' => 'exit_intent_t3_coupon_border_radius', 'type' => 'number', 'default' => 8, 'description' => 'px' ],
// CTA button
[ 'label' => __( 'Button Background', 'notificationx' ), 'name' => 'exit_intent_t3_btn_bg', 'type' => 'colorpicker', 'default' => '#e91e63' ],
[ 'label' => __( 'Button Text Color', 'notificationx' ), 'name' => 'exit_intent_t3_btn_color', 'type' => 'colorpicker', 'default' => '#ffffff' ],
[ 'label' => __( 'Button Border Radius', 'notificationx' ), 'name' => 'exit_intent_t3_btn_border_radius', 'type' => 'number', 'default' => 6, 'description' => 'px' ],
[ 'label' => __( 'Button Font Size', 'notificationx' ), 'name' => 'exit_intent_t3_btn_font_size', 'type' => 'number', 'default' => 14, 'description' => 'px' ],
[ 'label' => __( 'Button Font Weight', 'notificationx' ), 'name' => 'exit_intent_t3_btn_font_weight', 'type' => 'select', 'default' => '700',
'options' => $this->font_weight_options() ],
// Dismiss link
[ 'label' => __( 'Dismiss Text Color', 'notificationx' ), 'name' => 'exit_intent_t3_dismiss_color', 'type' => 'colorpicker', 'default' => '#9a9aa8' ],
[ 'label' => __( 'Dismiss Font Size', 'notificationx' ), 'name' => 'exit_intent_t3_dismiss_font_size', 'type' => 'number', 'default' => 12, 'description' => 'px' ],
];
}
/** ───────────────────────── Theme Four — Video Popup ───────────────────────── */
private function theme_four_design_fields() {
return [
// Container / overlay / close
[ 'label' => __( 'Popup Max Width', 'notificationx' ), 'name' => 'exit_intent_t4_max_width', 'type' => 'number', 'default' => 520, 'description' => 'px' ],
[ 'label' => __( 'Border Radius', 'notificationx' ), 'name' => 'exit_intent_t4_border_radius', 'type' => 'number', 'default' => 16, 'description' => 'px' ],
[ 'label' => __( 'Background Color', 'notificationx' ), 'name' => 'exit_intent_t4_bg_color', 'type' => 'colorpicker', 'default' => '#f4ecff' ],
[ 'label' => __( 'Overlay Background Color', 'notificationx' ), 'name' => 'exit_intent_overlay_color', 'type' => 'colorpicker', 'default' => 'rgba(0,0,0,0.5)' ],
[ 'label' => __( 'Close Button Color', 'notificationx' ), 'name' => 'exit_intent_close_color', 'type' => 'colorpicker', 'default' => '#666666' ],
[ 'label' => __( 'Close Button Size', 'notificationx' ), 'name' => 'exit_intent_close_size', 'type' => 'number', 'default' => 20, 'description' => 'px' ],
// Badge
[ 'label' => __( 'Badge Background', 'notificationx' ), 'name' => 'exit_intent_t4_badge_bg', 'type' => 'colorpicker', 'default' => '#ffffff' ],
[ 'label' => __( 'Badge Text Color', 'notificationx' ),'name' => 'exit_intent_t4_badge_color', 'type' => 'colorpicker', 'default' => '#6B21A8' ],
[ 'label' => __( 'Badge Font Size', 'notificationx' ), 'name' => 'exit_intent_t4_badge_font_size', 'type' => 'number', 'default' => 12, 'description' => 'px' ],
// Title
[ 'label' => __( 'Title Color', 'notificationx' ), 'name' => 'exit_intent_t4_title_color', 'type' => 'colorpicker', 'default' => '#1a1a2e' ],
[ 'label' => __( 'Title Font Size', 'notificationx' ), 'name' => 'exit_intent_t4_title_font_size', 'type' => 'number', 'default' => 24, 'description' => 'px' ],
[ 'label' => __( 'Title Font Weight', 'notificationx' ), 'name' => 'exit_intent_t4_title_font_weight', 'type' => 'select', 'default' => '700',
'options' => $this->font_weight_options() ],
// Subtitle
[ 'label' => __( 'Subtitle Color', 'notificationx' ), 'name' => 'exit_intent_t4_subtitle_color', 'type' => 'colorpicker', 'default' => '#4a4a6a' ],
[ 'label' => __( 'Subtitle Font Size', 'notificationx' ), 'name' => 'exit_intent_t4_subtitle_font_size', 'type' => 'number', 'default' => 14, 'description' => 'px' ],
// Video wrap + play icon
[ 'label' => __( 'Video Wrapper Background', 'notificationx' ), 'name' => 'exit_intent_t4_video_bg', 'type' => 'colorpicker', 'default' => '#000000' ],
[ 'label' => __( 'Video Wrapper Border Radius', 'notificationx' ), 'name' => 'exit_intent_t4_video_radius', 'type' => 'number', 'default' => 12, 'description' => 'px' ],
[ 'label' => __( 'Play Icon Background', 'notificationx' ), 'name' => 'exit_intent_t4_play_bg', 'type' => 'colorpicker', 'default' => '#ffffff' ],
[ 'label' => __( 'Play Icon Color', 'notificationx' ), 'name' => 'exit_intent_t4_play_color', 'type' => 'colorpicker', 'default' => '#1a1a2e' ],
];
}
/** ───────────────────────── Theme Five — Live Flash Sale ───────────────────────── */
private function theme_five_design_fields() {
return [
// Container / overlay / close
[ 'label' => __( 'Popup Max Width', 'notificationx' ), 'name' => 'exit_intent_t5_max_width', 'type' => 'number', 'default' => 900, 'description' => 'px' ],
[ 'label' => __( 'Border Radius', 'notificationx' ), 'name' => 'exit_intent_t5_border_radius', 'type' => 'number', 'default' => 12, 'description' => 'px' ],
[ 'label' => __( 'Left Panel Background', 'notificationx' ), 'name' => 'exit_intent_t5_bg_color', 'type' => 'colorpicker', 'default' => '#ffffff' ],
[ 'label' => __( 'Overlay Background Color', 'notificationx' ), 'name' => 'exit_intent_overlay_color', 'type' => 'colorpicker', 'default' => 'rgba(0,0,0,0.6)' ],
[ 'label' => __( 'Close Button Color', 'notificationx' ), 'name' => 'exit_intent_close_color', 'type' => 'colorpicker', 'default' => '#666666' ],
[ 'label' => __( 'Close Button Size', 'notificationx' ), 'name' => 'exit_intent_close_size', 'type' => 'number', 'default' => 20, 'description' => 'px' ],
// Title
[ 'label' => __( 'Title Color', 'notificationx' ), 'name' => 'exit_intent_t5_title_color', 'type' => 'colorpicker', 'default' => '#1a1a2e' ],
[ 'label' => __( 'Title Font Size', 'notificationx' ), 'name' => 'exit_intent_t5_title_font_size', 'type' => 'number', 'default' => 18, 'description' => 'px' ],
[ 'label' => __( 'Title Font Weight', 'notificationx' ), 'name' => 'exit_intent_t5_title_font_weight', 'type' => 'select', 'default' => '700',
'options' => $this->font_weight_options() ],
// Headline
[ 'label' => __( 'Headline Color', 'notificationx' ), 'name' => 'exit_intent_t5_headline_color', 'type' => 'colorpicker', 'default' => '#1a1a2e' ],
[ 'label' => __( 'Headline Font Size', 'notificationx' ), 'name' => 'exit_intent_t5_headline_font_size', 'type' => 'number', 'default' => 56, 'description' => 'px' ],
[ 'label' => __( 'Headline Font Weight', 'notificationx' ), 'name' => 'exit_intent_t5_headline_font_weight', 'type' => 'select', 'default' => '800',
'options' => $this->font_weight_options() ],
// Description
[ 'label' => __( 'Description Color', 'notificationx' ), 'name' => 'exit_intent_t5_desc_color', 'type' => 'colorpicker', 'default' => '#4a4a6a' ],
[ 'label' => __( 'Description Font Size', 'notificationx' ), 'name' => 'exit_intent_t5_desc_font_size', 'type' => 'number', 'default' => 14, 'description' => 'px' ],
// Countdown label + numbers + unit labels
[ 'label' => __( 'Countdown Label Color', 'notificationx' ), 'name' => 'exit_intent_t5_cd_label_color', 'type' => 'colorpicker', 'default' => '#1a1a2e',
'rules' => Rules::is( 'exit_intent_t5_show_timer', true ) ],
[ 'label' => __( 'Countdown Label Font Size', 'notificationx' ), 'name' => 'exit_intent_t5_cd_label_font_size', 'type' => 'number', 'default' => 12, 'description' => 'px',
'rules' => Rules::is( 'exit_intent_t5_show_timer', true ) ],
[ 'label' => __( 'Countdown Number Background', 'notificationx' ), 'name' => 'exit_intent_t5_cd_num_bg', 'type' => 'colorpicker', 'default' => '#fff0f5',
'rules' => Rules::is( 'exit_intent_t5_show_timer', true ) ],
[ 'label' => __( 'Countdown Number Color', 'notificationx' ), 'name' => 'exit_intent_t5_cd_num_color', 'type' => 'colorpicker', 'default' => '#e91e63',
'rules' => Rules::is( 'exit_intent_t5_show_timer', true ) ],
[ 'label' => __( 'Countdown Number Font Size', 'notificationx' ), 'name' => 'exit_intent_t5_cd_num_font_size', 'type' => 'number', 'default' => 22, 'description' => 'px',
'rules' => Rules::is( 'exit_intent_t5_show_timer', true ) ],
[ 'label' => __( 'Countdown Number Border Radius', 'notificationx' ),'name' => 'exit_intent_t5_cd_num_radius', 'type' => 'number', 'default' => 6, 'description' => 'px',
'rules' => Rules::is( 'exit_intent_t5_show_timer', true ) ],
[ 'label' => __( 'Countdown Unit Label Color', 'notificationx' ), 'name' => 'exit_intent_t5_cd_unit_color', 'type' => 'colorpicker', 'default' => '#4a4a6a',
'rules' => Rules::is( 'exit_intent_t5_show_timer', true ) ],
[ 'label' => __( 'Countdown Unit Label Font Size', 'notificationx' ),'name' => 'exit_intent_t5_cd_unit_font_size', 'type' => 'number', 'default' => 11, 'description' => 'px',
'rules' => Rules::is( 'exit_intent_t5_show_timer', true ) ],
// CTA button
[ 'label' => __( 'Button Background', 'notificationx' ), 'name' => 'exit_intent_t5_btn_bg', 'type' => 'colorpicker', 'default' => '#e91e63' ],
[ 'label' => __( 'Button Text Color', 'notificationx' ), 'name' => 'exit_intent_t5_btn_color', 'type' => 'colorpicker', 'default' => '#ffffff' ],
[ 'label' => __( 'Button Border Radius', 'notificationx' ), 'name' => 'exit_intent_t5_btn_border_radius', 'type' => 'number', 'default' => 6, 'description' => 'px' ],
[ 'label' => __( 'Button Font Size', 'notificationx' ), 'name' => 'exit_intent_t5_btn_font_size', 'type' => 'number', 'default' => 14, 'description' => 'px' ],
[ 'label' => __( 'Button Font Weight', 'notificationx' ), 'name' => 'exit_intent_t5_btn_font_weight', 'type' => 'select', 'default' => '700',
'options' => $this->font_weight_options() ],
// Dismiss link
[ 'label' => __( 'Dismiss Text Color', 'notificationx' ), 'name' => 'exit_intent_t5_dismiss_color', 'type' => 'colorpicker', 'default' => '#9a9aa8' ],
[ 'label' => __( 'Dismiss Font Size', 'notificationx' ), 'name' => 'exit_intent_t5_dismiss_font_size', 'type' => 'number', 'default' => 12, 'description' => 'px' ],
];
}
/** ───────────────────────── Theme Six — Product Countdown ───────────────────────── */
private function theme_six_design_fields() {
return [
// Container / overlay / close
[ 'label' => __( 'Popup Max Width', 'notificationx' ), 'name' => 'exit_intent_t6_max_width', 'type' => 'number', 'default' => 600, 'description' => 'px' ],
[ 'label' => __( 'Border Radius', 'notificationx' ), 'name' => 'exit_intent_t6_border_radius', 'type' => 'number', 'default' => 12, 'description' => 'px' ],
[ 'label' => __( 'Background Start Color', 'notificationx' ), 'name' => 'exit_intent_t6_bg_start', 'type' => 'colorpicker', 'default' => '#ffffff',
'help' => __( 'Center color of the radial background gradient.', 'notificationx' ) ],
[ 'label' => __( 'Background Mid Color', 'notificationx' ), 'name' => 'exit_intent_t6_bg_mid', 'type' => 'colorpicker', 'default' => '#fdf2f8' ],
[ 'label' => __( 'Background End Color', 'notificationx' ), 'name' => 'exit_intent_t6_bg_end', 'type' => 'colorpicker', 'default' => '#f5f3ff',
'help' => __( 'Outer color of the radial background gradient.', 'notificationx' ) ],
[ 'label' => __( 'Overlay Background Color', 'notificationx' ), 'name' => 'exit_intent_overlay_color', 'type' => 'colorpicker', 'default' => 'rgba(0,0,0,0.5)' ],
[ 'label' => __( 'Close Button Color', 'notificationx' ), 'name' => 'exit_intent_close_color', 'type' => 'colorpicker', 'default' => '#1f2937' ],
[ 'label' => __( 'Close Button Size', 'notificationx' ), 'name' => 'exit_intent_close_size', 'type' => 'number', 'default' => 20, 'description' => 'px' ],
// Title
[ 'label' => __( 'Title Color', 'notificationx' ), 'name' => 'exit_intent_t6_title_color', 'type' => 'colorpicker', 'default' => '#1f2937' ],
[ 'label' => __( 'Title Font Size', 'notificationx' ), 'name' => 'exit_intent_t6_title_font_size', 'type' => 'number', 'default' => 36, 'description' => 'px' ],
[ 'label' => __( 'Title Font Weight', 'notificationx' ), 'name' => 'exit_intent_t6_title_font_weight', 'type' => 'select', 'default' => '700',
'options' => $this->font_weight_options() ],
// Countdown label + numbers + unit labels
[ 'label' => __( 'Countdown Label Color', 'notificationx' ), 'name' => 'exit_intent_t6_cd_label_color', 'type' => 'colorpicker', 'default' => '#4b5563',
'rules' => Rules::is( 'exit_intent_t6_show_timer', true ) ],
[ 'label' => __( 'Countdown Label Font Size', 'notificationx' ), 'name' => 'exit_intent_t6_cd_label_font_size', 'type' => 'number', 'default' => 18, 'description' => 'px',
'rules' => Rules::is( 'exit_intent_t6_show_timer', true ) ],
[ 'label' => __( 'Countdown Number Background', 'notificationx' ), 'name' => 'exit_intent_t6_cd_num_bg', 'type' => 'colorpicker', 'default' => '#f3e8f2',
'rules' => Rules::is( 'exit_intent_t6_show_timer', true ) ],
[ 'label' => __( 'Countdown Number Color', 'notificationx' ), 'name' => 'exit_intent_t6_cd_num_color', 'type' => 'colorpicker', 'default' => '#374151',
'rules' => Rules::is( 'exit_intent_t6_show_timer', true ) ],
[ 'label' => __( 'Countdown Number Font Size', 'notificationx' ), 'name' => 'exit_intent_t6_cd_num_font_size', 'type' => 'number', 'default' => 24, 'description' => 'px',
'rules' => Rules::is( 'exit_intent_t6_show_timer', true ) ],
[ 'label' => __( 'Countdown Number Border Radius', 'notificationx' ),'name' => 'exit_intent_t6_cd_num_radius', 'type' => 'number', 'default' => 2, 'description' => 'px',
'rules' => Rules::is( 'exit_intent_t6_show_timer', true ) ],
[ 'label' => __( 'Countdown Unit Label Color', 'notificationx' ), 'name' => 'exit_intent_t6_cd_unit_color', 'type' => 'colorpicker', 'default' => '#9f1239',
'rules' => Rules::is( 'exit_intent_t6_show_timer', true ) ],
[ 'label' => __( 'Countdown Unit Label Font Size', 'notificationx' ),'name' => 'exit_intent_t6_cd_unit_font_size', 'type' => 'number', 'default' => 12, 'description' => 'px',
'rules' => Rules::is( 'exit_intent_t6_show_timer', true ) ],
// CTA button
[ 'label' => __( 'Button Background', 'notificationx' ), 'name' => 'exit_intent_t6_btn_bg', 'type' => 'colorpicker', 'default' => '#845e7c' ],
[ 'label' => __( 'Button Text Color', 'notificationx' ), 'name' => 'exit_intent_t6_btn_color', 'type' => 'colorpicker', 'default' => '#ffffff' ],
[ 'label' => __( 'Button Border Radius', 'notificationx' ), 'name' => 'exit_intent_t6_btn_border_radius', 'type' => 'number', 'default' => 4, 'description' => 'px' ],
[ 'label' => __( 'Button Font Size', 'notificationx' ), 'name' => 'exit_intent_t6_btn_font_size', 'type' => 'number', 'default' => 24, 'description' => 'px' ],
[ 'label' => __( 'Button Font Weight', 'notificationx' ), 'name' => 'exit_intent_t6_btn_font_weight', 'type' => 'select', 'default' => '700',
'options' => $this->font_weight_options() ],
];
}
/** ───────────────────────── Theme Seven — Lead Capture w/ Image ───────────────────────── */
private function theme_seven_design_fields() {
$font_family_options = GlobalFields::get_instance()->normalize_fields( [
'inherit' => __( 'Default (inherit)', 'notificationx' ),
"'Playfair Display', Georgia, serif" => __( 'Playfair Display (serif)', 'notificationx' ),
"Georgia, 'Times New Roman', serif" => __( 'Georgia (serif)', 'notificationx' ),
"'Times New Roman', Times, serif" => __( 'Times New Roman (serif)', 'notificationx' ),
"Inter, 'Helvetica Neue', Arial, sans-serif" => __( 'Inter (sans-serif)', 'notificationx' ),
"'Helvetica Neue', Helvetica, Arial, sans-serif" => __( 'Helvetica (sans-serif)', 'notificationx' ),
] );
return [
// Container / overlay / close
[ 'label' => __( 'Popup Max Width', 'notificationx' ), 'name' => 'exit_intent_t7_max_width', 'type' => 'number', 'default' => 750, 'description' => 'px' ],
[ 'label' => __( 'Border Radius', 'notificationx' ), 'name' => 'exit_intent_t7_border_radius', 'type' => 'number', 'default' => 12, 'description' => 'px' ],
[ 'label' => __( 'Background Color', 'notificationx' ), 'name' => 'exit_intent_t7_bg_color', 'type' => 'colorpicker', 'default' => '#413532',
'help' => __( 'Right (content) panel background.', 'notificationx' ) ],
[ 'label' => __( 'Image Panel Background', 'notificationx' ), 'name' => 'exit_intent_t7_image_bg', 'type' => 'colorpicker', 'default' => '#534542',
'help' => __( 'Shown behind the image (visible only if the image leaves transparent areas or fails to load).', 'notificationx' ) ],
[ 'label' => __( 'Overlay Background Color', 'notificationx' ), 'name' => 'exit_intent_overlay_color', 'type' => 'colorpicker', 'default' => 'rgba(0,0,0,0.5)' ],
[ 'label' => __( 'Close Button Color', 'notificationx' ), 'name' => 'exit_intent_close_color', 'type' => 'colorpicker', 'default' => '#f3d5a2' ],
[ 'label' => __( 'Close Button Size', 'notificationx' ), 'name' => 'exit_intent_close_size', 'type' => 'number', 'default' => 22, 'description' => 'px' ],
// Headline
[ 'label' => __( 'Headline Color', 'notificationx' ), 'name' => 'exit_intent_t7_headline_color', 'type' => 'colorpicker', 'default' => '#f3d5a2' ],
[ 'label' => __( 'Headline Font Size', 'notificationx' ), 'name' => 'exit_intent_t7_headline_font_size', 'type' => 'number', 'default' => 30, 'description' => 'px' ],
[ 'label' => __( 'Headline Font Weight', 'notificationx' ), 'name' => 'exit_intent_t7_headline_font_weight', 'type' => 'select', 'default' => '700',
'options' => $this->font_weight_options() ],
[ 'label' => __( 'Headline Font Family', 'notificationx' ), 'name' => 'exit_intent_t7_headline_font_family', 'type' => 'select', 'default' => "'Playfair Display', Georgia, serif",
'options' => $font_family_options ],
// Discount banner
[ 'label' => __( 'Discount Banner Background', 'notificationx' ), 'name' => 'exit_intent_t7_discount_bg', 'type' => 'colorpicker', 'default' => 'rgba(255,255,255,0.1)' ],
[ 'label' => __( 'Discount Banner Border Color', 'notificationx' ), 'name' => 'exit_intent_t7_discount_border', 'type' => 'colorpicker', 'default' => 'rgba(255,255,255,0.05)' ],
[ 'label' => __( 'Discount Banner Text Color', 'notificationx' ), 'name' => 'exit_intent_t7_discount_color', 'type' => 'colorpicker', 'default' => '#f3d5a2' ],
[ 'label' => __( 'Discount Banner Font Size', 'notificationx' ), 'name' => 'exit_intent_t7_discount_font_size', 'type' => 'number', 'default' => 16, 'description' => 'px' ],
[ 'label' => __( 'Discount Banner Border Radius', 'notificationx' ), 'name' => 'exit_intent_t7_discount_radius', 'type' => 'number', 'default' => 2, 'description' => 'px' ],
// Description
[ 'label' => __( 'Description Color', 'notificationx' ), 'name' => 'exit_intent_t7_desc_color', 'type' => 'colorpicker', 'default' => 'rgba(243,213,162,0.9)' ],
[ 'label' => __( 'Description Font Size', 'notificationx' ), 'name' => 'exit_intent_t7_desc_font_size', 'type' => 'number', 'default' => 16, 'description' => 'px' ],
// Email input
[ 'label' => __( 'Input Background Color', 'notificationx' ), 'name' => 'exit_intent_t7_input_bg', 'type' => 'colorpicker', 'default' => '#ffffff' ],
[ 'label' => __( 'Input Border Color', 'notificationx' ), 'name' => 'exit_intent_t7_input_border_color', 'type' => 'colorpicker', 'default' => '#6b7280' ],
[ 'label' => __( 'Input Border Radius', 'notificationx' ), 'name' => 'exit_intent_t7_input_border_radius','type' => 'number', 'default' => 0, 'description' => 'px' ],
[ 'label' => __( 'Input Text Color', 'notificationx' ), 'name' => 'exit_intent_t7_input_text_color', 'type' => 'colorpicker', 'default' => '#1f2937' ],
// CTA button
[ 'label' => __( 'Button Background', 'notificationx' ), 'name' => 'exit_intent_t7_btn_bg', 'type' => 'colorpicker', 'default' => '#f3d5a2' ],
[ 'label' => __( 'Button Text Color', 'notificationx' ), 'name' => 'exit_intent_t7_btn_color', 'type' => 'colorpicker', 'default' => '#4d3e3e' ],
[ 'label' => __( 'Button Border Radius', 'notificationx' ), 'name' => 'exit_intent_t7_btn_border_radius', 'type' => 'number', 'default' => 0, 'description' => 'px' ],
[ 'label' => __( 'Button Font Size', 'notificationx' ), 'name' => 'exit_intent_t7_btn_font_size', 'type' => 'number', 'default' => 14, 'description' => 'px' ],
[ 'label' => __( 'Button Font Weight', 'notificationx' ), 'name' => 'exit_intent_t7_btn_font_weight', 'type' => 'select', 'default' => '700',
'options' => $this->font_weight_options() ],
];
}
public function customize_fields( $fields ) {
// Hide standard timing/behaviour irrelevant to exit intent
foreach ( [ 'timing', 'behaviour', 'sound_section', 'queue_management', 'appearance', 'animation' ] as $key ) {
if ( isset( $fields[ $key ] ) ) {
$fields[ $key ] = Rules::is( 'source', $this->id, true, $fields[ $key ] );
}
}
// Add center position option
if ( isset( $fields['appearance']['fields']['position']['options'] ) ) {
$fields['appearance']['fields']['position']['options']['center'] = [
'label' => __( 'Center', 'notificationx' ),
'value' => 'center',
'rules' => Rules::is( 'source', $this->id ),
];
}
// NOTE: keep this key unique. The Announcement extension (PopupNotification)
// also registers a section literally named `exit_intent_settings` for its
// "Convert to Exit Intent" feature; sharing the key here let Popup's filter
// (same `nx_customize_fields` priority, registered later) overwrite this
// section with a `source == popup_notification` rule, hiding it for the
// Exit Intent type and leaving the whole Customize tab blank.
$fields['exit_intent_popup_settings'] = [
'label' => __( 'Exit Intent Settings', 'notificationx' ),
'name' => 'exit_intent_popup_settings',
'type' => 'section',
'priority' => 15,
'rules' => Rules::is( 'source', $this->id ),
'fields' => [
'show_close_button' => [
'label' => __( 'Show Close Button', 'notificationx' ),
'name' => 'show_close_button',
'type' => 'toggle',
'default' => true,
],
'exit_intent_position' => [
'label' => __( 'Position', 'notificationx' ),
'name' => 'exit_intent_position',
'type' => 'select',
'default' => 'center',
'options' => GlobalFields::get_instance()->normalize_fields( [
'center' => __( 'Center', 'notificationx' ),
'bottom-left' => __( 'Bottom Left', 'notificationx' ),
'bottom-right' => __( 'Bottom Right', 'notificationx' ),
] ),
],
'exit_intent_sensitivity' => [
'label' => __( 'Trigger Sensitivity', 'notificationx' ),
'name' => 'exit_intent_sensitivity',
'type' => 'select',
'default' => '20',
'help' => __( 'Distance from top of viewport (px) that triggers the popup.', 'notificationx' ),
'options' => GlobalFields::get_instance()->normalize_fields( [
'10' => __( 'High (10px)', 'notificationx' ),
'20' => __( 'Medium (20px)', 'notificationx' ),
'50' => __( 'Low (50px)', 'notificationx' ),
] ),
],
'exit_intent_cookie_days' => [
'label' => __( 'Do Not Show Again For', 'notificationx' ),
'name' => 'exit_intent_cookie_days',
'type' => 'number',
'default' => 7,
'description' => __( 'days', 'notificationx' ),
'help' => __( 'Once dismissed, hide the popup for this many days.', 'notificationx' ),
],
'exit_intent_mobile_disable' => [
'label' => __( 'Disable on Mobile', 'notificationx' ),
'name' => 'exit_intent_mobile_disable',
'type' => 'toggle',
'default' => true,
'help' => __( 'Exit intent detection is unreliable on touch devices.', 'notificationx' ),
],
],
];
return $fields;
}
public function doc() {
/* translators: %1$s: documentation link URL */
return sprintf(__('
Show a targeted message at the exact moment someone is about to close your tab & bring them back into the funnel. Need help? Check out our documentation.
',
'notificationx'),
'https://notificationx.com/docs/how-to-configure-exit-intent-popup/',
);
}
}