fh-matui 0.9.8__py3-none-any.whl → 0.9.9__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
fh_matui/__init__.py CHANGED
@@ -1 +1 @@
1
- __version__ = "0.9.7"
1
+ __version__ = "0.9.8"
fh_matui/datatable.py CHANGED
@@ -22,10 +22,50 @@ from .components import *
22
22
  from math import ceil
23
23
  from urllib.parse import urlencode
24
24
  from typing import Callable, Optional, Any
25
+ from dataclasses import asdict, is_dataclass
25
26
 
26
27
  # Default page size options
27
28
  PAGE_SIZES = [5, 10, 20, 50]
28
29
 
30
+
31
+ def _to_dict(obj: Any) -> dict:
32
+ """
33
+ Convert any record type to dict.
34
+
35
+ Handles:
36
+ - dict -> pass through
37
+ - dataclass -> asdict()
38
+ - namedtuple -> _asdict()
39
+ - Pydantic model -> model_dump() or dict()
40
+ - ORM/object with __dict__ -> vars() filtered
41
+ - dict-like with keys -> dict()
42
+ - None -> {}
43
+ """
44
+ if obj is None:
45
+ return {}
46
+ if isinstance(obj, dict):
47
+ return obj
48
+ # Dataclass
49
+ if is_dataclass(obj) and not isinstance(obj, type):
50
+ return asdict(obj)
51
+ # Namedtuple
52
+ if hasattr(obj, '_asdict'):
53
+ return obj._asdict()
54
+ # Pydantic v2
55
+ if hasattr(obj, 'model_dump'):
56
+ return obj.model_dump()
57
+ # Pydantic v1
58
+ if hasattr(obj, 'dict') and callable(getattr(obj, 'dict')):
59
+ return obj.dict()
60
+ # ORM-style objects with __dict__
61
+ if hasattr(obj, "__dict__"):
62
+ return {k: v for k, v in obj.__dict__.items() if not k.startswith("_")}
63
+ # Dict-like
64
+ if hasattr(obj, 'keys'):
65
+ return dict(obj)
66
+ return {}
67
+
68
+
29
69
  def _safe_int(value, default):
30
70
  """Safely convert to positive int or return default."""
31
71
  try:
@@ -173,6 +213,9 @@ def DataTable(
173
213
  container_id = container_id or f"crud-table-{base_route.replace('/', '-').strip('-')}"
174
214
  feedback_id = f"{container_id}-feedback"
175
215
 
216
+ # Auto-convert data records to dicts (supports dataclass, namedtuple, Pydantic, ORM)
217
+ data = [_to_dict(r) for r in data]
218
+
176
219
  # Auto-generate columns from first data row if not provided
177
220
  if columns is None and data:
178
221
  columns = [{"key": k, "label": k.replace("_", " ").title()} for k in data[0].keys()]
@@ -279,22 +322,27 @@ def DataTable(
279
322
  cls="field prefix"
280
323
  ),
281
324
  Input(type="hidden", name="page_size", value=page_size),
282
- cls="row"
325
+ cls="max"
283
326
  )
284
327
 
