cross-state 0.9.3 → 0.10.0

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.
Files changed (44) hide show
  1. package/dist/cjs/cache.cjs +2 -7
  2. package/dist/cjs/cache.cjs.map +1 -1
  3. package/dist/cjs/index.cjs +3 -89
  4. package/dist/cjs/index.cjs.map +1 -1
  5. package/dist/cjs/react/index.cjs +87 -36
  6. package/dist/cjs/react/index.cjs.map +1 -1
  7. package/dist/cjs/scope.cjs +2 -3
  8. package/dist/cjs/scope.cjs.map +1 -1
  9. package/dist/cjs/store.cjs +47 -9
  10. package/dist/cjs/store.cjs.map +1 -1
  11. package/dist/cjs/urlStore.cjs +94 -0
  12. package/dist/cjs/urlStore.cjs.map +1 -0
  13. package/dist/cjs/useCache.cjs +2 -7
  14. package/dist/cjs/useCache.cjs.map +1 -1
  15. package/dist/es/cache.mjs +3 -8
  16. package/dist/es/cache.mjs.map +1 -1
  17. package/dist/es/index.mjs +27 -113
  18. package/dist/es/index.mjs.map +1 -1
  19. package/dist/es/react/index.mjs +90 -39
  20. package/dist/es/react/index.mjs.map +1 -1
  21. package/dist/es/scope.mjs +2 -3
  22. package/dist/es/scope.mjs.map +1 -1
  23. package/dist/es/store.mjs +55 -17
  24. package/dist/es/store.mjs.map +1 -1
  25. package/dist/es/urlStore.mjs +95 -0
  26. package/dist/es/urlStore.mjs.map +1 -0
  27. package/dist/es/useCache.mjs +3 -8
  28. package/dist/es/useCache.mjs.map +1 -1
  29. package/dist/types/core/index.d.ts +1 -1
  30. package/dist/types/core/store.d.ts +1 -1
  31. package/dist/types/core/urlStore.d.ts +6 -14
  32. package/dist/types/index2.d.ts +2 -0
  33. package/dist/types/lib/autobind.d.ts +1 -0
  34. package/dist/types/lib/path.d.ts +1 -1
  35. package/dist/types/react/form/form.d.ts +18 -9
  36. package/dist/types/react/form/formField.d.ts +53 -0
  37. package/dist/types/react/form/index.d.ts +1 -1
  38. package/dist/types/react/index.d.ts +1 -0
  39. package/dist/types/react/reactMethods.d.ts +1 -1
  40. package/dist/types/react/register.d.ts +1 -1
  41. package/dist/types/react/scope.d.ts +7 -2
  42. package/dist/types/react/useUrlParamScope.d.ts +4 -0
  43. package/package.json +10 -10
  44. package/dist/types/react/form/formInput.d.ts +0 -48
