react-state-monad 1.0.24 → 1.0.25

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,54 +1,55 @@
1
- import {StateObject} from "../stateObject";
2
- import {ValidFieldFrom} from "./types";
3
-
4
- /**
5
- * Hook that derives a field from the state object and creates a new StateObject for the field's value.
6
- *
7
- * @template TOriginal - The type of the original state object.
8
- * @template TField - The type of the field value to be derived.
9
- * @param state - The StateObject containing the original state.
10
- * @param field - The field name to be derived from the state.
11
- * @returns A new StateObject for the derived field.
12
- */
13
- export function useFieldState<TOriginal, TField>(
14
- state: StateObject<TOriginal>,
15
- field: ValidFieldFrom<TOriginal, TField>
16
- ): StateObject<TField> {
17
- return state.map(
18
- (original) => original[field] as TField, // Extracts the field value.
19
- (newField, original) => ({...original, [field]: newField} as TOriginal) // Updates the field with the new value.
20
- );
21
- }
22
-
23
- /**
24
- * Hook that remaps the keys of a state object to a record of StateObjects.
25
- *
26
- * @template TOriginal - The type of the original state object.
27
- * @template TField - The type of the field value to be derived.
28
- * @param state - The StateObject containing the original state.
29
- * @returns A record where each key is mapped to a new StateObject for the corresponding field.
30
- */
31
-
32
- export function useRemapKeysState<TOriginal extends object, TField>(state: StateObject<TOriginal>): Record<string, StateObject<TField>> {
33
- // si state no tiene valor, retornar un invalid
34
-
35
- if (!state.hasValue) {
36
- return {} as Record<string, StateObject<TField>>;
37
- }
38
-
39
- if (Array.isArray(state.value)) {
40
- console.warn('useRemapKeysState should be used with objects, use useRemapArray for arrays');
41
- return {} as Record<string, StateObject<TField>>;
42
- }
43
-
44
- const keys = Object.keys(state.value);
45
-
46
- return keys.reduce((acc, key) => {
47
- acc[key] = useFieldState(state, key as ValidFieldFrom<TOriginal, TField>);
48
- return acc;
49
- }, {} as Record<string, StateObject<TField>>);
50
- }
51
-
52
-
53
-
1
+ import {StateObject} from "../stateObject";
2
+ import {ValidFieldFrom} from "./types";
3
+
4
+ /**
5
+ * Hook that derives a field from the state object and creates a new StateObject for the field's value.
6
+ *
7
+ * @template TOriginal - The type of the original state object.
8
+ * @template TField - The type of the field value to be derived.
9
+ * @param state - The StateObject containing the original state.
10
+ * @param field - The field name to be derived from the state.
11
+ * @returns A new StateObject for the derived field.
12
+ */
13
+ export function useFieldState<TOriginal, TField>(
14
+ state: StateObject<TOriginal>,
15
+ field: ValidFieldFrom<TOriginal, TField>
16
+ ): StateObject<TField> {
17
+ return state.map(
18
+ (original) => original[field] as TField, // Extracts the field value.
19
+ (newField, original) => ({...original, [field]: newField} as TOriginal) // Updates the field with the new value.
20
+ );
21
+ }
22
+
23
+ /**
24
+ * Hook that remaps the keys of a state object to a record of StateObjects.
25
+ *
26
+ * @template TOriginal - The type of the original state object.
27
+ * @template TField - The type of the field value to be derived.
28
+ * @param state - The StateObject containing the original state.
29
+ * @returns A record where each key is mapped to a new StateObject for the corresponding field.
30
+ */
31
+
32
+ export function useRemapKeysState<TOriginal extends object, TField>(state: StateObject<TOriginal>): Record<keyof TOriginal, StateObject<TField>> {
33
+ // si state no tiene valor, retornar un invalid
34
+
35
+ if (!state.hasValue) {
36
+ return {} as Record<keyof TOriginal, StateObject<TField>>;
37
+ }
38
+
39
+ if (Array.isArray(state.value)) {
40
+ console.warn('useRemapKeysState should be used with objects, use useRemapArray for arrays');
41
+ return {} as Record<keyof TOriginal, StateObject<TField>>;
42
+ }
43
+
44
+ const keys = Object.keys(state.value) as (keyof TOriginal)[];
45
+
46
+ return keys.reduce((acc, key) => {
47
+ acc[key] = useFieldState(state, key as ValidFieldFrom<TOriginal, TField>);
48
+ return acc;
49
+ }
50
+ , {} as Record<keyof TOriginal, StateObject<TField>>);
51
+ }
52
+
53
+
54
+
54
55
 
