from fastcore.basics import NotStr from core.utils import merge_classes attr_map = { "cls": "class", "_id": "id", } def safe_attr(attr_name): attr_name = attr_name.replace("hx_", "hx-") attr_name = attr_name.replace("data_", "data-") return attr_map.get(attr_name, attr_name) def to_html(item): if item is None: return "" elif isinstance(item, str): return item elif isinstance(item, (int, float, bool)): return str(item) elif isinstance(item, MyFt): return item.to_html() elif isinstance(item, NotStr): return str(item) else: raise Exception(f"Unsupported type: {type(item)}, {item=}") class MyFt: def __init__(self, tag, *args, **kwargs): self.tag = tag self.children = args self.attrs = {safe_attr(k): v for k, v in kwargs.items()} def to_html(self): body_items = [to_html(item) for item in self.children] return f"<{self.tag} {' '.join(f'{k}="{v}"' for k, v in self.attrs.items())}>{' '.join(body_items)}" def __ft__(self): return NotStr(self.to_html()) class MyDiv(MyFt): def __init__(self, *args, **kwargs): super().__init__("div", *args, **kwargs) class MySpan(MyFt): def __init__(self, *args, **kwargs): super().__init__("span", *args, **kwargs) def mk_my_ellipsis(txt: str, cls='', **kwargs): merged_cls = merge_classes("truncate", cls, kwargs) return MyDiv(txt, cls=merged_cls, data_tooltip=txt, **kwargs) def mk_my_icon(icon, size=20, can_select=True, can_hover=False, cls='', tooltip=None, **kwargs): merged_cls = merge_classes(f"icon-{size}", 'icon-btn' if can_select else '', 'mmt-btn' if can_hover else '', cls, kwargs) return mk_my_tooltip(icon, tooltip, cls=merged_cls, **kwargs) if tooltip else MyDiv(icon, cls=merged_cls, **kwargs) def mk_my_tooltip(element, tooltip: str, cls='', **kwargs): merged_cls = merge_classes("mmt-tooltip", cls, kwargs) return MyDiv(element, cls=merged_cls, data_tooltip=tooltip, **kwargs)