register_query_section(); $this->register_layout_section(); $this->register_content_section(); $this->register_style_card_section(); $this->register_style_content_section(); $this->register_style_pagination_section(); $this->register_style_carousel_section(); $this->eppro_register_entrance_animation_controls(); } // ── Query ───────────────────────────────────────────────────────────────── private function register_query_section(): void { $this->start_controls_section( 'section_query', [ 'label' => __( 'Query', 'admore-widgets-suite' ), ] ); $this->add_control( 'post_type', [ 'label' => __( 'Post Type', 'admore-widgets-suite' ), 'type' => Controls_Manager::SELECT, 'default' => 'post', 'options' => self::get_post_type_options(), ] ); $this->add_control( 'posts_per_page', [ 'label' => __( 'Posts Per Page', 'admore-widgets-suite' ), 'type' => Controls_Manager::NUMBER, 'default' => 6, 'min' => 1, 'max' => 50, ] ); $this->add_control( 'orderby', [ 'label' => __( 'Order By', 'admore-widgets-suite' ), 'type' => Controls_Manager::SELECT, 'default' => 'date', 'options' => [ 'date' => __( 'Date', 'admore-widgets-suite' ), 'title' => __( 'Title', 'admore-widgets-suite' ), 'rand' => __( 'Random', 'admore-widgets-suite' ), 'comment_count' => __( 'Comment Count', 'admore-widgets-suite' ), 'modified' => __( 'Last Modified', 'admore-widgets-suite' ), ], ] ); $this->add_control( 'order', [ 'label' => __( 'Order', 'admore-widgets-suite' ), 'type' => Controls_Manager::SELECT, 'default' => 'DESC', 'options' => [ 'DESC' => __( 'Descending', 'admore-widgets-suite' ), 'ASC' => __( 'Ascending', 'admore-widgets-suite' ), ], ] ); $this->add_control( 'category_filter', [ 'label' => __( 'Categories', 'admore-widgets-suite' ), 'type' => Controls_Manager::SELECT2, 'multiple' => true, 'options' => self::get_category_options(), 'description' => __( 'Leave empty to show all.', 'admore-widgets-suite' ), ] ); $this->add_control( 'tag_filter', [ 'label' => __( 'Tags', 'admore-widgets-suite' ), 'type' => Controls_Manager::SELECT2, 'multiple' => true, 'options' => self::get_tag_options(), 'description' => __( 'Leave empty to show all.', 'admore-widgets-suite' ), ] ); $this->add_control( 'exclude_ids', [ 'label' => __( 'Exclude Post IDs', 'admore-widgets-suite' ), 'type' => Controls_Manager::TEXT, 'description' => __( 'Comma-separated post IDs.', 'admore-widgets-suite' ), ] ); $this->add_control( 'offset', [ 'label' => __( 'Offset', 'admore-widgets-suite' ), 'type' => Controls_Manager::NUMBER, 'min' => 0, ] ); $this->add_control( 'sticky_posts', [ 'label' => __( 'Show Sticky Posts First', 'admore-widgets-suite' ), 'type' => Controls_Manager::SWITCHER, 'default' => '', 'return_value' => 'yes', 'separator' => 'before', 'description' => __( 'Sticky posts will appear at the top of the results.', 'admore-widgets-suite' ), ] ); $this->end_controls_section(); } // ── Layout ──────────────────────────────────────────────────────────────── private function register_layout_section(): void { $this->start_controls_section( 'section_layout', [ 'label' => __( 'Layout', 'admore-widgets-suite' ), ] ); $this->add_control( 'layout', [ 'label' => __( 'Layout', 'admore-widgets-suite' ), 'type' => Controls_Manager::SELECT, 'default' => 'grid', 'options' => [ 'grid' => __( 'Grid', 'admore-widgets-suite' ), 'masonry' => __( 'Masonry', 'admore-widgets-suite' ), 'list' => __( 'List', 'admore-widgets-suite' ), 'carousel' => __( 'Carousel', 'admore-widgets-suite' ), ], ] ); $this->add_responsive_control( 'columns', [ 'label' => __( 'Columns', 'admore-widgets-suite' ), 'type' => Controls_Manager::SELECT, 'default' => '3', 'mobile_default' => '1', 'options' => [ '1' => '1', '2' => '2', '3' => '3', '4' => '4' ], 'selectors' => [ '{{WRAPPER}} .eppro-pg-grid' => '--eppro-pg-cols: {{VALUE}};' ], 'condition' => [ 'layout!' => 'list' ], ] ); $this->add_control( 'show_filter_tabs', [ 'label' => __( 'Category Filter Tabs', 'admore-widgets-suite' ), 'type' => Controls_Manager::SWITCHER, 'default' => '', 'return_value' => 'yes', 'description' => __( 'Show AJAX-powered category filter tabs above the grid.', 'admore-widgets-suite' ), 'condition' => [ 'layout!' => [ 'list', 'carousel' ] ], 'separator' => 'before', ] ); $this->add_control( 'filter_all_text', [ 'label' => __( 'All Tab Label', 'admore-widgets-suite' ), 'type' => Controls_Manager::TEXT, 'default' => __( 'All', 'admore-widgets-suite' ), 'condition' => [ 'show_filter_tabs' => 'yes', 'layout!' => [ 'list', 'carousel' ] ], ] ); $this->add_control( 'image_hover_zoom', [ 'label' => __( 'Image Hover Zoom', 'admore-widgets-suite' ), 'type' => Controls_Manager::SWITCHER, 'default' => '', 'return_value' => 'yes', 'prefix_class' => 'eppro-pg--imgzoom-', 'separator' => 'before', 'description' => __( 'Zoom the image slightly on card hover.', 'admore-widgets-suite' ), ] ); $this->add_responsive_control( 'gap', [ 'label' => __( 'Gap', 'admore-widgets-suite' ), 'type' => Controls_Manager::SLIDER, 'size_units' => [ 'px' ], 'range' => [ 'px' => [ 'min' => 0, 'max' => 60 ] ], 'default' => [ 'size' => 24 ], 'selectors' => [ '{{WRAPPER}} .eppro-pg-grid' => 'gap: {{SIZE}}{{UNIT}};' ], ] ); $this->add_control( 'image_position', [ 'label' => __( 'Image Position', 'admore-widgets-suite' ), 'type' => Controls_Manager::SELECT, 'default' => 'top', 'options' => [ 'top' => __( 'Top', 'admore-widgets-suite' ), 'left' => __( 'Left', 'admore-widgets-suite' ), 'none' => __( 'Hidden', 'admore-widgets-suite' ), ], ] ); $this->add_group_control( Group_Control_Image_Size::get_type(), [ 'name' => 'thumbnail', 'default' => 'medium_large', 'condition' => [ 'image_position!' => 'none' ], ] ); $this->add_control( 'aspect_ratio', [ 'label' => __( 'Image Aspect Ratio', 'admore-widgets-suite' ), 'type' => Controls_Manager::SELECT, 'default' => '16/9', 'options' => [ 'auto' => __( 'Auto', 'admore-widgets-suite' ), '1/1' => '1:1', '4/3' => '4:3', '16/9' => '16:9', '3/2' => '3:2', ], 'selectors' => [ '{{WRAPPER}} .eppro-pg-thumb img' => 'aspect-ratio: {{VALUE}}; object-fit: cover;' ], 'condition' => [ 'image_position!' => 'none' ], ] ); $this->add_control( 'pagination_type', [ 'label' => __( 'Pagination Type', 'admore-widgets-suite' ), 'type' => Controls_Manager::SELECT, 'default' => 'none', 'options' => [ 'none' => __( 'None', 'admore-widgets-suite' ), 'numbers' => __( 'Page Numbers', 'admore-widgets-suite' ), 'load_more' => __( 'Load More Button', 'admore-widgets-suite' ), 'infinite_scroll' => __( 'Infinite Scroll', 'admore-widgets-suite' ), ], 'condition' => [ 'layout!' => 'carousel' ], 'separator' => 'before', ] ); $this->add_control( 'load_more_text', [ 'label' => __( 'Load More Text', 'admore-widgets-suite' ), 'type' => Controls_Manager::TEXT, 'default' => __( 'Load More Posts', 'admore-widgets-suite' ), 'condition' => [ 'layout!' => 'carousel', 'pagination_type' => [ 'load_more', 'infinite_scroll' ], ], ] ); $this->add_control( 'loading_text', [ 'label' => __( 'Loading Text', 'admore-widgets-suite' ), 'type' => Controls_Manager::TEXT, 'default' => __( 'Loading...', 'admore-widgets-suite' ), 'condition' => [ 'layout!' => 'carousel', 'pagination_type' => [ 'load_more', 'infinite_scroll' ], ], ] ); $this->add_control( 'no_more_text', [ 'label' => __( 'No More Posts Text', 'admore-widgets-suite' ), 'type' => Controls_Manager::TEXT, 'default' => __( 'No more posts to load', 'admore-widgets-suite' ), 'condition' => [ 'layout!' => 'carousel', 'pagination_type' => [ 'load_more', 'infinite_scroll' ], ], ] ); $this->add_control( 'carousel_autoplay', [ 'label' => __( 'Autoplay', 'admore-widgets-suite' ), 'type' => Controls_Manager::SWITCHER, 'default' => 'yes', 'condition' => [ 'layout' => 'carousel' ], ] ); $this->add_control( 'carousel_loop', [ 'label' => __( 'Loop', 'admore-widgets-suite' ), 'type' => Controls_Manager::SWITCHER, 'default' => 'yes', 'condition' => [ 'layout' => 'carousel' ], ] ); $this->add_control( 'carousel_arrows', [ 'label' => __( 'Arrows', 'admore-widgets-suite' ), 'type' => Controls_Manager::SWITCHER, 'default' => 'yes', 'condition' => [ 'layout' => 'carousel' ], ] ); $this->add_control( 'carousel_dots', [ 'label' => __( 'Dots', 'admore-widgets-suite' ), 'type' => Controls_Manager::SWITCHER, 'default' => 'yes', 'condition' => [ 'layout' => 'carousel' ], ] ); $this->end_controls_section(); } // ── Content Elements ────────────────────────────────────────────────────── private function register_content_section(): void { $this->start_controls_section( 'section_content_elements', [ 'label' => __( 'Content', 'admore-widgets-suite' ), ] ); $this->add_control( 'show_category', [ 'label' => __( 'Show Category Badge', 'admore-widgets-suite' ), 'type' => Controls_Manager::SWITCHER, 'default' => 'yes', 'return_value' => 'yes', ] ); $this->add_control( 'title_tag', [ 'label' => __( 'Title HTML Tag', 'admore-widgets-suite' ), 'type' => Controls_Manager::SELECT, 'default' => 'h3', 'options' => [ 'h2' => 'H2', 'h3' => 'H3', 'h4' => 'H4', 'h5' => 'H5', 'div' => 'div', ], ] ); $this->add_control( 'excerpt_length', [ 'label' => __( 'Excerpt Length (words)', 'admore-widgets-suite' ), 'type' => Controls_Manager::NUMBER, 'default' => 18, 'min' => 0, ] ); $this->add_control( 'show_author', [ 'label' => __( 'Show Author', 'admore-widgets-suite' ), 'type' => Controls_Manager::SWITCHER, 'default' => 'yes', 'return_value' => 'yes', ] ); $this->add_control( 'show_date', [ 'label' => __( 'Show Date', 'admore-widgets-suite' ), 'type' => Controls_Manager::SWITCHER, 'default' => 'yes', 'return_value' => 'yes', ] ); $this->add_control( 'date_format', [ 'label' => __( 'Date Format', 'admore-widgets-suite' ), 'type' => Controls_Manager::SELECT, 'default' => '', 'options' => [ '' => __( 'WordPress Default', 'admore-widgets-suite' ), 'F j, Y' => 'F j, Y (e.g. January 1, 2025)', 'j F Y' => 'j F Y (e.g. 1 January 2025)', 'd/m/Y' => 'd/m/Y (e.g. 01/01/2025)', 'm/d/Y' => 'm/d/Y (e.g. 01/01/2025)', 'Y-m-d' => 'Y-m-d (e.g. 2025-01-01)', 'd M Y' => 'd M Y (e.g. 01 Jan 2025)', 'M j, Y' => 'M j, Y (e.g. Jan 1, 2025)', 'd.m.Y' => 'd.m.Y (e.g. 01.01.2025)', ], 'condition' => [ 'show_date' => 'yes' ], ] ); $this->add_control( 'show_reading_time', [ 'label' => __( 'Show Reading Time', 'admore-widgets-suite' ), 'type' => Controls_Manager::SWITCHER, 'default' => '', 'return_value' => 'yes', ] ); $this->add_control( 'reading_time_wpm', [ 'label' => __( 'Words Per Minute', 'admore-widgets-suite' ), 'type' => Controls_Manager::NUMBER, 'default' => 200, 'min' => 50, 'max' => 500, 'description' => __( 'Average reading speed for time calculation.', 'admore-widgets-suite' ), 'condition' => [ 'show_reading_time' => 'yes' ], ] ); $this->add_control( 'show_comment_count', [ 'label' => __( 'Show Comment Count', 'admore-widgets-suite' ), 'type' => Controls_Manager::SWITCHER, 'default' => '', 'return_value' => 'yes', ] ); $this->add_control( 'show_read_more', [ 'label' => __( 'Read More Button', 'admore-widgets-suite' ), 'type' => Controls_Manager::SWITCHER, 'default' => 'yes', 'return_value' => 'yes', 'separator' => 'before', ] ); $this->add_control( 'read_more_text', [ 'label' => __( 'Button Text', 'admore-widgets-suite' ), 'type' => Controls_Manager::TEXT, 'default' => __( 'Read More', 'admore-widgets-suite' ), 'condition' => [ 'show_read_more' => 'yes' ], ] ); $this->add_control( 'no_posts_message', [ 'label' => __( 'No Posts Found Message', 'admore-widgets-suite' ), 'type' => Controls_Manager::TEXT, 'default' => __( 'No posts found.', 'admore-widgets-suite' ), 'separator' => 'before', 'description' => __( 'Shown on the frontend when no posts match the query.', 'admore-widgets-suite' ), 'dynamic' => [ 'active' => true ], ] ); $this->end_controls_section(); } // ── Style: Card ─────────────────────────────────────────────────────────── private function register_style_card_section(): void { $this->start_controls_section( 'style_card', [ 'label' => __( 'Card', 'admore-widgets-suite' ), 'tab' => Controls_Manager::TAB_STYLE, ] ); $this->add_control( 'card_bg', [ 'label' => __( 'Background', 'admore-widgets-suite' ), 'type' => Controls_Manager::COLOR, 'default' => '#ffffff', 'selectors' => [ '{{WRAPPER}} .eppro-pg-card' => 'background: {{VALUE}};' ], ] ); $this->add_group_control( Group_Control_Border::get_type(), [ 'name' => 'card_border', 'selector' => '{{WRAPPER}} .eppro-pg-card', ] ); $this->add_responsive_control( 'card_radius', [ 'label' => __( 'Border Radius', 'admore-widgets-suite' ), 'type' => Controls_Manager::DIMENSIONS, 'size_units' => [ 'px', '%' ], 'selectors' => [ '{{WRAPPER}} .eppro-pg-card' => 'border-radius: {{TOP}}{{UNIT}} {{RIGHT}}{{UNIT}} {{BOTTOM}}{{UNIT}} {{LEFT}}{{UNIT}};' ], ] ); $this->add_group_control( Group_Control_Box_Shadow::get_type(), [ 'name' => 'card_shadow', 'selector' => '{{WRAPPER}} .eppro-pg-card', ] ); $this->add_control( 'card_hover_shadow_heading', [ 'label' => __( 'Hover', 'admore-widgets-suite' ), 'type' => Controls_Manager::HEADING, 'separator' => 'before', ] ); $this->add_group_control( Group_Control_Box_Shadow::get_type(), [ 'name' => 'card_hover_shadow', 'label' => __( 'Hover Shadow', 'admore-widgets-suite' ), 'selector' => '{{WRAPPER}} .eppro-pg-card:hover', ] ); $this->add_control( 'card_hover_lift', [ 'label' => __( 'Lift on Hover', 'admore-widgets-suite' ), 'type' => Controls_Manager::SLIDER, 'size_units' => [ 'px' ], 'range' => [ 'px' => [ 'min' => 0, 'max' => 20 ] ], 'default' => [ 'size' => 4 ], 'selectors' => [ '{{WRAPPER}} .eppro-pg-card:hover' => 'transform: translateY(-{{SIZE}}{{UNIT}});' ], ] ); $this->add_control( 'card_hover_bg', [ 'label' => __( 'Hover Background', 'admore-widgets-suite' ), 'type' => Controls_Manager::COLOR, 'selectors' => [ '{{WRAPPER}} .eppro-pg-card:hover' => 'background: {{VALUE}};' ], ] ); $this->add_control( 'image_overlay_color', [ 'label' => __( 'Image Hover Overlay', 'admore-widgets-suite' ), 'separator' => 'before', 'type' => Controls_Manager::COLOR, 'selectors' => [ '{{WRAPPER}} .eppro-pg-thumb::after' => 'content:""; position:absolute; inset:0; background:{{VALUE}}; opacity:0; transition:opacity .3s; pointer-events:none;', '{{WRAPPER}} .eppro-pg-card:hover .eppro-pg-thumb::after' => 'opacity:1;', ], ] ); $this->end_controls_section(); } // ── Style: Content ──────────────────────────────────────────────────────── private function register_style_content_section(): void { $this->start_controls_section( 'style_content', [ 'label' => __( 'Content', 'admore-widgets-suite' ), 'tab' => Controls_Manager::TAB_STYLE, ] ); $this->add_responsive_control( 'content_padding', [ 'label' => __( 'Content Padding', 'admore-widgets-suite' ), 'type' => Controls_Manager::DIMENSIONS, 'size_units' => [ 'px', 'em' ], 'default' => [ 'top' => '20', 'right' => '20', 'bottom' => '20', 'left' => '20', 'unit' => 'px', 'isLinked' => true ], 'selectors' => [ '{{WRAPPER}} .eppro-pg-body' => 'padding: {{TOP}}{{UNIT}} {{RIGHT}}{{UNIT}} {{BOTTOM}}{{UNIT}} {{LEFT}}{{UNIT}};' ], ] ); $this->add_group_control( Group_Control_Typography::get_type(), [ 'name' => 'title_typography', 'label' => __( 'Title', 'admore-widgets-suite' ), 'selector' => '{{WRAPPER}} .eppro-pg-title', ] ); $this->add_control( 'title_color', [ 'label' => __( 'Title Color', 'admore-widgets-suite' ), 'type' => Controls_Manager::COLOR, 'selectors' => [ '{{WRAPPER}} .eppro-pg-title a' => 'color: {{VALUE}};' ], ] ); $this->add_control( 'title_hover_color', [ 'label' => __( 'Title Hover Color', 'admore-widgets-suite' ), 'type' => Controls_Manager::COLOR, 'selectors' => [ '{{WRAPPER}} .eppro-pg-title a:hover' => 'color: {{VALUE}};' ], ] ); $this->add_group_control( Group_Control_Typography::get_type(), [ 'name' => 'excerpt_typography', 'label' => __( 'Excerpt', 'admore-widgets-suite' ), 'selector' => '{{WRAPPER}} .eppro-pg-excerpt', 'separator' => 'before', ] ); $this->add_control( 'excerpt_color', [ 'label' => __( 'Excerpt Color', 'admore-widgets-suite' ), 'type' => Controls_Manager::COLOR, 'selectors' => [ '{{WRAPPER}} .eppro-pg-excerpt' => 'color: {{VALUE}};' ], ] ); $this->add_control( 'meta_color', [ 'label' => __( 'Meta Color', 'admore-widgets-suite' ), 'type' => Controls_Manager::COLOR, 'selectors' => [ '{{WRAPPER}} .eppro-pg-meta' => 'color: {{VALUE}};' ], 'separator' => 'before', ] ); $this->add_control( 'badge_bg', [ 'label' => __( 'Category Badge Background', 'admore-widgets-suite' ), 'type' => Controls_Manager::COLOR, 'default' => '#7c3aed', 'selectors' => [ '{{WRAPPER}} .eppro-pg-badge' => 'background: {{VALUE}};' ], 'separator' => 'before', ] ); $this->add_control( 'badge_color', [ 'label' => __( 'Category Badge Color', 'admore-widgets-suite' ), 'type' => Controls_Manager::COLOR, 'default' => '#ffffff', 'selectors' => [ '{{WRAPPER}} .eppro-pg-badge' => 'color: {{VALUE}};' ], ] ); $this->add_group_control( Group_Control_Typography::get_type(), [ 'name' => 'meta_typography', 'label' => __( 'Meta', 'admore-widgets-suite' ), 'selector' => '{{WRAPPER}} .eppro-pg-meta', 'separator' => 'before', ] ); $this->add_responsive_control( 'badge_radius', [ 'label' => __( 'Badge Border Radius', 'admore-widgets-suite' ), 'type' => Controls_Manager::SLIDER, 'size_units' => [ 'px' ], 'range' => [ 'px' => [ 'min' => 0, 'max' => 30 ] ], 'default' => [ 'size' => 4 ], 'selectors' => [ '{{WRAPPER}} .eppro-pg-badge' => 'border-radius: {{SIZE}}{{UNIT}};' ], 'separator' => 'before', ] ); $this->add_control( 'readmore_heading', [ 'label' => __( 'Read More', 'admore-widgets-suite' ), 'type' => Controls_Manager::HEADING, 'separator' => 'before', 'condition' => [ 'show_read_more' => 'yes' ], ] ); $this->add_control( 'readmore_color', [ 'label' => __( 'Color', 'admore-widgets-suite' ), 'type' => Controls_Manager::COLOR, 'default' => '#7c3aed', 'selectors' => [ '{{WRAPPER}} .eppro-pg-readmore' => 'color: {{VALUE}};' ], 'condition' => [ 'show_read_more' => 'yes' ], ] ); $this->add_control( 'readmore_hover_color', [ 'label' => __( 'Hover Color', 'admore-widgets-suite' ), 'type' => Controls_Manager::COLOR, 'selectors' => [ '{{WRAPPER}} .eppro-pg-readmore:hover' => 'color: {{VALUE}};' ], 'condition' => [ 'show_read_more' => 'yes' ], ] ); $this->add_group_control( Group_Control_Typography::get_type(), [ 'name' => 'readmore_typography', 'label' => __( 'Typography', 'admore-widgets-suite' ), 'selector' => '{{WRAPPER}} .eppro-pg-readmore', 'condition' => [ 'show_read_more' => 'yes' ], ] ); $this->end_controls_section(); } // ── Style: Pagination ───────────────────────────────────────────────────── private function register_style_pagination_section(): void { $this->start_controls_section( 'style_pagination', [ 'label' => __( 'Pagination', 'admore-widgets-suite' ), 'tab' => Controls_Manager::TAB_STYLE, 'condition' => [ 'pagination_type!' => [ 'none', '' ], 'layout!' => 'carousel' ], ] ); $this->add_control( 'pagination_color', [ 'label' => __( 'Color', 'admore-widgets-suite' ), 'type' => Controls_Manager::COLOR, 'selectors' => [ '{{WRAPPER}} .eppro-pg-pagination a' => 'color: {{VALUE}};' ], ] ); $this->add_control( 'pagination_active_color', [ 'label' => __( 'Active Color', 'admore-widgets-suite' ), 'type' => Controls_Manager::COLOR, 'default' => '#7c3aed', 'selectors' => [ '{{WRAPPER}} .eppro-pg-pagination .current' => 'background: {{VALUE}}; color: #fff;', ], ] ); $this->add_control( 'loadmore_heading', [ 'label' => __( 'Load More Button', 'admore-widgets-suite' ), 'type' => Controls_Manager::HEADING, 'separator' => 'before', 'condition' => [ 'pagination_type' => 'load_more' ], ] ); $this->add_control( 'loadmore_bg', [ 'label' => __( 'Background', 'admore-widgets-suite' ), 'type' => Controls_Manager::COLOR, 'default' => '#7c3aed', 'selectors' => [ '{{WRAPPER}} .eppro-pg-load-more' => 'background-color: {{VALUE}};' ], 'condition' => [ 'pagination_type' => 'load_more' ], ] ); $this->add_control( 'loadmore_color', [ 'label' => __( 'Text Color', 'admore-widgets-suite' ), 'type' => Controls_Manager::COLOR, 'default' => '#ffffff', 'selectors' => [ '{{WRAPPER}} .eppro-pg-load-more' => 'color: {{VALUE}};' ], 'condition' => [ 'pagination_type' => 'load_more' ], ] ); $this->add_control( 'loadmore_hover_bg', [ 'label' => __( 'Hover Background', 'admore-widgets-suite' ), 'type' => Controls_Manager::COLOR, 'selectors' => [ '{{WRAPPER}} .eppro-pg-load-more:hover' => 'background-color: {{VALUE}};' ], 'condition' => [ 'pagination_type' => 'load_more' ], ] ); $this->add_group_control( Group_Control_Typography::get_type(), [ 'name' => 'loadmore_typography', 'selector' => '{{WRAPPER}} .eppro-pg-load-more', 'condition' => [ 'pagination_type' => 'load_more' ], ] ); $this->add_responsive_control( 'loadmore_padding', [ 'label' => __( 'Padding', 'admore-widgets-suite' ), 'type' => Controls_Manager::DIMENSIONS, 'size_units' => [ 'px', 'em' ], 'selectors' => [ '{{WRAPPER}} .eppro-pg-load-more' => 'padding: {{TOP}}{{UNIT}} {{RIGHT}}{{UNIT}} {{BOTTOM}}{{UNIT}} {{LEFT}}{{UNIT}};' ], 'condition' => [ 'pagination_type' => 'load_more' ], ] ); $this->add_control( 'loadmore_radius', [ 'label' => __( 'Border Radius', 'admore-widgets-suite' ), 'type' => Controls_Manager::SLIDER, 'size_units' => [ 'px' ], 'default' => [ 'size' => 6 ], 'selectors' => [ '{{WRAPPER}} .eppro-pg-load-more' => 'border-radius: {{SIZE}}{{UNIT}};' ], 'condition' => [ 'pagination_type' => 'load_more' ], ] ); $this->end_controls_section(); } // ── Style: Carousel navigation ─────────────────────────────────────────── private function register_style_carousel_section(): void { $this->start_controls_section( 'style_carousel_nav', [ 'label' => __( 'Carousel Navigation', 'admore-widgets-suite' ), 'tab' => Controls_Manager::TAB_STYLE, 'condition' => [ 'layout' => 'carousel' ], ] ); $this->add_control( 'carousel_arrow_size', [ 'label' => __( 'Arrow Size', 'admore-widgets-suite' ), 'type' => Controls_Manager::SLIDER, 'size_units' => [ 'px' ], 'range' => [ 'px' => [ 'min' => 24, 'max' => 72 ] ], 'selectors' => [ '{{WRAPPER}} .eppro-pg-wrap .swiper-button-prev, {{WRAPPER}} .eppro-pg-wrap .swiper-button-next' => 'width: {{SIZE}}{{UNIT}}; height: {{SIZE}}{{UNIT}}; margin-top: calc({{SIZE}}{{UNIT}} / -2);', ], 'condition' => [ 'carousel_arrows' => 'yes' ], ] ); $this->start_controls_tabs( 'carousel_arrow_tabs', [ 'condition' => [ 'carousel_arrows' => 'yes' ] ] ); $this->start_controls_tab( 'carousel_arrow_normal', [ 'label' => __( 'Normal', 'admore-widgets-suite' ) ] ); $this->add_control( 'carousel_arrow_color', [ 'label' => __( 'Arrow Color', 'admore-widgets-suite' ), 'type' => Controls_Manager::COLOR, 'selectors' => [ '{{WRAPPER}} .eppro-pg-wrap .swiper-button-prev, {{WRAPPER}} .eppro-pg-wrap .swiper-button-next' => 'color: {{VALUE}};' ], ] ); $this->add_control( 'carousel_arrow_bg', [ 'label' => __( 'Background', 'admore-widgets-suite' ), 'type' => Controls_Manager::COLOR, 'selectors' => [ '{{WRAPPER}} .eppro-pg-wrap .swiper-button-prev, {{WRAPPER}} .eppro-pg-wrap .swiper-button-next' => 'background-color: {{VALUE}};' ], ] ); $this->add_group_control( Group_Control_Box_Shadow::get_type(), [ 'name' => 'carousel_arrow_shadow', 'selector' => '{{WRAPPER}} .eppro-pg-wrap .swiper-button-prev, {{WRAPPER}} .eppro-pg-wrap .swiper-button-next', ] ); $this->end_controls_tab(); $this->start_controls_tab( 'carousel_arrow_hover', [ 'label' => __( 'Hover', 'admore-widgets-suite' ) ] ); $this->add_control( 'carousel_arrow_color_hover', [ 'label' => __( 'Arrow Color', 'admore-widgets-suite' ), 'type' => Controls_Manager::COLOR, 'selectors' => [ '{{WRAPPER}} .eppro-pg-wrap .swiper-button-prev:hover, {{WRAPPER}} .eppro-pg-wrap .swiper-button-next:hover' => 'color: {{VALUE}};' ], ] ); $this->add_control( 'carousel_arrow_bg_hover', [ 'label' => __( 'Background', 'admore-widgets-suite' ), 'type' => Controls_Manager::COLOR, 'selectors' => [ '{{WRAPPER}} .eppro-pg-wrap .swiper-button-prev:hover, {{WRAPPER}} .eppro-pg-wrap .swiper-button-next:hover' => 'background-color: {{VALUE}};' ], ] ); $this->add_group_control( Group_Control_Box_Shadow::get_type(), [ 'name' => 'carousel_arrow_shadow_hover', 'selector' => '{{WRAPPER}} .eppro-pg-wrap .swiper-button-prev:hover, {{WRAPPER}} .eppro-pg-wrap .swiper-button-next:hover', ] ); $this->end_controls_tab(); $this->end_controls_tabs(); $this->add_control( 'carousel_dot_color', [ 'label' => __( 'Dot Color', 'admore-widgets-suite' ), 'type' => Controls_Manager::COLOR, 'separator' => 'before', 'selectors' => [ '{{WRAPPER}} .eppro-pg-wrap .swiper-pagination-bullet' => 'background-color: {{VALUE}};' ], 'condition' => [ 'carousel_dots' => 'yes' ], ] ); $this->add_control( 'carousel_dot_active_color', [ 'label' => __( 'Active Dot Color', 'admore-widgets-suite' ), 'type' => Controls_Manager::COLOR, 'selectors' => [ '{{WRAPPER}} .eppro-pg-wrap .swiper-pagination-bullet-active' => 'background-color: {{VALUE}};' ], 'condition' => [ 'carousel_dots' => 'yes' ], ] ); $this->end_controls_section(); } // ========================================================================= // Query & card markup — shared by render() and the Load More / Infinite // Scroll AJAX handler, so appended posts look exactly like the first page. // ========================================================================= /** Order-by values accepted from the "Order By" control. */ private const ORDERBY = [ 'date', 'title', 'rand', 'comment_count', 'modified', 'menu_order', 'name', 'author' ]; /** * WP_Query arguments for one page of this widget. * * @param array $s Widget settings (get_settings_for_display()). * @param int $paged 1-based page number. * @param int[] $exclude Extra post IDs to skip (random order "load more"). */ private function get_query_args( array $s, int $paged = 1, array $exclude = [] ): array { $post_type = sanitize_key( $s['post_type'] ?? 'post' ); if ( ! in_array( $post_type, get_post_types( [ 'public' => true ], 'names' ), true ) ) { $post_type = 'post'; } $orderby = sanitize_key( $s['orderby'] ?? 'date' ); if ( ! in_array( $orderby, self::ORDERBY, true ) ) { $orderby = 'date'; } $per_page = max( 1, min( 100, absint( $s['posts_per_page'] ?? 6 ) ?: 6 ) ); $paged = max( 1, $paged ); $args = [ 'post_type' => $post_type, 'posts_per_page' => $per_page, 'orderby' => $orderby, 'order' => 'ASC' === ( $s['order'] ?? 'DESC' ) ? 'ASC' : 'DESC', 'paged' => $paged, 'post_status' => 'publish', ]; if ( ! empty( $s['category_filter'] ) ) { $args['category__in'] = array_values( array_filter( array_map( 'absint', (array) $s['category_filter'] ) ) ); } if ( ! empty( $s['tag_filter'] ) ) { $args['tag__in'] = array_values( array_filter( array_map( 'absint', (array) $s['tag_filter'] ) ) ); } $not_in = ! empty( $s['exclude_ids'] ) ? array_map( 'absint', explode( ',', (string) $s['exclude_ids'] ) ) : []; $not_in = array_values( array_unique( array_filter( array_merge( $not_in, array_map( 'absint', $exclude ) ) ) ) ); if ( $not_in ) { $args['post__not_in'] = $not_in; } if ( ! empty( $s['offset'] ) ) { // WordPress ignores "paged" when "offset" is set, so page manually. $args['offset'] = absint( $s['offset'] ) + ( ( $paged - 1 ) * $per_page ); } if ( 'yes' !== ( $s['sticky_posts'] ?? '' ) ) { $args['ignore_sticky_posts'] = true; } return $args; } /** Display options for one card, derived from the widget settings. */ private function get_card_options( array $s ): array { $img_pos = in_array( $s['image_position'] ?? 'top', [ 'top', 'left', 'none' ], true ) ? $s['image_position'] : 'top'; $title_tag = in_array( $s['title_tag'] ?? 'h3', [ 'h2', 'h3', 'h4', 'h5', 'div' ], true ) ? $s['title_tag'] : 'h3'; return [ 'img_pos' => $img_pos, 'img_size' => sanitize_text_field( (string) ( $s['thumbnail_size'] ?? 'medium_large' ) ) ?: 'medium_large', 'title_tag' => $title_tag, 'excerpt_len' => absint( $s['excerpt_length'] ?? 18 ), 'show_cat' => 'yes' === ( $s['show_category'] ?? 'yes' ), 'show_author' => 'yes' === ( $s['show_author'] ?? 'yes' ), 'show_date' => 'yes' === ( $s['show_date'] ?? 'yes' ), 'date_format' => (string) ( $s['date_format'] ?? '' ), 'show_reading_time' => 'yes' === ( $s['show_reading_time'] ?? '' ), 'reading_time_wpm' => absint( $s['reading_time_wpm'] ?? 200 ) ?: 200, 'show_comments' => 'yes' === ( $s['show_comment_count'] ?? '' ), 'show_rm' => 'yes' === ( $s['show_read_more'] ?? '' ), 'rm_text' => (string) ( $s['read_more_text'] ?? __( 'Read More', 'admore-widgets-suite' ) ), ]; } /** Print the card for the current post in the loop. */ private function render_card( array $o, bool $is_carousel = false ): void { $thumb_html = ''; if ( 'none' !== $o['img_pos'] && has_post_thumbnail() ) { $thumb_html = get_the_post_thumbnail( get_the_ID(), $o['img_size'], [ 'class' => 'eppro-pg-img', 'loading' => 'lazy' ] ); } $categories = get_the_category(); $cat_name = ! empty( $categories ) ? $categories[0]->name : ''; $cat_slugs = wp_list_pluck( $categories, 'slug' ); $title_tag = $o['title_tag']; ?>
get_settings_for_display(); $random = 'rand' === ( $s['orderby'] ?? '' ); $args = $random ? $this->get_query_args( $s, 1, $loaded ) : $this->get_query_args( $s, $page ); $query = new \WP_Query( $args ); $o = $this->get_card_options( $s ); ob_start(); while ( $query->have_posts() ) { $query->the_post(); $this->render_card( $o ); } wp_reset_postdata(); $html = (string) ob_get_clean(); $has_more = $random ? (int) $query->found_posts > (int) $query->post_count : $page < (int) $query->max_num_pages; return [ 'html' => $html, 'has_more' => $has_more && $query->post_count > 0 ]; } // ========================================================================= // Render // ========================================================================= protected function render(): void { $s = $this->get_settings_for_display(); $layout = in_array( $s['layout'] ?? 'grid', [ 'grid', 'masonry', 'list', 'carousel' ], true ) ? $s['layout'] : 'grid'; $cols = max( 1, min( 6, intval( $s['columns'] ?? 3 ) ) ); $pagination_type = $s['pagination_type'] ?? 'none'; $is_carousel = 'carousel' === $layout; $pagination = 'numbers' === $pagination_type && ! $is_carousel; $ajax_paging = in_array( $pagination_type, [ 'load_more', 'infinite_scroll' ], true ) && ! $is_carousel; $paged = $pagination ? max( 1, (int) get_query_var( 'paged' ), (int) get_query_var( 'page' ) ) : 1; $query = new \WP_Query( $this->get_query_args( $s, $paged ) ); if ( ! $query->have_posts() ) { if ( \Elementor\Plugin::$instance->editor->is_edit_mode() ) { echo '' . esc_html__( 'Post Grid', 'admore-widgets-suite' ) . '
' . esc_html__( 'No posts found. Adjust the query settings.', 'admore-widgets-suite' ) . '
' . esc_html( $no_posts_msg ) . '
'; } } return; } $o = $this->get_card_options( $s ); $wrap_class = 'eppro-pg-wrap eppro-pg-layout-' . $layout; if ( 'yes' === ( $s['image_hover_zoom'] ?? '' ) ) { $wrap_class .= ' eppro-pg--imgzoom-yes'; } // Desktop column count as a fallback on the wrapper; the responsive // "Columns" control sets the value per device on the grid itself. $wrap_style = ( 'list' !== $layout && ! $is_carousel ) ? '--eppro-pg-cols:' . $cols . ';' : ''; $show_filter = 'yes' === ( $s['show_filter_tabs'] ?? '' ) && in_array( $layout, [ 'grid', 'masonry' ], true ); $filter_all = $s['filter_all_text'] ?? __( 'All', 'admore-widgets-suite' ); ?>