2
0

🚸 (phone) Improve phone input behavior and validation

Now accepting landline phone numbers. Consistent select UI on every browser. Auto focus on country select.
This commit is contained in:
Baptiste Arnaud
2023-03-09 14:19:39 +01:00
parent bf1fbf2c53
commit 6b08df71ba
10 changed files with 70 additions and 41 deletions

View File

@ -37,7 +37,7 @@ test.describe('Phone input block', () => {
await page.click('text=Restart')
await page.locator(`input[placeholder="+33 XX XX XX XX"]`).type('+33 6 73')
await expect(page.getByRole('combobox')).toHaveText(/🇫🇷.+/)
await expect(page.getByText('🇫🇷')).toBeVisible()
await page.locator('button >> text="Go"').click()
await expect(page.locator('text=Try again bro')).toBeVisible()
await page

View File

@ -23,11 +23,11 @@
"db": "workspace:*",
"google-spreadsheet": "3.3.0",
"got": "12.5.3",
"libphonenumber-js": "^1.10.21",
"next": "13.1.6",
"nextjs-cors": "^2.1.2",
"nodemailer": "6.9.1",
"openai": "^3.2.1",
"phone": "^3.1.34",
"qs": "6.11.0",
"react": "18.2.0",
"react-dom": "18.2.0",

View File

@ -1,4 +1,4 @@
import phone from 'phone'
import { parsePhoneNumber } from 'libphonenumber-js'
export const formatPhoneNumber = (phoneNumber: string) =>
phone(phoneNumber).phoneNumber
parsePhoneNumber(phoneNumber).formatInternational()

View File

@ -1,4 +1,4 @@
import { phone } from 'phone'
import { isValidPhoneNumber } from 'libphonenumber-js'
export const validatePhoneNumber = (phoneNumber: string) =>
phone(phoneNumber).isValid
isValidPhoneNumber(phoneNumber)

View File

@ -50,13 +50,13 @@ export const continueBotFlow =
message: 'Current block is not an input block',
})
if (reply && !isReplyValid(reply, block)) return parseRetryMessage(block)
const formattedReply = formatReply(reply, block.type)
if (!formattedReply && !canSkip(block.type)) {
return parseRetryMessage(block)
}
if (formattedReply && !isReplyValid(formattedReply, block))
return parseRetryMessage(block)
const newSessionState = await processAndSaveAnswer(
state,

View File

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

View File

@ -0,0 +1,16 @@
import { JSX } from 'solid-js/jsx-runtime'
export const ChevronDownIcon = (props: JSX.SvgSVGAttributes<SVGSVGElement>) => (
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2px"
stroke-linecap="round"
stroke-linejoin="round"
{...props}
>
<polyline points="6 9 12 15 18 9" />
</svg>
)

View File

@ -1,4 +1,5 @@
import { ShortTextInput } from '@/components'
import { ChevronDownIcon } from '@/components/icons/ChevronDownIcon'
import { SendButton } from '@/components/SendButton'
import { InputSubmitContent } from '@/types'
import { isMobile } from '@/utils/isMobileSignal'
@ -75,7 +76,13 @@ export const PhoneInput = (props: PhoneInputProps) => {
const selectNewCountryCode = (
event: Event & { currentTarget: { value: string } }
) => {
setSelectedCountryCode(event.currentTarget.value)
const code = event.currentTarget.value
setSelectedCountryCode(code)
const dial_code = phoneCountries.find(
(country) => country.code === code
)?.dial_code
if (inputValue() === '' && dial_code) setInputValue(dial_code)
inputRef?.focus()
}
onMount(() => {
@ -91,30 +98,37 @@ export const PhoneInput = (props: PhoneInputProps) => {
}}
onKeyDown={submitWhenEnter}
>
<div class="flex flex-1">
<select
onChange={selectNewCountryCode}
class="w-12 pl-2 focus:outline-none rounded-lg typebot-country-select"
>
<option selected>
<div class="flex">
<div class="relative typebot-country-select flex justify-center items-center rounded-md">
<div class="pl-2 pr-1 flex items-center gap-2">
<span>
{
phoneCountries.find(
(country) => selectedCountryCode() === country.code
)?.flag
}
</option>
<For
each={phoneCountries.filter(
(country) => country.code !== selectedCountryCode()
)}
</span>
<ChevronDownIcon class="w-3" />
</div>
<select
onChange={selectNewCountryCode}
class="absolute top-0 left-0 w-full h-full cursor-pointer opacity-0"
>
<For each={phoneCountries}>
{(country) => (
<option value={country.code}>
{country.name} ({country.dial_code})
<option
value={country.code}
selected={country.code === selectedCountryCode()}
>
{country.name}{' '}
{country.dial_code ? `(${country.dial_code})` : ''}
</option>
)}
</For>
</select>
</div>
<ShortTextInput
type="tel"
ref={inputRef}

View File

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

13
pnpm-lock.yaml generated
View File

@ -370,6 +370,7 @@ importers:
google-auth-library: 8.7.0
google-spreadsheet: 3.3.0
got: 12.5.3
libphonenumber-js: ^1.10.21
models: workspace:*
next: 13.1.6
next-transpile-modules: 10.0.0
@ -378,7 +379,6 @@ importers:
nodemailer: 6.9.1
openai: ^3.2.1
papaparse: 5.3.2
phone: ^3.1.34
qs: 6.11.0
react: 18.2.0
react-dom: 18.2.0
@ -400,11 +400,11 @@ importers:
db: link:../../packages/db
google-spreadsheet: 3.3.0
got: 12.5.3
libphonenumber-js: 1.10.21
next: 13.1.6_6m24vuloj5ihw4zc5lbsktc4fu
nextjs-cors: 2.1.2_next@13.1.6
nodemailer: 6.9.1
openai: 3.2.1
phone: 3.1.34
qs: 6.11.0
react: 18.2.0
react-dom: 18.2.0_react@18.2.0
@ -14284,6 +14284,10 @@ packages:
resolution: {integrity: sha512-MDZ1zLIkfSDZV5xBta3nuvbEOlsnKCPe4z5r3hyup/AXveevkl9A1eSWmLhd2FX4k7pJDe4MrLeQsux0HI/VWg==}
dev: false
/libphonenumber-js/1.10.21:
resolution: {integrity: sha512-/udZhx49av2r2gZR/+xXSrwcR8smX/sDNrVpOFrvW+CA26TfYTVZfwb3MIDvmwAYMLs7pXuJjZX0VxxGpqPhsA==}
dev: false
/lie/3.1.1:
resolution: {integrity: sha512-RiNhHysUjhrDQntfYSfY4MU24coXXdEOgw9WGcKHNeEwffDYbF//u87M1EWaMGzuFoSbqW0C9C6lEEhDOAswfw==}
dependencies:
@ -15983,11 +15987,6 @@ packages:
sha.js: 2.4.11
dev: false
/phone/3.1.34:
resolution: {integrity: sha512-h+nJqLyzA4vbPlD9poMS6fqeW4Dz1lRNPK9qHmrM7Pqkac/0RdiFZrbSJTVxE5xj/HFAaggQTZyfj6XmSjootA==}
engines: {node: '>=12'}
dev: false
/php-parser/3.1.3:
resolution: {integrity: sha512-hPvBmnRYPqWEtMfIFOlyjQv1q75UUtxt4U+YscKIQViGmEE2Xa4BuS1B1/cZdjy7MVcwtnr0WkEsr915LgRKOw==}
dev: true