+
+ {errors.map((error, i) => renderError(error, i))}
+
+
+ )
+}
+
+/**
+ * Focus the first invalid field in the form.
+ * @param {object} form - The form object returned by useForm
+ */
+export function focusFirstError(form) {
+ const errorFields = findAllErrorFields(form)
+ const sortedFields = errorFields.sort(byDomOrder)
+ const firstErrorField = getFirstItem(sortedFields)
+
+ firstErrorField?.ref.current?.focus()
+}
+
+function findAllErrorFields(field) {
+ const state = field.state.get()
+
+ if (field.type === 'basic' && state.error && field.ref?.current) return [field]
+
+ return [
+ ...(field.fields ? Object.values(field.fields) : []),
+ ...(state.children || [])
+ ].flatMap(findAllErrorFields)
+}
+
+function byDomOrder(a, b) {
+ const nodeA = a.ref.current
+ const nodeB = b.ref.current
+ if (!nodeA || !nodeB) return 0
+ return nodeAPrecedesNodeB(nodeA, nodeB) ? -1 : 1
+}
+
+function nodeAPrecedesNodeB(nodeA, nodeB) {
+ return nodeB.compareDocumentPosition(nodeA) & Node.DOCUMENT_POSITION_PRECEDING
+}
+
+function getFirstItem(array) {
+ return array?.[0] ?? undefined
+}
+
+function flattenErrors(errorTree) {
+ if (!errorTree) return []
+
+ if (typeof errorTree !== 'object' || (!errorTree.self && !errorTree.children)) {
+ return errorTree ? [errorTree] : []
+ }
+
+ const selfErrors = errorTree.self ? [errorTree.self] : []
+ const childErrors = errorTree.children
+ ? Object.values(errorTree.children).flatMap(flattenErrors)
+ : []
+
+ return [...selfErrors, ...childErrors]
+}
+
+function defaultRenderError(error, key) {
+ return