diff --git a/packages/shared/useToNumber/index.md b/packages/shared/useToNumber/index.md new file mode 100644 index 00000000000..850aed4716b --- /dev/null +++ b/packages/shared/useToNumber/index.md @@ -0,0 +1,18 @@ +--- +category: Utilities +--- + +# useToNumber + +Reactively convert a string ref to number. + +## Usage + +```ts +import { useToNumber } from '@vueuse/core' + +const str = ref('123') +const number = useToNumber(str) + +number.value // 123 +``` diff --git a/packages/shared/useToNumber/index.test.ts b/packages/shared/useToNumber/index.test.ts new file mode 100644 index 00000000000..ae4e828cb27 --- /dev/null +++ b/packages/shared/useToNumber/index.test.ts @@ -0,0 +1,41 @@ +import { ref } from 'vue-demi' +import { useToNumber } from '.' + +describe('useToNumber', () => { + it('default', () => { + const value = ref('123.345') + const float = useToNumber(value) + const int = useToNumber(value, { method: 'parseInt' }) + + expect(float.value).toBe(123.345) + expect(int.value).toBe(123) + + value.value = 'hi' + + expect(float.value).toBe(NaN) + expect(int.value).toBe(NaN) + + value.value = 123.4 + + expect(float.value).toBe(123.4) + expect(int.value).toBe(123.4) + + value.value = '-43.53' + + expect(float.value).toBe(-43.53) + expect(int.value).toBe(-43) + }) + + it('radix', () => { + const value = ref('0xFA') + const int = useToNumber(value, { method: 'parseInt', radix: 16 }) + + expect(int.value).toBe(250) + }) + + it('nanToZero', () => { + const value = ref('Hi') + const float = useToNumber(value, { nanToZero: true }) + expect(float.value).toBe(0) + }) +}) diff --git a/packages/shared/useToNumber/index.ts b/packages/shared/useToNumber/index.ts new file mode 100644 index 00000000000..9e3b34ab5b4 --- /dev/null +++ b/packages/shared/useToNumber/index.ts @@ -0,0 +1,49 @@ +import type { ComputedRef } from 'vue-demi' +import { computed } from 'vue-demi' +import { resolveUnref } from '../resolveUnref' +import type { MaybeComputedRef } from '../utils' + +export interface UseToNumberOptions { + /** + * Method to use to convert the value to a number. + * + * @default 'parseFloat' + */ + method?: 'parseFloat' | 'parseInt' + + /** + * The base in mathematical numeral systems passed to `parseInt`. + * Only works with `method: 'parseInt'` + */ + radix?: number + + /** + * Replace NaN with zero + * + * @default false + */ + nanToZero?: boolean +} + +/** + * Computed reactive object. + */ +export function useToNumber( + value: MaybeComputedRef, + options: UseToNumberOptions = {}, +): ComputedRef { + const { + method = 'parseFloat', + radix, + nanToZero, + } = options + + return computed(() => { + let resolved = resolveUnref(value) + if (typeof resolved === 'string') + resolved = Number[method](resolved, radix) + if (nanToZero && isNaN(resolved)) + resolved = 0 + return resolved + }) +} diff --git a/tsconfig.json b/tsconfig.json index 5e98597348e..1bc7135aad8 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -42,7 +42,6 @@ ], "exclude": [ "node_modules", - "**/**/*.stories.tsx", "**/**/*.md", "**/dist", "packages/.test",