Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(pagination): add new pagination component #106

Merged
merged 34 commits into from
Dec 31, 2024

Conversation

bence444
Copy link
Contributor

@bence444 bence444 commented Dec 19, 2024

PR Checklist

Please check if your PR fulfills the following requirements:

  • Docs have been added/updated (for bug fixes/features)

PR Type

What kind of change does this PR introduce?

  • Bugfix
  • Feature
  • Code style update (formatting, local variables)
  • Refactoring (no functional changes, no API changes)
  • Build related changes
  • CI-related changes
  • Documentation content changes
  • Other... Please describe:

Issue Number

Issue Number: N/A

Does this PR introduce a breaking change?

  • Yes
  • No

Other information

Remaining works to do:

  • fix icons in first/last and prev/next button
  • possibility to use custom icons, like in accordion ([Feature] {Accordion} - Possibility to change icon #95)
  • possibility to customize buttons' label + internalization
  • implement different size variables
  • remove duplications from libs/flowbite-angular/core/flowbite.theme.init.ts
  • remove unused pageChange output
  • create InjectionTokens for properties (tabs, pageSize, etc..)
  • use a cleaner way to customize PaginationButtonDirective (big thanks @MGREMY )
  • requested changes

Summary by CodeRabbit

Summary by CodeRabbit

Release Notes: Flowbite Angular Pagination Component

  • New Features

    • Introduced multiple Pagination components with various configurations, including default, custom, and text navigation modes.
    • Added support for customizable pagination styles and attributes such as current page, total items, and page size.
    • Expanded the available SVG icons for navigation.
  • Documentation

    • Updated documentation with comprehensive examples for different pagination styles and configurations.
    • Added compatibility information for library versions with Angular and TailwindCSS.
  • Improvements

    • Enhanced theming capabilities for pagination components.
    • Improved error handling for page navigation controls.

…ular into pagination

# Conflicts:
#	libs/flowbite-angular/core/flowbite.theme.init.ts
#	libs/flowbite-angular/pagination/index.ts
#	libs/flowbite-angular/pagination/pagination.component.ts
#	libs/flowbite-angular/pagination/pagination.theme.service.ts
#	libs/flowbite-angular/pagination/pagination.theme.ts
# Conflicts:
#	libs/flowbite-angular/core/flowbite.theme.init.ts
#	libs/flowbite-angular/pagination/index.ts
#	libs/flowbite-angular/pagination/pagination.component.ts
#	libs/flowbite-angular/pagination/pagination.theme.service.ts
#	libs/flowbite-angular/pagination/pagination.theme.ts
…ular into pagination

# Conflicts:
#	libs/flowbite-angular/core/flowbite.theme.init.ts
Copy link

vercel bot commented Dec 19, 2024

The latest updates on your projects. Learn more about Vercel for Git ↗︎

Name Status Preview Comments Updated (UTC)
flowbite-angular ✅ Ready (Inspect) Visit Preview 💬 Add feedback Dec 31, 2024 0:38am

Copy link
Contributor

coderabbitai bot commented Dec 19, 2024

Walkthrough

This pull request introduces a comprehensive pagination component to the Flowbite Angular library. The implementation includes a new secondary entry point for pagination, with extensive customization options, theming capabilities, and documentation. The changes span multiple files across documentation, component implementation, and configuration, adding robust pagination functionality with support for various navigation styles, custom theming, and flexible page management.

Changes

File Path Change Summary
apps/docs/docs/components/pagination/* Added multiple component files (HTML/TS) demonstrating different pagination styles: default, text, both navigation, and custom pagination.
libs/flowbite-angular/pagination/* Introduced new pagination module with component, theme service, and configuration files.
libs/flowbite-angular/core/flowbite.theme.init.ts Added pagination-related service providers and theme configurations.
tsconfig.base.json Added path mapping for flowbite-angular/pagination.

Possibly related PRs

  • feat(badge): add bordered badge #100: The changes in this PR introduce a new bordered badge component, which is related to the <flowbite-pagination> component added in the main PR as both involve enhancements to UI components within the Flowbite Angular library.
  • feat(badge): add dismissable badge #101: This PR adds a dismissable badge feature, which is also a component enhancement similar to the pagination component introduced in the main PR, focusing on improving user interface elements.

Suggested reviewers

  • MGREMY

Poem

🐰 Hopping through pages with glee,
Pagination's magic, now set free!
Buttons dance, numbers align,
A rabbit's dream of design divine!
Flowbite's newest feature takes flight! 🚀

Tip

CodeRabbit's docstrings feature is now available as part of our Early Access Program! Simply use the command @coderabbitai generate docstrings to have CodeRabbit automatically generate docstrings for your pull request. We would love to hear your feedback on Discord.


Thank you for using CodeRabbit. We offer it for free to the OSS community and would appreciate your support in helping us grow. If you find it useful, would you consider giving us a shout-out on your favorite social media?

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Generate unit testing code for this file.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai generate unit testing code for this file.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and generate unit testing code.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR. (Beta)
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 15

🧹 Nitpick comments (20)
libs/flowbite-angular/pagination/pagination.component.ts (1)

27-36: Consider allowing consumers to override the default pagination style more granularly.
Currently, the entire pagination theme custom style is treated as a single object. It may be beneficial to allow partial overrides at the level of specific pagination elements (e.g., first/last buttons, page tabs), so consumers can fine-tune each element.

apps/docs/docs/components/pagination/_both.component.html (1)

1-4: Ensure support for customizable labels in 'both' mode.
The component currently uses a fixed “First/Last” or “Previous/Next” text alongside icons. If this is intended to support multiple languages or dynamic text, add input properties, e.g., “previousLabel,” “nextLabel,” etc.

apps/docs/docs/components/pagination/_text.component.html (1)

1-4: Add dynamic data binding for the initial page or total items.
Currently, both “currentPage” and “totalItems” are hard-coded. If you plan to demonstrate changing pagination states in this example, consider binding them to component properties (e.g., [currentPage]="myPageVar") for clarity and future extensibility.

apps/docs/docs/components/pagination/_both.component.ts (1)

5-10: Consider adding component documentation and type safety

While the component structure is correct, consider these improvements:

  1. Add JSDoc comments to document the component's purpose and usage
  2. Consider implementing OnInit if initialization logic will be needed
  3. Add strict typing by enabling strict: true in your component metadata
+/**
+ * Demonstrates pagination component with both text and icon navigation
+ */
 @Component({
   selector: 'flowbite-demo-pagination-both',
   imports: [PaginationComponent],
   templateUrl: './_both.component.html',
+  standalone: true,
 })
-export class FlowbiteBothComponent {}
+export class FlowbiteBothComponent implements OnInit {
+  ngOnInit(): void {
+    // Add initialization logic here
+  }
+}
apps/docs/docs/components/pagination/_custom.component.ts (1)

5-10: Consider creating a base demo component

Given the similar structure across demo components, consider:

  1. Creating a base demo component or abstract class
  2. Adding component documentation
  3. Including example code in the component itself
+/**
+ * Demonstrates pagination component with custom styling
+ * @example
+ * <flowbite-demo-pagination-custom>
+ *   <!-- Add example usage here -->
+ * </flowbite-demo-pagination-custom>
+ */
 @Component({
   selector: 'flowbite-demo-pagination-custom',
   imports: [PaginationComponent],
   templateUrl: './_custom.component.html',
+  standalone: true,
 })
-export class FlowbiteCustomComponent {}
+export class FlowbiteCustomComponent extends BasePaginationDemo {
+  // Implement custom styling logic
+}
apps/docs/docs/components/pagination/_custom.component.html (1)

5-5: Document the firstLast property behavior.

Consider adding a comment explaining that [firstLast]="false" hides the first/last page buttons, as this might not be immediately obvious to users.

apps/docs/docs/components/pagination/ng-doc.page.ts (1)

9-20: Enhance documentation metadata.

Consider adding a description and tags to improve documentation searchability and organization.

 const pagination: NgDocPage = {
   title: 'Pagination',
   mdFile: './index.md',
   category: ComponentCategory,
   order: 10,
+  description: 'Pagination component for navigating through multiple pages of content',
+  tags: ['navigation', 'pagination', 'components'],
   demos: {
     flowbiteDefaultComponent: FlowbiteDefaultComponent,
     flowbiteTextComponent: FlowbiteTextComponent,
     flowbiteBothComponent: FlowbiteBothComponent,
     flowbiteCustomComponent: FlowbiteCustomComponent,
   },
 };
libs/flowbite-angular/pagination/index.ts (1)

1-1: Overall PR Assessment

The pagination component implementation is progressing well, but several items from the PR objectives need attention:

  1. Icons for navigation buttons are still pending
  2. Internationalization support needs to be implemented
  3. Size variants should be added as suggested above

The code structure and organization are solid, with good attention to theming and customization. Consider addressing the suggested improvements before finalizing the PR.

libs/flowbite-angular/pagination/pagination.theme.ts (2)

20-22: Fix incorrect JSDoc comment

The JSDoc comment references NavbarComponent instead of PaginationComponent.

- * Theme definition for `NavbarComponent`
+ * Theme definition for `PaginationComponent`

35-42: Consider adding theme properties for different sizes

The PR objectives mention implementing "different size variables for the pagination component". The current theme structure doesn't include size-related properties.

Consider extending the theme to include size variants:

export interface PaginationTheme {
  root: {
    base: string;
    sizes: {
      sm: string;
      md: string;
      lg: string;
    };
  };
  // ... existing properties
}
libs/flowbite-angular/pagination/pagination.theme.service.ts (1)

27-36: LGTM! Consider adding input validation

The implementation correctly merges themes and processes classes. However, consider adding validation for the properties parameter.

 public getClasses(properties: PaginationProperties): PaginationClass {
+    if (!properties?.customStyle) {
+      return {
+        rootClass: twMerge(this.baseTheme.root.base),
+        navigationClass: twMerge(this.baseTheme.navigation.base),
+      };
+    }
     const theme: PaginationTheme = mergeTheme(this.baseTheme, properties.customStyle);
     // ... rest of the implementation
apps/docs/docs/components/pagination/index.md (1)

29-29: Fix grammatical issue in section title

Change "Pagination with text and icon" to "Pagination with text and icons" for correct grammatical number.

🧰 Tools
🪛 LanguageTool

[uncategorized] ~29-~29: The grammatical number of this noun doesn’t look right. Consider replacing it.
Context: ...ript" ``` ## Pagination with text and icon {{ NgDocActions.demo('flowbiteBothComp...

(AI_EN_LECTOR_REPLACEMENT_NOUN_NUMBER)

libs/flowbite-angular/pagination/pagination-button.theme.service.ts (1)

33-41: Consider adding type safety for custom styles

The mergeTheme operation could benefit from additional type checking for custom styles.

  public getClasses(properties: PaginationButtonProperties): PaginationButtonClass {
+   if (!properties?.customStyle) {
+     properties = { ...properties, customStyle: {} };
+   }
    const theme: PaginationButtonTheme = mergeTheme(this.baseTheme, properties.customStyle);

    const output: PaginationButtonClass = {
      rootClass: twMerge(theme.root.base, theme.root.active[properties.active]),
    };

    return output;
  }
libs/flowbite-angular/pagination/pagination-button.theme.ts (2)

27-28: Consider adding hover state handling for disabled buttons

The base class includes hover states, but there's no specific handling for disabled buttons which could lead to inconsistent UX.

  base: 'flex items-center justify-center px-3 h-8 ms-0 leading-tight text-gray-500 bg-white border border-e-0 border-gray-300 hover:bg-gray-100 hover:text-gray-700 dark:bg-gray-800 dark:border-gray-700 dark:text-gray-400 dark:hover:bg-gray-700 dark:hover:text-white first:rounded-l-lg last:rounded-r-lg',
+ disabled: 'cursor-not-allowed opacity-50 hover:bg-white hover:text-gray-500 dark:hover:bg-gray-800 dark:hover:text-gray-400',

15-20: Add size variants to theme interface

As mentioned in the PR objectives, size variants are planned. Consider adding the interface structure now.

 export interface PaginationButtonTheme {
   root: {
     base: string;
     active: FlowbiteBoolean;
+    size: {
+      small: string;
+      default: string;
+      large: string;
+    };
   };
 }
apps/docs/docs/ng-doc.api.ts (1)

Line range hint 1-1: Consider implementing remaining features using separate services

Based on the PR objectives, several features are still pending. Consider the following architectural approaches:

  1. For icon customization:

    • Create an IconConfigService to manage icon configurations
    • Use dependency injection to allow icon overrides
  2. For i18n support:

    • Implement an abstract PaginationI18nService
    • Use Angular's i18n infrastructure or a translation library
  3. For size variants:

    • Add size enum and interface
    • Implement size-specific styles in theme

Would you like assistance in implementing any of these features?

libs/flowbite-angular/pagination/pagination-button.directive.ts (2)

32-35: Enhance documentation for themeService

The documentation comment could be more descriptive about the service's purpose and usage.

-  /**
-   * Service injected used to generate class
-   */
+  /**
+   * Theme service responsible for generating CSS classes based on button state and custom styles.
+   * Injected automatically through DI.
+   */

27-31: Consider i18n preparation for button labels

Since internationalization support is in the PR's pending tasks, consider adding an input for customizable button labels that can be translated:

// Future enhancement suggestion:
@Input() ariaLabel?: string;
@Input() buttonText?: string;

This would support the pending task of "adding the ability to customize button labels and support for internationalization" mentioned in the PR objectives.

apps/docs/docs/components/pagination/_default.component.ts (2)

21-23: Enhance test data generation

The current implementation uses repetitive data. Consider adding more realistic and varied test data.

-      this._testDatas.push({ id: i, name: 'John Doe' });
+      this._testDatas.push({ 
+        id: i, 
+        name: `User ${i}`,
+      });

4-4: Add missing tests

The PR objectives indicate that tests haven't been specified yet.

Would you like me to help generate unit tests for this component? The tests should cover:

  • Page change handling
  • Edge cases (first/last page)
  • Error scenarios
📜 Review details

Configuration used: .coderabbit.yaml
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between dca933a and cbaf247.

📒 Files selected for processing (22)
  • apps/docs/docs/components/pagination/_both.component.html (1 hunks)
  • apps/docs/docs/components/pagination/_both.component.ts (1 hunks)
  • apps/docs/docs/components/pagination/_custom.component.html (1 hunks)
  • apps/docs/docs/components/pagination/_custom.component.ts (1 hunks)
  • apps/docs/docs/components/pagination/_default.component.html (1 hunks)
  • apps/docs/docs/components/pagination/_default.component.ts (1 hunks)
  • apps/docs/docs/components/pagination/_text.component.html (1 hunks)
  • apps/docs/docs/components/pagination/_text.component.ts (1 hunks)
  • apps/docs/docs/components/pagination/index.md (1 hunks)
  • apps/docs/docs/components/pagination/ng-doc.page.ts (1 hunks)
  • apps/docs/docs/ng-doc.api.ts (1 hunks)
  • libs/flowbite-angular/core/flowbite.theme.init.ts (6 hunks)
  • libs/flowbite-angular/pagination/README.md (1 hunks)
  • libs/flowbite-angular/pagination/index.ts (1 hunks)
  • libs/flowbite-angular/pagination/ng-package.json (1 hunks)
  • libs/flowbite-angular/pagination/pagination-button.directive.ts (1 hunks)
  • libs/flowbite-angular/pagination/pagination-button.theme.service.ts (1 hunks)
  • libs/flowbite-angular/pagination/pagination-button.theme.ts (1 hunks)
  • libs/flowbite-angular/pagination/pagination.component.ts (1 hunks)
  • libs/flowbite-angular/pagination/pagination.theme.service.ts (1 hunks)
  • libs/flowbite-angular/pagination/pagination.theme.ts (1 hunks)
  • tsconfig.base.json (1 hunks)
✅ Files skipped from review due to trivial changes (2)
  • libs/flowbite-angular/pagination/README.md
  • libs/flowbite-angular/pagination/ng-package.json
🧰 Additional context used
🪛 Biome (1.9.4)
apps/docs/docs/components/pagination/_default.component.ts

[error] 17-17: This variable is used before its declaration.

The variable is declared here:

(lint/correctness/noInvalidUseBeforeDeclaration)

🪛 LanguageTool
apps/docs/docs/components/pagination/index.md

[uncategorized] ~29-~29: The grammatical number of this noun doesn’t look right. Consider replacing it.
Context: ...ript" ``` ## Pagination with text and icon {{ NgDocActions.demo('flowbiteBothComp...

(AI_EN_LECTOR_REPLACEMENT_NOUN_NUMBER)

🔇 Additional comments (8)
apps/docs/docs/components/pagination/_default.component.html (1)

2-2: Verify data access pattern

The testDatas().items access pattern suggests direct function calls in the template. Consider using a signal or observable pattern instead for better performance.

apps/docs/docs/components/pagination/_custom.component.html (1)

12-12: Verify color contrast ratios for accessibility.

The custom colors used (neutral-400, neutral-700) should be verified for sufficient contrast ratios to ensure WCAG compliance.

apps/docs/docs/ng-doc.api.ts (1)

35-35: LGTM: Documentation entry properly added

The pagination component is correctly added to the API documentation scope.

tsconfig.base.json (1)

35-35: LGTM! Path mapping follows project conventions

The pagination module path mapping is correctly added and follows the established pattern for Flowbite Angular components.

libs/flowbite-angular/pagination/pagination-button.directive.ts (1)

27-54: Well-structured directive implementation!

The directive follows Angular best practices:

  • Standalone directive with clear selector
  • Proper use of signals with input() and model()
  • Clean inheritance from BaseComponent
  • Type-safe theme implementation
libs/flowbite-angular/core/flowbite.theme.init.ts (3)

121-130: LGTM: Pagination imports follow established patterns

The new pagination-related imports are well-organized and include all necessary components for theme integration.


484-485: LGTM: Default value providers are properly integrated

The pagination default value providers are correctly added and follow the established pattern.


121-130: Verify pagination module integration

Let's ensure that all required pagination-related files are present and properly structured.

✅ Verification successful

Let me verify the exports to ensure they match the imports in the theme init file.


Pagination module integration is properly structured and exported

The verification confirms that:

  • All required pagination files are present with consistent naming
  • The imports in flowbite.theme.init.ts match the exports from the pagination module
  • All theme-related tokens, services, and configurations are properly exported through the module's index.ts
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Verify pagination module structure and exports

# Check if pagination module directory exists and has required files
echo "Checking pagination module structure..."
fd -t f . -e ts --base-directory libs/flowbite-angular/pagination

# Verify exports of pagination components
echo -e "\nChecking pagination exports..."
rg -l "export.*pagination" libs/flowbite-angular/pagination

# Verify consistent naming patterns
echo -e "\nChecking naming consistency..."
rg -l "(pagination|Pagination)" libs/flowbite-angular/pagination

Length of output: 1337


Script:

#!/bin/bash
# Check the exports in index.ts and specific files to verify they match the imports
echo "Checking index.ts exports..."
cat libs/flowbite-angular/pagination/index.ts

echo -e "\nChecking theme-related exports..."
rg "export.*FLOWBITE_PAGINATION.*_THEME_TOKEN|export.*pagination.*Theme|export.*PaginationThemeService" libs/flowbite-angular/pagination/pagination.theme.ts libs/flowbite-angular/pagination/pagination-button.theme.ts -A 1

Length of output: 1685

Comment on lines 38 to 74
@Component({
selector: 'flowbite-pagination',
standalone: true,
imports: [PaginationButtonDirective, IconComponent],
template: `<nav
[class]="contentClasses().navigationClass"
[ariaLabel]="ariaLabel()">
@if (firstLast()) {
<button
type="button"
(click)="firstPage()"
[customStyle]="buttonCustomStyle()"
flowbitePaginationButton>
@switch (navigation()) {
@case ('icon') {
<flowbite-icon
svgIcon="flowbite-angular:chevron-right"
class="w-5 h-5 rotate-180" />
<flowbite-icon
svgIcon="flowbite-angular:chevron-right"
class="w-5 h-5 rotate-180" />
}
@case ('text') {
<span>First</span>
}
@case ('both') {
<flowbite-icon
svgIcon="flowbite-angular:chevron-right"
class="w-5 h-5 rotate-180" />
<flowbite-icon
svgIcon="flowbite-angular:chevron-right"
class="w-5 h-5 rotate-180" />
<span>First</span>
}
}
</button>
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Add i18n/ARIA best practices for the 'First' button text.
The template supports textual labels for the “First” button, but there's no clear mechanism to customize them for different locales. Consider adding an input property, like “firstLabel,” with a default of “First,” so that the label can be easily localized.

Comment on lines 137 to 166
@if (firstLast()) {
<button
type="button"
(click)="lastPage()"
[customStyle]="buttonCustomStyle()"
flowbitePaginationButton>
@switch (navigation()) {
@case ('icon') {
<flowbite-icon
svgIcon="flowbite-angular:chevron-right"
class="w-5 h-5" />
<flowbite-icon
svgIcon="flowbite-angular:chevron-right"
class="w-5 h-5" />
}
@case ('text') {
<span>Last</span>
}
@case ('both') {
<span>Last</span>
<flowbite-icon
svgIcon="flowbite-angular:chevron-right"
class="w-5 h-5" />
<flowbite-icon
svgIcon="flowbite-angular:chevron-right"
class="w-5 h-5" />
}
}
</button>
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Add i18n/ARIA best practices for the 'Last' button text.
Similarly, you could introduce an input property (e.g., “lastLabel”) so the “Last” link text can be localized.

Comment on lines 171 to 347
return this.currentPage() - Math.floor(this.tabs() / 2);
});

/**
* Value of the maximum pages calculated from `totalItems`
*/
readonly maxPages = computed(() => {
return Math.max(Math.ceil(this.totalItems() / this.pageSize()), 1);
});

/**
* Array of the visible page tabs
*/
readonly visiblePages = computed(() => {
const pages: number[] = [];
const visibleTabs = Math.min(this.tabs(), this.maxPages());

for (let i = this.firstPageToShow(); i < this.firstPageToShow() + visibleTabs; i++) {
pages.push(i);
}

return pages;
});

/**
* Real value of the current page
*
* If the given `currentPage` is bigger than the `maxPages`,
* the last page will be the active one
*/
readonly visibleCurrentPage = computed(() => {
return Math.min(this.currentPage(), this.maxPages());
});

/**
* Set the custom style for this pagination
*/
public customStyle = model(inject(FLOWBITE_PAGINATION_CUSTOM_STYLE_DEFAULT_VALUE));
/**
* Set the custom style for this pagination's button
*/
public buttonCustomStyle = model(inject(FLOWBITE_PAGINATION_BUTTON_CUSTOM_STYLE_DEFAULT_VALUE));

//#region BaseComponent implementation
public override fetchClass(): PaginationClass {
return this.themeService.getClasses({
customStyle: this.customStyle(),
});
}

public override init(): void {
this.iconRegistry.addRawSvgIconInNamepsace(
'flowbite-angular',
'chevron-right',
this.domSanitizer.bypassSecurityTrustHtml(CHEVRON_RIGHT_SVG_ICON)
);
}
//#endregion

/**
* Sets the value of the `currentPage`
* @param page number of the active page
*/
changePage(page: number) {
if (this.visibleCurrentPage() === page) return;
this.currentPage.set(page);
}

/**
* Decreases the value of `currentPage` if it's bigger than 1
*/
previousPage() {
if (this.visibleCurrentPage() === 1) return;
this.currentPage.update((value) => value - 1);
}

/**
* Increases the value of `currentPage` if it's smaller than `maxPages`
*/
nextPage() {
if (this.visibleCurrentPage() === this.maxPages()) return;
this.currentPage.update((value) => value + 1);
}

/**
* Sets the value of `currentPage` to 1
*/
firstPage() {
if (this.currentPage() === 1) return;
this.currentPage.set(1);
}

/**
* Sets the value of `currentPage` equal to `maxPages`
*/
lastPage() {
if (this.currentPage() === this.maxPages()) return;
this.currentPage.set(this.maxPages());
}
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Leverage the “pageChange” output event.
“pageChange” is declared (line 234) but never emitted within the component’s logic. If you intend for external consumers to respond to page changes, you could emit an event each time the page value updates, for example, right after the call to “this.currentPage.set(page).”

Here's one potential approach:

--- a/pagination.component.ts
+++ b/pagination.component.ts
@@ -312,6 +312,7 @@ changePage(page: number) {
   if (this.visibleCurrentPage() === page) return;
   this.currentPage.set(page);
+  this.pageChange.emit(page);
 }

Committable suggestion skipped: line range outside the PR's diff.

Comment on lines +1 to +10
import { PaginationComponent } from 'flowbite-angular/pagination';

import { Component } from '@angular/core';

@Component({
selector: 'flowbite-demo-pagination-text',
imports: [PaginationComponent],
templateUrl: './_text.component.html',
})
export class FlowbiteTextComponent {}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Add a dedicated property and event emitter for page changes.
This example references the pagination component but does not display how to handle page changes. To make the documentation more instructive, you might add a property like “page: number = 1” and subscribe to the (pageChange) event for demonstration.

Comment on lines 1 to 8
<table>
@for (item of testDatas().items; track $index) {
<tr>
<td>{{ item.id }}</td>
<td>{{ item.name }}</td>
</tr>
}
</table>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Add accessibility attributes and table headers

The table structure needs improvement for accessibility:

  1. Missing table headers
  2. Missing accessibility attributes
  3. No loading or error states handled
-<table>
+<table role="grid" aria-label="Pagination demo data">
+  <thead>
+    <tr>
+      <th scope="col">ID</th>
+      <th scope="col">Name</th>
+    </tr>
+  </thead>
+  <tbody>
   @for (item of testDatas().items; track $index) {
     <tr>
-      <td>{{ item.id }}</td>
-      <td>{{ item.name }}</td>
+      <td role="gridcell">{{ item.id }}</td>
+      <td role="gridcell">{{ item.name }}</td>
     </tr>
   }
+  </tbody>
 </table>
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
<table>
@for (item of testDatas().items; track $index) {
<tr>
<td>{{ item.id }}</td>
<td>{{ item.name }}</td>
</tr>
}
</table>
<table role="grid" aria-label="Pagination demo data">
<thead>
<tr>
<th scope="col">ID</th>
<th scope="col">Name</th>
</tr>
</thead>
<tbody>
@for (item of testDatas().items; track $index) {
<tr>
<td role="gridcell">{{ item.id }}</td>
<td role="gridcell">{{ item.name }}</td>
</tr>
}
</tbody>
</table>


readonly currentPage = signal(1);
readonly pageSize = signal(10);
readonly testDatas = signal(PagedResult.empty<IdNameDto>());
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Fix variable declaration order

The static analysis tool correctly flags that PagedResult is used before its declaration.

Move the PagedResult interface and constant declarations above the component class.

🧰 Tools
🪛 Biome (1.9.4)

[error] 17-17: This variable is used before its declaration.

The variable is declared here:

(lint/correctness/noInvalidUseBeforeDeclaration)


@Component({
// ng-doc-ignore-line
selector: 'flowbite-demo-navbar-default',
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Incorrect selector name

The selector 'flowbite-demo-navbar-default' doesn't match the component's pagination functionality.

-  selector: 'flowbite-demo-navbar-default',
+  selector: 'flowbite-demo-pagination-default',
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
selector: 'flowbite-demo-navbar-default',
selector: 'flowbite-demo-pagination-default',

Comment on lines 29 to 46
pageChangeHandler(page: number) {
this.currentPage.set(page);

// Call your API here
// The following lines of code simulates a backend query
const _items: IdNameDto[] = [];
const _start = (this.currentPage() - 1) * this.pageSize();
const _end = Math.min(this._testDatas.length, _start + this.pageSize());

for (let i = _start; i < _end; i++) {
_items.push({ id: i + 1, name: 'John Doe' });
}

this.testDatas.set({
items: _items,
totalItems: this._testDatas.length,
});
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Add type safety and error handling to pageChangeHandler

The page change handler could benefit from additional type safety and error handling.

-  pageChangeHandler(page: number) {
+  pageChangeHandler(page: number): void {
+    if (page < 1) {
+      console.warn('Invalid page number');
+      return;
+    }
+
     this.currentPage.set(page);
 
-    // Call your API here
-    // The following lines of code simulates a backend query
-    const _items: IdNameDto[] = [];
+    // Simulate API call with proper error handling
+    try {
+      const _items: IdNameDto[] = [];
       const _start = (this.currentPage() - 1) * this.pageSize();
       const _end = Math.min(this._testDatas.length, _start + this.pageSize());
 
       for (let i = _start; i < _end; i++) {
-        _items.push({ id: i + 1, name: 'John Doe' });
+        _items.push(this._testDatas[i]);
       }
 
       this.testDatas.set({
         items: _items,
         totalItems: this._testDatas.length,
       });
+    } catch (error) {
+      console.error('Error updating pagination:', error);
+      this.testDatas.set(PagedResult.empty());
+    }
   }

Committable suggestion skipped: line range outside the PR's diff.

Comment on lines 256 to 259
{
provide: PaginationThemeService,
useClass: PaginationThemeService,
},
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Remove duplicate PaginationThemeService registration

The PaginationThemeService is registered twice in the service providers array. This could lead to unexpected behavior in the dependency injection system.

Apply this change to remove the duplicate registration:

    {
      provide: PaginationThemeService,
      useClass: PaginationThemeService,
    },
    {
      provide: NavbarContentThemeService,
      useClass: NavbarContentThemeService,
    },
    // ... other services ...
-   {
-     provide: PaginationThemeService,
-     useClass: PaginationThemeService,
-   },
    {
      provide: PaginationButtonThemeService,
      useClass: PaginationButtonThemeService,
    },

Also applies to: 280-287

Comment on lines 400 to 403
{
provide: FLOWBITE_PAGINATION_THEME_TOKEN,
useValue: paginationTheme,
},
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Remove duplicate pagination theme token registration

The FLOWBITE_PAGINATION_THEME_TOKEN is registered twice in the theme providers array. This could lead to unexpected behavior in the theme system.

Apply this change to remove the duplicate registration:

    {
      provide: FLOWBITE_PAGINATION_THEME_TOKEN,
      useValue: paginationTheme,
    },
    {
      provide: FLOWBITE_NAVBAR_ITEM_THEME_TOKEN,
      useValue: navbarItemTheme,
    },
    // ... other themes ...
-   {
-     provide: FLOWBITE_PAGINATION_THEME_TOKEN,
-     useValue: paginationTheme,
-   },
    {
      provide: FLOWBITE_PAGINATION_BUTTON_THEME_TOKEN,
      useValue: paginationButtonTheme,
    },

Also applies to: 420-427

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

♻️ Duplicate comments (2)
libs/flowbite-angular/pagination/pagination.component.ts (2)

88-88: 🛠️ Refactor suggestion

Add i18n support for navigation button labels.

The hardcoded English strings "First" and "Last" should be externalized for internationalization.

Consider adding input properties for these labels:

+  readonly firstLabel = input('First');
+  readonly lastLabel = input('Last');

Then update the template:

-  <span>First</span>
+  <span>{{ firstLabel() }}</span>
-  <span>Last</span>
+  <span>{{ lastLabel() }}</span>

Also applies to: 211-211


403-406: 🛠️ Refactor suggestion

Add pageChange event emitter.

The changePage method updates the page but doesn't notify parent components of the change.

Add an event emitter and emit the new page value:

+  readonly pageChange = output<number>();

 changePage(page: number) {
   if (this.visibleCurrentPage() === page) return;
   this.currentPage.set(page);
+  this.pageChange.emit(page);
 }
🧹 Nitpick comments (8)
libs/flowbite-angular/pagination/pagination.theme.ts (2)

29-30: Fix incorrect component reference in documentation.

The comment references NavbarComponent instead of PaginationComponent.

-  * Theme definition for `NavbarComponent`
+  * Theme definition for `PaginationComponent`

16-18: Consider using a more specific type for size keys.

The string index signature allows any string key, which could lead to runtime errors. Consider using a union type of allowed values instead.

-export interface PaginationSizes extends Pick<FlowbiteSizes, 'sm' | 'md'> {
-  [key: string]: string;
-}
+export interface PaginationSizes extends Pick<FlowbiteSizes, 'sm' | 'md'> {
+  // Add specific additional sizes if needed
+  // lg?: string;
+  // xl?: string;
+}
libs/flowbite-angular/pagination/pagination-button.theme.ts (2)

31-31: Consider splitting the base styles for better readability.

The long string of CSS classes could be split into logical groups (layout, colors, states) for better maintainability.

-    base: 'flex items-center justify-center px-3 h-8 ms-0 leading-tight text-gray-500 bg-white border border-e-0 border-gray-300 hover:bg-gray-100 hover:text-gray-700 dark:bg-gray-800 dark:border-gray-700 dark:text-gray-400 dark:hover:bg-gray-700 dark:hover:text-white first:rounded-l-lg last:rounded-r-lg',
+    base: [
+      // Layout
+      'flex items-center justify-center px-3 h-8 ms-0 leading-tight',
+      // Borders
+      'border border-e-0 border-gray-300 first:rounded-l-lg last:rounded-r-lg',
+      // Colors
+      'text-gray-500 bg-white hover:bg-gray-100 hover:text-gray-700',
+      // Dark mode
+      'dark:bg-gray-800 dark:border-gray-700 dark:text-gray-400 dark:hover:bg-gray-700 dark:hover:text-white'
+    ].join(' '),

32-36: Consider extracting color values to theme variables.

The hardcoded color values could be moved to theme variables for better customization support.

Consider implementing a color token system that allows for easy customization of the color scheme while maintaining consistency across components.

libs/flowbite-angular/pagination/pagination.component.ts (1)

384-396: Add cleanup for registered icons.

The component registers SVG icons but doesn't clean them up when the component is destroyed.

Consider adding cleanup in the destroy hook:

+  override destroy(): void {
+    this.iconRegistry.removeIconInNamespace('flowbite-angular', 'chevron-right');
+    this.iconRegistry.removeIconInNamespace('flowbite-angular', 'chevron-double-right');
+    super.destroy();
+  }
libs/flowbite-angular/pagination/pagination-button.directive.ts (3)

17-26: Add JSDoc comments for the injection token and provider

Consider adding comprehensive documentation for:

  • The structure and expected properties of PaginationButtonTheme
  • Usage examples for custom style overrides
  • Purpose and use cases of the default value provider
+/**
+ * Injection token for customizing the default pagination button styles.
+ * @example
+ * ```typescript
+ * {
+ *   base: 'custom-base-class',
+ *   active: 'custom-active-class',
+ *   // ... other theme properties
+ * }
+ * ```
+ */
 export const FLOWBITE_PAGINATION_BUTTON_CUSTOM_STYLE_DEFAULT_VALUE = new InjectionToken<
   DeepPartial<PaginationButtonTheme>
 >('FLOWBITE_PAGINATION_BUTTON_CUSTOM_STYLE_DEFAULT_VALUE');

+/**
+ * Default provider for pagination button styles.
+ * Use this provider to set up default custom styles at the application level.
+ */
 export const paginationButtonDefaultValueProvider = makeEnvironmentProviders([

47-47: Add size validation

Consider adding validation for the size input to ensure only valid sizes are used.

-  public readonly size = input.required<keyof PaginationSizes>();
+  public readonly size = input.required<keyof PaginationSizes>({
+    transform: (value: keyof PaginationSizes) => {
+      const validSizes: (keyof PaginationSizes)[] = ['sm', 'md', 'lg'];
+      return validSizes.includes(value) ? value : 'md';
+    }
+  });

54-60: Add unit tests for the directive

The PR objectives mention missing tests. Please add comprehensive unit tests for:

  • Class generation with different sizes
  • Active state handling
  • Custom style application

Would you like me to help generate the unit test suite for this directive?

📜 Review details

Configuration used: .coderabbit.yaml
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between ea541d2 and c92b724.

📒 Files selected for processing (8)
  • libs/flowbite-angular/pagination/pagination-button.directive.ts (1 hunks)
  • libs/flowbite-angular/pagination/pagination-button.theme.service.ts (1 hunks)
  • libs/flowbite-angular/pagination/pagination-button.theme.ts (1 hunks)
  • libs/flowbite-angular/pagination/pagination.component.ts (1 hunks)
  • libs/flowbite-angular/pagination/pagination.theme.service.ts (1 hunks)
  • libs/flowbite-angular/pagination/pagination.theme.ts (1 hunks)
  • libs/flowbite-angular/utils/icon.list.ts (1 hunks)
  • libs/flowbite-angular/utils/index.ts (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (2)
  • libs/flowbite-angular/pagination/pagination-button.theme.service.ts
  • libs/flowbite-angular/pagination/pagination.theme.service.ts
🔇 Additional comments (5)
libs/flowbite-angular/utils/index.ts (1)

12-12: LGTM! Verify icon usage in pagination components.

The export is correctly placed and follows the established naming convention.

Let's verify the icon usage in pagination components:

✅ Verification successful

Icon is correctly used in pagination component

The verification confirms that CHEVRON_DOUBLE_RIGHT_SVG_ICON is:

  • Defined in utils/icon.list.ts
  • Exported through utils/index.ts
  • Properly imported and used in pagination.component.ts
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Search for CHEVRON_DOUBLE_RIGHT_SVG_ICON usage in pagination components
rg "CHEVRON_DOUBLE_RIGHT_SVG_ICON" --type ts

Length of output: 491

libs/flowbite-angular/pagination/pagination.theme.ts (1)

47-64: LGTM! Well-structured theme definition.

The theme structure is clean and follows Flowbite's design system with appropriate dark mode support.

libs/flowbite-angular/pagination/pagination-button.theme.ts (1)

1-47: LGTM! Well-structured theme implementation.

The overall structure is clean and follows Angular best practices. The theme implementation provides good flexibility for customization while maintaining default styles.

libs/flowbite-angular/utils/icon.list.ts (1)

26-30: LGTM! SVG icon implementation is consistent.

The new CHEVRON_DOUBLE_RIGHT_SVG_ICON follows the established pattern and best practices:

  • Uses currentColor for theming compatibility
  • Maintains consistent SVG attributes
  • Properly structured path data
libs/flowbite-angular/pagination/pagination-button.directive.ts (1)

5-6: Verify potential circular dependency

Importing from 'flowbite-angular' within a library that's part of the same package could create circular dependencies.

Comment on lines 68 to 104
<button
type="button"
(click)="firstPage()"
[customStyle]="buttonCustomStyle()"
[size]="size()"
flowbitePaginationButton>
@switch (navigation()) {
@case ('icon') {
@if (lastIcon()) {
<div class="rotate-180">
<ng-container [ngTemplateOutlet]="lastIcon()!" />
</div>
} @else {
<flowbite-icon
svgIcon="flowbite-angular:chevron-double-right"
[class]="contentClasses().iconClass"
class="rotate-180" />
}
}
@case ('text') {
<span>First</span>
}
@case ('both') {
@if (lastIcon()) {
<div class="rotate-180">
<ng-container [ngTemplateOutlet]="lastIcon()!" />
</div>
} @else {
<flowbite-icon
svgIcon="flowbite-angular:chevron-double-right"
[class]="contentClasses().iconClass"
class="rotate-180" />
}
<span>First</span>
}
}
</button>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Enhance accessibility for navigation buttons.

Navigation buttons should have appropriate ARIA attributes to improve screen reader support.

Add these attributes to the first/last buttons:

 <button
   type="button"
   (click)="firstPage()"
+  [attr.aria-label]="firstLabel()"
+  [attr.aria-disabled]="currentPage() === 1"
   [customStyle]="buttonCustomStyle()"
   [size]="size()"
   flowbitePaginationButton>
 <button
   type="button"
   (click)="lastPage()"
+  [attr.aria-label]="lastLabel()"
+  [attr.aria-disabled]="currentPage() === maxPages()"
   [customStyle]="buttonCustomStyle()"
   [size]="size()"
   flowbitePaginationButton>

Also applies to: 194-225

Comment on lines 411 to 414
previousPage() {
if (this.visibleCurrentPage() === 1) return;
this.currentPage.update((value) => value - 1);
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Add unit tests for navigation methods.

The navigation methods need test coverage to ensure they handle edge cases correctly.

Consider adding these test cases:

  • Previous page at first page
  • Next page at last page
  • Navigation within bounds
  • Page size changes
  • Total items changes

Also applies to: 419-422

Comment on lines 28 to 32
@Directive({
standalone: true,
selector: 'button[flowbitePaginationButton]',
})
export class PaginationButtonDirective extends BaseComponent<PaginationButtonClass> {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Add ARIA attributes for accessibility

The pagination button should include appropriate ARIA attributes for better accessibility.

 @Directive({
   standalone: true,
   selector: 'button[flowbitePaginationButton]',
+  host: {
+    'role': 'button',
+    '[attr.aria-current]': 'active() ? "page" : null',
+    '[attr.aria-label]': '"Page " + label',
+  }
 })
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
@Directive({
standalone: true,
selector: 'button[flowbitePaginationButton]',
})
export class PaginationButtonDirective extends BaseComponent<PaginationButtonClass> {
@Directive({
standalone: true,
selector: 'button[flowbitePaginationButton]',
host: {
'role': 'button',
'[attr.aria-current]': 'active() ? "page" : null',
'[attr.aria-label]': '"Page " + label',
}
})
export class PaginationButtonDirective extends BaseComponent<PaginationButtonClass> {

@MGREMY
Copy link
Collaborator

MGREMY commented Dec 28, 2024

So, sorry for what's coming really, plenty of work to do on this, but that's honestly an excellent start !

Review

Refacto
  • public computed value must be explicitly marked as public
  • private computed value must be explicitly marked as protected (not private)
  • Navigation function (first or so) must be prefixed with goTo => goToFirst and must be marked as public
  • Using ChevronRight and DoubleChevronRight is good | Must add/use ChevronLeft and DoubleChevronLeft and not rotate-180 class
  • Remove div around ng-content used for custom icon, and remove rotate-180 too (the user don't want to see its icon being reversed).
  • Variable names in InjectionToken must use underscore => FLOWBITE_PAGINATION_PAGE_SIZE_DEFAULT_VALUE not FLOWBITE_PAGINATION_PAGESIZE_DEFAULT_VALUE
Inputs
  • All inputs must explicitly be marked as public readonly
  • All inputs must use model API to provide an input and an output usable by the user
  • Don't need to specify generic type in a model(inject()) since it's inherited by the InjectionToken generic type
Template
  • Template begin and end with a new line
[...]
template: `
<...>
`
[...]
  • In icons section, change the conditions to
@if (['icon', 'both'].includes(navigation())){}
@if (['text', 'both'].includes(navigation())){}
  • Delete nav HTML tag - we use the component itself as the container => add necessary accessibility attribute on the host component's property
Buttons
  • Every button used in the template must be flowbite-button-component
  • Provide an input encapsulating input of the button component and pass every value in the button parameters
<...>
<flowbite-button
  [size]="properties.size"
  [color]="properties.color"
  ...>
<...>
</flowbite-button>
<...>

(where properties is the input encapsulating input of the button component)

To achieve this behavior, we can use an input type ButtonProperties

public buttonProperties = model<DeepPartial<ButtonProperties>>({});

(Imagine with an InjectionToken)

With this solution, we are not forced to use a Directive and let the user choose the style of its button
=> Could be added to other components like Dropdown to modify the button style

Additional information

On the internationalization part, for the moment we are not adding anything for it. Let's use English only and see if users want to have some flexibility on this. Also, I don't think that flowbite-react for example has something related to internationalization either so...

feat(pagination): remove directive & use flowbite-button
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 4

🧹 Nitpick comments (5)
libs/flowbite-angular/pagination/pagination.theme.ts (2)

4-11: Consider using an enum or union type for navigation types

The PaginationNavigation interface could benefit from stronger type safety. Instead of using string properties, consider using an enum or union type to enforce specific navigation types, especially since the PR mentions pending icon fixes.

+export type NavigationType = 'icon' | 'text' | 'both';
+
 export interface PaginationNavigation {
-  icon: string;
-  text: string;
-  both: string;
+  type: NavigationType;
+  content: string;
 }

13-18: Consider constraining size options

The string index signature allows any additional sizes, which could lead to inconsistencies. Since the PR mentions implementing specific size variables, consider:

  1. Explicitly defining all supported sizes
  2. Documenting the expected size values
  3. Adding validation for custom sizes
-export interface PaginationSizes extends Pick<FlowbiteSizes, 'sm' | 'md'> {
-  [key: string]: string;
+export interface PaginationSizes extends Pick<FlowbiteSizes, 'sm' | 'md' | 'lg'> {
+  // Custom sizes should follow the pattern: 'text-{size}'
+  [key: `text-${string}`]: string;
}
apps/docs/docs/components/pagination/ng-doc.page.ts (2)

9-13: Enhance the component documentation.

The current JSDoc documentation could be more comprehensive. Consider adding:

  • Available props and their types
  • Usage examples
  • Accessibility considerations
  • Browser compatibility notes
 /**
  * Use the pagination component to show a list of buttons to navigate in your tables
+ * 
+ * @example
+ * ```html
+ * <flowbite-pagination
+ *   [currentPage]="1"
+ *   [totalPages]="10"
+ *   (pageChange)="onPageChange($event)">
+ * </flowbite-pagination>
+ * ```
+ * 
+ * @props
+ * - currentPage: number - The current active page
+ * - totalPages: number - Total number of pages
+ * - size: 'sm' | 'md' | 'lg' - Size of the pagination component
+ * 
+ * @events
+ * - pageChange: EventEmitter<number> - Emitted when page changes
+ * 
+ * @accessibility
+ * - Follows WCAG 2.1 guidelines for navigation
+ * - Supports keyboard navigation
  *
  * @status:info NEW
  */

14-25: Consider reorganizing demos for better documentation flow.

The current demo structure could be reorganized to better guide users through the component's features:

  1. Basic usage (already covered by flowbiteDefaultComponent)
  2. Sizes and variants
  3. Navigation styles
  4. Customization examples
  5. Internationalization examples

Also, consider adding a description for each demo in the configuration:

 demos: {
-  flowbiteDefaultComponent: FlowbiteDefaultComponent,
+  flowbiteDefaultComponent: {
+    component: FlowbiteDefaultComponent,
+    description: 'Basic pagination with numbers only',
+    order: 1
+  },
   // Add similar descriptions for other demos
 },
libs/flowbite-angular/pagination/pagination.component.ts (1)

363-373: Mark internal computed properties as protected.

The following computed properties should be marked as protected since they are implementation details:

  • firstPageToShow
  • maxPages
  • visiblePages
  • visibleCurrentPage
  • visiblePagesCount

Also applies to: 378-380, 385-397, 405-407, 412-414

📜 Review details

Configuration used: .coderabbit.yaml
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 15376cb and e524102.

📒 Files selected for processing (9)
  • apps/docs/docs/components/pagination/_custom.component.html (1 hunks)
  • apps/docs/docs/components/pagination/ng-doc.page.ts (1 hunks)
  • apps/docs/docs/getting-started/quickstart/ng-doc.page.ts (1 hunks)
  • apps/docs/docs/getting-started/versioning/index.md (1 hunks)
  • apps/docs/docs/getting-started/versioning/ng-doc.page.ts (1 hunks)
  • libs/flowbite-angular/core/flowbite.theme.init.ts (4 hunks)
  • libs/flowbite-angular/pagination/index.ts (1 hunks)
  • libs/flowbite-angular/pagination/pagination.component.ts (1 hunks)
  • libs/flowbite-angular/pagination/pagination.theme.ts (1 hunks)
✅ Files skipped from review due to trivial changes (2)
  • apps/docs/docs/getting-started/quickstart/ng-doc.page.ts
  • apps/docs/docs/getting-started/versioning/ng-doc.page.ts
🚧 Files skipped from review as they are similar to previous changes (3)
  • apps/docs/docs/components/pagination/_custom.component.html
  • libs/flowbite-angular/core/flowbite.theme.init.ts
  • libs/flowbite-angular/pagination/index.ts
🔇 Additional comments (9)
apps/docs/docs/getting-started/versioning/index.md (1)

9-10: Please clarify the versioning strategy.

A few concerns regarding the version table updates:

  1. Two new versions (1.3.0 and 1.4.0) are being added simultaneously. Since this PR is marked as WIP, should we be documenting these versions before the feature is complete?

  2. The TailwindCSS version requirement has been relaxed from ^3.0.24 to ^3.0.0. Please verify if this change is intentional and won't introduce compatibility issues.

Run the following script to check for potential TailwindCSS compatibility issues:

✅ Verification successful

Let me gather more information about the versioning strategy by checking the version history and package dependencies.


Version changes appear to be correctly documented

Based on the verification results:

  1. The TailwindCSS version change from ^3.0.24 to ^3.0.0 is intentional and safe:

    • The project currently uses TailwindCSS 3.4.17 in development
    • The relaxed requirement ^3.0.0 still ensures compatibility with breaking changes (major version)
    • This aligns with semantic versioning best practices
  2. The version bumps are appropriate:

    • Version 1.3.0 matches the current package version in libs/flowbite-angular/package.json
    • Version 1.4.0 is likely planned for the pagination feature, which is actively being developed (evidenced by multiple pagination-related files)
    • Both versions maintaining the same dependency requirements ensures consistency

The versioning strategy appears sound, documenting both the current and upcoming versions with appropriate compatibility requirements.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Check for breaking changes in TailwindCSS versions

# Check package.json for current TailwindCSS version
echo "Current TailwindCSS version requirement:"
fd package.json --exec grep -A 5 "tailwindcss"

# Check for any TailwindCSS imports or configurations
echo -e "\nTailwindCSS usage in codebase:"
rg -l "tailwindcss" --type ts --type js --type json

Length of output: 885


Script:

#!/bin/bash
# Check version history in the versioning doc
echo "Version history in docs:"
cat apps/docs/docs/getting-started/versioning/index.md

# Check package.json versions
echo -e "\nFlowbite Angular package version:"
cat libs/flowbite-angular/package.json | grep -A 2 '"version"'

# Check for recent changes related to pagination
echo -e "\nPagination-related files:"
rg -l "pagination" --type ts --type html

Length of output: 1823

libs/flowbite-angular/pagination/pagination.theme.ts (2)

47-64: LGTM! Well-structured theme implementation

The theme implementation:

  • Follows Flowbite's theming patterns
  • Includes dark mode support
  • Provides appropriate size variations
  • Uses semantic Tailwind classes

66-72: LGTM! Clean class interface definition

The interface properly extends FlowbiteClass and includes all necessary class properties for the pagination component.

apps/docs/docs/components/pagination/ng-doc.page.ts (1)

19-24: Verify the demo component implementations.

The demo components are properly mapped, but let's ensure they cover all the planned features mentioned in the PR objectives.

✅ Verification successful

Demo components provide good coverage of pagination features

The demo components effectively showcase the key pagination features:

  • FlowbiteDefaultComponent: Demonstrates practical pagination with data handling and page size control
  • FlowbiteTextComponent: Shows text-only navigation mode
  • FlowbiteBothComponent: Illustrates combined text and icon navigation
  • FlowbiteCustomComponent: Exhibits customization capabilities including:
    • Custom page size
    • ARIA label support
    • Style customization
    • First/Last navigation control

The components provide a comprehensive demonstration of the pagination functionality, covering both basic usage and advanced customization options.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Verify if demo components implement all planned features

# Check for icon customization in demo components
echo "Checking for icon customization implementations..."
rg -l "ChevronLeft|ChevronRight|DoubleChevronLeft|DoubleChevronRight" apps/docs/docs/components/pagination/_*.component.ts

# Check for size variants
echo "Checking for size variant implementations..."
rg -l "\[size\]=" apps/docs/docs/components/pagination/_*.component.ts

# Check for i18n support
echo "Checking for i18n implementations..."
rg -l "i18n" apps/docs/docs/components/pagination/_*.component.ts

Length of output: 1084


Script:

#!/bin/bash
# Let's check the actual content of these demo components to verify their implementations

echo "=== Default Component ==="
cat apps/docs/docs/components/pagination/_default.component.ts

echo -e "\n=== Text Component ==="
cat apps/docs/docs/components/pagination/_text.component.ts

echo -e "\n=== Both Component ==="
cat apps/docs/docs/components/pagination/_both.component.ts

echo -e "\n=== Custom Component ==="
cat apps/docs/docs/components/pagination/_custom.component.ts

Length of output: 2883


Script:

#!/bin/bash
# Let's check the template files to see the actual usage of the pagination component

echo "=== Default Component Template ==="
cat apps/docs/docs/components/pagination/_default.component.html

echo -e "\n=== Text Component Template ==="
cat apps/docs/docs/components/pagination/_text.component.html

echo -e "\n=== Both Component Template ==="
cat apps/docs/docs/components/pagination/_both.component.html

echo -e "\n=== Custom Component Template ==="
cat apps/docs/docs/components/pagination/_custom.component.html

Length of output: 1291

libs/flowbite-angular/pagination/pagination.component.ts (5)

1-127: LGTM! Well-structured dependency injection setup.

The injection tokens and their default providers are well-organized, type-safe, and follow consistent naming patterns.


157-157: Add i18n support for navigation text.

The navigation text is hardcoded in English. Consider using translation keys for internationalization.

Also applies to: 182-182, 219-219, 243-243


134-136: Enhance accessibility attributes.

Add more ARIA attributes to improve screen reader support:

  • Add aria-current="page" for the current page
  • Add aria-disabled for disabled navigation buttons
  • Add descriptive aria-label for page numbers

Also applies to: 188-198


443-446: Emit pageChange event when page updates.

The pageChange event should be emitted when the page value changes to notify parent components.


451-454: Add unit tests for navigation methods.

The navigation methods need test coverage to ensure they handle edge cases correctly.

Also applies to: 459-462, 467-470, 475-478

Comment on lines 28 to 30
/**
* Theme definition for `NavbarComponent`
*/
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Fix incorrect JSDoc reference

The JSDoc comment incorrectly references NavbarComponent instead of PaginationComponent.

 /**
- * Theme definition for `NavbarComponent`
+ * Theme definition for `PaginationComponent`
  */
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
/**
* Theme definition for `NavbarComponent`
*/
/**
* Theme definition for `PaginationComponent`
*/

Comment on lines 20 to 26
/**
* Required properties for class generation of `PaginationComponent`
*/
export interface PaginationProperties {
customStyle: DeepPartial<PaginationTheme>;
size: keyof PaginationSizes;
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Add i18n support for button labels

Since the PR objectives mention "adding the ability to customize button labels and support for internationalization", consider extending PaginationProperties to include i18n-related properties:

 export interface PaginationProperties {
   customStyle: DeepPartial<PaginationTheme>;
   size: keyof PaginationSizes;
+  labels?: {
+    first?: string;
+    previous?: string;
+    next?: string;
+    last?: string;
+  };
 }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
/**
* Required properties for class generation of `PaginationComponent`
*/
export interface PaginationProperties {
customStyle: DeepPartial<PaginationTheme>;
size: keyof PaginationSizes;
}
/**
* Required properties for class generation of `PaginationComponent`
*/
export interface PaginationProperties {
customStyle: DeepPartial<PaginationTheme>;
size: keyof PaginationSizes;
labels?: {
first?: string;
previous?: string;
next?: string;
last?: string;
};
}

Comment on lines 150 to 154
<flowbite-icon
svgIcon="flowbite-angular:chevron-double-right"
[class]="contentClasses().iconClass"
class="rotate-180" />
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Replace rotated icons with dedicated left-facing icons.

Instead of using rotate-180 class on right-facing icons, use dedicated left-facing icons (chevron-left and chevron-double-left) for better maintainability and performance.

-<flowbite-icon
-  svgIcon="flowbite-angular:chevron-double-right"
-  [class]="contentClasses().iconClass"
-  class="rotate-180" />
+<flowbite-icon
+  svgIcon="flowbite-angular:chevron-double-left"
+  [class]="contentClasses().iconClass" />

Also applies to: 175-179

Comment on lines 424 to 436
public override init(): void {
this.iconRegistry.addRawSvgIconInNamepsace(
'flowbite-angular',
'chevron-right',
this.domSanitizer.bypassSecurityTrustHtml(CHEVRON_RIGHT_SVG_ICON)
);

this.iconRegistry.addRawSvgIconInNamepsace(
'flowbite-angular',
'chevron-double-right',
this.domSanitizer.bypassSecurityTrustHtml(CHEVRON_DOUBLE_RIGHT_SVG_ICON)
);
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Register left-facing icons in init method.

Add registration for chevron-left and chevron-double-left icons to support the refactoring of rotated icons.

 public override init(): void {
+  this.iconRegistry.addRawSvgIconInNamepsace(
+    'flowbite-angular',
+    'chevron-left',
+    this.domSanitizer.bypassSecurityTrustHtml(CHEVRON_LEFT_SVG_ICON)
+  );
+
+  this.iconRegistry.addRawSvgIconInNamepsace(
+    'flowbite-angular',
+    'chevron-double-left',
+    this.domSanitizer.bypassSecurityTrustHtml(CHEVRON_DOUBLE_LEFT_SVG_ICON)
+  );
+
   this.iconRegistry.addRawSvgIconInNamepsace(
     'flowbite-angular',
     'chevron-right',
     this.domSanitizer.bypassSecurityTrustHtml(CHEVRON_RIGHT_SVG_ICON)
   );

Committable suggestion skipped: line range outside the PR's diff.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

🧹 Nitpick comments (2)
libs/flowbite-angular/utils/icon.list.ts (1)

38-42: Consider extracting common SVG attributes to reduce duplication.

While the implementation is correct, consider creating a shared interface or type for common SVG attributes to improve maintainability. This would help ensure consistency across all icons and make future updates easier.

Example approach:

interface IconSvgAttributes {
  xmlns: string;
  fill: string;
  viewBox: string;
}

const DEFAULT_SVG_ATTRIBUTES: IconSvgAttributes = {
  xmlns: 'http://www.w3.org/2000/svg',
  fill: 'none',
  viewBox: '0 0 24 24'
};

const createIconSvg = (path: string): string => {
  const attrs = DEFAULT_SVG_ATTRIBUTES;
  return `
<svg xmlns="${attrs.xmlns}" fill="${attrs.fill}" viewBox="${attrs.viewBox}">
  ${path}
</svg>
`;
};
libs/flowbite-angular/pagination/pagination.theme.service.ts (1)

27-36: Consider adding fallback logic for unknown or invalid size properties.
If an invalid properties.size key is passed, twMerge might fail to apply classes or generate unexpected styling. A fallback (e.g., 'md') helps avoid runtime errors and ensures consistent behavior.

📜 Review details

Configuration used: .coderabbit.yaml
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between e524102 and 783c3ed.

📒 Files selected for processing (7)
  • apps/docs/docs/components/pagination/_custom.component.html (1 hunks)
  • libs/flowbite-angular/pagination/index.ts (1 hunks)
  • libs/flowbite-angular/pagination/pagination.component.ts (1 hunks)
  • libs/flowbite-angular/pagination/pagination.theme.service.ts (1 hunks)
  • libs/flowbite-angular/pagination/pagination.theme.ts (1 hunks)
  • libs/flowbite-angular/utils/icon.list.ts (1 hunks)
  • libs/flowbite-angular/utils/index.ts (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (3)
  • libs/flowbite-angular/utils/index.ts
  • apps/docs/docs/components/pagination/_custom.component.html
  • libs/flowbite-angular/pagination/index.ts
🔇 Additional comments (9)
libs/flowbite-angular/pagination/pagination.component.ts (2)

34-81: LGTM! Consistent naming convention for injection tokens.

The injection tokens follow a consistent naming pattern and are well-documented with appropriate types.


153-174: 🛠️ Refactor suggestion

Add accessibility attributes to the First button.

The First button lacks proper ARIA attributes for accessibility. Add aria-label and aria-disabled attributes.

 <flowbite-button
   type="button"
   data-active="false"
+  [attr.aria-label]="'Go to first page'"
+  [attr.aria-disabled]="currentPage() === 1"
   (click)="goToFirstPage()"
   [color]="buttonProperties().color!"
   [fill]="buttonProperties().fill!"

Likely invalid or redundant comment.

libs/flowbite-angular/utils/icon.list.ts (3)

20-24: LGTM! Left chevron icon implementation is consistent.

The SVG implementation follows the established pattern and maintains consistency with other icons in the file.


32-36: Double chevron icon addresses the first/last button requirement.

The implementation is consistent with other icons and provides the necessary visual indicator for first/last page navigation.


20-42: Verify icon integration with the pagination component.

The implementation provides all necessary icons for pagination (previous/next and first/last). However, ensure these are properly integrated with the pagination component's navigation functions mentioned in the PR comments (goToFirst, etc.).

✅ Verification successful

Let me gather more specific information about the pagination component implementation.


Icons are properly integrated with pagination navigation

The verification confirms that:

  • All chevron icons (single and double) are correctly imported and registered in the pagination component
  • The icons are properly connected to their respective navigation functions:
    • CHEVRON_DOUBLE_LEFT_SVG_ICON with goToFirstPage()
    • CHEVRON_LEFT_SVG_ICON with goToPreviousPage()
    • CHEVRON_RIGHT_SVG_ICON with goToNextPage()
    • CHEVRON_DOUBLE_RIGHT_SVG_ICON with goToLastPage()
  • Each navigation function includes appropriate boundary checks and page updates
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Verify the usage of these icons in the pagination component

# Search for icon usage in pagination component
rg -l "CHEVRON_.*_SVG_ICON" --type ts

# Check if the icons are used with the correct navigation functions
ast-grep --pattern 'class $_ {
  $$$
  goTo$_($$$) {
    $$$
  }
  $$$
}'

Length of output: 545


Script:

#!/bin/bash
# Check the pagination component implementation
rg -A 5 "CHEVRON_.*_SVG_ICON" libs/flowbite-angular/pagination/pagination.component.ts

# Check for navigation method implementations
rg -A 3 "goTo(First|Last|Previous|Next)" libs/flowbite-angular/pagination/pagination.component.ts

Length of output: 2220

libs/flowbite-angular/pagination/pagination.theme.service.ts (1)

1-6: No issues found with imports and InjectionToken usage.
All imports and token definitions are well-structured and clear. The naming convention for FLOWBITE_PAGINATION_THEME_TOKEN follows the recommended underscore style.

libs/flowbite-angular/pagination/pagination.theme.ts (3)

20-26: Add i18n support for button labels
This was previously requested. It would align with the PR objectives and user needs for easy localization and customization (e.g., “previous”, “next” in multiple languages).


28-30: Correct the JSDoc reference
The comment references NavbarComponent instead of PaginationComponent. Update it accordingly to avoid confusion.


44-58: Theme definition looks good
The default theme configuration for the pagination component is well-structured, providing clear base classes and size variations. This ensures users can easily customize pagination styles.

libs/flowbite-angular/pagination/pagination.component.ts Outdated Show resolved Hide resolved
libs/flowbite-angular/pagination/pagination.component.ts Outdated Show resolved Hide resolved
libs/flowbite-angular/pagination/pagination.component.ts Outdated Show resolved Hide resolved
@bence444 bence444 marked this pull request as ready for review December 30, 2024 20:52
@MGREMY MGREMY changed the title feat(pagination): add new pagination component [wip] feat(pagination): add new pagination component Dec 30, 2024
Copy link
Collaborator

@MGREMY MGREMY left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Waiting for my PR to be merged in your PR

Waiting for discussion about totalPages | totalCount

refactor(pagination): update post update post comment
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (5)
libs/flowbite-angular/pagination/pagination.component.ts (5)

151-152: Consider removing redundant type casting

The as DeepPartial<ButtonTheme> and as DeepPartial<ButtonProperties> type assertions are redundant since TypeScript can infer these types from the injection token's type definition.

-      } as DeepPartial<ButtonTheme>,
+      },
-    } as DeepPartial<ButtonProperties>,
+    },

212-213: Enhance accessibility for page buttons

Add aria-current="page" for the active page button to improve screen reader support.

 [attr.data-active]="page === currentPage()"
+[attr.aria-current]="page === currentPage() ? 'page' : undefined"
 (click)="goToPage(page)"

466-468: Improve error message specificity

The error message could be more helpful by indicating the expected values and their purpose.

-      throw new Error('Either `totalPages` or `totalItems` must have a value');
+      throw new Error('Pagination requires either `totalPages` (number of pages) or `totalItems` (total number of items) to be set');

430-430: Add validation for negative values

The maxPages computation should handle negative totalItems values.

-    return Math.max(Math.ceil(this.totalItems()! / this.pageSize()), 1);
+    return Math.max(Math.ceil(Math.max(this.totalItems()!, 0) / Math.max(this.pageSize(), 1)), 1);

496-519: Enhance method documentation

Consider adding more descriptive JSDoc comments for navigation methods, including:

  • Return type
  • Example usage
  • Edge case behavior

Example for goToPage:

/**
 * Sets the value of the `currentPage` if it's between 1 and `maxPages`
 * @param page - Number of the target page
 * @returns void
 * @example
 * // Go to page 5
 * pagination.goToPage(5);
 * 
 * // No effect if page is out of bounds
 * pagination.goToPage(0); // No effect
 * pagination.goToPage(maxPages + 1); // No effect
 */
📜 Review details

Configuration used: .coderabbit.yaml
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 3947513 and e8860f1.

📒 Files selected for processing (1)
  • libs/flowbite-angular/pagination/pagination.component.ts (1 hunks)
🧰 Additional context used
📓 Learnings (1)
libs/flowbite-angular/pagination/pagination.component.ts (1)
Learnt from: MGREMY
PR: themesberg/flowbite-angular#106
File: libs/flowbite-angular/pagination/pagination.component.ts:480-483
Timestamp: 2024-12-30T23:08:54.395Z
Learning: In Angular with the signals-based model approach (ModelInput), a separate EventEmitter for output is not required because the model() automatically provides an output for data updates.
🔇 Additional comments (1)
libs/flowbite-angular/pagination/pagination.component.ts (1)

458-494: LGTM! Base component implementation is solid

The implementation properly handles initialization and class fetching.

@MGREMY MGREMY merged commit dbea986 into themesberg:main Dec 31, 2024
5 checks passed
@bence444 bence444 deleted the pagination branch December 31, 2024 22:18
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants