Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

@tanstack/form-core

Package Overview
Dependencies
Maintainers
2
Versions
103
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@tanstack/form-core - npm Package Compare versions

Comparing version 0.0.11 to 0.0.12

build/lib/_virtual/_rollupPluginBabelHelpers.cjs

31

package.json
{
"name": "@tanstack/form-core",
"version": "0.0.11",
"version": "0.0.12",
"description": "Powerful, type-safe, framework agnostic forms.",

@@ -13,8 +13,18 @@ "author": "tannerlinsley",

},
"types": "build/types/index.d.ts",
"main": "build/cjs/index.js",
"module": "build/esm/index.js",
"type": "module",
"types": "build/lib/index.d.ts",
"main": "build/lib/index.legacy.cjs",
"module": "build/lib/index.legacy.js",
"exports": {
".": {
"types": "./build/lib/index.d.ts",
"import": "./build/lib/index.js",
"require": "./build/lib/index.cjs",
"default": "./build/lib/index.cjs"
},
"./package.json": "./package.json"
},
"sideEffects": false,
"files": [
"build/**",
"build/lib/*",
"src"

@@ -26,9 +36,12 @@ ],

"scripts": {
"clean": "rimraf ./build",
"clean": "rimraf ./build && rimraf ./coverage",
"test:eslint": "eslint --ext .ts,.tsx ./src",
"test:types": "tsc",
"test:lib": "jest --config ./jest.config.ts",
"test:types": "tsc --noEmit && vitest typecheck",
"test:lib": "vitest run --coverage",
"test:lib:dev": "pnpm run test:lib --watch",
"build:types": "tsc --build"
"test:build": "publint --strict",
"build": "pnpm build:rollup && pnpm build:types",
"build:rollup": "rollup --config rollup.config.js",
"build:types": "tsc --emitDeclarationOnly"
}
}

@@ -1,3 +0,2 @@

//
import type { DeepKeys, DeepValue, RequiredByKey, Updater } from './utils'
import type { DeepKeys, DeepValue, Updater } from './utils'
import type { FormApi, ValidationError } from './FormApi'

@@ -18,4 +17,16 @@ import { Store } from '@tanstack/store'

