2
0

(imageBubble) Add redirect on image click option

Closes #448
This commit is contained in:
Baptiste Arnaud
2023-04-07 11:30:54 +02:00
parent ee14228ee3
commit e06f8186f6
7 changed files with 121 additions and 26 deletions

View File

@ -0,0 +1,80 @@
import { ImageUploadContent } from '@/components/ImageUploadContent'
import { TextInput } from '@/components/inputs'
import { SwitchWithLabel } from '@/components/inputs/SwitchWithLabel'
import { Stack } from '@chakra-ui/react'
import { isDefined, isNotEmpty } from '@typebot.io/lib'
import { ImageBubbleBlock } from '@typebot.io/schemas'
import React, { useState } from 'react'
type Props = {
typebotId: string
block: ImageBubbleBlock
onContentChange: (content: ImageBubbleBlock['content']) => void
}
export const ImageBubbleSettings = ({
typebotId,
block,
onContentChange,
}: Props) => {
const [showClickLinkInput, setShowClickLinkInput] = useState(
isNotEmpty(block.content.clickLink?.url)
)
const updateImage = (url: string) => {
onContentChange({ ...block.content, url })
}
const updateClickLinkUrl = (url: string) => {
onContentChange({
...block.content,
clickLink: { ...block.content.clickLink, url },
})
}
const updateClickLinkAltText = (alt: string) => {
onContentChange({
...block.content,
clickLink: { ...block.content.clickLink, alt },
})
}
const toggleClickLink = () => {
if (isDefined(block.content.clickLink) && showClickLinkInput) {
onContentChange({ ...block.content, clickLink: undefined })
}
setShowClickLinkInput(!showClickLinkInput)
}
return (
<Stack p="2" spacing={4}>
<ImageUploadContent
filePath={`typebots/${typebotId}/blocks/${block.id}`}
defaultUrl={block.content?.url}
onSubmit={updateImage}
/>
<Stack>
<SwitchWithLabel
label={'On click link'}
initialValue={showClickLinkInput}
onCheckChange={toggleClickLink}
/>
{showClickLinkInput && (
<>
<TextInput
autoFocus
placeholder="https://example.com"
onChange={updateClickLinkUrl}
defaultValue={block.content.clickLink?.url}
/>
<TextInput
placeholder="Link alt text (description)"
onChange={updateClickLinkAltText}
defaultValue={block.content.clickLink?.alt}
/>
</>
)}
</Stack>
</Stack>
)
}

View File

@ -1,6 +1,6 @@
import { ImageUploadContent } from '@/components/ImageUploadContent'
import { AudioBubbleForm } from '@/features/blocks/bubbles/audio/components/AudioBubbleForm' import { AudioBubbleForm } from '@/features/blocks/bubbles/audio/components/AudioBubbleForm'
import { EmbedUploadContent } from '@/features/blocks/bubbles/embed/components/EmbedUploadContent' import { EmbedUploadContent } from '@/features/blocks/bubbles/embed/components/EmbedUploadContent'
import { ImageBubbleSettings } from '@/features/blocks/bubbles/image/components/ImageBubbleSettings'
import { VideoUploadContent } from '@/features/blocks/bubbles/video/components/VideoUploadContent' import { VideoUploadContent } from '@/features/blocks/bubbles/video/components/VideoUploadContent'
import { import {
Portal, Portal,
@ -46,15 +46,13 @@ export const MediaBubbleContent = ({
block, block,
onContentChange, onContentChange,
}: Props) => { }: Props) => {
const handleImageUrlChange = (url: string) => onContentChange({ url })
switch (block.type) { switch (block.type) {
case BubbleBlockType.IMAGE: { case BubbleBlockType.IMAGE: {
return ( return (
<ImageUploadContent <ImageBubbleSettings
filePath={`typebots/${typebotId}/blocks/${block.id}`} typebotId={typebotId}
defaultUrl={block.content?.url} block={block}
onSubmit={handleImageUrlChange} onContentChange={onContentChange}
/> />
) )
} }

View File

@ -1,6 +1,6 @@
{ {
"name": "@typebot.io/js", "name": "@typebot.io/js",
"version": "0.0.33", "version": "0.0.34",
"description": "Javascript library to display typebots on your website", "description": "Javascript library to display typebots on your website",
"type": "module", "type": "module",
"main": "dist/index.js", "main": "dist/index.js",

View File

@ -37,7 +37,7 @@ export const HostBubble = (props: Props) => {
</Match> </Match>
<Match when={props.message.type === BubbleBlockType.IMAGE}> <Match when={props.message.type === BubbleBlockType.IMAGE}>
<ImageBubble <ImageBubble
url={(props.message.content as ImageBubbleContent).url} content={props.message.content as ImageBubbleContent}
onTransitionEnd={onTransitionEnd} onTransitionEnd={onTransitionEnd}
/> />
</Match> </Match>

View File

@ -3,7 +3,7 @@ import type { ImageBubbleContent } from '@typebot.io/schemas'
import { createSignal, onCleanup, onMount } from 'solid-js' import { createSignal, onCleanup, onMount } from 'solid-js'
type Props = { type Props = {
url: ImageBubbleContent['url'] content: ImageBubbleContent
onTransitionEnd: () => void onTransitionEnd: () => void
} }
@ -38,6 +38,21 @@ export const ImageBubble = (props: Props) => {
if (typingTimeout) clearTimeout(typingTimeout) if (typingTimeout) clearTimeout(typingTimeout)
}) })
const Image = (
<img
ref={image}
src={props.content.url}
alt={props.content.clickLink?.alt ?? 'Bubble image'}
class={
'text-fade-in w-full ' + (isTyping() ? 'opacity-0' : 'opacity-100')
}
style={{
'max-height': '512px',
height: isTyping() ? '32px' : 'auto',
}}
/>
)
return ( return (
<div class="flex flex-col animate-fade-in"> <div class="flex flex-col animate-fade-in">
<div class="flex mb-2 w-full items-center"> <div class="flex mb-2 w-full items-center">
@ -51,21 +66,17 @@ export const ImageBubble = (props: Props) => {
> >
{isTyping() ? <TypingBubble /> : null} {isTyping() ? <TypingBubble /> : null}
</div> </div>
<figure class="p-4 z-10"> {props.content.clickLink ? (
<img <a
ref={image} href={props.content.clickLink.url}
src={props.url} target="_blank"
class={ class="p-4 z-10"
'text-fade-in w-full ' + >
(isTyping() ? 'opacity-0' : 'opacity-100') {Image}
} </a>
style={{ ) : (
'max-height': '512px', <figure class="p-4 z-10">{Image}</figure>
height: isTyping() ? '32px' : 'auto', )}
}}
alt="Bubble image"
/>
</figure>
</div> </div>
</div> </div>
</div> </div>

View File

@ -1,6 +1,6 @@
{ {
"name": "@typebot.io/react", "name": "@typebot.io/react",
"version": "0.0.33", "version": "0.0.34",
"description": "React library to display typebots on your website", "description": "React library to display typebots on your website",
"main": "dist/index.js", "main": "dist/index.js",
"types": "dist/index.d.ts", "types": "dist/index.d.ts",

View File

@ -4,6 +4,12 @@ import { BubbleBlockType } from './enums'
export const imageBubbleContentSchema = z.object({ export const imageBubbleContentSchema = z.object({
url: z.string().optional(), url: z.string().optional(),
clickLink: z
.object({
url: z.string().optional(),
alt: z.string().optional(),
})
.optional(),
}) })
export const imageBubbleBlockSchema = blockBaseSchema.merge( export const imageBubbleBlockSchema = blockBaseSchema.merge(