mirror of
https://github.com/robonen/tools.git
synced 2026-03-20 19:04:46 +00:00
feat(web/vue): add useStorage and useStorageAsync, separate all composables by categories
This commit is contained in:
8
web/vue/src/composables/state/useCounter/demo.vue
Normal file
8
web/vue/src/composables/state/useCounter/demo.vue
Normal file
@@ -0,0 +1,8 @@
|
||||
<script setup lang="ts">
|
||||
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div>
|
||||
</div>
|
||||
</template>
|
||||
81
web/vue/src/composables/state/useCounter/index.test.ts
Normal file
81
web/vue/src/composables/state/useCounter/index.test.ts
Normal file
@@ -0,0 +1,81 @@
|
||||
import { it, expect, describe } from 'vitest';
|
||||
import { ref } from 'vue';
|
||||
import { useCounter } from '.';
|
||||
|
||||
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('initialize count with the provided initial value from a getter', () => {
|
||||
const { count } = useCounter(() => 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);
|
||||
});
|
||||
});
|
||||
73
web/vue/src/composables/state/useCounter/index.ts
Normal file
73
web/vue/src/composables/state/useCounter/index.ts
Normal file
@@ -0,0 +1,73 @@
|
||||
import { ref, toValue, type MaybeRefOrGetter, type Ref } from 'vue';
|
||||
import { clamp } from '@robonen/stdlib';
|
||||
|
||||
export interface UseCounterOptions {
|
||||
min?: number;
|
||||
max?: number;
|
||||
}
|
||||
|
||||
export interface UseConterReturn {
|
||||
count: Ref<number>;
|
||||
increment: (delta?: number) => void;
|
||||
decrement: (delta?: number) => void;
|
||||
set: (value: number) => void;
|
||||
get: () => number;
|
||||
reset: (value?: number) => void;
|
||||
}
|
||||
|
||||
/**
|
||||
* @name useCounter
|
||||
* @category State
|
||||
* @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
|
||||
* @returns {UseConterReturn} The counter object
|
||||
*
|
||||
* @example
|
||||
* const { count, increment } = useCounter(0);
|
||||
*
|
||||
* @example
|
||||
* const { count, increment, decrement, set, get, reset } = useCounter(0, { min: 0, max: 10 });
|
||||
*
|
||||
* @since 0.0.1
|
||||
*/
|
||||
export function useCounter(
|
||||
initialValue: MaybeRefOrGetter<number> = 0,
|
||||
options: UseCounterOptions = {},
|
||||
): UseConterReturn {
|
||||
let _initialValue = toValue(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,
|
||||
};
|
||||
};
|
||||
Reference in New Issue
Block a user