export interface FieldOptions<TData, TFormData> {
name: unknown extends TFormData ? string : DeepKeys<TFormData>
export interface FieldOptions<
_TData,
TFormData,
/**
* This allows us to restrict the name to only be a valid field name while
* also assigning it to a generic
*/
TName = unknown extends TFormData ? string : DeepKeys<TFormData>,
/**
* If TData is unknown, we can use the TName generic to determine the type
*/
TData = unknown extends _TData ? DeepValue<TFormData, TName> : _TData,
> {
name: TName
index?: TData extends any[] ? number : never

@@ -66,4 +77,4 @@ defaultValue?: TData

export type InputProps = {
value: string
export type InputProps<T> = {
value: T
onChange: (event: any) => void

@@ -80,2 +91,13 @@ onBlur: (event: any) => void

/**
* TData may not be known at the time of FieldApi construction, so we need to
* use a conditional type to determine if TData is known or not.
*
* If TData is not known, we use the TFormData type to determine the type of
* the field value based on the field name.
*/
type GetTData<Name, TData, TFormData> = unknown extends TData
? DeepValue<TFormData, Name>
: TData
export class FieldApi<TData, TFormData> {

@@ -85,6 +107,14 @@ uid: number

name!: DeepKeys<TFormData>
store!: Store<FieldState<TData>>
state!: FieldState<TData>
#prevState!: FieldState<TData>
options: FieldOptions<TData, TFormData> = {} as any
/**
* This is a hack that allows us to use `GetTData` without calling it everywhere
*
* Unfortunately this hack appears to be needed alongside the `TName` hack
* further up in this file. This properly types all of the internal methods,
* while the `TName` hack types the options properly
*/
_tdata!: GetTData<typeof this.name, TData, TFormData>
store!: Store<FieldState<typeof this._tdata>>
state!: FieldState<typeof this._tdata>
prevState!: FieldState<typeof this._tdata>
options: FieldOptions<typeof this._tdata, TFormData> = {} as any

@@ -102,3 +132,3 @@ constructor(opts: FieldApiOptions<TData, TFormData>) {

this.store = new Store<FieldState<TData>>(
this.store = new Store<FieldState<typeof this._tdata>>(
{

@@ -121,7 +151,3 @@ value: this.getValue(),

if (state.value !== this.#prevState.value) {
this.validate('change', state.value)
}
this.#prevState = state
this.prevState = state
this.state = state

@@ -133,4 +159,4 @@ },

this.state = this.store.state
this.#prevState = this.state
this.update(opts)
this.prevState = this.state
this.update(opts as never)
}

@@ -157,3 +183,3 @@

this.options.onMount?.(this)
this.options.onMount?.(this as never)

@@ -169,3 +195,3 @@ return () => {

update = (opts: FieldApiOptions<TData, TFormData>) => {
update = (opts: FieldApiOptions<typeof this._tdata, TFormData>) => {
this.options = {

@@ -176,10 +202,20 @@ asyncDebounceMs: this.form.options.asyncDebounceMs ?? 0,

...opts,
}
} as never
// Default Value
if (
this.state.value === undefined &&
this.options.defaultValue !== undefined
) {
this.setValue(this.options.defaultValue)
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
if (this.state.value === undefined) {
if (this.options.defaultValue !== undefined) {
this.setValue(this.options.defaultValue as never)
} else if (
opts.form.options.defaultValues?.[
this.options.name as keyof TFormData
] !== undefined
) {
this.setValue(
opts.form.options.defaultValues[
this.options.name as keyof TFormData
] as never,
)
}
}

@@ -194,11 +230,16 @@

getValue = (): TData => {
getValue = (): typeof this._tdata => {
return this.form.getFieldValue(this.name)
}
setValue = (
updater: Updater<TData>,
updater: Updater<typeof this._tdata>,
options?: { touch?: boolean; notify?: boolean },
) => this.form.setFieldValue(this.name, updater as any, options)
) => {
this.form.setFieldValue(this.name, updater as never, options)
this.validate('change', this.state.value)
}
getMeta = (): FieldMeta => this.form.getFieldMeta(this.name)
setMeta = (updater: Updater<FieldMeta>) =>

@@ -209,17 +250,27 @@ this.form.setFieldMeta(this.name, updater)

pushValue = (value: TData extends any[] ? TData[number] : never) =>
this.form.pushFieldValue(this.name, value as any)
insertValue = (index: number, value: TData) =>
this.form.insertFieldValue(this.name, index, value as any)
pushValue = (
value: typeof this._tdata extends any[]
? (typeof this._tdata)[number]
: never,
) => this.form.pushFieldValue(this.name, value as any)
insertValue = (
index: number,
value: typeof this._tdata extends any[]
? (typeof this._tdata)[number]
: never,
) => this.form.insertFieldValue(this.name, index, value as any)
removeValue = (index: number) => this.form.removeFieldValue(this.name, index)
swapValues = (aIndex: number, bIndex: number) =>
this.form.swapFieldValues(this.name, aIndex, bIndex)
getSubField = <TName extends DeepKeys<TData>>(name: TName) =>
new FieldApi<DeepValue<TData, TName>, TFormData>({
name: `${this.name}.${name}` as any,
getSubField = <TName extends DeepKeys<typeof this._tdata>>(name: TName) =>
new FieldApi<DeepValue<typeof this._tdata, TName>, TFormData>({
name: `${this.name}.${name}` as never,
form: this.form,
})
validateSync = async (value = this.state.value, cause: ValidationCause) => {
validateSync = (value = this.state.value, cause: ValidationCause) => {
const { onChange, onBlur } = this.options

@@ -235,3 +286,3 @@ const validate =

this.getInfo().validationCount = validationCount
const error = normalizeError(validate(value, this))
const error = normalizeError(validate(value as never, this as never))

@@ -319,3 +370,3 @@ if (this.state.meta.error !== error) {

try {
const rawError = await validate(value, this)
const rawError = await validate(value as never, this as never)

@@ -350,3 +401,3 @@ if (checkLatest()) {

cause: ValidationCause,
value?: TData,
value?: typeof this._tdata,
): ValidationError | Promise<ValidationError> => {

@@ -372,3 +423,4 @@ // If the field is pristine and validatePristine is false, do not validate

props: T = {} as T,
): ChangeProps<TData> & Omit<T, keyof ChangeProps<TData>> => {
): ChangeProps<typeof this._tdata> &
Omit<T, keyof ChangeProps<typeof this._tdata>> => {
return {

@@ -378,3 +430,3 @@ ...props,

onChange: (value) => {
this.setValue(value)
this.setValue(value as never)
props.onChange?.(value)

@@ -390,3 +442,4 @@ },

},
} as ChangeProps<TData> & Omit<T, keyof ChangeProps<TData>>
} as ChangeProps<typeof this._tdata> &
Omit<T, keyof ChangeProps<typeof this._tdata>>
}

@@ -396,6 +449,7 @@

props: T = {} as T,
): InputProps & Omit<T, keyof InputProps> => {
): InputProps<typeof this._tdata> &
Omit<T, keyof InputProps<typeof this._tdata>> => {
return {
...props,
value: String(this.state.value),
value: this.state.value,
onChange: (e) => {

@@ -406,3 +460,4 @@ this.setValue(e.target.value)

onBlur: this.getChangeProps(props).onBlur,
}
} as InputProps<typeof this._tdata> &
Omit<T, keyof InputProps<typeof this._tdata>>
}

@@ -409,0 +464,0 @@ }

@@ -167,15 +167,29 @@ import { Store } from '@tanstack/store'

this.store.batch(() => {
if (
options.defaultState &&
const shouldUpdateValues =
options.defaultValues &&
options.defaultValues !== this.options.defaultValues
const shouldUpdateState =
options.defaultState !== this.options.defaultState
) {
this.store.setState((prev) => ({
...prev,
...options.defaultState,
}))
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
if (!shouldUpdateValues || !shouldUpdateValues) {
return
}
if (options.defaultValues !== this.options.defaultValues) {
this.store.setState(() => getDefaultFormState(options.defaultValues!))
}
this.store.setState(() =>
getDefaultFormState(
Object.assign(
{},
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
shouldUpdateState ? options.defaultState : {},
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
shouldUpdateValues
? {
values: options.defaultValues,
}
: {},
),
),
)
})

@@ -187,3 +201,8 @@

reset = () =>
this.store.setState(() => getDefaultFormState(this.options.defaultValues!))
this.store.setState(() =>
getDefaultFormState({
...this.options.defaultState,
values: this.options.defaultValues ?? this.options.defaultState?.values,
}),
)

@@ -286,2 +305,3 @@ validateAllFields = async (cause: ValidationCause) => {

getFieldInfo = <TField extends DeepKeys<TFormData>>(field: TField) => {
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
return (this.fieldInfo[field] ||= {

@@ -333,3 +353,3 @@ instances: {},

field: TField,
value: DeepValue<TFormData, TField>,
value: DeepValue<TFormData, TField>[number],
opts?: { touch?: boolean },

@@ -347,3 +367,3 @@ ) => {

index: number,
value: DeepValue<TFormData, TField>,
value: DeepValue<TFormData, TField>[number],
opts?: { touch?: boolean },

@@ -386,5 +406,5 @@ ) => {

const prev2 = prev[index2]!
return setBy(setBy(prev, [index1], prev2), [index2], prev1)
return setBy(setBy(prev, `${index1}`, prev2), `${index2}`, prev1)
})
}
}

@@ -16,2 +16,5 @@ export type UpdaterFn<TInput, TOutput = TInput> = (input: TInput) => TOutput

/**
* Get a value from an object using a path, including dot notation.
*/
export function getBy(obj: any, path: any) {

@@ -28,2 +31,5 @@ const pathArray = makePathArray(path)

/**
* Set a value on an object using a path, including dot notation.
*/
export function setBy(obj: any, _path: any, updater: Updater<any>) {

@@ -80,3 +86,3 @@ const path = makePathArray(_path)

if (typeof str !== 'string') {
throw new Error()
throw new Error('Path must be a string.')
}

@@ -165,1 +171,4 @@

type Try<A1, A2, Catch = never> = A1 extends A2 ? A1 : Catch
// Hack to get TypeScript to show simplified types in error messages
export type Pretty<T> = { [K in keyof T]: T[K] } & {}
SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc