Coverage for src / lexigram / admin / ui / columns / column / config.py: 39%
56 statements
« prev ^ index » next coverage.py v7.13.5, created at 2026-08-11 17:07 +0800
« prev ^ index » next coverage.py v7.13.5, created at 2026-08-11 17:07 +0800
1"""
2Column configuration methods for fluent API.
3"""
5from __future__ import annotations
7from typing import Any, Self
10class ColumnConfigMixin:
11 """Mixin class containing all column configuration methods."""
13 def sortable(self, sortable: bool = True) -> Self:
14 """Make column sortable in the DataTable.
16 When enabled, clicking the column header will toggle between
17 ascending and descending sort order. A sort indicator (↑/↓)
18 will be displayed in the header.
20 Args:
21 sortable: Whether to enable sorting (default: True)
23 Returns:
24 Self for method chaining
26 Example:
27 >>> # Enable sorting
28 >>> TextColumn("name").sortable()
29 >>>
30 >>> # Disable sorting
31 >>> TextColumn("id").sortable(False)
32 >>>
33 >>> # Chain with other methods
34 >>> TextColumn("email").sortable().searchable().copyable()
35 """
36 self._sortable = sortable
37 return self
39 def searchable(self, searchable: bool = True) -> Self:
40 """Include column in global search.
42 When enabled, this column's values will be included in the
43 DataTable's global search functionality.
45 Args:
46 searchable: Whether to include in search (default: True)
48 Returns:
49 Self for method chaining
51 Example:
52 >>> TextColumn("name").searchable()
53 >>> TextColumn("email").searchable().sortable()
54 """
55 self._searchable = searchable
56 return self
58 def toggleable(self, toggleable: bool = True) -> Self:
59 """Allow showing/hiding column in UI.
61 When enabled, users can toggle column visibility through
62 the DataTable's column visibility controls.
64 Args:
65 toggleable: Whether column can be toggled (default: True)
67 Returns:
68 Self for method chaining
70 Example:
71 >>> TextColumn("description").toggleable()
72 >>> TextColumn("id").toggleable(False) # Always visible
73 """
74 self._toggleable = toggleable
75 return self
77 def copyable(self, copyable: bool = True) -> Self:
78 """Add click-to-copy functionality.
80 When enabled, clicking the cell will copy its value to the
81 clipboard. A visual indicator will show on hover.
83 Args:
84 copyable: Whether to enable click-to-copy (default: True)
86 Returns:
87 Self for method chaining
89 Example:
90 >>> TextColumn("api_key").copyable()
91 >>> TextColumn("email").copyable().searchable()
92 """
93 self._copyable = copyable
94 return self
96 def filterable(self, filter_instance: Any = True) -> Self:
97 """Mark column as filterable with optional filter configuration.
99 Can accept either:
100 - True (default): Mark as filterable with default filter behavior
101 - Filter instance: Specific filter configuration (SelectFilter, RangeFilter, etc.)
103 Args:
104 filter_instance: Boolean or Filter instance (SelectFilter, RangeFilter, ToggleFilter, MultiSelectFilter)
106 Returns:
107 Self for method chaining
109 Example:
110 >>> from lexigram.admin.ui.filters import SelectFilter, RangeFilter
111 >>>
112 >>> # Simple boolean
113 >>> TextColumn("status").filterable()
114 >>>
115 >>> # With SelectFilter
116 >>> BadgeColumn("species").filterable(SelectFilter(
117 ... options={"dog": "Dogs", "cat": "Cats"},
118 ... label="Species"
119 ... ))
120 >>>
121 >>> # With RangeFilter
122 >>> DateColumn("birth_date").filterable(RangeFilter(
123 ... label="Birth Date Range"
124 ... ))
125 """
126 if filter_instance is True:
127 self._filterable = True
128 self._filter_instance = None
129 else:
130 self._filterable = True
131 self._filter_instance = filter_instance
132 # Store filter instance with column name if not explicitly set
133 if hasattr(filter_instance, "name"):
134 # Check for "unnamed_field" (Field class default) or empty name
135 current_name = filter_instance.name
136 if not current_name or current_name == "unnamed_field":
137 filter_instance.name = self.name # type: ignore[attr-defined]
138 return self
140 def exportable(self, exportable: bool = True) -> Self:
141 """Include column in data exports.
143 When enabled, this column will be included when exporting
144 DataTable data to CSV, Excel, or other formats.
146 Args:
147 exportable: Whether to include in exports (default: True)
149 Returns:
150 Self for method chaining
152 Example:
153 >>> TextColumn("name").exportable()
154 >>> ImageColumn("avatar").exportable(False) # Skip images
155 """
156 self._exportable = exportable
157 return self
159 def limit(self, chars: int) -> Self:
160 """Truncate text to specified character limit.
162 Text longer than the limit will be truncated with an ellipsis (...).
164 Args:
165 chars: Maximum number of characters to display
167 Returns:
168 Self for method chaining
170 Example:
171 >>> TextColumn("description").limit(100)
172 >>> TextColumn("email").limit(50).copyable()
173 """
174 self._limit = chars
175 return self
177 def wrap(self, wrap: bool = True) -> Self:
178 """Enable word wrapping for long content.
180 When enabled, long text will wrap to multiple lines instead
181 of being truncated or overflowing.
183 Args:
184 wrap: Whether to enable word wrapping (default: True)
186 Returns:
187 Self for method chaining
189 Example:
190 >>> TextColumn("description").wrap()
191 >>> TextColumn("notes").wrap().limit(200)
192 """
193 self._wrap = wrap
194 return self
196 def width(self, pixels: int | str) -> Self:
197 """Set column width.
199 Accepts either a numeric value (treated as `rem` units) or a
200 string with explicit units (e.g. '200px' or '10%').
202 Args:
203 pixels: Width in rem when numeric, or an explicit CSS width string
205 Returns:
206 Self for method chaining
208 Example:
209 >>> TextColumn("id").width(4) # 4rem
210 >>> TextColumn("name").width('200px') # 200px
211 """
212 self._width = pixels
213 return self
215 def grow(self, grow: bool = True) -> Self:
216 """Control whether this column is allowed to grow (fluid).
218 When grow is True (default), and no explicit width is set, the
219 column will receive a Tailwind `w-full`/`min-w-0` treatment so
220 it can expand to fill available space. When False, the column
221 will be sized tightly to its content.
222 """
223 self._grow = grow
224 return self
226 def tooltip(self, text: str) -> Self:
227 """Add tooltip to column header.
229 Displays helpful information when hovering over the column header.
231 Args:
232 text: Tooltip text to display
234 Returns:
235 Self for method chaining
237 Example:
238 >>> TextColumn("api_key").tooltip("Click to copy API key")
239 >>> DateColumn("created_at").tooltip("Account creation date")
240 """
241 self._tooltip = text
242 return self
244 def align_left(self) -> Self:
245 """Align content to the left.
247 Returns:
248 Self for method chaining
250 Example:
251 >>> TextColumn("name").align_left()
252 """
253 self._alignment = "left"
254 return self
256 def align_center(self) -> Self:
257 """Align content to the center.
259 Returns:
260 Self for method chaining
262 Example:
263 >>> TextColumn("status").align_center()
264 """
265 self._alignment = "center"
266 return self
268 def align_right(self) -> Self:
269 """Align content to the right.
271 Commonly used for numeric columns.
273 Returns:
274 Self for method chaining
276 Example:
277 >>> CurrencyColumn("price").align_right()
278 >>> TextColumn("count").align_right().sortable()
279 """
280 self._alignment = "right"
281 return self
283 def pinned(self, position: str = "left") -> Self:
284 """Pin column to the side.
286 Pinned columns remain visible when horizontally scrolling
287 the DataTable.
289 Args:
290 position: 'left' or 'right' (default: 'left')
292 Returns:
293 Self for method chaining
294 """
295 self._pinned = position
296 return self