Packages
noora
0.2.2
0.86.0
0.85.0
0.84.1
0.84.0
0.83.2
0.83.1
0.83.0
0.82.7
0.82.6
0.82.5
0.82.4
0.82.3
0.82.2
0.82.1
0.82.0
0.81.4
0.81.3
0.81.2
0.81.1
0.81.0
0.80.1
0.80.0
0.79.1
0.79.0
0.78.1
0.78.0
0.77.4
0.77.3
0.77.2
0.77.1
0.77.0
0.76.0
0.75.0
0.74.0
0.73.0
0.72.0
0.71.0
0.70.0
0.69.1
0.69.0
0.68.0
0.67.0
0.66.0
0.65.0
0.64.2
0.64.1
0.64.0
0.63.2
0.63.1
0.63.0
0.62.0
0.61.0
0.60.0
0.59.0
0.58.0
0.57.0
0.56.1
0.56.0
0.55.0
0.54.0
0.53.1
0.53.0
0.52.1
0.52.0
0.51.0
0.50.1
0.50.0
0.49.0
0.48.0
0.47.0
0.46.0
0.45.0
0.44.3
0.44.2
0.44.1
0.44.0
0.43.0
0.42.0
0.41.0
0.40.6
0.40.5
0.40.4
0.40.3
0.40.2
0.40.1
0.40.0
0.39.1
0.39.0
0.38.0
0.37.0
0.36.0
0.35.0
0.34.0
0.33.0
0.32.1
0.32.0
0.31.0
0.30.0
0.29.2
0.29.1
0.29.0
0.28.5
0.28.4
0.28.3
0.28.2
0.28.1
0.28.0
0.27.0
0.26.1
0.26.0
0.25.0
0.24.0
0.23.1
0.23.0
0.22.1
0.22.0
0.21.0
0.20.0
0.19.0
0.18.0
0.17.0
0.16.0
0.15.0
0.14.0
0.13.0
0.12.1
0.12.0
0.11.2
0.11.1
0.11.0
0.10.0
0.9.0
0.8.0
0.7.0
0.6.1
0.6.0
0.5.1
0.5.0
0.4.0
0.3.2
0.3.1
0.3.0
0.2.2
0.2.0
0.1.0
0.1.0-rc.2
0.1.0-rc.1
0.1.0-alpha.6
0.1.0-alpha.5
0.1.0-alpha.4
0.1.0-alpha.3
0.1.0-alpha.2
0.1.0-alpha.1
A component library for Phoenix LiveView applications
Current section
Files
Jump to
Current section
Files
lib/noora/pagination_group.ex
defmodule Noora.PaginationGroup do
@moduledoc """
Pagination group component for paginating with a defined set of pages. Do not use this component for cursor-based pagination.
## Example
```elixir
<.pagination_group
current_page={@current_page}
number_of_pages={25}
page_patch={fn page -> ~p"/products?page=\#{page}" end}
/>
```
"""
use Phoenix.Component
import Noora.Button
import Noora.Icon
attr(:current_page, :integer, required: true, doc: "The current page number.")
attr(:number_of_pages, :integer, required: true, doc: "The number of pages to display.")
attr(:page_patch, :fun,
required: true,
doc: "Get a patch for an individual page where the input is the index."
)
attr(:rest, :global)
def pagination_group(assigns) do
~H"""
<div class="noora-pagination-group" {@rest}>
<.neutral_button
size="large"
disabled={@current_page == 1}
patch={@current_page != 1 and @page_patch.(@current_page - 1)}
>
<.chevron_left />
</.neutral_button>
<%= for page <- pagination_items(@current_page, @number_of_pages) do %>
<span :if={page == :ellipsis} size="large" data-part="ellipsis">
...
</span>
<.link
:if={page != :ellipsis}
patch={@page_patch.(page)}
data-part="page-button"
data-selected={@current_page == page}
>
<span data-part="label">
{page}
</span>
</.link>
<% end %>
<.neutral_button
size="large"
disabled={@current_page == @number_of_pages}
patch={@current_page != @number_of_pages and @page_patch.(@current_page + 1)}
>
<.chevron_right />
</.neutral_button>
</div>
"""
end
# This method is heavily inspired by: https://github.com/chakra-ui/zag/blob/b7adf8e5f0acc1a83c8e1745ed9809ad598e3d4a/packages/machines/pagination/src/pagination.utils.ts
defp pagination_items(current_page, number_of_pages) do
sibling_count = 1
total_page_numbers = min(2 * sibling_count + 5, number_of_pages)
first_page_index = 1
last_page_index = number_of_pages
left_sibling_index = max(current_page - sibling_count, first_page_index)
right_sibling_index = min(current_page + sibling_count, last_page_index)
show_left_ellipsis = left_sibling_index > first_page_index + 1
show_right_ellipsis = right_sibling_index < last_page_index - 1
# 2 stands for one ellipsis and either first or last page
item_count = total_page_numbers - 2
cond do
!show_left_ellipsis && show_right_ellipsis ->
left_range = Enum.to_list(1..item_count)
left_range ++ [:ellipsis, last_page_index]
show_left_ellipsis && !show_right_ellipsis ->
right_range = Enum.to_list((last_page_index - item_count + 1)..last_page_index)
[first_page_index, :ellipsis | right_range]
show_left_ellipsis && show_right_ellipsis ->
middle_range = Enum.to_list(left_sibling_index..right_sibling_index)
[first_page_index, :ellipsis] ++ middle_range ++ [:ellipsis, last_page_index]
true ->
first_page_index..last_page_index
end
end
end