@@ -1,24 +1,24 @@
1
- import {StateObject} from "../stateObject";
2
- import {ValidState} from "../implementations/validState";
3
- import {EmptyState} from "../implementations/emptyState";
4
-
5
- /**
6
- * Hook that ensures a StateObject contains a defined, non-null value.
7
- * If the StateObject's value is `undefined` or `null`, it returns an EmptyState.
8
- * Otherwise, it returns a ValidState with the value and a setter to update the value.
9
- *
10
- * @template TOrigin - The type of the value contained in the StateObject.
11
- * @param state - The StateObject which may contain a value, `undefined`, or `null`.
12
- * @returns A new StateObject containing the value if it is defined and non-null,
13
- * otherwise an EmptyState.
14
- */
15
- export function useNullSafety<TOrigin>(state: StateObject<TOrigin | undefined | null>): StateObject<TOrigin> {
16
-
17
- if (!state.hasValue) return new EmptyState<TOrigin>();
18
-
19
- if (state.value === undefined) return new EmptyState<TOrigin>();
20
-
21
- if (state.value === null) return new EmptyState<TOrigin>();
22
-
23
- return new ValidState<TOrigin>(state.value, (value: TOrigin) => state.value = value);
1
+ import {StateObject} from "../stateObject";
2
+ import {ValidState} from "../implementations/validState";
3
+ import {EmptyState} from "../implementations/emptyState";
4
+
5
+ /**
6
+ * Hook that ensures a StateObject contains a defined, non-null value.
7
+ * If the StateObject's value is `undefined` or `null`, it returns an EmptyState.
8
+ * Otherwise, it returns a ValidState with the value and a setter to update the value.
9
+ *
10
+ * @template TOrigin - The type of the value contained in the StateObject.
11
+ * @param state - The StateObject which may contain a value, `undefined`, or `null`.
12
+ * @returns A new StateObject containing the value if it is defined and non-null,
13
+ * otherwise an EmptyState.
14
+ */
15
+ export function useNullSafety<TOrigin>(state: StateObject<TOrigin | undefined | null>): StateObject<TOrigin> {
16
+
17
+ if (!state.hasValue) return new EmptyState<TOrigin>();
18
+
19
+ if (state.value === undefined) return new EmptyState<TOrigin>();
20
+
21
+ if (state.value === null) return new EmptyState<TOrigin>();
22
+
23
+ return new ValidState<TOrigin>(state.value, (value: TOrigin) => state.value = value);
24
24
  }
@@ -1,50 +1,50 @@
1
- import {StateObject} from "../stateObject";
2
- import {ValidState} from "../implementations/validState";
3
- import {useState} from "react";
4
- import {useStateObject} from "./useStateObject";
5
-
6
- /**
7
- * Hook that maps each element in an array within a StateObject to a new StateObject,
8
- * allowing for independent updates of each element while keeping the overall array state synchronized.
9
- *
10
- * @template T - The type of the array elements.
11
- * @param state - The StateObject containing an array.
12
- * @returns An array of new StateObjects, each representing an element in the original array,
13
- * allowing individual updates while keeping the array state synchronized.
14
- */
15
- export function useRemapArray<T>(state: StateObject<T[]>): StateObject<T>[] {
16
- if (!state.hasValue) return [] // Returns an empty array if the state has no value.
17
-
18
- const count = state.value.length
19
- const result: StateObject<T>[] = []
20
-
21
- for (let i = 0; i < count; i++) {
22
- result.push(
23
- new ValidState<T>(
24
- state.value[i], // The current value of the element at index i.
25
- (newElement) => { // Setter to update the element at index i in the array.
26
- const arrayCopy = [...state.value]; // Create a copy of the original array.
27
- arrayCopy[i] = newElement; // Replace the element at index i with the new element.
28
- state.value = arrayCopy; // Update the state with the new array, triggering a re-render.
29
- }
30
- )
31
- )
32
- }
33
-
34
- return result // Return the array of StateObjects representing each element.
35
- }
36
-
37
-
38
- /**
39
- * Hook that takes an array of StateObjects and returns a new StateObject containing that array,
40
- * allowing for updates to the entire array while keeping it synchronized within a single StateObject.
41
- *
42
- * @template T - The type of the elements in the array.
43
- * @param states - The array of StateObjects.
44
- * @returns A new StateObject containing the array of StateObjects, allowing for updates to the whole array.
45
- */
46
- export function useArrayState<T>(states: StateObject<T>[]): StateObject<T[]> {
47
-
48
- return useStateObject(states.filter(state => state.hasValue).map(state => state.value));
49
-
50
- }
1
+ import {StateObject} from "../stateObject";
2
+ import {ValidState} from "../implementations/validState";
3
+ import {useState} from "react";
4
+ import {useStateObject} from "./useStateObject";
5
+
6
+ /**
7
+ * Hook that maps each element in an array within a StateObject to a new StateObject,
8
+ * allowing for independent updates of each element while keeping the overall array state synchronized.
9
+ *
10
+ * @template T - The type of the array elements.
11
+ * @param state - The StateObject containing an array.
12
+ * @returns An array of new StateObjects, each representing an element in the original array,
13
+ * allowing individual updates while keeping the array state synchronized.
14
+ */
15
+ export function useRemapArray<T>(state: StateObject<T[]>): StateObject<T>[] {
16
+ if (!state.hasValue) return [] // Returns an empty array if the state has no value.
17
+
18
+ const count = state.value.length
19
+ const result: StateObject<T>[] = []
20
+
21
+ for (let i = 0; i < count; i++) {
22
+ result.push(
23
+ new ValidState<T>(
24
+ state.value[i], // The current value of the element at index i.
25
+ (newElement) => { // Setter to update the element at index i in the array.
26
+ const arrayCopy = [...state.value]; // Create a copy of the original array.
27
+ arrayCopy[i] = newElement; // Replace the element at index i with the new element.
28
+ state.value = arrayCopy; // Update the state with the new array, triggering a re-render.
29
+ }
30
+ )
31
+ )
32
+ }
33
+
34
+ return result // Return the array of StateObjects representing each element.
35
+ }
36
+
37
+
38
+ /**
39
+ * Hook that takes an array of StateObjects and returns a new StateObject containing that array,
40
+ * allowing for updates to the entire array while keeping it synchronized within a single StateObject.
41
+ *
42
+ * @template T - The type of the elements in the array.
43
+ * @param states - The array of StateObjects.
44
+ * @returns A new StateObject containing the array of StateObjects, allowing for updates to the whole array.
45
+ */
46
+ export function useArrayState<T>(states: StateObject<T>[]): StateObject<T[]> {
47
+
48
+ return useStateObject(states.filter(state => state.hasValue).map(state => state.value));
49
+
50
+ }
@@ -1,15 +1,15 @@
1
- import {StateObject} from "../stateObject";
2
- import {useState} from "react";
3
- import {ValidState} from "../implementations/validState";
4
-
5
- /**
6
- * Hook that initializes a StateObject with the given initial value.
7
- *
8
- * @template T - The type of the value to be stored in the state.
9
- * @param initialState - The initial value of the state.
10
- * @returns A StateObject representing the initialized state.
11
- */
12
- export function useStateObject<T>(initialState: T): StateObject<T> {
13
- const [state, setState] = useState<T>(initialState);
14
- return new ValidState<T>(state, setState); // Returns a new ValidState object with the initial state value.
1
+ import {StateObject} from "../stateObject";
2
+ import {useState} from "react";
3
+ import {ValidState} from "../implementations/validState";
4
+
5
+ /**
6
+ * Hook that initializes a StateObject with the given initial value.
7
+ *
8
+ * @template T - The type of the value to be stored in the state.
9
+ * @param initialState - The initial value of the state.
10
+ * @returns A StateObject representing the initialized state.
11
+ */
12
+ export function useStateObject<T>(initialState: T): StateObject<T> {
13
+ const [state, setState] = useState<T>(initialState);
14
+ return new ValidState<T>(state, setState); // Returns a new ValidState object with the initial state value.
15
15
  }
@@ -1,43 +1,43 @@
1
- import {StateObject} from "../stateObject";
2
-
3
- /**
4
- * Represents a state that holds no value and is considered "empty".
5
- * This is used as a fallback or default when there is no valid state.
6
- * you should NEVER use this class directly, use the `StateObject` interface instead.
7
- * and create instances by using the hooks
8
- * @template T - The type of the value that could be held by the state.
9
- */
10
- export class EmptyState<T> implements StateObject<T> {
11
- // No value stored, returns an error when accessed.
12
- get value(): T {
13
- throw new Error("Not implemented");
14
- }
15
-
16
- get hasValue(): boolean {
17
- return false;
18
- }
19
-
20
- orElse(orElse: T): T {
21
- return orElse; // Returns the fallback value when the state is empty.
22
- }
23
-
24
- do() {
25
- // No operation for empty state.
26
- }
27
-
28
- filter(): StateObject<T> {
29
- return this; // The empty state remains unchanged when filtered.
30
- }
31
-
32
- set value(_: T) {
33
- // No operation for setting a value in the empty state.
34
- }
35
-
36
- flatMap<U>(): StateObject<U> {
37
- return new EmptyState<U>(); // Returns an empty state when flatMapped.
38
- }
39
-
40
- map<U>(): StateObject<U> {
41
- return new EmptyState<U>(); // Returns an empty state when mapped.
42
- }
1
+ import {StateObject} from "../stateObject";
2
+
3
+ /**
4
+ * Represents a state that holds no value and is considered "empty".
5
+ * This is used as a fallback or default when there is no valid state.
6
+ * you should NEVER use this class directly, use the `StateObject` interface instead.
7
+ * and create instances by using the hooks
8
+ * @template T - The type of the value that could be held by the state.
9
+ */
10
+ export class EmptyState<T> implements StateObject<T> {
11
+ // No value stored, returns an error when accessed.
12
+ get value(): T {
13
+ throw new Error("Not implemented");
14
+ }
15
+
16
+ get hasValue(): boolean {
17
+ return false;
18
+ }
19
+
20
+ orElse(orElse: T): T {
21
+ return orElse; // Returns the fallback value when the state is empty.
22
+ }
23
+
24
+ do() {
25
+ // No operation for empty state.
26
+ }
27
+
28
+ filter(): StateObject<T> {
29
+ return this; // The empty state remains unchanged when filtered.
30
+ }
31
+
32
+ set value(_: T) {
33
+ // No operation for setting a value in the empty state.
34
+ }
35
+
36
+ flatMap<U>(): StateObject<U> {
37
+ return new EmptyState<U>(); // Returns an empty state when flatMapped.
38
+ }
39
+
40
+ map<U>(): StateObject<U> {
41
+ return new EmptyState<U>(); // Returns an empty state when mapped.
42
+ }
43
43
  }
@@ -1,60 +1,60 @@
1
- import {EmptyState} from "./emptyState";
2
- import {StateObject} from "../stateObject";
3
-
4
- /**
5
- * Represents a state that holds a valid value of type T.
6
- * you should NEVER use this class directly, use the `StateObject` interface instead.
7
- * and create instances by using the hooks
8
- * @template T - The type of the value stored in the state.
9
- */
10
- export class ValidState<T> implements StateObject<T> {
11
- private readonly state: T;
12
- private readonly setter: (state: T) => void;
13
-
14
- constructor(state: T, setter: (state: T) => void) {
15
- this.state = state;
16
- this.setter = setter;
17
- }
18
-
19
- get value(): T {
20
- return this.state;
21
- }
22
-
23
- do(action: (t: T) => void) {
24
- action(this.state); // Performs the given action on the state value.
25
- }
26
-
27
- orElse() {
28
- return this.state; // Returns the state value as it is valid.
29
- }
30
-
31
- set value(newState: T) {
32
- this.setter(newState); // Sets a new value for the state.
33
- }
34
-
35
- map<U>(
36
- mappingFunction: (t: T) => U,
37
- inverseMappingFunction: (u: U, t: T) => T
38
- ): StateObject<U> {
39
- const derivedState = mappingFunction(this.state);
40
- const derivedSetter = (newState: U) => {
41
- this.setter(inverseMappingFunction(newState, this.state)); // Updates the state with the inverse mapping.
42
- };
43
-
44
- return new ValidState<U>(derivedState, derivedSetter); // Returns a new state object with the transformed value.
45
- }
46
-
47
- flatMap<U>(
48
- mappingFunction: (t: T) => StateObject<U>
49
- ): StateObject<U> {
50
- return mappingFunction(this.state); // Applies the mapping function and returns the result.
51
- }
52
-
53
- get hasValue(): boolean {
54
- return true;
55
- }
56
-
57
- filter(predicate: (t: T) => boolean): StateObject<T> {
58
- return predicate(this.state) ? (this as StateObject<T>) : new EmptyState<T>(); // Filters the state based on the predicate.
59
- }
1
+ import {EmptyState} from "./emptyState";
2
+ import {StateObject} from "../stateObject";
3
+
4
+ /**
5
+ * Represents a state that holds a valid value of type T.
6
+ * you should NEVER use this class directly, use the `StateObject` interface instead.
7
+ * and create instances by using the hooks
8
+ * @template T - The type of the value stored in the state.
9
+ */
10
+ export class ValidState<T> implements StateObject<T> {
11
+ private readonly state: T;
12
+ private readonly setter: (state: T) => void;
13
+
14
+ constructor(state: T, setter: (state: T) => void) {
15
+ this.state = state;
16
+ this.setter = setter;
17
+ }
18
+
19
+ get value(): T {
20
+ return this.state;
21
+ }
22
+
23
+ do(action: (t: T) => void) {
24
+ action(this.state); // Performs the given action on the state value.
25
+ }
26
+
27
+ orElse() {
28
+ return this.state; // Returns the state value as it is valid.
29
+ }
30
+
31
+ set value(newState: T) {
32
+ this.setter(newState); // Sets a new value for the state.
33
+ }
34
+
35
+ map<U>(
36
+ mappingFunction: (t: T) => U,
37
+ inverseMappingFunction: (u: U, t: T) => T
38
+ ): StateObject<U> {
39
+ const derivedState = mappingFunction(this.state);
40
+ const derivedSetter = (newState: U) => {
41
+ this.setter(inverseMappingFunction(newState, this.state)); // Updates the state with the inverse mapping.
42
+ };
43
+
44
+ return new ValidState<U>(derivedState, derivedSetter); // Returns a new state object with the transformed value.
45
+ }
46
+
47
+ flatMap<U>(
48
+ mappingFunction: (t: T) => StateObject<U>
49
+ ): StateObject<U> {
50
+ return mappingFunction(this.state); // Applies the mapping function and returns the result.
51
+ }
52
+
53
+ get hasValue(): boolean {
54
+ return true;
55
+ }
56
+
57
+ filter(predicate: (t: T) => boolean): StateObject<T> {
58
+ return predicate(this.state) ? (this as StateObject<T>) : new EmptyState<T>(); // Filters the state based on the predicate.
59
+ }
60
60
  }
package/src/index.ts CHANGED
@@ -1,10 +1,10 @@
1
- export * from "./hooks/useFieldState";
2
- export * from "./hooks/useElementState";
3
- export * from "./hooks/useEmptyState";
4
- export * from "./hooks/useFieldState";
5
- export * from "./hooks/useRemapArray";
6
- export * from "./hooks/useStateObject";
7
- export * from "./hooks/useNullSafety";
8
- export * from "./stateObject";
9
-
10
- export default this;
1
+ export * from "./hooks/useFieldState";
2
+ export * from "./hooks/useElementState";
3
+ export * from "./hooks/useEmptyState";
4
+ export * from "./hooks/useFieldState";
5
+ export * from "./hooks/useRemapArray";
6
+ export * from "./hooks/useStateObject";
7
+ export * from "./hooks/useNullSafety";
8
+ export * from "./stateObject";
9
+
10
+ export default this;