From 09c4217cb6c49b5a447971c2252de36104847380 Mon Sep 17 00:00:00 2001 From: Kodjo Sossouvi Date: Sat, 15 Nov 2025 23:49:37 +0100 Subject: [PATCH] Adding search control --- src/myfasthtml/controls/Search.py | 55 ++++++++++++++++++++++++++ src/myfasthtml/controls/TabsManager.py | 11 ++++-- src/myfasthtml/controls/helpers.py | 1 + src/myfasthtml/core/commands.py | 6 ++- 4 files changed, 69 insertions(+), 4 deletions(-) create mode 100644 src/myfasthtml/controls/Search.py diff --git a/src/myfasthtml/controls/Search.py b/src/myfasthtml/controls/Search.py new file mode 100644 index 0000000..78cf9e2 --- /dev/null +++ b/src/myfasthtml/controls/Search.py @@ -0,0 +1,55 @@ +import logging + +from fasthtml.components import * + +from myfasthtml.controls.BaseCommands import BaseCommands +from myfasthtml.controls.helpers import Ids, mk +from myfasthtml.core.commands import Command +from myfasthtml.core.instances import MultipleInstance + +logger = logging.getLogger("Search") + + +class Commands(BaseCommands): + def search(self): + return (Command("Search", f"Search {self._owner.items_names}", self._owner.search). + htmx(trigger="keyup changed delay:300ms")) + + +class Search(MultipleInstance): + def __init__(self, session, items_names=None, template=None, _id=None): + super().__init__(session, Ids.Search, _id=_id) + self.items_names = items_names + self.items = [] + self.filtered = [] + self.template = template or Div + self.commands = Commands(self) + + def set_items(self, items): + self.items = items + self.filtered = self.items + return self + + def search(self, query): + logger.debug(f"search {query=}") + pass + + def _mk_search_results(self): + return [self.template(item) for item in self.filtered] + + def render(self): + return Div( + # mk.mk(Input(name="query", id=f"{self._id}-search", type="text", placeholder="Search...", cls="input input-xs"), + # command=self.commands.search()), + mk.mk(Input(name="query", id=f"{self._id}-search", type="search", placeholder="Search...", cls="input input-xs"), + ), + Div( + *self._mk_search_results(), + id=f"{self._id}-results", + cls="mf-search-results", + ), + id=f"{self._id}", + ) + + def __ft__(self): + return self.render() diff --git a/src/myfasthtml/controls/TabsManager.py b/src/myfasthtml/controls/TabsManager.py index 6d42d7b..9334dba 100644 --- a/src/myfasthtml/controls/TabsManager.py +++ b/src/myfasthtml/controls/TabsManager.py @@ -7,6 +7,7 @@ from fasthtml.common import Div, Span from fasthtml.xtend import Script from myfasthtml.controls.BaseCommands import BaseCommands +from myfasthtml.controls.Search import Search from myfasthtml.controls.VisNetwork import VisNetwork from myfasthtml.controls.helpers import Ids, mk from myfasthtml.core.commands import Command @@ -96,6 +97,7 @@ class TabsManager(MultipleInstance): self._state = TabsManagerState(self) self.commands = Commands(self) self._boundaries = Boundaries() + self._search = Search(self._session).set_items(self._get_tabs_labels()) logger.debug(f"TabsManager created with id: {self._id}") logger.debug(f" tabs : {self._get_ordered_tabs()}") logger.debug(f" active tab : {self._state.active_tab}") @@ -191,6 +193,7 @@ class TabsManager(MultipleInstance): # finally, update the state self._state.update(state) + self._search.set_items(self._get_tabs_labels()) return tab_id @@ -248,6 +251,7 @@ class TabsManager(MultipleInstance): # Update state self._state.update(state) + self._search.set_items(self._get_tabs_labels()) return self @@ -365,9 +369,7 @@ class TabsManager(MultipleInstance): role="button", cls="btn btn-xs"), Div( - Div("content"), - Div("content"), - Div("content"), + self._search, tabindex="-1", cls="dropdown-content menu w-52 rounded-box bg-base-300 shadow-xl" ), @@ -380,6 +382,9 @@ class TabsManager(MultipleInstance): hx_swap_oob=f"beforeend:#{self._id}-content-wrapper", ) + def _get_tabs_labels(self): + return [tab["label"] for tab in self._state.tabs.values()] + def update_boundaries(self): return Script(f"updateBoundaries('{self._id}');") diff --git a/src/myfasthtml/controls/helpers.py b/src/myfasthtml/controls/helpers.py index 3630ae6..cebab03 100644 --- a/src/myfasthtml/controls/helpers.py +++ b/src/myfasthtml/controls/helpers.py @@ -11,6 +11,7 @@ class Ids: Boundaries = "mf-boundaries" DbManager = "mf-dbmanager" Layout = "mf-layout" + Search = "mf-search" TabsManager = "mf-tabs-manager" UserProfile = "mf-user-profile" VisNetwork = "mf-vis-network" diff --git a/src/myfasthtml/core/commands.py b/src/myfasthtml/core/commands.py index a442a3b..5841a6f 100644 --- a/src/myfasthtml/core/commands.py +++ b/src/myfasthtml/core/commands.py @@ -44,7 +44,7 @@ class BaseCommand: def execute(self, client_response: dict = None): raise NotImplementedError - def htmx(self, target="this", swap="innerHTML"): + def htmx(self, target="this", swap="innerHTML", trigger=None): if target is None: self._htmx_extra["hx-swap"] = "none" elif target != "this": @@ -54,6 +54,10 @@ class BaseCommand: self._htmx_extra["hx-swap"] = "none" elif swap != "innerHTML": self._htmx_extra["hx-swap"] = swap + + if trigger is not None: + self._htmx_extra["hx-trigger"] = trigger + return self def bind_ft(self, ft):