Coverage for src / lexigram / admin / ui / molecules / jump_to_page.py: 30%
20 statements
« prev ^ index » next coverage.py v7.13.5, created at 2026-08-11 02:25 +0800
« prev ^ index » next coverage.py v7.13.5, created at 2026-08-11 02:25 +0800
1from __future__ import annotations
3from typing import Any
5from lexigram.ui import Component, NumberInput, Zones, el
8class JumpToPage(Component):
9 """
10 Component for jumping to a specific page number.
11 Uses Zone-based targeting for consistent HTMX behavior.
12 """
14 def __init__(
15 self,
16 page: int = 1,
17 total_pages: int = 1,
18 per_page: int = 20,
19 base_url: str = "",
20 extra_query: str = "",
21 hx_target: str | None = None,
22 hx_swap: str = "innerHTML",
23 hx_push_url: str = "true",
24 state: Any | None = None,
25 **props,
26 ) -> None:
27 super().__init__(**props)
28 self.page = page
29 self.total_pages = total_pages
30 self.per_page = per_page
31 self.base_url = base_url
32 self.extra_query = extra_query
33 # Use Zones.DATA by default
34 self.hx_target = hx_target or Zones.DATA.selector
35 self.hx_swap = hx_swap
36 self.hx_push_url = hx_push_url
37 self.state = state
39 def render(self) -> Any:
40 # Build consistent HTMX attrs using new API
42 if self.state:
43 # Use clean URL with full state include to avoid duplication and state loss
44 htmx_attrs = {
45 "hx-get": f"{self.base_url.rstrip('/')}/",
46 "hx-target": self.hx_target,
47 "hx-swap": self.hx_swap,
48 "hx-select": Zones.DATA.selector,
49 "hx-push-url": "true",
50 "hx-trigger": "change, keydown[key=='Enter']",
51 "hx-include": f"{Zones.TABLE.selector} [name]",
52 "hx-params": "*",
53 }
54 else:
55 # Fallback for simple usage
56 htmx_attrs = {
57 "hx-get": f"{self.base_url}?per_page={self.per_page}{self.extra_query}",
58 "hx-target": self.hx_target,
59 "hx-swap": self.hx_swap,
60 "hx-select": Zones.DATA.selector,
61 "hx-push_url": str(self.hx_push_url).lower(),
62 "hx-trigger": "change, keydown[key=='Enter']",
63 "hx-include": "this",
64 }
66 return el(
67 "div",
68 el(
69 "label",
70 "Go to",
71 class_="text-sm text-muted-foreground mr-2",
72 ),
73 NumberInput(
74 name="page",
75 label=None,
76 value=self.page,
77 min=1,
78 max=self.total_pages,
79 class_="w-16 text-center text-sm",
80 **{k.replace("-", "_"): v for k, v in htmx_attrs.items()}, # type: ignore[arg-type]
81 ),
82 class_="flex items-center",
83 )