@@ -1,6 +1,5 @@
1
- import { type Update } from './commonTypes';
2
- import { Store, type StoreOptions } from './store';
3
- import { type Path, type Value } from '../lib/path';
1
+ import { type Cancel } from './commonTypes';
2
+ import { type Store, type StoreOptions } from './store';
4
3
  export interface UrlStoreOptions<T> extends StoreOptions {
5
4
  key: string;
6
5
  type?: 'search' | 'hash';
@@ -13,14 +12,7 @@ export interface UrlStoreOptionsWithDefaults<T> extends UrlStoreOptions<T> {
13
12
  defaultValue: T;
14
13
  }
15
14
  export type UrlStoreOptionsRequired<T> = UrlStoreOptions<T> & Required<Pick<UrlStoreOptions<T>, 'type' | 'serialize' | 'deserialize' | 'defaultValue'>>;
16
- export declare class UrlStore<T> extends Store<T> {
17
- readonly options: UrlStoreOptionsRequired<T>;
18
- private serializedDefaultValue;
19
- constructor(options: UrlStoreOptionsRequired<T>);
20
- set(update: Update<T>): void;
21
- set<P extends Path<T>>(path: P, update: Update<Value<T, P>>): void;
22
- protected watchUrl(): () => void;
23
- protected updateUrl(value: T | undefined): void;
24
- }
25
- export declare function createUrlStore<T>(options: UrlStoreOptionsWithDefaults<T>): UrlStore<T>;
26
- export declare function createUrlStore<T>(options: UrlStoreOptions<T>): UrlStore<T | undefined>;
15
+ export declare function connectUrl<T>(store: Store<T>, options: UrlStoreOptionsWithDefaults<T>): Cancel;
16
+ export declare function connectUrl<T>(store: Store<T | undefined>, options: UrlStoreOptions<T>): Cancel;
17
+ export declare function createUrlStore<T>(options: UrlStoreOptionsWithDefaults<T>): Store<T>;
18
+ export declare function createUrlStore<T>(options: UrlStoreOptions<T>): Store<T | undefined>;
@@ -0,0 +1,2 @@
1
+ export { calcDuration } from './lib/calcDuration';
2
+ export * from './core';
@@ -0,0 +1 @@
1
+ export declare const autobind: <TClass extends abstract new (...args: any) => any = abstract new (...args: any) => any>(_class: TClass, _context?: ClassDecoratorContext<TClass> | undefined) => TClass;
@@ -7,7 +7,7 @@ export type _PathAsArray<T, Optional, MaxDepth, Depth extends 1[]> = true extend
7
7
  export type PathAsArray<T, Optional extends boolean = false, MaxDepth extends number = 5> = _PathAsArray<T, Optional, MaxDepth, []>;
8
8
  export type PathAsString<T, Optional extends boolean = false, MaxDepth extends number = 5> = ArrayToStringPath<PathAsArray<T, Optional, MaxDepth>>;
9
9
  export type Path<T, Optional extends boolean = false, MaxDepth extends number = 5> = PathAsString<T, Optional, MaxDepth> | PathAsArray<T, Optional, MaxDepth>;
10
- export type Value<T, P> = true extends IsAny<T> | IsAny<P> ? any : true extends IsNever<T> | IsNever<P> ? never : P extends string ? Value<T, StringToArrayPath<P>> : P extends readonly [infer First extends KeyType, ...infer Rest extends KeyType[]] ? T extends Map<any, infer V> | Set<infer V> ? Value<V, Rest> | undefined : T extends Array_ ? any[] extends T ? Value<T[First & keyof T], Rest> | undefined : Value<T[First & keyof T], Rest> : T extends Object_ ? Record<any, any> extends T ? Value<T[First], Rest> | undefined : Value<T[First], Rest> : never : T;
10
+ export type Value<T, P> = P extends readonly [] ? T : true extends IsAny<T> | IsAny<P> ? any : true extends IsNever<T> | IsNever<P> ? never : P extends string ? Value<T, StringToArrayPath<P>> : P extends readonly [infer First extends KeyType, ...infer Rest extends readonly KeyType[]] ? T extends Map<any, infer V> | Set<infer V> ? Value<V, Rest> | undefined : T extends Array_ ? any[] extends T ? Value<T[First & keyof T], Rest> | undefined : Value<T[First & keyof T], Rest> : T extends Object_ ? Record<any, any> extends T ? Value<T[First], Rest> | undefined : Value<T[First], Rest> : never : never;
11
11
  export type _WildcardPathAsArray<T, MaxDepth, Depth extends 1[]> = [] | (0 extends 1 & T ? KeyType[] : T extends never ? never : T extends Object_ ? Depth['length'] extends MaxDepth ? string[] : T extends Map<infer K extends KeyType, infer V> ? ['*'] | [K] | [K, ..._WildcardPathAsArray<V, MaxDepth, [...Depth, 1]>] : T extends Set<any> ? ['*'] | [number] : {
12
12
  [K in GetKeys<T>]: ['*'] | [K] | [K, ..._WildcardPathAsArray<T[K], MaxDepth, [...Depth, 1]>];
13
13
  }[GetKeys<T>] : never);
@@ -1,11 +1,13 @@
1
- import { type ComponentPropsWithoutRef, type ReactNode } from 'react';
1
+ import { type ComponentPropsWithoutRef, type HTMLProps } from 'react';
2
2
  import { type UseStoreOptions } from '../useStore';
3
3
  import { type FormErrorProps } from './formError';
4
- import { type FormInputComponent, type FormInputProps } from './formInput';
4
+ import { type FormFieldComponent, type FormFieldProps } from './formField';
5
+ import { Scope, type UrlStoreOptions } from '../../core';
5
6
  import { type PathAsString, type Value, type WildcardPathAsString, type WildcardValue } from '../../lib/path';
6
7
  export interface FormOptions<TDraft, TOriginal> {
7
8
  defaultValue: TDraft;
8
9
  validations?: Validations<TDraft, TOriginal>;
10
+ urlState?: boolean | UrlStoreOptions<TDraft>;
9
11
  }
10
12
  export type Validations<TDraft, TOriginal> = {
11
13
  [P in WildcardPathAsString<TDraft>]?: Record<string, Validation<WildcardValue<TDraft, P>, TDraft, TOriginal>>;
@@ -24,13 +26,17 @@ export interface Field<TDraft, TOriginal, TPath extends PathAsString<TDraft>> {
24
26
  }
25
27
  export declare class Form<TDraft, TOriginal extends TDraft = TDraft> {
26
28
  readonly options: FormOptions<TDraft, TOriginal>;
27
- private context;
28
- private state;
29
+ context: import("react").Context<{
30
+ original: TOriginal | undefined;
31
+ options: FormOptions<TDraft, TOriginal>;
32
+ }>;
33
+ state: Scope<{
34
+ draft?: TDraft | undefined;
35
+ touched: Set<string>;
36
+ errors: Map<string, string[]>;
37
+ hasTriggeredValidations?: boolean | undefined;
38
+ }>;
29
39
  constructor(options: FormOptions<TDraft, TOriginal>);
30
- Provider({ children, original, defaultValue, validations, }: {
31
- children?: ReactNode;
32
- original?: TOriginal;
33
- } & Partial<FormOptions<TDraft, TOriginal>>): import("react/jsx-runtime").JSX.Element;
34
40
  useForm(): {
35
41
  original: TOriginal | undefined;
36
42
  draft: import("../../core").Store<TDraft>;
@@ -44,7 +50,10 @@ export declare class Form<TDraft, TOriginal extends TDraft = TDraft> {
44
50
  useField<TPath extends PathAsString<TDraft>>(path: TPath, useStoreOptions?: UseStoreOptions): Field<TDraft, TOriginal, TPath>;
45
51
  useHasChanges(): boolean;
46
52
  useIsValid(): boolean;
47
- Input<TPath extends PathAsString<TDraft>, TComponent extends FormInputComponent<any> = (props: ComponentPropsWithoutRef<'input'>) => JSX.Element>(props: FormInputProps<TDraft, TPath, TComponent>): JSX.Element;
53
+ Form({ original, defaultValue, validations, urlState, ...formProps }: {
54
+ original?: TOriginal;
55
+ } & Partial<FormOptions<TDraft, TOriginal>> & Omit<HTMLProps<HTMLFormElement>, 'defaultValue'>): import("react/jsx-runtime").JSX.Element;
56
+ Field<TPath extends PathAsString<TDraft>, TComponent extends FormFieldComponent<any> = (props: ComponentPropsWithoutRef<'input'>) => JSX.Element>(props: FormFieldProps<TDraft, TPath, TComponent>): JSX.Element;
48
57
  Error<TPath extends PathAsString<TDraft>>({ name }: FormErrorProps<TDraft, TPath>): any;
49
58
  }
50
59
  export declare function createForm<TDraft, TOriginal extends TDraft = TDraft>(options: FormOptions<TDraft, TOriginal>): Form<TDraft, TOriginal>;
@@ -0,0 +1,53 @@
1
+ import { type ComponentPropsWithoutRef, type ElementType, type HTMLProps } from 'react';
2
+ import { type Form } from './form';
3
+ import { type PathAsString } from '../../index';
4
+ import { type Value } from '../../lib/path';
5
+ export type FormFieldComponent<T> = ElementType<{
6
+ id: string;
7
+ value: T;
8
+ onChange: (event: {
9
+ target: {
10
+ value: T;
11
+ };
12
+ } | T | undefined, ...args: any[]) => void;
13
+ onFocus: (...args: any[]) => void;
14
+ onBlur: (...args: any[]) => void;
15
+ }>;
16
+ type FieldValue<T extends FormFieldComponent<any>> = ComponentPropsWithoutRef<T & 'input'> extends {
17
+ value: infer U;
18
+ } ? U : ComponentPropsWithoutRef<T & 'input'> extends {
19
+ value?: infer U;
20
+ } ? U | undefined : never;
21
+ type FieldChangeValue<T extends FormFieldComponent<any>> = ComponentPropsWithoutRef<T & 'input'> extends {
22
+ onChange?: (update: infer U) => void;
23
+ } ? U extends {
24
+ target: {
25
+ value: infer V;
26
+ };
27
+ } ? V : U : never;
28
+ export type FormFieldProps<TDraft, TPath extends PathAsString<TDraft>, TComponent extends FormFieldComponent<any>> = {
29
+ name: TPath;
30
+ commitOnBlur?: boolean;
31
+ commitDebounce?: number;
32
+ inputFilter?: (value: FieldChangeValue<TComponent>) => boolean;
33
+ onChange?: ComponentPropsWithoutRef<TComponent>['onChange'];
34
+ onBlur?: ComponentPropsWithoutRef<TComponent>['onBlur'];
35
+ } & (TComponent extends 'input' | ((props: HTMLProps<HTMLInputElement>) => JSX.Element) ? {
36
+ component?: TComponent;
37
+ } | {
38
+ children?: TComponent;
39
+ } : {
40
+ component: TComponent;
41
+ } | {
42
+ children: TComponent;
43
+ }) & Omit<ComponentPropsWithoutRef<TComponent>, 'form' | 'name' | 'component' | 'commitOnBlur' | 'commitDebounce' | 'value' | 'onChange' | 'onBlur' | 'children'> & (Value<TDraft, TPath> extends FieldValue<TComponent> ? {
44
+ serialize?: (value: Value<TDraft, TPath>) => FieldValue<TComponent>;
45
+ } : {
46
+ serialize: (value: Value<TDraft, TPath>) => FieldValue<TComponent>;
47
+ }) & (FieldChangeValue<TComponent> extends Value<TDraft, TPath> ? {
48
+ deserialize?: (value: FieldChangeValue<TComponent>) => Value<TDraft, TPath>;
49
+ } : {
50
+ deserialize: (value: FieldChangeValue<TComponent>) => Value<TDraft, TPath>;
51
+ });
52
+ export declare function FormField<TDraft, TPath extends PathAsString<TDraft>, TComponent extends FormFieldComponent<any>>(this: Form<TDraft, any>, { name, commitOnBlur, commitDebounce, inputFilter, serialize, deserialize, ...restProps }: FormFieldProps<TDraft, TPath, TComponent>): JSX.Element;
53
+ export {};
@@ -1,3 +1,3 @@
1
1
  export { type Field, Form, type FormOptions, type Validation, type Validations, createForm, } from './form';
2
2
  export { type FormErrorProps } from './formError';
3
- export { type FormInputComponent, type FormInputProps } from './formInput';
3
+ export { type FormFieldComponent, type FormFieldProps } from './formField';
@@ -6,3 +6,4 @@ export { useCache, type UseCacheArray, type UseCacheValue } from './useCache';
6
6
  export { useDecoupledState, type UseDecoupledStateOptions } from './useDecoupledState';
7
7
  export { useProp } from './useProp';
8
8
  export { useStore, type UseStoreOptions } from './useStore';
9
+ export { useUrlParamScope } from './useUrlParamScope';
@@ -4,6 +4,6 @@ export declare const reactMethods: {
4
4
  useStore<T>(this: Store<T>, options?: UseStoreOptions): T;
5
5
  useProp<T_1>(this: Store<T_1>, options?: UseStoreOptions): [value: T_1, setValue: {
6
6
  (update: import("../core/commonTypes").Update<T_1>): void;
7
- <P extends import("..").Path<T_1>>(path: P, update: import("../core/commonTypes").Update<import("..").Value<T_1, P>>): void;
7
+ <const P extends import("..").Path<T_1>>(path: P, update: import("../core/commonTypes").Update<import("..").Value<T_1, P>>): void;
8
8
  }];
9
9
  };
@@ -22,7 +22,7 @@ declare const scopeMethods: {
22
22
  useStore<T_1>(this: Scope<T_1>, options?: UseStoreOptions): T_1;
23
23
  useProp<T_2>(this: Scope<T_2>, options?: UseStoreOptions): [value: T_2, setValue: {
24
24
  (update: import("../core/commonTypes").Update<T_2>): void;
25
- <P extends import("..").Path<T_2>>(path: P, update: import("../core/commonTypes").Update<import("..").Value<T_2, P>>): void;
25
+ <const P extends import("..").Path<T_2>>(path: P, update: import("../core/commonTypes").Update<import("..").Value<T_2, P>>): void;
26
26
  }];
27
27
  Provider<T_3>(this: Scope<T_3>, props: Omit<ScopeProps<T_3>, "scope">): import("react/jsx-runtime").JSX.Element;
28
28
  };
@@ -1,4 +1,4 @@
1
- import type { ReactNode } from 'react';
1
+ import type { Context, ReactNode } from 'react';
2
2
  import { type UseStoreOptions } from './useStore';
3
3
  import type { Store } from '../core/store';
4
4
  import type { Scope } from '../core';
@@ -7,10 +7,15 @@ export type ScopeProps<T> = {
7
7
  store?: Store<T>;
8
8
  children?: ReactNode;
9
9
  };
10
+ declare module '../core' {
11
+ interface Scope<T> {
12
+ context?: Context<Store<T>>;
13
+ }
14
+ }
10
15
  export declare function ScopeProvider<T>({ scope, store: inputStore, children }: ScopeProps<T>): import("react/jsx-runtime").JSX.Element;
11
16
  export declare function useScope<T>(scope: Scope<T>): Store<T>;
12
17
  export declare function useScopeStore<T>(scope: Scope<T>, options?: UseStoreOptions): T;
13
18
  export declare function useScopeProp<T>(scope: Scope<T>, options?: UseStoreOptions): [value: T, setValue: {
14
19
  (update: import("../core/commonTypes").Update<T>): void;
15
- <P extends import("..").Path<T>>(path: P, update: import("../core/commonTypes").Update<import("..").Value<T, P>>): void;
20
+ <const P extends import("..").Path<T>>(path: P, update: import("../core/commonTypes").Update<import("..").Value<T, P>>): void;
16
21
  }];
@@ -0,0 +1,4 @@
1
+ export declare function useUrlParamScope({ key, type, }: {
2
+ key: string | string[];
3
+ type?: 'search' | 'hash';
4
+ }): void;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "cross-state",
3
- "version": "0.9.3",
3
+ "version": "0.10.0",
4
4
  "description": "(React) state library",
5
5
  "license": "ISC",
6
6
  "repository": "schummar/schummar-state",
@@ -110,34 +110,34 @@
110
110
  "@schummar/eslint-config": "github:schummar/eslint-config",
111
111
  "@schummar/prettier-config": "github:schummar/prettier-config",
112
112
  "@schummar/runp": "1.12.0",
113
- "@size-limit/preset-small-lib": "^8.2.4",
113
+ "@size-limit/preset-small-lib": "8.2.4",
114
114
  "@testing-library/react": "14.0.0",
115
- "@types/react": "18.2.11",
116
- "@types/react-dom": "18.2.4",
115
+ "@types/react": "18.2.12",
116
+ "@types/react-dom": "18.2.5",
117
117
  "@types/seedrandom": "3.0.5",
118
118
  "@types/use-sync-external-store": "0.0.3",
119
- "@types/ws": "^8.5.5",
119
+ "@types/ws": "8.5.5",
120
120
  "@vitejs/plugin-react": "4.0.0",
121
- "@vitest/coverage-v8": "^0.32.0",
121
+ "@vitest/coverage-v8": "0.32.0",
122
+ "esbuild": "0.18.2",
122
123
  "eslint": "8.42.0",
123
124
  "happy-dom": "9.20.3",
124
125
  "immer": "10.0.2",
125
126
  "jsdom": "22.1.0",
126
127
  "prettier": "2.8.8",
127
- "publint": "^0.1.12",
128
+ "publint": "0.1.12",
128
129
  "react": "18.2.0",
129
130
  "react-dom": "18.2.0",
130
131
  "rimraf": "5.0.1",
131
132
  "seedrandom": "3.0.5",
132
133
  "semantic-release": "21.0.5",
133
- "size-limit": "^8.2.4",
134
+ "size-limit": "8.2.4",
134
135
  "tsc-alias": "1.8.6",
135
136
  "typescript": "5.1.3",
136
137
  "use-sync-external-store": "1.2.0",
137
138
  "vite": "4.3.9",
138
139
  "vite-tsconfig-paths": "4.2.0",
139
- "vitest": "0.32.0",
140
- "ws": "^8.13.0"
140
+ "vitest": "0.32.0"
141
141
  },
142
142
  "volta": {
143
143
  "node": "18.16.0",
@@ -1,48 +0,0 @@
1
- import { type ComponentPropsWithoutRef, type ElementType, type HTMLProps } from 'react';
2
- import { type Form } from './form';
3
- import { type PathAsString } from '../../index';
4
- import { type Value } from '../../lib/path';
5
- export type FormInputComponent<T> = ElementType<{
6
- id: string;
7
- value: T;
8
- onChange: (event: {
9
- target: {
10
- value: T;
11
- };
12
- } | T | undefined, ...args: any[]) => void;
13
- onBlur: (...args: any[]) => void;
14
- }>;
15
- type InputValue<T extends FormInputComponent<any>> = ComponentPropsWithoutRef<T> extends {
16
- value: infer U;
17
- } ? U : ComponentPropsWithoutRef<T> extends {
18
- value?: infer U;
19
- } ? U | undefined : never;
20
- type InputChangeValue<T extends FormInputComponent<any>> = ComponentPropsWithoutRef<T> extends {
21
- onChange?: (update: infer U) => void;
22
- } ? U extends {
23
- target: {
24
- value: infer V;
25
- };
26
- } ? V : U : never;
27
- export type FormInputProps<TDraft, TPath extends PathAsString<TDraft>, TComponent extends FormInputComponent<any>> = {
28
- name: TPath;
29
- commitOnBlur?: boolean;
30
- commitDebounce?: number;
31
- inputFilter?: (value: InputChangeValue<TComponent>) => boolean;
32
- onChange?: ComponentPropsWithoutRef<TComponent>['onChange'];
33
- onBlur?: ComponentPropsWithoutRef<TComponent>['onBlur'];
34
- } & (TComponent extends 'input' | ((props: HTMLProps<HTMLInputElement>) => JSX.Element) ? {
35
- component?: TComponent;
36
- } : {
37
- component: TComponent;
38
- }) & Omit<ComponentPropsWithoutRef<TComponent>, 'form' | 'name' | 'component' | 'commitOnBlur' | 'commitDebounce' | 'value' | 'onChange' | 'onBlur'> & (Value<TDraft, TPath> extends InputValue<TComponent> ? {
39
- serialize?: (value: Value<TDraft, TPath>) => InputValue<TComponent>;
40
- } : {
41
- serialize: (value: Value<TDraft, TPath>) => InputValue<TComponent>;
42
- }) & (InputChangeValue<TComponent> extends Value<TDraft, TPath> ? {
43
- deserialize?: (value: InputChangeValue<TComponent>) => Value<TDraft, TPath>;
44
- } : {
45
- deserialize: (value: InputChangeValue<TComponent>) => Value<TDraft, TPath>;
46
- });
47
- export declare function FormInput<TDraft, TPath extends PathAsString<TDraft>, TComponent extends FormInputComponent<any>>(this: Form<TDraft, any>, { id, name, component, commitOnBlur, commitDebounce, inputFilter, serialize, deserialize, ...restProps }: FormInputProps<TDraft, TPath, TComponent>): JSX.Element;
48
- export {};