Support class-based components
This release contains a big set of changes to support class-based components, as described in #53.
In addition to writing standard function-based components:
from typing import Iterable
from tdom import html
def FunctionComponent(children: Iterable[Node], something: int) -> Node:
return html(t"<div>Something: {something}<br />{children}</div>")
result = html(t"<{FunctionComponent} something={42}><p>hi</p></{FunctionComponent}>")
# <div>Something: 42<br /><p>hi</p></div>You can now write class-based components:
from dataclasses import dataclass, field
from typing import Any, Iterable
from tdom import Node, html
@dataclass
class Card:
children: Iterable[Node]
title: str
subtitle: str | None = None
def __call__(self) -> Node:
return html(t"""
<div class='card'>
<h2>{self.title}</h2>
{self.subtitle and t'<h3>{self.subtitle}</h3>'}
<div class="content">{self.children}</div>
</div>
""")
result = html(t"<{Card} title='My Card' subtitle='A subtitle'><p>Card content</p></{Card}>")
# <div class='card'>
# <h2>My Card</h2>
# <h3>A subtitle</h3>
# <div class="content"><p>Card content</p></div>
# </div>There are a number of under-the-hood changes to support this.
Also, we've now officially achieved 100% statement coverage.