diff --git a/packages/fastui/src/components/image.tsx b/packages/fastui/src/components/image.tsx new file mode 100644 index 00000000..8e04b118 --- /dev/null +++ b/packages/fastui/src/components/image.tsx @@ -0,0 +1,43 @@ +import { FC } from 'react' + +import { ClassName, useClassName } from '../hooks/className' +import { useFireEvent, AnyEvent } from '../events' + +export interface ImageProps { + type: 'Image' + src: string + alt?: string + width?: number | string + height?: number | string + referrerPolicy?: + | 'no-referrer' + | 'no-referrer-when-downgrade' + | 'origin' + | 'origin-when-cross-origin' + | 'same-origin' + | 'strict-origin' + | 'strict-origin-when-cross-origin' + | 'unsafe-url' + loading?: 'eager' | 'lazy' + onClick?: AnyEvent + className?: ClassName +} + +export const ImageComp: FC = (props) => { + const { src, alt, width, height, referrerPolicy, loading, onClick } = props + + const { fireEvent } = useFireEvent() + + return ( + {alt} fireEvent(onClick)} + /> + ) +} diff --git a/packages/fastui/src/components/index.tsx b/packages/fastui/src/components/index.tsx index 328af174..f500bc53 100644 --- a/packages/fastui/src/components/index.tsx +++ b/packages/fastui/src/components/index.tsx @@ -38,6 +38,7 @@ import { } from './display' import { JsonComp, JsonProps } from './Json' import { ServerLoadComp, ServerLoadProps } from './ServerLoad' +import { ImageComp, ImageProps } from './image' import { IframeComp, IframeProps } from './Iframe' export type { @@ -64,6 +65,7 @@ export type { DisplayPrimitiveProps, JsonProps, ServerLoadProps, + ImageProps, IframeProps, } @@ -93,6 +95,7 @@ export type FastProps = | AllDisplayProps | JsonProps | ServerLoadProps + | ImageProps | IframeProps export type FastClassNameProps = Exclude @@ -172,6 +175,8 @@ export const AnyComp: FC = (props) => { return case 'ServerLoad': return + case 'Image': + return case 'Iframe': return default: diff --git a/python/demo/components_list.py b/python/demo/components_list.py index d9b8230c..5b76e1b7 100644 --- a/python/demo/components_list.py +++ b/python/demo/components_list.py @@ -168,6 +168,22 @@ class Delivery(BaseModel): ], class_name='border-top mt-3 pt-1', ), + c.Div( + components=[ + c.Heading(text='Image', level=2), + c.Paragraph(text='An image component.'), + c.Image( + src='https://avatars.githubusercontent.com/u/110818415', + alt='Pydantic Logo', + width=200, + height=200, + loading='lazy', + referrerpolicy='no-referrer', + class_name='border rounded', + ), + ], + class_name='border-top mt-3 pt-1', + ), title='Components', ) diff --git a/python/fastui/components/__init__.py b/python/fastui/components/__init__.py index 3a313a67..ccfd68b2 100644 --- a/python/fastui/components/__init__.py +++ b/python/fastui/components/__init__.py @@ -47,6 +47,7 @@ 'Table', 'Display', 'Details', + 'Image', ) @@ -170,6 +171,27 @@ class ServerLoad(pydantic.BaseModel, extra='forbid'): type: typing.Literal['ServerLoad'] = 'ServerLoad' +class Image(pydantic.BaseModel, extra='forbid'): + src: str + alt: str | None = None + width: int | float | str | None = None + height: int | float | str | None = None + referrerpolicy: typing.Literal[ + 'no-referrer', + 'no-referrer-when-downgrade', + 'origin', + 'origin-when-cross-origin', + 'same-origin', + 'strict-origin', + 'strict-origin-when-cross-origin', + 'unsafe-url', + ] | None = None + loading: typing.Literal['eager', 'lazy'] | None = None + on_click: events.AnyEvent | None = pydantic.Field(default=None, serialization_alias='onClick') + class_name: _class_name.ClassName = None + type: typing.Literal['Image'] = 'Image' + + class Iframe(pydantic.BaseModel, extra='forbid'): src: pydantic.HttpUrl title: str | None = None @@ -199,6 +221,7 @@ class Iframe(pydantic.BaseModel, extra='forbid'): | Details | Form | ModelForm + | Image | Iframe | FormField, pydantic.Field(discriminator='type'),