From 8833f35c0cceec3c6abb4dce21f06c6e008243ec Mon Sep 17 00:00:00 2001 From: Iftakharul Islam Ifat <88052038+iftakharul-islam@users.noreply.github.com> Date: Wed, 18 Feb 2026 11:17:14 +0600 Subject: [PATCH 1/4] Add Elementor widgets and AJAX handlers Register and include several new Elementor widgets and add AJAX endpoints/handlers. - Added new Elementor widgets: DocsSidebar, NeedHelp, SearchModal, TableOfContents, WasThisHelpful (full widget implementations added under includes/Elementor/Widgets). - Updated includes/Elementor.php to require and register the new widgets with Elementor. - Extended includes/Ajax.php to register AJAX actions and implemented handlers for: - wedocs_helpful_vote: records yes/no votes using post meta (_wedocs_helpful_yes/_wedocs_helpful_no) with nonce verification. - wedocs_helpful_feedback: saves textual negative feedback into post meta (_wedocs_helpful_feedback) with nonce verification. - wedocs_need_help_submit: processes the "Need More Help" contact form (nonce check per widget), sends email to recipient (falls back to admin email), and optionally saves submission to Elementor Pro submissions if available. - Added private helper save_to_elementor_submissions() to persist form entries to Elementor Pro Submissions DB (checks for Elementor Pro class first). Security: nonces and input sanitization are applied; email/recipient fallbacks handled. Widgets include styles, scripts and content templates for Elementor editor preview. --- includes/Ajax.php | 184 ++++ includes/Elementor.php | 10 + includes/Elementor/Widgets/DocsSidebar.php | 789 ++++++++++++++ includes/Elementor/Widgets/NeedHelp.php | 890 ++++++++++++++++ includes/Elementor/Widgets/SearchModal.php | 972 ++++++++++++++++++ .../Elementor/Widgets/TableOfContents.php | 745 ++++++++++++++ includes/Elementor/Widgets/WasThisHelpful.php | 636 ++++++++++++ 7 files changed, 4226 insertions(+) create mode 100644 includes/Elementor/Widgets/DocsSidebar.php create mode 100644 includes/Elementor/Widgets/NeedHelp.php create mode 100644 includes/Elementor/Widgets/SearchModal.php create mode 100644 includes/Elementor/Widgets/TableOfContents.php create mode 100644 includes/Elementor/Widgets/WasThisHelpful.php diff --git a/includes/Ajax.php b/includes/Ajax.php index 81700b0e..6ad3270c 100644 --- a/includes/Ajax.php +++ b/includes/Ajax.php @@ -53,6 +53,18 @@ public function __construct() { // Handle load more for DocsGrid widget add_action('wp_ajax_wedocs_load_more_docs', [$this, 'load_more_docs']); add_action('wp_ajax_nopriv_wedocs_load_more_docs', [$this, 'load_more_docs']); + + // Handle "Was This Helpful" votes + add_action('wp_ajax_wedocs_helpful_vote', [$this, 'handle_helpful_vote']); + add_action('wp_ajax_nopriv_wedocs_helpful_vote', [$this, 'handle_helpful_vote']); + + // Handle "Was This Helpful" feedback + add_action('wp_ajax_wedocs_helpful_feedback', [$this, 'handle_helpful_feedback']); + add_action('wp_ajax_nopriv_wedocs_helpful_feedback', [$this, 'handle_helpful_feedback']); + + // Handle "Need More Help" form submission + add_action('wp_ajax_wedocs_need_help_submit', [$this, 'handle_need_help_submit']); + add_action('wp_ajax_nopriv_wedocs_need_help_submit', [$this, 'handle_need_help_submit']); } /** @@ -574,4 +586,176 @@ public function quick_search() { wp_send_json_success( $results ); } } + + /** + * Handle "Was This Helpful" vote. + */ + public function handle_helpful_vote() { + check_ajax_referer('wedocs_helpful_vote', 'nonce'); + + $post_id = intval($_POST['post_id'] ?? 0); + $vote = sanitize_text_field($_POST['vote'] ?? ''); + + if (!$post_id || !in_array($vote, ['yes', 'no'], true)) { + wp_send_json_error(['message' => __('Invalid vote.', 'wedocs')]); + } + + $meta_key = $vote === 'yes' ? '_wedocs_helpful_yes' : '_wedocs_helpful_no'; + $current = (int) get_post_meta($post_id, $meta_key, true); + update_post_meta($post_id, $meta_key, $current + 1); + + wp_send_json_success([ + 'yes' => (int) get_post_meta($post_id, '_wedocs_helpful_yes', true), + 'no' => (int) get_post_meta($post_id, '_wedocs_helpful_no', true), + ]); + } + + /** + * Handle "Was This Helpful" negative feedback text. + */ + public function handle_helpful_feedback() { + check_ajax_referer('wedocs_helpful_vote', 'nonce'); + + $post_id = intval($_POST['post_id'] ?? 0); + $feedback = sanitize_textarea_field($_POST['feedback'] ?? ''); + + if (!$post_id || empty($feedback)) { + wp_send_json_error(['message' => __('Invalid feedback.', 'wedocs')]); + } + + $existing = get_post_meta($post_id, '_wedocs_helpful_feedback', true); + if (!is_array($existing)) { + $existing = []; + } + + $existing[] = [ + 'feedback' => $feedback, + 'date' => current_time('mysql'), + 'ip' => sanitize_text_field($_SERVER['REMOTE_ADDR'] ?? ''), + ]; + + update_post_meta($post_id, '_wedocs_helpful_feedback', $existing); + wp_send_json_success(); + } + + /** + * Handle "Need More Help" contact form submission. + */ + public function handle_need_help_submit() { + $widget_id = sanitize_text_field($_POST['widget_id'] ?? ''); + + if (!wp_verify_nonce($_POST['nonce'] ?? '', 'wedocs_need_help_' . $widget_id)) { + wp_send_json_error(['message' => __('Security check failed.', 'wedocs')]); + } + + $name = sanitize_text_field($_POST['name'] ?? ''); + $email = sanitize_email($_POST['email'] ?? ''); + $subject = sanitize_text_field($_POST['subject'] ?? ''); + $message = sanitize_textarea_field($_POST['message'] ?? ''); + $page_url = esc_url_raw($_POST['page_url'] ?? ''); + $page_title = sanitize_text_field($_POST['page_title'] ?? ''); + $recipient = sanitize_email($_POST['recipient'] ?? get_option('admin_email')); + $save_to_elementor = sanitize_text_field($_POST['save_to_elementor'] ?? ''); + $post_id = intval($_POST['post_id'] ?? 0); + + if (empty($message)) { + wp_send_json_error(['message' => __('Message is required.', 'wedocs')]); + } + + if (empty($recipient) || !is_email($recipient)) { + $recipient = get_option('admin_email'); + } + + // Send email + $email_subject = !empty($subject) ? $subject : sprintf(__('[weDocs] Support request from %s', 'wedocs'), $page_title); + + $body = sprintf(__("Name: %s\n", 'wedocs'), $name ?: __('Not provided', 'wedocs')); + $body .= sprintf(__("Email: %s\n", 'wedocs'), $email ?: __('Not provided', 'wedocs')); + $body .= sprintf(__("Page: %s (%s)\n\n", 'wedocs'), $page_title, $page_url); + $body .= sprintf(__("Message:\n%s", 'wedocs'), $message); + + $headers = ['Content-Type: text/plain; charset=UTF-8']; + if (!empty($email) && is_email($email)) { + $headers[] = 'Reply-To: ' . ($name ? "$name <$email>" : $email); + } + + $sent = wp_mail($recipient, $email_subject, $body, $headers); + + // Save to Elementor Pro submissions if enabled + if ($save_to_elementor === 'yes') { + $this->save_to_elementor_submissions($widget_id, $post_id, $page_url, $page_title, [ + 'name' => $name, + 'email' => $email, + 'subject' => $subject, + 'message' => $message, + ]); + } + + if ($sent) { + wp_send_json_success(); + } else { + wp_send_json_error(['message' => __('Failed to send email. Please try again.', 'wedocs')]); + } + } + + /** + * Save form data to Elementor Pro submissions table. + * + * @param string $widget_id The Elementor widget ID. + * @param int $post_id The post/page ID where the form was submitted. + * @param string $page_url The page URL (referer). + * @param string $page_title The page title. + * @param array $fields Associative array of field id => value. + */ + private function save_to_elementor_submissions($widget_id, $post_id, $page_url, $page_title, $fields) { + // Check if Elementor Pro submissions are available + if (!class_exists('\ElementorPro\Modules\Forms\Submissions\Database\Query')) { + return; + } + + $query = \ElementorPro\Modules\Forms\Submissions\Database\Query::get_instance(); + + $fields_data = []; + foreach ($fields as $id => $value) { + if (empty($value)) { + continue; + } + + $type = 'text'; + if ($id === 'email') { + $type = 'email'; + } elseif ($id === 'message') { + $type = 'textarea'; + } + + $fields_data[] = [ + 'id' => $id, + 'value' => $value, + 'type' => $type, + ]; + } + + if (empty($fields_data)) { + return; + } + + $submission_data = [ + 'post_id' => $post_id ?: 0, + 'referer' => $page_url, + 'referer_title' => $page_title, + 'element_id' => $widget_id, + 'form_name' => __('weDocs - Need More Help', 'wedocs'), + 'campaign_id' => 0, + 'user_id' => get_current_user_id() ?: null, + 'user_ip' => sanitize_text_field($_SERVER['REMOTE_ADDR'] ?? ''), + 'user_agent' => sanitize_text_field($_SERVER['HTTP_USER_AGENT'] ?? ''), + 'actions_count' => 1, + 'actions_succeeded_count' => 1, + 'meta' => wp_json_encode([ + 'edit_post_id' => $post_id ?: 0, + ]), + ]; + + $query->add_submission($submission_data, $fields_data); + } } diff --git a/includes/Elementor.php b/includes/Elementor.php index 9f433630..a62fae37 100644 --- a/includes/Elementor.php +++ b/includes/Elementor.php @@ -44,10 +44,20 @@ public function register_widgets() { // Include widget files // require_once WEDOCS_PATH . '/includes/Elementor/Widgets/Search.php'; require_once WEDOCS_PATH . '/includes/Elementor/Widgets/DocsGrid.php'; + require_once WEDOCS_PATH . '/includes/Elementor/Widgets/TableOfContents.php'; + require_once WEDOCS_PATH . '/includes/Elementor/Widgets/NeedHelp.php'; + require_once WEDOCS_PATH . '/includes/Elementor/Widgets/WasThisHelpful.php'; + require_once WEDOCS_PATH . '/includes/Elementor/Widgets/DocsSidebar.php'; + require_once WEDOCS_PATH . '/includes/Elementor/Widgets/SearchModal.php'; // Register widgets // \Elementor\Plugin::instance()->widgets_manager->register( new \WeDevs\WeDocs\Elementor\Widgets\Search() ); \Elementor\Plugin::instance()->widgets_manager->register( new \WeDevs\WeDocs\Elementor\Widgets\DocsGrid() ); + \Elementor\Plugin::instance()->widgets_manager->register( new \WeDevs\WeDocs\Elementor\Widgets\TableOfContents() ); + \Elementor\Plugin::instance()->widgets_manager->register( new \WeDevs\WeDocs\Elementor\Widgets\NeedHelp() ); + \Elementor\Plugin::instance()->widgets_manager->register( new \WeDevs\WeDocs\Elementor\Widgets\WasThisHelpful() ); + \Elementor\Plugin::instance()->widgets_manager->register( new \WeDevs\WeDocs\Elementor\Widgets\DocsSidebar() ); + \Elementor\Plugin::instance()->widgets_manager->register( new \WeDevs\WeDocs\Elementor\Widgets\SearchModal() ); } /** diff --git a/includes/Elementor/Widgets/DocsSidebar.php b/includes/Elementor/Widgets/DocsSidebar.php new file mode 100644 index 00000000..fa429f8d --- /dev/null +++ b/includes/Elementor/Widgets/DocsSidebar.php @@ -0,0 +1,789 @@ +start_controls_section( + 'content_section', + [ + 'label' => __('Content', 'wedocs'), + 'tab' => Controls_Manager::TAB_CONTENT, + ] + ); + + $this->add_control( + 'show_search', + [ + 'label' => __('Show Quick Search', 'wedocs'), + 'type' => Controls_Manager::SWITCHER, + 'label_on' => __('Yes', 'wedocs'), + 'label_off' => __('No', 'wedocs'), + 'return_value' => 'yes', + 'default' => 'yes', + ] + ); + + $this->add_control( + 'search_placeholder', + [ + 'label' => __('Search Placeholder', 'wedocs'), + 'type' => Controls_Manager::TEXT, + 'default' => __('Quick search...', 'wedocs'), + 'condition' => ['show_search' => 'yes'], + ] + ); + + $this->add_control( + 'show_shortcut', + [ + 'label' => __('Show Keyboard Shortcut', 'wedocs'), + 'type' => Controls_Manager::SWITCHER, + 'label_on' => __('Yes', 'wedocs'), + 'label_off' => __('No', 'wedocs'), + 'return_value' => 'yes', + 'default' => 'yes', + 'description' => __('Show the ⌘K shortcut hint', 'wedocs'), + 'condition' => ['show_search' => 'yes'], + ] + ); + + $this->add_control( + 'show_title', + [ + 'label' => __('Show Doc Title', 'wedocs'), + 'type' => Controls_Manager::SWITCHER, + 'label_on' => __('Yes', 'wedocs'), + 'label_off' => __('No', 'wedocs'), + 'return_value' => 'yes', + 'default' => 'yes', + ] + ); + + $this->add_control( + 'collapse_behavior', + [ + 'label' => __('Default Collapse', 'wedocs'), + 'type' => Controls_Manager::SELECT, + 'default' => 'expand_active', + 'options' => [ + 'expand_active' => __('Expand Active Only', 'wedocs'), + 'expand_all' => __('Expand All', 'wedocs'), + 'collapse_all' => __('Collapse All', 'wedocs'), + ], + ] + ); + + $this->end_controls_section(); + + // Style Section - Container + $this->start_controls_section( + 'style_container', + [ + 'label' => __('Container', 'wedocs'), + 'tab' => Controls_Manager::TAB_STYLE, + ] + ); + + $this->add_control( + 'bg_color', + [ + 'label' => __('Background Color', 'wedocs'), + 'type' => Controls_Manager::COLOR, + 'default' => '', + 'selectors' => [ + '{{WRAPPER}} .wedocs-el-sidebar' => 'background-color: {{VALUE}};', + ], + ] + ); + + $this->add_responsive_control( + 'container_padding', + [ + 'label' => __('Padding', 'wedocs'), + 'type' => Controls_Manager::DIMENSIONS, + 'size_units' => ['px', '%', 'em'], + 'selectors' => [ + '{{WRAPPER}} .wedocs-el-sidebar' => 'padding: {{TOP}}{{UNIT}} {{RIGHT}}{{UNIT}} {{BOTTOM}}{{UNIT}} {{LEFT}}{{UNIT}};', + ], + ] + ); + + $this->add_group_control( + Group_Control_Border::get_type(), + [ + 'name' => 'container_border', + 'selector' => '{{WRAPPER}} .wedocs-el-sidebar', + ] + ); + + $this->add_responsive_control( + 'container_border_radius', + [ + 'label' => __('Border Radius', 'wedocs'), + 'type' => Controls_Manager::DIMENSIONS, + 'size_units' => ['px', '%'], + 'selectors' => [ + '{{WRAPPER}} .wedocs-el-sidebar' => 'border-radius: {{TOP}}{{UNIT}} {{RIGHT}}{{UNIT}} {{BOTTOM}}{{UNIT}} {{LEFT}}{{UNIT}};', + ], + ] + ); + + $this->add_group_control( + Group_Control_Box_Shadow::get_type(), + [ + 'name' => 'container_shadow', + 'selector' => '{{WRAPPER}} .wedocs-el-sidebar', + ] + ); + + $this->end_controls_section(); + + // Style Section - Title + $this->start_controls_section( + 'style_title', + [ + 'label' => __('Doc Title', 'wedocs'), + 'tab' => Controls_Manager::TAB_STYLE, + 'condition' => ['show_title' => 'yes'], + ] + ); + + $this->add_control( + 'title_color', + [ + 'label' => __('Color', 'wedocs'), + 'type' => Controls_Manager::COLOR, + 'default' => '#1e293b', + 'selectors' => [ + '{{WRAPPER}} .wedocs-el-sidebar__title' => 'color: {{VALUE}};', + ], + ] + ); + + $this->add_group_control( + Group_Control_Typography::get_type(), + [ + 'name' => 'title_typography', + 'selector' => '{{WRAPPER}} .wedocs-el-sidebar__title', + ] + ); + + $this->add_responsive_control( + 'title_margin', + [ + 'label' => __('Margin', 'wedocs'), + 'type' => Controls_Manager::DIMENSIONS, + 'size_units' => ['px', 'em'], + 'default' => ['top' => 0, 'right' => 0, 'bottom' => 15, 'left' => 0, 'unit' => 'px'], + 'selectors' => [ + '{{WRAPPER}} .wedocs-el-sidebar__title' => 'margin: {{TOP}}{{UNIT}} {{RIGHT}}{{UNIT}} {{BOTTOM}}{{UNIT}} {{LEFT}}{{UNIT}};', + ], + ] + ); + + $this->end_controls_section(); + + // Style Section - Search + $this->start_controls_section( + 'style_search', + [ + 'label' => __('Quick Search', 'wedocs'), + 'tab' => Controls_Manager::TAB_STYLE, + 'condition' => ['show_search' => 'yes'], + ] + ); + + $this->add_control( + 'search_bg', + [ + 'label' => __('Background Color', 'wedocs'), + 'type' => Controls_Manager::COLOR, + 'default' => '#f8fafc', + 'selectors' => [ + '{{WRAPPER}} .wedocs-el-sidebar__search' => 'background-color: {{VALUE}};', + ], + ] + ); + + $this->add_control( + 'search_text_color', + [ + 'label' => __('Text Color', 'wedocs'), + 'type' => Controls_Manager::COLOR, + 'default' => '#64748b', + 'selectors' => [ + '{{WRAPPER}} .wedocs-el-sidebar__search input' => 'color: {{VALUE}};', + ], + ] + ); + + $this->add_control( + 'search_placeholder_color', + [ + 'label' => __('Placeholder Color', 'wedocs'), + 'type' => Controls_Manager::COLOR, + 'default' => '#94a3b8', + 'selectors' => [ + '{{WRAPPER}} .wedocs-el-sidebar__search input::placeholder' => 'color: {{VALUE}};', + ], + ] + ); + + $this->add_control( + 'search_icon_color', + [ + 'label' => __('Icon Color', 'wedocs'), + 'type' => Controls_Manager::COLOR, + 'default' => '#95a4b9', + 'selectors' => [ + '{{WRAPPER}} .wedocs-el-sidebar__search svg' => 'fill: {{VALUE}};', + '{{WRAPPER}} .wedocs-el-sidebar__search svg path' => 'fill: {{VALUE}};', + ], + ] + ); + + $this->add_group_control( + Group_Control_Border::get_type(), + [ + 'name' => 'search_border', + 'selector' => '{{WRAPPER}} .wedocs-el-sidebar__search', + 'fields_options' => [ + 'border' => ['default' => 'solid'], + 'width' => ['default' => ['top' => 1, 'right' => 1, 'bottom' => 1, 'left' => 1]], + 'color' => ['default' => '#e2e8f0'], + ], + ] + ); + + $this->add_responsive_control( + 'search_border_radius', + [ + 'label' => __('Border Radius', 'wedocs'), + 'type' => Controls_Manager::DIMENSIONS, + 'size_units' => ['px', '%'], + 'default' => ['top' => 6, 'right' => 6, 'bottom' => 6, 'left' => 6, 'unit' => 'px'], + 'selectors' => [ + '{{WRAPPER}} .wedocs-el-sidebar__search' => 'border-radius: {{TOP}}{{UNIT}} {{RIGHT}}{{UNIT}} {{BOTTOM}}{{UNIT}} {{LEFT}}{{UNIT}};', + ], + ] + ); + + $this->add_responsive_control( + 'search_padding', + [ + 'label' => __('Padding', 'wedocs'), + 'type' => Controls_Manager::DIMENSIONS, + 'size_units' => ['px', 'em'], + 'default' => ['top' => 10, 'right' => 14, 'bottom' => 10, 'left' => 14, 'unit' => 'px'], + 'selectors' => [ + '{{WRAPPER}} .wedocs-el-sidebar__search' => 'padding: {{TOP}}{{UNIT}} {{RIGHT}}{{UNIT}} {{BOTTOM}}{{UNIT}} {{LEFT}}{{UNIT}};', + ], + ] + ); + + $this->add_control( + 'shortcut_bg', + [ + 'label' => __('Shortcut Badge Background', 'wedocs'), + 'type' => Controls_Manager::COLOR, + 'default' => '#e2e8f0', + 'selectors' => [ + '{{WRAPPER}} .wedocs-el-sidebar__search .short-key' => 'background-color: {{VALUE}};', + ], + 'condition' => ['show_shortcut' => 'yes'], + ] + ); + + $this->end_controls_section(); + + // Style Section - Navigation Items + $this->start_controls_section( + 'style_nav', + [ + 'label' => __('Navigation Items', 'wedocs'), + 'tab' => Controls_Manager::TAB_STYLE, + ] + ); + + $this->add_control( + 'link_color', + [ + 'label' => __('Link Color', 'wedocs'), + 'type' => Controls_Manager::COLOR, + 'default' => '#475569', + 'selectors' => [ + '{{WRAPPER}} .wedocs-el-sidebar .doc-nav-list a' => 'color: {{VALUE}};', + ], + ] + ); + + $this->add_control( + 'link_hover_color', + [ + 'label' => __('Hover Color', 'wedocs'), + 'type' => Controls_Manager::COLOR, + 'default' => '#0073aa', + 'selectors' => [ + '{{WRAPPER}} .wedocs-el-sidebar .doc-nav-list a:hover' => 'color: {{VALUE}};', + ], + ] + ); + + $this->add_control( + 'active_color', + [ + 'label' => __('Active Item Color', 'wedocs'), + 'type' => Controls_Manager::COLOR, + 'default' => '#0073aa', + 'selectors' => [ + '{{WRAPPER}} .wedocs-el-sidebar .doc-nav-list .current_page_item > a' => 'color: {{VALUE}};', + ], + ] + ); + + $this->add_control( + 'active_bg_color', + [ + 'label' => __('Active Item Background', 'wedocs'), + 'type' => Controls_Manager::COLOR, + 'default' => '', + 'selectors' => [ + '{{WRAPPER}} .wedocs-el-sidebar .doc-nav-list .current_page_item > a' => 'background-color: {{VALUE}};', + ], + ] + ); + + $this->add_control( + 'active_border_color', + [ + 'label' => __('Active Border Color', 'wedocs'), + 'type' => Controls_Manager::COLOR, + 'default' => '#0073aa', + 'selectors' => [ + '{{WRAPPER}} .wedocs-el-sidebar .doc-nav-list .current_page_item > a' => 'border-left-color: {{VALUE}};', + ], + ] + ); + + $this->add_group_control( + Group_Control_Typography::get_type(), + [ + 'name' => 'link_typography', + 'selector' => '{{WRAPPER}} .wedocs-el-sidebar .doc-nav-list a', + ] + ); + + $this->add_responsive_control( + 'item_padding', + [ + 'label' => __('Item Padding', 'wedocs'), + 'type' => Controls_Manager::DIMENSIONS, + 'size_units' => ['px', 'em'], + 'default' => ['top' => 8, 'right' => 12, 'bottom' => 8, 'left' => 12, 'unit' => 'px'], + 'selectors' => [ + '{{WRAPPER}} .wedocs-el-sidebar .doc-nav-list a' => 'padding: {{TOP}}{{UNIT}} {{RIGHT}}{{UNIT}} {{BOTTOM}}{{UNIT}} {{LEFT}}{{UNIT}};', + ], + ] + ); + + $this->add_responsive_control( + 'child_indent', + [ + 'label' => __('Sub-item Indent', 'wedocs'), + 'type' => Controls_Manager::SLIDER, + 'range' => ['px' => ['min' => 0, 'max' => 40]], + 'default' => ['size' => 16], + 'selectors' => [ + '{{WRAPPER}} .wedocs-el-sidebar .doc-nav-list .children' => 'padding-left: {{SIZE}}px;', + ], + ] + ); + + $this->add_control( + 'caret_color', + [ + 'label' => __('Caret/Arrow Color', 'wedocs'), + 'type' => Controls_Manager::COLOR, + 'default' => '#94a3b8', + 'selectors' => [ + '{{WRAPPER}} .wedocs-el-sidebar .wedocs-caret' => 'border-top-color: {{VALUE}};', + '{{WRAPPER}} .wedocs-el-sidebar .wd-state-closed > a .wedocs-caret' => 'border-left-color: {{VALUE}}; border-top-color: transparent;', + ], + ] + ); + + $this->add_control( + 'divider_color', + [ + 'label' => __('Divider Color', 'wedocs'), + 'type' => Controls_Manager::COLOR, + 'default' => '#f1f5f9', + 'selectors' => [ + '{{WRAPPER}} .wedocs-el-sidebar .doc-nav-list > li' => 'border-bottom-color: {{VALUE}};', + ], + ] + ); + + $this->add_control( + 'show_dividers', + [ + 'label' => __('Show Dividers', 'wedocs'), + 'type' => Controls_Manager::SWITCHER, + 'label_on' => __('Yes', 'wedocs'), + 'label_off' => __('No', 'wedocs'), + 'return_value' => 'yes', + 'default' => '', + ] + ); + + $this->end_controls_section(); + } + + protected function render() { + $settings = $this->get_settings_for_display(); + + $show_search = ($settings['show_search'] ?? 'yes') === 'yes'; + $show_shortcut = ($settings['show_shortcut'] ?? 'yes') === 'yes'; + $show_title = ($settings['show_title'] ?? 'yes') === 'yes'; + $search_placeholder = $settings['search_placeholder'] ?? __('Quick search...', 'wedocs'); + $collapse_behavior = $settings['collapse_behavior'] ?? 'expand_active'; + $show_dividers = ($settings['show_dividers'] ?? '') === 'yes'; + + global $post; + + // Determine the parent doc + $ancestors = []; + $parent = false; + + if (!empty($post->post_parent)) { + $ancestors = get_post_ancestors($post->ID); + $root = count($ancestors) - 1; + $parent = $ancestors[$root]; + } else { + $parent = !empty($post->ID) ? $post->ID : ''; + } + + if (!$parent) { + if (\Elementor\Plugin::$instance->editor->is_edit_mode()) { + echo '

' . __('Docs Sidebar: This widget displays the documentation navigation. Preview it on a single doc page.', 'wedocs') . '

'; + } + return; + } + + $walker = new \WeDevs\WeDocs\Walker(); + $children = wp_list_pages([ + 'title_li' => '', + 'order' => 'menu_order', + 'child_of' => $parent, + 'echo' => false, + 'post_type' => 'docs', + 'walker' => $walker, + ]); + + $sidebar_class = 'wedocs-el-sidebar'; + if ($collapse_behavior === 'expand_all') { + $sidebar_class .= ' wedocs-el-sidebar--expand-all'; + } elseif ($collapse_behavior === 'collapse_all') { + $sidebar_class .= ' wedocs-el-sidebar--collapse-all'; + } + ?> + +
+ +

+ +

+ + + + + + + + + +
+ + + + + + <# + var showSearch = settings.show_search === 'yes'; + var showShortcut = settings.show_shortcut === 'yes'; + var showTitle = settings.show_title === 'yes'; + var showDividers = settings.show_dividers === 'yes'; + #> + +
+ <# if (showTitle) { #> +

+ Sample Documentation +

+ <# } #> + + <# if (showSearch) { #> + + <# } #> + + +
+ start_controls_section( + 'trigger_section', + [ + 'label' => __('Trigger', 'wedocs'), + 'tab' => Controls_Manager::TAB_CONTENT, + ] + ); + + $this->add_control( + 'trigger_heading', + [ + 'label' => __('Heading', 'wedocs'), + 'type' => Controls_Manager::TEXT, + 'default' => __('Need More Help?', 'wedocs'), + ] + ); + + $this->add_control( + 'trigger_description', + [ + 'label' => __('Description', 'wedocs'), + 'type' => Controls_Manager::TEXTAREA, + 'default' => __("Can't find what you're looking for? Reach out to our support team.", 'wedocs'), + 'rows' => 3, + ] + ); + + $this->add_control( + 'trigger_icon', + [ + 'label' => __('Icon', 'wedocs'), + 'type' => Controls_Manager::ICONS, + 'default' => [ + 'value' => 'fas fa-headset', + 'library' => 'fa-solid', + ], + ] + ); + + $this->add_control( + 'button_text', + [ + 'label' => __('Button Text', 'wedocs'), + 'type' => Controls_Manager::TEXT, + 'default' => __('Contact Support', 'wedocs'), + ] + ); + + $this->add_control( + 'layout', + [ + 'label' => __('Layout', 'wedocs'), + 'type' => Controls_Manager::SELECT, + 'default' => 'card', + 'options' => [ + 'card' => __('Card', 'wedocs'), + 'inline' => __('Inline', 'wedocs'), + 'minimal' => __('Minimal (Button Only)', 'wedocs'), + ], + ] + ); + + $this->end_controls_section(); + + // Content Section - Modal + $this->start_controls_section( + 'modal_section', + [ + 'label' => __('Modal Content', 'wedocs'), + 'tab' => Controls_Manager::TAB_CONTENT, + ] + ); + + $this->add_control( + 'modal_title', + [ + 'label' => __('Modal Title', 'wedocs'), + 'type' => Controls_Manager::TEXT, + 'default' => __('Contact Support', 'wedocs'), + ] + ); + + $this->add_control( + 'modal_description', + [ + 'label' => __('Modal Description', 'wedocs'), + 'type' => Controls_Manager::TEXTAREA, + 'default' => __('Fill out the form below and our team will get back to you as soon as possible.', 'wedocs'), + 'rows' => 2, + ] + ); + + $this->add_control( + 'show_name_field', + [ + 'label' => __('Show Name Field', 'wedocs'), + 'type' => Controls_Manager::SWITCHER, + 'return_value' => 'yes', + 'default' => 'yes', + ] + ); + + $this->add_control( + 'show_email_field', + [ + 'label' => __('Show Email Field', 'wedocs'), + 'type' => Controls_Manager::SWITCHER, + 'return_value' => 'yes', + 'default' => 'yes', + ] + ); + + $this->add_control( + 'show_subject_field', + [ + 'label' => __('Show Subject Field', 'wedocs'), + 'type' => Controls_Manager::SWITCHER, + 'return_value' => 'yes', + 'default' => 'yes', + ] + ); + + $this->add_control( + 'submit_text', + [ + 'label' => __('Submit Button Text', 'wedocs'), + 'type' => Controls_Manager::TEXT, + 'default' => __('Send Message', 'wedocs'), + ] + ); + + $this->add_control( + 'success_message', + [ + 'label' => __('Success Message', 'wedocs'), + 'type' => Controls_Manager::TEXT, + 'default' => __('Thank you! Your message has been sent successfully.', 'wedocs'), + ] + ); + + $this->add_control( + 'recipient_email', + [ + 'label' => __('Recipient Email', 'wedocs'), + 'type' => Controls_Manager::TEXT, + 'default' => get_option('admin_email'), + 'description' => __('Email address where form submissions will be sent', 'wedocs'), + ] + ); + + $this->add_control( + 'save_to_elementor', + [ + 'label' => __('Save to Elementor Submissions', 'wedocs'), + 'type' => Controls_Manager::SWITCHER, + 'label_on' => __('Yes', 'wedocs'), + 'label_off' => __('No', 'wedocs'), + 'return_value' => 'yes', + 'default' => '', + 'description' => __('Save form data to Elementor Pro submissions (requires Elementor Pro)', 'wedocs'), + 'separator' => 'before', + ] + ); + + $this->end_controls_section(); + + // Style Section - Card + $this->start_controls_section( + 'style_card', + [ + 'label' => __('Card / Trigger', 'wedocs'), + 'tab' => Controls_Manager::TAB_STYLE, + ] + ); + + $this->add_control( + 'card_bg_color', + [ + 'label' => __('Background Color', 'wedocs'), + 'type' => Controls_Manager::COLOR, + 'default' => '#f0f7ff', + 'selectors' => [ + '{{WRAPPER}} .wedocs-need-help__card' => 'background-color: {{VALUE}};', + ], + ] + ); + + $this->add_responsive_control( + 'card_padding', + [ + 'label' => __('Padding', 'wedocs'), + 'type' => Controls_Manager::DIMENSIONS, + 'size_units' => ['px', '%', 'em'], + 'default' => [ + 'top' => 25, + 'right' => 25, + 'bottom' => 25, + 'left' => 25, + 'unit' => 'px', + ], + 'selectors' => [ + '{{WRAPPER}} .wedocs-need-help__card' => 'padding: {{TOP}}{{UNIT}} {{RIGHT}}{{UNIT}} {{BOTTOM}}{{UNIT}} {{LEFT}}{{UNIT}};', + ], + ] + ); + + $this->add_group_control( + Group_Control_Border::get_type(), + [ + 'name' => 'card_border', + 'selector' => '{{WRAPPER}} .wedocs-need-help__card', + 'fields_options' => [ + 'border' => ['default' => 'solid'], + 'width' => ['default' => ['top' => 1, 'right' => 1, 'bottom' => 1, 'left' => 1]], + 'color' => ['default' => '#d0e3f7'], + ], + ] + ); + + $this->add_responsive_control( + 'card_border_radius', + [ + 'label' => __('Border Radius', 'wedocs'), + 'type' => Controls_Manager::DIMENSIONS, + 'size_units' => ['px', '%'], + 'default' => ['top' => 8, 'right' => 8, 'bottom' => 8, 'left' => 8, 'unit' => 'px'], + 'selectors' => [ + '{{WRAPPER}} .wedocs-need-help__card' => 'border-radius: {{TOP}}{{UNIT}} {{RIGHT}}{{UNIT}} {{BOTTOM}}{{UNIT}} {{LEFT}}{{UNIT}};', + ], + ] + ); + + $this->add_control( + 'heading_color', + [ + 'label' => __('Heading Color', 'wedocs'), + 'type' => Controls_Manager::COLOR, + 'default' => '#1a202c', + 'selectors' => [ + '{{WRAPPER}} .wedocs-need-help__heading' => 'color: {{VALUE}};', + ], + ] + ); + + $this->add_group_control( + Group_Control_Typography::get_type(), + [ + 'name' => 'heading_typography', + 'selector' => '{{WRAPPER}} .wedocs-need-help__heading', + ] + ); + + $this->add_control( + 'desc_color', + [ + 'label' => __('Description Color', 'wedocs'), + 'type' => Controls_Manager::COLOR, + 'default' => '#4a5568', + 'selectors' => [ + '{{WRAPPER}} .wedocs-need-help__desc' => 'color: {{VALUE}};', + ], + ] + ); + + $this->add_control( + 'icon_color', + [ + 'label' => __('Icon Color', 'wedocs'), + 'type' => Controls_Manager::COLOR, + 'default' => '#0073aa', + 'selectors' => [ + '{{WRAPPER}} .wedocs-need-help__icon' => 'color: {{VALUE}};', + '{{WRAPPER}} .wedocs-need-help__icon svg' => 'fill: {{VALUE}};', + ], + ] + ); + + $this->add_responsive_control( + 'icon_size', + [ + 'label' => __('Icon Size', 'wedocs'), + 'type' => Controls_Manager::SLIDER, + 'range' => ['px' => ['min' => 16, 'max' => 80]], + 'default' => ['size' => 40], + 'selectors' => [ + '{{WRAPPER}} .wedocs-need-help__icon i' => 'font-size: {{SIZE}}px;', + '{{WRAPPER}} .wedocs-need-help__icon svg' => 'width: {{SIZE}}px; height: {{SIZE}}px;', + ], + ] + ); + + $this->end_controls_section(); + + // Style Section - Button + $this->start_controls_section( + 'style_button', + [ + 'label' => __('Button', 'wedocs'), + 'tab' => Controls_Manager::TAB_STYLE, + ] + ); + + $this->add_control( + 'btn_bg_color', + [ + 'label' => __('Background Color', 'wedocs'), + 'type' => Controls_Manager::COLOR, + 'default' => '#0073aa', + 'selectors' => [ + '{{WRAPPER}} .wedocs-need-help__btn' => 'background-color: {{VALUE}};', + ], + ] + ); + + $this->add_control( + 'btn_text_color', + [ + 'label' => __('Text Color', 'wedocs'), + 'type' => Controls_Manager::COLOR, + 'default' => '#ffffff', + 'selectors' => [ + '{{WRAPPER}} .wedocs-need-help__btn' => 'color: {{VALUE}};', + ], + ] + ); + + $this->add_control( + 'btn_hover_bg_color', + [ + 'label' => __('Hover Background', 'wedocs'), + 'type' => Controls_Manager::COLOR, + 'default' => '#005177', + 'selectors' => [ + '{{WRAPPER}} .wedocs-need-help__btn:hover' => 'background-color: {{VALUE}};', + ], + ] + ); + + $this->add_responsive_control( + 'btn_padding', + [ + 'label' => __('Padding', 'wedocs'), + 'type' => Controls_Manager::DIMENSIONS, + 'size_units' => ['px', 'em'], + 'default' => ['top' => 12, 'right' => 24, 'bottom' => 12, 'left' => 24, 'unit' => 'px'], + 'selectors' => [ + '{{WRAPPER}} .wedocs-need-help__btn' => 'padding: {{TOP}}{{UNIT}} {{RIGHT}}{{UNIT}} {{BOTTOM}}{{UNIT}} {{LEFT}}{{UNIT}};', + ], + ] + ); + + $this->add_responsive_control( + 'btn_border_radius', + [ + 'label' => __('Border Radius', 'wedocs'), + 'type' => Controls_Manager::DIMENSIONS, + 'size_units' => ['px', '%'], + 'default' => ['top' => 6, 'right' => 6, 'bottom' => 6, 'left' => 6, 'unit' => 'px'], + 'selectors' => [ + '{{WRAPPER}} .wedocs-need-help__btn' => 'border-radius: {{TOP}}{{UNIT}} {{RIGHT}}{{UNIT}} {{BOTTOM}}{{UNIT}} {{LEFT}}{{UNIT}};', + ], + ] + ); + + $this->add_group_control( + Group_Control_Typography::get_type(), + [ + 'name' => 'btn_typography', + 'selector' => '{{WRAPPER}} .wedocs-need-help__btn', + ] + ); + + $this->end_controls_section(); + + // Style Section - Modal + $this->start_controls_section( + 'style_modal', + [ + 'label' => __('Modal', 'wedocs'), + 'tab' => Controls_Manager::TAB_STYLE, + ] + ); + + $this->add_control( + 'modal_bg_color', + [ + 'label' => __('Background Color', 'wedocs'), + 'type' => Controls_Manager::COLOR, + 'default' => '#ffffff', + 'selectors' => [ + '{{WRAPPER}} .wedocs-need-help__modal-content' => 'background-color: {{VALUE}};', + ], + ] + ); + + $this->add_control( + 'modal_overlay_color', + [ + 'label' => __('Overlay Color', 'wedocs'), + 'type' => Controls_Manager::COLOR, + 'default' => 'rgba(0,0,0,0.5)', + 'selectors' => [ + '{{WRAPPER}} .wedocs-need-help__modal' => 'background-color: {{VALUE}};', + ], + ] + ); + + $this->add_responsive_control( + 'modal_width', + [ + 'label' => __('Modal Width', 'wedocs'), + 'type' => Controls_Manager::SLIDER, + 'size_units' => ['px', '%'], + 'range' => [ + 'px' => ['min' => 300, 'max' => 800], + '%' => ['min' => 30, 'max' => 90], + ], + 'default' => ['size' => 500, 'unit' => 'px'], + 'selectors' => [ + '{{WRAPPER}} .wedocs-need-help__modal-content' => 'max-width: {{SIZE}}{{UNIT}};', + ], + ] + ); + + $this->add_responsive_control( + 'modal_border_radius', + [ + 'label' => __('Border Radius', 'wedocs'), + 'type' => Controls_Manager::DIMENSIONS, + 'size_units' => ['px', '%'], + 'default' => ['top' => 12, 'right' => 12, 'bottom' => 12, 'left' => 12, 'unit' => 'px'], + 'selectors' => [ + '{{WRAPPER}} .wedocs-need-help__modal-content' => 'border-radius: {{TOP}}{{UNIT}} {{RIGHT}}{{UNIT}} {{BOTTOM}}{{UNIT}} {{LEFT}}{{UNIT}};', + ], + ] + ); + + $this->add_group_control( + Group_Control_Box_Shadow::get_type(), + [ + 'name' => 'modal_shadow', + 'selector' => '{{WRAPPER}} .wedocs-need-help__modal-content', + ] + ); + + $this->end_controls_section(); + } + + protected function render() { + $settings = $this->get_settings_for_display(); + + $layout = $settings['layout'] ?? 'card'; + $show_name = ($settings['show_name_field'] ?? 'yes') === 'yes'; + $show_email = ($settings['show_email_field'] ?? 'yes') === 'yes'; + $show_subject = ($settings['show_subject_field'] ?? 'yes') === 'yes'; + $widget_id = $this->get_id(); + ?> + + +
+ +
+ 'true']); ?> +
+ + +
+

