@tanstack/form-core 1.3.4 → 1.4.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 +78 -62
- package/dist/cjs/FieldApi.cjs.map +1 -1
- package/dist/cjs/FieldApi.d.cts +9 -2
- package/dist/cjs/types.d.cts +4 -0
- package/dist/esm/FieldApi.d.ts +9 -2
- package/dist/esm/FieldApi.js +78 -62
- package/dist/esm/FieldApi.js.map +1 -1
- package/dist/esm/types.d.ts +4 -0
- package/package.json +1 -1
- package/src/FieldApi.ts +87 -55
- package/src/types.ts +5 -0
package/src/FieldApi.ts
CHANGED
|
@@ -20,6 +20,7 @@ import type {
|
|
|
20
20
|
FormValidateOrFn,
|
|
21
21
|
} from './FormApi'
|
|
22
22
|
import type {
|
|
23
|
+
ListenerCause,
|
|
23
24
|
UpdateMetaOptions,
|
|
24
25
|
ValidationCause,
|
|
25
26
|
ValidationError,
|
|
@@ -349,7 +350,9 @@ export interface FieldListeners<
|
|
|
349
350
|
TData extends DeepValue<TParentData, TName> = DeepValue<TParentData, TName>,
|
|
350
351
|
> {
|
|
351
352
|
onChange?: FieldListenerFn<TParentData, TName, TData>
|
|
353
|
+
onChangeDebounceMs?: number
|
|
352
354
|
onBlur?: FieldListenerFn<TParentData, TName, TData>
|
|
355
|
+
onBlurDebounceMs?: number
|
|
353
356
|
onMount?: FieldListenerFn<TParentData, TName, TData>
|
|
354
357
|
onSubmit?: FieldListenerFn<TParentData, TName, TData>
|
|
355
358
|
}
|
|
@@ -962,7 +965,10 @@ export class FieldApi<
|
|
|
962
965
|
get state() {
|
|
963
966
|
return this.store.state
|
|
964
967
|
}
|
|
965
|
-
timeoutIds:
|
|
968
|
+
timeoutIds: {
|
|
969
|
+
validations: Record<ValidationCause, ReturnType<typeof setTimeout> | null>
|
|
970
|
+
listeners: Record<ListenerCause, ReturnType<typeof setTimeout> | null>
|
|
971
|
+
}
|
|
966
972
|
|
|
967
973
|
/**
|
|
968
974
|
* Initializes a new `FieldApi` instance.
|
|
@@ -992,7 +998,10 @@ export class FieldApi<
|
|
|
992
998
|
) {
|
|
993
999
|
this.form = opts.form as never
|
|
994
1000
|
this.name = opts.name as never
|
|
995
|
-
this.timeoutIds = {
|
|
1001
|
+
this.timeoutIds = {
|
|
1002
|
+
validations: {} as Record<ValidationCause, never>,
|
|
1003
|
+
listeners: {} as Record<ListenerCause, never>,
|
|
1004
|
+
}
|
|
996
1005
|
|
|
997
1006
|
this.store = new Derived({
|
|
998
1007
|
deps: [this.form.store],
|
|
@@ -1175,10 +1184,7 @@ export class FieldApi<
|
|
|
1175
1184
|
setValue = (updater: Updater<TData>, options?: UpdateMetaOptions) => {
|
|
1176
1185
|
this.form.setFieldValue(this.name, updater as never, options)
|
|
1177
1186
|
|
|
1178
|
-
this.
|
|
1179
|
-
value: this.state.value,
|
|
1180
|
-
fieldApi: this,
|
|
1181
|
-
})
|
|
1187
|
+
this.triggerOnChangeListener()
|
|
1182
1188
|
|
|
1183
1189
|
this.validate('change')
|
|
1184
1190
|
}
|
|
@@ -1226,10 +1232,7 @@ export class FieldApi<
|
|
|
1226
1232
|
) => {
|
|
1227
1233
|
this.form.pushFieldValue(this.name, value as any, opts)
|
|
1228
1234
|
|
|
1229
|
-
this.
|
|
1230
|
-
value: this.state.value,
|
|
1231
|
-
fieldApi: this,
|
|
1232
|
-
})
|
|
1235
|
+
this.triggerOnChangeListener()
|
|
1233
1236
|
}
|
|
1234
1237
|
|
|
1235
1238
|
/**
|
|
@@ -1242,10 +1245,7 @@ export class FieldApi<
|
|
|
1242
1245
|
) => {
|
|
1243
1246
|
this.form.insertFieldValue(this.name, index, value as any, opts)
|
|
1244
1247
|
|
|
1245
|
-
this.
|
|
1246
|
-
value: this.state.value,
|
|
1247
|
-
fieldApi: this,
|
|
1248
|
-
})
|
|
1248
|
+
this.triggerOnChangeListener()
|
|
1249
1249
|
}
|
|
1250
1250
|
|
|
1251
1251
|
/**
|
|
@@ -1258,10 +1258,7 @@ export class FieldApi<
|
|
|
1258
1258
|
) => {
|
|
1259
1259
|
this.form.replaceFieldValue(this.name, index, value as any, opts)
|
|
1260
1260
|
|
|
1261
|
-
this.
|
|
1262
|
-
value: this.state.value,
|
|
1263
|
-
fieldApi: this,
|
|
1264
|
-
})
|
|
1261
|
+
this.triggerOnChangeListener()
|
|
1265
1262
|
}
|
|
1266
1263
|
|
|
1267
1264
|
/**
|
|
@@ -1270,10 +1267,7 @@ export class FieldApi<
|
|
|
1270
1267
|
removeValue = (index: number, opts?: UpdateMetaOptions) => {
|
|
1271
1268
|
this.form.removeFieldValue(this.name, index, opts)
|
|
1272
1269
|
|
|
1273
|
-
this.
|
|
1274
|
-
value: this.state.value,
|
|
1275
|
-
fieldApi: this,
|
|
1276
|
-
})
|
|
1270
|
+
this.triggerOnChangeListener()
|
|
1277
1271
|
}
|
|
1278
1272
|
|
|
1279
1273
|
/**
|
|
@@ -1282,10 +1276,7 @@ export class FieldApi<
|
|
|
1282
1276
|
swapValues = (aIndex: number, bIndex: number, opts?: UpdateMetaOptions) => {
|
|
1283
1277
|
this.form.swapFieldValues(this.name, aIndex, bIndex, opts)
|
|
1284
1278
|
|
|
1285
|
-
this.
|
|
1286
|
-
value: this.state.value,
|
|
1287
|
-
fieldApi: this,
|
|
1288
|
-
})
|
|
1279
|
+
this.triggerOnChangeListener()
|
|
1289
1280
|
}
|
|
1290
1281
|
|
|
1291
1282
|
/**
|
|
@@ -1294,10 +1285,7 @@ export class FieldApi<
|
|
|
1294
1285
|
moveValue = (aIndex: number, bIndex: number, opts?: UpdateMetaOptions) => {
|
|
1295
1286
|
this.form.moveFieldValues(this.name, aIndex, bIndex, opts)
|
|
1296
1287
|
|
|
1297
|
-
this.
|
|
1298
|
-
value: this.state.value,
|
|
1299
|
-
fieldApi: this,
|
|
1300
|
-
})
|
|
1288
|
+
this.triggerOnChangeListener()
|
|
1301
1289
|
}
|
|
1302
1290
|
|
|
1303
1291
|
/**
|
|
@@ -1502,29 +1490,32 @@ export class FieldApi<
|
|
|
1502
1490
|
let rawError!: ValidationError | undefined
|
|
1503
1491
|
try {
|
|
1504
1492
|
rawError = await new Promise((rawResolve, rawReject) => {
|
|
1505
|
-
if (this.timeoutIds[validateObj.cause]) {
|
|
1506
|
-
clearTimeout(this.timeoutIds[validateObj.cause]!)
|
|
1493
|
+
if (this.timeoutIds.validations[validateObj.cause]) {
|
|
1494
|
+
clearTimeout(this.timeoutIds.validations[validateObj.cause]!)
|
|
1507
1495
|
}
|
|
1508
1496
|
|
|
1509
|
-
this.timeoutIds[validateObj.cause] = setTimeout(
|
|
1510
|
-
|
|
1511
|
-
|
|
1512
|
-
|
|
1513
|
-
|
|
1514
|
-
|
|
1515
|
-
|
|
1516
|
-
value:
|
|
1517
|
-
|
|
1518
|
-
|
|
1519
|
-
|
|
1520
|
-
|
|
1521
|
-
|
|
1522
|
-
|
|
1523
|
-
|
|
1524
|
-
|
|
1525
|
-
|
|
1526
|
-
|
|
1527
|
-
|
|
1497
|
+
this.timeoutIds.validations[validateObj.cause] = setTimeout(
|
|
1498
|
+
async () => {
|
|
1499
|
+
if (controller.signal.aborted) return rawResolve(undefined)
|
|
1500
|
+
try {
|
|
1501
|
+
rawResolve(
|
|
1502
|
+
await this.runValidator({
|
|
1503
|
+
validate: validateObj.validate,
|
|
1504
|
+
value: {
|
|
1505
|
+
value: field.store.state.value,
|
|
1506
|
+
fieldApi: field,
|
|
1507
|
+
signal: controller.signal,
|
|
1508
|
+
validationSource: 'field',
|
|
1509
|
+
},
|
|
1510
|
+
type: 'validateAsync',
|
|
1511
|
+
}),
|
|
1512
|
+
)
|
|
1513
|
+
} catch (e) {
|
|
1514
|
+
rawReject(e)
|
|
1515
|
+
}
|
|
1516
|
+
},
|
|
1517
|
+
validateObj.debounceMs,
|
|
1518
|
+
)
|
|
1528
1519
|
})
|
|
1529
1520
|
} catch (e: unknown) {
|
|
1530
1521
|
rawError = e as ValidationError
|
|
@@ -1633,10 +1624,7 @@ export class FieldApi<
|
|
|
1633
1624
|
}
|
|
1634
1625
|
this.validate('blur')
|
|
1635
1626
|
|
|
1636
|
-
this.
|
|
1637
|
-
value: this.state.value,
|
|
1638
|
-
fieldApi: this,
|
|
1639
|
-
})
|
|
1627
|
+
this.triggerOnBlurListener()
|
|
1640
1628
|
}
|
|
1641
1629
|
|
|
1642
1630
|
/**
|
|
@@ -1654,6 +1642,50 @@ export class FieldApi<
|
|
|
1654
1642
|
}) as never,
|
|
1655
1643
|
)
|
|
1656
1644
|
}
|
|
1645
|
+
|
|
1646
|
+
private triggerOnBlurListener() {
|
|
1647
|
+
const debounceMs = this.options.listeners?.onBlurDebounceMs
|
|
1648
|
+
|
|
1649
|
+
if (debounceMs && debounceMs > 0) {
|
|
1650
|
+
if (this.timeoutIds.listeners.blur) {
|
|
1651
|
+
clearTimeout(this.timeoutIds.listeners.blur)
|
|
1652
|
+
}
|
|
1653
|
+
|
|
1654
|
+
this.timeoutIds.listeners.blur = setTimeout(() => {
|
|
1655
|
+
this.options.listeners?.onBlur?.({
|
|
1656
|
+
value: this.state.value,
|
|
1657
|
+
fieldApi: this,
|
|
1658
|
+
})
|
|
1659
|
+
}, debounceMs)
|
|
1660
|
+
} else {
|
|
1661
|
+
this.options.listeners?.onBlur?.({
|
|
1662
|
+
value: this.state.value,
|
|
1663
|
+
fieldApi: this,
|
|
1664
|
+
})
|
|
1665
|
+
}
|
|
1666
|
+
}
|
|
1667
|
+
|
|
1668
|
+
private triggerOnChangeListener() {
|
|
1669
|
+
const debounceMs = this.options.listeners?.onChangeDebounceMs
|
|
1670
|
+
|
|
1671
|
+
if (debounceMs && debounceMs > 0) {
|
|
1672
|
+
if (this.timeoutIds.listeners.change) {
|
|
1673
|
+
clearTimeout(this.timeoutIds.listeners.change)
|
|
1674
|
+
}
|
|
1675
|
+
|
|
1676
|
+
this.timeoutIds.listeners.change = setTimeout(() => {
|
|
1677
|
+
this.options.listeners?.onChange?.({
|
|
1678
|
+
value: this.state.value,
|
|
1679
|
+
fieldApi: this,
|
|
1680
|
+
})
|
|
1681
|
+
}, debounceMs)
|
|
1682
|
+
} else {
|
|
1683
|
+
this.options.listeners?.onChange?.({
|
|
1684
|
+
value: this.state.value,
|
|
1685
|
+
fieldApi: this,
|
|
1686
|
+
})
|
|
1687
|
+
}
|
|
1688
|
+
}
|
|
1657
1689
|
}
|
|
1658
1690
|
|
|
1659
1691
|
function normalizeError(rawError?: ValidationError) {
|
package/src/types.ts
CHANGED
|
@@ -10,6 +10,11 @@ export type ValidationSource = 'form' | 'field'
|
|
|
10
10
|
*/
|
|
11
11
|
export type ValidationCause = 'change' | 'blur' | 'submit' | 'mount' | 'server'
|
|
12
12
|
|
|
13
|
+
/**
|
|
14
|
+
* @private
|
|
15
|
+
*/
|
|
16
|
+
export type ListenerCause = 'change' | 'blur' | 'submit' | 'mount'
|
|
17
|
+
|
|
13
18
|
/**
|
|
14
19
|
* @private
|
|
15
20
|
*/
|