{"version":3,"sources":["../../../src/client/app-dir/form.tsx"],"sourcesContent":["'use client'\n\nimport { useCallback, type FormEvent, useContext } from 'react'\nimport { addBasePath } from '../add-base-path'\nimport { useMergedRef } from '../use-merged-ref'\nimport {\n AppRouterContext,\n type AppRouterInstance,\n} from '../../shared/lib/app-router-context.shared-runtime'\nimport {\n checkFormActionUrl,\n createFormSubmitDestinationUrl,\n DISALLOWED_FORM_PROPS,\n hasReactClientActionAttributes,\n hasUnsupportedSubmitterAttributes,\n type FormProps,\n} from '../form-shared'\nimport {\n mountFormInstance,\n unmountPrefetchableInstance,\n} from '../components/links'\nimport { FetchStrategy } from '../components/segment-cache'\n\nexport type { FormProps }\n\nexport default function Form({\n replace,\n scroll,\n prefetch: prefetchProp,\n ref: externalRef,\n ...props\n}: FormProps) {\n const router = useContext(AppRouterContext)\n\n const actionProp = props.action\n const isNavigatingForm = typeof actionProp === 'string'\n\n // Validate `action`\n if (process.env.NODE_ENV === 'development') {\n if (isNavigatingForm) {\n checkFormActionUrl(actionProp, 'action')\n }\n }\n\n // Validate `prefetch`\n if (process.env.NODE_ENV === 'development') {\n if (\n !(\n prefetchProp === undefined ||\n prefetchProp === false ||\n prefetchProp === null\n )\n ) {\n console.error('The `prefetch` prop of
must be `false` or `null`')\n }\n\n if (prefetchProp !== undefined && !isNavigatingForm) {\n console.error(\n 'Passing `prefetch` to a whose `action` is a function has no effect.'\n )\n }\n }\n\n // TODO(runtime-ppr): allow runtime prefetches in Form\n const prefetch =\n prefetchProp === false || prefetchProp === null ? prefetchProp : null\n\n // Validate `scroll` and `replace`\n if (process.env.NODE_ENV === 'development') {\n if (!isNavigatingForm && (replace !== undefined || scroll !== undefined)) {\n console.error(\n 'Passing `replace` or `scroll` to a whose `action` is a function has no effect.\\n' +\n 'See the relevant docs to learn how to control this behavior for navigations triggered from actions:\\n' +\n ' `redirect()` - https://nextjs.org/docs/app/api-reference/functions/redirect#parameters\\n' +\n ' `router.replace()` - https://nextjs.org/docs/app/api-reference/functions/use-router#userouter\\n'\n )\n }\n }\n\n // Clean up any unsupported form props (and warn if present)\n for (const key of DISALLOWED_FORM_PROPS) {\n if (key in props) {\n if (process.env.NODE_ENV === 'development') {\n console.error(\n ` does not support changing \\`${key}\\`. ` +\n (isNavigatingForm\n ? `If you'd like to use it to perform a mutation, consider making \\`action\\` a function instead.\\n` +\n `Learn more: https://nextjs.org/docs/app/building-your-application/data-fetching/server-actions-and-mutations`\n : '')\n )\n }\n delete (props as Record)[key]\n }\n }\n\n const isPrefetchEnabled =\n // if we don't have an action path, we can't prefetch anything.\n !!router && isNavigatingForm && prefetch === null\n\n const observeFormVisibilityOnMount = useCallback(\n (element: HTMLFormElement) => {\n if (isPrefetchEnabled && router !== null) {\n mountFormInstance(\n element,\n actionProp,\n router,\n // We default to PPR. We'll discover whether or not the route supports it with the initial prefetch.\n FetchStrategy.PPR\n )\n }\n return () => {\n unmountPrefetchableInstance(element)\n }\n },\n [isPrefetchEnabled, actionProp, router]\n )\n\n const mergedRef = useMergedRef(\n observeFormVisibilityOnMount,\n externalRef ?? null\n )\n\n if (!isNavigatingForm) {\n return \n }\n\n const actionHref = addBasePath(actionProp)\n\n return (\n \n onFormSubmit(event, {\n router,\n actionHref,\n replace,\n scroll,\n onSubmit: props.onSubmit,\n })\n }\n />\n )\n}\n\nfunction onFormSubmit(\n event: FormEvent,\n {\n actionHref,\n onSubmit,\n replace,\n scroll,\n router,\n }: {\n actionHref: string\n onSubmit: FormProps['onSubmit']\n replace: FormProps['replace']\n scroll: FormProps['scroll']\n router: AppRouterInstance | null\n }\n) {\n if (typeof onSubmit === 'function') {\n onSubmit(event)\n\n // if the user called event.preventDefault(), do nothing.\n // (this matches what Link does for `onClick`)\n if (event.defaultPrevented) {\n return\n }\n }\n\n if (!router) {\n // Form was somehow used outside of the router (but not in pages, the implementation is forked!).\n // We can't perform a soft navigation, so let the native submit handling do its thing.\n return\n }\n\n const formElement = event.currentTarget\n const submitter = (event.nativeEvent as SubmitEvent).submitter\n\n let action = actionHref\n\n if (submitter) {\n if (process.env.NODE_ENV === 'development') {\n // the way server actions are encoded (e.g. `formMethod=\"post\")\n // causes some unnecessary dev-mode warnings from `hasUnsupportedSubmitterAttributes`.\n // we'd bail out anyway, but we just do it silently.\n if (hasReactServerActionAttributes(submitter)) {\n return\n }\n }\n\n if (hasUnsupportedSubmitterAttributes(submitter)) {\n return\n }\n\n // client actions have `formAction=\"javascript:...\"`. We obviously can't prefetch/navigate to that.\n if (hasReactClientActionAttributes(submitter)) {\n return\n }\n\n // If the submitter specified an alternate formAction,\n // use that URL instead -- this is what a native form would do.\n // NOTE: `submitter.formAction` is unreliable, because it will give us `location.href` if it *wasn't* set\n // NOTE: this should not have `basePath` added, because we can't add it before hydration\n const submitterFormAction = submitter.getAttribute('formAction')\n if (submitterFormAction !== null) {\n if (process.env.NODE_ENV === 'development') {\n checkFormActionUrl(submitterFormAction, 'formAction')\n }\n action = submitterFormAction\n }\n }\n\n const targetUrl = createFormSubmitDestinationUrl(action, formElement)\n\n // Finally, no more reasons for bailing out.\n event.preventDefault()\n\n const method = replace ? 'replace' : 'push'\n const targetHref = targetUrl.href\n router[method](targetHref, { scroll })\n}\n\nfunction hasReactServerActionAttributes(submitter: HTMLElement) {\n // https://github.com/facebook/react/blob/942eb80381b96f8410eab1bef1c539bed1ab0eb1/packages/react-client/src/ReactFlightReplyClient.js#L931-L934\n const name = submitter.getAttribute('name')\n return (\n name && (name.startsWith('$ACTION_ID_') || name.startsWith('$ACTION_REF_'))\n )\n}\n"],"names":["Form","replace","scroll","prefetch","prefetchProp","ref","externalRef","props","router","useContext","AppRouterContext","actionProp","action","isNavigatingForm","process","env","NODE_ENV","checkFormActionUrl","undefined","console","error","key","DISALLOWED_FORM_PROPS","isPrefetchEnabled","observeFormVisibilityOnMount","useCallback","element","mountFormInstance","FetchStrategy","PPR","unmountPrefetchableInstance","mergedRef","useMergedRef","form","actionHref","addBasePath","onSubmit","event","onFormSubmit","defaultPrevented","formElement","currentTarget","submitter","nativeEvent","hasReactServerActionAttributes","hasUnsupportedSubmitterAttributes","hasReactClientActionAttributes","submitterFormAction","getAttribute","targetUrl","createFormSubmitDestinationUrl","preventDefault","method","targetHref","href","name","startsWith"],"mappings":"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","ignoreList":[0]}