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:
110
web/vue/src/composables/state/useToggle/index.test.ts
Normal file
110
web/vue/src/composables/state/useToggle/index.test.ts
Normal 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);
|
||||
});
|
||||
});
|
||||
56
web/vue/src/composables/state/useToggle/index.ts
Normal file
56
web/vue/src/composables/state/useToggle/index.ts
Normal 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 };
|
||||
}
|
||||
Reference in New Issue
Block a user