@ -1,4 +1,12 @@
|
||||
import { FormLabel, Stack } from '@chakra-ui/react'
|
||||
import {
|
||||
Accordion,
|
||||
AccordionButton,
|
||||
AccordionIcon,
|
||||
AccordionItem,
|
||||
AccordionPanel,
|
||||
FormLabel,
|
||||
Stack,
|
||||
} from '@chakra-ui/react'
|
||||
import { CodeEditor } from '@/components/inputs/CodeEditor'
|
||||
import { FileInputBlock, Variable } from '@typebot.io/schemas'
|
||||
import React from 'react'
|
||||
@ -45,6 +53,24 @@ export const FileInputSettings = ({ options, onOptionsChange }: Props) => {
|
||||
visibility: (typeof fileVisibilityOptions)[number]
|
||||
) => onOptionsChange({ ...options, visibility })
|
||||
|
||||
const updateSingleFileSuccessLabel = (single: string) =>
|
||||
onOptionsChange({
|
||||
...options,
|
||||
labels: {
|
||||
...options?.labels,
|
||||
success: { ...options?.labels?.success, single },
|
||||
},
|
||||
})
|
||||
|
||||
const updateMultipleFilesSuccessLabel = (multiple: string) =>
|
||||
onOptionsChange({
|
||||
...options,
|
||||
labels: {
|
||||
...options?.labels,
|
||||
success: { ...options?.labels?.success, multiple },
|
||||
},
|
||||
})
|
||||
|
||||
return (
|
||||
<Stack spacing={4}>
|
||||
<SwitchWithLabel
|
||||
@ -75,6 +101,13 @@ export const FileInputSettings = ({ options, onOptionsChange }: Props) => {
|
||||
withVariableButton={false}
|
||||
/>
|
||||
</Stack>
|
||||
<Accordion allowToggle>
|
||||
<AccordionItem>
|
||||
<AccordionButton justifyContent="space-between">
|
||||
Labels
|
||||
<AccordionIcon />
|
||||
</AccordionButton>
|
||||
<AccordionPanel as={Stack} spacing={4}>
|
||||
<TextInput
|
||||
label={t('blocks.inputs.settings.button.label')}
|
||||
defaultValue={
|
||||
@ -83,6 +116,7 @@ export const FileInputSettings = ({ options, onOptionsChange }: Props) => {
|
||||
onChange={handleButtonLabelChange}
|
||||
withVariableButton={false}
|
||||
/>
|
||||
{options?.isMultipleAllowed && (
|
||||
<TextInput
|
||||
label={t('blocks.inputs.file.settings.clear.label')}
|
||||
defaultValue={
|
||||
@ -91,6 +125,8 @@ export const FileInputSettings = ({ options, onOptionsChange }: Props) => {
|
||||
onChange={updateClearButtonLabel}
|
||||
withVariableButton={false}
|
||||
/>
|
||||
)}
|
||||
{!(options?.isRequired ?? defaultFileInputOptions.isRequired) && (
|
||||
<TextInput
|
||||
label={t('blocks.inputs.file.settings.skip.label')}
|
||||
defaultValue={
|
||||
@ -99,6 +135,32 @@ export const FileInputSettings = ({ options, onOptionsChange }: Props) => {
|
||||
onChange={updateSkipButtonLabel}
|
||||
withVariableButton={false}
|
||||
/>
|
||||
)}
|
||||
<TextInput
|
||||
label="Single file success"
|
||||
defaultValue={
|
||||
options?.labels?.success?.single ??
|
||||
defaultFileInputOptions.labels.success.single
|
||||
}
|
||||
onChange={updateSingleFileSuccessLabel}
|
||||
withVariableButton={false}
|
||||
/>
|
||||
{options?.isMultipleAllowed && (
|
||||
<TextInput
|
||||
label="Multi files success"
|
||||
moreInfoTooltip="Include {total} to show the total number of files uploaded"
|
||||
defaultValue={
|
||||
options?.labels?.success?.multiple ??
|
||||
defaultFileInputOptions.labels.success.multiple
|
||||
}
|
||||
onChange={updateMultipleFilesSuccessLabel}
|
||||
withVariableButton={false}
|
||||
/>
|
||||
)}
|
||||
</AccordionPanel>
|
||||
</AccordionItem>
|
||||
</Accordion>
|
||||
|
||||
<DropdownList
|
||||
label="Visibility:"
|
||||
moreInfoTooltip='This setting determines who can see the uploaded files. "Public" means that anyone who has the link can see the files. "Private" means that only a members of this workspace can see the files.'
|
||||
|
@ -2,4 +2,6 @@ const urlRegex =
|
||||
/^(https?:\/\/(?:www\.|(?!www))[a-zA-Z0-9][a-zA-Z0-9-]+[a-zA-Z0-9]:[0-9]*\.[^\s]{2,}|www\.[a-zA-Z0-9][a-zA-Z0-9-]+[a-zA-Z0-9]:[0-9]*\.[^\s]{2,}|https?:\/\/(?:www\.|(?!www))[a-zA-Z0-9]+\.[^\s]{2,}|www\.[a-zA-Z0-9]+\.[^\s]{2,})$/
|
||||
|
||||
export const validateUrl = (url: string) =>
|
||||
url.startsWith('http://localhost') || urlRegex.test(url)
|
||||
url.startsWith('http://localhost') ||
|
||||
url.startsWith('http://fake-upload-url.com') ||
|
||||
urlRegex.test(url)
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@typebot.io/js",
|
||||
"version": "0.2.39",
|
||||
"version": "0.2.40",
|
||||
"description": "Javascript library to display typebots on your website",
|
||||
"type": "module",
|
||||
"main": "dist/index.js",
|
||||
|
@ -51,7 +51,9 @@ export const FileUploadForm = (props: Props) => {
|
||||
const startSingleFileUpload = async (file: File) => {
|
||||
if (props.context.isPreview || !props.context.resultId)
|
||||
return props.onSubmit({
|
||||
label: `File uploaded`,
|
||||
label:
|
||||
props.block.options?.labels?.success?.single ??
|
||||
defaultFileInputOptions.labels.success.single,
|
||||
value: 'http://fake-upload-url.com',
|
||||
})
|
||||
setIsUploading(true)
|
||||
@ -70,7 +72,9 @@ export const FileUploadForm = (props: Props) => {
|
||||
setIsUploading(false)
|
||||
if (urls.length)
|
||||
return props.onSubmit({
|
||||
label: `File uploaded`,
|
||||
label:
|
||||
props.block.options?.labels?.success?.single ??
|
||||
defaultFileInputOptions.labels.success.single,
|
||||
value: urls[0] ? encodeUrl(urls[0]) : '',
|
||||
})
|
||||
setErrorMessage('An error occured while uploading the file')
|
||||
@ -79,7 +83,14 @@ export const FileUploadForm = (props: Props) => {
|
||||
const resultId = props.context.resultId
|
||||
if (props.context.isPreview || !resultId)
|
||||
return props.onSubmit({
|
||||
label: `${files.length} file${files.length > 1 ? 's' : ''} uploaded`,
|
||||
label:
|
||||
files.length > 1
|
||||
? (
|
||||
props.block.options?.labels?.success?.multiple ??
|
||||
defaultFileInputOptions.labels.success.multiple
|
||||
).replaceAll('{total}', files.length.toString())
|
||||
: props.block.options?.labels?.success?.single ??
|
||||
defaultFileInputOptions.labels.success.single,
|
||||
value: files
|
||||
.map((_, idx) => `http://fake-upload-url.com/${idx}`)
|
||||
.join(', '),
|
||||
@ -101,7 +112,14 @@ export const FileUploadForm = (props: Props) => {
|
||||
if (urls.length !== files.length)
|
||||
return setErrorMessage('An error occured while uploading the files')
|
||||
props.onSubmit({
|
||||
label: `${urls.length} file${urls.length > 1 ? 's' : ''} uploaded`,
|
||||
label:
|
||||
urls.length > 1
|
||||
? (
|
||||
props.block.options?.labels?.success?.multiple ??
|
||||
defaultFileInputOptions.labels.success.multiple
|
||||
).replaceAll('{total}', urls.length.toString())
|
||||
: props.block.options?.labels?.success?.single ??
|
||||
defaultFileInputOptions.labels.success.single,
|
||||
value: urls.filter(isDefined).map(encodeUrl).join(', '),
|
||||
})
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@typebot.io/nextjs",
|
||||
"version": "0.2.39",
|
||||
"version": "0.2.40",
|
||||
"description": "Convenient library to display typebots on your Next.js website",
|
||||
"main": "dist/index.js",
|
||||
"types": "dist/index.d.ts",
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@typebot.io/react",
|
||||
"version": "0.2.39",
|
||||
"version": "0.2.40",
|
||||
"description": "Convenient library to display typebots on your React app",
|
||||
"main": "dist/index.js",
|
||||
"types": "dist/index.d.ts",
|
||||
|
@ -12,6 +12,10 @@ export const defaultFileInputOptions = {
|
||||
button: 'Upload',
|
||||
clear: 'Clear',
|
||||
skip: 'Skip',
|
||||
success: {
|
||||
single: 'File uploaded',
|
||||
multiple: '{total} files uploaded',
|
||||
},
|
||||
},
|
||||
} as const satisfies FileInputBlock['options']
|
||||
|
||||
|
@ -13,6 +13,12 @@ const fileInputOptionsV5Schema = optionBaseSchema.merge(
|
||||
button: z.string().optional(),
|
||||
clear: z.string().optional(),
|
||||
skip: z.string().optional(),
|
||||
success: z
|
||||
.object({
|
||||
single: z.string().optional(),
|
||||
multiple: z.string().optional(),
|
||||
})
|
||||
.optional(),
|
||||
})
|
||||
.optional(),
|
||||
sizeLimit: z.number().optional(),
|
||||
|
Reference in New Issue
Block a user