First set of upgrades for the Panel component
This commit is contained in:
@@ -5,23 +5,37 @@ from fasthtml.components import Div
|
||||
from fasthtml.xtend import Script
|
||||
|
||||
from myfasthtml.controls.BaseCommands import BaseCommands
|
||||
from myfasthtml.controls.helpers import mk
|
||||
from myfasthtml.core.commands import Command
|
||||
from myfasthtml.core.dbmanager import DbObject
|
||||
from myfasthtml.core.instances import MultipleInstance
|
||||
from myfasthtml.icons.fluent_p1 import more_horizontal20_regular
|
||||
from myfasthtml.icons.fluent_p2 import subtract20_regular
|
||||
|
||||
|
||||
@dataclass
|
||||
class PanelConf:
|
||||
left: bool = False
|
||||
left: bool = True
|
||||
right: bool = True
|
||||
|
||||
|
||||
class PanelState(DbObject):
|
||||
def __init__(self, owner, name=None):
|
||||
super().__init__(owner, name=name)
|
||||
with self.initializing():
|
||||
self.left_visible: bool = True
|
||||
self.right_visible: bool = True
|
||||
self.left_width: int = 250
|
||||
self.right_width: int = 250
|
||||
|
||||
|
||||
class Commands(BaseCommands):
|
||||
def toggle_side(self, side: Literal["left", "right"]):
|
||||
def toggle_side(self, side: Literal["left", "right"], visible: bool = None):
|
||||
return Command("TogglePanelSide",
|
||||
f"Toggle {side} side panel",
|
||||
self._owner,
|
||||
self._owner.toggle_side,
|
||||
args=[side])
|
||||
args=[side, visible]).htmx(target=f"#{self._id}_panel_{side}")
|
||||
|
||||
def update_side_width(self, side: Literal["left", "right"]):
|
||||
"""
|
||||
@@ -37,7 +51,7 @@ class Commands(BaseCommands):
|
||||
f"Update {side} side panel width",
|
||||
self._owner,
|
||||
self._owner.update_side_width,
|
||||
args=[side])
|
||||
args=[side]).htmx(target=f"#{self._id}_panel_{side}")
|
||||
|
||||
|
||||
class Panel(MultipleInstance):
|
||||
@@ -54,15 +68,26 @@ class Panel(MultipleInstance):
|
||||
super().__init__(parent, _id=_id)
|
||||
self.conf = conf or PanelConf()
|
||||
self.commands = Commands(self)
|
||||
self._state = PanelState(self)
|
||||
self._main = None
|
||||
self._right = None
|
||||
self._left = None
|
||||
|
||||
def update_side_width(self, side, width):
|
||||
pass
|
||||
if side == "left":
|
||||
self._state.left_width = width
|
||||
else:
|
||||
self._state.right_width = width
|
||||
|
||||
return self._mk_panel(side)
|
||||
|
||||
def toggle_side(self, side):
|
||||
pass
|
||||
def toggle_side(self, side, visible):
|
||||
if side == "left":
|
||||
self._state.left_visible = visible
|
||||
else:
|
||||
self._state.right_visible = visible
|
||||
|
||||
return self._mk_panel(side), self._mk_show_icon(side)
|
||||
|
||||
def set_main(self, main):
|
||||
self._main = main
|
||||
@@ -76,35 +101,82 @@ class Panel(MultipleInstance):
|
||||
self._left = left
|
||||
return Div(self._left, id=f"{self._id}_l")
|
||||
|
||||
def _mk_right(self):
|
||||
if not self.conf.right:
|
||||
def _mk_panel(self, side: Literal["left", "right"]):
|
||||
enabled = self.conf.left if side == "left" else self.conf.right
|
||||
if not enabled:
|
||||
return None
|
||||
|
||||
visible = self._state.left_visible if side == "left" else self._state.right_visible
|
||||
content = self._right if side == "right" else self._left
|
||||
|
||||
resizer = Div(
|
||||
cls="mf-resizer mf-resizer-right",
|
||||
data_command_id=self.commands.update_side_width("right").id,
|
||||
data_side="right"
|
||||
cls=f"mf-resizer mf-resizer-{side}",
|
||||
data_command_id=self.commands.update_side_width(side).id,
|
||||
data_side=side
|
||||
)
|
||||
|
||||
return Div(resizer, Div(self._right, id=f"{self._id}_r"), cls="mf-panel-right")
|
||||
hide_icon = mk.icon(
|
||||
subtract20_regular,
|
||||
size=20,
|
||||
command=self.commands.toggle_side(side, False),
|
||||
cls="mf-panel-hide-icon"
|
||||
)
|
||||
|
||||
panel_cls = f"mf-panel-{side}"
|
||||
if not visible:
|
||||
panel_cls += " mf-hidden"
|
||||
|
||||
# Left panel: content then resizer (resizer on the right)
|
||||
# Right panel: resizer then content (resizer on the left)
|
||||
if side == "left":
|
||||
return Div(
|
||||
Div(hide_icon, content, id=f"{self._id}_content_{side}"),
|
||||
resizer,
|
||||
cls=panel_cls,
|
||||
id=f"{self._id}_panel_{side}"
|
||||
)
|
||||
else:
|
||||
return Div(
|
||||
resizer,
|
||||
Div(hide_icon, content, id=f"{self._id}_content_{side}"),
|
||||
cls=panel_cls,
|
||||
id=f"{self._id}_panel_{side}"
|
||||
)
|
||||
|
||||
def _mk_left(self):
|
||||
if not self.conf.left:
|
||||
def _mk_show_icon(self, side: Literal["left", "right"]):
|
||||
"""
|
||||
Create show icon for a panel side if it's hidden.
|
||||
|
||||
Args:
|
||||
side: Which panel side ("left" or "right")
|
||||
|
||||
Returns:
|
||||
Div with icon if panel is hidden, None otherwise
|
||||
"""
|
||||
enabled = self.conf.left if side == "left" else self.conf.right
|
||||
if not enabled:
|
||||
return None
|
||||
|
||||
resizer = Div(
|
||||
cls="mf-resizer mf-resizer-left",
|
||||
data_command_id=self.commands.update_side_width("left").id,
|
||||
data_side="left"
|
||||
)
|
||||
is_visible = self._state.left_visible if side == "left" else self._state.right_visible
|
||||
icon_cls = "hidden" if is_visible else f"mf-panel-show-icon mf-panel-show-icon-{side}"
|
||||
|
||||
return Div(Div(self._left, id=f"{self._id}_l"), resizer, cls="mf-panel-left")
|
||||
return mk.icon(
|
||||
more_horizontal20_regular,
|
||||
command=self.commands.toggle_side(side, True),
|
||||
cls=icon_cls,
|
||||
id=f"{self._id}_show_{side}"
|
||||
)
|
||||
|
||||
def render(self):
|
||||
return Div(
|
||||
self._mk_left(),
|
||||
Div(self._main, cls="mf-panel-main"),
|
||||
self._mk_right(),
|
||||
self._mk_panel("left"),
|
||||
Div(
|
||||
self._mk_show_icon("left"),
|
||||
self._main,
|
||||
self._mk_show_icon("right"),
|
||||
cls="mf-panel-main"
|
||||
),
|
||||
self._mk_panel("right"),
|
||||
Script(f"initResizer('{self._id}');"),
|
||||
cls="mf-panel",
|
||||
id=self._id,
|
||||
|
||||
Reference in New Issue
Block a user