diff --git a/packages/bot-engine/blocks/inputs/number/parseNumber.ts b/packages/bot-engine/blocks/inputs/number/parseNumber.ts new file mode 100644 index 00000000000..0faf50ad00c --- /dev/null +++ b/packages/bot-engine/blocks/inputs/number/parseNumber.ts @@ -0,0 +1 @@ +export const parseNumber = (value: string) => Number(value).toString() diff --git a/packages/bot-engine/blocks/inputs/number/validateNumber.ts b/packages/bot-engine/blocks/inputs/number/validateNumber.ts index 47dc2b385e5..a7a69c1faa0 100644 --- a/packages/bot-engine/blocks/inputs/number/validateNumber.ts +++ b/packages/bot-engine/blocks/inputs/number/validateNumber.ts @@ -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)) diff --git a/packages/bot-engine/continueBotFlow.ts b/packages/bot-engine/continueBotFlow.ts index 4f6e2922e02..1267c8a1c35 100644 --- a/packages/bot-engine/continueBotFlow.ts +++ b/packages/bot-engine/continueBotFlow.ts @@ -30,6 +30,7 @@ import { parseVariables } from './variables/parseVariables' import { updateVariablesInSession } from './variables/updateVariablesInSession' import { startBotFlow } from './startBotFlow' import { TRPCError } from '@trpc/server' +import { parseNumber } from './blocks/inputs/number/parseNumber' type Params = { version: 1 | 2 @@ -344,9 +345,9 @@ const parseReply = } case InputBlockType.NUMBER: { if (!inputValue) return { status: 'fail' } - const isValid = validateNumber(inputValue) + const isValid = validateNumber(inputValue, block.options) if (!isValid) return { status: 'fail' } - return { status: 'success', reply: inputValue } + return { status: 'success', reply: parseNumber(inputValue) } } case InputBlockType.DATE: { if (!inputValue) return { status: 'fail' } diff --git a/packages/embeds/js/package.json b/packages/embeds/js/package.json index 9e73c4b6aa0..521cfe922fc 100644 --- a/packages/embeds/js/package.json +++ b/packages/embeds/js/package.json @@ -1,6 +1,6 @@ { "name": "@typebot.io/js", - "version": "0.2.8", + "version": "0.2.9", "description": "Javascript library to display typebots on your website", "type": "module", "main": "dist/index.js", diff --git a/packages/embeds/js/src/features/blocks/inputs/number/components/NumberInput.tsx b/packages/embeds/js/src/features/blocks/inputs/number/components/NumberInput.tsx index f06dbb7ed94..dd5254a246f 100644 --- a/packages/embeds/js/src/features/blocks/inputs/number/components/NumberInput.tsx +++ b/packages/embeds/js/src/features/blocks/inputs/number/components/NumberInput.tsx @@ -1,10 +1,10 @@ -import { ShortTextInput } from '@/components' import { SendButton } from '@/components/SendButton' import { CommandData } from '@/features/commands/types' import { InputSubmitContent } from '@/types' import { isMobile } from '@/utils/isMobileSignal' import type { NumberInputBlock } from '@typebot.io/schemas' import { createSignal, onCleanup, onMount } from 'solid-js' +import { numberInputHelper } from '../numberInputHelper' type NumberInputProps = { block: NumberInputBlock @@ -13,16 +13,21 @@ type NumberInputProps = { } export const NumberInput = (props: NumberInputProps) => { - const [inputValue, setInputValue] = createSignal(props.defaultValue ?? '') + const [inputValue, setInputValue] = createSignal( + props.defaultValue ?? '' + ) + // eslint-disable-next-line solid/reactivity + const [staticValue, bindValue, targetValue] = numberInputHelper(() => + inputValue() + ) let inputRef: HTMLInputElement | undefined - const handleInput = (inputValue: string) => setInputValue(inputValue) - const checkIfInputIsValid = () => inputValue() !== '' && inputRef?.reportValidity() const submit = () => { - if (checkIfInputIsValid()) props.onSubmit({ value: inputValue() }) + if (checkIfInputIsValid()) + props.onSubmit({ value: inputValue().toString() }) } const submitWhenEnter = (e: KeyboardEvent) => { @@ -53,15 +58,21 @@ export const NumberInput = (props: NumberInputProps) => { }} onKeyDown={submitWhenEnter} > - { + setInputValue(targetValue(e.currentTarget)) + }} type="number" - style={{ appearance: 'auto' }} min={props.block.options?.min} max={props.block.options?.max} step={props.block.options?.step ?? 'any'} diff --git a/packages/embeds/js/src/features/blocks/inputs/number/numberInputHelper.tsx b/packages/embeds/js/src/features/blocks/inputs/number/numberInputHelper.tsx new file mode 100644 index 00000000000..f684bb80de8 --- /dev/null +++ b/packages/embeds/js/src/features/blocks/inputs/number/numberInputHelper.tsx @@ -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] +} diff --git a/packages/embeds/nextjs/package.json b/packages/embeds/nextjs/package.json index 210e6958dba..69568f9548b 100644 --- a/packages/embeds/nextjs/package.json +++ b/packages/embeds/nextjs/package.json @@ -1,6 +1,6 @@ { "name": "@typebot.io/nextjs", - "version": "0.2.8", + "version": "0.2.9", "description": "Convenient library to display typebots on your Next.js website", "main": "dist/index.js", "types": "dist/index.d.ts", diff --git a/packages/embeds/react/package.json b/packages/embeds/react/package.json index dd8ea46e62b..3a3440b6534 100644 --- a/packages/embeds/react/package.json +++ b/packages/embeds/react/package.json @@ -1,6 +1,6 @@ { "name": "@typebot.io/react", - "version": "0.2.8", + "version": "0.2.9", "description": "Convenient library to display typebots on your React app", "main": "dist/index.js", "types": "dist/index.d.ts",