1
0
mirror of https://github.com/robonen/tools.git synced 2026-03-20 02:44:45 +00:00

feat(packages/vue): add useCounter composable

This commit is contained in:
2024-05-30 04:16:45 +07:00
parent 03245921da
commit d7c32f2f45
4 changed files with 143 additions and 0 deletions

View File

@@ -0,0 +1,8 @@
<script setup lang="ts">
</script>
<template>
<div>
</div>
</template>

View File

@@ -0,0 +1,76 @@
import { it, expect, describe } from 'vitest';
import { useCounter } from '.';
import { ref } from 'vue';
describe('useCounter', () => {
it('initialize count with the provided initial value', () => {
const { count } = useCounter(5);
expect(count.value).toBe(5);
});
it('initialize count with the provided initial value from a ref', () => {
const { count } = useCounter(ref(5));
expect(count.value).toBe(5);
});
it('increment count by 1 by default', () => {
const { count, increment } = useCounter(0);
increment();
expect(count.value).toBe(1);
});
it('increment count by the specified delta', () => {
const { count, increment } = useCounter(0);
increment(5);
expect(count.value).toBe(5);
});
it('decrement count by 1 by default', () => {
const { count, decrement } = useCounter(5);
decrement();
expect(count.value).toBe(4);
});
it('decrement count by the specified delta', () => {
const { count, decrement } = useCounter(10);
decrement(5);
expect(count.value).toBe(5);
});
it('set count to the specified value', () => {
const { count, set } = useCounter(0);
set(10);
expect(count.value).toBe(10);
});
it('get the current count value', () => {
const { get } = useCounter(5);
expect(get()).toBe(5);
});
it('reset count to the initial value', () => {
const { count, reset } = useCounter(10);
count.value = 5;
reset();
expect(count.value).toBe(10);
});
it('reset count to the specified value', () => {
const { count, reset } = useCounter(10);
count.value = 5;
reset(20);
expect(count.value).toBe(20);
});
it('clamp count to the minimum value', () => {
const { count, decrement } = useCounter(Number.MIN_SAFE_INTEGER);
decrement();
expect(count.value).toBe(Number.MIN_SAFE_INTEGER);
});
it('clamp count to the maximum value', () => {
const { count, increment } = useCounter(Number.MAX_SAFE_INTEGER);
increment();
expect(count.value).toBe(Number.MAX_SAFE_INTEGER);
});
});

View File

@@ -0,0 +1,58 @@
import { ref, unref, type MaybeRef } from 'vue';
import { clamp } from '@robonen/stdlib';
export interface UseCounterOptions {
min?: number;
max?: number;
}
/**
* @name useCounter
* @category Utilities
* @description A composable that provides a counter with increment, decrement, set, get, and reset functions
*
* @param {MaybeRef<number>} [initialValue=0] The initial value of the counter
* @param {UseCounterOptions} [options={}] The options for the counter
* @param {number} [options.min=Number.MIN_SAFE_INTEGER] The minimum value of the counter
* @param {number} [options.max=Number.MAX_SAFE_INTEGER] The maximum value of the counter
*
* @example
* const { count, increment } = useCounter(0);
*
* @example
* const { count, increment, decrement, set, get, reset } = useCounter(0, { min: 0, max: 10 });
*/
export function useCounter(initialValue: MaybeRef<number> = 0, options: UseCounterOptions = {}) {
let _initialValue = unref(initialValue);
const count = ref(initialValue);
const {
min = Number.MIN_SAFE_INTEGER,
max = Number.MAX_SAFE_INTEGER,
} = options;
const increment = (delta = 1) =>
count.value = clamp(count.value + delta, min, max);
const decrement = (delta = 1) =>
count.value = clamp(count.value - delta, min, max);
const set = (value: number) =>
count.value = clamp(value, min, max);
const get = () => count.value;
const reset = (value = _initialValue) => {
_initialValue = value;
return set(value);
};
return {
count,
increment,
decrement,
set,
get,
reset,
};
};

View File

@@ -0,0 +1 @@
export * from './composables';