🐛 (numberInput) Fix input clearing out on dot or comma press
This commit is contained in:
1
packages/bot-engine/blocks/inputs/number/parseNumber.ts
Normal file
1
packages/bot-engine/blocks/inputs/number/parseNumber.ts
Normal file
@@ -0,0 +1 @@
|
|||||||
|
export const parseNumber = (value: string) => Number(value).toString()
|
||||||
@@ -1 +1,10 @@
|
|||||||
export const validateNumber = (inputValue: string) => !isNaN(Number(inputValue))
|
import { isNotDefined } from '@typebot.io/lib'
|
||||||
|
import { NumberInputBlock } from '@typebot.io/schemas'
|
||||||
|
|
||||||
|
export const validateNumber = (
|
||||||
|
inputValue: string,
|
||||||
|
options: NumberInputBlock['options']
|
||||||
|
) =>
|
||||||
|
inputValue !== '' &&
|
||||||
|
(isNotDefined(options?.min) || Number(inputValue) >= Number(options.min)) &&
|
||||||
|
(isNotDefined(options?.max) || Number(inputValue) <= Number(options.max))
|
||||||
|
|||||||
@@ -30,6 +30,7 @@ import { parseVariables } from './variables/parseVariables'
|
|||||||
import { updateVariablesInSession } from './variables/updateVariablesInSession'
|
import { updateVariablesInSession } from './variables/updateVariablesInSession'
|
||||||
import { startBotFlow } from './startBotFlow'
|
import { startBotFlow } from './startBotFlow'
|
||||||
import { TRPCError } from '@trpc/server'
|
import { TRPCError } from '@trpc/server'
|
||||||
|
import { parseNumber } from './blocks/inputs/number/parseNumber'
|
||||||
|
|
||||||
type Params = {
|
type Params = {
|
||||||
version: 1 | 2
|
version: 1 | 2
|
||||||
@@ -344,9 +345,9 @@ const parseReply =
|
|||||||
}
|
}
|
||||||
case InputBlockType.NUMBER: {
|
case InputBlockType.NUMBER: {
|
||||||
if (!inputValue) return { status: 'fail' }
|
if (!inputValue) return { status: 'fail' }
|
||||||
const isValid = validateNumber(inputValue)
|
const isValid = validateNumber(inputValue, block.options)
|
||||||
if (!isValid) return { status: 'fail' }
|
if (!isValid) return { status: 'fail' }
|
||||||
return { status: 'success', reply: inputValue }
|
return { status: 'success', reply: parseNumber(inputValue) }
|
||||||
}
|
}
|
||||||
case InputBlockType.DATE: {
|
case InputBlockType.DATE: {
|
||||||
if (!inputValue) return { status: 'fail' }
|
if (!inputValue) return { status: 'fail' }
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@typebot.io/js",
|
"name": "@typebot.io/js",
|
||||||
"version": "0.2.8",
|
"version": "0.2.9",
|
||||||
"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,10 +1,10 @@
|
|||||||
import { ShortTextInput } from '@/components'
|
|
||||||
import { SendButton } from '@/components/SendButton'
|
import { SendButton } from '@/components/SendButton'
|
||||||
import { CommandData } from '@/features/commands/types'
|
import { CommandData } from '@/features/commands/types'
|
||||||
import { InputSubmitContent } from '@/types'
|
import { InputSubmitContent } from '@/types'
|
||||||
import { isMobile } from '@/utils/isMobileSignal'
|
import { isMobile } from '@/utils/isMobileSignal'
|
||||||
import type { NumberInputBlock } from '@typebot.io/schemas'
|
import type { NumberInputBlock } from '@typebot.io/schemas'
|
||||||
import { createSignal, onCleanup, onMount } from 'solid-js'
|
import { createSignal, onCleanup, onMount } from 'solid-js'
|
||||||
|
import { numberInputHelper } from '../numberInputHelper'
|
||||||
|
|
||||||
type NumberInputProps = {
|
type NumberInputProps = {
|
||||||
block: NumberInputBlock
|
block: NumberInputBlock
|
||||||
@@ -13,16 +13,21 @@ type NumberInputProps = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export const NumberInput = (props: NumberInputProps) => {
|
export const NumberInput = (props: NumberInputProps) => {
|
||||||
const [inputValue, setInputValue] = createSignal(props.defaultValue ?? '')
|
const [inputValue, setInputValue] = createSignal<string | number>(
|
||||||
|
props.defaultValue ?? ''
|
||||||
|
)
|
||||||
|
// eslint-disable-next-line solid/reactivity
|
||||||
|
const [staticValue, bindValue, targetValue] = numberInputHelper(() =>
|
||||||
|
inputValue()
|
||||||
|
)
|
||||||
let inputRef: HTMLInputElement | undefined
|
let inputRef: HTMLInputElement | undefined
|
||||||
|
|
||||||
const handleInput = (inputValue: string) => setInputValue(inputValue)
|
|
||||||
|
|
||||||
const checkIfInputIsValid = () =>
|
const checkIfInputIsValid = () =>
|
||||||
inputValue() !== '' && inputRef?.reportValidity()
|
inputValue() !== '' && inputRef?.reportValidity()
|
||||||
|
|
||||||
const submit = () => {
|
const submit = () => {
|
||||||
if (checkIfInputIsValid()) props.onSubmit({ value: inputValue() })
|
if (checkIfInputIsValid())
|
||||||
|
props.onSubmit({ value: inputValue().toString() })
|
||||||
}
|
}
|
||||||
|
|
||||||
const submitWhenEnter = (e: KeyboardEvent) => {
|
const submitWhenEnter = (e: KeyboardEvent) => {
|
||||||
@@ -53,15 +58,21 @@ export const NumberInput = (props: NumberInputProps) => {
|
|||||||
}}
|
}}
|
||||||
onKeyDown={submitWhenEnter}
|
onKeyDown={submitWhenEnter}
|
||||||
>
|
>
|
||||||
<ShortTextInput
|
<input
|
||||||
ref={inputRef}
|
ref={inputRef}
|
||||||
value={inputValue()}
|
class="focus:outline-none bg-transparent px-4 py-4 flex-1 w-full text-input"
|
||||||
|
style={{ 'font-size': '16px', appearance: 'auto' }}
|
||||||
|
value={staticValue}
|
||||||
|
// @ts-expect-error not defined
|
||||||
|
// eslint-disable-next-line solid/jsx-no-undef
|
||||||
|
use:bindValue
|
||||||
placeholder={
|
placeholder={
|
||||||
props.block.options?.labels?.placeholder ?? 'Type your answer...'
|
props.block.options?.labels?.placeholder ?? 'Type your answer...'
|
||||||
}
|
}
|
||||||
onInput={handleInput}
|
onInput={(e) => {
|
||||||
|
setInputValue(targetValue(e.currentTarget))
|
||||||
|
}}
|
||||||
type="number"
|
type="number"
|
||||||
style={{ appearance: 'auto' }}
|
|
||||||
min={props.block.options?.min}
|
min={props.block.options?.min}
|
||||||
max={props.block.options?.max}
|
max={props.block.options?.max}
|
||||||
step={props.block.options?.step ?? 'any'}
|
step={props.block.options?.step ?? 'any'}
|
||||||
|
|||||||
@@ -0,0 +1,32 @@
|
|||||||
|
import { createEffect, untrack } from 'solid-js'
|
||||||
|
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||||
|
export const numberInputHelper = function (value: () => any) {
|
||||||
|
const bindDirective = function (el: HTMLInputElement) {
|
||||||
|
createEffect(function () {
|
||||||
|
const v = value()
|
||||||
|
if (v == null) {
|
||||||
|
el.value = v
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
const nodeV = el.value
|
||||||
|
if ((v === 0 && nodeV === '') || v != nodeV) {
|
||||||
|
el.value = v + ''
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
const targetValue = function (el: HTMLInputElement) {
|
||||||
|
if (el.validity.badInput) {
|
||||||
|
return value()
|
||||||
|
}
|
||||||
|
|
||||||
|
if (el.value == '') {
|
||||||
|
return undefined
|
||||||
|
}
|
||||||
|
|
||||||
|
return el.valueAsNumber
|
||||||
|
}
|
||||||
|
|
||||||
|
return [untrack(value), bindDirective, targetValue]
|
||||||
|
}
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@typebot.io/nextjs",
|
"name": "@typebot.io/nextjs",
|
||||||
"version": "0.2.8",
|
"version": "0.2.9",
|
||||||
"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.2.8",
|
"version": "0.2.9",
|
||||||
"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