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/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?: React.RefObject<any>;
68
+ ref?: RefObject<any>;
65
69
  value?: T extends boolean ? never : T;
66
70
  onChange?: (
67
- event: React.ChangeEvent<
71
+ event: ChangeEvent<
68
72
  HTMLInputElement | HTMLTextAreaElement | HTMLSelectElement
69
73
  >
70
74
  ) => void;
71
75
  onBlur?: (
72
- event: React.FocusEvent<
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>) => React.ReactNode
172
+ renderFn: (state: StateObject<T, TPlugins>) => ReactNode
169
173
  ): JSX.Element;
170
174
  (
171
175
  dependencies: any[],
172
- renderFn: (state: StateObject<T, TPlugins>) => React.ReactNode
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: React.ReactNode;
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: React.ReactNode;
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
- }) => React.ReactNode;
571
+ }) => ReactNode;
568
572
  syncRender?: (options: {
569
- children: React.ReactNode;
573
+ children: ReactNode;
570
574
  time: number;
571
575
  data?: TState;
572
576
  key?: string;
573
- }) => React.ReactNode;
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 Record<string, unknown>,
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 ExtractPluginOptions<T> = T extends {
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
- // Extract plugin initial state from the CogsPlugin generic (7th param) first,
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, []) || statePart[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: React.MutableRefObject<OptionsType<T> | null>
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: React.ReactNode;
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) => React.ReactNode),
3533
- arg2?: (state: any) => React.ReactNode
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: React.RefObject<HTMLElement>;
83
+ domRef: RefObject<HTMLElement>;
83
84
  elementType:
84
85
  | 'input'
85
86
  | 'textarea'