2
0

🐛 (numberInput) Fix input clearing out on dot or comma press

This commit is contained in:
Baptiste Arnaud
2023-10-25 17:37:45 +02:00
parent c2a08c482e
commit 4b248d554f
8 changed files with 69 additions and 15 deletions

View File

@@ -0,0 +1 @@
export const parseNumber = (value: string) => Number(value).toString()

View File

@@ -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))

View File

@@ -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' }

View File

@@ -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",

View File

@@ -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'}

View File

@@ -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]
}

View File

@@ -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",

View File

@@ -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",