Skip to content

Instantly share code, notes, and snippets.

@bessey
Created March 25, 2024 22:59
Show Gist options
  • Save bessey/36bb432288fc268a7ea59131509f8132 to your computer and use it in GitHub Desktop.
Save bessey/36bb432288fc268a7ea59131509f8132 to your computer and use it in GitHub Desktop.
from typing import Any, Callable, Self
from htpy import (
Element,
Node,
Iterator,
Attribute,
_id_class_names_from_css_str,
_kwarg_attribute_name,
div,
button,
span,
)
from markupsafe import Markup as _Markup
class Component(Element):
def __init__(
self, func: Callable[[Any], Any], attrs: dict[str, Attribute], children: Node
) -> None:
self._name = func.__name__
self._func = func
self._attrs = attrs
self._children = children
def __iter__(self) -> Iterator[str]:
yield from self._func(**self._attrs, children=self._children)
def __call__(self, *args: Any, **kwargs: Any) -> Self:
id_class = ""
attrs: dict[str, Attribute] = {}
if len(args) == 1:
if isinstance(args[0], str):
# element(".foo")
id_class = args[0]
attrs = {}
else:
# element({"foo": "bar"})
id_class = ""
attrs = args[0]
elif len(args) == 2:
# element(".foo", {"bar": "baz"})
id_class, attrs = args
return self.__class__(
self._func,
{
**self._attrs,
**(_id_class_names_from_css_str(id_class) if id_class else {}),
**attrs,
**{_kwarg_attribute_name(k): v for k, v in kwargs.items()},
},
self._children,
)
def __getitem__(self, children: Node) -> Self:
return self.__class__(self._func, self._attrs, children)
def component(func):
return Component(func, {}, None)
@component
def bootstrap_modal(*, children: Node) -> Element:
return div(".modal", tabindex="-1", role="dialog")[
div(".modal-dialog", role="document")[div(".modal-content")[children]]
]
@component
def bootstrap_header(*, closeable: bool, children: Node) -> Element:
close_button = button(
".close",
type="button",
data_dismiss="modal",
aria_label="Close",
)[span(aria_hidden="true")[_Markup("×")]]
return div(".modal-header")[
div(".modal-title")[
children,
close_button if closeable else None,
]
]
@component
def bootstrap_body(*, children: Node) -> Element:
return div(".modal-body")[children]
@component
def bootstrap_footer(*, children: Node) -> Element:
return div(".modal-footer")[children]
print(
bootstrap_modal[
bootstrap_header(closeable=True)["Hello, World!"],
bootstrap_body["Lorem ipsum"],
bootstrap_footer["Etc!"],
]
)
# <div class="modal" tabindex="-1" role="dialog"><div class="modal-dialog" role="document"><div class="modal-content"><div class="modal-header"><div class="modal-title">Hello, World!<button class="close" type="button" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">&times;</span></button></div></div><div class="modal-body">Lorem ipsum</div><div class="modal-footer">Etc!</div></div></div></div>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment