Skip to content

Commit

Permalink
feat: new API for useToggle hook (#96)
Browse files Browse the repository at this point in the history
The hook structure and logic has been completely modified. It no longer toggles a boolean value by default, but now requires an array of values ​​to toggle.
  • Loading branch information
immois authored Jul 3, 2024
1 parent d83f7fa commit ea4a69d
Show file tree
Hide file tree
Showing 8 changed files with 156 additions and 110 deletions.
6 changes: 6 additions & 0 deletions .changeset/six-worms-watch.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
'@raddix/use-toggle': major
'@raddix/switch': minor
---

New API for useToggle hook [#96](https://github.com/vintach/raddix/pull/96)
74 changes: 48 additions & 26 deletions docs/en/use-toggle.mdx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
---
title: useToggle
description: A hook that toggles a boolean value.
description: Toggles state between given values.
---

## Installation
Expand All @@ -11,15 +11,51 @@ Install the custom hook from your command line.

## Usage

### Basic example
To toggle the state between given values ​​add an array to the `useToggle` hook.

In this example, we are going to expand or hide the text of a paragraph.
by clicking a button (read more/read less).
The first element of the array will be used by default as the initial value, you can
override this by adding the desired initial value as the second parameter.

<CodeBlock folder='use-toggle' file='example1.tsx' />
```jsx
import { useToggle } from '@raddix/use-toggle';

export default function App() {
const [color, toggle, setColor] = useToggle(['blue', 'orange', 'cyan']);

return (
<div>
<button onClick={toggle}>{color}</button>
<button onClick={() => setColor('blue')}>Set color blue</button>
<button onClick={() => setColor('cyan')}>Set color cyan</button>
</div>
)
}
```

## API

### Parameters

<ApiTable
data={[
{
name: 'values',
description: 'An array of values',
required: 'Yes',
type: 'Array<T>',
defaultValue: '-'
},
{
name: 'initValue',
description: 'initial value',
required: 'No',
type: 'T',
defaultValue: 'values[0]'
}
]}
/>


### Result

The `useToggle` hook returns an array with the following elements:
Expand All @@ -30,33 +66,19 @@ The `useToggle` hook returns an array with the following elements:
}}
data={[
{
name: '0',
name: '[0]',
description: 'The current value of the state.',
type: 'boolean'
type: 'T'
},
{
name: '1',
description: 'A function to change the state.',
name: '[1]',
description: 'A function to toggle the state.',
type: 'function'
},
{
name: '2',
description: 'A function to toggle the state.',
name: '[2]',
description: 'A function to change the state.',
type: 'function'
}
]}
/>

### Parameters

<ApiTable
data={[
{
name: 'initialValue',
description: 'The initial value of the boolean state.',
required: 'No',
type: 'boolean',
defaultValue: 'false'
}
},
]}
/>
85 changes: 55 additions & 30 deletions docs/es/use-toggle.mdx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
---
title: useToggle
description: Un hook que alterna un valor booleano.
description: Cambia el estado entre valores dados.
---

## Instalación
Expand All @@ -11,60 +11,85 @@ Instale el custom hook desde su terminal.

## Uso

### Ejemplo Básico
Para cambiar el estado entre valores dados agrega un array al hook `useToggle`.

En este ejemplo, vamos a expandir o esconder texto de un parrafo
dando click en un botón(leer más/leer menos).
El primer elemento de la matriz se utilizará de forma predeterminada como valor inicial; puede anular
esto agregando el valor inicial deseado como segundo parámetro.

<CodeBlock folder='use-toggle' file='example1.tsx' />
```jsx
import { useToggle } from '@raddix/use-toggle';

## API
export default function App() {
const [color, toggle, setColor] = useToggle(['blue', 'orange', 'cyan']);

### Resultado
return (
<div>
<button onClick={toggle}>{color}</button>
<button onClick={() => setColor('blue')}>Set color blue</button>
<button onClick={() => setColor('cyan')}>Set color cyan</button>
</div>
)
}
```

El hook `useToggle` devuelve un array con los siguientes elementos:
## API

### Parámetros

<ApiTable
head={{
name: 'Índice',
name: 'Nombre',
description: 'Descripción',
required: 'Requerido'
required: 'Requerido',
defaultValue: 'Valor por defecto',
type: false,
}}
data={[
{
name: '0',
description: 'El valor actual del estado.',
type: 'boolean'
},
{
name: '1',
description: 'Una función para cambiar el estado.',
type: 'function'
name: 'values',
description: 'Un array de valores',
required: 'Yes',
type: 'Array<T>',
defaultValue: '-'
},
{
name: '2',
description: 'Una función para alternar el estado.',
type: 'function'
name: 'initValue',
description: 'El valor inicial.',
required: 'No',
type: 'T',
defaultValue: 'values[0]'
}
]}
/>

### Parámetros

### Resultado

El hook `useToggle` devuelve un array con los siguientes elementos:

