@tanstack/form-core 0.3.4 → 0.3.6
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/build/legacy/FieldApi.cjs.map +1 -1
- package/build/legacy/FieldApi.d.cts +1 -1
- package/build/legacy/FieldApi.d.ts +1 -1
- package/build/legacy/FieldApi.js.map +1 -1
- package/build/legacy/FormApi.cjs.map +1 -1
- package/build/legacy/FormApi.js.map +1 -1
- package/build/legacy/index.d.cts +27 -36
- package/build/legacy/index.d.ts +27 -36
- package/build/legacy/utils.cjs.map +1 -1
- package/build/legacy/utils.d.cts +2 -2
- package/build/legacy/utils.d.ts +2 -2
- package/build/legacy/utils.js.map +1 -1
- package/build/modern/FieldApi.cjs.map +1 -1
- package/build/modern/FieldApi.d.cts +1 -1
- package/build/modern/FieldApi.d.ts +1 -1
- package/build/modern/FieldApi.js.map +1 -1
- package/build/modern/FormApi.cjs.map +1 -1
- package/build/modern/FormApi.js.map +1 -1
- package/build/modern/index.d.cts +27 -36
- package/build/modern/index.d.ts +27 -36
- package/build/modern/utils.cjs.map +1 -1
- package/build/modern/utils.d.cts +2 -2
- package/build/modern/utils.d.ts +2 -2
- package/build/modern/utils.js.map +1 -1
- package/package.json +1 -1
- package/src/FieldApi.ts +45 -62
- package/src/FormApi.ts +7 -5
- package/src/utils.ts +13 -7
package/build/modern/index.d.cts
CHANGED
|
@@ -19,7 +19,7 @@ type FormOptions<TData> = {
|
|
|
19
19
|
onSubmitInvalid?: (values: TData, formApi: FormApi<TData>) => void;
|
|
20
20
|
};
|
|
21
21
|
type FieldInfo<TFormData> = {
|
|
22
|
-
instances: Record<string, FieldApi<any,
|
|
22
|
+
instances: Record<string, FieldApi<TFormData, any, any>>;
|
|
23
23
|
} & ValidationMeta;
|
|
24
24
|
type ValidationMeta = {
|
|
25
25
|
validationCount?: number;
|
|
@@ -64,7 +64,7 @@ declare class FormApi<TFormData> {
|
|
|
64
64
|
handleSubmit: () => Promise<void>;
|
|
65
65
|
getFieldValue: <TField extends DeepKeys<TFormData>>(field: TField) => DeepValue<TFormData, TField>;
|
|
66
66
|
getFieldMeta: <TField extends DeepKeys<TFormData>>(field: TField) => FieldMeta | undefined;
|
|
67
|
-
getFieldInfo: <TField extends DeepKeys<TFormData>>(field: TField) =>
|
|
67
|
+
getFieldInfo: <TField extends DeepKeys<TFormData>>(field: TField) => FieldInfo<TFormData>;
|
|
68
68
|
setFieldMeta: <TField extends DeepKeys<TFormData>>(field: TField, updater: Updater<FieldMeta>) => void;
|
|
69
69
|
setFieldValue: <TField extends DeepKeys<TFormData>>(field: TField, updater: Updater<DeepValue<TFormData, TField>>, opts?: {
|
|
70
70
|
touch?: boolean;
|
|
@@ -82,44 +82,35 @@ declare class FormApi<TFormData> {
|
|
|
82
82
|
}
|
|
83
83
|
|
|
84
84
|
type ValidationCause = 'change' | 'blur' | 'submit' | 'mount';
|
|
85
|
-
type ValidateFn<
|
|
86
|
-
type ValidateAsyncFn<
|
|
87
|
-
interface FieldOptions<
|
|
85
|
+
type ValidateFn<TParentData, TName extends DeepKeys<TParentData>, TData> = (value: TData, fieldApi: FieldApi<TParentData, TName>) => ValidationError;
|
|
86
|
+
type ValidateAsyncFn<TParentData, TName extends DeepKeys<TParentData>, TData> = (value: TData, fieldApi: FieldApi<TParentData, TName>) => ValidationError | Promise<ValidationError>;
|
|
87
|
+
interface FieldOptions<TParentData,
|
|
88
88
|
/**
|
|
89
89
|
* This allows us to restrict the name to only be a valid field name while
|
|
90
90
|
* also assigning it to a generic
|
|
91
91
|
*/
|
|
92
|
-
TName
|
|
92
|
+
TName extends DeepKeys<TParentData>,
|
|
93
93
|
/**
|
|
94
94
|
* If TData is unknown, we can use the TName generic to determine the type
|
|
95
95
|
*/
|
|
96
|
-
TData =
|
|
97
|
-
name:
|
|
96
|
+
TData = DeepValue<TParentData, TName>> {
|
|
97
|
+
name: DeepKeys<TParentData>;
|
|
98
98
|
index?: TData extends any[] ? number : never;
|
|
99
99
|
defaultValue?: TData;
|
|
100
100
|
asyncDebounceMs?: number;
|
|
101
101
|
asyncAlways?: boolean;
|
|
102
|
-
onMount?: (formApi: FieldApi<
|
|
103
|
-
onChange?: ValidateFn<
|
|
104
|
-
onChangeAsync?: ValidateAsyncFn<
|
|
102
|
+
onMount?: (formApi: FieldApi<TParentData, TName>) => void;
|
|
103
|
+
onChange?: ValidateFn<TParentData, TName, TData>;
|
|
104
|
+
onChangeAsync?: ValidateAsyncFn<TParentData, TName, TData>;
|
|
105
105
|
onChangeAsyncDebounceMs?: number;
|
|
106
|
-
onBlur?: ValidateFn<
|
|
107
|
-
onBlurAsync?: ValidateAsyncFn<
|
|
106
|
+
onBlur?: ValidateFn<TParentData, TName, TData>;
|
|
107
|
+
onBlurAsync?: ValidateAsyncFn<TParentData, TName, TData>;
|
|
108
108
|
onBlurAsyncDebounceMs?: number;
|
|
109
|
-
onSubmitAsync?: ValidateAsyncFn<
|
|
109
|
+
onSubmitAsync?: ValidateAsyncFn<TParentData, TName, TData>;
|
|
110
110
|
defaultMeta?: Partial<FieldMeta>;
|
|
111
111
|
}
|
|
112
|
-
interface FieldApiOptions<
|
|
113
|
-
|
|
114
|
-
* This allows us to restrict the name to only be a valid field name while
|
|
115
|
-
* also assigning it to a generic
|
|
116
|
-
*/
|
|
117
|
-
TName = unknown extends TFormData ? string : DeepKeys<TFormData>,
|
|
118
|
-
/**
|
|
119
|
-
* If TData is unknown, we can use the TName generic to determine the type
|
|
120
|
-
*/
|
|
121
|
-
TData = unknown extends _TData ? DeepValue<TFormData, TName> : _TData> extends FieldOptions<_TData, TFormData, TName, TData> {
|
|
122
|
-
form: FormApi<TFormData>;
|
|
112
|
+
interface FieldApiOptions<TParentData, TName extends DeepKeys<TParentData>, TData = DeepValue<TParentData, TName>> extends FieldOptions<TParentData, TName, TData> {
|
|
113
|
+
form: FormApi<TParentData>;
|
|
123
114
|
}
|
|
124
115
|
type FieldMeta = {
|
|
125
116
|
isTouched: boolean;
|
|
@@ -132,21 +123,21 @@ type FieldState<TData> = {
|
|
|
132
123
|
value: TData;
|
|
133
124
|
meta: FieldMeta;
|
|
134
125
|
};
|
|
135
|
-
type
|
|
136
|
-
declare class FieldApi<
|
|
126
|
+
type ResolveName<TParentData> = unknown extends TParentData ? string : DeepKeys<TParentData>;
|
|
127
|
+
declare class FieldApi<TParentData, TName extends DeepKeys<TParentData>, TData = DeepValue<TParentData, TName>> {
|
|
137
128
|
#private;
|
|
138
129
|
uid: number;
|
|
139
|
-
form:
|
|
140
|
-
name: DeepKeys<
|
|
141
|
-
options:
|
|
130
|
+
form: FieldApiOptions<TParentData, TName, TData>['form'];
|
|
131
|
+
name: DeepKeys<TParentData>;
|
|
132
|
+
options: FieldApiOptions<TParentData, TName>;
|
|
142
133
|
store: Store<FieldState<TData>>;
|
|
143
134
|
state: FieldState<TData>;
|
|
144
135
|
prevState: FieldState<TData>;
|
|
145
|
-
constructor(opts:
|
|
146
|
-
form: FormApi<
|
|
136
|
+
constructor(opts: FieldApiOptions<TParentData, TName, TData> & {
|
|
137
|
+
form: FormApi<TParentData>;
|
|
147
138
|
});
|
|
148
139
|
mount: () => () => void;
|
|
149
|
-
update: (opts: FieldApiOptions<
|
|
140
|
+
update: (opts: FieldApiOptions<TParentData, TName, TData>) => void;
|
|
150
141
|
getValue: () => TData;
|
|
151
142
|
setValue: (updater: Updater<TData>, options?: {
|
|
152
143
|
touch?: boolean;
|
|
@@ -155,12 +146,12 @@ declare class FieldApi<_TData, TFormData, Opts extends FieldApiOptions<_TData, T
|
|
|
155
146
|
_getMeta: () => FieldMeta | undefined;
|
|
156
147
|
getMeta: () => FieldMeta;
|
|
157
148
|
setMeta: (updater: Updater<FieldMeta>) => void;
|
|
158
|
-
getInfo: () =>
|
|
149
|
+
getInfo: () => FieldInfo<TParentData>;
|
|
159
150
|
pushValue: (value: TData extends any[] ? TData[number] : never) => void;
|
|
160
151
|
insertValue: (index: number, value: TData extends any[] ? TData[number] : never) => void;
|
|
161
152
|
removeValue: (index: number) => void;
|
|
162
153
|
swapValues: (aIndex: number, bIndex: number) => void;
|
|
163
|
-
getSubField: <
|
|
154
|
+
getSubField: <TSubName extends DeepKeys<TData>, TSubData = DeepValue<TData, TSubName>>(name: TSubName) => FieldApi<TData, TSubName, TSubData>;
|
|
164
155
|
validateSync: (value: TData | undefined, cause: ValidationCause) => void;
|
|
165
156
|
cancelValidateAsync: () => void;
|
|
166
157
|
validateAsync: (value: TData | undefined, cause: ValidationCause) => Promise<ValidationError[]>;
|
|
@@ -169,4 +160,4 @@ declare class FieldApi<_TData, TFormData, Opts extends FieldApiOptions<_TData, T
|
|
|
169
160
|
handleBlur: () => void;
|
|
170
161
|
}
|
|
171
162
|
|
|
172
|
-
export { DeepKeys, DeepValue, FieldApi, FieldApiOptions, FieldInfo, FieldMeta, FieldOptions, FieldState, FormApi, FormOptions, FormState, Updater, ValidationCause, ValidationError, ValidationErrorMap, ValidationErrorMapKeys, ValidationMeta };
|
|
163
|
+
export { DeepKeys, DeepValue, FieldApi, FieldApiOptions, FieldInfo, FieldMeta, FieldOptions, FieldState, FormApi, FormOptions, FormState, ResolveName, Updater, ValidationCause, ValidationError, ValidationErrorMap, ValidationErrorMapKeys, ValidationMeta };
|
package/build/modern/index.d.ts
CHANGED
|
@@ -19,7 +19,7 @@ type FormOptions<TData> = {
|
|
|
19
19
|
onSubmitInvalid?: (values: TData, formApi: FormApi<TData>) => void;
|
|
20
20
|
};
|
|
21
21
|
type FieldInfo<TFormData> = {
|
|
22
|
-
instances: Record<string, FieldApi<any,
|
|
22
|
+
instances: Record<string, FieldApi<TFormData, any, any>>;
|
|
23
23
|
} & ValidationMeta;
|
|
24
24
|
type ValidationMeta = {
|
|
25
25
|
validationCount?: number;
|
|
@@ -64,7 +64,7 @@ declare class FormApi<TFormData> {
|
|
|
64
64
|
handleSubmit: () => Promise<void>;
|
|
65
65
|
getFieldValue: <TField extends DeepKeys<TFormData>>(field: TField) => DeepValue<TFormData, TField>;
|
|
66
66
|
getFieldMeta: <TField extends DeepKeys<TFormData>>(field: TField) => FieldMeta | undefined;
|
|
67
|
-
getFieldInfo: <TField extends DeepKeys<TFormData>>(field: TField) =>
|
|
67
|
+
getFieldInfo: <TField extends DeepKeys<TFormData>>(field: TField) => FieldInfo<TFormData>;
|
|
68
68
|
setFieldMeta: <TField extends DeepKeys<TFormData>>(field: TField, updater: Updater<FieldMeta>) => void;
|
|
69
69
|
setFieldValue: <TField extends DeepKeys<TFormData>>(field: TField, updater: Updater<DeepValue<TFormData, TField>>, opts?: {
|
|
70
70
|
touch?: boolean;
|
|
@@ -82,44 +82,35 @@ declare class FormApi<TFormData> {
|
|
|
82
82
|
}
|
|
83
83
|
|
|
84
84
|
type ValidationCause = 'change' | 'blur' | 'submit' | 'mount';
|
|
85
|
-
type ValidateFn<
|
|
86
|
-
type ValidateAsyncFn<
|
|
87
|
-
interface FieldOptions<
|
|
85
|
+
type ValidateFn<TParentData, TName extends DeepKeys<TParentData>, TData> = (value: TData, fieldApi: FieldApi<TParentData, TName>) => ValidationError;
|
|
86
|
+
type ValidateAsyncFn<TParentData, TName extends DeepKeys<TParentData>, TData> = (value: TData, fieldApi: FieldApi<TParentData, TName>) => ValidationError | Promise<ValidationError>;
|
|
87
|
+
interface FieldOptions<TParentData,
|
|
88
88
|
/**
|
|
89
89
|
* This allows us to restrict the name to only be a valid field name while
|
|
90
90
|
* also assigning it to a generic
|
|
91
91
|
*/
|
|
92
|
-
TName
|
|
92
|
+
TName extends DeepKeys<TParentData>,
|
|
93
93
|
/**
|
|
94
94
|
* If TData is unknown, we can use the TName generic to determine the type
|
|
95
95
|
*/
|
|
96
|
-
TData =
|
|
97
|
-
name:
|
|
96
|
+
TData = DeepValue<TParentData, TName>> {
|
|
97
|
+
name: DeepKeys<TParentData>;
|
|
98
98
|
index?: TData extends any[] ? number : never;
|
|
99
99
|
defaultValue?: TData;
|
|
100
100
|
asyncDebounceMs?: number;
|
|
101
101
|
asyncAlways?: boolean;
|
|
102
|
-
onMount?: (formApi: FieldApi<
|
|
103
|
-
onChange?: ValidateFn<
|
|
104
|
-
onChangeAsync?: ValidateAsyncFn<
|
|
102
|
+
onMount?: (formApi: FieldApi<TParentData, TName>) => void;
|
|
103
|
+
onChange?: ValidateFn<TParentData, TName, TData>;
|
|
104
|
+
onChangeAsync?: ValidateAsyncFn<TParentData, TName, TData>;
|
|
105
105
|
onChangeAsyncDebounceMs?: number;
|
|
106
|
-
onBlur?: ValidateFn<
|
|
107
|
-
onBlurAsync?: ValidateAsyncFn<
|
|
106
|
+
onBlur?: ValidateFn<TParentData, TName, TData>;
|
|
107
|
+
onBlurAsync?: ValidateAsyncFn<TParentData, TName, TData>;
|
|
108
108
|
onBlurAsyncDebounceMs?: number;
|
|
109
|
-
onSubmitAsync?: ValidateAsyncFn<
|
|
109
|
+
onSubmitAsync?: ValidateAsyncFn<TParentData, TName, TData>;
|
|
110
110
|
defaultMeta?: Partial<FieldMeta>;
|
|
111
111
|
}
|
|
112
|
-
interface FieldApiOptions<
|
|
113
|
-
|
|
114
|
-
* This allows us to restrict the name to only be a valid field name while
|
|
115
|
-
* also assigning it to a generic
|
|
116
|
-
*/
|
|
117
|
-
TName = unknown extends TFormData ? string : DeepKeys<TFormData>,
|
|
118
|
-
/**
|
|
119
|
-
* If TData is unknown, we can use the TName generic to determine the type
|
|
120
|
-
*/
|
|
121
|
-
TData = unknown extends _TData ? DeepValue<TFormData, TName> : _TData> extends FieldOptions<_TData, TFormData, TName, TData> {
|
|
122
|
-
form: FormApi<TFormData>;
|
|
112
|
+
interface FieldApiOptions<TParentData, TName extends DeepKeys<TParentData>, TData = DeepValue<TParentData, TName>> extends FieldOptions<TParentData, TName, TData> {
|
|
113
|
+
form: FormApi<TParentData>;
|
|
123
114
|
}
|
|
124
115
|
type FieldMeta = {
|
|
125
116
|
isTouched: boolean;
|
|
@@ -132,21 +123,21 @@ type FieldState<TData> = {
|
|
|
132
123
|
value: TData;
|
|
133
124
|
meta: FieldMeta;
|
|
134
125
|
};
|
|
135
|
-
type
|
|
136
|
-
declare class FieldApi<
|
|
126
|
+
type ResolveName<TParentData> = unknown extends TParentData ? string : DeepKeys<TParentData>;
|
|
127
|
+
declare class FieldApi<TParentData, TName extends DeepKeys<TParentData>, TData = DeepValue<TParentData, TName>> {
|
|
137
128
|
#private;
|
|
138
129
|
uid: number;
|
|
139
|
-
form:
|
|
140
|
-
name: DeepKeys<
|
|
141
|
-
options:
|
|
130
|
+
form: FieldApiOptions<TParentData, TName, TData>['form'];
|
|
131
|
+
name: DeepKeys<TParentData>;
|
|
132
|
+
options: FieldApiOptions<TParentData, TName>;
|
|
142
133
|
store: Store<FieldState<TData>>;
|
|
143
134
|
state: FieldState<TData>;
|
|
144
135
|
prevState: FieldState<TData>;
|
|
145
|
-
constructor(opts:
|
|
146
|
-
form: FormApi<
|
|
136
|
+
constructor(opts: FieldApiOptions<TParentData, TName, TData> & {
|
|
137
|
+
form: FormApi<TParentData>;
|
|
147
138
|
});
|
|
148
139
|
mount: () => () => void;
|
|
149
|
-
update: (opts: FieldApiOptions<
|
|
140
|
+
update: (opts: FieldApiOptions<TParentData, TName, TData>) => void;
|
|
150
141
|
getValue: () => TData;
|
|
151
142
|
setValue: (updater: Updater<TData>, options?: {
|
|
152
143
|
touch?: boolean;
|
|
@@ -155,12 +146,12 @@ declare class FieldApi<_TData, TFormData, Opts extends FieldApiOptions<_TData, T
|
|
|
155
146
|
_getMeta: () => FieldMeta | undefined;
|
|
156
147
|
getMeta: () => FieldMeta;
|
|
157
148
|
setMeta: (updater: Updater<FieldMeta>) => void;
|
|
158
|
-
getInfo: () =>
|
|
149
|
+
getInfo: () => FieldInfo<TParentData>;
|
|
159
150
|
pushValue: (value: TData extends any[] ? TData[number] : never) => void;
|
|
160
151
|
insertValue: (index: number, value: TData extends any[] ? TData[number] : never) => void;
|
|
161
152
|
removeValue: (index: number) => void;
|
|
162
153
|
swapValues: (aIndex: number, bIndex: number) => void;
|
|
163
|
-
getSubField: <
|
|
154
|
+
getSubField: <TSubName extends DeepKeys<TData>, TSubData = DeepValue<TData, TSubName>>(name: TSubName) => FieldApi<TData, TSubName, TSubData>;
|
|
164
155
|
validateSync: (value: TData | undefined, cause: ValidationCause) => void;
|
|
165
156
|
cancelValidateAsync: () => void;
|
|
166
157
|
validateAsync: (value: TData | undefined, cause: ValidationCause) => Promise<ValidationError[]>;
|
|
@@ -169,4 +160,4 @@ declare class FieldApi<_TData, TFormData, Opts extends FieldApiOptions<_TData, T
|
|
|
169
160
|
handleBlur: () => void;
|
|
170
161
|
}
|
|
171
162
|
|
|
172
|
-
export { DeepKeys, DeepValue, FieldApi, FieldApiOptions, FieldInfo, FieldMeta, FieldOptions, FieldState, FormApi, FormOptions, FormState, Updater, ValidationCause, ValidationError, ValidationErrorMap, ValidationErrorMapKeys, ValidationMeta };
|
|
163
|
+
export { DeepKeys, DeepValue, FieldApi, FieldApiOptions, FieldInfo, FieldMeta, FieldOptions, FieldState, FormApi, FormOptions, FormState, ResolveName, Updater, ValidationCause, ValidationError, ValidationErrorMap, ValidationErrorMapKeys, ValidationMeta };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/utils.ts"],"sourcesContent":["export type UpdaterFn<TInput, TOutput = TInput> = (input: TInput) => TOutput\n\nexport type Updater<TInput, TOutput = TInput> =\n | TOutput\n | UpdaterFn<TInput, TOutput>\n\nexport function functionalUpdate<TInput, TOutput = TInput>(\n updater: Updater<TInput, TOutput>,\n input: TInput,\n): TOutput {\n return typeof updater === 'function'\n ? (updater as UpdaterFn<TInput, TOutput>)(input)\n : updater\n}\n\n/**\n * Get a value from an object using a path, including dot notation.\n */\nexport function getBy(obj: any, path: any) {\n const pathArray = makePathArray(path)\n const pathObj = pathArray\n return pathObj.reduce((current: any, pathPart: any) => {\n if (typeof current !== 'undefined') {\n return current[pathPart]\n }\n return undefined\n }, obj)\n}\n\n/**\n * Set a value on an object using a path, including dot notation.\n */\nexport function setBy(obj: any, _path: any, updater: Updater<any>) {\n const path = makePathArray(_path)\n\n function doSet(parent?: any): any {\n if (!path.length) {\n return functionalUpdate(updater, parent)\n }\n\n const key = path.shift()\n\n if (typeof key === 'string') {\n if (typeof parent === 'object') {\n return {\n ...parent,\n [key]: doSet(parent[key]),\n }\n }\n return {\n [key]: doSet(),\n }\n }\n\n if (typeof key === 'number') {\n if (Array.isArray(parent)) {\n const prefix = parent.slice(0, key)\n return [\n ...(prefix.length ? prefix : new Array(key)),\n doSet(parent[key]),\n ...parent.slice(key + 1),\n ]\n }\n return [...new Array(key), doSet()]\n }\n\n throw new Error('Uh oh!')\n }\n\n return doSet(obj)\n}\n\nconst reFindNumbers0 = /^(\\d*)$/gm\nconst reFindNumbers1 = /\\.(\\d*)\\./gm\nconst reFindNumbers2 = /^(\\d*)\\./gm\nconst reFindNumbers3 = /\\.(\\d*$)/gm\nconst reFindMultiplePeriods = /\\.{2,}/gm\n\nconst intPrefix = '__int__'\nconst intReplace = `${intPrefix}$1`\n\nfunction makePathArray(str: string) {\n if (typeof str !== 'string') {\n throw new Error('Path must be a string.')\n }\n\n return str\n .replace('[', '.')\n .replace(']', '')\n .replace(reFindNumbers0, intReplace)\n .replace(reFindNumbers1, `.${intReplace}.`)\n .replace(reFindNumbers2, `${intReplace}.`)\n .replace(reFindNumbers3, `.${intReplace}`)\n .replace(reFindMultiplePeriods, '.')\n .split('.')\n .map((d) => {\n if (d.indexOf(intPrefix) === 0) {\n return parseInt(d.substring(intPrefix.length), 10)\n }\n return d\n })\n}\n\nexport function isNonEmptyArray(obj: any) {\n return !(Array.isArray(obj) && obj.length === 0)\n}\n\nexport type RequiredByKey<T, K extends keyof T> = Omit<T, K> &\n Required<Pick<T, K>>\n\ntype ComputeRange<\n N extends number,\n Result extends Array<unknown> = [],\n> = Result['length'] extends N\n ? Result\n : ComputeRange<N, [...Result, Result['length']]>\ntype Index40 = ComputeRange<40>[number]\n\n// Is this type a tuple?\ntype IsTuple<T> = T extends readonly any[] & { length: infer Length }\n ? Length extends Index40\n ? T\n : never\n : never\n\n// If this type is a tuple, what indices are allowed?\ntype AllowedIndexes<\n Tuple extends ReadonlyArray<any>,\n Keys extends number = never,\n> = Tuple extends readonly []\n ? Keys\n : Tuple extends readonly [infer _, ...infer Tail]\n ? AllowedIndexes<Tail, Keys | Tail['length']>\n : Keys\n\nexport type DeepKeys<T> =
|
|
1
|
+
{"version":3,"sources":["../../src/utils.ts"],"sourcesContent":["export type UpdaterFn<TInput, TOutput = TInput> = (input: TInput) => TOutput\n\nexport type Updater<TInput, TOutput = TInput> =\n | TOutput\n | UpdaterFn<TInput, TOutput>\n\nexport function functionalUpdate<TInput, TOutput = TInput>(\n updater: Updater<TInput, TOutput>,\n input: TInput,\n): TOutput {\n return typeof updater === 'function'\n ? (updater as UpdaterFn<TInput, TOutput>)(input)\n : updater\n}\n\n/**\n * Get a value from an object using a path, including dot notation.\n */\nexport function getBy(obj: any, path: any) {\n const pathArray = makePathArray(path)\n const pathObj = pathArray\n return pathObj.reduce((current: any, pathPart: any) => {\n if (typeof current !== 'undefined') {\n return current[pathPart]\n }\n return undefined\n }, obj)\n}\n\n/**\n * Set a value on an object using a path, including dot notation.\n */\nexport function setBy(obj: any, _path: any, updater: Updater<any>) {\n const path = makePathArray(_path)\n\n function doSet(parent?: any): any {\n if (!path.length) {\n return functionalUpdate(updater, parent)\n }\n\n const key = path.shift()\n\n if (typeof key === 'string') {\n if (typeof parent === 'object') {\n return {\n ...parent,\n [key]: doSet(parent[key]),\n }\n }\n return {\n [key]: doSet(),\n }\n }\n\n if (typeof key === 'number') {\n if (Array.isArray(parent)) {\n const prefix = parent.slice(0, key)\n return [\n ...(prefix.length ? prefix : new Array(key)),\n doSet(parent[key]),\n ...parent.slice(key + 1),\n ]\n }\n return [...new Array(key), doSet()]\n }\n\n throw new Error('Uh oh!')\n }\n\n return doSet(obj)\n}\n\nconst reFindNumbers0 = /^(\\d*)$/gm\nconst reFindNumbers1 = /\\.(\\d*)\\./gm\nconst reFindNumbers2 = /^(\\d*)\\./gm\nconst reFindNumbers3 = /\\.(\\d*$)/gm\nconst reFindMultiplePeriods = /\\.{2,}/gm\n\nconst intPrefix = '__int__'\nconst intReplace = `${intPrefix}$1`\n\nfunction makePathArray(str: string) {\n if (typeof str !== 'string') {\n throw new Error('Path must be a string.')\n }\n\n return str\n .replace('[', '.')\n .replace(']', '')\n .replace(reFindNumbers0, intReplace)\n .replace(reFindNumbers1, `.${intReplace}.`)\n .replace(reFindNumbers2, `${intReplace}.`)\n .replace(reFindNumbers3, `.${intReplace}`)\n .replace(reFindMultiplePeriods, '.')\n .split('.')\n .map((d) => {\n if (d.indexOf(intPrefix) === 0) {\n return parseInt(d.substring(intPrefix.length), 10)\n }\n return d\n })\n}\n\nexport function isNonEmptyArray(obj: any) {\n return !(Array.isArray(obj) && obj.length === 0)\n}\n\nexport type RequiredByKey<T, K extends keyof T> = Omit<T, K> &\n Required<Pick<T, K>>\n\ntype ComputeRange<\n N extends number,\n Result extends Array<unknown> = [],\n> = Result['length'] extends N\n ? Result\n : ComputeRange<N, [...Result, Result['length']]>\ntype Index40 = ComputeRange<40>[number]\n\n// Is this type a tuple?\ntype IsTuple<T> = T extends readonly any[] & { length: infer Length }\n ? Length extends Index40\n ? T\n : never\n : never\n\n// If this type is a tuple, what indices are allowed?\ntype AllowedIndexes<\n Tuple extends ReadonlyArray<any>,\n Keys extends number = never,\n> = Tuple extends readonly []\n ? Keys\n : Tuple extends readonly [infer _, ...infer Tail]\n ? AllowedIndexes<Tail, Keys | Tail['length']>\n : Keys\n\nexport type DeepKeys<T, TDepth extends any[] = []> = TDepth['length'] extends 5\n ? never\n : unknown extends T\n ? string\n : object extends T\n ? string\n : T extends readonly any[] & IsTuple<T>\n ? AllowedIndexes<T> | DeepKeysPrefix<T, AllowedIndexes<T>, TDepth>\n : T extends any[]\n ? DeepKeys<T[number], [...TDepth, any]>\n : T extends Date\n ? never\n : T extends object\n ? (keyof T & string) | DeepKeysPrefix<T, keyof T, TDepth>\n : never\n\ntype DeepKeysPrefix<\n T,\n TPrefix,\n TDepth extends any[],\n> = TPrefix extends keyof T & (number | string)\n ? `${TPrefix}.${DeepKeys<T[TPrefix], [...TDepth, any]> & string}`\n : never\n\nexport type DeepValue<T, TProp> = T extends Record<string | number, any>\n ? TProp extends `${infer TBranch}.${infer TDeepProp}`\n ? DeepValue<T[TBranch], TDeepProp>\n : T[TProp & string]\n : never\n\ntype Narrowable = string | number | bigint | boolean\n\ntype NarrowRaw<A> =\n | (A extends [] ? [] : never)\n | (A extends Narrowable ? A : never)\n | {\n [K in keyof A]: A[K] extends Function ? A[K] : NarrowRaw<A[K]>\n }\n\nexport type Narrow<A> = Try<A, [], NarrowRaw<A>>\n\ntype Try<A1, A2, Catch = never> = A1 extends A2 ? A1 : Catch\n\n// Hack to get TypeScript to show simplified types in error messages\nexport type Pretty<T> = { [K in keyof T]: T[K] } & {}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAMO,SAAS,iBACd,SACA,OACS;AACT,SAAO,OAAO,YAAY,aACrB,QAAuC,KAAK,IAC7C;AACN;AAKO,SAAS,MAAM,KAAU,MAAW;AACzC,QAAM,YAAY,cAAc,IAAI;AACpC,QAAM,UAAU;AAChB,SAAO,QAAQ,OAAO,CAAC,SAAc,aAAkB;AACrD,QAAI,OAAO,YAAY,aAAa;AAClC,aAAO,QAAQ,QAAQ;AAAA,IACzB;AACA,WAAO;AAAA,EACT,GAAG,GAAG;AACR;AAKO,SAAS,MAAM,KAAU,OAAY,SAAuB;AACjE,QAAM,OAAO,cAAc,KAAK;AAEhC,WAAS,MAAM,QAAmB;AAChC,QAAI,CAAC,KAAK,QAAQ;AAChB,aAAO,iBAAiB,SAAS,MAAM;AAAA,IACzC;AAEA,UAAM,MAAM,KAAK,MAAM;AAEvB,QAAI,OAAO,QAAQ,UAAU;AAC3B,UAAI,OAAO,WAAW,UAAU;AAC9B,eAAO;AAAA,UACL,GAAG;AAAA,UACH,CAAC,GAAG,GAAG,MAAM,OAAO,GAAG,CAAC;AAAA,QAC1B;AAAA,MACF;AACA,aAAO;AAAA,QACL,CAAC,GAAG,GAAG,MAAM;AAAA,MACf;AAAA,IACF;AAEA,QAAI,OAAO,QAAQ,UAAU;AAC3B,UAAI,MAAM,QAAQ,MAAM,GAAG;AACzB,cAAM,SAAS,OAAO,MAAM,GAAG,GAAG;AAClC,eAAO;AAAA,UACL,GAAI,OAAO,SAAS,SAAS,IAAI,MAAM,GAAG;AAAA,UAC1C,MAAM,OAAO,GAAG,CAAC;AAAA,UACjB,GAAG,OAAO,MAAM,MAAM,CAAC;AAAA,QACzB;AAAA,MACF;AACA,aAAO,CAAC,GAAG,IAAI,MAAM,GAAG,GAAG,MAAM,CAAC;AAAA,IACpC;AAEA,UAAM,IAAI,MAAM,QAAQ;AAAA,EAC1B;AAEA,SAAO,MAAM,GAAG;AAClB;AAEA,IAAM,iBAAiB;AACvB,IAAM,iBAAiB;AACvB,IAAM,iBAAiB;AACvB,IAAM,iBAAiB;AACvB,IAAM,wBAAwB;AAE9B,IAAM,YAAY;AAClB,IAAM,aAAa,GAAG,SAAS;AAE/B,SAAS,cAAc,KAAa;AAClC,MAAI,OAAO,QAAQ,UAAU;AAC3B,UAAM,IAAI,MAAM,wBAAwB;AAAA,EAC1C;AAEA,SAAO,IACJ,QAAQ,KAAK,GAAG,EAChB,QAAQ,KAAK,EAAE,EACf,QAAQ,gBAAgB,UAAU,EAClC,QAAQ,gBAAgB,IAAI,UAAU,GAAG,EACzC,QAAQ,gBAAgB,GAAG,UAAU,GAAG,EACxC,QAAQ,gBAAgB,IAAI,UAAU,EAAE,EACxC,QAAQ,uBAAuB,GAAG,EAClC,MAAM,GAAG,EACT,IAAI,CAAC,MAAM;AACV,QAAI,EAAE,QAAQ,SAAS,MAAM,GAAG;AAC9B,aAAO,SAAS,EAAE,UAAU,UAAU,MAAM,GAAG,EAAE;AAAA,IACnD;AACA,WAAO;AAAA,EACT,CAAC;AACL;AAEO,SAAS,gBAAgB,KAAU;AACxC,SAAO,EAAE,MAAM,QAAQ,GAAG,KAAK,IAAI,WAAW;AAChD;","names":[]}
|
package/build/modern/utils.d.cts
CHANGED
|
@@ -17,8 +17,8 @@ type IsTuple<T> = T extends readonly any[] & {
|
|
|
17
17
|
length: infer Length;
|
|
18
18
|
} ? Length extends Index40 ? T : never : never;
|
|
19
19
|
type AllowedIndexes<Tuple extends ReadonlyArray<any>, Keys extends number = never> = Tuple extends readonly [] ? Keys : Tuple extends readonly [infer _, ...infer Tail] ? AllowedIndexes<Tail, Keys | Tail['length']> : Keys;
|
|
20
|
-
type DeepKeys<T> = unknown extends T ?
|
|
21
|
-
type DeepKeysPrefix<T, TPrefix> = TPrefix extends keyof T & (number | string) ? `${TPrefix}.${DeepKeys<T[TPrefix]> & string}` : never;
|
|
20
|
+
type DeepKeys<T, TDepth extends any[] = []> = TDepth['length'] extends 5 ? never : unknown extends T ? string : object extends T ? string : T extends readonly any[] & IsTuple<T> ? AllowedIndexes<T> | DeepKeysPrefix<T, AllowedIndexes<T>, TDepth> : T extends any[] ? DeepKeys<T[number], [...TDepth, any]> : T extends Date ? never : T extends object ? (keyof T & string) | DeepKeysPrefix<T, keyof T, TDepth> : never;
|
|
21
|
+
type DeepKeysPrefix<T, TPrefix, TDepth extends any[]> = TPrefix extends keyof T & (number | string) ? `${TPrefix}.${DeepKeys<T[TPrefix], [...TDepth, any]> & string}` : never;
|
|
22
22
|
type DeepValue<T, TProp> = T extends Record<string | number, any> ? TProp extends `${infer TBranch}.${infer TDeepProp}` ? DeepValue<T[TBranch], TDeepProp> : T[TProp & string] : never;
|
|
23
23
|
type Narrowable = string | number | bigint | boolean;
|
|
24
24
|
type NarrowRaw<A> = (A extends [] ? [] : never) | (A extends Narrowable ? A : never) | {
|
package/build/modern/utils.d.ts
CHANGED
|
@@ -17,8 +17,8 @@ type IsTuple<T> = T extends readonly any[] & {
|
|
|
17
17
|
length: infer Length;
|
|
18
18
|
} ? Length extends Index40 ? T : never : never;
|
|
19
19
|
type AllowedIndexes<Tuple extends ReadonlyArray<any>, Keys extends number = never> = Tuple extends readonly [] ? Keys : Tuple extends readonly [infer _, ...infer Tail] ? AllowedIndexes<Tail, Keys | Tail['length']> : Keys;
|
|
20
|
-
type DeepKeys<T> = unknown extends T ?
|
|
21
|
-
type DeepKeysPrefix<T, TPrefix> = TPrefix extends keyof T & (number | string) ? `${TPrefix}.${DeepKeys<T[TPrefix]> & string}` : never;
|
|
20
|
+
type DeepKeys<T, TDepth extends any[] = []> = TDepth['length'] extends 5 ? never : unknown extends T ? string : object extends T ? string : T extends readonly any[] & IsTuple<T> ? AllowedIndexes<T> | DeepKeysPrefix<T, AllowedIndexes<T>, TDepth> : T extends any[] ? DeepKeys<T[number], [...TDepth, any]> : T extends Date ? never : T extends object ? (keyof T & string) | DeepKeysPrefix<T, keyof T, TDepth> : never;
|
|
21
|
+
type DeepKeysPrefix<T, TPrefix, TDepth extends any[]> = TPrefix extends keyof T & (number | string) ? `${TPrefix}.${DeepKeys<T[TPrefix], [...TDepth, any]> & string}` : never;
|
|
22
22
|
type DeepValue<T, TProp> = T extends Record<string | number, any> ? TProp extends `${infer TBranch}.${infer TDeepProp}` ? DeepValue<T[TBranch], TDeepProp> : T[TProp & string] : never;
|
|
23
23
|
type Narrowable = string | number | bigint | boolean;
|
|
24
24
|
type NarrowRaw<A> = (A extends [] ? [] : never) | (A extends Narrowable ? A : never) | {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/utils.ts"],"sourcesContent":["export type UpdaterFn<TInput, TOutput = TInput> = (input: TInput) => TOutput\n\nexport type Updater<TInput, TOutput = TInput> =\n | TOutput\n | UpdaterFn<TInput, TOutput>\n\nexport function functionalUpdate<TInput, TOutput = TInput>(\n updater: Updater<TInput, TOutput>,\n input: TInput,\n): TOutput {\n return typeof updater === 'function'\n ? (updater as UpdaterFn<TInput, TOutput>)(input)\n : updater\n}\n\n/**\n * Get a value from an object using a path, including dot notation.\n */\nexport function getBy(obj: any, path: any) {\n const pathArray = makePathArray(path)\n const pathObj = pathArray\n return pathObj.reduce((current: any, pathPart: any) => {\n if (typeof current !== 'undefined') {\n return current[pathPart]\n }\n return undefined\n }, obj)\n}\n\n/**\n * Set a value on an object using a path, including dot notation.\n */\nexport function setBy(obj: any, _path: any, updater: Updater<any>) {\n const path = makePathArray(_path)\n\n function doSet(parent?: any): any {\n if (!path.length) {\n return functionalUpdate(updater, parent)\n }\n\n const key = path.shift()\n\n if (typeof key === 'string') {\n if (typeof parent === 'object') {\n return {\n ...parent,\n [key]: doSet(parent[key]),\n }\n }\n return {\n [key]: doSet(),\n }\n }\n\n if (typeof key === 'number') {\n if (Array.isArray(parent)) {\n const prefix = parent.slice(0, key)\n return [\n ...(prefix.length ? prefix : new Array(key)),\n doSet(parent[key]),\n ...parent.slice(key + 1),\n ]\n }\n return [...new Array(key), doSet()]\n }\n\n throw new Error('Uh oh!')\n }\n\n return doSet(obj)\n}\n\nconst reFindNumbers0 = /^(\\d*)$/gm\nconst reFindNumbers1 = /\\.(\\d*)\\./gm\nconst reFindNumbers2 = /^(\\d*)\\./gm\nconst reFindNumbers3 = /\\.(\\d*$)/gm\nconst reFindMultiplePeriods = /\\.{2,}/gm\n\nconst intPrefix = '__int__'\nconst intReplace = `${intPrefix}$1`\n\nfunction makePathArray(str: string) {\n if (typeof str !== 'string') {\n throw new Error('Path must be a string.')\n }\n\n return str\n .replace('[', '.')\n .replace(']', '')\n .replace(reFindNumbers0, intReplace)\n .replace(reFindNumbers1, `.${intReplace}.`)\n .replace(reFindNumbers2, `${intReplace}.`)\n .replace(reFindNumbers3, `.${intReplace}`)\n .replace(reFindMultiplePeriods, '.')\n .split('.')\n .map((d) => {\n if (d.indexOf(intPrefix) === 0) {\n return parseInt(d.substring(intPrefix.length), 10)\n }\n return d\n })\n}\n\nexport function isNonEmptyArray(obj: any) {\n return !(Array.isArray(obj) && obj.length === 0)\n}\n\nexport type RequiredByKey<T, K extends keyof T> = Omit<T, K> &\n Required<Pick<T, K>>\n\ntype ComputeRange<\n N extends number,\n Result extends Array<unknown> = [],\n> = Result['length'] extends N\n ? Result\n : ComputeRange<N, [...Result, Result['length']]>\ntype Index40 = ComputeRange<40>[number]\n\n// Is this type a tuple?\ntype IsTuple<T> = T extends readonly any[] & { length: infer Length }\n ? Length extends Index40\n ? T\n : never\n : never\n\n// If this type is a tuple, what indices are allowed?\ntype AllowedIndexes<\n Tuple extends ReadonlyArray<any>,\n Keys extends number = never,\n> = Tuple extends readonly []\n ? Keys\n : Tuple extends readonly [infer _, ...infer Tail]\n ? AllowedIndexes<Tail, Keys | Tail['length']>\n : Keys\n\nexport type DeepKeys<T> =
|
|
1
|
+
{"version":3,"sources":["../../src/utils.ts"],"sourcesContent":["export type UpdaterFn<TInput, TOutput = TInput> = (input: TInput) => TOutput\n\nexport type Updater<TInput, TOutput = TInput> =\n | TOutput\n | UpdaterFn<TInput, TOutput>\n\nexport function functionalUpdate<TInput, TOutput = TInput>(\n updater: Updater<TInput, TOutput>,\n input: TInput,\n): TOutput {\n return typeof updater === 'function'\n ? (updater as UpdaterFn<TInput, TOutput>)(input)\n : updater\n}\n\n/**\n * Get a value from an object using a path, including dot notation.\n */\nexport function getBy(obj: any, path: any) {\n const pathArray = makePathArray(path)\n const pathObj = pathArray\n return pathObj.reduce((current: any, pathPart: any) => {\n if (typeof current !== 'undefined') {\n return current[pathPart]\n }\n return undefined\n }, obj)\n}\n\n/**\n * Set a value on an object using a path, including dot notation.\n */\nexport function setBy(obj: any, _path: any, updater: Updater<any>) {\n const path = makePathArray(_path)\n\n function doSet(parent?: any): any {\n if (!path.length) {\n return functionalUpdate(updater, parent)\n }\n\n const key = path.shift()\n\n if (typeof key === 'string') {\n if (typeof parent === 'object') {\n return {\n ...parent,\n [key]: doSet(parent[key]),\n }\n }\n return {\n [key]: doSet(),\n }\n }\n\n if (typeof key === 'number') {\n if (Array.isArray(parent)) {\n const prefix = parent.slice(0, key)\n return [\n ...(prefix.length ? prefix : new Array(key)),\n doSet(parent[key]),\n ...parent.slice(key + 1),\n ]\n }\n return [...new Array(key), doSet()]\n }\n\n throw new Error('Uh oh!')\n }\n\n return doSet(obj)\n}\n\nconst reFindNumbers0 = /^(\\d*)$/gm\nconst reFindNumbers1 = /\\.(\\d*)\\./gm\nconst reFindNumbers2 = /^(\\d*)\\./gm\nconst reFindNumbers3 = /\\.(\\d*$)/gm\nconst reFindMultiplePeriods = /\\.{2,}/gm\n\nconst intPrefix = '__int__'\nconst intReplace = `${intPrefix}$1`\n\nfunction makePathArray(str: string) {\n if (typeof str !== 'string') {\n throw new Error('Path must be a string.')\n }\n\n return str\n .replace('[', '.')\n .replace(']', '')\n .replace(reFindNumbers0, intReplace)\n .replace(reFindNumbers1, `.${intReplace}.`)\n .replace(reFindNumbers2, `${intReplace}.`)\n .replace(reFindNumbers3, `.${intReplace}`)\n .replace(reFindMultiplePeriods, '.')\n .split('.')\n .map((d) => {\n if (d.indexOf(intPrefix) === 0) {\n return parseInt(d.substring(intPrefix.length), 10)\n }\n return d\n })\n}\n\nexport function isNonEmptyArray(obj: any) {\n return !(Array.isArray(obj) && obj.length === 0)\n}\n\nexport type RequiredByKey<T, K extends keyof T> = Omit<T, K> &\n Required<Pick<T, K>>\n\ntype ComputeRange<\n N extends number,\n Result extends Array<unknown> = [],\n> = Result['length'] extends N\n ? Result\n : ComputeRange<N, [...Result, Result['length']]>\ntype Index40 = ComputeRange<40>[number]\n\n// Is this type a tuple?\ntype IsTuple<T> = T extends readonly any[] & { length: infer Length }\n ? Length extends Index40\n ? T\n : never\n : never\n\n// If this type is a tuple, what indices are allowed?\ntype AllowedIndexes<\n Tuple extends ReadonlyArray<any>,\n Keys extends number = never,\n> = Tuple extends readonly []\n ? Keys\n : Tuple extends readonly [infer _, ...infer Tail]\n ? AllowedIndexes<Tail, Keys | Tail['length']>\n : Keys\n\nexport type DeepKeys<T, TDepth extends any[] = []> = TDepth['length'] extends 5\n ? never\n : unknown extends T\n ? string\n : object extends T\n ? string\n : T extends readonly any[] & IsTuple<T>\n ? AllowedIndexes<T> | DeepKeysPrefix<T, AllowedIndexes<T>, TDepth>\n : T extends any[]\n ? DeepKeys<T[number], [...TDepth, any]>\n : T extends Date\n ? never\n : T extends object\n ? (keyof T & string) | DeepKeysPrefix<T, keyof T, TDepth>\n : never\n\ntype DeepKeysPrefix<\n T,\n TPrefix,\n TDepth extends any[],\n> = TPrefix extends keyof T & (number | string)\n ? `${TPrefix}.${DeepKeys<T[TPrefix], [...TDepth, any]> & string}`\n : never\n\nexport type DeepValue<T, TProp> = T extends Record<string | number, any>\n ? TProp extends `${infer TBranch}.${infer TDeepProp}`\n ? DeepValue<T[TBranch], TDeepProp>\n : T[TProp & string]\n : never\n\ntype Narrowable = string | number | bigint | boolean\n\ntype NarrowRaw<A> =\n | (A extends [] ? [] : never)\n | (A extends Narrowable ? A : never)\n | {\n [K in keyof A]: A[K] extends Function ? A[K] : NarrowRaw<A[K]>\n }\n\nexport type Narrow<A> = Try<A, [], NarrowRaw<A>>\n\ntype Try<A1, A2, Catch = never> = A1 extends A2 ? A1 : Catch\n\n// Hack to get TypeScript to show simplified types in error messages\nexport type Pretty<T> = { [K in keyof T]: T[K] } & {}\n"],"mappings":";AAMO,SAAS,iBACd,SACA,OACS;AACT,SAAO,OAAO,YAAY,aACrB,QAAuC,KAAK,IAC7C;AACN;AAKO,SAAS,MAAM,KAAU,MAAW;AACzC,QAAM,YAAY,cAAc,IAAI;AACpC,QAAM,UAAU;AAChB,SAAO,QAAQ,OAAO,CAAC,SAAc,aAAkB;AACrD,QAAI,OAAO,YAAY,aAAa;AAClC,aAAO,QAAQ,QAAQ;AAAA,IACzB;AACA,WAAO;AAAA,EACT,GAAG,GAAG;AACR;AAKO,SAAS,MAAM,KAAU,OAAY,SAAuB;AACjE,QAAM,OAAO,cAAc,KAAK;AAEhC,WAAS,MAAM,QAAmB;AAChC,QAAI,CAAC,KAAK,QAAQ;AAChB,aAAO,iBAAiB,SAAS,MAAM;AAAA,IACzC;AAEA,UAAM,MAAM,KAAK,MAAM;AAEvB,QAAI,OAAO,QAAQ,UAAU;AAC3B,UAAI,OAAO,WAAW,UAAU;AAC9B,eAAO;AAAA,UACL,GAAG;AAAA,UACH,CAAC,GAAG,GAAG,MAAM,OAAO,GAAG,CAAC;AAAA,QAC1B;AAAA,MACF;AACA,aAAO;AAAA,QACL,CAAC,GAAG,GAAG,MAAM;AAAA,MACf;AAAA,IACF;AAEA,QAAI,OAAO,QAAQ,UAAU;AAC3B,UAAI,MAAM,QAAQ,MAAM,GAAG;AACzB,cAAM,SAAS,OAAO,MAAM,GAAG,GAAG;AAClC,eAAO;AAAA,UACL,GAAI,OAAO,SAAS,SAAS,IAAI,MAAM,GAAG;AAAA,UAC1C,MAAM,OAAO,GAAG,CAAC;AAAA,UACjB,GAAG,OAAO,MAAM,MAAM,CAAC;AAAA,QACzB;AAAA,MACF;AACA,aAAO,CAAC,GAAG,IAAI,MAAM,GAAG,GAAG,MAAM,CAAC;AAAA,IACpC;AAEA,UAAM,IAAI,MAAM,QAAQ;AAAA,EAC1B;AAEA,SAAO,MAAM,GAAG;AAClB;AAEA,IAAM,iBAAiB;AACvB,IAAM,iBAAiB;AACvB,IAAM,iBAAiB;AACvB,IAAM,iBAAiB;AACvB,IAAM,wBAAwB;AAE9B,IAAM,YAAY;AAClB,IAAM,aAAa,GAAG,SAAS;AAE/B,SAAS,cAAc,KAAa;AAClC,MAAI,OAAO,QAAQ,UAAU;AAC3B,UAAM,IAAI,MAAM,wBAAwB;AAAA,EAC1C;AAEA,SAAO,IACJ,QAAQ,KAAK,GAAG,EAChB,QAAQ,KAAK,EAAE,EACf,QAAQ,gBAAgB,UAAU,EAClC,QAAQ,gBAAgB,IAAI,UAAU,GAAG,EACzC,QAAQ,gBAAgB,GAAG,UAAU,GAAG,EACxC,QAAQ,gBAAgB,IAAI,UAAU,EAAE,EACxC,QAAQ,uBAAuB,GAAG,EAClC,MAAM,GAAG,EACT,IAAI,CAAC,MAAM;AACV,QAAI,EAAE,QAAQ,SAAS,MAAM,GAAG;AAC9B,aAAO,SAAS,EAAE,UAAU,UAAU,MAAM,GAAG,EAAE;AAAA,IACnD;AACA,WAAO;AAAA,EACT,CAAC;AACL;AAEO,SAAS,gBAAgB,KAAU;AACxC,SAAO,EAAE,MAAM,QAAQ,GAAG,KAAK,IAAI,WAAW;AAChD;","names":[]}
|
package/package.json
CHANGED
package/src/FieldApi.ts
CHANGED
|
@@ -4,59 +4,54 @@ import { Store } from '@tanstack/store'
|
|
|
4
4
|
|
|
5
5
|
export type ValidationCause = 'change' | 'blur' | 'submit' | 'mount'
|
|
6
6
|
|
|
7
|
-
type ValidateFn<
|
|
7
|
+
type ValidateFn<TParentData, TName extends DeepKeys<TParentData>, TData> = (
|
|
8
8
|
value: TData,
|
|
9
|
-
fieldApi: FieldApi<
|
|
9
|
+
fieldApi: FieldApi<TParentData, TName>,
|
|
10
10
|
) => ValidationError
|
|
11
11
|
|
|
12
|
-
type ValidateAsyncFn<
|
|
12
|
+
type ValidateAsyncFn<
|
|
13
|
+
TParentData,
|
|
14
|
+
TName extends DeepKeys<TParentData>,
|
|
15
|
+
TData,
|
|
16
|
+
> = (
|
|
13
17
|
value: TData,
|
|
14
|
-
fieldApi: FieldApi<
|
|
18
|
+
fieldApi: FieldApi<TParentData, TName>,
|
|
15
19
|
) => ValidationError | Promise<ValidationError>
|
|
16
20
|
|
|
17
21
|
export interface FieldOptions<
|
|
18
|
-
|
|
19
|
-
TFormData,
|
|
22
|
+
TParentData,
|
|
20
23
|
/**
|
|
21
24
|
* This allows us to restrict the name to only be a valid field name while
|
|
22
25
|
* also assigning it to a generic
|
|
23
26
|
*/
|
|
24
|
-
TName
|
|
27
|
+
TName extends DeepKeys<TParentData>,
|
|
25
28
|
/**
|
|
26
29
|
* If TData is unknown, we can use the TName generic to determine the type
|
|
27
30
|
*/
|
|
28
|
-
TData =
|
|
31
|
+
TData = DeepValue<TParentData, TName>,
|
|
29
32
|
> {
|
|
30
|
-
name:
|
|
33
|
+
name: DeepKeys<TParentData>
|
|
31
34
|
index?: TData extends any[] ? number : never
|
|
32
35
|
defaultValue?: TData
|
|
33
36
|
asyncDebounceMs?: number
|
|
34
37
|
asyncAlways?: boolean
|
|
35
|
-
onMount?: (formApi: FieldApi<
|
|
36
|
-
onChange?: ValidateFn<
|
|
37
|
-
onChangeAsync?: ValidateAsyncFn<
|
|
38
|
+
onMount?: (formApi: FieldApi<TParentData, TName>) => void
|
|
39
|
+
onChange?: ValidateFn<TParentData, TName, TData>
|
|
40
|
+
onChangeAsync?: ValidateAsyncFn<TParentData, TName, TData>
|
|
38
41
|
onChangeAsyncDebounceMs?: number
|
|
39
|
-
onBlur?: ValidateFn<
|
|
40
|
-
onBlurAsync?: ValidateAsyncFn<
|
|
42
|
+
onBlur?: ValidateFn<TParentData, TName, TData>
|
|
43
|
+
onBlurAsync?: ValidateAsyncFn<TParentData, TName, TData>
|
|
41
44
|
onBlurAsyncDebounceMs?: number
|
|
42
|
-
onSubmitAsync?: ValidateAsyncFn<
|
|
45
|
+
onSubmitAsync?: ValidateAsyncFn<TParentData, TName, TData>
|
|
43
46
|
defaultMeta?: Partial<FieldMeta>
|
|
44
47
|
}
|
|
45
48
|
|
|
46
49
|
export interface FieldApiOptions<
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
*/
|
|
53
|
-
TName = unknown extends TFormData ? string : DeepKeys<TFormData>,
|
|
54
|
-
/**
|
|
55
|
-
* If TData is unknown, we can use the TName generic to determine the type
|
|
56
|
-
*/
|
|
57
|
-
TData = unknown extends _TData ? DeepValue<TFormData, TName> : _TData,
|
|
58
|
-
> extends FieldOptions<_TData, TFormData, TName, TData> {
|
|
59
|
-
form: FormApi<TFormData>
|
|
50
|
+
TParentData,
|
|
51
|
+
TName extends DeepKeys<TParentData>,
|
|
52
|
+
TData = DeepValue<TParentData, TName>,
|
|
53
|
+
> extends FieldOptions<TParentData, TName, TData> {
|
|
54
|
+
form: FormApi<TParentData>
|
|
60
55
|
}
|
|
61
56
|
|
|
62
57
|
export type FieldMeta = {
|
|
@@ -74,43 +69,26 @@ export type FieldState<TData> = {
|
|
|
74
69
|
meta: FieldMeta
|
|
75
70
|
}
|
|
76
71
|
|
|
77
|
-
type
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
Opts extends FieldApiOptions<TData, TFormData>,
|
|
81
|
-
> = Opts extends FieldApiOptions<
|
|
82
|
-
infer _TData,
|
|
83
|
-
infer _TFormData,
|
|
84
|
-
infer _TName,
|
|
85
|
-
infer RealTData
|
|
86
|
-
>
|
|
87
|
-
? RealTData
|
|
88
|
-
: never
|
|
72
|
+
export type ResolveName<TParentData> = unknown extends TParentData
|
|
73
|
+
? string
|
|
74
|
+
: DeepKeys<TParentData>
|
|
89
75
|
|
|
90
76
|
export class FieldApi<
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
_TData,
|
|
95
|
-
TFormData
|
|
96
|
-
>,
|
|
97
|
-
TData extends GetTData<_TData, TFormData, Opts> = GetTData<
|
|
98
|
-
_TData,
|
|
99
|
-
TFormData,
|
|
100
|
-
Opts
|
|
101
|
-
>,
|
|
77
|
+
TParentData,
|
|
78
|
+
TName extends DeepKeys<TParentData>,
|
|
79
|
+
TData = DeepValue<TParentData, TName>,
|
|
102
80
|
> {
|
|
103
81
|
uid: number
|
|
104
|
-
form:
|
|
105
|
-
name!: DeepKeys<
|
|
106
|
-
options:
|
|
82
|
+
form: FieldApiOptions<TParentData, TName, TData>['form']
|
|
83
|
+
name!: DeepKeys<TParentData>
|
|
84
|
+
options: FieldApiOptions<TParentData, TName> = {} as any
|
|
107
85
|
store!: Store<FieldState<TData>>
|
|
108
86
|
state!: FieldState<TData>
|
|
109
87
|
prevState!: FieldState<TData>
|
|
110
88
|
|
|
111
89
|
constructor(
|
|
112
|
-
opts:
|
|
113
|
-
form: FormApi<
|
|
90
|
+
opts: FieldApiOptions<TParentData, TName, TData> & {
|
|
91
|
+
form: FormApi<TParentData>
|
|
114
92
|
},
|
|
115
93
|
) {
|
|
116
94
|
this.form = opts.form
|
|
@@ -190,12 +168,12 @@ export class FieldApi<
|
|
|
190
168
|
}
|
|
191
169
|
}
|
|
192
170
|
|
|
193
|
-
update = (opts: FieldApiOptions<
|
|
171
|
+
update = (opts: FieldApiOptions<TParentData, TName, TData>) => {
|
|
194
172
|
// Default Value
|
|
195
173
|
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
|
|
196
174
|
if (this.state.value === undefined) {
|
|
197
175
|
const formDefault =
|
|
198
|
-
opts.form.options.defaultValues?.[opts.name as keyof
|
|
176
|
+
opts.form.options.defaultValues?.[opts.name as keyof TParentData]
|
|
199
177
|
|
|
200
178
|
if (opts.defaultValue !== undefined) {
|
|
201
179
|
this.setValue(opts.defaultValue as never)
|
|
@@ -213,7 +191,7 @@ export class FieldApi<
|
|
|
213
191
|
}
|
|
214
192
|
|
|
215
193
|
getValue = (): TData => {
|
|
216
|
-
return this.form.getFieldValue(this.name)
|
|
194
|
+
return this.form.getFieldValue(this.name) as any
|
|
217
195
|
}
|
|
218
196
|
|
|
219
197
|
setValue = (
|
|
@@ -254,11 +232,16 @@ export class FieldApi<
|
|
|
254
232
|
swapValues = (aIndex: number, bIndex: number) =>
|
|
255
233
|
this.form.swapFieldValues(this.name, aIndex, bIndex)
|
|
256
234
|
|
|
257
|
-
getSubField = <
|
|
258
|
-
|
|
235
|
+
getSubField = <
|
|
236
|
+
TSubName extends DeepKeys<TData>,
|
|
237
|
+
TSubData = DeepValue<TData, TSubName>,
|
|
238
|
+
>(
|
|
239
|
+
name: TSubName,
|
|
240
|
+
): FieldApi<TData, TSubName, TSubData> =>
|
|
241
|
+
new FieldApi({
|
|
259
242
|
name: `${this.name}.${name}` as never,
|
|
260
243
|
form: this.form,
|
|
261
|
-
})
|
|
244
|
+
}) as any
|
|
262
245
|
|
|
263
246
|
validateSync = (value = this.state.value, cause: ValidationCause) => {
|
|
264
247
|
const { onChange, onBlur } = this.options
|
package/src/FormApi.ts
CHANGED
|
@@ -31,7 +31,7 @@ export type FormOptions<TData> = {
|
|
|
31
31
|
}
|
|
32
32
|
|
|
33
33
|
export type FieldInfo<TFormData> = {
|
|
34
|
-
instances: Record<string, FieldApi<any,
|
|
34
|
+
instances: Record<string, FieldApi<TFormData, any, any>>
|
|
35
35
|
} & ValidationMeta
|
|
36
36
|
|
|
37
37
|
export type ValidationMeta = {
|
|
@@ -106,7 +106,7 @@ export class FormApi<TFormData> {
|
|
|
106
106
|
constructor(opts?: FormOptions<TFormData>) {
|
|
107
107
|
this.store = new Store<FormState<TFormData>>(
|
|
108
108
|
getDefaultFormState({
|
|
109
|
-
...opts?.defaultState,
|
|
109
|
+
...(opts?.defaultState as any),
|
|
110
110
|
values: opts?.defaultValues ?? opts?.defaultState?.values,
|
|
111
111
|
isFormValid: true,
|
|
112
112
|
}),
|
|
@@ -174,7 +174,7 @@ export class FormApi<TFormData> {
|
|
|
174
174
|
getDefaultFormState(
|
|
175
175
|
Object.assign(
|
|
176
176
|
{},
|
|
177
|
-
this.state,
|
|
177
|
+
this.state as any,
|
|
178
178
|
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
|
|
179
179
|
shouldUpdateState ? options.defaultState : {},
|
|
180
180
|
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
|
|
@@ -194,7 +194,7 @@ export class FormApi<TFormData> {
|
|
|
194
194
|
reset = () =>
|
|
195
195
|
this.store.setState(() =>
|
|
196
196
|
getDefaultFormState({
|
|
197
|
-
...this.options.defaultState,
|
|
197
|
+
...(this.options.defaultState as any),
|
|
198
198
|
values: this.options.defaultValues ?? this.options.defaultState?.values,
|
|
199
199
|
}),
|
|
200
200
|
)
|
|
@@ -288,7 +288,9 @@ export class FormApi<TFormData> {
|
|
|
288
288
|
return this.state.fieldMeta[field]
|
|
289
289
|
}
|
|
290
290
|
|
|
291
|
-
getFieldInfo = <TField extends DeepKeys<TFormData>>(
|
|
291
|
+
getFieldInfo = <TField extends DeepKeys<TFormData>>(
|
|
292
|
+
field: TField,
|
|
293
|
+
): FieldInfo<TFormData> => {
|
|
292
294
|
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
|
|
293
295
|
return (this.fieldInfo[field] ||= {
|
|
294
296
|
instances: {},
|
package/src/utils.ts
CHANGED
|
@@ -133,22 +133,28 @@ type AllowedIndexes<
|
|
|
133
133
|
? AllowedIndexes<Tail, Keys | Tail['length']>
|
|
134
134
|
: Keys
|
|
135
135
|
|
|
136
|
-
export type DeepKeys<T> =
|
|
137
|
-
?
|
|
136
|
+
export type DeepKeys<T, TDepth extends any[] = []> = TDepth['length'] extends 5
|
|
137
|
+
? never
|
|
138
|
+
: unknown extends T
|
|
139
|
+
? string
|
|
138
140
|
: object extends T
|
|
139
141
|
? string
|
|
140
142
|
: T extends readonly any[] & IsTuple<T>
|
|
141
|
-
? AllowedIndexes<T> | DeepKeysPrefix<T, AllowedIndexes<T
|
|
143
|
+
? AllowedIndexes<T> | DeepKeysPrefix<T, AllowedIndexes<T>, TDepth>
|
|
142
144
|
: T extends any[]
|
|
143
|
-
? DeepKeys<T[number]>
|
|
145
|
+
? DeepKeys<T[number], [...TDepth, any]>
|
|
144
146
|
: T extends Date
|
|
145
147
|
? never
|
|
146
148
|
: T extends object
|
|
147
|
-
? (keyof T & string) | DeepKeysPrefix<T, keyof T>
|
|
149
|
+
? (keyof T & string) | DeepKeysPrefix<T, keyof T, TDepth>
|
|
148
150
|
: never
|
|
149
151
|
|
|
150
|
-
type DeepKeysPrefix<
|
|
151
|
-
|
|
152
|
+
type DeepKeysPrefix<
|
|
153
|
+
T,
|
|
154
|
+
TPrefix,
|
|
155
|
+
TDepth extends any[],
|
|
156
|
+
> = TPrefix extends keyof T & (number | string)
|
|
157
|
+
? `${TPrefix}.${DeepKeys<T[TPrefix], [...TDepth, any]> & string}`
|
|
152
158
|
: never
|
|
153
159
|
|
|
154
160
|
export type DeepValue<T, TProp> = T extends Record<string | number, any>
|