328
+ # Build table with proper Thead/Tbody structure
329
+ data_table = Table(
330
+ Thead(Tr(*[Th(label) for label in header_labels])),
331
+ Tbody(*[
332
+ Tr(*[Td(row_dict.get(key, '')) for key in header_keys])
333
+ for row_dict in table_rows
334
+ ]),
335
+ cls="border"
336
+ ) if data else Div(empty_message, cls="center-align padding")
337
+
285
338
  return Article(
286
339
  Div(id=feedback_id), # Feedback container for modals/toasts
287
340
  Div(
288
341
  search_form,
289
342
  create_button,
290
- cls="grid"
343
+ cls="row"
291
344
  ),
292
- Table(
293
- *table_rows,
294
- headers=header_labels,
295
- keys=header_keys,
296
- cls="border"
297
- ) if data else Div(empty_message, cls="center-align padding"),
345
+ data_table,
298
346
  Div(
299
347
  Div(
300
348
  _page_size_select(page_size, search, base_route, container_id, page_sizes),
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: fh-matui
3
- Version: 0.9.8
3
+ Version: 0.9.9
4
4
  Summary: material-ui for fasthtml
5
5
  Home-page: https://github.com/abhisheksreesaila/fh-matui
6
6
  Author: abhishek sreesaila
@@ -1,14 +1,14 @@
1
- fh_matui/__init__.py,sha256=83qFJMFAgvdHV5e8Nh9ByUaQinNxBUPlTKjxfpge3xM,23
1
+ fh_matui/__init__.py,sha256=4eQCGJV2-GRHX8FlvA_4etK0E4LFj2or592J4aePZoA,23
2
2
  fh_matui/_modidx.py,sha256=naHwPQ4kCo-5saE_uozmdPA881kp1gnqvKhmaG-Ya-4,23914
3
3
  fh_matui/app_pages.py,sha256=Sn9-tgBpaPNbR-0nZtPLoSCmAWLOGB4UQ88IkFvzBRY,10361
4
4
  fh_matui/components.py,sha256=KjdTHzWRXpVWBEIGskW1HfhjPpzRYzi6UA_yRjZyMWM,48254
5
5
  fh_matui/core.py,sha256=xtVBN8CtC50ZJ4Iu7o-mUhaA87tWdnz8gBfKRk63Zhs,10680
6
- fh_matui/datatable.py,sha256=UWS4PlFl2WjmgU54GLc4CJCS4wiLpDsUyX9MDdwRXWY,35117
6
+ fh_matui/datatable.py,sha256=NNb6WvGZ0QY13md4itwYH4a9yKZrOdwcaDW7PGo-vQM,36558
7
7
  fh_matui/foundations.py,sha256=b7PnObJpKN8ZAU9NzCm9xpfnHzFjjAROU7E2YvA_tj4,1820
8
8
  fh_matui/web_pages.py,sha256=4mF-jpfVcZTVepfQ-aMGgIUp-nBp0YCkvcdsWhUYeaA,34879
9
- fh_matui-0.9.8.dist-info/licenses/LICENSE,sha256=xV8xoN4VOL0uw9X8RSs2IMuD_Ss_a9yAbtGNeBWZwnw,11337
10
- fh_matui-0.9.8.dist-info/METADATA,sha256=WcGOgoryZOSjmfJPM21WIEbrB_55uVwtzD-Y0JCbbQA,10490
11
- fh_matui-0.9.8.dist-info/WHEEL,sha256=qELbo2s1Yzl39ZmrAibXA2jjPLUYfnVhUNTlyF1rq0Y,92
12
- fh_matui-0.9.8.dist-info/entry_points.txt,sha256=zn4CR4gNTiAAxbFsCxHAf2tQhtW29_YOffjbUTgeoWI,38
13
- fh_matui-0.9.8.dist-info/top_level.txt,sha256=l80d5eoA2ZjqtPYwAorLMS5PiHxUxz3zKzxMJ41Xoso,9
14
- fh_matui-0.9.8.dist-info/RECORD,,
9
+ fh_matui-0.9.9.dist-info/licenses/LICENSE,sha256=xV8xoN4VOL0uw9X8RSs2IMuD_Ss_a9yAbtGNeBWZwnw,11337
10
+ fh_matui-0.9.9.dist-info/METADATA,sha256=OGoxCFS3_qRnEJe2EkD-dMDl21lhYt5ecds1B6f5xpU,10490
11
+ fh_matui-0.9.9.dist-info/WHEEL,sha256=qELbo2s1Yzl39ZmrAibXA2jjPLUYfnVhUNTlyF1rq0Y,92
12
+ fh_matui-0.9.9.dist-info/entry_points.txt,sha256=zn4CR4gNTiAAxbFsCxHAf2tQhtW29_YOffjbUTgeoWI,38
13
+ fh_matui-0.9.9.dist-info/top_level.txt,sha256=l80d5eoA2ZjqtPYwAorLMS5PiHxUxz3zKzxMJ41Xoso,9
14
+ fh_matui-0.9.9.dist-info/RECORD,,