puppygirl-py/puppygirl/elements/shadow_root.py
2025-10-06 18:03:06 -04:00

131 lines
3.1 KiB
Python

from copy import copy
from dataclasses import dataclass
from enum import StrEnum
from typing import TYPE_CHECKING, Optional, Self
from bs4 import Tag
from ..clonable import Clonable
if TYPE_CHECKING:
from ..puppytype import ElementLike
TemplateName = "template"
class ShadowRootMode(StrEnum):
Open = "open"
Closed = "closed"
@dataclass
class Node(Clonable):
_value: Tag
@property
def value(self):
return self._value
def attach_shadow(self, shadow_root_mode: ShadowRootMode, clonable: Optional[bool] = None, delegates_focus: Optional[bool] = None, serializable: Optional[bool] = None):
return ShadowRoot(
host=self,
mode=shadow_root_mode,
clonable=clonable,
delegates_focus=delegates_focus,
serializable=serializable
)
def from_element(element: "ElementLike") -> Self:
if isinstance(element, Node):
return element
return Node(element)
def clone(self) -> "Self":
return Node(copy(self.value))
def __getattr__(self, name):
if name == '_value':
raise AttributeError()
return getattr(self._value, name)
def __getitem__(self, index):
return self._value[index]
@dataclass
class Template(Clonable):
_value: Node
@property
def value(self):
return self._value
@property
def shadow_root_mode(self) -> ShadowRootMode | None:
return self._value.get("shadowrootmode")
@shadow_root_mode.setter
def shadow_root_mode(self, mode: ShadowRootMode):
self._value["shadowrootmode"] = mode.value
@property
def delegates_focus(self) -> Optional[bool]:
return self._value.get("delegatesfocus")
@delegates_focus.setter
def delegates_focus(self, value: bool):
self._value["delegatesfocus"] = value
@property
def clonable(self) -> Optional[bool]:
return self._value.get("clonable")
@clonable.setter
def clonable(self, value: bool):
self._value["clonable"] = value
@property
def serializable(self) -> Optional[bool]:
return self._value.get("serializable")
@serializable.setter
def serializable(self, value: bool):
self._value["serializable"] = value
def from_element(element: "ElementLike") -> Self:
if isinstance(element, Template):
return element
return Template(element)
def clone(self) -> Self:
return Template(copy(self._value))
def __getattr__(self, name):
if name == '_value':
raise AttributeError()
return getattr(self._value, name)
def __getitem__(self, index):
return self._value[index]
def __setitem__(self, index, value):
self._value[index] = value
@dataclass
class ShadowRoot(Clonable):
host: "Node"
mode: ShadowRootMode
clonable: Optional[bool] = None
delegates_focus: Optional[bool] = None
serializable: Optional[bool] = None
def append_child(self, template: Template):
template.shadow_root_mode = self.mode
if self.clonable is not None:
template.clonable = self.clonable
if self.delegates_focus is not None:
template.delegates_focus = self.delegates_focus
if self.serializable is not None:
template.serializable = self.serializable
self.host.value.insert(0, template.value)