feat(engine): ♿️ Smarter website input
This commit is contained in:
@@ -71,8 +71,6 @@ test.describe.parallel('Editor', () => {
|
|||||||
await expect(page.locator('[data-testid="step"] >> nth=2')).toHaveText(
|
await expect(page.locator('[data-testid="step"] >> nth=2')).toHaveText(
|
||||||
'Hello!'
|
'Hello!'
|
||||||
)
|
)
|
||||||
await page.dragAndDrop('text=Hello', '[data-testid="step"] >> text=Start')
|
|
||||||
await expect(page.locator('text=Block #4')).toBeVisible()
|
|
||||||
await page.dragAndDrop('text=Hello', 'text=Block #2')
|
await page.dragAndDrop('text=Hello', 'text=Block #2')
|
||||||
await expect(page.locator('[data-testid="step"] >> nth=3')).toHaveText(
|
await expect(page.locator('[data-testid="step"] >> nth=3')).toHaveText(
|
||||||
'Hello!'
|
'Hello!'
|
||||||
|
|||||||
@@ -42,7 +42,7 @@ test.describe('Url input step', () => {
|
|||||||
await page.click('text=Restart')
|
await page.click('text=Restart')
|
||||||
await typebotViewer(page)
|
await typebotViewer(page)
|
||||||
.locator(`input[placeholder="Your URL..."]`)
|
.locator(`input[placeholder="Your URL..."]`)
|
||||||
.fill('gg://test.com')
|
.fill('https://https://test')
|
||||||
await typebotViewer(page).locator('button >> text="Go"').click()
|
await typebotViewer(page).locator('button >> text="Go"').click()
|
||||||
await expect(
|
await expect(
|
||||||
typebotViewer(page).locator('text=Try again bro')
|
typebotViewer(page).locator('text=Try again bro')
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
import {
|
import {
|
||||||
EmailInputStep,
|
EmailInputStep,
|
||||||
|
InputStepType,
|
||||||
NumberInputStep,
|
NumberInputStep,
|
||||||
PhoneNumberInputStep,
|
PhoneNumberInputStep,
|
||||||
TextInputStep,
|
TextInputStep,
|
||||||
@@ -23,7 +24,14 @@ type TextFormProps = {
|
|||||||
export const TextForm = ({ step, onSubmit, defaultValue }: TextFormProps) => {
|
export const TextForm = ({ step, onSubmit, defaultValue }: TextFormProps) => {
|
||||||
const [inputValue, setInputValue] = useState(defaultValue ?? '')
|
const [inputValue, setInputValue] = useState(defaultValue ?? '')
|
||||||
|
|
||||||
const handleChange = (inputValue: string) => setInputValue(inputValue)
|
const handleChange = (inputValue: string) => {
|
||||||
|
if (step.type === InputStepType.URL && !inputValue.startsWith('https://'))
|
||||||
|
return inputValue === 'https:/'
|
||||||
|
? undefined
|
||||||
|
: setInputValue(`https://${inputValue}`)
|
||||||
|
|
||||||
|
setInputValue(inputValue)
|
||||||
|
}
|
||||||
|
|
||||||
const handleSubmit = (e: FormEvent) => {
|
const handleSubmit = (e: FormEvent) => {
|
||||||
e.preventDefault()
|
e.preventDefault()
|
||||||
@@ -39,11 +47,7 @@ export const TextForm = ({ step, onSubmit, defaultValue }: TextFormProps) => {
|
|||||||
onSubmit={handleSubmit}
|
onSubmit={handleSubmit}
|
||||||
data-testid="input"
|
data-testid="input"
|
||||||
>
|
>
|
||||||
<TextInput
|
<TextInput step={step} onChange={handleChange} value={inputValue} />
|
||||||
step={step}
|
|
||||||
onChange={handleChange}
|
|
||||||
defaultValue={defaultValue ?? ''}
|
|
||||||
/>
|
|
||||||
<SendButton
|
<SendButton
|
||||||
label={step.options?.labels?.button ?? 'Send'}
|
label={step.options?.labels?.button ?? 'Send'}
|
||||||
isDisabled={inputValue === ''}
|
isDisabled={inputValue === ''}
|
||||||
|
|||||||
@@ -22,11 +22,11 @@ type TextInputProps = {
|
|||||||
| NumberInputStep
|
| NumberInputStep
|
||||||
| UrlInputStep
|
| UrlInputStep
|
||||||
| PhoneNumberInputStep
|
| PhoneNumberInputStep
|
||||||
defaultValue: string
|
value: string
|
||||||
onChange: (value: string) => void
|
onChange: (value: string) => void
|
||||||
}
|
}
|
||||||
|
|
||||||
export const TextInput = ({ step, defaultValue, onChange }: TextInputProps) => {
|
export const TextInput = ({ step, value, onChange }: TextInputProps) => {
|
||||||
const inputRef = useRef<HTMLInputElement & HTMLTextAreaElement>(null)
|
const inputRef = useRef<HTMLInputElement & HTMLTextAreaElement>(null)
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
@@ -47,19 +47,19 @@ export const TextInput = ({ step, defaultValue, onChange }: TextInputProps) => {
|
|||||||
return step.options?.isLong ? (
|
return step.options?.isLong ? (
|
||||||
<LongTextInput
|
<LongTextInput
|
||||||
ref={inputRef as unknown as RefObject<HTMLTextAreaElement>}
|
ref={inputRef as unknown as RefObject<HTMLTextAreaElement>}
|
||||||
|
value={value}
|
||||||
placeholder={
|
placeholder={
|
||||||
step.options?.labels?.placeholder ?? 'Type your answer...'
|
step.options?.labels?.placeholder ?? 'Type your answer...'
|
||||||
}
|
}
|
||||||
defaultValue={defaultValue}
|
|
||||||
onChange={handleInputChange}
|
onChange={handleInputChange}
|
||||||
/>
|
/>
|
||||||
) : (
|
) : (
|
||||||
<ShortTextInput
|
<ShortTextInput
|
||||||
ref={inputRef}
|
ref={inputRef}
|
||||||
|
value={value}
|
||||||
placeholder={
|
placeholder={
|
||||||
step.options?.labels?.placeholder ?? 'Type your answer...'
|
step.options?.labels?.placeholder ?? 'Type your answer...'
|
||||||
}
|
}
|
||||||
defaultValue={defaultValue}
|
|
||||||
onChange={handleInputChange}
|
onChange={handleInputChange}
|
||||||
/>
|
/>
|
||||||
)
|
)
|
||||||
@@ -68,10 +68,10 @@ export const TextInput = ({ step, defaultValue, onChange }: TextInputProps) => {
|
|||||||
return (
|
return (
|
||||||
<ShortTextInput
|
<ShortTextInput
|
||||||
ref={inputRef}
|
ref={inputRef}
|
||||||
|
value={value}
|
||||||
placeholder={
|
placeholder={
|
||||||
step.options?.labels?.placeholder ?? 'Type your email...'
|
step.options?.labels?.placeholder ?? 'Type your email...'
|
||||||
}
|
}
|
||||||
defaultValue={defaultValue}
|
|
||||||
onChange={handleInputChange}
|
onChange={handleInputChange}
|
||||||
type="email"
|
type="email"
|
||||||
/>
|
/>
|
||||||
@@ -81,10 +81,10 @@ export const TextInput = ({ step, defaultValue, onChange }: TextInputProps) => {
|
|||||||
return (
|
return (
|
||||||
<ShortTextInput
|
<ShortTextInput
|
||||||
ref={inputRef}
|
ref={inputRef}
|
||||||
|
value={value}
|
||||||
placeholder={
|
placeholder={
|
||||||
step.options?.labels?.placeholder ?? 'Type your answer...'
|
step.options?.labels?.placeholder ?? 'Type your answer...'
|
||||||
}
|
}
|
||||||
defaultValue={defaultValue}
|
|
||||||
onChange={handleInputChange}
|
onChange={handleInputChange}
|
||||||
type="number"
|
type="number"
|
||||||
style={{ appearance: 'auto' }}
|
style={{ appearance: 'auto' }}
|
||||||
@@ -98,8 +98,8 @@ export const TextInput = ({ step, defaultValue, onChange }: TextInputProps) => {
|
|||||||
return (
|
return (
|
||||||
<ShortTextInput
|
<ShortTextInput
|
||||||
ref={inputRef}
|
ref={inputRef}
|
||||||
|
value={value}
|
||||||
placeholder={step.options?.labels?.placeholder ?? 'Type your URL...'}
|
placeholder={step.options?.labels?.placeholder ?? 'Type your URL...'}
|
||||||
defaultValue={defaultValue}
|
|
||||||
onChange={handleInputChange}
|
onChange={handleInputChange}
|
||||||
type="url"
|
type="url"
|
||||||
/>
|
/>
|
||||||
@@ -110,8 +110,8 @@ export const TextInput = ({ step, defaultValue, onChange }: TextInputProps) => {
|
|||||||
<PhoneInput
|
<PhoneInput
|
||||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||||
ref={inputRef as any}
|
ref={inputRef as any}
|
||||||
|
value={value}
|
||||||
onChange={handlePhoneNumberChange}
|
onChange={handlePhoneNumberChange}
|
||||||
defaultValue={defaultValue}
|
|
||||||
placeholder={
|
placeholder={
|
||||||
step.options.labels.placeholder ?? 'Your phone number...'
|
step.options.labels.placeholder ?? 'Your phone number...'
|
||||||
}
|
}
|
||||||
@@ -141,7 +141,7 @@ const LongTextInput = React.forwardRef(
|
|||||||
(
|
(
|
||||||
props: {
|
props: {
|
||||||
placeholder: string
|
placeholder: string
|
||||||
defaultValue: string
|
value: string
|
||||||
onChange: ChangeEventHandler
|
onChange: ChangeEventHandler
|
||||||
},
|
},
|
||||||
ref: React.ForwardedRef<HTMLTextAreaElement>
|
ref: React.ForwardedRef<HTMLTextAreaElement>
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ import { parseVariables } from './variable'
|
|||||||
const emailRegex =
|
const emailRegex =
|
||||||
/^(([^<>()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/
|
/^(([^<>()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/
|
||||||
const urlRegex =
|
const urlRegex =
|
||||||
/((([A-Za-z]{3,9}:(?:\/\/)?)(?:[\-;:&=\+\$,\w]+@)?[A-Za-z0-9\.\-]+|(?:www\.|[\-;:&=\+\$,\w]+@)[A-Za-z0-9\.\-]+)((?:\/[\+~%\/\.\w\-_]*)?\??(?:[\-\+=&;%@\.\w_]*)#?(?:[\.\!\/\\\w]*))?)/
|
/^((([A-Za-z]{3,9}:(?:\/\/)?)(?:[\-;:&=\+\$,\w]+@)?[A-Za-z0-9\.\-]+|(?:www\.|[\-;:&=\+\$,\w]+@)[A-Za-z0-9\.\-]+)((?:\/[\+~%\/\.\w\-_]*)?\??(?:[\-\+=&;%@\.\w_]*)#?(?:[\.\!\/\\\w]*))?)$/
|
||||||
|
|
||||||
export const isInputValid = (
|
export const isInputValid = (
|
||||||
inputValue: string,
|
inputValue: string,
|
||||||
|
|||||||
Reference in New Issue
Block a user