+ +

+ +
+ + +
+ + + + + + + + + + + + <# + var layout = settings.layout || 'card'; + #> + + <# if (layout !== 'minimal') { #> +
+ <# if (settings.trigger_icon && settings.trigger_icon.value) { #> +
+ <# var iconHTML = elementor.helpers.renderIcon(view, settings.trigger_icon, { 'aria-hidden': true }, 'i', 'object'); + if (iconHTML && iconHTML.rendered) { #> + {{{ iconHTML.value }}} + <# } else { #> + + <# } #> +
+ <# } #> + +
+

{{ settings.trigger_heading }}

+ <# if (settings.trigger_description) { #> +

{{ settings.trigger_description }}

+ <# } #> +
+ + +
+ <# } else { #> + + <# } #> + start_controls_section( + 'trigger_section', + [ + 'label' => __('Trigger', 'wedocs'), + 'tab' => Controls_Manager::TAB_CONTENT, + ] + ); + + $this->add_control( + 'trigger_type', + [ + 'label' => __('Trigger Type', 'wedocs'), + 'type' => Controls_Manager::SELECT, + 'default' => 'input', + 'options' => [ + 'input' => __('Search Input (like sidebar)', 'wedocs'), + 'button' => __('Button', 'wedocs'), + 'icon' => __('Icon Only', 'wedocs'), + ], + ] + ); + + $this->add_control( + 'placeholder', + [ + 'label' => __('Placeholder Text', 'wedocs'), + 'type' => Controls_Manager::TEXT, + 'default' => __('Search documentation...', 'wedocs'), + ] + ); + + $this->add_control( + 'button_text', + [ + 'label' => __('Button Text', 'wedocs'), + 'type' => Controls_Manager::TEXT, + 'default' => __('Search Docs', 'wedocs'), + 'condition' => ['trigger_type' => 'button'], + ] + ); + + $this->add_control( + 'show_shortcut', + [ + 'label' => __('Show ⌘K Shortcut', 'wedocs'), + 'type' => Controls_Manager::SWITCHER, + 'return_value' => 'yes', + 'default' => 'yes', + ] + ); + + $this->add_control( + 'trigger_icon', + [ + 'label' => __('Search Icon', 'wedocs'), + 'type' => Controls_Manager::ICONS, + 'default' => [ + 'value' => 'fas fa-search', + 'library' => 'fa-solid', + ], + ] + ); + + $this->add_control( + 'alignment', + [ + 'label' => __('Alignment', 'wedocs'), + 'type' => Controls_Manager::CHOOSE, + 'options' => [ + 'left' => ['title' => __('Left', 'wedocs'), 'icon' => 'eicon-text-align-left'], + 'center' => ['title' => __('Center', 'wedocs'), 'icon' => 'eicon-text-align-center'], + 'right' => ['title' => __('Right', 'wedocs'), 'icon' => 'eicon-text-align-right'], + ], + 'default' => 'left', + 'selectors' => [ + '{{WRAPPER}} .wedocs-search-modal-trigger-wrap' => 'text-align: {{VALUE}};', + ], + ] + ); + + $this->end_controls_section(); + + // Content Section - Modal + $this->start_controls_section( + 'modal_section', + [ + 'label' => __('Modal', 'wedocs'), + 'tab' => Controls_Manager::TAB_CONTENT, + ] + ); + + $this->add_control( + 'modal_placeholder', + [ + 'label' => __('Modal Search Placeholder', 'wedocs'), + 'type' => Controls_Manager::TEXT, + 'default' => __('Search documentation', 'wedocs'), + ] + ); + + $this->add_control( + 'empty_message', + [ + 'label' => __('No Results Message', 'wedocs'), + 'type' => Controls_Manager::TEXT, + 'default' => __("Your search didn't match any documents", 'wedocs'), + ] + ); + + $this->add_control( + 'blank_message', + [ + 'label' => __('Blank Search Message', 'wedocs'), + 'type' => Controls_Manager::TEXT, + 'default' => __('Search field cannot be blank', 'wedocs'), + ] + ); + + $this->end_controls_section(); + + // Style Section - Trigger + $this->start_controls_section( + 'style_trigger', + [ + 'label' => __('Trigger', 'wedocs'), + 'tab' => Controls_Manager::TAB_STYLE, + ] + ); + + $this->add_control( + 'trigger_bg', + [ + 'label' => __('Background Color', 'wedocs'), + 'type' => Controls_Manager::COLOR, + 'default' => '#f8fafc', + 'selectors' => [ + '{{WRAPPER}} .wedocs-search-modal-trigger' => 'background-color: {{VALUE}};', + ], + ] + ); + + $this->add_control( + 'trigger_text_color', + [ + 'label' => __('Text Color', 'wedocs'), + 'type' => Controls_Manager::COLOR, + 'default' => '#94a3b8', + 'selectors' => [ + '{{WRAPPER}} .wedocs-search-modal-trigger' => 'color: {{VALUE}};', + ], + ] + ); + + $this->add_control( + 'trigger_icon_color', + [ + 'label' => __('Icon Color', 'wedocs'), + 'type' => Controls_Manager::COLOR, + 'default' => '#95a4b9', + 'selectors' => [ + '{{WRAPPER}} .wedocs-search-modal-trigger__icon' => 'color: {{VALUE}};', + '{{WRAPPER}} .wedocs-search-modal-trigger__icon svg' => 'fill: {{VALUE}};', + ], + ] + ); + + $this->add_control( + 'trigger_hover_bg', + [ + 'label' => __('Hover Background', 'wedocs'), + 'type' => Controls_Manager::COLOR, + 'default' => '#f1f5f9', + 'selectors' => [ + '{{WRAPPER}} .wedocs-search-modal-trigger:hover' => 'background-color: {{VALUE}};', + ], + ] + ); + + $this->add_control( + 'trigger_hover_border_color', + [ + 'label' => __('Hover Border Color', 'wedocs'), + 'type' => Controls_Manager::COLOR, + 'default' => '#cbd5e1', + 'selectors' => [ + '{{WRAPPER}} .wedocs-search-modal-trigger:hover' => 'border-color: {{VALUE}};', + ], + ] + ); + + $this->add_group_control( + Group_Control_Border::get_type(), + [ + 'name' => 'trigger_border', + 'selector' => '{{WRAPPER}} .wedocs-search-modal-trigger', + 'fields_options' => [ + 'border' => ['default' => 'solid'], + 'width' => ['default' => ['top' => 1, 'right' => 1, 'bottom' => 1, 'left' => 1]], + 'color' => ['default' => '#e2e8f0'], + ], + ] + ); + + $this->add_responsive_control( + 'trigger_border_radius', + [ + 'label' => __('Border Radius', 'wedocs'), + 'type' => Controls_Manager::DIMENSIONS, + 'size_units' => ['px', '%'], + 'default' => ['top' => 8, 'right' => 8, 'bottom' => 8, 'left' => 8, 'unit' => 'px'], + 'selectors' => [ + '{{WRAPPER}} .wedocs-search-modal-trigger' => 'border-radius: {{TOP}}{{UNIT}} {{RIGHT}}{{UNIT}} {{BOTTOM}}{{UNIT}} {{LEFT}}{{UNIT}};', + ], + ] + ); + + $this->add_responsive_control( + 'trigger_padding', + [ + 'label' => __('Padding', 'wedocs'), + 'type' => Controls_Manager::DIMENSIONS, + 'size_units' => ['px', 'em'], + 'default' => ['top' => 12, 'right' => 16, 'bottom' => 12, 'left' => 16, 'unit' => 'px'], + 'selectors' => [ + '{{WRAPPER}} .wedocs-search-modal-trigger' => 'padding: {{TOP}}{{UNIT}} {{RIGHT}}{{UNIT}} {{BOTTOM}}{{UNIT}} {{LEFT}}{{UNIT}};', + ], + ] + ); + + $this->add_group_control( + Group_Control_Box_Shadow::get_type(), + [ + 'name' => 'trigger_shadow', + 'selector' => '{{WRAPPER}} .wedocs-search-modal-trigger', + ] + ); + + $this->add_group_control( + Group_Control_Typography::get_type(), + [ + 'name' => 'trigger_typography', + 'selector' => '{{WRAPPER}} .wedocs-search-modal-trigger', + ] + ); + + $this->add_responsive_control( + 'trigger_width', + [ + 'label' => __('Width', 'wedocs'), + 'type' => Controls_Manager::SLIDER, + 'size_units' => ['px', '%'], + 'range' => [ + 'px' => ['min' => 100, 'max' => 800], + '%' => ['min' => 10, 'max' => 100], + ], + 'default' => ['size' => 100, 'unit' => '%'], + 'selectors' => [ + '{{WRAPPER}} .wedocs-search-modal-trigger' => 'width: {{SIZE}}{{UNIT}};', + ], + 'condition' => ['trigger_type' => 'input'], + ] + ); + + $this->add_control( + 'shortcut_bg', + [ + 'label' => __('Shortcut Badge Background', 'wedocs'), + 'type' => Controls_Manager::COLOR, + 'default' => '#e2e8f0', + 'selectors' => [ + '{{WRAPPER}} .wedocs-search-modal-trigger__shortcut' => 'background-color: {{VALUE}};', + ], + 'condition' => ['show_shortcut' => 'yes'], + ] + ); + + $this->add_control( + 'shortcut_text_color', + [ + 'label' => __('Shortcut Badge Text', 'wedocs'), + 'type' => Controls_Manager::COLOR, + 'default' => '#64748b', + 'selectors' => [ + '{{WRAPPER}} .wedocs-search-modal-trigger__shortcut' => 'color: {{VALUE}};', + ], + 'condition' => ['show_shortcut' => 'yes'], + ] + ); + + $this->end_controls_section(); + + // Style Section - Modal + $this->start_controls_section( + 'style_modal', + [ + 'label' => __('Modal', 'wedocs'), + 'tab' => Controls_Manager::TAB_STYLE, + ] + ); + + $this->add_control( + 'modal_overlay_color', + [ + 'label' => __('Overlay Color', 'wedocs'), + 'type' => Controls_Manager::COLOR, + 'default' => 'rgba(15, 23, 42, 0.6)', + ] + ); + + $this->add_control( + 'modal_bg', + [ + 'label' => __('Modal Background', 'wedocs'), + 'type' => Controls_Manager::COLOR, + 'default' => '#ffffff', + ] + ); + + $this->add_responsive_control( + 'modal_width', + [ + 'label' => __('Modal Width', 'wedocs'), + 'type' => Controls_Manager::SLIDER, + 'size_units' => ['px', '%'], + 'range' => [ + 'px' => ['min' => 400, 'max' => 900], + '%' => ['min' => 30, 'max' => 90], + ], + 'default' => ['size' => 620, 'unit' => 'px'], + ] + ); + + $this->add_responsive_control( + 'modal_border_radius', + [ + 'label' => __('Modal Border Radius', 'wedocs'), + 'type' => Controls_Manager::DIMENSIONS, + 'size_units' => ['px'], + 'default' => ['top' => 12, 'right' => 12, 'bottom' => 12, 'left' => 12, 'unit' => 'px'], + ] + ); + + $this->add_control( + 'result_hover_color', + [ + 'label' => __('Result Hover Background', 'wedocs'), + 'type' => Controls_Manager::COLOR, + 'default' => '#3B82F6', + ] + ); + + $this->add_control( + 'result_icon_bg', + [ + 'label' => __('Result Icon Background', 'wedocs'), + 'type' => Controls_Manager::COLOR, + 'default' => '#D9EBFF', + ] + ); + + $this->add_control( + 'result_icon_color', + [ + 'label' => __('Result Icon Color', 'wedocs'), + 'type' => Controls_Manager::COLOR, + 'default' => '#3B82F6', + ] + ); + + $this->end_controls_section(); + } + + protected function render() { + $settings = $this->get_settings_for_display(); + + $trigger_type = $settings['trigger_type'] ?? 'input'; + $show_shortcut = ($settings['show_shortcut'] ?? 'yes') === 'yes'; + $widget_id = $this->get_id(); + + $modal_overlay = $settings['modal_overlay_color'] ?? 'rgba(15, 23, 42, 0.6)'; + $modal_bg = $settings['modal_bg'] ?? '#ffffff'; + $modal_width = ($settings['modal_width']['size'] ?? 620) . ($settings['modal_width']['unit'] ?? 'px'); + $modal_radius_top = $settings['modal_border_radius']['top'] ?? 12; + $modal_radius_right = $settings['modal_border_radius']['right'] ?? 12; + $modal_radius_bottom = $settings['modal_border_radius']['bottom'] ?? 12; + $modal_radius_left = $settings['modal_border_radius']['left'] ?? 12; + $modal_radius_unit = $settings['modal_border_radius']['unit'] ?? 'px'; + $modal_radius = "{$modal_radius_top}{$modal_radius_unit} {$modal_radius_right}{$modal_radius_unit} {$modal_radius_bottom}{$modal_radius_unit} {$modal_radius_left}{$modal_radius_unit}"; + + $result_hover = $settings['result_hover_color'] ?? '#3B82F6'; + $result_icon_bg = $settings['result_icon_bg'] ?? '#D9EBFF'; + $result_icon_color = $settings['result_icon_color'] ?? '#3B82F6'; + ?> + +
+ +
+ + + 'true']); ?> + + + + + + + ⌘K + +
+ + + + + + + +
+ + + + + + + + + <# + var triggerType = settings.trigger_type || 'input'; + var showShortcut = settings.show_shortcut === 'yes'; + #> + +
+ <# if (triggerType === 'input') { #> +
+ + <# if (settings.trigger_icon && settings.trigger_icon.value) { + var iconHTML = elementor.helpers.renderIcon(view, settings.trigger_icon, { 'aria-hidden': true }, 'i', 'object'); + if (iconHTML && iconHTML.rendered) { #> + {{{ iconHTML.value }}} + <# } else { #> + + <# } + } else { #> + + <# } #> + + {{ settings.placeholder || 'Search documentation...' }} + <# if (showShortcut) { #> + ⌘K + <# } #> +
+ + <# } else if (triggerType === 'button') { #> + + + <# } else { #> + + <# } #> +
+ start_controls_section( + 'content_section', + [ + 'label' => __('Content', 'wedocs'), + 'tab' => Controls_Manager::TAB_CONTENT, + ] + ); + + $this->add_control( + 'title', + [ + 'label' => __('Title', 'wedocs'), + 'type' => Controls_Manager::TEXT, + 'default' => __('On This Page', 'wedocs'), + ] + ); + + $this->add_control( + 'title_tag', + [ + 'label' => __('Title HTML Tag', 'wedocs'), + 'type' => Controls_Manager::SELECT, + 'default' => 'h3', + 'options' => [ + 'h2' => 'H2', + 'h3' => 'H3', + 'h4' => 'H4', + 'h5' => 'H5', + 'div' => 'DIV', + 'span' => 'SPAN', + ], + ] + ); + + $this->add_control( + 'heading_levels', + [ + 'label' => __('Heading Levels', 'wedocs'), + 'type' => Controls_Manager::SELECT2, + 'multiple' => true, + 'default' => ['2', '3'], + 'options' => [ + '2' => 'H2', + '3' => 'H3', + '4' => 'H4', + '5' => 'H5', + '6' => 'H6', + ], + 'description' => __('Select which heading levels to include', 'wedocs'), + ] + ); + + $this->add_control( + 'collapsible', + [ + 'label' => __('Collapsible', 'wedocs'), + 'type' => Controls_Manager::SWITCHER, + 'label_on' => __('Yes', 'wedocs'), + 'label_off' => __('No', 'wedocs'), + 'return_value' => 'yes', + 'default' => '', + ] + ); + + $this->add_control( + 'collapsed_default', + [ + 'label' => __('Collapsed by Default', 'wedocs'), + 'type' => Controls_Manager::SWITCHER, + 'label_on' => __('Yes', 'wedocs'), + 'label_off' => __('No', 'wedocs'), + 'return_value' => 'yes', + 'default' => '', + 'condition' => [ + 'collapsible' => 'yes', + ], + ] + ); + + $this->add_control( + 'sticky', + [ + 'label' => __('Sticky Position', 'wedocs'), + 'type' => Controls_Manager::SWITCHER, + 'label_on' => __('Yes', 'wedocs'), + 'label_off' => __('No', 'wedocs'), + 'return_value' => 'yes', + 'default' => '', + 'description' => __('Make TOC sticky when scrolling', 'wedocs'), + ] + ); + + $this->add_control( + 'sticky_offset', + [ + 'label' => __('Sticky Offset (px)', 'wedocs'), + 'type' => Controls_Manager::SLIDER, + 'range' => [ + 'px' => [ + 'min' => 0, + 'max' => 200, + ], + ], + 'default' => [ + 'size' => 20, + ], + 'condition' => [ + 'sticky' => 'yes', + ], + ] + ); + + $this->add_control( + 'show_numbers', + [ + 'label' => __('Show Numbers', 'wedocs'), + 'type' => Controls_Manager::SWITCHER, + 'label_on' => __('Yes', 'wedocs'), + 'label_off' => __('No', 'wedocs'), + 'return_value' => 'yes', + 'default' => '', + ] + ); + + $this->add_control( + 'smooth_scroll', + [ + 'label' => __('Smooth Scroll', 'wedocs'), + 'type' => Controls_Manager::SWITCHER, + 'label_on' => __('Yes', 'wedocs'), + 'label_off' => __('No', 'wedocs'), + 'return_value' => 'yes', + 'default' => 'yes', + ] + ); + + $this->add_control( + 'highlight_active', + [ + 'label' => __('Highlight Active Section', 'wedocs'), + 'type' => Controls_Manager::SWITCHER, + 'label_on' => __('Yes', 'wedocs'), + 'label_off' => __('No', 'wedocs'), + 'return_value' => 'yes', + 'default' => 'yes', + ] + ); + + $this->end_controls_section(); + + // Style Section - Container + $this->start_controls_section( + 'style_container', + [ + 'label' => __('Container', 'wedocs'), + 'tab' => Controls_Manager::TAB_STYLE, + ] + ); + + $this->add_control( + 'bg_color', + [ + 'label' => __('Background Color', 'wedocs'), + 'type' => Controls_Manager::COLOR, + 'default' => '#f8f9fa', + 'selectors' => [ + '{{WRAPPER}} .wedocs-toc' => 'background-color: {{VALUE}};', + ], + ] + ); + + $this->add_responsive_control( + 'padding', + [ + 'label' => __('Padding', 'wedocs'), + 'type' => Controls_Manager::DIMENSIONS, + 'size_units' => ['px', '%', 'em'], + 'default' => [ + 'top' => 20, + 'right' => 20, + 'bottom' => 20, + 'left' => 20, + 'unit' => 'px', + ], + 'selectors' => [ + '{{WRAPPER}} .wedocs-toc' => 'padding: {{TOP}}{{UNIT}} {{RIGHT}}{{UNIT}} {{BOTTOM}}{{UNIT}} {{LEFT}}{{UNIT}};', + ], + ] + ); + + $this->add_group_control( + Group_Control_Border::get_type(), + [ + 'name' => 'container_border', + 'label' => __('Border', 'wedocs'), + 'selector' => '{{WRAPPER}} .wedocs-toc', + 'fields_options' => [ + 'border' => ['default' => 'solid'], + 'width' => ['default' => ['top' => 1, 'right' => 1, 'bottom' => 1, 'left' => 1]], + 'color' => ['default' => '#e2e8f0'], + ], + ] + ); + + $this->add_responsive_control( + 'border_radius', + [ + 'label' => __('Border Radius', 'wedocs'), + 'type' => Controls_Manager::DIMENSIONS, + 'size_units' => ['px', '%'], + 'default' => [ + 'top' => 8, + 'right' => 8, + 'bottom' => 8, + 'left' => 8, + 'unit' => 'px', + ], + 'selectors' => [ + '{{WRAPPER}} .wedocs-toc' => 'border-radius: {{TOP}}{{UNIT}} {{RIGHT}}{{UNIT}} {{BOTTOM}}{{UNIT}} {{LEFT}}{{UNIT}};', + ], + ] + ); + + $this->add_group_control( + Group_Control_Box_Shadow::get_type(), + [ + 'name' => 'container_shadow', + 'selector' => '{{WRAPPER}} .wedocs-toc', + ] + ); + + $this->end_controls_section(); + + // Style Section - Title + $this->start_controls_section( + 'style_title', + [ + 'label' => __('Title', 'wedocs'), + 'tab' => Controls_Manager::TAB_STYLE, + ] + ); + + $this->add_control( + 'title_color', + [ + 'label' => __('Color', 'wedocs'), + 'type' => Controls_Manager::COLOR, + 'default' => '#1a202c', + 'selectors' => [ + '{{WRAPPER}} .wedocs-toc__title' => 'color: {{VALUE}};', + ], + ] + ); + + $this->add_group_control( + Group_Control_Typography::get_type(), + [ + 'name' => 'title_typography', + 'selector' => '{{WRAPPER}} .wedocs-toc__title', + ] + ); + + $this->add_responsive_control( + 'title_margin', + [ + 'label' => __('Margin Bottom', 'wedocs'), + 'type' => Controls_Manager::SLIDER, + 'range' => [ + 'px' => ['min' => 0, 'max' => 50], + ], + 'default' => ['size' => 15], + 'selectors' => [ + '{{WRAPPER}} .wedocs-toc__title' => 'margin-bottom: {{SIZE}}px;', + ], + ] + ); + + $this->end_controls_section(); + + // Style Section - List Items + $this->start_controls_section( + 'style_items', + [ + 'label' => __('List Items', 'wedocs'), + 'tab' => Controls_Manager::TAB_STYLE, + ] + ); + + $this->add_control( + 'link_color', + [ + 'label' => __('Link Color', 'wedocs'), + 'type' => Controls_Manager::COLOR, + 'default' => '#4a5568', + 'selectors' => [ + '{{WRAPPER}} .wedocs-toc__link' => 'color: {{VALUE}};', + ], + ] + ); + + $this->add_control( + 'link_hover_color', + [ + 'label' => __('Link Hover Color', 'wedocs'), + 'type' => Controls_Manager::COLOR, + 'default' => '#0073aa', + 'selectors' => [ + '{{WRAPPER}} .wedocs-toc__link:hover' => 'color: {{VALUE}};', + ], + ] + ); + + $this->add_control( + 'active_color', + [ + 'label' => __('Active Color', 'wedocs'), + 'type' => Controls_Manager::COLOR, + 'default' => '#0073aa', + 'selectors' => [ + '{{WRAPPER}} .wedocs-toc__link.active' => 'color: {{VALUE}};', + ], + ] + ); + + $this->add_control( + 'active_border_color', + [ + 'label' => __('Active Border Color', 'wedocs'), + 'type' => Controls_Manager::COLOR, + 'default' => '#0073aa', + 'selectors' => [ + '{{WRAPPER}} .wedocs-toc__link.active' => 'border-left-color: {{VALUE}};', + ], + ] + ); + + $this->add_group_control( + Group_Control_Typography::get_type(), + [ + 'name' => 'link_typography', + 'selector' => '{{WRAPPER}} .wedocs-toc__link', + ] + ); + + $this->add_responsive_control( + 'item_spacing', + [ + 'label' => __('Item Spacing', 'wedocs'), + 'type' => Controls_Manager::SLIDER, + 'range' => [ + 'px' => ['min' => 0, 'max' => 30], + ], + 'default' => ['size' => 8], + 'selectors' => [ + '{{WRAPPER}} .wedocs-toc__item' => 'margin-bottom: {{SIZE}}px;', + ], + ] + ); + + $this->add_responsive_control( + 'indent', + [ + 'label' => __('Sub-item Indent', 'wedocs'), + 'type' => Controls_Manager::SLIDER, + 'range' => [ + 'px' => ['min' => 0, 'max' => 50], + ], + 'default' => ['size' => 16], + 'selectors' => [ + '{{WRAPPER}} .wedocs-toc__list .wedocs-toc__list' => 'padding-left: {{SIZE}}px;', + ], + ] + ); + + $this->end_controls_section(); + } + + protected function render() { + $settings = $this->get_settings_for_display(); + + $title = $settings['title'] ?? __('On This Page', 'wedocs'); + $title_tag = $settings['title_tag'] ?? 'h3'; + $heading_levels = $settings['heading_levels'] ?? ['2', '3']; + $collapsible = ($settings['collapsible'] ?? '') === 'yes'; + $collapsed_default = ($settings['collapsed_default'] ?? '') === 'yes'; + $sticky = ($settings['sticky'] ?? '') === 'yes'; + $sticky_offset = $settings['sticky_offset']['size'] ?? 20; + $show_numbers = ($settings['show_numbers'] ?? '') === 'yes'; + $smooth_scroll = ($settings['smooth_scroll'] ?? 'yes') === 'yes'; + $highlight_active = ($settings['highlight_active'] ?? 'yes') === 'yes'; + + $selector = implode(',', array_map(function ($level) { + return 'h' . intval($level); + }, $heading_levels)); + + // Build heading regex pattern from selected levels + $level_pattern = implode('|', array_map('intval', $heading_levels)); + + // Extract headings from the current post content (server-side) + $headings = []; + global $post; + if (!empty($post->post_content)) { + $content = apply_filters('the_content', $post->post_content); + if (preg_match_all('/]*(?:\s+id=["\']([^"\']*)["\'])?[^>]*>(.*?)<\/h\1>/si', $content, $matches, PREG_SET_ORDER)) { + $counter = 0; + foreach ($matches as $match) { + $counter++; + $level = intval($match[1]); + $id = !empty($match[2]) ? $match[2] : 'wedocs-heading-' . $counter; + $text = wp_strip_all_tags($match[3]); + if (!empty(trim($text))) { + $headings[] = [ + 'level' => $level, + 'id' => $id, + 'text' => $text, + 'index' => $counter, + ]; + } + } + } + } + + $wrapper_class = 'wedocs-toc'; + if ($sticky) { + $wrapper_class .= ' wedocs-toc--sticky'; + } + if ($collapsible) { + $wrapper_class .= ' wedocs-toc--collapsible'; + } + if ($collapsed_default) { + $wrapper_class .= ' wedocs-toc--collapsed'; + } + + // Determine minimum heading level for indentation + $min_level = !empty($headings) ? min(array_column($headings, 'level')) : 2; + ?> + +
style="position: sticky; top: px;"> + +
+ < class="wedocs-toc__title"> + + + + + > +
+ + +
+ + + + + + <# + var titleTag = settings.title_tag || 'h3'; + var collapsible = settings.collapsible === 'yes'; + var collapsed = settings.collapsed_default === 'yes'; + var sticky = settings.sticky === 'yes'; + var stickyOffset = settings.sticky_offset?.size || 20; + var showNumbers = settings.show_numbers === 'yes'; + + var wrapperClass = 'wedocs-toc'; + if (sticky) wrapperClass += ' wedocs-toc--sticky'; + if (collapsible) wrapperClass += ' wedocs-toc--collapsible'; + #> + +
style="position: sticky; top: {{ stickyOffset }}px;"<# } #>> +
+ <{{ titleTag }} class="wedocs-toc__title"> + {{ settings.title || 'On This Page' }} + <# if (collapsible) { #> + + <# } #> + +
+ + +
+ start_controls_section( + 'content_section', + [ + 'label' => __('Content', 'wedocs'), + 'tab' => Controls_Manager::TAB_CONTENT, + ] + ); + + $this->add_control( + 'question_text', + [ + 'label' => __('Question Text', 'wedocs'), + 'type' => Controls_Manager::TEXT, + 'default' => __('Was this article helpful?', 'wedocs'), + ] + ); + + $this->add_control( + 'style', + [ + 'label' => __('Style', 'wedocs'), + 'type' => Controls_Manager::SELECT, + 'default' => 'thumbs', + 'options' => [ + 'thumbs' => __('Thumbs Up/Down', 'wedocs'), + 'emoji' => __('Emoji Reactions', 'wedocs'), + 'yes_no' => __('Yes/No Buttons', 'wedocs'), + ], + ] + ); + + $this->add_control( + 'yes_text', + [ + 'label' => __('Positive Text', 'wedocs'), + 'type' => Controls_Manager::TEXT, + 'default' => __('Yes', 'wedocs'), + 'condition' => ['style' => 'yes_no'], + ] + ); + + $this->add_control( + 'no_text', + [ + 'label' => __('Negative Text', 'wedocs'), + 'type' => Controls_Manager::TEXT, + 'default' => __('No', 'wedocs'), + 'condition' => ['style' => 'yes_no'], + ] + ); + + $this->add_control( + 'show_count', + [ + 'label' => __('Show Vote Count', 'wedocs'), + 'type' => Controls_Manager::SWITCHER, + 'return_value' => 'yes', + 'default' => '', + ] + ); + + $this->add_control( + 'thank_you_message', + [ + 'label' => __('Thank You Message', 'wedocs'), + 'type' => Controls_Manager::TEXT, + 'default' => __('Thank you for your feedback!', 'wedocs'), + ] + ); + + $this->add_control( + 'negative_follow_up', + [ + 'label' => __('Negative Feedback Follow-up', 'wedocs'), + 'type' => Controls_Manager::SWITCHER, + 'return_value' => 'yes', + 'default' => '', + 'description' => __('Show a text field when negative feedback is given', 'wedocs'), + ] + ); + + $this->add_control( + 'follow_up_placeholder', + [ + 'label' => __('Follow-up Placeholder', 'wedocs'), + 'type' => Controls_Manager::TEXT, + 'default' => __('How can we improve this article?', 'wedocs'), + 'condition' => ['negative_follow_up' => 'yes'], + ] + ); + + $this->add_control( + 'alignment', + [ + 'label' => __('Alignment', 'wedocs'), + 'type' => Controls_Manager::CHOOSE, + 'options' => [ + 'left' => ['title' => __('Left', 'wedocs'), 'icon' => 'eicon-text-align-left'], + 'center' => ['title' => __('Center', 'wedocs'), 'icon' => 'eicon-text-align-center'], + 'right' => ['title' => __('Right', 'wedocs'), 'icon' => 'eicon-text-align-right'], + ], + 'default' => 'center', + 'selectors' => [ + '{{WRAPPER}} .wedocs-helpful' => 'text-align: {{VALUE}};', + ], + ] + ); + + $this->end_controls_section(); + + // Style Section - Container + $this->start_controls_section( + 'style_container', + [ + 'label' => __('Container', 'wedocs'), + 'tab' => Controls_Manager::TAB_STYLE, + ] + ); + + $this->add_control( + 'bg_color', + [ + 'label' => __('Background Color', 'wedocs'), + 'type' => Controls_Manager::COLOR, + 'default' => '#f8f9fa', + 'selectors' => [ + '{{WRAPPER}} .wedocs-helpful' => 'background-color: {{VALUE}};', + ], + ] + ); + + $this->add_responsive_control( + 'padding', + [ + 'label' => __('Padding', 'wedocs'), + 'type' => Controls_Manager::DIMENSIONS, + 'size_units' => ['px', '%', 'em'], + 'default' => ['top' => 20, 'right' => 25, 'bottom' => 20, 'left' => 25, 'unit' => 'px'], + 'selectors' => [ + '{{WRAPPER}} .wedocs-helpful' => 'padding: {{TOP}}{{UNIT}} {{RIGHT}}{{UNIT}} {{BOTTOM}}{{UNIT}} {{LEFT}}{{UNIT}};', + ], + ] + ); + + $this->add_group_control( + Group_Control_Border::get_type(), + [ + 'name' => 'container_border', + 'selector' => '{{WRAPPER}} .wedocs-helpful', + 'fields_options' => [ + 'border' => ['default' => 'solid'], + 'width' => ['default' => ['top' => 1, 'right' => 1, 'bottom' => 1, 'left' => 1]], + 'color' => ['default' => '#e2e8f0'], + ], + ] + ); + + $this->add_responsive_control( + 'border_radius', + [ + 'label' => __('Border Radius', 'wedocs'), + 'type' => Controls_Manager::DIMENSIONS, + 'size_units' => ['px', '%'], + 'default' => ['top' => 8, 'right' => 8, 'bottom' => 8, 'left' => 8, 'unit' => 'px'], + 'selectors' => [ + '{{WRAPPER}} .wedocs-helpful' => 'border-radius: {{TOP}}{{UNIT}} {{RIGHT}}{{UNIT}} {{BOTTOM}}{{UNIT}} {{LEFT}}{{UNIT}};', + ], + ] + ); + + $this->end_controls_section(); + + // Style Section - Question + $this->start_controls_section( + 'style_question', + [ + 'label' => __('Question Text', 'wedocs'), + 'tab' => Controls_Manager::TAB_STYLE, + ] + ); + + $this->add_control( + 'question_color', + [ + 'label' => __('Color', 'wedocs'), + 'type' => Controls_Manager::COLOR, + 'default' => '#1a202c', + 'selectors' => [ + '{{WRAPPER}} .wedocs-helpful__question' => 'color: {{VALUE}};', + ], + ] + ); + + $this->add_group_control( + Group_Control_Typography::get_type(), + [ + 'name' => 'question_typography', + 'selector' => '{{WRAPPER}} .wedocs-helpful__question', + ] + ); + + $this->end_controls_section(); + + // Style Section - Buttons + $this->start_controls_section( + 'style_buttons', + [ + 'label' => __('Vote Buttons', 'wedocs'), + 'tab' => Controls_Manager::TAB_STYLE, + ] + ); + + $this->add_control( + 'btn_color', + [ + 'label' => __('Button Color', 'wedocs'), + 'type' => Controls_Manager::COLOR, + 'default' => '#718096', + 'selectors' => [ + '{{WRAPPER}} .wedocs-helpful__btn' => 'color: {{VALUE}}; border-color: {{VALUE}};', + ], + ] + ); + + $this->add_control( + 'btn_hover_color', + [ + 'label' => __('Hover Color', 'wedocs'), + 'type' => Controls_Manager::COLOR, + 'default' => '#0073aa', + 'selectors' => [ + '{{WRAPPER}} .wedocs-helpful__btn:hover' => 'color: {{VALUE}}; border-color: {{VALUE}};', + ], + ] + ); + + $this->add_control( + 'btn_positive_active', + [ + 'label' => __('Positive Active Color', 'wedocs'), + 'type' => Controls_Manager::COLOR, + 'default' => '#10b981', + 'selectors' => [ + '{{WRAPPER}} .wedocs-helpful__btn--positive.active' => 'color: {{VALUE}}; border-color: {{VALUE}}; background-color: color-mix(in srgb, {{VALUE}} 10%, transparent);', + ], + ] + ); + + $this->add_control( + 'btn_negative_active', + [ + 'label' => __('Negative Active Color', 'wedocs'), + 'type' => Controls_Manager::COLOR, + 'default' => '#ef4444', + 'selectors' => [ + '{{WRAPPER}} .wedocs-helpful__btn--negative.active' => 'color: {{VALUE}}; border-color: {{VALUE}}; background-color: color-mix(in srgb, {{VALUE}} 10%, transparent);', + ], + ] + ); + + $this->add_responsive_control( + 'btn_size', + [ + 'label' => __('Button Size', 'wedocs'), + 'type' => Controls_Manager::SLIDER, + 'range' => ['px' => ['min' => 24, 'max' => 80]], + 'default' => ['size' => 44], + 'selectors' => [ + '{{WRAPPER}} .wedocs-helpful__btn' => 'width: {{SIZE}}px; height: {{SIZE}}px;', + '{{WRAPPER}} .wedocs-helpful__btn--text' => 'width: auto; height: auto;', + ], + ] + ); + + $this->add_responsive_control( + 'btn_icon_size', + [ + 'label' => __('Icon Size', 'wedocs'), + 'type' => Controls_Manager::SLIDER, + 'range' => ['px' => ['min' => 14, 'max' => 48]], + 'default' => ['size' => 22], + 'selectors' => [ + '{{WRAPPER}} .wedocs-helpful__btn svg' => 'width: {{SIZE}}px; height: {{SIZE}}px;', + '{{WRAPPER}} .wedocs-helpful__btn .wedocs-helpful__emoji' => 'font-size: {{SIZE}}px;', + ], + ] + ); + + $this->add_responsive_control( + 'btn_gap', + [ + 'label' => __('Button Spacing', 'wedocs'), + 'type' => Controls_Manager::SLIDER, + 'range' => ['px' => ['min' => 4, 'max' => 30]], + 'default' => ['size' => 10], + 'selectors' => [ + '{{WRAPPER}} .wedocs-helpful__actions' => 'gap: {{SIZE}}px;', + ], + ] + ); + + $this->end_controls_section(); + } + + protected function render() { + $settings = $this->get_settings_for_display(); + + $style = $settings['style'] ?? 'thumbs'; + $show_count = ($settings['show_count'] ?? '') === 'yes'; + $negative_follow_up = ($settings['negative_follow_up'] ?? '') === 'yes'; + $widget_id = $this->get_id(); + $post_id = get_the_ID(); + + // Get existing vote counts + $positive_count = (int) get_post_meta($post_id, '_wedocs_helpful_yes', true); + $negative_count = (int) get_post_meta($post_id, '_wedocs_helpful_no', true); + ?> + +
+ + +
+ + + + + + + + + + + + +
+ + + + + + +
+ + + + + + <# + var style = settings.style || 'thumbs'; + var showCount = settings.show_count === 'yes'; + #> + +
+ {{ settings.question_text }} + +
+ <# if (style === 'thumbs') { #> + + + <# } else if (style === 'emoji') { #> + + + <# } else if (style === 'yes_no') { #> + + + <# } #> +
+
+ Date: Wed, 18 Feb 2026 12:04:54 +0600 Subject: [PATCH 2/4] Add Elementor widgets: nav, breadcrumb, menu Register and include three new Elementor widgets (DocNavigation, DocsBreadcrumb, DocsHamburgerMenu) by updating includes/Elementor.php. Add full widget implementations for next/previous doc navigation, docs breadcrumb, and an off-canvas/hamburger docs menu including controls, rendering, editor preview templates and inline styles. Also adjust responsive styles in src/assets/less/responsive.less to support the new widgets. --- includes/Elementor.php | 6 + includes/Elementor/Widgets/DocNavigation.php | 577 ++++++++++++++ includes/Elementor/Widgets/DocsBreadcrumb.php | 508 ++++++++++++ .../Elementor/Widgets/DocsHamburgerMenu.php | 749 ++++++++++++++++++ src/assets/less/responsive.less | 73 ++ 5 files changed, 1913 insertions(+) create mode 100644 includes/Elementor/Widgets/DocNavigation.php create mode 100644 includes/Elementor/Widgets/DocsBreadcrumb.php create mode 100644 includes/Elementor/Widgets/DocsHamburgerMenu.php diff --git a/includes/Elementor.php b/includes/Elementor.php index a62fae37..d34b9c40 100644 --- a/includes/Elementor.php +++ b/includes/Elementor.php @@ -49,6 +49,9 @@ public function register_widgets() { require_once WEDOCS_PATH . '/includes/Elementor/Widgets/WasThisHelpful.php'; require_once WEDOCS_PATH . '/includes/Elementor/Widgets/DocsSidebar.php'; require_once WEDOCS_PATH . '/includes/Elementor/Widgets/SearchModal.php'; + require_once WEDOCS_PATH . '/includes/Elementor/Widgets/DocNavigation.php'; + require_once WEDOCS_PATH . '/includes/Elementor/Widgets/DocsHamburgerMenu.php'; + require_once WEDOCS_PATH . '/includes/Elementor/Widgets/DocsBreadcrumb.php'; // Register widgets // \Elementor\Plugin::instance()->widgets_manager->register( new \WeDevs\WeDocs\Elementor\Widgets\Search() ); @@ -58,6 +61,9 @@ public function register_widgets() { \Elementor\Plugin::instance()->widgets_manager->register( new \WeDevs\WeDocs\Elementor\Widgets\WasThisHelpful() ); \Elementor\Plugin::instance()->widgets_manager->register( new \WeDevs\WeDocs\Elementor\Widgets\DocsSidebar() ); \Elementor\Plugin::instance()->widgets_manager->register( new \WeDevs\WeDocs\Elementor\Widgets\SearchModal() ); + \Elementor\Plugin::instance()->widgets_manager->register( new \WeDevs\WeDocs\Elementor\Widgets\DocNavigation() ); + \Elementor\Plugin::instance()->widgets_manager->register( new \WeDevs\WeDocs\Elementor\Widgets\DocsHamburgerMenu() ); + \Elementor\Plugin::instance()->widgets_manager->register( new \WeDevs\WeDocs\Elementor\Widgets\DocsBreadcrumb() ); } /** diff --git a/includes/Elementor/Widgets/DocNavigation.php b/includes/Elementor/Widgets/DocNavigation.php new file mode 100644 index 00000000..7c4577a7 --- /dev/null +++ b/includes/Elementor/Widgets/DocNavigation.php @@ -0,0 +1,577 @@ +start_controls_section( + 'content_section', + [ + 'label' => __('Content', 'wedocs'), + 'tab' => Controls_Manager::TAB_CONTENT, + ] + ); + + $this->add_control( + 'show_prev', + [ + 'label' => __('Show Previous', 'wedocs'), + 'type' => Controls_Manager::SWITCHER, + 'label_on' => __('Yes', 'wedocs'), + 'label_off' => __('No', 'wedocs'), + 'return_value' => 'yes', + 'default' => 'yes', + ] + ); + + $this->add_control( + 'show_next', + [ + 'label' => __('Show Next', 'wedocs'), + 'type' => Controls_Manager::SWITCHER, + 'label_on' => __('Yes', 'wedocs'), + 'label_off' => __('No', 'wedocs'), + 'return_value' => 'yes', + 'default' => 'yes', + ] + ); + + $this->add_control( + 'prev_label', + [ + 'label' => __('Previous Label', 'wedocs'), + 'type' => Controls_Manager::TEXT, + 'default' => __('Previous', 'wedocs'), + 'condition' => ['show_prev' => 'yes'], + ] + ); + + $this->add_control( + 'next_label', + [ + 'label' => __('Next Label', 'wedocs'), + 'type' => Controls_Manager::TEXT, + 'default' => __('Next', 'wedocs'), + 'condition' => ['show_next' => 'yes'], + ] + ); + + $this->add_control( + 'show_arrows', + [ + 'label' => __('Show Arrows', 'wedocs'), + 'type' => Controls_Manager::SWITCHER, + 'label_on' => __('Yes', 'wedocs'), + 'label_off' => __('No', 'wedocs'), + 'return_value' => 'yes', + 'default' => 'yes', + ] + ); + + $this->add_control( + 'layout', + [ + 'label' => __('Layout', 'wedocs'), + 'type' => Controls_Manager::SELECT, + 'default' => 'side-by-side', + 'options' => [ + 'side-by-side' => __('Side by Side', 'wedocs'), + 'stacked' => __('Stacked', 'wedocs'), + ], + ] + ); + + $this->end_controls_section(); + + // Style Section - Container + $this->start_controls_section( + 'style_container', + [ + 'label' => __('Container', 'wedocs'), + 'tab' => Controls_Manager::TAB_STYLE, + ] + ); + + $this->add_control( + 'bg_color', + [ + 'label' => __('Background Color', 'wedocs'), + 'type' => Controls_Manager::COLOR, + 'default' => '', + 'selectors' => [ + '{{WRAPPER}} .wedocs-el-nav' => 'background-color: {{VALUE}};', + ], + ] + ); + + $this->add_responsive_control( + 'container_padding', + [ + 'label' => __('Padding', 'wedocs'), + 'type' => Controls_Manager::DIMENSIONS, + 'size_units' => ['px', '%', 'em'], + 'default' => ['top' => 20, 'right' => 0, 'bottom' => 20, 'left' => 0, 'unit' => 'px'], + 'selectors' => [ + '{{WRAPPER}} .wedocs-el-nav' => 'padding: {{TOP}}{{UNIT}} {{RIGHT}}{{UNIT}} {{BOTTOM}}{{UNIT}} {{LEFT}}{{UNIT}};', + ], + ] + ); + + $this->add_group_control( + Group_Control_Border::get_type(), + [ + 'name' => 'container_border', + 'selector' => '{{WRAPPER}} .wedocs-el-nav', + 'fields_options' => [ + 'border' => ['default' => 'solid'], + 'width' => ['default' => ['top' => 1, 'right' => 0, 'bottom' => 1, 'left' => 0]], + 'color' => ['default' => '#e2e8f0'], + ], + ] + ); + + $this->add_responsive_control( + 'container_border_radius', + [ + 'label' => __('Border Radius', 'wedocs'), + 'type' => Controls_Manager::DIMENSIONS, + 'size_units' => ['px', '%'], + 'selectors' => [ + '{{WRAPPER}} .wedocs-el-nav' => 'border-radius: {{TOP}}{{UNIT}} {{RIGHT}}{{UNIT}} {{BOTTOM}}{{UNIT}} {{LEFT}}{{UNIT}};', + ], + ] + ); + + $this->add_group_control( + Group_Control_Box_Shadow::get_type(), + [ + 'name' => 'container_shadow', + 'selector' => '{{WRAPPER}} .wedocs-el-nav', + ] + ); + + $this->end_controls_section(); + + // Style Section - Label + $this->start_controls_section( + 'style_label', + [ + 'label' => __('Label', 'wedocs'), + 'tab' => Controls_Manager::TAB_STYLE, + ] + ); + + $this->add_control( + 'label_color', + [ + 'label' => __('Color', 'wedocs'), + 'type' => Controls_Manager::COLOR, + 'default' => '#94a3b8', + 'selectors' => [ + '{{WRAPPER}} .wedocs-el-nav__label' => 'color: {{VALUE}};', + ], + ] + ); + + $this->add_group_control( + Group_Control_Typography::get_type(), + [ + 'name' => 'label_typography', + 'selector' => '{{WRAPPER}} .wedocs-el-nav__label', + ] + ); + + $this->end_controls_section(); + + // Style Section - Title + $this->start_controls_section( + 'style_title', + [ + 'label' => __('Doc Title', 'wedocs'), + 'tab' => Controls_Manager::TAB_STYLE, + ] + ); + + $this->add_control( + 'title_color', + [ + 'label' => __('Color', 'wedocs'), + 'type' => Controls_Manager::COLOR, + 'default' => '#1e293b', + 'selectors' => [ + '{{WRAPPER}} .wedocs-el-nav__title a' => 'color: {{VALUE}};', + ], + ] + ); + + $this->add_control( + 'title_hover_color', + [ + 'label' => __('Hover Color', 'wedocs'), + 'type' => Controls_Manager::COLOR, + 'default' => '#0073aa', + 'selectors' => [ + '{{WRAPPER}} .wedocs-el-nav__title a:hover' => 'color: {{VALUE}};', + ], + ] + ); + + $this->add_group_control( + Group_Control_Typography::get_type(), + [ + 'name' => 'title_typography', + 'selector' => '{{WRAPPER}} .wedocs-el-nav__title', + ] + ); + + $this->end_controls_section(); + + // Style Section - Arrow + $this->start_controls_section( + 'style_arrow', + [ + 'label' => __('Arrow', 'wedocs'), + 'tab' => Controls_Manager::TAB_STYLE, + 'condition' => ['show_arrows' => 'yes'], + ] + ); + + $this->add_control( + 'arrow_color', + [ + 'label' => __('Color', 'wedocs'), + 'type' => Controls_Manager::COLOR, + 'default' => '#94a3b8', + 'selectors' => [ + '{{WRAPPER}} .wedocs-el-nav__arrow' => 'color: {{VALUE}};', + ], + ] + ); + + $this->add_responsive_control( + 'arrow_size', + [ + 'label' => __('Size', 'wedocs'), + 'type' => Controls_Manager::SLIDER, + 'range' => ['px' => ['min' => 12, 'max' => 40]], + 'default' => ['size' => 20], + 'selectors' => [ + '{{WRAPPER}} .wedocs-el-nav__arrow svg' => 'width: {{SIZE}}px; height: {{SIZE}}px;', + ], + ] + ); + + $this->end_controls_section(); + + // Style Section - Separator + $this->start_controls_section( + 'style_separator', + [ + 'label' => __('Separator', 'wedocs'), + 'tab' => Controls_Manager::TAB_STYLE, + ] + ); + + $this->add_control( + 'separator_color', + [ + 'label' => __('Color', 'wedocs'), + 'type' => Controls_Manager::COLOR, + 'default' => '#e2e8f0', + 'selectors' => [ + '{{WRAPPER}} .wedocs-el-nav--side-by-side .wedocs-el-nav__separator' => 'background-color: {{VALUE}};', + '{{WRAPPER}} .wedocs-el-nav--stacked .wedocs-el-nav__item + .wedocs-el-nav__item' => 'border-top-color: {{VALUE}};', + ], + ] + ); + + $this->add_responsive_control( + 'separator_width', + [ + 'label' => __('Width', 'wedocs'), + 'type' => Controls_Manager::SLIDER, + 'range' => ['px' => ['min' => 0, 'max' => 5]], + 'default' => ['size' => 1], + 'selectors' => [ + '{{WRAPPER}} .wedocs-el-nav--side-by-side .wedocs-el-nav__separator' => 'width: {{SIZE}}px;', + '{{WRAPPER}} .wedocs-el-nav--stacked .wedocs-el-nav__item + .wedocs-el-nav__item' => 'border-top-width: {{SIZE}}px;', + ], + ] + ); + + $this->end_controls_section(); + } + + protected function render() { + $settings = $this->get_settings_for_display(); + + $show_prev = ($settings['show_prev'] ?? 'yes') === 'yes'; + $show_next = ($settings['show_next'] ?? 'yes') === 'yes'; + $prev_label = $settings['prev_label'] ?? __('Previous', 'wedocs'); + $next_label = $settings['next_label'] ?? __('Next', 'wedocs'); + $show_arrows = ($settings['show_arrows'] ?? 'yes') === 'yes'; + $layout = $settings['layout'] ?? 'side-by-side'; + + global $post, $wpdb; + + if (empty($post) || $post->post_type !== 'docs') { + if (\Elementor\Plugin::$instance->editor->is_edit_mode()) { + echo '

' . __('Doc Navigation: Preview it on a single doc page.', 'wedocs') . '

'; + } + return; + } + + $next_post_id = 0; + $prev_post_id = 0; + + if ($show_next) { + $next_query = "SELECT ID FROM {$wpdb->posts} + WHERE post_parent = {$post->post_parent} AND post_type = 'docs' AND post_status = 'publish' AND menu_order > {$post->menu_order} + ORDER BY menu_order ASC + LIMIT 0, 1"; + $next_post_id = (int) $wpdb->get_var($next_query); + } + + if ($show_prev) { + $prev_query = "SELECT ID FROM {$wpdb->posts} + WHERE post_parent = {$post->post_parent} AND post_type = 'docs' AND post_status = 'publish' AND menu_order < {$post->menu_order} + ORDER BY menu_order DESC + LIMIT 0, 1"; + $prev_post_id = (int) $wpdb->get_var($prev_query); + } + + if (!$next_post_id && !$prev_post_id) { + if (\Elementor\Plugin::$instance->editor->is_edit_mode()) { + echo '

' . __('Doc Navigation: No adjacent docs found.', 'wedocs') . '

'; + } + return; + } + + $nav_class = 'wedocs-el-nav wedocs-el-nav--' . $layout; + ?> + + + + + + <# + var showPrev = settings.show_prev === 'yes'; + var showNext = settings.show_next === 'yes'; + var showArrows = settings.show_arrows === 'yes'; + var layout = settings.layout || 'side-by-side'; + var prevLabel = settings.prev_label || 'Previous'; + var nextLabel = settings.next_label || 'Next'; + var arrowColor = settings.arrow_color || '#94a3b8'; + var labelColor = settings.label_color || '#94a3b8'; + var titleColor = settings.title_color || '#1e293b'; + var arrowSize = settings.arrow_size?.size || 20; + #> + + + start_controls_section( + 'content_section', + [ + 'label' => __('Content', 'wedocs'), + 'tab' => Controls_Manager::TAB_CONTENT, + ] + ); + + $this->add_control( + 'home_text', + [ + 'label' => __('Home Text', 'wedocs'), + 'type' => Controls_Manager::TEXT, + 'default' => __('Home', 'wedocs'), + ] + ); + + $this->add_control( + 'show_home_icon', + [ + 'label' => __('Show Home Icon', 'wedocs'), + 'type' => Controls_Manager::SWITCHER, + 'label_on' => __('Yes', 'wedocs'), + 'label_off' => __('No', 'wedocs'), + 'return_value' => 'yes', + 'default' => 'yes', + ] + ); + + $this->add_control( + 'separator', + [ + 'label' => __('Separator', 'wedocs'), + 'type' => Controls_Manager::SELECT, + 'default' => 'angle', + 'options' => [ + 'angle' => '›', + 'slash' => '/', + 'arrow' => '→', + 'dot' => '·', + 'dash' => '—', + ], + ] + ); + + $this->add_control( + 'truncate_length', + [ + 'label' => __('Max Characters per Item', 'wedocs'), + 'type' => Controls_Manager::NUMBER, + 'default' => 0, + 'min' => 0, + 'max' => 100, + 'description' => __('0 = no truncation', 'wedocs'), + ] + ); + + $this->end_controls_section(); + + // Style Section - Container + $this->start_controls_section( + 'style_container', + [ + 'label' => __('Container', 'wedocs'), + 'tab' => Controls_Manager::TAB_STYLE, + ] + ); + + $this->add_control( + 'bg_color', + [ + 'label' => __('Background Color', 'wedocs'), + 'type' => Controls_Manager::COLOR, + 'default' => '', + 'selectors' => [ + '{{WRAPPER}} .wedocs-el-breadcrumb' => 'background-color: {{VALUE}};', + ], + ] + ); + + $this->add_responsive_control( + 'container_padding', + [ + 'label' => __('Padding', 'wedocs'), + 'type' => Controls_Manager::DIMENSIONS, + 'size_units' => ['px', 'em'], + 'selectors' => [ + '{{WRAPPER}} .wedocs-el-breadcrumb' => 'padding: {{TOP}}{{UNIT}} {{RIGHT}}{{UNIT}} {{BOTTOM}}{{UNIT}} {{LEFT}}{{UNIT}};', + ], + ] + ); + + $this->add_responsive_control( + 'item_gap', + [ + 'label' => __('Item Spacing', 'wedocs'), + 'type' => Controls_Manager::SLIDER, + 'range' => ['px' => ['min' => 2, 'max' => 20]], + 'default' => ['size' => 8], + 'selectors' => [ + '{{WRAPPER}} .wedocs-el-breadcrumb__list' => 'gap: {{SIZE}}px;', + ], + ] + ); + + $this->end_controls_section(); + + // Style Section - Links + $this->start_controls_section( + 'style_links', + [ + 'label' => __('Links', 'wedocs'), + 'tab' => Controls_Manager::TAB_STYLE, + ] + ); + + $this->add_control( + 'link_color', + [ + 'label' => __('Color', 'wedocs'), + 'type' => Controls_Manager::COLOR, + 'default' => '#64748b', + 'selectors' => [ + '{{WRAPPER}} .wedocs-el-breadcrumb__link' => 'color: {{VALUE}};', + ], + ] + ); + + $this->add_control( + 'link_hover_color', + [ + 'label' => __('Hover Color', 'wedocs'), + 'type' => Controls_Manager::COLOR, + 'default' => '#0073aa', + 'selectors' => [ + '{{WRAPPER}} .wedocs-el-breadcrumb__link:hover' => 'color: {{VALUE}};', + ], + ] + ); + + $this->add_group_control( + Group_Control_Typography::get_type(), + [ + 'name' => 'link_typography', + 'selector' => '{{WRAPPER}} .wedocs-el-breadcrumb__link, {{WRAPPER}} .wedocs-el-breadcrumb__current', + ] + ); + + $this->end_controls_section(); + + // Style Section - Current Item + $this->start_controls_section( + 'style_current', + [ + 'label' => __('Current Item', 'wedocs'), + 'tab' => Controls_Manager::TAB_STYLE, + ] + ); + + $this->add_control( + 'current_color', + [ + 'label' => __('Color', 'wedocs'), + 'type' => Controls_Manager::COLOR, + 'default' => '#1e293b', + 'selectors' => [ + '{{WRAPPER}} .wedocs-el-breadcrumb__current' => 'color: {{VALUE}};', + ], + ] + ); + + $this->add_control( + 'current_font_weight', + [ + 'label' => __('Font Weight', 'wedocs'), + 'type' => Controls_Manager::SELECT, + 'default' => '600', + 'options' => [ + '400' => __('Normal', 'wedocs'), + '500' => __('Medium', 'wedocs'), + '600' => __('Semi Bold', 'wedocs'), + '700' => __('Bold', 'wedocs'), + ], + 'selectors' => [ + '{{WRAPPER}} .wedocs-el-breadcrumb__current' => 'font-weight: {{VALUE}};', + ], + ] + ); + + $this->end_controls_section(); + + // Style Section - Separator + $this->start_controls_section( + 'style_separator', + [ + 'label' => __('Separator', 'wedocs'), + 'tab' => Controls_Manager::TAB_STYLE, + ] + ); + + $this->add_control( + 'separator_color', + [ + 'label' => __('Color', 'wedocs'), + 'type' => Controls_Manager::COLOR, + 'default' => '#cbd5e1', + 'selectors' => [ + '{{WRAPPER}} .wedocs-el-breadcrumb__sep' => 'color: {{VALUE}};', + ], + ] + ); + + $this->add_responsive_control( + 'separator_size', + [ + 'label' => __('Size', 'wedocs'), + 'type' => Controls_Manager::SLIDER, + 'range' => ['px' => ['min' => 10, 'max' => 24]], + 'default' => ['size' => 14], + 'selectors' => [ + '{{WRAPPER}} .wedocs-el-breadcrumb__sep' => 'font-size: {{SIZE}}px;', + ], + ] + ); + + $this->end_controls_section(); + + // Style Section - Home Icon + $this->start_controls_section( + 'style_home_icon', + [ + 'label' => __('Home Icon', 'wedocs'), + 'tab' => Controls_Manager::TAB_STYLE, + 'condition' => ['show_home_icon' => 'yes'], + ] + ); + + $this->add_control( + 'home_icon_color', + [ + 'label' => __('Color', 'wedocs'), + 'type' => Controls_Manager::COLOR, + 'default' => '#94a3b8', + 'selectors' => [ + '{{WRAPPER}} .wedocs-el-breadcrumb__home-icon svg' => 'fill: {{VALUE}};', + ], + ] + ); + + $this->add_responsive_control( + 'home_icon_size', + [ + 'label' => __('Size', 'wedocs'), + 'type' => Controls_Manager::SLIDER, + 'range' => ['px' => ['min' => 12, 'max' => 24]], + 'default' => ['size' => 16], + 'selectors' => [ + '{{WRAPPER}} .wedocs-el-breadcrumb__home-icon svg' => 'width: {{SIZE}}px; height: {{SIZE}}px;', + ], + ] + ); + + $this->end_controls_section(); + } + + protected function render() { + $settings = $this->get_settings_for_display(); + + $home_text = $settings['home_text'] ?? __('Home', 'wedocs'); + $show_home_icon = ($settings['show_home_icon'] ?? 'yes') === 'yes'; + $separator = $settings['separator'] ?? 'angle'; + $truncate = absint($settings['truncate_length'] ?? 0); + + $separators = [ + 'angle' => '›', + 'slash' => '/', + 'arrow' => '→', + 'dot' => '·', + 'dash' => '—', + ]; + $sep_char = $separators[$separator] ?? '›'; + + global $post; + + if (empty($post) || $post->post_type !== 'docs') { + if (\Elementor\Plugin::$instance->editor->is_edit_mode()) { + echo '

' . __('Docs Breadcrumb: Preview it on a single doc page.', 'wedocs') . '

'; + } + return; + } + + // Build breadcrumb items + $items = []; + + // Home + $items[] = [ + 'label' => $home_text, + 'url' => home_url('/'), + 'home' => true, + ]; + + // Docs home page + $docs_home = wedocs_get_general_settings('docs_home'); + if ($docs_home) { + $items[] = [ + 'label' => __('Docs', 'wedocs'), + 'url' => get_permalink($docs_home), + ]; + } + + // Parent hierarchy + if ($post->post_parent) { + $parent_id = $post->post_parent; + $parents = []; + + while ($parent_id) { + $page = get_post($parent_id); + $parents[] = [ + 'label' => get_the_title($page->ID), + 'url' => get_permalink($page->ID), + ]; + $parent_id = $page->post_parent; + } + + $items = array_merge($items, array_reverse($parents)); + } + + // Current page (no link) + $items[] = [ + 'label' => get_the_title(), + 'current' => true, + ]; + + ?> + + + + + <# + var homeText = settings.home_text || 'Home'; + var showHomeIcon = settings.show_home_icon === 'yes'; + var separator = settings.separator || 'angle'; + var linkColor = settings.link_color || '#64748b'; + var currentColor = settings.current_color || '#1e293b'; + var sepColor = settings.separator_color || '#cbd5e1'; + var sepSize = settings.separator_size?.size || 14; + var iconColor = settings.home_icon_color || '#94a3b8'; + var iconSize = settings.home_icon_size?.size || 16; + var currentWeight = settings.current_font_weight || '600'; + + var seps = { angle: '›', slash: '/', arrow: '→', dot: '·', dash: '—' }; + var sepChar = seps[separator] || '›'; + + var items = [ + { label: homeText, home: true }, + { label: 'Documentation' }, + { label: 'Getting Started' }, + { label: 'Installation Guide', current: true } + ]; + #> + + + start_controls_section( + 'content_section', + [ + 'label' => __('Content', 'wedocs'), + 'tab' => Controls_Manager::TAB_CONTENT, + ] + ); + + $this->add_control( + 'icon_type', + [ + 'label' => __('Trigger Icon', 'wedocs'), + 'type' => Controls_Manager::SELECT, + 'default' => 'bars', + 'options' => [ + 'bars' => __('Hamburger Bars', 'wedocs'), + 'dots' => __('Dots', 'wedocs'), + 'menu_text' => __('Menu + Icon', 'wedocs'), + ], + ] + ); + + $this->add_control( + 'panel_position', + [ + 'label' => __('Panel Position', 'wedocs'), + 'type' => Controls_Manager::SELECT, + 'default' => 'left', + 'options' => [ + 'left' => __('Left', 'wedocs'), + 'right' => __('Right', 'wedocs'), + ], + ] + ); + + $this->add_control( + 'show_search', + [ + 'label' => __('Show Quick Search', 'wedocs'), + 'type' => Controls_Manager::SWITCHER, + 'label_on' => __('Yes', 'wedocs'), + 'label_off' => __('No', 'wedocs'), + 'return_value' => 'yes', + 'default' => 'yes', + ] + ); + + $this->add_control( + 'search_placeholder', + [ + 'label' => __('Search Placeholder', 'wedocs'), + 'type' => Controls_Manager::TEXT, + 'default' => __('Quick search...', 'wedocs'), + 'condition' => ['show_search' => 'yes'], + ] + ); + + $this->add_control( + 'show_title', + [ + 'label' => __('Show Doc Title', 'wedocs'), + 'type' => Controls_Manager::SWITCHER, + 'label_on' => __('Yes', 'wedocs'), + 'label_off' => __('No', 'wedocs'), + 'return_value' => 'yes', + 'default' => 'yes', + ] + ); + + $this->end_controls_section(); + + // Style Section - Trigger Button + $this->start_controls_section( + 'style_trigger', + [ + 'label' => __('Trigger Button', 'wedocs'), + 'tab' => Controls_Manager::TAB_STYLE, + ] + ); + + $this->add_control( + 'trigger_color', + [ + 'label' => __('Icon Color', 'wedocs'), + 'type' => Controls_Manager::COLOR, + 'default' => '#1e293b', + 'selectors' => [ + '{{WRAPPER}} .wedocs-hamburger__trigger' => 'color: {{VALUE}};', + '{{WRAPPER}} .wedocs-hamburger__trigger svg' => 'fill: {{VALUE}};', + ], + ] + ); + + $this->add_control( + 'trigger_bg', + [ + 'label' => __('Background Color', 'wedocs'), + 'type' => Controls_Manager::COLOR, + 'default' => '', + 'selectors' => [ + '{{WRAPPER}} .wedocs-hamburger__trigger' => 'background-color: {{VALUE}};', + ], + ] + ); + + $this->add_responsive_control( + 'trigger_size', + [ + 'label' => __('Icon Size', 'wedocs'), + 'type' => Controls_Manager::SLIDER, + 'range' => ['px' => ['min' => 16, 'max' => 48]], + 'default' => ['size' => 24], + 'selectors' => [ + '{{WRAPPER}} .wedocs-hamburger__trigger svg' => 'width: {{SIZE}}px; height: {{SIZE}}px;', + ], + ] + ); + + $this->add_responsive_control( + 'trigger_padding', + [ + 'label' => __('Padding', 'wedocs'), + 'type' => Controls_Manager::DIMENSIONS, + 'size_units' => ['px'], + 'default' => ['top' => 8, 'right' => 8, 'bottom' => 8, 'left' => 8, 'unit' => 'px'], + 'selectors' => [ + '{{WRAPPER}} .wedocs-hamburger__trigger' => 'padding: {{TOP}}{{UNIT}} {{RIGHT}}{{UNIT}} {{BOTTOM}}{{UNIT}} {{LEFT}}{{UNIT}};', + ], + ] + ); + + $this->add_responsive_control( + 'trigger_border_radius', + [ + 'label' => __('Border Radius', 'wedocs'), + 'type' => Controls_Manager::DIMENSIONS, + 'size_units' => ['px', '%'], + 'default' => ['top' => 6, 'right' => 6, 'bottom' => 6, 'left' => 6, 'unit' => 'px'], + 'selectors' => [ + '{{WRAPPER}} .wedocs-hamburger__trigger' => 'border-radius: {{TOP}}{{UNIT}} {{RIGHT}}{{UNIT}} {{BOTTOM}}{{UNIT}} {{LEFT}}{{UNIT}};', + ], + ] + ); + + $this->end_controls_section(); + + // Style Section - Panel + $this->start_controls_section( + 'style_panel', + [ + 'label' => __('Panel', 'wedocs'), + 'tab' => Controls_Manager::TAB_STYLE, + ] + ); + + $this->add_control( + 'panel_bg', + [ + 'label' => __('Background Color', 'wedocs'), + 'type' => Controls_Manager::COLOR, + 'default' => '#ffffff', + 'selectors' => [ + '{{WRAPPER}} .wedocs-hamburger__panel' => 'background-color: {{VALUE}};', + ], + ] + ); + + $this->add_responsive_control( + 'panel_width', + [ + 'label' => __('Width', 'wedocs'), + 'type' => Controls_Manager::SLIDER, + 'range' => ['px' => ['min' => 240, 'max' => 500]], + 'default' => ['size' => 320], + 'selectors' => [ + '{{WRAPPER}} .wedocs-hamburger__panel' => 'width: {{SIZE}}px;', + ], + ] + ); + + $this->add_responsive_control( + 'panel_padding', + [ + 'label' => __('Padding', 'wedocs'), + 'type' => Controls_Manager::DIMENSIONS, + 'size_units' => ['px', 'em'], + 'default' => ['top' => 20, 'right' => 20, 'bottom' => 20, 'left' => 20, 'unit' => 'px'], + 'selectors' => [ + '{{WRAPPER}} .wedocs-hamburger__panel' => 'padding: {{TOP}}{{UNIT}} {{RIGHT}}{{UNIT}} {{BOTTOM}}{{UNIT}} {{LEFT}}{{UNIT}};', + ], + ] + ); + + $this->add_group_control( + Group_Control_Box_Shadow::get_type(), + [ + 'name' => 'panel_shadow', + 'selector' => '{{WRAPPER}} .wedocs-hamburger__panel', + 'fields_options' => [ + 'box_shadow_type' => ['default' => 'yes'], + 'box_shadow' => ['default' => ['horizontal' => 4, 'vertical' => 0, 'blur' => 20, 'spread' => 0, 'color' => 'rgba(0,0,0,0.15)']], + ], + ] + ); + + $this->add_control( + 'overlay_color', + [ + 'label' => __('Overlay Color', 'wedocs'), + 'type' => Controls_Manager::COLOR, + 'default' => 'rgba(0,0,0,0.4)', + 'selectors' => [ + '{{WRAPPER}} .wedocs-hamburger__overlay' => 'background-color: {{VALUE}};', + ], + ] + ); + + $this->end_controls_section(); + + // Style Section - Title + $this->start_controls_section( + 'style_title', + [ + 'label' => __('Doc Title', 'wedocs'), + 'tab' => Controls_Manager::TAB_STYLE, + 'condition' => ['show_title' => 'yes'], + ] + ); + + $this->add_control( + 'title_color', + [ + 'label' => __('Color', 'wedocs'), + 'type' => Controls_Manager::COLOR, + 'default' => '#1e293b', + 'selectors' => [ + '{{WRAPPER}} .wedocs-hamburger__title' => 'color: {{VALUE}};', + ], + ] + ); + + $this->add_group_control( + Group_Control_Typography::get_type(), + [ + 'name' => 'title_typography', + 'selector' => '{{WRAPPER}} .wedocs-hamburger__title', + ] + ); + + $this->end_controls_section(); + + // Style Section - Navigation Items + $this->start_controls_section( + 'style_nav', + [ + 'label' => __('Navigation Items', 'wedocs'), + 'tab' => Controls_Manager::TAB_STYLE, + ] + ); + + $this->add_control( + 'link_color', + [ + 'label' => __('Link Color', 'wedocs'), + 'type' => Controls_Manager::COLOR, + 'default' => '#475569', + 'selectors' => [ + '{{WRAPPER}} .wedocs-hamburger__nav a' => 'color: {{VALUE}};', + ], + ] + ); + + $this->add_control( + 'link_hover_color', + [ + 'label' => __('Hover Color', 'wedocs'), + 'type' => Controls_Manager::COLOR, + 'default' => '#0073aa', + 'selectors' => [ + '{{WRAPPER}} .wedocs-hamburger__nav a:hover' => 'color: {{VALUE}};', + ], + ] + ); + + $this->add_control( + 'active_color', + [ + 'label' => __('Active Color', 'wedocs'), + 'type' => Controls_Manager::COLOR, + 'default' => '#0073aa', + 'selectors' => [ + '{{WRAPPER}} .wedocs-hamburger__nav .current_page_item > a' => 'color: {{VALUE}}; font-weight: 600;', + ], + ] + ); + + $this->add_group_control( + Group_Control_Typography::get_type(), + [ + 'name' => 'link_typography', + 'selector' => '{{WRAPPER}} .wedocs-hamburger__nav a', + ] + ); + + $this->add_responsive_control( + 'item_padding', + [ + 'label' => __('Item Padding', 'wedocs'), + 'type' => Controls_Manager::DIMENSIONS, + 'size_units' => ['px', 'em'], + 'default' => ['top' => 8, 'right' => 0, 'bottom' => 8, 'left' => 0, 'unit' => 'px'], + 'selectors' => [ + '{{WRAPPER}} .wedocs-hamburger__nav a' => 'padding: {{TOP}}{{UNIT}} {{RIGHT}}{{UNIT}} {{BOTTOM}}{{UNIT}} {{LEFT}}{{UNIT}};', + ], + ] + ); + + $this->end_controls_section(); + + // Style Section - Close Button + $this->start_controls_section( + 'style_close', + [ + 'label' => __('Close Button', 'wedocs'), + 'tab' => Controls_Manager::TAB_STYLE, + ] + ); + + $this->add_control( + 'close_color', + [ + 'label' => __('Color', 'wedocs'), + 'type' => Controls_Manager::COLOR, + 'default' => '#64748b', + 'selectors' => [ + '{{WRAPPER}} .wedocs-hamburger__close' => 'color: {{VALUE}};', + '{{WRAPPER}} .wedocs-hamburger__close svg' => 'fill: {{VALUE}};', + ], + ] + ); + + $this->add_responsive_control( + 'close_size', + [ + 'label' => __('Size', 'wedocs'), + 'type' => Controls_Manager::SLIDER, + 'range' => ['px' => ['min' => 16, 'max' => 40]], + 'default' => ['size' => 24], + 'selectors' => [ + '{{WRAPPER}} .wedocs-hamburger__close svg' => 'width: {{SIZE}}px; height: {{SIZE}}px;', + ], + ] + ); + + $this->end_controls_section(); + } + + protected function render() { + $settings = $this->get_settings_for_display(); + + $icon_type = $settings['icon_type'] ?? 'bars'; + $panel_position = $settings['panel_position'] ?? 'left'; + $show_search = ($settings['show_search'] ?? 'yes') === 'yes'; + $search_placeholder = $settings['search_placeholder'] ?? __('Quick search...', 'wedocs'); + $show_title = ($settings['show_title'] ?? 'yes') === 'yes'; + + global $post; + + // Determine the parent doc + $ancestors = []; + $parent = false; + + if (!empty($post->post_parent)) { + $ancestors = get_post_ancestors($post->ID); + $root = count($ancestors) - 1; + $parent = $ancestors[$root]; + } else { + $parent = !empty($post->ID) ? $post->ID : ''; + } + + if (!$parent) { + if (\Elementor\Plugin::$instance->editor->is_edit_mode()) { + echo '

' . __('Hamburger Menu: Preview it on a single doc page.', 'wedocs') . '

'; + } + return; + } + + $walker = new \WeDevs\WeDocs\Walker(); + $children = wp_list_pages([ + 'title_li' => '', + 'order' => 'menu_order', + 'child_of' => $parent, + 'echo' => false, + 'post_type' => 'docs', + 'walker' => $walker, + ]); + + $widget_id = $this->get_id(); + ?> + + + + + +
+ + +
+
+ +

+ + + +

+ + + + +
+ + + + + + + + +
+ + + + + + <# + var iconType = settings.icon_type || 'bars'; + var triggerColor = settings.trigger_color || '#1e293b'; + var triggerBg = settings.trigger_bg || ''; + #> + + + +

+ Off-canvas panel opens on the frontend when clicked. Position: {{ settings.panel_position || 'left' }}. +

+ Date: Wed, 18 Feb 2026 13:43:15 +0600 Subject: [PATCH 3/4] Unify feedback meta keys and Elementor previews Switch feedback storage to unified 'positive'/'negative' meta keys (Ajax, admin metabox, list table) and update code to read/write those keys. Add editor-aware context and preview rendering for Elementor widgets (DocNavigation, DocsBreadcrumb, DocsSidebar), plus new responsive controls (mobile stacking/toggle/hamburger) and related CSS for better editor UX and mobile behavior. Include a new three_column Elementor template and multiple formatting/whitespace cleanups across API and admin code. These changes improve consistency of feedback data and provide accurate previews in Elementor editor. --- includes/API/API.php | 7 +- includes/Admin/Docs_List_Table.php | 72 +-- includes/Ajax.php | 6 +- .../Elementor/Templates/three_column.json | 1 + includes/Elementor/Widgets/DocNavigation.php | 268 +++++++--- includes/Elementor/Widgets/DocsBreadcrumb.php | 209 ++++++-- includes/Elementor/Widgets/DocsSidebar.php | 497 +++++++++++++++--- .../Elementor/Widgets/TableOfContents.php | 350 ++++++++++-- includes/Elementor/Widgets/WasThisHelpful.php | 23 +- 9 files changed, 1161 insertions(+), 272 deletions(-) create mode 100644 includes/Elementor/Templates/three_column.json diff --git a/includes/API/API.php b/includes/API/API.php index 67edd1dd..3508df69 100644 --- a/includes/API/API.php +++ b/includes/API/API.php @@ -756,8 +756,9 @@ public function get_helpful_docs() { continue; } - $positive = (int) get_post_meta( $doc->ID, 'positive', true ); - $negative = (int) get_post_meta( $doc->ID, 'negative', true ); + // Get feedback counts + $positive = (int) get_post_meta($doc->ID, 'positive', true); + $negative = (int) get_post_meta($doc->ID, 'negative', true); if ( empty( $positive ) && empty( $negative ) ) { continue; } @@ -1231,7 +1232,7 @@ public function get_promotional_notice() { return false; } - /** + /** * Handle promotional notice hidden action * * @since 2.1.11 diff --git a/includes/Admin/Docs_List_Table.php b/includes/Admin/Docs_List_Table.php index 1a9bed30..8b903442 100644 --- a/includes/Admin/Docs_List_Table.php +++ b/includes/Admin/Docs_List_Table.php @@ -11,49 +11,59 @@ class Docs_List_Table { * Constructor */ public function __construct() { - add_filter( 'manage_docs_posts_columns', [ $this, 'docs_list_columns' ] ); - add_action( 'manage_docs_posts_custom_column', [ $this, 'docs_list_columns_row' ], 10, 2 ); - add_filter( 'manage_edit-docs_sortable_columns', [ $this, 'docs_sortable_columns' ] ); + add_filter('manage_docs_posts_columns', [$this, 'docs_list_columns']); + add_action('manage_docs_posts_custom_column', [$this, 'docs_list_columns_row'], 10, 2); + add_filter('manage_edit-docs_sortable_columns', [$this, 'docs_sortable_columns']); - add_action( 'load-edit.php', [ $this, 'edit_docs_load' ] ); - add_action( 'load-post.php', [ $this, 'add_meta_box' ] ); + add_action('load-edit.php', [$this, 'edit_docs_load']); + add_action('load-post.php', [$this, 'add_meta_box']); // load css - add_action( 'admin_print_styles-post.php', [ $this, 'helpfulness_css' ] ); - add_action( 'admin_print_styles-edit.php', [ $this, 'helpfulness_css' ] ); + add_action('admin_print_styles-post.php', [$this, 'helpfulness_css']); + add_action('admin_print_styles-edit.php', [$this, 'helpfulness_css']); } public function add_meta_box() { - add_meta_box( 'op-menu-meta-box-id', __( 'Helpfulness', 'wedocs' ), [ $this, 'helpfulness_metabox' ], 'docs', 'side', 'core' ); + add_meta_box('op-menu-meta-box-id', __('Helpfulness', 'wedocs'), [$this, 'helpfulness_metabox'], 'docs', 'side', 'core'); } public function helpfulness_css() { - if ( 'docs' != get_current_screen()->post_type ) { + if ('docs' != get_current_screen()->post_type) { return; } ?> - + global $post; + + $positive = (int) get_post_meta($post->ID, 'positive', true); + $negative = (int) get_post_meta($post->ID, 'negative', true); + ?>
- ID, 'positive', true ) ); ?> + - ID, 'negative', true ) ); ?> +
- __( 'Votes', 'wedocs' ) ]; + public function docs_list_columns($columns) { + $vote = ['votes' => __('Votes', 'wedocs')]; // insert before last element, date - $first_items = array_splice( $columns, 0, 3 ); // remove first 3 items and store to $first_items, date remains to $columns - $new_columns = array_merge( $first_items, $vote, $columns ); // merge all those + $first_items = array_splice($columns, 0, 3); // remove first 3 items and store to $first_items, date remains to $columns + $new_columns = array_merge($first_items, $vote, $columns); // merge all those return $new_columns; } - public function docs_sortable_columns( $columns ) { - $columns['votes'] = [ 'votes', true ]; + public function docs_sortable_columns($columns) { + $columns['votes'] = ['votes', true]; return $columns; } - public function docs_list_columns_row( $column_name, $post_id ) { - if ( 'votes' == $column_name ) { - $positive = get_post_meta( $post_id, 'positive', true ); - $negative = get_post_meta( $post_id, 'negative', true ); + public function docs_list_columns_row($column_name, $post_id) { + if ('votes' == $column_name) { + $positive = get_post_meta($post_id, 'positive', true); + $negative = get_post_meta($post_id, 'negative', true); - printf( '%d/%d', $positive, $negative ); + printf('%d/%d', $positive, $negative); } } public function edit_docs_load() { - add_filter( 'request', [ $this, 'sort_docs' ] ); + add_filter('request', [$this, 'sort_docs']); } // Sorts the movies. - public function sort_docs( $vars ) { + public function sort_docs($vars) { // Check if we're viewing the 'movie' post type. - if ( isset( $vars['post_type'] ) && 'docs' == $vars['post_type'] ) { + if (isset($vars['post_type']) && 'docs' == $vars['post_type']) { // Check if 'orderby' is set to 'duration'. - if ( isset( $vars['orderby'] ) && 'votes' == $vars['orderby'] ) { + if (isset($vars['orderby']) && 'votes' == $vars['orderby']) { $vars = array_merge( $vars, [ diff --git a/includes/Ajax.php b/includes/Ajax.php index 6ad3270c..7104c21f 100644 --- a/includes/Ajax.php +++ b/includes/Ajax.php @@ -600,13 +600,13 @@ public function handle_helpful_vote() { wp_send_json_error(['message' => __('Invalid vote.', 'wedocs')]); } - $meta_key = $vote === 'yes' ? '_wedocs_helpful_yes' : '_wedocs_helpful_no'; + $meta_key = $vote === 'yes' ? 'positive' : 'negative'; $current = (int) get_post_meta($post_id, $meta_key, true); update_post_meta($post_id, $meta_key, $current + 1); wp_send_json_success([ - 'yes' => (int) get_post_meta($post_id, '_wedocs_helpful_yes', true), - 'no' => (int) get_post_meta($post_id, '_wedocs_helpful_no', true), + 'yes' => (int) get_post_meta($post_id, 'positive', true), + 'no' => (int) get_post_meta($post_id, 'negative', true), ]); } diff --git a/includes/Elementor/Templates/three_column.json b/includes/Elementor/Templates/three_column.json new file mode 100644 index 00000000..71d7c2e8 --- /dev/null +++ b/includes/Elementor/Templates/three_column.json @@ -0,0 +1 @@ +{"content":[{"id":"66627e54","settings":{"flex_direction":"row","flex_gap":{"unit":"px","size":0,"column":"0","row":"0"},"content_width":"full","width":{"unit":"%","size":83,"sizes":[]}},"elements":[{"id":"751203","settings":{"flex_direction":"column","content_width":"full","width":{"unit":"%","size":"25"}},"elements":[{"id":"5494ee5","settings":{"search_placeholder":"Quick search...","mobile_toggle_text":"Navigation"},"elements":[],"isInner":false,"widgetType":"wedocs-docs-sidebar","elType":"widget"}],"isInner":true,"elType":"container"},{"id":"3f1364d7","settings":{"flex_direction":"column","content_width":"full","width":{"unit":"%","size":"50"}},"elements":[{"id":"11b33a2e","settings":{"content_width":"full"},"elements":[{"id":"56992cab","settings":{"__dynamic__":{"title":"[elementor-tag id=\"\" name=\"post-title\" settings=\"%7B%22before%22%3A%22%22%2C%22after%22%3A%22%22%2C%22fallback%22%3A%22%22%7D\"]"},"title":"Add Your Heading Text Here","title_color":"#142932"},"elements":[],"isInner":false,"widgetType":"theme-post-title","elType":"widget"},{"id":"62e424ef","settings":{"home_text":"Home"},"elements":[],"isInner":false,"widgetType":"wedocs-breadcrumb","elType":"widget"},{"id":"429504be","settings":[],"elements":[],"isInner":false,"widgetType":"theme-post-content","elType":"widget"},{"id":"736e93eb","settings":{"question_text":"Was this article helpful?","yes_text":"Yes","no_text":"No","show_count":"yes","thank_you_message":"Thank you for your feedback!","follow_up_placeholder":"How can we improve this article?"},"elements":[],"isInner":false,"widgetType":"wedocs-was-helpful","elType":"widget"},{"id":"360e1b81","settings":{"trigger_heading":"Need More Help?","trigger_description":"Can't find what you're looking for? Reach out to our support team.","button_text":"Contact Support","layout":"inline","modal_title":"Contact Support","modal_description":"Fill out the form below and our team will get back to you as soon as possible.","submit_text":"Send Message","success_message":"Thank you! Your message has been sent successfully.","recipient_email":"dev-email@wpengine.local","icon_color":"#364248","btn_bg_color":"#202527","btn_hover_bg_color":"#000000"},"elements":[],"isInner":false,"widgetType":"wedocs-need-help","elType":"widget"}],"isInner":true,"elType":"container"}],"isInner":true,"elType":"container"},{"id":"42bb9ff6","settings":{"flex_direction":"column","content_width":"full","width":{"unit":"%","size":"25"}},"elements":[{"id":"417d6e7f","settings":{"title":"On This Page"},"elements":[],"isInner":false,"widgetType":"wedocs-toc","elType":"widget"}],"isInner":true,"elType":"container"}],"isInner":false,"elType":"container"}],"page_settings":{"page_template":"elementor_header_footer"},"version":"0.4","title":"WeDocs Single Page","type":"single-post"} diff --git a/includes/Elementor/Widgets/DocNavigation.php b/includes/Elementor/Widgets/DocNavigation.php index 7c4577a7..cc4e4c9f 100644 --- a/includes/Elementor/Widgets/DocNavigation.php +++ b/includes/Elementor/Widgets/DocNavigation.php @@ -33,6 +33,31 @@ public function get_keywords() { return ['navigation', 'next', 'previous', 'prev', 'wedocs', 'docs']; } + /** + * Get the proper post context for editor mode + */ + protected function get_editor_post_context() { + global $post; + + // If we have a valid docs post, use it + if ($post && $post->post_type === 'docs') { + return $post; + } + + // In editor mode, try to get the post being edited + if (\Elementor\Plugin::$instance->editor->is_edit_mode()) { + $document = \Elementor\Plugin::$instance->documents->get_current(); + if ($document) { + $edit_post = get_post($document->get_main_id()); + if ($edit_post && $edit_post->post_type === 'docs') { + return $edit_post; + } + } + } + + return null; + } + protected function register_controls() { // Content Section @@ -113,6 +138,20 @@ protected function register_controls() { ] ); + $this->add_control( + 'mobile_stack', + [ + 'label' => __('Stack on Mobile', 'wedocs'), + 'type' => Controls_Manager::SWITCHER, + 'label_on' => __('Yes', 'wedocs'), + 'label_off' => __('No', 'wedocs'), + 'return_value' => 'yes', + 'default' => 'yes', + 'description' => __('Stack prev/next vertically on screens ≤768px', 'wedocs'), + 'condition' => ['layout' => 'side-by-side'], + ] + ); + $this->end_controls_section(); // Style Section - Container @@ -344,21 +383,23 @@ protected function render() { $show_arrows = ($settings['show_arrows'] ?? 'yes') === 'yes'; $layout = $settings['layout'] ?? 'side-by-side'; - global $post, $wpdb; + $current_post = $this->get_editor_post_context(); - if (empty($post) || $post->post_type !== 'docs') { + if (!$current_post) { if (\Elementor\Plugin::$instance->editor->is_edit_mode()) { - echo '

' . __('Doc Navigation: Preview it on a single doc page.', 'wedocs') . '

'; + $this->render_editor_preview($settings); } return; } + global $wpdb; + $next_post_id = 0; $prev_post_id = 0; if ($show_next) { $next_query = "SELECT ID FROM {$wpdb->posts} - WHERE post_parent = {$post->post_parent} AND post_type = 'docs' AND post_status = 'publish' AND menu_order > {$post->menu_order} + WHERE post_parent = {$current_post->post_parent} AND post_type = 'docs' AND post_status = 'publish' AND menu_order > {$current_post->menu_order} ORDER BY menu_order ASC LIMIT 0, 1"; $next_post_id = (int) $wpdb->get_var($next_query); @@ -366,7 +407,7 @@ protected function render() { if ($show_prev) { $prev_query = "SELECT ID FROM {$wpdb->posts} - WHERE post_parent = {$post->post_parent} AND post_type = 'docs' AND post_status = 'publish' AND menu_order < {$post->menu_order} + WHERE post_parent = {$current_post->post_parent} AND post_type = 'docs' AND post_status = 'publish' AND menu_order < {$current_post->menu_order} ORDER BY menu_order DESC LIMIT 0, 1"; $prev_post_id = (int) $wpdb->get_var($prev_query); @@ -374,13 +415,18 @@ protected function render() { if (!$next_post_id && !$prev_post_id) { if (\Elementor\Plugin::$instance->editor->is_edit_mode()) { - echo '

' . __('Doc Navigation: No adjacent docs found.', 'wedocs') . '

'; + $this->render_editor_preview($settings); } return; } + $mobile_stack = ($settings['mobile_stack'] ?? 'yes') === 'yes'; + $nav_class = 'wedocs-el-nav wedocs-el-nav--' . $layout; - ?> + if ($mobile_stack && $layout === 'side-by-side') { + $nav_class .= ' wedocs-el-nav--mobile-stack'; + } +?> - + /** + * Render preview for editor mode with sample data + */ + protected function render_editor_preview($settings) { + $title = $settings['title'] ?? __('On This Page', 'wedocs'); + $title_tag = $settings['title_tag'] ?? 'h3'; + $show_numbers = ($settings['show_numbers'] ?? '') === 'yes'; + $collapsible = ($settings['collapsible'] ?? '') === 'yes'; + $collapsed_default = ($settings['collapsed_default'] ?? '') === 'yes'; + $sticky = ($settings['sticky'] ?? '') === 'yes'; + $sticky_offset = $settings['sticky_offset']['size'] ?? 20; + + $wrapper_class = 'wedocs-toc'; + if ($sticky) { + $wrapper_class .= ' wedocs-toc--sticky'; + } + if ($collapsible) { + $wrapper_class .= ' wedocs-toc--collapsible'; + } + if ($collapsed_default) { + $wrapper_class .= ' wedocs-toc--collapsed'; + } + + // Sample headings for preview + $sample_headings = [ + ['level' => 2, 'id' => 'introduction', 'text' => 'Introduction', 'index' => 1], + ['level' => 3, 'id' => 'getting-started', 'text' => 'Getting Started', 'index' => 2], + ['level' => 2, 'id' => 'configuration', 'text' => 'Configuration', 'index' => 3], + ['level' => 3, 'id' => 'basic-settings', 'text' => 'Basic Settings', 'index' => 4], + ['level' => 3, 'id' => 'advanced-options', 'text' => 'Advanced Options', 'index' => 5], + ['level' => 2, 'id' => 'troubleshooting', 'text' => 'Troubleshooting', 'index' => 6], + ]; + + $min_level = 2; + ?> + +
style="position: sticky; top: px;" > + +
+ < class="wedocs-toc__title"> + + + + + > +
+ + + +
+ 📝 +
+
get_id(); + + // Get post ID - handle editor mode $post_id = get_the_ID(); + if (!$post_id && \Elementor\Plugin::$instance->editor->is_edit_mode()) { + $document = \Elementor\Plugin::$instance->documents->get_current(); + if ($document) { + $post_id = $document->get_main_id(); + } + } + + // Fallback for editor preview + if (!$post_id) { + $post_id = 0; + } // Get existing vote counts - $positive_count = (int) get_post_meta($post_id, '_wedocs_helpful_yes', true); - $negative_count = (int) get_post_meta($post_id, '_wedocs_helpful_no', true); + $positive_count = (int) get_post_meta($post_id, 'positive', true); + $negative_count = (int) get_post_meta($post_id, 'negative', true); + + // Show sample counts in editor mode for better preview + if (\Elementor\Plugin::$instance->editor->is_edit_mode() && !$positive_count && !$negative_count) { + $positive_count = 12; + $negative_count = 3; + } ?>
From d9f96a37d8ef2f3205de796068d7196bc4915a3b Mon Sep 17 00:00:00 2001 From: Iftakharul Islam Ifat <88052038+iftakharul-islam@users.noreply.github.com> Date: Mon, 8 Jun 2026 11:37:47 +0600 Subject: [PATCH 4/4] Add Elementor template import and fixes Register template import flow and editor scripts for weDocs. Adds init_templates hook, admin-only enqueue for Elementor editor, and functions to import a three_column template from JSON, fix/normalize existing template meta formats, set template conditions, reset imports for development, and get template version. Marks imported templates with _wedocs_template and uses an option (wedocs_elementor_templates_imported) to avoid re-importing. Also includes minor code style tweaks and updates three_column.json to a validated, pretty-printed template format. --- includes/Elementor.php | 276 ++++++++++++++++-- .../Elementor/Templates/three_column.json | 177 ++++++++++- 2 files changed, 435 insertions(+), 18 deletions(-) diff --git a/includes/Elementor.php b/includes/Elementor.php index d34b9c40..05e7fa60 100644 --- a/includes/Elementor.php +++ b/includes/Elementor.php @@ -11,22 +11,30 @@ class Elementor { * Initialize the class */ public function __construct() { - add_action( 'elementor/widgets/register', [ $this, 'register_widgets' ] ); - add_action( 'elementor/elements/categories_registered', [ $this, 'register_widget_category' ] ); + add_action('elementor/widgets/register', [$this, 'register_widgets']); + add_action('elementor/elements/categories_registered', [$this, 'register_widget_category']); // Register widget scripts - add_action( 'elementor/frontend/after_register_scripts', [ $this, 'register_widget_scripts' ] ); - add_action( 'elementor/frontend/after_enqueue_styles', [ $this, 'register_widget_styles' ] ); + add_action('elementor/frontend/after_register_scripts', [$this, 'register_widget_scripts']); + add_action('elementor/frontend/after_enqueue_styles', [$this, 'register_widget_styles']); + + // Register templates + add_action('init', [$this, 'init_templates']); + + // Admin only scripts for Elementor editor + if (is_admin()) { + add_action('elementor/editor/footer', [$this, 'enqueue_template_scripts']); + } } /** * Register custom widget category */ - public function register_widget_category( $elements_manager ) { + public function register_widget_category($elements_manager) { $elements_manager->add_category( 'wedocs-category', [ - 'title' => __( 'weDocs', 'wedocs' ), + 'title' => __('weDocs', 'wedocs'), 'icon' => 'fa fa-book', ] ); @@ -37,7 +45,7 @@ public function register_widget_category( $elements_manager ) { */ public function register_widgets() { // Check if Elementor is loaded - if ( ! did_action( 'elementor/loaded' ) ) { + if (! did_action('elementor/loaded')) { return; } @@ -55,15 +63,15 @@ public function register_widgets() { // Register widgets // \Elementor\Plugin::instance()->widgets_manager->register( new \WeDevs\WeDocs\Elementor\Widgets\Search() ); - \Elementor\Plugin::instance()->widgets_manager->register( new \WeDevs\WeDocs\Elementor\Widgets\DocsGrid() ); - \Elementor\Plugin::instance()->widgets_manager->register( new \WeDevs\WeDocs\Elementor\Widgets\TableOfContents() ); - \Elementor\Plugin::instance()->widgets_manager->register( new \WeDevs\WeDocs\Elementor\Widgets\NeedHelp() ); - \Elementor\Plugin::instance()->widgets_manager->register( new \WeDevs\WeDocs\Elementor\Widgets\WasThisHelpful() ); - \Elementor\Plugin::instance()->widgets_manager->register( new \WeDevs\WeDocs\Elementor\Widgets\DocsSidebar() ); - \Elementor\Plugin::instance()->widgets_manager->register( new \WeDevs\WeDocs\Elementor\Widgets\SearchModal() ); - \Elementor\Plugin::instance()->widgets_manager->register( new \WeDevs\WeDocs\Elementor\Widgets\DocNavigation() ); - \Elementor\Plugin::instance()->widgets_manager->register( new \WeDevs\WeDocs\Elementor\Widgets\DocsHamburgerMenu() ); - \Elementor\Plugin::instance()->widgets_manager->register( new \WeDevs\WeDocs\Elementor\Widgets\DocsBreadcrumb() ); + \Elementor\Plugin::instance()->widgets_manager->register(new \WeDevs\WeDocs\Elementor\Widgets\DocsGrid()); + \Elementor\Plugin::instance()->widgets_manager->register(new \WeDevs\WeDocs\Elementor\Widgets\TableOfContents()); + \Elementor\Plugin::instance()->widgets_manager->register(new \WeDevs\WeDocs\Elementor\Widgets\NeedHelp()); + \Elementor\Plugin::instance()->widgets_manager->register(new \WeDevs\WeDocs\Elementor\Widgets\WasThisHelpful()); + \Elementor\Plugin::instance()->widgets_manager->register(new \WeDevs\WeDocs\Elementor\Widgets\DocsSidebar()); + \Elementor\Plugin::instance()->widgets_manager->register(new \WeDevs\WeDocs\Elementor\Widgets\SearchModal()); + \Elementor\Plugin::instance()->widgets_manager->register(new \WeDevs\WeDocs\Elementor\Widgets\DocNavigation()); + \Elementor\Plugin::instance()->widgets_manager->register(new \WeDevs\WeDocs\Elementor\Widgets\DocsHamburgerMenu()); + \Elementor\Plugin::instance()->widgets_manager->register(new \WeDevs\WeDocs\Elementor\Widgets\DocsBreadcrumb()); } /** @@ -73,7 +81,7 @@ public function register_widget_scripts() { wp_register_script( 'wedocs-elementor-widgets', WEDOCS_ASSETS . '/js/elementor-widgets.js', - [ 'elementor-frontend' ], + ['elementor-frontend'], WEDOCS_VERSION, true ); @@ -90,4 +98,238 @@ public function register_widget_styles() { WEDOCS_VERSION ); } + + /** + * Initialize template import + */ + public function init_templates() { + if (! did_action('elementor/loaded')) { + return; + } + + // Import default templates if they don't exist + $this->import_default_templates(); + } + + /** + * Import default weDocs templates + */ + public function import_default_templates() { + // Clean up any existing templates with incorrect format + $this->fix_existing_template_conditions(); + + // Force re-import if templates exist with wrong format + $existing_templates = get_posts([ + 'post_type' => 'elementor_library', + 'meta_key' => '_wedocs_template', + 'meta_value' => true, + 'posts_per_page' => 1 + ]); + + if (!empty($existing_templates)) { + // Check if existing template has proper data format + $elementor_data = get_post_meta($existing_templates[0]->ID, '_elementor_data', true); + if (is_array($elementor_data)) { + // Re-import with correct format + delete_option('wedocs_elementor_templates_imported'); + wp_delete_post($existing_templates[0]->ID, true); + } + } + + // Check if template import is needed + if (get_option('wedocs_elementor_templates_imported')) { + return; + } + + $template_id = $this->import_template_from_json('three_column', 'weDocs - Single Doc Page'); + + if ($template_id) { + // Set template conditions for single docs + $this->set_template_conditions($template_id, 'single_docs'); + + // Mark as imported + update_option('wedocs_elementor_templates_imported', true); + } + } + + /** + * Fix existing template conditions and settings format + */ + public function fix_existing_template_conditions() { + $templates = get_posts([ + 'post_type' => 'elementor_library', + 'meta_key' => '_wedocs_template', + 'meta_value' => true, + 'posts_per_page' => -1 + ]); + + foreach ($templates as $template) { + // Fix conditions format + $conditions = get_post_meta($template->ID, '_elementor_conditions', true); + + // Check if conditions are in old array format + if (is_array($conditions) && isset($conditions[0]['type'])) { + // Convert to proper string format + $new_conditions = []; + foreach ($conditions as $condition) { + if (isset($condition['type'], $condition['sub'], $condition['sub_id'])) { + $new_conditions[] = $condition['type'] . '/' . $condition['sub'] . '/' . $condition['sub_id']; + } + } + + if (!empty($new_conditions)) { + update_post_meta($template->ID, '_elementor_conditions', $new_conditions); + } + } + + // Fix page settings format + $page_settings = get_post_meta($template->ID, '_elementor_page_settings', true); + + // Check if page settings are JSON string instead of array + if (is_string($page_settings) && !empty($page_settings)) { + $decoded_settings = json_decode($page_settings, true); + if (json_last_error() === JSON_ERROR_NONE && is_array($decoded_settings)) { + // Convert from JSON string to array + update_post_meta($template->ID, '_elementor_page_settings', $decoded_settings); + } + } elseif (empty($page_settings)) { + // Set empty array if none exists + update_post_meta($template->ID, '_elementor_page_settings', []); + } + + // Fix elementor data format + $elementor_data = get_post_meta($template->ID, '_elementor_data', true); + + // Check if elementor data is stored as array instead of JSON string + if (is_array($elementor_data) && !empty($elementor_data)) { + // Convert from array to JSON string + update_post_meta($template->ID, '_elementor_data', wp_json_encode($elementor_data)); + } + } + } + + /** + * Set template conditions + */ + public function set_template_conditions($template_id, $condition_type = 'single_docs') { + $conditions = []; + + switch ($condition_type) { + case 'single_docs': + $conditions = [ + 'include/single/docs' + ]; + break; + + case 'docs_archive': + $conditions = [ + 'include/archive/docs' + ]; + break; + } + + if (! empty($conditions)) { + update_post_meta($template_id, '_elementor_conditions', $conditions); + } + } + + /** + * Import template from JSON file + */ + public function import_template_from_json($template_name, $template_title) { + $template_path = WEDOCS_PATH . '/includes/Elementor/Templates/' . $template_name . '.json'; + + if (! file_exists($template_path)) { + return false; + } + + $json_content = file_get_contents($template_path); + $template_data = json_decode($json_content, true); + + if (! $template_data || json_last_error() !== JSON_ERROR_NONE) { + return false; + } + + // Validate required template structure + if (! isset($template_data['content']) || ! is_array($template_data['content'])) { + return false; + } + + // Prepare page settings + $page_settings = []; + if (isset($template_data['page_settings']) && is_array($template_data['page_settings'])) { + $page_settings = $template_data['page_settings']; + } + + // Create template post + $template_id = wp_insert_post([ + 'post_type' => 'elementor_library', + 'post_status' => 'publish', + 'post_title' => $template_title, + 'meta_input' => [ + '_elementor_data' => wp_json_encode($template_data['content']), + '_elementor_page_settings' => $page_settings, + '_elementor_template_type' => $template_data['type'] ?? 'single', + '_elementor_version' => $template_data['version'] ?? ELEMENTOR_VERSION, + '_elementor_edit_mode' => 'builder', + '_wedocs_template' => true, // Mark as weDocs template + ] + ]); + + return ($template_id && ! is_wp_error($template_id)) ? $template_id : false; + } + + /** + * Enqueue template scripts in Elementor editor + */ + public function enqueue_template_scripts() { +?> + + 'elementor_library', + 'meta_key' => '_wedocs_template', + 'meta_value' => true, + 'posts_per_page' => -1 + ]); + + foreach ($templates as $template) { + wp_delete_post($template->ID, true); + } + } + + /** + * Get template version for comparison + */ + public function get_template_version($template_name) { + $template_path = WEDOCS_PATH . '/includes/Elementor/Templates/' . $template_name . '.json'; + + if (! file_exists($template_path)) { + return false; + } + + $template_data = json_decode(file_get_contents($template_path), true); + return $template_data['version'] ?? '1.0.0'; + } } diff --git a/includes/Elementor/Templates/three_column.json b/includes/Elementor/Templates/three_column.json index 71d7c2e8..e14f9f1a 100644 --- a/includes/Elementor/Templates/three_column.json +++ b/includes/Elementor/Templates/three_column.json @@ -1 +1,176 @@ -{"content":[{"id":"66627e54","settings":{"flex_direction":"row","flex_gap":{"unit":"px","size":0,"column":"0","row":"0"},"content_width":"full","width":{"unit":"%","size":83,"sizes":[]}},"elements":[{"id":"751203","settings":{"flex_direction":"column","content_width":"full","width":{"unit":"%","size":"25"}},"elements":[{"id":"5494ee5","settings":{"search_placeholder":"Quick search...","mobile_toggle_text":"Navigation"},"elements":[],"isInner":false,"widgetType":"wedocs-docs-sidebar","elType":"widget"}],"isInner":true,"elType":"container"},{"id":"3f1364d7","settings":{"flex_direction":"column","content_width":"full","width":{"unit":"%","size":"50"}},"elements":[{"id":"11b33a2e","settings":{"content_width":"full"},"elements":[{"id":"56992cab","settings":{"__dynamic__":{"title":"[elementor-tag id=\"\" name=\"post-title\" settings=\"%7B%22before%22%3A%22%22%2C%22after%22%3A%22%22%2C%22fallback%22%3A%22%22%7D\"]"},"title":"Add Your Heading Text Here","title_color":"#142932"},"elements":[],"isInner":false,"widgetType":"theme-post-title","elType":"widget"},{"id":"62e424ef","settings":{"home_text":"Home"},"elements":[],"isInner":false,"widgetType":"wedocs-breadcrumb","elType":"widget"},{"id":"429504be","settings":[],"elements":[],"isInner":false,"widgetType":"theme-post-content","elType":"widget"},{"id":"736e93eb","settings":{"question_text":"Was this article helpful?","yes_text":"Yes","no_text":"No","show_count":"yes","thank_you_message":"Thank you for your feedback!","follow_up_placeholder":"How can we improve this article?"},"elements":[],"isInner":false,"widgetType":"wedocs-was-helpful","elType":"widget"},{"id":"360e1b81","settings":{"trigger_heading":"Need More Help?","trigger_description":"Can't find what you're looking for? Reach out to our support team.","button_text":"Contact Support","layout":"inline","modal_title":"Contact Support","modal_description":"Fill out the form below and our team will get back to you as soon as possible.","submit_text":"Send Message","success_message":"Thank you! Your message has been sent successfully.","recipient_email":"dev-email@wpengine.local","icon_color":"#364248","btn_bg_color":"#202527","btn_hover_bg_color":"#000000"},"elements":[],"isInner":false,"widgetType":"wedocs-need-help","elType":"widget"}],"isInner":true,"elType":"container"}],"isInner":true,"elType":"container"},{"id":"42bb9ff6","settings":{"flex_direction":"column","content_width":"full","width":{"unit":"%","size":"25"}},"elements":[{"id":"417d6e7f","settings":{"title":"On This Page"},"elements":[],"isInner":false,"widgetType":"wedocs-toc","elType":"widget"}],"isInner":true,"elType":"container"}],"isInner":false,"elType":"container"}],"page_settings":{"page_template":"elementor_header_footer"},"version":"0.4","title":"WeDocs Single Page","type":"single-post"} +{ + "content": [ + { + "id": "66627e54", + "settings": { + "flex_direction": "row", + "flex_gap": { + "unit": "px", + "size": 0, + "column": "0", + "row": "0" + }, + "content_width": "full", + "width": { + "unit": "%", + "size": 83, + "sizes": [] + } + }, + "elements": [ + { + "id": "751203", + "settings": { + "flex_direction": "column", + "content_width": "full", + "width": { + "unit": "%", + "size": "25" + } + }, + "elements": [ + { + "id": "5494ee5", + "settings": { + "search_placeholder": "Quick search...", + "mobile_toggle_text": "Navigation" + }, + "elements": [], + "isInner": false, + "widgetType": "wedocs-docs-sidebar", + "elType": "widget" + } + ], + "isInner": true, + "elType": "container" + }, + { + "id": "3f1364d7", + "settings": { + "flex_direction": "column", + "content_width": "full", + "width": { + "unit": "%", + "size": "50" + } + }, + "elements": [ + { + "id": "11b33a2e", + "settings": { + "content_width": "full" + }, + "elements": [ + { + "id": "56992cab", + "settings": { + "__dynamic__": { + "title": "[elementor-tag id=\"\" name=\"post-title\" settings=\"%7B%22before%22%3A%22%22%2C%22after%22%3A%22%22%2C%22fallback%22%3A%22%22%7D\"]" + }, + "title": "Add Your Heading Text Here", + "title_color": "#142932" + }, + "elements": [], + "isInner": false, + "widgetType": "theme-post-title", + "elType": "widget" + }, + { + "id": "62e424ef", + "settings": { + "home_text": "Home" + }, + "elements": [], + "isInner": false, + "widgetType": "wedocs-breadcrumb", + "elType": "widget" + }, + { + "id": "429504be", + "settings": [], + "elements": [], + "isInner": false, + "widgetType": "theme-post-content", + "elType": "widget" + }, + { + "id": "736e93eb", + "settings": { + "question_text": "Was this article helpful?", + "yes_text": "Yes", + "no_text": "No", + "show_count": "yes", + "thank_you_message": "Thank you for your feedback!", + "follow_up_placeholder": "How can we improve this article?" + }, + "elements": [], + "isInner": false, + "widgetType": "wedocs-was-helpful", + "elType": "widget" + }, + { + "id": "360e1b81", + "settings": { + "trigger_heading": "Need More Help?", + "trigger_description": "Can't find what you're looking for? Reach out to our support team.", + "button_text": "Contact Support", + "layout": "inline", + "modal_title": "Contact Support", + "modal_description": "Fill out the form below and our team will get back to you as soon as possible.", + "submit_text": "Send Message", + "success_message": "Thank you! Your message has been sent successfully.", + "recipient_email": "dev-email@wpengine.local", + "icon_color": "#364248", + "btn_bg_color": "#202527", + "btn_hover_bg_color": "#000000" + }, + "elements": [], + "isInner": false, + "widgetType": "wedocs-need-help", + "elType": "widget" + } + ], + "isInner": true, + "elType": "container" + } + ], + "isInner": true, + "elType": "container" + }, + { + "id": "42bb9ff6", + "settings": { + "flex_direction": "column", + "content_width": "full", + "width": { + "unit": "%", + "size": "25" + } + }, + "elements": [ + { + "id": "417d6e7f", + "settings": { + "title": "On This Page" + }, + "elements": [], + "isInner": false, + "widgetType": "wedocs-toc", + "elType": "widget" + } + ], + "isInner": true, + "elType": "container" + } + ], + "isInner": false, + "elType": "container" + } + ], + "page_settings": { + "page_template": "elementor_header_footer" + }, + "version": "0.4", + "title": "WeDocs Single Page", + "type": "single-post" +}