tel_href( $text ) : ''; } elseif ( 'email' === $kind ) { $text = sanitize_email( $text ); if ( '' === $text || ! is_email( $text ) ) { continue; } $url = $linked ? 'mailto:' . $text : ''; } elseif ( $linked ) { $url = $this->maps_href( $text ); } $out[] = array( 'text' => $text, 'label' => trim( (string) ( $row['label'] ?? '' ) ), 'url' => $url, ); } return $out; } private function get_days() { return array( 'mon' => __( 'Monday', 'a1-tools' ), 'tue' => __( 'Tuesday', 'a1-tools' ), 'wed' => __( 'Wednesday', 'a1-tools' ), 'thu' => __( 'Thursday', 'a1-tools' ), 'fri' => __( 'Friday', 'a1-tools' ), 'sat' => __( 'Saturday', 'a1-tools' ), 'sun' => __( 'Sunday', 'a1-tools' ), ); } // ──────────────────────────────────────────────────────────────── // Controls // ──────────────────────────────────────────────────────────────── protected function register_controls() { // ── Content: Phone ────────────────────────────────────────── $this->start_controls_section( 'phone_section', array( 'label' => __( 'Phone', 'a1-tools' ), 'tab' => \Elementor\Controls_Manager::TAB_CONTENT, ) ); $this->add_control( 'show_phone', array( 'label' => __( 'Show Phone', 'a1-tools' ), 'type' => \Elementor\Controls_Manager::SWITCHER, 'default' => 'yes', 'return_value' => 'yes', ) ); $this->add_control( 'phone_icon', array( 'label' => __( 'Icon', 'a1-tools' ), 'type' => \Elementor\Controls_Manager::ICONS, 'default' => array( 'value' => 'fas fa-phone-alt', 'library' => 'fa-solid' ), 'condition' => array( 'show_phone' => 'yes' ), ) ); $this->add_control( 'phone_title', array( 'label' => __( 'Title', 'a1-tools' ), 'type' => \Elementor\Controls_Manager::TEXT, 'default' => __( 'Phone', 'a1-tools' ), 'condition' => array( 'show_phone' => 'yes' ), ) ); $this->add_control( 'phone_link', array( 'label' => __( 'Click-to-call Link', 'a1-tools' ), 'type' => \Elementor\Controls_Manager::SWITCHER, 'default' => 'yes', 'return_value' => 'yes', 'condition' => array( 'show_phone' => 'yes' ), ) ); $phone_repeater = new \Elementor\Repeater(); $phone_repeater->add_control( 'number', array( 'label' => __( 'Phone Number', 'a1-tools' ), 'type' => \Elementor\Controls_Manager::TEXT, 'placeholder' => '(216) 555-0100', 'label_block' => true, ) ); $phone_repeater->add_control( 'label', array( 'label' => __( 'Label', 'a1-tools' ), 'type' => \Elementor\Controls_Manager::TEXT, 'placeholder' => __( 'Office', 'a1-tools' ), ) ); $phone_repeater->add_control( 'link', array( 'label' => __( 'Click-to-call', 'a1-tools' ), 'type' => \Elementor\Controls_Manager::SWITCHER, 'default' => 'yes', 'return_value' => 'yes', ) ); $this->add_control( 'phone_extra', array( 'label' => __( 'Additional Phone Numbers', 'a1-tools' ), 'type' => \Elementor\Controls_Manager::REPEATER, 'fields' => $phone_repeater->get_controls(), 'default' => array(), 'title_field' => '{{{ label ? label + ": " + number : number }}}', 'condition' => array( 'show_phone' => 'yes' ), 'separator' => 'before', ) ); $this->end_controls_section(); // ── Content: Email ────────────────────────────────────────── $this->start_controls_section( 'email_section', array( 'label' => __( 'Email', 'a1-tools' ), 'tab' => \Elementor\Controls_Manager::TAB_CONTENT, ) ); $this->add_control( 'show_email', array( 'label' => __( 'Show Email', 'a1-tools' ), 'type' => \Elementor\Controls_Manager::SWITCHER, 'default' => 'yes', 'return_value' => 'yes', ) ); $this->add_control( 'email_icon', array( 'label' => __( 'Icon', 'a1-tools' ), 'type' => \Elementor\Controls_Manager::ICONS, 'default' => array( 'value' => 'fas fa-envelope', 'library' => 'fa-solid' ), 'condition' => array( 'show_email' => 'yes' ), ) ); $this->add_control( 'email_title', array( 'label' => __( 'Title', 'a1-tools' ), 'type' => \Elementor\Controls_Manager::TEXT, 'default' => __( 'Email', 'a1-tools' ), 'condition' => array( 'show_email' => 'yes' ), ) ); $this->add_control( 'email_link', array( 'label' => __( 'Mailto Link', 'a1-tools' ), 'type' => \Elementor\Controls_Manager::SWITCHER, 'default' => 'yes', 'return_value' => 'yes', 'condition' => array( 'show_email' => 'yes' ), ) ); $email_repeater = new \Elementor\Repeater(); $email_repeater->add_control( 'address', array( 'label' => __( 'Email Address', 'a1-tools' ), 'type' => \Elementor\Controls_Manager::TEXT, 'input_type' => 'email', 'placeholder' => 'office@example.com', 'label_block' => true, ) ); $email_repeater->add_control( 'label', array( 'label' => __( 'Label', 'a1-tools' ), 'type' => \Elementor\Controls_Manager::TEXT, 'placeholder' => __( 'Support', 'a1-tools' ), ) ); $email_repeater->add_control( 'link', array( 'label' => __( 'Mailto Link', 'a1-tools' ), 'type' => \Elementor\Controls_Manager::SWITCHER, 'default' => 'yes', 'return_value' => 'yes', ) ); $this->add_control( 'email_extra', array( 'label' => __( 'Additional Email Addresses', 'a1-tools' ), 'type' => \Elementor\Controls_Manager::REPEATER, 'fields' => $email_repeater->get_controls(), 'default' => array(), 'title_field' => '{{{ label ? label + ": " + address : address }}}', 'condition' => array( 'show_email' => 'yes' ), 'separator' => 'before', ) ); $this->end_controls_section(); // ── Content: Location ─────────────────────────────────────── $this->start_controls_section( 'location_section', array( 'label' => __( 'Location', 'a1-tools' ), 'tab' => \Elementor\Controls_Manager::TAB_CONTENT, ) ); $this->add_control( 'show_location', array( 'label' => __( 'Show Location', 'a1-tools' ), 'type' => \Elementor\Controls_Manager::SWITCHER, 'default' => 'yes', 'return_value' => 'yes', ) ); $this->add_control( 'location_icon', array( 'label' => __( 'Icon', 'a1-tools' ), 'type' => \Elementor\Controls_Manager::ICONS, 'default' => array( 'value' => 'fas fa-map-marker-alt', 'library' => 'fa-solid' ), 'condition' => array( 'show_location' => 'yes' ), ) ); $this->add_control( 'location_title', array( 'label' => __( 'Title', 'a1-tools' ), 'type' => \Elementor\Controls_Manager::TEXT, 'default' => __( 'Location', 'a1-tools' ), 'condition' => array( 'show_location' => 'yes' ), ) ); $this->add_control( 'location_link', array( 'label' => __( 'Google Maps Link', 'a1-tools' ), 'type' => \Elementor\Controls_Manager::SWITCHER, 'default' => 'yes', 'return_value' => 'yes', 'condition' => array( 'show_location' => 'yes' ), ) ); $location_repeater = new \Elementor\Repeater(); $location_repeater->add_control( 'address', array( 'label' => __( 'Address', 'a1-tools' ), 'type' => \Elementor\Controls_Manager::TEXTAREA, 'rows' => 3, 'placeholder' => "123 Main St\nCleveland, OH 44101", 'label_block' => true, ) ); $location_repeater->add_control( 'label', array( 'label' => __( 'Label', 'a1-tools' ), 'type' => \Elementor\Controls_Manager::TEXT, 'placeholder' => __( 'Main Office', 'a1-tools' ), ) ); $location_repeater->add_control( 'link', array( 'label' => __( 'Google Maps Link', 'a1-tools' ), 'type' => \Elementor\Controls_Manager::SWITCHER, 'default' => 'yes', 'return_value' => 'yes', ) ); $this->add_control( 'location_extra', array( 'label' => __( 'Additional Locations', 'a1-tools' ), 'type' => \Elementor\Controls_Manager::REPEATER, 'fields' => $location_repeater->get_controls(), 'default' => array(), 'title_field' => '{{{ label ? label : address }}}', 'condition' => array( 'show_location' => 'yes' ), 'separator' => 'before', ) ); $this->end_controls_section(); // ── Content: Hours ────────────────────────────────────────── $this->start_controls_section( 'hours_section', array( 'label' => __( 'Hours', 'a1-tools' ), 'tab' => \Elementor\Controls_Manager::TAB_CONTENT, ) ); $this->add_control( 'show_hours', array( 'label' => __( 'Show Hours', 'a1-tools' ), 'type' => \Elementor\Controls_Manager::SWITCHER, 'default' => 'yes', 'return_value' => 'yes', ) ); $this->add_control( 'hours_icon', array( 'label' => __( 'Icon', 'a1-tools' ), 'type' => \Elementor\Controls_Manager::ICONS, 'default' => array( 'value' => 'far fa-clock', 'library' => 'fa-regular' ), 'condition' => array( 'show_hours' => 'yes' ), ) ); $this->add_control( 'hours_title', array( 'label' => __( 'Title', 'a1-tools' ), 'type' => \Elementor\Controls_Manager::TEXT, 'default' => __( 'Hours', 'a1-tools' ), 'condition' => array( 'show_hours' => 'yes' ), ) ); $this->add_control( 'hours_closed_text', array( 'label' => __( 'Closed Text', 'a1-tools' ), 'type' => \Elementor\Controls_Manager::TEXT, 'default' => __( 'Closed', 'a1-tools' ), 'condition' => array( 'show_hours' => 'yes' ), ) ); $this->add_control( 'hours_hide_closed', array( 'label' => __( 'Hide Closed Days', 'a1-tools' ), 'type' => \Elementor\Controls_Manager::SWITCHER, 'return_value' => 'yes', 'default' => '', 'condition' => array( 'show_hours' => 'yes' ), ) ); $this->end_controls_section(); // ── Content: License ──────────────────────────────────────── $this->start_controls_section( 'license_section', array( 'label' => __( 'License', 'a1-tools' ), 'tab' => \Elementor\Controls_Manager::TAB_CONTENT, ) ); $this->add_control( 'show_license', array( 'label' => __( 'Show License', 'a1-tools' ), 'type' => \Elementor\Controls_Manager::SWITCHER, 'default' => 'yes', 'return_value' => 'yes', ) ); $this->add_control( 'license_icon', array( 'label' => __( 'Icon', 'a1-tools' ), 'type' => \Elementor\Controls_Manager::ICONS, 'default' => array( 'value' => 'fas fa-certificate', 'library' => 'fa-solid' ), 'condition' => array( 'show_license' => 'yes' ), ) ); $this->add_control( 'license_title', array( 'label' => __( 'Title', 'a1-tools' ), 'type' => \Elementor\Controls_Manager::TEXT, 'default' => __( 'License', 'a1-tools' ), 'condition' => array( 'show_license' => 'yes' ), ) ); $this->end_controls_section(); // ── Style: Icon ───────────────────────────────────────────── $this->start_controls_section( 'icon_style', array( 'label' => __( 'Icon', 'a1-tools' ), 'tab' => \Elementor\Controls_Manager::TAB_STYLE, ) ); $this->add_control( 'icon_color', array( 'label' => __( 'Color', 'a1-tools' ), 'type' => \Elementor\Controls_Manager::COLOR, 'default' => '#E53935', 'selectors' => array( '{{WRAPPER}} .a1tools-info-box-icon' => 'color: {{VALUE}};', '{{WRAPPER}} .a1tools-info-box-icon svg' => 'fill: {{VALUE}};', ), ) ); $this->add_control( 'icon_size', array( 'label' => __( 'Size', 'a1-tools' ), 'type' => \Elementor\Controls_Manager::SLIDER, 'size_units' => array( 'px' ), 'range' => array( 'px' => array( 'min' => 12, 'max' => 80 ) ), 'default' => array( 'unit' => 'px', 'size' => 28 ), 'selectors' => array( '{{WRAPPER}} .a1tools-info-box-icon' => 'font-size: {{SIZE}}{{UNIT}};', '{{WRAPPER}} .a1tools-info-box-icon svg' => 'width: {{SIZE}}{{UNIT}}; height: {{SIZE}}{{UNIT}};', ), ) ); $this->add_control( 'icon_bg_heading', array( 'label' => __( 'Background', 'a1-tools' ), 'type' => \Elementor\Controls_Manager::HEADING, 'separator' => 'before', ) ); $this->add_control( 'icon_bg_color', array( 'label' => __( 'Background Color', 'a1-tools' ), 'type' => \Elementor\Controls_Manager::COLOR, 'default' => '', 'selectors' => array( '{{WRAPPER}} .a1tools-info-box-icon' => 'background-color: {{VALUE}};', ), ) ); $this->add_control( 'icon_padding', array( 'label' => __( 'Padding', 'a1-tools' ), 'type' => \Elementor\Controls_Manager::DIMENSIONS, 'size_units' => array( 'px' ), 'selectors' => array( '{{WRAPPER}} .a1tools-info-box-icon' => 'padding: {{TOP}}{{UNIT}} {{RIGHT}}{{UNIT}} {{BOTTOM}}{{UNIT}} {{LEFT}}{{UNIT}};', ), ) ); $this->add_control( 'icon_border_heading', array( 'label' => __( 'Border', 'a1-tools' ), 'type' => \Elementor\Controls_Manager::HEADING, 'separator' => 'before', ) ); $this->add_group_control( \Elementor\Group_Control_Border::get_type(), array( 'name' => 'icon_border', 'label' => __( 'Border', 'a1-tools' ), 'selector' => '{{WRAPPER}} .a1tools-info-box-icon', ) ); $this->add_control( 'icon_border_radius', array( 'label' => __( 'Border Radius', 'a1-tools' ), 'type' => \Elementor\Controls_Manager::SLIDER, 'size_units' => array( 'px', '%' ), 'range' => array( 'px' => array( 'min' => 0, 'max' => 50 ), '%' => array( 'min' => 0, 'max' => 50 ), ), 'selectors' => array( '{{WRAPPER}} .a1tools-info-box-icon' => 'border-radius: {{SIZE}}{{UNIT}};', ), ) ); $this->add_control( 'icon_gap', array( 'label' => __( 'Spacing', 'a1-tools' ), 'type' => \Elementor\Controls_Manager::SLIDER, 'size_units' => array( 'px' ), 'range' => array( 'px' => array( 'min' => 0, 'max' => 40 ) ), 'default' => array( 'unit' => 'px', 'size' => 12 ), 'separator' => 'before', 'selectors' => array( '{{WRAPPER}} .a1tools-contact-info-item' => 'gap: {{SIZE}}{{UNIT}};', ), ) ); $this->end_controls_section(); // ── Style: Content ────────────────────────────────────────── $this->start_controls_section( 'content_style', array( 'label' => __( 'Content', 'a1-tools' ), 'tab' => \Elementor\Controls_Manager::TAB_STYLE, ) ); $this->add_responsive_control( 'alignment', array( 'label' => __( 'Alignment', 'a1-tools' ), 'type' => \Elementor\Controls_Manager::CHOOSE, 'options' => array( 'left' => array( 'title' => __( 'Left', 'a1-tools' ), 'icon' => 'eicon-text-align-left' ), 'center' => array( 'title' => __( 'Center', 'a1-tools' ), 'icon' => 'eicon-text-align-center' ), 'right' => array( 'title' => __( 'Right', 'a1-tools' ), 'icon' => 'eicon-text-align-right' ), ), 'default' => 'left', 'selectors_dictionary' => array( 'left' => 'flex-start', 'center' => 'center', 'right' => 'flex-end' ), 'selectors' => array( '{{WRAPPER}} .a1tools-contact-info-item' => 'justify-content: {{VALUE}};', ), ) ); $this->add_responsive_control( 'vertical_alignment', array( 'label' => __( 'Vertical Alignment', 'a1-tools' ), 'type' => \Elementor\Controls_Manager::CHOOSE, 'options' => array( 'flex-start' => array( 'title' => __( 'Top', 'a1-tools' ), 'icon' => 'eicon-v-align-top' ), 'center' => array( 'title' => __( 'Middle', 'a1-tools' ), 'icon' => 'eicon-v-align-middle' ), 'flex-end' => array( 'title' => __( 'Bottom', 'a1-tools' ), 'icon' => 'eicon-v-align-bottom' ), ), 'default' => 'flex-start', 'selectors' => array( '{{WRAPPER}} .a1tools-contact-info-item' => 'align-items: {{VALUE}};', ), ) ); $this->add_control( 'title_color', array( 'label' => __( 'Title Color', 'a1-tools' ), 'type' => \Elementor\Controls_Manager::COLOR, 'separator' => 'before', 'selectors' => array( '{{WRAPPER}} .a1tools-info-box-title' => 'color: {{VALUE}};' ), ) ); $this->add_group_control( \Elementor\Group_Control_Typography::get_type(), array( 'name' => 'title_typography', 'label' => __( 'Title Typography', 'a1-tools' ), 'selector' => '{{WRAPPER}} .a1tools-info-box-title', ) ); $this->add_control( 'value_color', array( 'label' => __( 'Value Color', 'a1-tools' ), 'type' => \Elementor\Controls_Manager::COLOR, 'separator' => 'before', 'selectors' => array( '{{WRAPPER}} .a1tools-info-box-value' => 'color: {{VALUE}};' ), ) ); $this->add_group_control( \Elementor\Group_Control_Typography::get_type(), array( 'name' => 'value_typography', 'label' => __( 'Value Typography', 'a1-tools' ), 'selector' => '{{WRAPPER}} .a1tools-info-box-value', ) ); $this->add_control( 'link_heading', array( 'label' => __( 'Link', 'a1-tools' ), 'type' => \Elementor\Controls_Manager::HEADING, 'separator' => 'before', ) ); $this->add_control( 'link_underline', array( 'label' => __( 'Underline', 'a1-tools' ), 'type' => \Elementor\Controls_Manager::SELECT, 'default' => 'none', 'options' => array( 'none' => __( 'None', 'a1-tools' ), 'underline' => __( 'Always', 'a1-tools' ), 'hover' => __( 'On Hover', 'a1-tools' ), ), 'selectors_dictionary' => array( 'none' => 'none', 'underline' => 'underline', 'hover' => 'none', ), 'selectors' => array( '{{WRAPPER}} a.a1tools-info-box-link .a1tools-info-box-value' => 'text-decoration: {{VALUE}};', ), ) ); $this->add_control( 'hover_heading', array( 'label' => __( 'Hover', 'a1-tools' ), 'type' => \Elementor\Controls_Manager::HEADING, 'separator' => 'before', ) ); $this->add_control( 'hover_icon_color', array( 'label' => __( 'Icon Color', 'a1-tools' ), 'type' => \Elementor\Controls_Manager::COLOR, 'selectors' => array( '{{WRAPPER}} a.a1tools-info-box-link:hover .a1tools-info-box-icon' => 'color: {{VALUE}};', '{{WRAPPER}} a.a1tools-info-box-link:hover .a1tools-info-box-icon svg' => 'fill: {{VALUE}};', ), ) ); $this->add_control( 'hover_title_color', array( 'label' => __( 'Title Color', 'a1-tools' ), 'type' => \Elementor\Controls_Manager::COLOR, 'selectors' => array( '{{WRAPPER}} a.a1tools-info-box-link:hover .a1tools-info-box-title' => 'color: {{VALUE}};', ), ) ); $this->add_control( 'hover_value_color', array( 'label' => __( 'Value Color', 'a1-tools' ), 'type' => \Elementor\Controls_Manager::COLOR, 'selectors' => array( '{{WRAPPER}} a.a1tools-info-box-link:hover .a1tools-info-box-value' => 'color: {{VALUE}};', ), ) ); $this->add_control( 'title_value_gap', array( 'label' => __( 'Title / Value Gap', 'a1-tools' ), 'type' => \Elementor\Controls_Manager::SLIDER, 'size_units' => array( 'px' ), 'range' => array( 'px' => array( 'min' => 0, 'max' => 20 ) ), 'default' => array( 'unit' => 'px', 'size' => 2 ), 'separator' => 'before', 'selectors' => array( '{{WRAPPER}} .a1tools-info-box-content' => 'gap: {{SIZE}}{{UNIT}};' ), ) ); $this->end_controls_section(); // ── Style: Hours ──────────────────────────────────────────── $this->start_controls_section( 'hours_style', array( 'label' => __( 'Hours', 'a1-tools' ), 'tab' => \Elementor\Controls_Manager::TAB_STYLE, 'condition' => array( 'show_hours' => 'yes' ), ) ); $this->add_control( 'hours_day_color', array( 'label' => __( 'Day Color', 'a1-tools' ), 'type' => \Elementor\Controls_Manager::COLOR, 'selectors' => array( '{{WRAPPER}} .a1tools-hours-day' => 'color: {{VALUE}};' ), ) ); $this->add_group_control( \Elementor\Group_Control_Typography::get_type(), array( 'name' => 'hours_day_typography', 'label' => __( 'Day Typography', 'a1-tools' ), 'selector' => '{{WRAPPER}} .a1tools-hours-day', ) ); $this->add_control( 'hours_time_color', array( 'label' => __( 'Time Color', 'a1-tools' ), 'type' => \Elementor\Controls_Manager::COLOR, 'separator' => 'before', 'selectors' => array( '{{WRAPPER}} .a1tools-hours-time' => 'color: {{VALUE}};' ), ) ); $this->add_group_control( \Elementor\Group_Control_Typography::get_type(), array( 'name' => 'hours_time_typography', 'label' => __( 'Time Typography', 'a1-tools' ), 'selector' => '{{WRAPPER}} .a1tools-hours-time', ) ); $this->add_control( 'hours_closed_color', array( 'label' => __( 'Closed Text Color', 'a1-tools' ), 'type' => \Elementor\Controls_Manager::COLOR, 'separator' => 'before', 'selectors' => array( '{{WRAPPER}} .a1tools-hours-closed .a1tools-hours-time' => 'color: {{VALUE}};' ), ) ); // The former "Day Column Width" slider forced a min-width on // .a1tools-hours-day, which is exactly the large day/time gap this // widget is not supposed to have. The control is gone; saved // `hours_day_width` values are simply ignored (Elementor drops keys // with no matching control), so no document migration is needed. $this->end_controls_section(); // ── Style: Layout ─────────────────────────────────────────── $this->start_controls_section( 'layout_style', array( 'label' => __( 'Layout', 'a1-tools' ), 'tab' => \Elementor\Controls_Manager::TAB_STYLE, ) ); $this->add_control( 'item_spacing', array( 'label' => __( 'Item Spacing', 'a1-tools' ), 'type' => \Elementor\Controls_Manager::SLIDER, 'size_units' => array( 'px' ), 'range' => array( 'px' => array( 'min' => 0, 'max' => 60 ) ), 'default' => array( 'unit' => 'px', 'size' => 20 ), 'selectors' => array( '{{WRAPPER}} .a1tools-contact-info-widget' => 'gap: {{SIZE}}{{UNIT}};', ), ) ); $this->add_control( 'value_spacing', array( 'label' => __( 'Value Spacing', 'a1-tools' ), 'description' => __( 'Gap between the primary value and any additional Phone / Email / Location entries.', 'a1-tools' ), 'type' => \Elementor\Controls_Manager::SLIDER, 'size_units' => array( 'px' ), 'range' => array( 'px' => array( 'min' => 0, 'max' => 24 ) ), 'default' => array( 'unit' => 'px', 'size' => 4 ), 'selectors' => array( '{{WRAPPER}} .a1tools-info-box-values' => 'gap: {{SIZE}}{{UNIT}};', ), ) ); $this->add_control( 'show_item_divider', array( 'label' => __( 'Show Dividers', 'a1-tools' ), 'type' => \Elementor\Controls_Manager::SWITCHER, 'return_value' => 'yes', 'default' => '', ) ); $this->add_control( 'item_divider_color', array( 'label' => __( 'Divider Color', 'a1-tools' ), 'type' => \Elementor\Controls_Manager::COLOR, 'default' => '#e0e0e0', 'condition' => array( 'show_item_divider' => 'yes' ), 'selectors' => array( '{{WRAPPER}} .a1tools-has-dividers > .a1tools-contact-info-item + .a1tools-contact-info-item' => 'border-top-color: {{VALUE}};', ), ) ); $this->end_controls_section(); // ── Style: Box ────────────────────────────────────────────── $this->start_controls_section( 'box_style', array( 'label' => __( 'Box Style', 'a1-tools' ), 'tab' => \Elementor\Controls_Manager::TAB_STYLE, ) ); $this->add_control( 'box_bg_color', array( 'label' => __( 'Background', 'a1-tools' ), 'type' => \Elementor\Controls_Manager::COLOR, 'selectors' => array( '{{WRAPPER}} .a1tools-contact-info-widget' => 'background-color: {{VALUE}};' ), ) ); $this->add_group_control( \Elementor\Group_Control_Border::get_type(), array( 'name' => 'box_border', 'selector' => '{{WRAPPER}} .a1tools-contact-info-widget', ) ); $this->add_control( 'box_border_hover_color', array( 'label' => __( 'Border Hover Color', 'a1-tools' ), 'type' => \Elementor\Controls_Manager::COLOR, 'selectors' => array( '{{WRAPPER}} .a1tools-contact-info-widget:hover' => 'border-color: {{VALUE}};', ), 'condition' => array( 'box_border_border!' => '' ), ) ); $this->add_control( 'box_border_radius', array( 'label' => __( 'Border Radius', 'a1-tools' ), 'type' => \Elementor\Controls_Manager::DIMENSIONS, 'size_units' => array( 'px', '%' ), 'selectors' => array( '{{WRAPPER}} .a1tools-contact-info-widget' => 'border-radius: {{TOP}}{{UNIT}} {{RIGHT}}{{UNIT}} {{BOTTOM}}{{UNIT}} {{LEFT}}{{UNIT}};' ), ) ); $this->add_control( 'box_padding', array( 'label' => __( 'Padding', 'a1-tools' ), 'type' => \Elementor\Controls_Manager::DIMENSIONS, 'size_units' => array( 'px', 'em' ), 'selectors' => array( '{{WRAPPER}} .a1tools-contact-info-widget' => 'padding: {{TOP}}{{UNIT}} {{RIGHT}}{{UNIT}} {{BOTTOM}}{{UNIT}} {{LEFT}}{{UNIT}};' ), ) ); $this->add_group_control( \Elementor\Group_Control_Box_Shadow::get_type(), array( 'name' => 'box_shadow', 'selector' => '{{WRAPPER}} .a1tools-contact-info-widget', ) ); $this->end_controls_section(); } // ──────────────────────────────────────────────────────────────── // Render // ──────────────────────────────────────────────────────────────── protected function render() { $settings = $this->get_settings_for_display(); $vars = $this->get_site_vars(); $has_dividers = 'yes' === ( $settings['show_item_divider'] ?? '' ) ? ' a1tools-has-dividers' : ''; $underline = $settings['link_underline'] ?? 'none'; $underline_class = 'hover' === $underline ? ' a1tools-underline-hover' : ''; echo '
'; // Phone — API phone_primary first, then any custom entries. if ( 'yes' === ( $settings['show_phone'] ?? '' ) && $vars ) { $phone = $vars['phone_primary'] ?? ''; if ( $phone ) { $values = array( array( 'text' => $phone, 'label' => '', 'url' => 'yes' === ( $settings['phone_link'] ?? '' ) ? $this->tel_href( $phone ) : '', ) ); $values = array_merge( $values, $this->collect_extra_values( $settings['phone_extra'] ?? array(), 'number', 'phone' ) ); $this->render_info_item( $settings['phone_icon'] ?? array(), $settings['phone_title'] ?? '', $values, $underline_class ); } } // Email — API email_primary first, then any custom entries. if ( 'yes' === ( $settings['show_email'] ?? '' ) && $vars ) { $email = $vars['email_primary'] ?? ''; if ( $email ) { $values = array( array( 'text' => $email, 'label' => '', 'url' => 'yes' === ( $settings['email_link'] ?? '' ) ? 'mailto:' . sanitize_email( $email ) : '', ) ); $values = array_merge( $values, $this->collect_extra_values( $settings['email_extra'] ?? array(), 'address', 'email' ) ); $this->render_info_item( $settings['email_icon'] ?? array(), $settings['email_title'] ?? '', $values, $underline_class ); } } // Location — API-derived address first, then any custom entries. if ( 'yes' === ( $settings['show_location'] ?? '' ) && $vars ) { $address = $this->get_address( $vars ); if ( $address ) { $values = array( array( 'text' => $address, 'label' => '', 'url' => 'yes' === ( $settings['location_link'] ?? '' ) ? $this->maps_href( $address ) : '', ) ); $values = array_merge( $values, $this->collect_extra_values( $settings['location_extra'] ?? array(), 'address', 'location' ) ); $this->render_info_item( $settings['location_icon'] ?? array(), $settings['location_title'] ?? '', $values, $underline_class ); } } // Hours if ( 'yes' === ( $settings['show_hours'] ?? '' ) && $vars && ! empty( $vars['operating_hours'] ) ) { $this->render_hours_item( $settings, $vars['operating_hours'] ); } // License if ( 'yes' === ( $settings['show_license'] ?? '' ) && $vars ) { $license = $vars['licence'] ?? ''; if ( $license ) { $this->render_info_item( $settings['license_icon'] ?? array(), $settings['license_title'] ?? '', array( array( 'text' => $license, 'label' => '', 'url' => '' ) ), $underline_class ); } } echo '
'; } /** * Render one information item: a single icon + title, then one primary * value and zero or more additional values stacked beneath it. * * With exactly one linked value the whole item stays a single , which is * the pre-repeater markup — existing widgets render byte-identically. As soon * as there is more than one value the item becomes a
and each value * carries its own anchor, because anchors cannot legally nest. * * @param array $icon Elementor ICONS control value. * @param string $title Item title ('Phone', 'Email', …). * @param array $values List of array{text,label,url}; first is primary. * @param string $underline_class Extra class for hover-underline styling. */ private function render_info_item( $icon, $title, $values, $underline_class = '' ) { $values = array_values( array_filter( (array) $values, function ( $v ) { return '' !== trim( (string) ( $v['text'] ?? '' ) ); } ) ); if ( empty( $values ) ) { return; } $wrap_link = ( 1 === count( $values ) ) && ! empty( $values[0]['url'] ); if ( $wrap_link ) { echo ''; } else { echo '
'; } if ( ! empty( $icon['value'] ) ) { echo '
'; \Elementor\Icons_Manager::render_icon( $icon, array( 'aria-hidden' => 'true' ) ); echo '
'; } echo '
'; echo $wrap_link ? '' : '
'; } private function render_hours_item( $settings, $hours ) { $closed_text = ! empty( $settings['hours_closed_text'] ) ? $settings['hours_closed_text'] : __( 'Closed', 'a1-tools' ); $hide_closed = 'yes' === ( $settings['hours_hide_closed'] ?? '' ); $days = $this->get_days(); echo '
'; if ( ! empty( $settings['hours_icon']['value'] ) ) { echo '
'; \Elementor\Icons_Manager::render_icon( $settings['hours_icon'], array( 'aria-hidden' => 'true' ) ); echo '
'; } echo '
'; if ( ! empty( $settings['hours_title'] ) ) { echo '' . esc_html( $settings['hours_title'] ) . ''; } echo '
'; foreach ( $days as $key => $label ) { $is_closed = ! isset( $hours[ $key ] ) || '' === $hours[ $key ]; $time_text = $is_closed ? $closed_text : $hours[ $key ]; if ( $hide_closed && $is_closed ) { continue; } $row_class = 'a1tools-hours-row' . ( $is_closed ? ' a1tools-hours-closed' : '' ); echo '
'; echo '' . esc_html( $label ) . ''; echo '' . esc_html( $time_text ) . ''; echo '
'; } echo '
'; echo '
'; echo '
'; } // ──────────────────────────────────────────────────────────────── // Editor template // ──────────────────────────────────────────────────────────────── protected function content_template() { $vars = $this->get_site_vars(); $phone = $vars ? ( $vars['phone_primary'] ?? '' ) : ''; $email = $vars ? ( $vars['email_primary'] ?? '' ) : ''; $address = $vars ? $this->get_address( $vars ) : ''; $hours = $vars && ! empty( $vars['operating_hours'] ) ? $vars['operating_hours'] : array(); $license = $vars ? ( $vars['licence'] ?? '' ) : ''; $days_map = $this->get_days(); $js_hours = array(); foreach ( $days_map as $k => $label ) { $js_hours[] = array( 'key' => $k, 'label' => $label, 'time' => isset( $hours[ $k ] ) ? $hours[ $k ] : '', ); } ?> <# var phone = ; var email = ; var address = ; var hours = ; var license = ; var divCls = settings.show_item_divider === 'yes' ? ' a1tools-has-dividers' : ''; var ulCls = settings.link_underline === 'hover' ? ' a1tools-underline-hover' : ''; function rIcon( v, s, attr ) { if ( ! s || ! s.value ) return ''; var o = elementor.helpers.renderIcon( v, s, attr || { 'aria-hidden': 'true' }, 'i', 'object' ); return ( o && o.rendered ) ? o.value : ''; } function itemOpen( hasLink ) { if ( hasLink ) return ''; return '
'; } function itemClose( hasLink ) { return hasLink ? '' : '
'; } /* Mirrors PHP tel_href()/maps_href()/collect_extra_values() so the editor preview and the frontend produce the same markup. */ function telHref( n ) { var plus = /^\s*\+/.test( n ) ? '+' : ''; var d = String( n ).replace( /[^0-9]/g, '' ); return d ? 'tel:' + plus + d : ''; } function mapsHref( a ) { return 'https://maps.google.com/?q=' + encodeURIComponent( String( a ).replace( /\s+/g, ' ' ).replace( /^ | $/g, '' ) ); } function extraValues( rows, field, kind ) { var out = []; _.each( rows || [], function ( r ) { var t = String( r[ field ] || '' ).replace( /^\s+|\s+$/g, '' ); if ( ! t ) { return; } var linked = r.link === 'yes'; var url = ''; if ( 'phone' === kind ) { url = linked ? telHref( t ) : ''; } else if ( 'email' === kind ) { if ( ! /^[^@\s]+@[^@\s]+\.[^@\s]+$/.test( t ) ) { return; } url = linked ? 'mailto:' + t : ''; } else if ( linked ) { url = mapsHref( t ); } out.push( { text: t, label: String( r.label || '' ).replace( /^\s+|\s+$/g, '' ), url: url } ); } ); return out; } function infoItem( iconSetting, title, values ) { values = _.filter( values || [], function ( v ) { return v && v.text; } ); if ( ! values.length ) { return ''; } var wrapLink = 1 === values.length && !! values[0].url; var html = itemOpen( wrapLink ); var ic = rIcon( view, iconSetting ); if ( ic ) { html += '
' + ic + '
'; } html += '
'; if ( title ) { html += '' + _.escape( title ) + ''; } html += '
'; _.each( values, function ( v, i ) { var cls = 'a1tools-info-box-value ' + ( 0 === i ? 'a1tools-info-box-value--primary' : 'a1tools-info-box-value--additional' ); var innerLink = ! wrapLink && !! v.url; if ( innerLink ) { html += ''; } html += ''; if ( v.label ) { html += '' + _.escape( v.label ) + ': '; } html += _.escape( v.text ) + ''; if ( innerLink ) { html += ''; } } ); html += '
' + itemClose( wrapLink ); return html; } #>
<# if ( settings.show_phone === 'yes' && phone ) { var phoneValues = [ { text: phone, label: '', url: settings.phone_link === 'yes' ? telHref( phone ) : '' } ] .concat( extraValues( settings.phone_extra, 'number', 'phone' ) ); #>{{{ infoItem( settings.phone_icon, settings.phone_title, phoneValues ) }}}<# } #> <# if ( settings.show_email === 'yes' && email ) { var emailValues = [ { text: email, label: '', url: settings.email_link === 'yes' ? 'mailto:' + email : '' } ] .concat( extraValues( settings.email_extra, 'address', 'email' ) ); #>{{{ infoItem( settings.email_icon, settings.email_title, emailValues ) }}}<# } #> <# if ( settings.show_location === 'yes' && address ) { var locValues = [ { text: address, label: '', url: settings.location_link === 'yes' ? mapsHref( address ) : '' } ] .concat( extraValues( settings.location_extra, 'address', 'location' ) ); #>{{{ infoItem( settings.location_icon, settings.location_title, locValues ) }}}<# } #> <# if ( settings.show_hours === 'yes' && hours.length ) { #>
<# var hi = rIcon( view, settings.hours_icon ); #> <# if ( hi ) { #>
{{{ hi }}}
<# } #>
<# if ( settings.hours_title ) { #>{{ settings.hours_title }}<# } #>
<# var ct = settings.hours_closed_text || 'Closed'; var hc = settings.hours_hide_closed === 'yes'; _.each( hours, function( d ) { var closed = ! d.time; if ( hc && closed ) return; var tt = closed ? ct : d.time; var rc = 'a1tools-hours-row' + ( closed ? ' a1tools-hours-closed' : '' ); #>
{{ d.label }} {{ tt }}
<# } ); #>
<# } #> <# if ( settings.show_license === 'yes' && license ) { #>{{{ infoItem( settings.license_icon, settings.license_title, [ { text: license, label: '', url: '' } ] ) }}}<# } #>