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

feat(web/vue): add useStorage and useStorageAsync, separate all composables by categories

This commit is contained in:
2026-02-14 21:38:29 +07:00
parent 7dce7ed482
commit 6565fa3de8
64 changed files with 1564 additions and 55 deletions

View File

@@ -0,0 +1,110 @@
import { it, expect, describe } from 'vitest';
import { ref } from 'vue';
import { useToggle } from '.';
describe('useToggle', () => {
it('initialize with false by default', () => {
const { value } = useToggle();
expect(value.value).toBe(false);
});
it('initialize with the provided initial value', () => {
const { value } = useToggle(true);
expect(value.value).toBe(true);
});
it('initialize with the provided initial value from a ref', () => {
const { value } = useToggle(ref(true));
expect(value.value).toBe(true);
});
it('toggle from false to true', () => {
const { value, toggle } = useToggle(false);
toggle();
expect(value.value).toBe(true);
});
it('toggle from true to false', () => {
const { value, toggle } = useToggle(true);
toggle();
expect(value.value).toBe(false);
});
it('toggle multiple times', () => {
const { value, toggle } = useToggle(false);
toggle();
expect(value.value).toBe(true);
toggle();
expect(value.value).toBe(false);
toggle();
expect(value.value).toBe(true);
});
it('toggle returns the new value', () => {
const { toggle } = useToggle(false);
expect(toggle()).toBe(true);
expect(toggle()).toBe(false);
});
it('set a specific value via toggle', () => {
const { value, toggle } = useToggle(false);
toggle(true);
expect(value.value).toBe(true);
toggle(true);
expect(value.value).toBe(true);
});
it('use custom truthy and falsy values', () => {
const { value, toggle } = useToggle('off', {
truthyValue: 'on',
falsyValue: 'off',
});
expect(value.value).toBe('off');
toggle();
expect(value.value).toBe('on');
toggle();
expect(value.value).toBe('off');
});
it('set a specific custom value via toggle', () => {
const { value, toggle } = useToggle('off', {
truthyValue: 'on',
falsyValue: 'off',
});
toggle('on');
expect(value.value).toBe('on');
toggle('on');
expect(value.value).toBe('on');
});
it('use ref-based truthy and falsy values', () => {
const truthy = ref('yes');
const falsy = ref('no');
const { value, toggle } = useToggle('no', {
truthyValue: truthy,
falsyValue: falsy,
});
expect(value.value).toBe('no');
toggle();
expect(value.value).toBe('yes');
toggle();
expect(value.value).toBe('no');
});
it('use getter-based truthy and falsy values', () => {
const { value, toggle } = useToggle(0, {
truthyValue: () => 1,
falsyValue: () => 0,
});
expect(value.value).toBe(0);
toggle();
expect(value.value).toBe(1);
toggle();
expect(value.value).toBe(0);
});
});

View File

@@ -0,0 +1,56 @@
import { ref, toValue, type MaybeRefOrGetter, type MaybeRef, type Ref } from 'vue';
export interface UseToggleOptions<Truthy, Falsy> {
truthyValue?: MaybeRefOrGetter<Truthy>,
falsyValue?: MaybeRefOrGetter<Falsy>,
}
export interface UseToggleReturn<Truthy, Falsy> {
value: Ref<Truthy | Falsy>;
toggle: (value?: Truthy | Falsy) => Truthy | Falsy;
}
/**
* @name useToggle
* @category State
* @description A composable that provides a boolean toggle with customizable truthy/falsy values
*
* @param {MaybeRef<Truthy | Falsy>} [initialValue=false] The initial value
* @param {UseToggleOptions<Truthy, Falsy>} [options={}] Options for custom truthy/falsy values
* @returns {UseToggleReturn<Truthy, Falsy>} The toggle state and function
*
* @example
* const { value, toggle } = useToggle();
*
* @example
* const { value, toggle } = useToggle(false, { truthyValue: 'on', falsyValue: 'off' });
*
* @since 0.0.1
*/
export function useToggle<Truthy = true, Falsy = false>(
initialValue: MaybeRef<Truthy | Falsy> = false as Truthy | Falsy,
options: UseToggleOptions<Truthy, Falsy> = {},
): UseToggleReturn<Truthy, Falsy> {
const {
truthyValue = true as Truthy,
falsyValue = false as Falsy,
} = options;
const value = ref(initialValue) as Ref<Truthy | Falsy>;
const toggle = (newValue?: Truthy | Falsy) => {
if (newValue !== undefined) {
value.value = newValue;
return value.value;
}
const truthy = toValue(truthyValue);
const falsy = toValue(falsyValue);
value.value = value.value === truthy ? falsy : truthy;
return value.value;
};
return { value, toggle };
}