317 lines
8.7 KiB
Python
317 lines
8.7 KiB
Python
from abc import abstractmethod
|
|
from typing import Any, Dict, List, Optional
|
|
|
|
from pydantic import Field
|
|
from pydantic.dataclasses import dataclass
|
|
|
|
from chainlit.types import InputWidgetType
|
|
|
|
|
|
@dataclass
|
|
class InputWidget:
|
|
id: str
|
|
label: str
|
|
initial: Any = None
|
|
tooltip: Optional[str] = None
|
|
description: Optional[str] = None
|
|
disabled: Optional[bool] = False
|
|
|
|
def __post_init__(
|
|
self,
|
|
) -> None:
|
|
if not self.id or not self.label:
|
|
raise ValueError("Must provide key and label to load InputWidget")
|
|
|
|
@abstractmethod
|
|
def to_dict(self) -> Dict[str, Any]:
|
|
pass
|
|
|
|
|
|
@dataclass
|
|
class Switch(InputWidget):
|
|
"""Useful to create a switch input."""
|
|
|
|
type: InputWidgetType = "switch"
|
|
initial: bool = False
|
|
|
|
def to_dict(self) -> Dict[str, Any]:
|
|
return {
|
|
"type": self.type,
|
|
"id": self.id,
|
|
"label": self.label,
|
|
"initial": self.initial,
|
|
"tooltip": self.tooltip,
|
|
"description": self.description,
|
|
"disabled": self.disabled,
|
|
}
|
|
|
|
|
|
@dataclass
|
|
class Slider(InputWidget):
|
|
"""Useful to create a slider input."""
|
|
|
|
type: InputWidgetType = "slider"
|
|
initial: float = 0
|
|
min: float = 0
|
|
max: float = 10
|
|
step: float = 1
|
|
|
|
def to_dict(self) -> Dict[str, Any]:
|
|
return {
|
|
"type": self.type,
|
|
"id": self.id,
|
|
"label": self.label,
|
|
"initial": self.initial,
|
|
"min": self.min,
|
|
"max": self.max,
|
|
"step": self.step,
|
|
"tooltip": self.tooltip,
|
|
"description": self.description,
|
|
"disabled": self.disabled,
|
|
}
|
|
|
|
|
|
@dataclass
|
|
class Select(InputWidget):
|
|
"""Useful to create a select input."""
|
|
|
|
type: InputWidgetType = "select"
|
|
initial: Optional[str] = None
|
|
initial_index: Optional[int] = None
|
|
initial_value: Optional[str] = None
|
|
values: List[str] = Field(default_factory=list)
|
|
items: Dict[str, str] = Field(default_factory=dict)
|
|
|
|
def __post_init__(
|
|
self,
|
|
) -> None:
|
|
super().__post_init__()
|
|
|
|
if not self.values and not self.items:
|
|
raise ValueError("Must provide values or items to create a Select")
|
|
|
|
if self.values and self.items:
|
|
raise ValueError(
|
|
"You can only provide either values or items to create a Select"
|
|
)
|
|
|
|
if not self.values and self.initial_index is not None:
|
|
raise ValueError(
|
|
"Initial_index can only be used in combination with values to create a Select"
|
|
)
|
|
|
|
if self.items:
|
|
self.initial = self.initial_value
|
|
elif self.values:
|
|
self.items = {value: value for value in self.values}
|
|
self.initial = (
|
|
self.values[self.initial_index]
|
|
if self.initial_index is not None
|
|
else self.initial_value
|
|
)
|
|
|
|
def to_dict(self) -> Dict[str, Any]:
|
|
return {
|
|
"type": self.type,
|
|
"id": self.id,
|
|
"label": self.label,
|
|
"initial": self.initial,
|
|
"items": [
|
|
{"label": id, "value": value} for id, value in self.items.items()
|
|
],
|
|
"tooltip": self.tooltip,
|
|
"description": self.description,
|
|
"disabled": self.disabled,
|
|
}
|
|
|
|
|
|
@dataclass
|
|
class TextInput(InputWidget):
|
|
"""Useful to create a text input."""
|
|
|
|
type: InputWidgetType = "textinput"
|
|
initial: Optional[str] = None
|
|
placeholder: Optional[str] = None
|
|
multiline: bool = False
|
|
|
|
def to_dict(self) -> Dict[str, Any]:
|
|
return {
|
|
"type": self.type,
|
|
"id": self.id,
|
|
"label": self.label,
|
|
"initial": self.initial,
|
|
"placeholder": self.placeholder,
|
|
"tooltip": self.tooltip,
|
|
"description": self.description,
|
|
"multiline": self.multiline,
|
|
"disabled": self.disabled,
|
|
}
|
|
|
|
|
|
@dataclass
|
|
class NumberInput(InputWidget):
|
|
"""Useful to create a number input."""
|
|
|
|
type: InputWidgetType = "numberinput"
|
|
initial: Optional[float] = None
|
|
placeholder: Optional[str] = None
|
|
|
|
def to_dict(self) -> Dict[str, Any]:
|
|
return {
|
|
"type": self.type,
|
|
"id": self.id,
|
|
"label": self.label,
|
|
"initial": self.initial,
|
|
"placeholder": self.placeholder,
|
|
"tooltip": self.tooltip,
|
|
"description": self.description,
|
|
"disabled": self.disabled,
|
|
}
|
|
|
|
|
|
@dataclass
|
|
class Tags(InputWidget):
|
|
"""Useful to create an input for an array of strings."""
|
|
|
|
type: InputWidgetType = "tags"
|
|
initial: List[str] = Field(default_factory=list)
|
|
values: List[str] = Field(default_factory=list)
|
|
|
|
def to_dict(self) -> Dict[str, Any]:
|
|
return {
|
|
"type": self.type,
|
|
"id": self.id,
|
|
"label": self.label,
|
|
"initial": self.initial,
|
|
"tooltip": self.tooltip,
|
|
"description": self.description,
|
|
"disabled": self.disabled,
|
|
}
|
|
|
|
|
|
@dataclass
|
|
class MultiSelect(InputWidget):
|
|
"""Useful to create a multi-select input."""
|
|
|
|
type: InputWidgetType = "multiselect"
|
|
initial: List[str] = Field(default_factory=list)
|
|
values: List[str] = Field(default_factory=list)
|
|
items: Dict[str, str] = Field(default_factory=dict)
|
|
|
|
def __post_init__(
|
|
self,
|
|
) -> None:
|
|
super().__post_init__()
|
|
|
|
if not self.values and not self.items:
|
|
raise ValueError("Must provide values or items to create a MultiSelect")
|
|
|
|
if self.values and self.items:
|
|
raise ValueError(
|
|
"You can only provide either values or items to create a MultiSelect"
|
|
)
|
|
|
|
if self.values:
|
|
self.items = {value: value for value in self.values}
|
|
|
|
def to_dict(self) -> Dict[str, Any]:
|
|
return {
|
|
"type": self.type,
|
|
"id": self.id,
|
|
"label": self.label,
|
|
"initial": self.initial,
|
|
"items": [
|
|
{"label": id, "value": value} for id, value in self.items.items()
|
|
],
|
|
"tooltip": self.tooltip,
|
|
"description": self.description,
|
|
"disabled": self.disabled,
|
|
}
|
|
|
|
|
|
@dataclass
|
|
class Checkbox(InputWidget):
|
|
"""Useful to create a checkbox input."""
|
|
|
|
type: InputWidgetType = "checkbox"
|
|
initial: bool = False
|
|
|
|
def to_dict(self) -> Dict[str, Any]:
|
|
return {
|
|
"type": self.type,
|
|
"id": self.id,
|
|
"label": self.label,
|
|
"initial": self.initial,
|
|
"tooltip": self.tooltip,
|
|
"description": self.description,
|
|
"disabled": self.disabled,
|
|
}
|
|
|
|
|
|
@dataclass
|
|
class RadioGroup(InputWidget):
|
|
"""Useful to create a radio button input."""
|
|
|
|
type: InputWidgetType = "radio"
|
|
initial: Optional[str] = None
|
|
initial_index: Optional[int] = None
|
|
initial_value: Optional[str] = None
|
|
values: List[str] = Field(default_factory=list)
|
|
items: Dict[str, str] = Field(default_factory=dict)
|
|
|
|
def __post_init__(
|
|
self,
|
|
) -> None:
|
|
super().__post_init__()
|
|
|
|
if not self.values and not self.items:
|
|
raise ValueError("Must provide values or items to create a RadioButton")
|
|
|
|
if self.values and self.items:
|
|
raise ValueError(
|
|
"You can only provide either values or items to create a RadioButton"
|
|
)
|
|
|
|
if not self.values and self.initial_index is not None:
|
|
raise ValueError(
|
|
"Initial_index can only be used in combination with values to create a RadioButton"
|
|
)
|
|
|
|
if self.items:
|
|
self.initial = self.initial_value
|
|
elif self.values:
|
|
self.items = {value: value for value in self.values}
|
|
self.initial = (
|
|
self.values[self.initial_index]
|
|
if self.initial_index is not None
|
|
else self.initial_value
|
|
)
|
|
|
|
def to_dict(self) -> Dict[str, Any]:
|
|
return {
|
|
"type": self.type,
|
|
"id": self.id,
|
|
"label": self.label,
|
|
"initial": self.initial,
|
|
"items": [
|
|
{"label": id, "value": value} for id, value in self.items.items()
|
|
],
|
|
"tooltip": self.tooltip,
|
|
"description": self.description,
|
|
"disabled": self.disabled,
|
|
}
|
|
|
|
|
|
@dataclass
|
|
class Tab:
|
|
id: str
|
|
label: str
|
|
inputs: list[InputWidget] = Field(default_factory=list, exclude=True)
|
|
|
|
def to_dict(self) -> dict[str, Any]:
|
|
return {
|
|
"id": self.id,
|
|
"label": self.label,
|
|
"inputs": [input.to_dict() for input in self.inputs],
|
|
}
|