Home / File/ Form.tsx — astro Source File

Form.tsx — astro Source File

Architecture documentation for Form.tsx, a tsx file in the astro codebase. 3 imports, 1 dependents.

File tsx CoreAstro RenderingEngine 3 imports 1 dependents 4 functions

Entity Profile

Dependency Diagram

graph LR
  6986db32_b74e_37a6_ff49_3275e975c4fb["Form.tsx"]
  2bb760ca_2c60_fa41_0d3c_8cc857eec5ac["client"]
  6986db32_b74e_37a6_ff49_3275e975c4fb --> 2bb760ca_2c60_fa41_0d3c_8cc857eec5ac
  c2e57772_bac6_7f43_6c14_f859a976c049["simple:form"]
  6986db32_b74e_37a6_ff49_3275e975c4fb --> c2e57772_bac6_7f43_6c14_f859a976c049
  d9988dd0_c044_f9d2_85cd_a31a0a2bdf80["react"]
  6986db32_b74e_37a6_ff49_3275e975c4fb --> d9988dd0_c044_f9d2_85cd_a31a0a2bdf80
  a5929905_a7c2_240f_3079_bacf2ad2ad3d["_Ticket.tsx"]
  a5929905_a7c2_240f_3079_bacf2ad2ad3d --> 6986db32_b74e_37a6_ff49_3275e975c4fb
  style 6986db32_b74e_37a6_ff49_3275e975c4fb fill:#6366f1,stroke:#818cf8,color:#fff

Relationship Graph

Source Code

// Generated by simple:form

import { navigate } from 'astro:transitions/client';
import {
	type FieldErrors,
	type FormState,
	type FormValidator,
	formNameInputProps,
	getInitialFormState,
	toSetValidationErrors,
	toTrackAstroSubmitStatus,
	toValidateField,
	validateForm,
} from 'simple:form';
import { type ComponentProps, createContext, useContext, useState } from 'react';

export function useCreateFormContext(validator: FormValidator, fieldErrors?: FieldErrors) {
	const initial = getInitialFormState({ validator, fieldErrors });
	const [formState, setFormState] = useState<FormState>(initial);
	return {
		value: formState,
		set: setFormState,
		setValidationErrors: toSetValidationErrors(setFormState),
		validateField: toValidateField(setFormState),
		trackAstroSubmitStatus: toTrackAstroSubmitStatus(setFormState),
	};
}

export function useFormContext() {
	const formContext = useContext(FormContext);
	if (!formContext) {
		throw new Error(
			'Form context not found. `useFormContext()` should only be called from children of a <Form> component.'
		);
	}
	return formContext;
}

type FormContextType = ReturnType<typeof useCreateFormContext>;

const FormContext = createContext<FormContextType | undefined>(undefined);

export function Form({
	children,
	validator,
	context,
	fieldErrors,
	name,
	...formProps
}: {
	validator: FormValidator;
	context?: FormContextType;
	fieldErrors?: FieldErrors;
} & Omit<ComponentProps<'form'>, 'method' | 'onSubmit'>) {
	const formContext = context ?? useCreateFormContext(validator, fieldErrors);

	return (
		<FormContext.Provider value={formContext}>
			<form
				{...formProps}
				method="POST"
				onSubmit={async (e) => {
					e.preventDefault();
					e.stopPropagation();
					const formData = new FormData(e.currentTarget);
					formContext.set((formState) => ({
						...formState,
						isSubmitPending: true,
						submitStatus: 'validating',
					}));
					const parsed = await validateForm({ formData, validator });
					if (parsed.data) {
						navigate(formProps.action ?? '', { formData });
						return formContext.trackAstroSubmitStatus();
					}

					formContext.setValidationErrors(parsed.fieldErrors);
				}}
			>
				{name ? <input {...formNameInputProps} value={name} /> : null}
				{children}
			</form>
		</FormContext.Provider>
	);
}

export function Input(inputProps: ComponentProps<'input'> & { name: string }) {
	const formContext = useFormContext();
	const fieldState = formContext.value.fields[inputProps.name];
	if (!fieldState) {
		throw new Error(
			`Input "${inputProps.name}" not found in form. Did you use the <Form> component?`
		);
	}

	const { hasErroredOnce, validationErrors, validator } = fieldState;
	return (
		<>
			<input
				onBlur={async (e) => {
					const value = e.target.value;
					if (value === '') return;
					formContext.validateField(inputProps.name, value, validator);
				}}
				onChange={async (e) => {
					if (!hasErroredOnce) return;
					const value = e.target.value;
					formContext.validateField(inputProps.name, value, validator);
				}}
				{...inputProps}
			/>
			{validationErrors?.map((e) => (
				<p className="error" key={e}>
					{e}
				</p>
			))}
		</>
	);
}

Domain

Subdomains

Dependencies

  • client
  • react
  • simple:form

Frequently Asked Questions

What does Form.tsx do?
Form.tsx is a source file in the astro codebase, written in tsx. It belongs to the CoreAstro domain, RenderingEngine subdomain.
What functions are defined in Form.tsx?
Form.tsx defines 4 function(s): Form, Input, useCreateFormContext, useFormContext.
What does Form.tsx depend on?
Form.tsx imports 3 module(s): client, react, simple:form.
What files import Form.tsx?
Form.tsx is imported by 1 file(s): _Ticket.tsx.
Where is Form.tsx in the architecture?
Form.tsx is located at packages/db/test/fixtures/ticketing-example/src/components/Form.tsx (domain: CoreAstro, subdomain: RenderingEngine, directory: packages/db/test/fixtures/ticketing-example/src/components).

Analyze Your Own Codebase

Get architecture documentation, dependency graphs, and domain analysis for your codebase in minutes.

Try Supermodel Free