cogsbox-state 0.5.480 → 0.5.482
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/CogsState.d.ts +51 -78
- package/dist/CogsState.d.ts.map +1 -1
- package/dist/CogsState.js.map +1 -1
- package/dist/store.d.ts +2 -1
- package/dist/store.d.ts.map +1 -1
- package/dist/store.js.map +1 -1
- package/package.json +2 -1
- package/src/CogsState.tsx +156 -63
- package/src/store.ts +2 -1
package/src/CogsState.tsx
CHANGED
|
@@ -15,6 +15,10 @@ import {
|
|
|
15
15
|
useRef,
|
|
16
16
|
useState,
|
|
17
17
|
type CSSProperties,
|
|
18
|
+
type ChangeEvent,
|
|
19
|
+
type FocusEvent,
|
|
20
|
+
type JSX,
|
|
21
|
+
type MutableRefObject,
|
|
18
22
|
type ReactNode,
|
|
19
23
|
type RefObject,
|
|
20
24
|
} from 'react';
|
|
@@ -61,15 +65,15 @@ export type SyncInfo = {
|
|
|
61
65
|
|
|
62
66
|
export type FormElementParams<T> = StateObject<T> & {
|
|
63
67
|
$inputProps: {
|
|
64
|
-
ref?:
|
|
68
|
+
ref?: RefObject<any>;
|
|
65
69
|
value?: T extends boolean ? never : T;
|
|
66
70
|
onChange?: (
|
|
67
|
-
event:
|
|
71
|
+
event: ChangeEvent<
|
|
68
72
|
HTMLInputElement | HTMLTextAreaElement | HTMLSelectElement
|
|
69
73
|
>
|
|
70
74
|
) => void;
|
|
71
75
|
onBlur?: (
|
|
72
|
-
event:
|
|
76
|
+
event: FocusEvent<
|
|
73
77
|
HTMLInputElement | HTMLTextAreaElement | HTMLSelectElement
|
|
74
78
|
>
|
|
75
79
|
) => void;
|
|
@@ -165,11 +169,11 @@ export type EndType<
|
|
|
165
169
|
$_stateKey: string;
|
|
166
170
|
$isolate: {
|
|
167
171
|
(
|
|
168
|
-
renderFn: (state: StateObject<T, TPlugins>) =>
|
|
172
|
+
renderFn: (state: StateObject<T, TPlugins>) => ReactNode
|
|
169
173
|
): JSX.Element;
|
|
170
174
|
(
|
|
171
175
|
dependencies: any[],
|
|
172
|
-
renderFn: (state: StateObject<T, TPlugins>) =>
|
|
176
|
+
renderFn: (state: StateObject<T, TPlugins>) => ReactNode
|
|
173
177
|
): JSX.Element;
|
|
174
178
|
};
|
|
175
179
|
$formElement: (
|
|
@@ -202,7 +206,7 @@ export type EndType<
|
|
|
202
206
|
children,
|
|
203
207
|
hideMessage,
|
|
204
208
|
}: {
|
|
205
|
-
children:
|
|
209
|
+
children: ReactNode;
|
|
206
210
|
hideMessage?: boolean;
|
|
207
211
|
}) => JSX.Element;
|
|
208
212
|
$lastSynced?: SyncInfo;
|
|
@@ -542,7 +546,7 @@ export type FormsElementsType<
|
|
|
542
546
|
> = {
|
|
543
547
|
// These optional, built-in wrappers are unchanged.
|
|
544
548
|
validation?: (options: {
|
|
545
|
-
children:
|
|
549
|
+
children: ReactNode;
|
|
546
550
|
status: ValidationStatus;
|
|
547
551
|
severity: ValidationSeverity;
|
|
548
552
|
hasErrors: boolean;
|
|
@@ -564,13 +568,13 @@ export type FormsElementsType<
|
|
|
564
568
|
ScopedPluginApi<THookReturn, TFieldMetaData>
|
|
565
569
|
: never;
|
|
566
570
|
};
|
|
567
|
-
}) =>
|
|
571
|
+
}) => ReactNode;
|
|
568
572
|
syncRender?: (options: {
|
|
569
|
-
children:
|
|
573
|
+
children: ReactNode;
|
|
570
574
|
time: number;
|
|
571
575
|
data?: TState;
|
|
572
576
|
key?: string;
|
|
573
|
-
}) =>
|
|
577
|
+
}) => ReactNode;
|
|
574
578
|
};
|
|
575
579
|
const {
|
|
576
580
|
getInitialOptions,
|
|
@@ -758,8 +762,138 @@ export type PluginData = {
|
|
|
758
762
|
|
|
759
763
|
////////////////////////////////
|
|
760
764
|
|
|
765
|
+
type AnyCogsPlugin = CogsPlugin<string, any, any, any, any, any, any>;
|
|
766
|
+
|
|
767
|
+
type ExtractPluginOptions<T> = T extends {
|
|
768
|
+
useHook?: (params: { options: infer O }) => any;
|
|
769
|
+
}
|
|
770
|
+
? O
|
|
771
|
+
: T extends CogsPlugin<string, infer O, any, any, any, any, any>
|
|
772
|
+
? O
|
|
773
|
+
: never;
|
|
774
|
+
|
|
775
|
+
type PluginOptionsMap<TPlugins extends readonly AnyCogsPlugin[]> = {
|
|
776
|
+
[K in TPlugins[number] as K['name']]?: ExtractPluginOptions<K>;
|
|
777
|
+
};
|
|
778
|
+
|
|
779
|
+
type ExtractPluginState<T> = T extends {
|
|
780
|
+
initialState?: () => infer S;
|
|
781
|
+
}
|
|
782
|
+
? S extends object
|
|
783
|
+
? S
|
|
784
|
+
: {}
|
|
785
|
+
: T extends CogsPlugin<string, any, any, any, any, any, infer S>
|
|
786
|
+
? S extends object
|
|
787
|
+
? S
|
|
788
|
+
: {}
|
|
789
|
+
: {};
|
|
790
|
+
|
|
791
|
+
type PluginStates<TPlugins extends readonly AnyCogsPlugin[]> =
|
|
792
|
+
UnionToIntersection<ExtractPluginState<TPlugins[number]>> extends infer S
|
|
793
|
+
? S extends object
|
|
794
|
+
? S
|
|
795
|
+
: {}
|
|
796
|
+
: {};
|
|
797
|
+
|
|
798
|
+
type KnownKeys<T> =
|
|
799
|
+
string extends keyof T
|
|
800
|
+
? never
|
|
801
|
+
: number extends keyof T
|
|
802
|
+
? never
|
|
803
|
+
: symbol extends keyof T
|
|
804
|
+
? never
|
|
805
|
+
: keyof T;
|
|
806
|
+
|
|
807
|
+
type MergeInitialState<
|
|
808
|
+
State extends object,
|
|
809
|
+
PluginState extends object,
|
|
810
|
+
> = Prettify<
|
|
811
|
+
State & {
|
|
812
|
+
[K in keyof PluginState as K extends KnownKeys<State>
|
|
813
|
+
? never
|
|
814
|
+
: K]: PluginState[K];
|
|
815
|
+
}
|
|
816
|
+
>;
|
|
817
|
+
|
|
818
|
+
type CogsFullState<
|
|
819
|
+
State extends object,
|
|
820
|
+
TPlugins extends readonly AnyCogsPlugin[],
|
|
821
|
+
> = MergeInitialState<State, PluginStates<TPlugins>>;
|
|
822
|
+
|
|
823
|
+
type CleanIntersection<T> = T extends object ? { [K in keyof T]: T[K] } : T;
|
|
824
|
+
|
|
825
|
+
type KeyedKeys<P> = {
|
|
826
|
+
[K in keyof P]-?: NonNullable<P[K]> extends { __key: 'keyed'; map: any }
|
|
827
|
+
? K
|
|
828
|
+
: never;
|
|
829
|
+
}[keyof P];
|
|
830
|
+
|
|
831
|
+
type PluginOptionsForState<
|
|
832
|
+
PluginOptions,
|
|
833
|
+
StateKey extends PropertyKey,
|
|
834
|
+
> = {
|
|
835
|
+
[PName in keyof PluginOptions]?: PluginOptions[PName] extends infer P
|
|
836
|
+
? P extends Record<string, any>
|
|
837
|
+
? Prettify<
|
|
838
|
+
Partial<Pick<P, Exclude<keyof P, KeyedKeys<P>>>> & {
|
|
839
|
+
[K in KeyedKeys<P> as StateKey extends keyof NonNullable<
|
|
840
|
+
P[K]
|
|
841
|
+
>['map']
|
|
842
|
+
? NonNullable<P[K]>['map'][StateKey] extends undefined
|
|
843
|
+
? never
|
|
844
|
+
: keyof NonNullable<P[K]>['map'][StateKey] extends never
|
|
845
|
+
? never
|
|
846
|
+
: K
|
|
847
|
+
: never]: CleanIntersection<
|
|
848
|
+
StateKey extends keyof NonNullable<P[K]>['map']
|
|
849
|
+
? NonNullable<P[K]>['map'][StateKey]
|
|
850
|
+
: never
|
|
851
|
+
>;
|
|
852
|
+
}
|
|
853
|
+
>
|
|
854
|
+
: P
|
|
855
|
+
: never;
|
|
856
|
+
};
|
|
857
|
+
|
|
858
|
+
type UseCogsStateOptions<
|
|
859
|
+
StateSlice,
|
|
860
|
+
PluginOptions,
|
|
861
|
+
StateKey extends PropertyKey,
|
|
862
|
+
> = Prettify<
|
|
863
|
+
OptionsType<StateSlice, never> & PluginOptionsForState<PluginOptions, StateKey>
|
|
864
|
+
>;
|
|
865
|
+
|
|
866
|
+
type CreateCogsStateReturn<
|
|
867
|
+
State extends object,
|
|
868
|
+
TPlugins extends readonly AnyCogsPlugin[],
|
|
869
|
+
> = {
|
|
870
|
+
useCogsState: <StateKey extends keyof CogsFullState<State, TPlugins>>(
|
|
871
|
+
stateKey: StateKey,
|
|
872
|
+
options?: UseCogsStateOptions<
|
|
873
|
+
CogsFullState<State, TPlugins>[StateKey],
|
|
874
|
+
PluginOptionsMap<TPlugins>,
|
|
875
|
+
StateKey
|
|
876
|
+
>
|
|
877
|
+
) => StateObject<CogsFullState<State, TPlugins>[StateKey]>;
|
|
878
|
+
setCogsOptionsByKey: <StateKey extends keyof CogsFullState<State, TPlugins>>(
|
|
879
|
+
stateKey: StateKey,
|
|
880
|
+
options: CreateStateOptionsType<
|
|
881
|
+
CogsFullState<State, TPlugins>[StateKey],
|
|
882
|
+
TPlugins
|
|
883
|
+
> &
|
|
884
|
+
Omit<
|
|
885
|
+
OptionsType<CogsFullState<State, TPlugins>[StateKey]>,
|
|
886
|
+
keyof CreateStateOptionsType
|
|
887
|
+
>
|
|
888
|
+
) => void;
|
|
889
|
+
setCogsOptions: (
|
|
890
|
+
globalOptions: CreateStateOptionsType<unknown, TPlugins> &
|
|
891
|
+
Omit<OptionsType<unknown>, keyof CreateStateOptionsType>
|
|
892
|
+
) => void;
|
|
893
|
+
};
|
|
894
|
+
|
|
761
895
|
export const createCogsState = <
|
|
762
|
-
State extends
|
|
896
|
+
State extends object,
|
|
763
897
|
const TPlugins extends readonly CogsPlugin<
|
|
764
898
|
string,
|
|
765
899
|
any,
|
|
@@ -776,18 +910,8 @@ export const createCogsState = <
|
|
|
776
910
|
formElements?: FormsElementsType<State, TPlugins>;
|
|
777
911
|
validation?: ValidationOptionsType;
|
|
778
912
|
}
|
|
779
|
-
) => {
|
|
780
|
-
type
|
|
781
|
-
useHook?: (params: { options: infer O }) => any; // infers O here
|
|
782
|
-
}
|
|
783
|
-
? O
|
|
784
|
-
: T extends CogsPlugin<string, infer O, any, any, any, any, any> // AND here
|
|
785
|
-
? O
|
|
786
|
-
: never;
|
|
787
|
-
|
|
788
|
-
type PluginOptions = {
|
|
789
|
-
[K in TPlugins[number] as K['name']]?: ExtractPluginOptions<K>;
|
|
790
|
-
};
|
|
913
|
+
) : CreateCogsStateReturn<State, TPlugins> => {
|
|
914
|
+
type PluginOptions = PluginOptionsMap<TPlugins>;
|
|
791
915
|
|
|
792
916
|
if (opt?.plugins) {
|
|
793
917
|
pluginStore.getState().setRegisteredPlugins(opt.plugins as any);
|
|
@@ -798,39 +922,7 @@ export const createCogsState = <
|
|
|
798
922
|
? I
|
|
799
923
|
: never;
|
|
800
924
|
|
|
801
|
-
|
|
802
|
-
// falling back to structural inference from initialState() return type.
|
|
803
|
-
type ExtractPluginState<T> = T extends CogsPlugin<
|
|
804
|
-
string,
|
|
805
|
-
any,
|
|
806
|
-
any,
|
|
807
|
-
any,
|
|
808
|
-
any,
|
|
809
|
-
any,
|
|
810
|
-
infer S
|
|
811
|
-
>
|
|
812
|
-
? S extends Record<string, unknown>
|
|
813
|
-
? S
|
|
814
|
-
: {}
|
|
815
|
-
: T extends {
|
|
816
|
-
initialState?: () => infer S;
|
|
817
|
-
}
|
|
818
|
-
? S extends Record<string, unknown>
|
|
819
|
-
? S
|
|
820
|
-
: {}
|
|
821
|
-
: {};
|
|
822
|
-
|
|
823
|
-
// Extract the merged plugin states into a helper type
|
|
824
|
-
type PluginStates = UnionToIntersection<ExtractPluginState<TPlugins[number]>>;
|
|
825
|
-
|
|
826
|
-
// User keys win over plugin keys — omit overlapping plugin keys before merging.
|
|
827
|
-
type FullState = Prettify<
|
|
828
|
-
State & {
|
|
829
|
-
[K in keyof PluginStates as K extends keyof State
|
|
830
|
-
? never
|
|
831
|
-
: K]: PluginStates[K];
|
|
832
|
-
}
|
|
833
|
-
>;
|
|
925
|
+
type FullState = CogsFullState<State, TPlugins>;
|
|
834
926
|
const pluginState: Record<string, unknown> = {};
|
|
835
927
|
if (opt?.plugins) {
|
|
836
928
|
for (const plugin of opt.plugins) {
|
|
@@ -876,7 +968,7 @@ export const createCogsState = <
|
|
|
876
968
|
});
|
|
877
969
|
|
|
878
970
|
Object.keys(statePart).forEach((key) => {
|
|
879
|
-
initializeShadowState(key, statePart[key]);
|
|
971
|
+
initializeShadowState(key, (statePart as Record<string, unknown>)[key]);
|
|
880
972
|
});
|
|
881
973
|
type StateKeys = keyof FullState;
|
|
882
974
|
|
|
@@ -932,7 +1024,8 @@ export const createCogsState = <
|
|
|
932
1024
|
optionsRef.current = currentOptions;
|
|
933
1025
|
|
|
934
1026
|
const thiState =
|
|
935
|
-
getShadowValue(stateKey as string, []) ||
|
|
1027
|
+
getShadowValue(stateKey as string, []) ||
|
|
1028
|
+
(statePart as Record<string, unknown>)[stateKey as string];
|
|
936
1029
|
|
|
937
1030
|
const updater = useCogsStateFn<StateSlice<StateKey>>(thiState, {
|
|
938
1031
|
stateKey: stateKey as string,
|
|
@@ -1021,7 +1114,7 @@ export const createCogsState = <
|
|
|
1021
1114
|
useCogsState,
|
|
1022
1115
|
setCogsOptionsByKey,
|
|
1023
1116
|
setCogsOptions,
|
|
1024
|
-
}
|
|
1117
|
+
} as CreateCogsStateReturn<State, TPlugins>;
|
|
1025
1118
|
};
|
|
1026
1119
|
|
|
1027
1120
|
const saveToLocalStorage = <T,>(
|
|
@@ -1541,7 +1634,7 @@ function flushQueue() {
|
|
|
1541
1634
|
function createEffectiveSetState<T>(
|
|
1542
1635
|
thisKey: string,
|
|
1543
1636
|
sessionId: string | undefined,
|
|
1544
|
-
latestInitialOptionsRef:
|
|
1637
|
+
latestInitialOptionsRef: MutableRefObject<OptionsType<T> | null>
|
|
1545
1638
|
): EffectiveSetState<T> {
|
|
1546
1639
|
return (newStateOrFunction, path, updateObj) => {
|
|
1547
1640
|
executeUpdate(thisKey, path, newStateOrFunction, updateObj);
|
|
@@ -3467,7 +3560,7 @@ function createProxyHandler<
|
|
|
3467
3560
|
children,
|
|
3468
3561
|
hideMessage,
|
|
3469
3562
|
}: {
|
|
3470
|
-
children:
|
|
3563
|
+
children: ReactNode;
|
|
3471
3564
|
hideMessage?: boolean;
|
|
3472
3565
|
}) => (
|
|
3473
3566
|
<ValidationWrapper
|
|
@@ -3529,8 +3622,8 @@ function createProxyHandler<
|
|
|
3529
3622
|
if (prop === '$isolate') {
|
|
3530
3623
|
// We accept (renderFn) OR (deps, renderFn)
|
|
3531
3624
|
return (
|
|
3532
|
-
arg1: any[] | ((state: any) =>
|
|
3533
|
-
arg2?: (state: any) =>
|
|
3625
|
+
arg1: any[] | ((state: any) => ReactNode),
|
|
3626
|
+
arg2?: (state: any) => ReactNode
|
|
3534
3627
|
) => {
|
|
3535
3628
|
// Check if the first argument is the dependency array
|
|
3536
3629
|
const hasDependencies = Array.isArray(arg1);
|
package/src/store.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { create } from 'zustand';
|
|
2
|
+
import type { RefObject } from 'react';
|
|
2
3
|
|
|
3
4
|
import type {
|
|
4
5
|
OptionsType,
|
|
@@ -79,7 +80,7 @@ export type ClientActivityState = {
|
|
|
79
80
|
string,
|
|
80
81
|
{
|
|
81
82
|
// componentId -> element info
|
|
82
|
-
domRef:
|
|
83
|
+
domRef: RefObject<HTMLElement>;
|
|
83
84
|
elementType:
|
|
84
85
|
| 'input'
|
|
85
86
|
| 'textarea'
|