Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ AI Elements Vue includes the following components:
| `actions` | ✅ 已完成 | Interactive action buttons for AI responses |
| `branch` | ✅ 已完成 | Branch visualization for conversation flows |
| `code-block` | ✅ 已完成 | Syntax-highlighted code display with copy functionality |
| `image` | ❌ 未完成 | AI-generated image display component |
| `image` | ✅ 已完成 | AI-generated image display component |
| `inline-citation` | ❌ 未完成 | Inline source citations |
| `loader` | ❌ 未完成 | Loading states for AI operations |
| `reasoning` | ❌ 未完成 | Display AI reasoning and thought processes |
Expand Down
18 changes: 18 additions & 0 deletions apps/test/app/examples/image.vue

Large diffs are not rendered by default.

10 changes: 10 additions & 0 deletions apps/test/app/examples/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
export { default as ActionsHover } from './actions-hover.vue'
export { default as Actions } from './actions.vue'
export { default as Branch } from './branch.vue'
export { default as CodeBlock } from './code-block.vue'
export { default as Conversation } from './conversation.vue'
export { default as Image } from './image.vue'
export { default as MessageMarkdown } from './message-markdown.vue'
export { default as Message } from './message.vue'
export { default as PromptInput } from './prompt-input.vue'
export { default as Response } from './response.vue'
2 changes: 2 additions & 0 deletions apps/test/app/pages/index.vue
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import Actions from '~/examples/actions.vue'
import Branch from '~/examples/branch.vue'
import CodeBlock from '~/examples/code-block.vue'
import Conversation from '~/examples/conversation.vue'
import Image from '~/examples/image.vue'
import MessageMarkdown from '~/examples/message-markdown.vue'
import Message from '~/examples/message.vue'
import PromptInput from '~/examples/prompt-input.vue'
Expand All @@ -20,6 +21,7 @@ const components = [
{ name: 'Response', Component: Response },
{ name: 'MessageMarkdown', Component: MessageMarkdown },
{ name: 'CodeBlock', Component: CodeBlock },
{ name: 'Image', Component: Image },
]
</script>

Expand Down
3 changes: 3 additions & 0 deletions apps/www/content/1.overview/1.Introduction.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,4 +30,7 @@ You can install it with:
:::ComponentLoader{label="Branch" componentName="Branch"}
:::

:::ComponentLoader{label="Image" componentName="Image"}
:::

