diff --git a/packages/math/usePrecision/index.md b/packages/math/usePrecision/index.md new file mode 100644 index 00000000000..a4e2fdc4b5f --- /dev/null +++ b/packages/math/usePrecision/index.md @@ -0,0 +1,24 @@ +--- +category: '@Math' +--- + +# usePrecision + +Reactively set the precision of a number. + +## Usage + +```ts +import { usePrecision } from '@vueuse/math' + +const value = ref(3.1415) +const result = usePrecision(value, 2) // 3.14 + +const ceilResult = usePrecision(value, 2, { + math: 'ceil' +}) // 3.15 + +const floorResult = usePrecision(value, 3, { + math: 'floor' +}) // 3.141 +``` diff --git a/packages/math/usePrecision/index.test.ts b/packages/math/usePrecision/index.test.ts new file mode 100644 index 00000000000..1cb9419c2a9 --- /dev/null +++ b/packages/math/usePrecision/index.test.ts @@ -0,0 +1,30 @@ +import { ref } from 'vue-demi' +import { describe, expect, it } from 'vitest' +import { usePrecision } from '.' + +describe('usePrecision', () => { + it('should be defined', () => { + expect(usePrecision).toBeDefined() + }) + it('should work', () => { + const base = ref(45.125) + const result = usePrecision(base, 2) + expect(result.value).toBe(45.13) + base.value = -45.155 + expect(result.value).toBe(-45.15) + }) + it('out ceil should work', () => { + const base = ref(45.125) + const result = usePrecision(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 = usePrecision(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/usePrecision/index.ts b/packages/math/usePrecision/index.ts new file mode 100644 index 00000000000..e39d8e41a22 --- /dev/null +++ b/packages/math/usePrecision/index.ts @@ -0,0 +1,31 @@ +import type { ComputedRef } from 'vue-demi' +import { computed } from 'vue-demi' +import type { MaybeComputedRef } from '@vueuse/shared' +import { resolveUnref } from '@vueuse/shared' + +export interface UsePrecisionOptions { + /** + * Method to use for rounding + * + * @default 'round' + */ + math?: 'floor' | 'ceil' | 'round' +} + +/** + * Reactively set the precision of a number. + * + * @see https://vueuse.org/usePrecision + */ +export function usePrecision( + value: MaybeComputedRef, + digits: MaybeComputedRef, + options?: MaybeComputedRef, +): ComputedRef { + return computed(() => { + const _value = resolveUnref(value) + const _digits = resolveUnref(digits) + const power = 10 ** _digits + return Math[resolveUnref(options)?.math || 'round'](_value * power) / power + }) +}