reflex/reflex/components/next/image.py
2025-02-18 15:20:10 -08:00

118 lines
3.8 KiB
Python

"""Image component from next/image."""
from __future__ import annotations
from typing import Any, Literal
from reflex.event import EventHandler, no_args_event_spec
from reflex.utils import console, types
from reflex.vars.base import Var
from .base import NextComponent
DEFAULT_W_H = "100%"
class Image(NextComponent):
"""Display an image."""
tag = "Image"
library = "next/image"
is_default = True
# This can be either an absolute external URL, or an internal path
src: Var[Any]
# Represents the rendered width in pixels, so it will affect how large the image appears.
width: Var[Any]
# Represents the rendered height in pixels, so it will affect how large the image appears.
height: Var[Any]
# Used to describe the image for screen readers and search engines.
alt: Var[str]
# A custom function used to resolve image URLs.
loader: Var[Any]
# A boolean that causes the image to fill the parent element, which is useful when the width and height are unknown. Default to True
fill: Var[bool]
# A string, similar to a media query, that provides information about how wide the image will be at different breakpoints.
sizes: Var[str]
# The quality of the optimized image, an integer between 1 and 100, where 100 is the best quality and therefore largest file size. Defaults to 75.
quality: Var[int]
# When true, the image will be considered high priority and preload. Lazy loading is automatically disabled for images using priority.
priority: Var[bool]
# A placeholder to use while the image is loading. Possible values are blur, empty, or data:image/.... Defaults to empty.
placeholder: Var[str]
# Allows passing CSS styles to the underlying image element.
# style: Var[Any] #noqa: ERA001
# The loading behavior of the image. Defaults to lazy. Can hurt performance, recommended to use `priority` instead.
loading: Var[Literal["lazy", "eager"]]
# A Data URL to be used as a placeholder image before the src image successfully loads. Only takes effect when combined with placeholder="blur".
blur_data_url: Var[str]
# Fires when the image has loaded.
on_load: EventHandler[no_args_event_spec]
# Fires when the image has an error.
on_error: EventHandler[no_args_event_spec]
@classmethod
def create(
cls,
*children,
width: int | str | None = None,
height: int | str | None = None,
**props,
):
"""Create an Image component from next/image.
Args:
*children: The children of the component.
width: The width of the image.
height: The height of the image.
**props:The props of the component.
Returns:
_type_: _description_
"""
if "blurDataURL" in props:
console.deprecate(
feature_name="blurDataURL",
reason="Use blur_data_url instead",
deprecation_version="0.7.0",
removal_version="0.8.0",
)
props["blur_data_url"] = props.pop("blurDataURL")
style = props.get("style", {})
def check_prop_type(prop_name: str, prop_value: int | str | None):
if types.check_prop_in_allowed_types(prop_value, allowed_types=[int]):
props[prop_name] = prop_value
elif types.check_prop_in_allowed_types(prop_value, allowed_types=[str]):
props[prop_name] = 0
style[prop_name] = prop_value
else:
props[prop_name] = 0
style[prop_name] = DEFAULT_W_H
check_prop_type("width", width)
check_prop_type("height", height)
props["style"] = style
# mysteriously, following `sizes` prop is needed to avoid blury images.
props["sizes"] = "100vw"
return super().create(*children, **props)