Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add undefined type #966

Closed
wants to merge 16 commits into from
35 changes: 24 additions & 11 deletions plugins/ui/src/deephaven/ui/_internal/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@
JavaTime,
LocalDateConvertible,
LocalDate,
Undefined,
UNDEFINED,
)

T = TypeVar("T")
Expand All @@ -36,6 +38,17 @@
}


def is_nullish(value: Any) -> bool:
"""
Check if a value is None or Undefined.
Args:
value: The value to check.
Returns:
Whether the value is nullish.
"""
return value is None or value is UNDEFINED
wusteven815 marked this conversation as resolved.
Show resolved Hide resolved


def get_component_name(component: Any) -> str:
"""
Get the name of the component
Expand Down Expand Up @@ -163,7 +176,7 @@ def remove_empty_keys(dict: dict[str, Any]) -> dict[str, Any]:
Returns:
The dict with keys removed.
"""
return {k: v for k, v in dict.items() if v is not None}
return {k: v for k, v in dict.items() if v is not UNDEFINED}


def _wrapped_callable(
Expand Down Expand Up @@ -481,7 +494,7 @@ def _get_first_set_key(props: dict[str, Any], sequence: Sequence[str]) -> str |
The first non-None prop, or None if all props are None.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
The first non-None prop, or None if all props are None.
The first non-nullish prop, or None if all props are None.

"""
for key in sequence:
if props.get(key) is not None:
if not is_nullish(props.get(key)):
return key
return None

Expand Down Expand Up @@ -666,11 +679,11 @@ def convert_date_props(
The converted props.
"""
for key in simple_date_props:
if props.get(key) is not None:
if not is_nullish(props.get(key)):
props[key] = _convert_to_java_date(props[key])

for key in date_range_props:
if props.get(key) is not None:
if not is_nullish(props.get(key)):
props[key] = convert_date_range(props[key], _convert_to_java_date)

# the simple props must be converted before this to simplify the callable conversion
Expand All @@ -680,25 +693,25 @@ def convert_date_props(
# Local Dates will default to DAY but we need to default to SECOND for the other types
if (
granularity_key is not None
and props.get(granularity_key) is None
and is_nullish(props.get(granularity_key))
and converter != to_j_local_date
):
props[granularity_key] = "SECOND"

# now that the converter is set, we can convert simple props to strings
for key in simple_date_props:
if props.get(key) is not None:
if not is_nullish(props.get(key)):
props[key] = str(props[key])

# and convert the date range props to strings
for key in date_range_props:
if props.get(key) is not None:
if not is_nullish(props.get(key)):
props[key] = convert_date_range(props[key], str)

# wrap the date callable with the convert
# if there are date range props, we need to convert as a date range
for key in callable_date_props:
if props.get(key) is not None:
if not is_nullish(props.get(key)):
if not callable(props[key]):
raise TypeError(f"{key} must be a callable")
if len(date_range_props) > 0:
Expand Down Expand Up @@ -730,20 +743,20 @@ def convert_time_props(
The converted props.
"""
for key in simple_time_props:
if props.get(key) is not None:
if not is_nullish(props.get(key)):
props[key] = _convert_to_java_time(props[key])

# the simple props must be converted before this to simplify the callable conversion
converter = _prioritized_time_callable_converter(props, priority, default_converter)

# now that the converter is set, we can convert simple props to strings
for key in simple_time_props:
if props.get(key) is not None:
if not is_nullish(props.get(key)):
props[key] = str(props[key])

# wrap the date callable with the convert
for key in callable_time_props:
if props.get(key) is not None:
if not is_nullish(props.get(key)):
if not callable(props[key]):
raise TypeError(f"{key} must be a callable")
props[key] = _wrap_time_callable(props[key], converter)
Expand Down
127 changes: 64 additions & 63 deletions plugins/ui/src/deephaven/ui/components/action_button.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,76 +22,77 @@

from .basic import component_element
from ..elements import Element
from ..types import Undefined, UNDEFINED

ActionButtonElement = Element


def action_button(
*children: Any,
type: ButtonType = "button",
on_press: PressEventCallable | None = None,
on_press_start: PressEventCallable | None = None,
on_press_end: PressEventCallable | None = None,
on_press_up: PressEventCallable | None = None,
on_press_change: Callable[[bool], None] | None = None,
on_focus: FocusEventCallable | None = None,
on_blur: FocusEventCallable | None = None,
on_focus_change: Callable[[bool], None] | None = None,
on_key_down: KeyboardEventCallable | None = None,
on_key_up: KeyboardEventCallable | None = None,
auto_focus: bool | None = None,
is_disabled: bool | None = None,
is_quiet: bool | None = None,
static_color: StaticColor | None = None,
flex: LayoutFlex | None = None,
flex_grow: float | None = None,
flex_shrink: float | None = None,
flex_basis: DimensionValue | None = None,
align_self: AlignSelf | None = None,
justify_self: JustifySelf | None = None,
order: int | None = None,
grid_area: str | None = None,
grid_row: str | None = None,
grid_row_start: str | None = None,
grid_row_end: str | None = None,
grid_column: str | None = None,
grid_column_start: str | None = None,
grid_column_end: str | None = None,
margin: DimensionValue | None = None,
margin_top: DimensionValue | None = None,
margin_bottom: DimensionValue | None = None,
margin_start: DimensionValue | None = None,
margin_end: DimensionValue | None = None,
margin_x: DimensionValue | None = None,
margin_y: DimensionValue | None = None,
width: DimensionValue | None = None,
height: DimensionValue | None = None,
min_width: DimensionValue | None = None,
min_height: DimensionValue | None = None,
max_width: DimensionValue | None = None,
max_height: DimensionValue | None = None,
position: Position | None = None,
top: DimensionValue | None = None,
bottom: DimensionValue | None = None,
start: DimensionValue | None = None,
end: DimensionValue | None = None,
left: DimensionValue | None = None,
right: DimensionValue | None = None,
z_index: int | None = None,
is_hidden: bool | None = None,
id: str | None = None,
exclude_from_tab_order: bool | None = None,
aria_expanded: AriaExpanded | None = None,
aria_haspopup: AriaHasPopup | None = None,
aria_controls: str | None = None,
aria_label: str | None = None,
aria_labelledby: str | None = None,
aria_describedby: str | None = None,
aria_pressed: AriaPressed | None = None,
aria_details: str | None = None,
UNSAFE_class_name: str | None = None,
UNSAFE_style: CSSProperties | None = None,
key: str | None = None,
on_press: PressEventCallable | Undefined = UNDEFINED,
on_press_start: PressEventCallable | Undefined = UNDEFINED,
on_press_end: PressEventCallable | Undefined = UNDEFINED,
on_press_up: PressEventCallable | Undefined = UNDEFINED,
on_press_change: Callable[[bool], None] | Undefined = UNDEFINED,
on_focus: FocusEventCallable | Undefined = UNDEFINED,
on_blur: FocusEventCallable | Undefined = UNDEFINED,
on_focus_change: Callable[[bool], None] | Undefined = UNDEFINED,
on_key_down: KeyboardEventCallable | Undefined = UNDEFINED,
on_key_up: KeyboardEventCallable | Undefined = UNDEFINED,
auto_focus: bool | Undefined = UNDEFINED,
is_disabled: bool | Undefined = UNDEFINED,
is_quiet: bool | Undefined = UNDEFINED,
static_color: StaticColor | Undefined = UNDEFINED,
flex: LayoutFlex | Undefined = UNDEFINED,
flex_grow: float | Undefined = UNDEFINED,
flex_shrink: float | Undefined = UNDEFINED,
flex_basis: DimensionValue | Undefined = UNDEFINED,
align_self: AlignSelf | Undefined = UNDEFINED,
justify_self: JustifySelf | Undefined = UNDEFINED,
order: int | Undefined = UNDEFINED,
grid_area: str | Undefined = UNDEFINED,
grid_row: str | Undefined = UNDEFINED,
grid_row_start: str | Undefined = UNDEFINED,
grid_row_end: str | Undefined = UNDEFINED,
grid_column: str | Undefined = UNDEFINED,
grid_column_start: str | Undefined = UNDEFINED,
grid_column_end: str | Undefined = UNDEFINED,
margin: DimensionValue | Undefined = UNDEFINED,
margin_top: DimensionValue | Undefined = UNDEFINED,
margin_bottom: DimensionValue | Undefined = UNDEFINED,
margin_start: DimensionValue | Undefined = UNDEFINED,
margin_end: DimensionValue | Undefined = UNDEFINED,
margin_x: DimensionValue | Undefined = UNDEFINED,
margin_y: DimensionValue | Undefined = UNDEFINED,
width: DimensionValue | Undefined = UNDEFINED,
height: DimensionValue | Undefined = UNDEFINED,
min_width: DimensionValue | Undefined = UNDEFINED,
min_height: DimensionValue | Undefined = UNDEFINED,
max_width: DimensionValue | Undefined = UNDEFINED,
max_height: DimensionValue | Undefined = UNDEFINED,
position: Position | Undefined = UNDEFINED,
top: DimensionValue | Undefined = UNDEFINED,
bottom: DimensionValue | Undefined = UNDEFINED,
start: DimensionValue | Undefined = UNDEFINED,
end: DimensionValue | Undefined = UNDEFINED,
left: DimensionValue | Undefined = UNDEFINED,
right: DimensionValue | Undefined = UNDEFINED,
z_index: int | Undefined = UNDEFINED,
is_hidden: bool | Undefined = UNDEFINED,
id: str | Undefined = UNDEFINED,
exclude_from_tab_order: bool | Undefined = UNDEFINED,
aria_expanded: AriaExpanded | Undefined = UNDEFINED,
aria_haspopup: AriaHasPopup | Undefined = UNDEFINED,
aria_controls: str | Undefined = UNDEFINED,
aria_label: str | Undefined = UNDEFINED,
aria_labelledby: str | Undefined = UNDEFINED,
aria_describedby: str | Undefined = UNDEFINED,
aria_pressed: AriaPressed | Undefined = UNDEFINED,
aria_details: str | Undefined = UNDEFINED,
UNSAFE_class_name: str | Undefined = UNDEFINED,
UNSAFE_style: CSSProperties | Undefined = UNDEFINED,
key: str | Undefined = UNDEFINED,
) -> ActionButtonElement:
"""
ActionButtons allow users to perform an action. They're used for similar, task-based options within a workflow, and are ideal for interfaces where buttons aren't meant to draw a lot of attention.
Expand Down
134 changes: 71 additions & 63 deletions plugins/ui/src/deephaven/ui/components/action_group.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,73 +18,81 @@
)
from .basic import component_element
from ..elements import Element
from ..types import ActionGroupDensity, SelectedKeys, SelectionMode, Key, Selection
from ..types import (
ActionGroupDensity,
SelectedKeys,
SelectionMode,
Key,
Selection,
Undefined,
UNDEFINED,
)


def action_group(
*children: Any,
is_emphasized: bool | None = None,
density: ActionGroupDensity | None = "regular",
is_justified: bool | None = None,
is_quiet: bool | None = None,
static_color: StaticColor | None = None,
overflow_mode: OverflowMode | None = "wrap",
button_label_behavior: ButtonLabelBehavior | None = "show",
summary_icon: Element | None = None,
orientation: Orientation | None = "horizontal",
disabled_keys: Iterable[str] | None = None,
is_disabled: bool | None = None,
selection_mode: SelectionMode | None = None,
disallow_empty_selection: bool | None = None,
selected_keys: SelectedKeys | Iterable[str] | None = None,
default_selected_keys: SelectedKeys | Iterable[str] | None = None,
on_action: Callable[[str], None] | None = None,
on_change: Callable[[Key], None] | None = None,
on_selection_change: Callable[[Selection], None] | None = None,
flex: LayoutFlex | None = None,
flex_grow: float | None = None,
flex_shrink: float | None = None,
flex_basis: DimensionValue | None = None,
align_self: AlignSelf | None = None,
justify_self: JustifySelf | None = None,
order: int | None = None,
grid_area: str | None = None,
grid_row: str | None = None,
grid_column: str | None = None,
grid_column_start: str | None = None,
grid_column_end: str | None = None,
grid_row_start: str | None = None,
grid_row_end: str | None = None,
margin: DimensionValue | None = None,
margin_top: DimensionValue | None = None,
margin_bottom: DimensionValue | None = None,
margin_start: DimensionValue | None = None,
margin_end: DimensionValue | None = None,
margin_x: DimensionValue | None = None,
margin_y: DimensionValue | None = None,
width: DimensionValue | None = None,
height: DimensionValue | None = None,
min_width: DimensionValue | None = None,
min_height: DimensionValue | None = None,
max_width: DimensionValue | None = None,
max_height: DimensionValue | None = None,
position: Position | None = None,
top: DimensionValue | None = None,
bottom: DimensionValue | None = None,
left: DimensionValue | None = None,
right: DimensionValue | None = None,
start: DimensionValue | None = None,
end: DimensionValue | None = None,
z_index: int | None = None,
is_hidden: bool | None = None,
id: str | None = None,
aria_label: str | None = None,
aria_labelledby: str | None = None,
aria_describedby: str | None = None,
aria_details: str | None = None,
UNSAFE_class_name: str | None = None,
UNSAFE_style: CSSProperties | None = None,
key: str | None = None,
is_emphasized: bool | Undefined = UNDEFINED,
density: ActionGroupDensity | Undefined = "regular",
is_justified: bool | Undefined = UNDEFINED,
is_quiet: bool | Undefined = UNDEFINED,
static_color: StaticColor | Undefined = UNDEFINED,
overflow_mode: OverflowMode | Undefined = "wrap",
button_label_behavior: ButtonLabelBehavior | Undefined = "show",
summary_icon: Element | Undefined = UNDEFINED,
orientation: Orientation | Undefined = "horizontal",
disabled_keys: Iterable[str] | Undefined = UNDEFINED,
is_disabled: bool | Undefined = UNDEFINED,
selection_mode: SelectionMode | Undefined = UNDEFINED,
disallow_empty_selection: bool | Undefined = UNDEFINED,
selected_keys: SelectedKeys | Iterable[str] | Undefined = UNDEFINED,
default_selected_keys: SelectedKeys | Iterable[str] | Undefined = UNDEFINED,
on_action: Callable[[str], None] | Undefined = UNDEFINED,
on_change: Callable[[Key], None] | Undefined = UNDEFINED,
on_selection_change: Callable[[Selection], None] | Undefined = UNDEFINED,
flex: LayoutFlex | Undefined = UNDEFINED,
flex_grow: float | Undefined = UNDEFINED,
flex_shrink: float | Undefined = UNDEFINED,
flex_basis: DimensionValue | Undefined = UNDEFINED,
align_self: AlignSelf | Undefined = UNDEFINED,
justify_self: JustifySelf | Undefined = UNDEFINED,
order: int | Undefined = UNDEFINED,
grid_area: str | Undefined = UNDEFINED,
grid_row: str | Undefined = UNDEFINED,
grid_column: str | Undefined = UNDEFINED,
grid_column_start: str | Undefined = UNDEFINED,
grid_column_end: str | Undefined = UNDEFINED,
grid_row_start: str | Undefined = UNDEFINED,
grid_row_end: str | Undefined = UNDEFINED,
margin: DimensionValue | Undefined = UNDEFINED,
margin_top: DimensionValue | Undefined = UNDEFINED,
margin_bottom: DimensionValue | Undefined = UNDEFINED,
margin_start: DimensionValue | Undefined = UNDEFINED,
margin_end: DimensionValue | Undefined = UNDEFINED,
margin_x: DimensionValue | Undefined = UNDEFINED,
margin_y: DimensionValue | Undefined = UNDEFINED,
width: DimensionValue | Undefined = UNDEFINED,
height: DimensionValue | Undefined = UNDEFINED,
min_width: DimensionValue | Undefined = UNDEFINED,
min_height: DimensionValue | Undefined = UNDEFINED,
max_width: DimensionValue | Undefined = UNDEFINED,
max_height: DimensionValue | Undefined = UNDEFINED,
position: Position | Undefined = UNDEFINED,
top: DimensionValue | Undefined = UNDEFINED,
bottom: DimensionValue | Undefined = UNDEFINED,
left: DimensionValue | Undefined = UNDEFINED,
right: DimensionValue | Undefined = UNDEFINED,
start: DimensionValue | Undefined = UNDEFINED,
end: DimensionValue | Undefined = UNDEFINED,
z_index: int | Undefined = UNDEFINED,
is_hidden: bool | Undefined = UNDEFINED,
id: str | Undefined = UNDEFINED,
aria_label: str | Undefined = UNDEFINED,
aria_labelledby: str | Undefined = UNDEFINED,
aria_describedby: str | Undefined = UNDEFINED,
aria_details: str | Undefined = UNDEFINED,
UNSAFE_class_name: str | Undefined = UNDEFINED,
UNSAFE_style: CSSProperties | Undefined = UNDEFINED,
key: str | Undefined = UNDEFINED,
) -> Element:
"""
An action grouping of action items that are related to each other.
Expand Down
Loading
Loading