View the [source code](https://github.com/cwandev/ai-elements-vue) for all components on GitHub.
117 changes: 117 additions & 0 deletions apps/www/content/2.components/8.image.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
---
title: Image
description:
icon: lucide:image
---

The `Image` component displays AI-generated images from the AI SDK. It accepts a [`Experimental_GeneratedImage`](https://ai-sdk.dev/docs/reference/ai-sdk-core/generate-image#generateimage) object from the AI SDK's `generateImage` function and automatically renders it as an image.

:::ComponentLoader{label="Image" componentName="Image"}
:::

## Install using CLI

:::tabs{variant="card"}
::div{label="ai-elements-vue"}
```sh
npx ai-elements-vue@latest add image
```
::
::div{label="shadcn-vue"}

```sh
npx shadcn-vue@latest add https://registry.ai-elements-vue.com/image.json
```
::
:::

## Install Manually

Copy and paste the following files into the same folder.

:::code-group
```vue [Image.vue]
<script setup lang="ts">
import type { Experimental_GeneratedImage } from 'ai'
import { cn } from '@repo/shadcn-vue/lib/utils'
import { computed, useAttrs } from 'vue'

interface Props extends Experimental_GeneratedImage {
class?: string
alt?: string
}

const props = defineProps<Props>()
const attrs = useAttrs()

const classes = computed(() => cn(
'h-auto max-w-full overflow-hidden rounded-md',
props.class,
))

const src = computed(() => `data:${props.mediaType};base64,${props.base64}`)
</script>

<template>
<img
:alt="props.alt"
:class="classes"
:src="src"
v-bind="attrs"
>
</template>
```

```ts [index.ts]
export { default as Image } from './Image.vue'
```
:::

## Usage

```vue
<script setup lang="ts">
import { Image } from '@/components/ai-elements/image'

const exampleImage = {
base64: 'valid-base64-string',
mediaType: 'image/jpeg',
uint8Array: new Uint8Array([]),
}
</script>

<template>
<Image
v-bind="exampleImage"
alt="Example generated image"
class="h-[150px] aspect-square border"
/>
</template>
```

## Features

- Accepts `Experimental_GeneratedImage` objects directly from the AI SDK
- Automatically creates proper data URLs from base64-encoded image data
- Supports all standard HTML image attributes
- Responsive by default with `max-w-full h-auto` styling
- Customizable with additional CSS classes
- Includes proper TypeScript types for AI SDK compatibility

## Props

### `<Image />`

:::field-group
::field{name="alt" type="string" optional}
Alternative text for the image.
::

::field{name="class" type="string" optional}
Additional CSS classes applied to the `<img>` element.
::

::field{name="[...props]" type="Experimental_GeneratedImage" optional}
The image data to display, as returned by the AI SDK.
::
:::
2 changes: 2 additions & 0 deletions apps/www/plugins/ai-elements.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import {
ActionsHover,
Branch,
Conversation,
Image,
Message,
MessageMarkdown,
PromptInput,
Expand All @@ -26,4 +27,5 @@ export default defineNuxtPlugin((nuxtApp) => {
vueApp.component('PromptInput', PromptInput)
vueApp.component('Conversation', Conversation)
vueApp.component('Response', Response)
vueApp.component('Image', Image)
})
29 changes: 29 additions & 0 deletions packages/elements/src/image/Image.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
<script setup lang="ts">
import type { Experimental_GeneratedImage } from 'ai'
import { cn } from '@repo/shadcn-vue/lib/utils'
import { computed, useAttrs } from 'vue'

interface Props extends Experimental_GeneratedImage {
class?: string
alt?: string
}

const props = defineProps<Props>()
const attrs = useAttrs()

const classes = computed(() => cn(
'h-auto max-w-full overflow-hidden rounded-md',
props.class,
))

const src = computed(() => `data:${props.mediaType};base64,${props.base64}`)
</script>

<template>
<img
:alt="props.alt"
:class="classes"
:src="src"
v-bind="attrs"
>
</template>
1 change: 1 addition & 0 deletions packages/elements/src/image/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export { default as Image } from './Image.vue'
1 change: 1 addition & 0 deletions packages/elements/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ export * from './actions'
export * from './branch'
export * from './code-block'
export * from './conversation'
export * from './image'
export * from './message'
export * from './prompt-input'
export * from './response'
18 changes: 18 additions & 0 deletions packages/examples/src/image.vue

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions packages/examples/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ export { default as ActionsHover } from './actions-hover.vue'
export { default as Actions } from './actions.vue'
export { default as Branch } from './branch.vue'
export { default as Conversation } from './conversation.vue'
export { default as Image } from './image.vue'
export { default as MessageMarkdown } from './message-markdown.vue'
export { default as Message } from './message.vue'
export { default as PromptInput } from './prompt-input.vue'
Expand Down
2 changes: 1 addition & 1 deletion packages/registry/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ AI Elements Vue includes the following components:
| `actions` | ✅ 已完成 | Interactive action buttons for AI responses |
| `branch` | ✅ 已完成 | Branch visualization for conversation flows |
| `code-block` | ✅ 已完成 | Syntax-highlighted code display with copy functionality |
| `image` | ❌ 未完成 | AI-generated image display component |
| `image` | ✅ 已完成 | AI-generated image display component |
| `inline-citation` | ❌ 未完成 | Inline source citations |
| `loader` | ❌ 未完成 | Loading states for AI operations |
| `reasoning` | ❌ 未完成 | Display AI reasoning and thought processes |
Expand Down