reflex/reflex/components/radix/primitives/form.py
Thomas Brandého 59dd54c049
add workflow to check dependencies on release branch (#4050)
* add workflow to check dependencies on release branch

* rename action to follow convention of other actions

* update workflow

* bump poetry version

* relock deps

* update check to ignore pyright and ruff

* oops, you saw nothing

* split dep check in two job

* fix frontend dep check

* fix stuff

* hmm yeah

* nope nope nope

* sigh

* bump js versions for some packages

* fix some warnings in tests

* fix tests

* try some options

* try to set asyncio policy

* debug dep check

* fix attempt for backend dep

* clean up output for backend check

* run bun outdated on reflex-web to catch most of the packages

* fix python version

* fix python version

* add missing env

* fix bun command

* fix workdir of frontend check

* update packages version

* up-pin plotly.js version

* add debug ouput

* clean frontend dep check output

* fix output

* fix async tests for redis

* relock poetry.lock

* Non-async functions do not need pytest_asyncio.fixture

* test_state: close StateManagerRedis connection in test to avoid warning

---------

Co-authored-by: Masen Furer <m_github@0x26.net>
2024-10-07 20:57:02 +02:00

188 lines
4.7 KiB
Python

"""Radix form component."""
from __future__ import annotations
from typing import Any, Literal
from reflex.components.component import ComponentNamespace
from reflex.components.core.debounce import DebounceInput
from reflex.components.el.elements.forms import Form as HTMLForm
from reflex.components.radix.themes.components.text_field import TextFieldRoot
from reflex.event import EventHandler
from reflex.vars.base import Var
from .base import RadixPrimitiveComponentWithClassName
class FormComponent(RadixPrimitiveComponentWithClassName):
"""Base class for all @radix-ui/react-form components."""
library = "@radix-ui/react-form@^0.1.0"
class FormRoot(FormComponent, HTMLForm):
"""The root component of a radix form."""
tag = "Root"
alias = "RadixFormRoot"
# Fired when the errors are cleared.
on_clear_server_errors: EventHandler[lambda: []]
def add_style(self) -> dict[str, Any] | None:
"""Add style to the component.
Returns:
The style of the component.
"""
return {"width": "100%"}
class FormField(FormComponent):
"""A form field component."""
tag = "Field"
alias = "RadixFormField"
# The name of the form field, that is passed down to the control and used to match with validation messages.
name: Var[str]
# Flag to mark the form field as invalid, for server side validation.
server_invalid: Var[bool]
def add_style(self) -> dict[str, Any] | None:
"""Add style to the component.
Returns:
The style of the component.
"""
return {"display": "grid", "margin_bottom": "10px"}
class FormLabel(FormComponent):
"""A form label component."""
tag = "Label"
alias = "RadixFormLabel"
def add_style(self) -> dict[str, Any] | None:
"""Add style to the component.
Returns:
The style of the component.
"""
return {"font_size": "15px", "font_weight": "500", "line_height": "35px"}
class FormControl(FormComponent):
"""A form control component."""
tag = "Control"
alias = "RadixFormControl"
@classmethod
def create(cls, *children, **props):
"""Create a Form Control component.
Args:
*children: The children of the form.
**props: The properties of the form.
Raises:
ValueError: If the number of children is greater than 1.
TypeError: If a child exists but it is not a TextFieldInput.
Returns:
The form control component.
"""
if len(children) > 1:
raise ValueError(
f"FormControl can only have at most one child, got {len(children)} children"
)
for child in children:
if not isinstance(child, (TextFieldRoot, DebounceInput)):
raise TypeError(
"Only Radix TextFieldRoot and DebounceInput are allowed as children of FormControl"
)
return super().create(*children, **props)
LiteralMatcher = Literal[
"badInput",
"patternMismatch",
"rangeOverflow",
"rangeUnderflow",
"stepMismatch",
"tooLong",
"tooShort",
"typeMismatch",
"valid",
"valueMissing",
]
class FormMessage(FormComponent):
"""A form message component."""
tag = "Message"
alias = "RadixFormMessage"
# Used to target a specific field by name when rendering outside of a Field part.
name: Var[str]
# Used to indicate on which condition the message should be visible.
match: Var[LiteralMatcher]
# Forces the message to be shown. This is useful when using server-side validation.
force_match: Var[bool]
def add_style(self) -> dict[str, Any] | None:
"""Add style to the component.
Returns:
The style of the component.
"""
return {"font_size": "13px", "opacity": "0.8", "color": "white"}
class FormValidityState(FormComponent):
"""A form validity state component."""
tag = "ValidityState"
alias = "RadixFormValidityState"
class FormSubmit(FormComponent):
"""A form submit component."""
tag = "Submit"
alias = "RadixFormSubmit"
# This class is created mainly for reflex-web docs.
class Form(FormRoot):
"""The Form component."""
pass
class FormNamespace(ComponentNamespace):
"""Form components."""
root = staticmethod(FormRoot.create)
control = staticmethod(FormControl.create)
field = staticmethod(FormField.create)
label = staticmethod(FormLabel.create)
message = staticmethod(FormMessage.create)
submit = staticmethod(FormSubmit.create)
validity_state = staticmethod(FormValidityState.create)
__call__ = staticmethod(Form.create)
form = FormNamespace()