@@ -127,13 +127,13 @@ def signals(
127127 :param expressions_: If True, the values of the signals will be evaluated as expressions
128128 rather than literals.
129129 """
130- signals = {** (signals_dict if signals_dict else {}), ** signals }
130+ signals = {** (signals_dict or {}), ** signals }
131131 val = _js_object (signals ) if expressions_ else json .dumps (signals )
132132 return SignalsAttr (value = val , alias = self ._alias )
133133
134134 def computed (self , computed_dict : Mapping | None = None , / , ** computed : str ) -> BaseAttr :
135135 """Create signals that are computed based on an expression."""
136- computed = {** (computed_dict if computed_dict else {}), ** computed }
136+ computed = {** (computed_dict or {}), ** computed }
137137 first , * rest = (
138138 BaseAttr ("computed" , key = sig , value = expr , alias = self ._alias )
139139 for sig , expr in computed .items ()
@@ -152,16 +152,16 @@ def ignore(self) -> IgnoreAttr:
152152
153153 def attr (self , attr_dict : Mapping | None = None , / , ** attrs : str ) -> BaseAttr :
154154 """Set the value of any HTML attributes to expressions, and keep them in sync."""
155- attrs = {** (attr_dict if attr_dict else {}), ** attrs }
155+ attrs = {** (attr_dict or {}), ** attrs }
156156 return BaseAttr ("attr" , value = _js_object (attrs ), alias = self ._alias )
157157
158158 def bind (self , signal_name : str ) -> BaseAttr :
159159 """Set up two-way data binding between a signal and an element's value."""
160- return BaseAttr ( "bind" , value = signal_name , alias = self ._alias )
160+ return BindAttr ( value = signal_name , alias = self ._alias )
161161
162162 def class_ (self , class_dict : Mapping | None = None , / , ** classes : str ) -> BaseAttr :
163163 """Add or removes classes to or from an element based on expressions."""
164- classes = {** (class_dict if class_dict else {}), ** classes }
164+ classes = {** (class_dict or {}), ** classes }
165165 return BaseAttr ("class" , value = _js_object (classes ), alias = self ._alias )
166166
167167 def init (self , expression : str ) -> InitAttr :
@@ -216,7 +216,7 @@ def show(self, expression: str) -> BaseAttr:
216216
217217 def style (self , style_dict : Mapping | None = None , / , ** styles : str ) -> BaseAttr :
218218 """Set the value of inline CSS styles on an element based on an expression, and keeps them in sync."""
219- styles = {** (style_dict if style_dict else {}), ** styles }
219+ styles = {** (style_dict or {}), ** styles }
220220 return BaseAttr ("style" , value = _js_object (styles ), alias = self ._alias )
221221
222222 def text (self , expression : str ) -> BaseAttr :
@@ -432,6 +432,21 @@ def self(self) -> Self:
432432 return self
433433
434434
435+ class BindAttr (BaseAttr ):
436+ _attr = "bind"
437+
438+ def prop (self , prop : str ) -> Self :
439+ """Bind to a specified property."""
440+ self ._mods ["prop" ] = [prop ]
441+ return self
442+
443+ def event (self , event : str | Iterable [str ]) -> Self :
444+ """Only update the signal when the specified events are fired."""
445+ events = [event ] if isinstance (event , str ) else list (event )
446+ self ._mods ["event" ] = events
447+ return self
448+
449+
435450class OnAttr (BaseAttr , TimingMod , DelayMod , ViewtransitionMod ):
436451 _attr = "on"
437452
@@ -459,6 +474,12 @@ def window(self) -> Self:
459474 self ._mods ["window" ] = []
460475 return self
461476
477+ @property
478+ def document (self ) -> Self :
479+ """Attach the event listener to the document element."""
480+ self ._mods ["document" ] = []
481+ return self
482+
462483 @property
463484 def outside (self ) -> Self :
464485 """Trigger when the event is outside the element."""
@@ -633,7 +654,7 @@ def threshold(self, threshold: int) -> Self:
633654class OnIntervalAttr (BaseAttr , ViewtransitionMod ):
634655 _attr = "on-interval"
635656
636- def duration (self , duration : int | float | str , * , leading : bool = False ) -> Self :
657+ def duration (self , duration : float | str , * , leading : bool = False ) -> Self :
637658 """Set the interval duration."""
638659 self ._mods ["duration" ] = [str (duration )]
639660 if leading :
0 commit comments