@tanstack/form-core 1.25.0 → 1.27.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.
- package/dist/cjs/FieldApi.cjs +15 -16
- package/dist/cjs/FieldApi.cjs.map +1 -1
- package/dist/cjs/FieldApi.d.cts +1 -1
- package/dist/cjs/FormApi.cjs +7 -9
- package/dist/cjs/FormApi.cjs.map +1 -1
- package/dist/cjs/FormApi.d.cts +1 -1
- package/dist/cjs/metaHelper.cjs +86 -70
- package/dist/cjs/metaHelper.cjs.map +1 -1
- package/dist/cjs/metaHelper.d.cts +5 -4
- package/dist/cjs/utils.cjs +1 -1
- package/dist/cjs/utils.cjs.map +1 -1
- package/dist/cjs/utils.d.cts +1 -1
- package/dist/esm/FieldApi.d.ts +1 -1
- package/dist/esm/FieldApi.js +16 -17
- package/dist/esm/FieldApi.js.map +1 -1
- package/dist/esm/FormApi.d.ts +1 -1
- package/dist/esm/FormApi.js +7 -9
- package/dist/esm/FormApi.js.map +1 -1
- package/dist/esm/metaHelper.d.ts +5 -4
- package/dist/esm/metaHelper.js +86 -70
- package/dist/esm/metaHelper.js.map +1 -1
- package/dist/esm/utils.d.ts +1 -1
- package/dist/esm/utils.js +1 -1
- package/dist/esm/utils.js.map +1 -1
- package/package.json +1 -1
- package/src/FieldApi.ts +27 -27
- package/src/FormApi.ts +10 -12
- package/src/metaHelper.ts +133 -117
- package/src/utils.ts +6 -3
package/src/metaHelper.ts
CHANGED
|
@@ -6,7 +6,7 @@ import type {
|
|
|
6
6
|
import type { AnyFieldMeta } from './FieldApi'
|
|
7
7
|
import type { DeepKeys } from './util-types'
|
|
8
8
|
|
|
9
|
-
type
|
|
9
|
+
type ValueFieldMode = 'insert' | 'remove' | 'swap' | 'move'
|
|
10
10
|
|
|
11
11
|
export const defaultFieldMeta: AnyFieldMeta = {
|
|
12
12
|
isValidating: false,
|
|
@@ -33,7 +33,7 @@ export function metaHelper<
|
|
|
33
33
|
TOnDynamic extends undefined | FormValidateOrFn<TFormData>,
|
|
34
34
|
TOnDynamicAsync extends undefined | FormAsyncValidateOrFn<TFormData>,
|
|
35
35
|
TOnServer extends undefined | FormAsyncValidateOrFn<TFormData>,
|
|
36
|
-
TSubmitMeta,
|
|
36
|
+
TSubmitMeta = never,
|
|
37
37
|
>(
|
|
38
38
|
formApi: FormApi<
|
|
39
39
|
TFormData,
|
|
@@ -50,57 +50,148 @@ export function metaHelper<
|
|
|
50
50
|
TSubmitMeta
|
|
51
51
|
>,
|
|
52
52
|
) {
|
|
53
|
-
|
|
53
|
+
/**
|
|
54
|
+
* Handle the meta shift caused from moving a field from one index to another.
|
|
55
|
+
*/
|
|
56
|
+
function handleArrayMove(
|
|
54
57
|
field: DeepKeys<TFormData>,
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
secondIndex?: number,
|
|
58
|
+
fromIndex: number,
|
|
59
|
+
toIndex: number,
|
|
58
60
|
) {
|
|
59
|
-
const affectedFields = getAffectedFields(field,
|
|
60
|
-
|
|
61
|
-
const
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
secondIndex !== undefined &&
|
|
66
|
-
handleSwapMode(affectedFields, field, index, secondIndex),
|
|
67
|
-
move: () =>
|
|
68
|
-
secondIndex !== undefined &&
|
|
69
|
-
handleMoveMode(affectedFields, field, index, secondIndex),
|
|
61
|
+
const affectedFields = getAffectedFields(field, fromIndex, 'move', toIndex)
|
|
62
|
+
|
|
63
|
+
const startIndex = Math.min(fromIndex, toIndex)
|
|
64
|
+
const endIndex = Math.max(fromIndex, toIndex)
|
|
65
|
+
for (let i = startIndex; i <= endIndex; i++) {
|
|
66
|
+
affectedFields.push(getFieldPath(field, i))
|
|
70
67
|
}
|
|
71
68
|
|
|
72
|
-
|
|
69
|
+
// Store the original field meta that will be reapplied at the destination index
|
|
70
|
+
const fromFields = Object.keys(formApi.fieldInfo).reduce(
|
|
71
|
+
(fieldMap, fieldKey) => {
|
|
72
|
+
if (fieldKey.startsWith(getFieldPath(field, fromIndex))) {
|
|
73
|
+
fieldMap.set(
|
|
74
|
+
fieldKey as DeepKeys<TFormData>,
|
|
75
|
+
formApi.getFieldMeta(fieldKey as DeepKeys<TFormData>),
|
|
76
|
+
)
|
|
77
|
+
}
|
|
78
|
+
return fieldMap
|
|
79
|
+
},
|
|
80
|
+
new Map<DeepKeys<TFormData>, AnyFieldMeta | undefined>(),
|
|
81
|
+
)
|
|
82
|
+
|
|
83
|
+
shiftMeta(affectedFields, fromIndex < toIndex ? 'up' : 'down')
|
|
84
|
+
|
|
85
|
+
// Reapply the stored field meta at the destination index
|
|
86
|
+
Object.keys(formApi.fieldInfo)
|
|
87
|
+
.filter((fieldKey) => fieldKey.startsWith(getFieldPath(field, toIndex)))
|
|
88
|
+
.forEach((fieldKey) => {
|
|
89
|
+
const fromKey = fieldKey.replace(
|
|
90
|
+
getFieldPath(field, toIndex),
|
|
91
|
+
getFieldPath(field, fromIndex),
|
|
92
|
+
) as DeepKeys<TFormData>
|
|
93
|
+
|
|
94
|
+
const fromMeta = fromFields.get(fromKey)
|
|
95
|
+
if (fromMeta) {
|
|
96
|
+
formApi.setFieldMeta(fieldKey as DeepKeys<TFormData>, fromMeta)
|
|
97
|
+
}
|
|
98
|
+
})
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
/**
|
|
102
|
+
* Handle the meta shift from removing a field at the specified index.
|
|
103
|
+
*/
|
|
104
|
+
function handleArrayRemove(field: DeepKeys<TFormData>, index: number) {
|
|
105
|
+
const affectedFields = getAffectedFields(field, index, 'remove')
|
|
106
|
+
|
|
107
|
+
shiftMeta(affectedFields, 'up')
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
/**
|
|
111
|
+
* Handle the meta shift from swapping two fields at the specified indeces.
|
|
112
|
+
*/
|
|
113
|
+
function handleArraySwap(
|
|
114
|
+
field: DeepKeys<TFormData>,
|
|
115
|
+
index: number,
|
|
116
|
+
secondIndex: number,
|
|
117
|
+
) {
|
|
118
|
+
const affectedFields = getAffectedFields(field, index, 'swap', secondIndex)
|
|
119
|
+
|
|
120
|
+
affectedFields.forEach((fieldKey) => {
|
|
121
|
+
if (!fieldKey.toString().startsWith(getFieldPath(field, index))) {
|
|
122
|
+
return
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
const swappedKey = fieldKey
|
|
126
|
+
.toString()
|
|
127
|
+
.replace(
|
|
128
|
+
getFieldPath(field, index),
|
|
129
|
+
getFieldPath(field, secondIndex),
|
|
130
|
+
) as DeepKeys<TFormData>
|
|
131
|
+
|
|
132
|
+
const [meta1, meta2] = [
|
|
133
|
+
formApi.getFieldMeta(fieldKey),
|
|
134
|
+
formApi.getFieldMeta(swappedKey),
|
|
135
|
+
]
|
|
136
|
+
|
|
137
|
+
if (meta1) formApi.setFieldMeta(swappedKey, meta1)
|
|
138
|
+
if (meta2) formApi.setFieldMeta(fieldKey, meta2)
|
|
139
|
+
})
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
/**
|
|
143
|
+
* Handle the meta shift from inserting a field at the specified index.
|
|
144
|
+
*/
|
|
145
|
+
function handleArrayInsert(field: DeepKeys<TFormData>, insertIndex: number) {
|
|
146
|
+
const affectedFields = getAffectedFields(field, insertIndex, 'insert')
|
|
147
|
+
|
|
148
|
+
shiftMeta(affectedFields, 'down')
|
|
149
|
+
|
|
150
|
+
affectedFields.forEach((fieldKey) => {
|
|
151
|
+
if (fieldKey.toString().startsWith(getFieldPath(field, insertIndex))) {
|
|
152
|
+
formApi.setFieldMeta(fieldKey, getEmptyFieldMeta())
|
|
153
|
+
}
|
|
154
|
+
})
|
|
73
155
|
}
|
|
74
156
|
|
|
75
|
-
function getFieldPath(
|
|
76
|
-
|
|
157
|
+
function getFieldPath(
|
|
158
|
+
field: DeepKeys<TFormData>,
|
|
159
|
+
index: number,
|
|
160
|
+
): DeepKeys<TFormData> {
|
|
161
|
+
return `${field}[${index}]` as DeepKeys<TFormData>
|
|
77
162
|
}
|
|
78
163
|
|
|
79
164
|
function getAffectedFields(
|
|
80
165
|
field: DeepKeys<TFormData>,
|
|
81
166
|
index: number,
|
|
82
|
-
mode:
|
|
167
|
+
mode: ValueFieldMode,
|
|
83
168
|
secondIndex?: number,
|
|
84
169
|
): DeepKeys<TFormData>[] {
|
|
85
170
|
const affectedFieldKeys = [getFieldPath(field, index)]
|
|
86
171
|
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
172
|
+
switch (mode) {
|
|
173
|
+
case 'swap':
|
|
174
|
+
affectedFieldKeys.push(getFieldPath(field, secondIndex!))
|
|
175
|
+
break
|
|
176
|
+
case 'move': {
|
|
177
|
+
const [startIndex, endIndex] = [
|
|
178
|
+
Math.min(index, secondIndex!),
|
|
179
|
+
Math.max(index, secondIndex!),
|
|
180
|
+
]
|
|
181
|
+
for (let i = startIndex; i <= endIndex; i++) {
|
|
182
|
+
affectedFieldKeys.push(getFieldPath(field, i))
|
|
183
|
+
}
|
|
184
|
+
break
|
|
96
185
|
}
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
186
|
+
default: {
|
|
187
|
+
const currentValue = formApi.getFieldValue(field)
|
|
188
|
+
const fieldItems = Array.isArray(currentValue)
|
|
189
|
+
? (currentValue as Array<unknown>).length
|
|
190
|
+
: 0
|
|
191
|
+
for (let i = index + 1; i < fieldItems; i++) {
|
|
192
|
+
affectedFieldKeys.push(getFieldPath(field, i))
|
|
193
|
+
}
|
|
194
|
+
break
|
|
104
195
|
}
|
|
105
196
|
}
|
|
106
197
|
|
|
@@ -137,85 +228,10 @@ export function metaHelper<
|
|
|
137
228
|
|
|
138
229
|
const getEmptyFieldMeta = (): AnyFieldMeta => defaultFieldMeta
|
|
139
230
|
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
shiftMeta(fields, 'down')
|
|
146
|
-
|
|
147
|
-
fields.forEach((fieldKey) => {
|
|
148
|
-
if (fieldKey.toString().startsWith(getFieldPath(field, insertIndex))) {
|
|
149
|
-
formApi.setFieldMeta(fieldKey, getEmptyFieldMeta())
|
|
150
|
-
}
|
|
151
|
-
})
|
|
231
|
+
return {
|
|
232
|
+
handleArrayMove,
|
|
233
|
+
handleArrayRemove,
|
|
234
|
+
handleArraySwap,
|
|
235
|
+
handleArrayInsert,
|
|
152
236
|
}
|
|
153
|
-
|
|
154
|
-
const handleRemoveMode = (fields: DeepKeys<TFormData>[]) => {
|
|
155
|
-
shiftMeta(fields, 'up')
|
|
156
|
-
}
|
|
157
|
-
|
|
158
|
-
const handleMoveMode = (
|
|
159
|
-
fields: DeepKeys<TFormData>[],
|
|
160
|
-
field: DeepKeys<TFormData>,
|
|
161
|
-
fromIndex: number,
|
|
162
|
-
toIndex: number,
|
|
163
|
-
) => {
|
|
164
|
-
// Store the original field meta that will be reapplied at the destination index
|
|
165
|
-
const fromFields = new Map(
|
|
166
|
-
Object.keys(formApi.fieldInfo)
|
|
167
|
-
.filter((fieldKey) =>
|
|
168
|
-
fieldKey.startsWith(getFieldPath(field, fromIndex)),
|
|
169
|
-
)
|
|
170
|
-
.map((fieldKey) => [
|
|
171
|
-
fieldKey as DeepKeys<TFormData>,
|
|
172
|
-
formApi.getFieldMeta(fieldKey as DeepKeys<TFormData>),
|
|
173
|
-
]),
|
|
174
|
-
)
|
|
175
|
-
|
|
176
|
-
shiftMeta(fields, fromIndex < toIndex ? 'up' : 'down')
|
|
177
|
-
|
|
178
|
-
// Reapply the stored field meta at the destination index
|
|
179
|
-
Object.keys(formApi.fieldInfo)
|
|
180
|
-
.filter((fieldKey) => fieldKey.startsWith(getFieldPath(field, toIndex)))
|
|
181
|
-
.forEach((fieldKey) => {
|
|
182
|
-
const fromKey = fieldKey.replace(
|
|
183
|
-
getFieldPath(field, toIndex),
|
|
184
|
-
getFieldPath(field, fromIndex),
|
|
185
|
-
) as DeepKeys<TFormData>
|
|
186
|
-
|
|
187
|
-
const fromMeta = fromFields.get(fromKey)
|
|
188
|
-
if (fromMeta) {
|
|
189
|
-
formApi.setFieldMeta(fieldKey as DeepKeys<TFormData>, fromMeta)
|
|
190
|
-
}
|
|
191
|
-
})
|
|
192
|
-
}
|
|
193
|
-
|
|
194
|
-
const handleSwapMode = (
|
|
195
|
-
fields: DeepKeys<TFormData>[],
|
|
196
|
-
field: DeepKeys<TFormData>,
|
|
197
|
-
index: number,
|
|
198
|
-
secondIndex: number,
|
|
199
|
-
) => {
|
|
200
|
-
fields.forEach((fieldKey) => {
|
|
201
|
-
if (!fieldKey.toString().startsWith(getFieldPath(field, index))) return
|
|
202
|
-
|
|
203
|
-
const swappedKey = fieldKey
|
|
204
|
-
.toString()
|
|
205
|
-
.replace(
|
|
206
|
-
getFieldPath(field, index),
|
|
207
|
-
getFieldPath(field, secondIndex),
|
|
208
|
-
) as DeepKeys<TFormData>
|
|
209
|
-
|
|
210
|
-
const [meta1, meta2] = [
|
|
211
|
-
formApi.getFieldMeta(fieldKey),
|
|
212
|
-
formApi.getFieldMeta(swappedKey),
|
|
213
|
-
]
|
|
214
|
-
|
|
215
|
-
if (meta1) formApi.setFieldMeta(swappedKey, meta1)
|
|
216
|
-
if (meta2) formApi.setFieldMeta(fieldKey, meta2)
|
|
217
|
-
})
|
|
218
|
-
}
|
|
219
|
-
|
|
220
|
-
return { handleArrayFieldMetaShift }
|
|
221
237
|
}
|
package/src/utils.ts
CHANGED
|
@@ -31,9 +31,9 @@ export function functionalUpdate<TInput, TOutput = TInput>(
|
|
|
31
31
|
* Get a value from an object using a path, including dot notation.
|
|
32
32
|
* @private
|
|
33
33
|
*/
|
|
34
|
-
export function getBy(obj:
|
|
34
|
+
export function getBy(obj: unknown, path: string | (string | number)[]): any {
|
|
35
35
|
const pathObj = makePathArray(path)
|
|
36
|
-
return pathObj.reduce((current: any, pathPart
|
|
36
|
+
return pathObj.reduce((current: any, pathPart) => {
|
|
37
37
|
if (current === null) return null
|
|
38
38
|
if (typeof current !== 'undefined') {
|
|
39
39
|
return current[pathPart]
|
|
@@ -108,7 +108,10 @@ export function deleteBy(obj: any, _path: any) {
|
|
|
108
108
|
|
|
109
109
|
const key = path.shift()
|
|
110
110
|
|
|
111
|
-
if (
|
|
111
|
+
if (
|
|
112
|
+
typeof key === 'string' ||
|
|
113
|
+
(typeof key === 'number' && !Array.isArray(parent))
|
|
114
|
+
) {
|
|
112
115
|
if (typeof parent === 'object') {
|
|
113
116
|
return {
|
|
114
117
|
...parent,
|