<ApiTable
head={{
name: 'Nombre',
name: 'Índice',
description: 'Descripción',
required: 'Requerido',
defaultValue: 'Valor por defecto'
required: false,
type: 'Tipo'
}}
data={[
{
name: 'initialValue',
description: 'El valor inicial del estado booleano.',
required: 'No',
type: 'boolean',
defaultValue: 'false'
name: '[0]',
description: 'El valor actual del estado.',
type: 'T'
},
{
name: '[1]',
description: 'Una función para alternar el estado.',
type: 'function'
},
{
name: '[2]',
description: 'Una función para cambiar el estado.',
type: 'function'
}
]}
/>

5 changes: 4 additions & 1 deletion packages/hooks/use-switch/src/switch.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,10 @@ export const useSwitch = (<E extends ElementType = 'div'>(
onChange: handleChange
} = props;

const [checked, setChecked, toggle] = useToggle(initialChecked);
const [checked, toggle, setChecked] = useToggle(
[false, true],
initialChecked
);

const nativeProps = Boolean(as === 'button' || as === 'input');
const nativeInput: boolean = as === 'input';
Expand Down
18 changes: 17 additions & 1 deletion packages/hooks/use-toggle/src/index.ts
Original file line number Diff line number Diff line change
@@ -1 +1,17 @@
export { useToggle } from './use-toggle';
import { useState, useCallback } from 'react';
import type { Dispatch, SetStateAction } from 'react';
type ReturnValue<T> = [T, () => void, Dispatch<SetStateAction<T>>];

export const useToggle = <T>(values: T[], initValue?: T): ReturnValue<T> => {
const [value, setValue] = useState(initValue ?? values[0]);

const toggle = useCallback(() => {
setValue(prev => {
const currentIndex = values.indexOf(prev);
const nextIndex = (currentIndex + 1) % values.length;
return values[nextIndex];
});
}, [values]);

return [value, toggle, setValue];
};
16 changes: 0 additions & 16 deletions packages/hooks/use-toggle/src/use-toggle.ts

This file was deleted.

59 changes: 25 additions & 34 deletions packages/hooks/use-toggle/tests/use-toggle.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,56 +3,47 @@ import { useToggle } from '../src';

describe('useToggle test:', () => {
test('should print initial value', () => {
const { result } = renderHook(() => useToggle());
const [state, setState, toggle] = result.current;
const { result } = renderHook(() => useToggle(['day', 'night']));
const [state, toggle, setState] = result.current;

expect(state).toBe(false);
expect(typeof setState).toBe('function');
expect(state).toBe('day');
expect(typeof toggle).toBe('function');
expect(typeof setState).toBe('function');
});

test('should print custom initial value', () => {
const { result } = renderHook(() => useToggle(true));
test('should use the first option as default', () => {
const { result } = renderHook(() => useToggle(['day', 'night']));
const [state] = result.current;

expect(state).toBe(true);
expect(state).toBe('day');
});

test('should print the mutated value with setState function', () => {
const { result } = renderHook(() => useToggle());
const [state, setState] = result.current;

expect(state).toBe(false);
test('should use the second parameter as default value', () => {
const { result } = renderHook(() => useToggle(['day', 'night'], 'night'));
const [state] = result.current;

act(() => {
setState(true);
});
expect(state).toBe('night');
});

expect(result.current[0]).toBe(true);
test('should print the mutated value with setState function', () => {
const { result } = renderHook(() => useToggle(['light', 'dark', 'system']));
const [, , setState] = result.current;

act(() => {
setState(false);
});
act(() => setState('system'));
expect(result.current[0]).toBe('system');

expect(result.current[0]).toBe(false);
act(() => setState('dark'));
expect(result.current[0]).toBe('dark');
});

test('should print the mutated value with toggle function', () => {
const { result } = renderHook(() => useToggle(true));
const [state, _, toogle] = result.current;

expect(state).toBe(true);

act(() => {
toogle();
});

expect(result.current[0]).toBe(false);
const { result } = renderHook(() => useToggle(['light', 'dark', 'system']));
const [, toogle] = result.current;

act(() => {
toogle();
});
act(() => toogle());
expect(result.current[0]).toBe('dark');

expect(result.current[0]).toBe(true);
act(() => toogle());
expect(result.current[0]).toBe('system');
});
});
3 changes: 1 addition & 2 deletions tsconfig.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"compilerOptions": {
"lib": ["dom", "ESNext"],
"lib": ["dom", "dom.iterable", "ESNext"],
"jsx": "react-jsx",
"module": "ESNext",
"target": "ESNext",
Expand All @@ -17,7 +17,6 @@
"noFallthroughCasesInSwitch": true,
"noImplicitOverride": true,
"noImplicitReturns": true,
"noUncheckedIndexedAccess": true,
"noUnusedLocals": true,
"noUnusedParameters": true,
"forceConsistentCasingInFileNames": true,
Expand Down

0 comments on commit ea4a69d

Please sign in to comment.