Packages
petal_components
0.18.2
4.6.2
4.6.1
4.6.0
4.5.0
4.4.0
4.3.0
4.2.1
4.2.0
4.1.2
4.1.1
4.1.0
4.0.12
4.0.11
4.0.10
4.0.6
4.0.5
4.0.4
4.0.3
4.0.1
3.2.2
3.2.1
3.2.0
3.1.0
3.0.2
3.0.1
3.0.0
2.9.3
2.9.2
retired
2.9.1
retired
2.9.0
retired
2.8.4
2.8.3
2.8.2
2.8.1
2.8.0
2.7.4
2.7.3
2.7.2
2.7.1
2.7.0
2.6.1
2.6.0
2.5.2
2.5.1
2.5.0
2.4.3
2.4.2
2.4.1
2.4.0
2.3.0
2.2.1
2.2.0
2.1.2
2.1.1
2.1.0
2.0.6
2.0.5
2.0.4
2.0.3
2.0.2
2.0.1
2.0.0
1.9.3
1.9.2
1.9.1
1.9.0
1.8.0
1.7.1
1.7.0
1.6.2
1.6.1
1.6.0
1.5.5
1.5.4
1.5.3
1.5.2
1.5.1
1.5.0
1.4.9
1.4.8
1.4.7
1.4.6
1.4.5
1.4.4
1.4.3
1.4.2
1.4.1
1.4.0
1.3.0
1.2.14
1.2.13
1.2.12
1.2.11
1.2.10
1.2.9
1.2.8
1.2.7
1.2.6
1.2.5
1.2.4
1.2.3
1.2.2
1.2.1
1.2.0
1.1.6
1.1.5
1.1.4
1.1.3
1.1.2
1.1.1
1.1.0
1.0.8
1.0.7
1.0.6
1.0.5
1.0.4
1.0.3
1.0.2
1.0.1
1.0.0
0.19.10
0.19.9
0.19.8
0.19.7
0.19.6
0.19.5
0.19.4
0.19.3
0.19.2
0.19.1
0.19.0
0.18.5
0.18.4
0.18.3
0.18.2
0.18.1
0.18.0
0.17.7
0.17.6
0.17.5
0.17.4
0.17.3
0.17.2
0.17.1
0.17.0
0.16.0
0.15.0
0.14.1
0.14.0
0.13.7
0.13.6
0.13.5
0.13.4
0.13.3
0.13.2
0.13.1
0.13.0
0.12.0
0.11.4
0.11.3
0.11.2
0.11.1
0.11.0
0.10.8
0.10.7
0.10.6
0.10.5
0.10.4
0.10.3
0.10.2
0.10.1
0.10.0
0.9.3
0.9.2
0.9.1
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.1
0.2.0
0.1.0
Shadcn-style Phoenix LiveView components that AI assistants can actually use. Pair with the MCP server so AI coding tools can inspect the real component API.
Current section
Files
Jump to
Current section
Files
lib/petal_components/pagination_internal.ex
defmodule PetalComponents.PaginationInternal do
@doc """
get_items computes the pagination button information based on
- total number of pages,
- current page,
- sibling count (pages left and right of current page)
- boundary count (pages at start, and at end of the page range)
As this control receives user input, possibly from the internet
a reasonable result is computed despite invalid input values and
at least one page item is returned always.
* The resulting items list always has 1 + max(0, sibling_count) + max(0, boundary_count) page items
* The resulting items may/will contains ellipsis items only if boundary_count > 0
* The previous item has `:enabled?` false if page 1 is current
* The next item has `:enabled?` false if the last page is current
please see the unit tests for examples
"""
def get_pagination_items(total_pages, current_page, sibling_count, boundary_count) do
total_pages = max(1, total_pages)
current_page = max(1, min(current_page, total_pages))
boundary_count = max(0, min(boundary_count, total_pages))
sibling_count = max(0, sibling_count)
siblings_size = 1 + 2 * sibling_count
start_siblings =
max(1, min(current_page - sibling_count, total_pages - siblings_size - boundary_count + 1))
end_siblings =
min(max(current_page + sibling_count, siblings_size + boundary_count), total_pages)
boundary_start =
if boundary_count > 0 do
1..min(boundary_count, start_siblings) |> Enum.to_list()
else
[start_siblings]
end
siblings = start_siblings..end_siblings |> Enum.to_list()
boundary_end =
if boundary_count > 0 do
max(total_pages - boundary_count + 1, end_siblings)..total_pages |> Enum.to_list()
else
[end_siblings]
end
pages =
Enum.concat([boundary_start, siblings, boundary_end])
|> Enum.sort()
|> Enum.dedup()
|> Enum.to_list()
first_page = List.first(pages)
last_page = List.last(pages)
pages_next =
Enum.drop(pages, 1)
|> Enum.concat([List.last(pages) + 1])
|> Enum.to_list()
Enum.zip(pages, pages_next)
|> Enum.flat_map(fn t ->
case t do
{page, next} when next - page == 1 ->
[%{type: "page", number: page}]
{page, next} when next - page > 1 ->
[%{type: "page", number: page}, %{type: "..."}]
_ ->
[]
end
end)
|> Enum.map(fn item ->
case item do
%{type: "page"} ->
item
|> Map.put(:first?, item.number == first_page)
|> Map.put(:current?, item.number == current_page)
|> Map.put(:last?, item.number == last_page)
_ ->
item
end
end)
|> Enum.flat_map(fn item ->
case item do
%{first?: true, current?: true, last?: true} when total_pages > 1 ->
[
get_prev_item(current_page, total_pages),
item,
get_next_item(current_page, total_pages)
]
%{first?: true, last?: false} when total_pages > 1 ->
[
get_prev_item(current_page, total_pages),
item
]
%{first?: false, last?: true} when total_pages > 1 ->
[
item,
get_next_item(current_page, total_pages)
]
_ ->
[item]
end
end)
end
defp get_prev_item(current_page, _total_pages) do
%{
type: "prev",
number: max(1, current_page - 1),
enabled?: current_page > 1
}
end
defp get_next_item(current_page, total_pages) do
%{
type: "next",
number: min(current_page + 1, total_pages),
enabled?: current_page < total_pages
}
end
end