🐛 (attachments) Fix attachments on mobile and fix long text…
Closes #1611, closes #1610
This commit is contained in:
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@typebot.io/js",
|
"name": "@typebot.io/js",
|
||||||
"version": "0.3.2",
|
"version": "0.3.3",
|
||||||
"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",
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { BotContext, ChatChunk as ChatChunkType } from '@/types'
|
import { Answer, BotContext, ChatChunk as ChatChunkType } from '@/types'
|
||||||
import { isMobile } from '@/utils/isMobileSignal'
|
import { isMobile } from '@/utils/isMobileSignal'
|
||||||
import { ContinueChatResponse, Settings, Theme } from '@typebot.io/schemas'
|
import { ContinueChatResponse, Settings, Theme } from '@typebot.io/schemas'
|
||||||
import { createSignal, For, onMount, Show } from 'solid-js'
|
import { createSignal, For, onMount, Show } from 'solid-js'
|
||||||
@@ -23,7 +23,7 @@ type Props = Pick<ContinueChatResponse, 'messages' | 'input'> & {
|
|||||||
isTransitionDisabled?: boolean
|
isTransitionDisabled?: boolean
|
||||||
onNewBubbleDisplayed: (blockId: string) => Promise<void>
|
onNewBubbleDisplayed: (blockId: string) => Promise<void>
|
||||||
onScrollToBottom: (ref?: HTMLDivElement, offset?: number) => void
|
onScrollToBottom: (ref?: HTMLDivElement, offset?: number) => void
|
||||||
onSubmit: (input?: string) => void
|
onSubmit: (answer?: string, attachments?: Answer['attachments']) => void
|
||||||
onSkip: () => void
|
onSkip: () => void
|
||||||
onAllBubblesDisplayed: () => void
|
onAllBubblesDisplayed: () => void
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,7 +15,12 @@ import {
|
|||||||
} from 'solid-js'
|
} from 'solid-js'
|
||||||
import { continueChatQuery } from '@/queries/continueChatQuery'
|
import { continueChatQuery } from '@/queries/continueChatQuery'
|
||||||
import { ChatChunk } from './ChatChunk'
|
import { ChatChunk } from './ChatChunk'
|
||||||
import { BotContext, ChatChunk as ChatChunkType, OutgoingLog } from '@/types'
|
import {
|
||||||
|
Answer,
|
||||||
|
BotContext,
|
||||||
|
ChatChunk as ChatChunkType,
|
||||||
|
OutgoingLog,
|
||||||
|
} from '@/types'
|
||||||
import { isNotDefined } from '@typebot.io/lib'
|
import { isNotDefined } from '@typebot.io/lib'
|
||||||
import { executeClientSideAction } from '@/utils/executeClientSideActions'
|
import { executeClientSideAction } from '@/utils/executeClientSideActions'
|
||||||
import { LoadingChunk } from './LoadingChunk'
|
import { LoadingChunk } from './LoadingChunk'
|
||||||
@@ -137,7 +142,10 @@ export const ConversationContainer = (props: Props) => {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
const sendMessage = async (message: string | undefined) => {
|
const sendMessage = async (
|
||||||
|
message?: string,
|
||||||
|
attachments?: Answer['attachments']
|
||||||
|
) => {
|
||||||
setHasError(false)
|
setHasError(false)
|
||||||
const currentInputBlock = [...chatChunks()].pop()?.input
|
const currentInputBlock = [...chatChunks()].pop()?.input
|
||||||
if (currentInputBlock?.id && props.onAnswer && message)
|
if (currentInputBlock?.id && props.onAnswer && message)
|
||||||
@@ -149,7 +157,13 @@ export const ConversationContainer = (props: Props) => {
|
|||||||
const { data, error } = await continueChatQuery({
|
const { data, error } = await continueChatQuery({
|
||||||
apiHost: props.context.apiHost,
|
apiHost: props.context.apiHost,
|
||||||
sessionId: props.initialChatReply.sessionId,
|
sessionId: props.initialChatReply.sessionId,
|
||||||
message,
|
message: message
|
||||||
|
? {
|
||||||
|
type: 'text',
|
||||||
|
text: message,
|
||||||
|
attachedFileUrls: attachments?.map((attachment) => attachment.url),
|
||||||
|
}
|
||||||
|
: undefined,
|
||||||
})
|
})
|
||||||
clearTimeout(longRequest)
|
clearTimeout(longRequest)
|
||||||
setIsSending(false)
|
setIsSending(false)
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
import { Show } from 'solid-js'
|
import { Match, Switch } from 'solid-js'
|
||||||
import { Menu } from '@ark-ui/solid'
|
import { Menu } from '@ark-ui/solid'
|
||||||
import { CameraIcon } from './icons/CameraIcon'
|
|
||||||
import { FileIcon } from './icons/FileIcon'
|
import { FileIcon } from './icons/FileIcon'
|
||||||
import { PictureIcon } from './icons/PictureIcon'
|
import { PictureIcon } from './icons/PictureIcon'
|
||||||
import { isMobile } from '@/utils/isMobileSignal'
|
import { isMobile } from '@/utils/isMobileSignal'
|
||||||
@@ -35,69 +34,62 @@ export const TextInputAddFileButton = (props: Props) => {
|
|||||||
props.onNewFiles(e.currentTarget.files)
|
props.onNewFiles(e.currentTarget.files)
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
<Show when={isMobile()}>
|
|
||||||
<input
|
|
||||||
type="file"
|
|
||||||
id="camera-upload"
|
|
||||||
class="hidden"
|
|
||||||
multiple
|
|
||||||
accept="image/*"
|
|
||||||
capture="environment"
|
|
||||||
onChange={(e) => {
|
|
||||||
if (!e.currentTarget.files) return
|
|
||||||
props.onNewFiles(e.currentTarget.files)
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
</Show>
|
|
||||||
|
|
||||||
<Menu.Root>
|
<Switch>
|
||||||
<Menu.Trigger
|
<Match when={isMobile()}>
|
||||||
class={clsx(
|
<label
|
||||||
'filter data-[state=open]:backdrop-brightness-90 hover:backdrop-brightness-95 transition rounded-md p-2 focus:outline-none',
|
aria-label="Add attachments"
|
||||||
props.class
|
for="document-upload"
|
||||||
)}
|
class={clsx(
|
||||||
aria-label="Add attachments"
|
'filter data-[state=open]:backdrop-brightness-90 hover:backdrop-brightness-95 transition rounded-md p-2 focus:outline-none',
|
||||||
>
|
props.class
|
||||||
<PaperClipIcon class="w-5" />
|
)}
|
||||||
</Menu.Trigger>
|
>
|
||||||
<Menu.Positioner>
|
<PaperClipIcon class="w-5" />
|
||||||
<Menu.Content class="p-3 gap-2 focus:outline-none">
|
</label>
|
||||||
<Menu.Item
|
</Match>
|
||||||
value="document"
|
<Match when={true}>
|
||||||
asChild={(props) => (
|
<Menu.Root>
|
||||||
<label
|
<Menu.Trigger
|
||||||
{...props()}
|
class={clsx(
|
||||||
for="document-upload"
|
'filter data-[state=open]:backdrop-brightness-90 hover:backdrop-brightness-95 transition rounded-md p-2 focus:outline-none',
|
||||||
class="p-2 filter hover:brightness-95 flex gap-3 items-center"
|
props.class
|
||||||
>
|
|
||||||
<FileIcon class="w-4" /> Document
|
|
||||||
</label>
|
|
||||||
)}
|
)}
|
||||||
/>
|
aria-label="Add attachments"
|
||||||
<Menu.Item
|
>
|
||||||
value="photos"
|
<PaperClipIcon class="w-5" />
|
||||||
asChild={(props) => (
|
</Menu.Trigger>
|
||||||
<label
|
<Menu.Positioner>
|
||||||
{...props()}
|
<Menu.Content class="p-3 gap-2 focus:outline-none">
|
||||||
for="photos-upload"
|
<Menu.Item
|
||||||
class="p-2 filter hover:brightness-95 flex gap-3 items-center"
|
value="document"
|
||||||
>
|
asChild={(props) => (
|
||||||
<PictureIcon class="w-4" /> Photos & videos
|
<label
|
||||||
</label>
|
{...props()}
|
||||||
)}
|
for="document-upload"
|
||||||
/>
|
class="p-2 filter hover:brightness-95 flex gap-3 items-center"
|
||||||
<Show when={isMobile()}>
|
>
|
||||||
<Menu.Item
|
<FileIcon class="w-4" /> Document
|
||||||
value="camera"
|
</label>
|
||||||
class="p-2 filter hover:brightness-95 flex gap-3 items-center"
|
)}
|
||||||
>
|
/>
|
||||||
<CameraIcon class="w-4" />
|
<Menu.Item
|
||||||
Camera
|
value="photos"
|
||||||
</Menu.Item>
|
asChild={(props) => (
|
||||||
</Show>
|
<label
|
||||||
</Menu.Content>
|
{...props()}
|
||||||
</Menu.Positioner>
|
for="photos-upload"
|
||||||
</Menu.Root>
|
class="p-2 filter hover:brightness-95 flex gap-3 items-center"
|
||||||
|
>
|
||||||
|
<PictureIcon class="w-4" /> Photos & videos
|
||||||
|
</label>
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
</Menu.Content>
|
||||||
|
</Menu.Positioner>
|
||||||
|
</Menu.Root>
|
||||||
|
</Match>
|
||||||
|
</Switch>
|
||||||
</>
|
</>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -139,7 +139,10 @@ export const TextInput = (props: Props) => {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
class="typebot-input-form flex w-full gap-2 items-end max-w-[350px]"
|
class={clsx(
|
||||||
|
'typebot-input-form flex w-full gap-2 items-end',
|
||||||
|
props.block.options?.isLong ? 'max-w-full' : 'max-w-[350px]'
|
||||||
|
)}
|
||||||
onKeyDown={submitWhenEnter}
|
onKeyDown={submitWhenEnter}
|
||||||
onDrop={handleDropFile}
|
onDrop={handleDropFile}
|
||||||
onDragOver={handleDragOver}
|
onDragOver={handleDragOver}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import { guessApiHost } from '@/utils/guessApiHost'
|
import { guessApiHost } from '@/utils/guessApiHost'
|
||||||
import { isNotEmpty } from '@typebot.io/lib'
|
import { isNotEmpty } from '@typebot.io/lib'
|
||||||
import { ContinueChatResponse } from '@typebot.io/schemas'
|
import { ContinueChatResponse, Message } from '@typebot.io/schemas'
|
||||||
import ky from 'ky'
|
import ky from 'ky'
|
||||||
|
|
||||||
export const continueChatQuery = async ({
|
export const continueChatQuery = async ({
|
||||||
@@ -9,7 +9,7 @@ export const continueChatQuery = async ({
|
|||||||
sessionId,
|
sessionId,
|
||||||
}: {
|
}: {
|
||||||
apiHost?: string
|
apiHost?: string
|
||||||
message: string | undefined
|
message?: Message
|
||||||
sessionId: string
|
sessionId: string
|
||||||
}) => {
|
}) => {
|
||||||
try {
|
try {
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@typebot.io/nextjs",
|
"name": "@typebot.io/nextjs",
|
||||||
"version": "0.3.2",
|
"version": "0.3.3",
|
||||||
"description": "Convenient library to display typebots on your Next.js website",
|
"description": "Convenient library to display typebots on your Next.js website",
|
||||||
"main": "dist/index.js",
|
"main": "dist/index.js",
|
||||||
"types": "dist/index.d.ts",
|
"types": "dist/index.d.ts",
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@typebot.io/react",
|
"name": "@typebot.io/react",
|
||||||
"version": "0.3.2",
|
"version": "0.3.3",
|
||||||
"description": "Convenient library to display typebots on your React app",
|
"description": "Convenient library to display typebots on your React app",
|
||||||
"main": "dist/index.js",
|
"main": "dist/index.js",
|
||||||
"types": "dist/index.d.ts",
|
"types": "dist/index.d.ts",
|
||||||
|
|||||||
Reference in New Issue
Block a user