|
17 | 17 |
|
18 | 18 |
|
19 | 19 | class _WithChildrenUnbound(t.Generic[C, P, R]): |
20 | | - """Decorator to make a component support children nodes. |
21 | | -
|
22 | | - This decorator is used to create a component that can accept children nodes, |
23 | | - just like native htpy components. |
24 | | -
|
25 | | - It lets you convert this: |
26 | | -
|
27 | | - ```python |
28 | | - def my_component(*, title: str, children: h.Node) -> h.Renderable: |
29 | | - ... |
30 | | -
|
31 | | - my_component(title="My title", children=h.div["My content"]) |
32 | | - ``` |
33 | | -
|
34 | | - To this: |
35 | | -
|
36 | | - ```python |
37 | | - @h.with_children |
38 | | - def my_component(children: h.Node, *, title: str) -> h.Renderable: |
39 | | - ... |
40 | | -
|
41 | | - my_component(title="My title")[h.div["My content"]] |
42 | | - ``` |
43 | | - """ |
44 | | - |
45 | 20 | wrapped: Callable[t.Concatenate[C | None, P], R] |
46 | 21 |
|
47 | 22 | def __init__(self, func: Callable[t.Concatenate[C | None, P], R]) -> None: |
48 | 23 | # This instance is created at import time when decorating the component. |
49 | 24 | # It means that this object is global, and shared between all renderings |
50 | 25 | # of the same component. |
51 | 26 | self.wrapped = func |
52 | | - functools.update_wrapper(self, func) |
53 | 27 |
|
54 | 28 | def __repr__(self) -> str: |
55 | 29 | return f"with_children({self.wrapped.__name__}, <unbound>)" |
@@ -139,4 +113,24 @@ def iter_chunks( |
139 | 113 | return self._func(None, *self._args, **self._kwargs).iter_chunks(context) |
140 | 114 |
|
141 | 115 |
|
142 | | -with_children = _WithChildrenUnbound |
| 116 | +def with_children( |
| 117 | + func: Callable[t.Concatenate[C | None, P], R], |
| 118 | +) -> _WithChildrenUnbound[C | None, P, R]: |
| 119 | + """Decorator to make a component support children nodes. |
| 120 | +
|
| 121 | + This decorator allows you to create components that can accept children nodes |
| 122 | + using the bracket notation, similar to native htpy components. |
| 123 | +
|
| 124 | + Example: |
| 125 | + @with_children |
| 126 | + def my_component(children: Node, *, title: str) -> Renderable: |
| 127 | + return div(class_="container")[h1[title], children] |
| 128 | +
|
| 129 | + # Usage: |
| 130 | + my_component(title="Hello")[span["World"]] |
| 131 | + """ |
| 132 | + wrapper = _WithChildrenUnbound(func) |
| 133 | + # Ensure the wrapper has the same signature as the original function |
| 134 | + # This is crucial for LSP to recognize the function arguments |
| 135 | + functools.update_wrapper(wrapper, func) |
| 136 | + return wrapper |
0 commit comments