diff --git a/packages/math/index.ts b/packages/math/index.ts index ea67a485588..99040945ffc 100644 --- a/packages/math/index.ts +++ b/packages/math/index.ts @@ -7,6 +7,7 @@ export * from './useAbs' export * from './useAverage' export * from './useCeil' export * from './useClamp' +export * from './useToFixed' export * from './useFloor' export * from './useMath' export * from './useMax' diff --git a/packages/math/useToFixed/demo.vue b/packages/math/useToFixed/demo.vue new file mode 100644 index 00000000000..7f85ceb2f36 --- /dev/null +++ b/packages/math/useToFixed/demo.vue @@ -0,0 +1,52 @@ + + + diff --git a/packages/math/useToFixed/index.md b/packages/math/useToFixed/index.md new file mode 100644 index 00000000000..7e7d7769a34 --- /dev/null +++ b/packages/math/useToFixed/index.md @@ -0,0 +1,28 @@ +--- +category: '@Math' +--- + +# useToFixed + +Reactive `toFixed`. + +## Usage + +```ts +import { useToFixed } from '@vueuse/math' + +const value = ref(3.1415) +const result = useToFixed(value, 2) // 3.14 + +const stringResult = useToFixed(value, 5, { + type: 'string' +}) // '3.14150' + +const ceilResult = useToFixed(value, 2, { + math: 'ceil' +}) // 3.15 + +const floorResult = useToFixed(value, 3, { + math: 'floor' +}) // 3.141 +``` diff --git a/packages/math/useToFixed/index.test.ts b/packages/math/useToFixed/index.test.ts new file mode 100644 index 00000000000..ae5531ec981 --- /dev/null +++ b/packages/math/useToFixed/index.test.ts @@ -0,0 +1,43 @@ +import { ref } from 'vue-demi' +import { useToFixed } from '.' + +describe('useToFixed', () => { + it('should be defined', () => { + expect(useToFixed).toBeDefined() + }) + it('should work', () => { + const base = ref(45.125) + const result = useToFixed(base, 2) + expect(result.value).toBe(45.13) + base.value = -45.155 + expect(result.value).toBe(-45.15) + }) + it('input string should work', () => { + const base = ref('45.125') + const result = useToFixed(base, 2) + expect(result.value).toBe(45.13) + base.value = '-45.155' + expect(result.value).toBe(-45.15) + }) + it('out string should work', () => { + const base = ref('45.125') + const result = useToFixed(base, 3, { type: 'string' }) + expect(result.value).toMatchInlineSnapshot('"45.125"') + base.value = '-45.15' + expect(result.value).toMatchInlineSnapshot('"-45.150"') + }) + it('out ceil should work', () => { + const base = ref('45.121') + const result = useToFixed(base, 2, { math: 'ceil' }) + expect(result.value).toMatchInlineSnapshot('45.13') + base.value = '-45.151' + expect(result.value).toMatchInlineSnapshot('-45.15') + }) + it('out floor should work', () => { + const base = ref('45.129') + const result = useToFixed(base, 2, { math: 'floor' }) + expect(result.value).toMatchInlineSnapshot('45.12') + base.value = '-45.159' + expect(result.value).toMatchInlineSnapshot('-45.16') + }) +}) diff --git a/packages/math/useToFixed/index.ts b/packages/math/useToFixed/index.ts new file mode 100644 index 00000000000..754864c3efc --- /dev/null +++ b/packages/math/useToFixed/index.ts @@ -0,0 +1,30 @@ +import type { ComputedRef } from 'vue-demi' +import { computed } from 'vue-demi' +import type { MaybeComputedRef } from '@vueuse/shared' +import { resolveUnref } from '@vueuse/shared' + +/** + * Reactive `toFixed` + * + * @see https://vueuse.org/useToFixed + */ +export interface FixedTypes { + type?: 'string' | 'number' + math?: 'floor' | 'ceil' | 'round' +} + +export function useToFixed( + value: MaybeComputedRef, + digits: MaybeComputedRef, + options?: MaybeComputedRef, +): ComputedRef { + return computed(() => { + const floatValue = parseFloat(`${resolveUnref(value)}`) + const outValue = Math[resolveUnref(options)?.math || 'round'](floatValue * 10 ** resolveUnref(digits)) / 10 ** resolveUnref(digits) + return resolveUnref(options)?.type === 'string' + ? resolveUnref(digits) >= 0 + ? outValue.toFixed(resolveUnref(digits)) + : `${outValue}` + : outValue + }) +}