File size: 5,212 Bytes
fea495a
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
'use client';
import { jsx as _jsx } from "react/jsx-runtime";
import { useContext, forwardRef } from 'react';
import { addBasePath } from './add-base-path';
import { RouterContext } from '../shared/lib/router-context.shared-runtime';
import { checkFormActionUrl, createFormSubmitDestinationUrl, DISALLOWED_FORM_PROPS, hasReactClientActionAttributes, hasUnsupportedSubmitterAttributes } from './form-shared';
const Form = /*#__PURE__*/ forwardRef(function FormComponent(param, ref) {
    let { replace, scroll, prefetch: prefetchProp, ...props } = param;
    const router = useContext(RouterContext);
    const actionProp = props.action;
    const isNavigatingForm = typeof actionProp === 'string';
    // Validate `action`
    if (process.env.NODE_ENV === 'development') {
        if (isNavigatingForm) {
            checkFormActionUrl(actionProp, 'action');
        }
    }
    // Validate `prefetch`
    if (process.env.NODE_ENV === 'development') {
        if (prefetchProp !== undefined) {
            console.error('Passing `prefetch` to a <Form> has no effect in the pages directory.');
        }
    }
    // Validate `scroll` and `replace`
    if (process.env.NODE_ENV === 'development') {
        if (!isNavigatingForm && (replace !== undefined || scroll !== undefined)) {
            console.error('Passing `replace` or `scroll` to a <Form> whose `action` is a function has no effect.\n' + 'See the relevant docs to learn how to control this behavior for navigations triggered from actions:\n' + '  `router.replace()` - https://nextjs.org/docs/pages/api-reference/functions/use-router#routerreplace\n');
        }
    }
    // Clean up any unsupported form props (and warn if present)
    for (const key of DISALLOWED_FORM_PROPS){
        if (key in props) {
            if (process.env.NODE_ENV === 'development') {
                console.error("<Form> does not support changing `" + key + "`.");
            }
            delete props[key];
        }
    }
    if (!isNavigatingForm) {
        return /*#__PURE__*/ _jsx("form", {
            ...props,
            ref: ref
        });
    }
    const actionHref = addBasePath(actionProp);
    return /*#__PURE__*/ _jsx("form", {
        ...props,
        ref: ref,
        action: actionHref,
        onSubmit: (event)=>onFormSubmit(event, {
                router,
                actionHref,
                replace,
                scroll,
                onSubmit: props.onSubmit
            })
    });
});
export default Form;
function onFormSubmit(event, param) {
    let { actionHref, onSubmit, replace, scroll, router } = param;
    if (typeof onSubmit === 'function') {
        onSubmit(event);
        // if the user called event.preventDefault(), do nothing.
        // (this matches what Link does for `onClick`)
        if (event.defaultPrevented) {
            return;
        }
    }
    if (!router) {
        // Form was somehow used outside of the router (but not in app/, the implementation is forked!).
        // We can't perform a soft navigation, so let the native submit handling do its thing.
        return;
    }
    const formElement = event.currentTarget;
    const submitter = event.nativeEvent.submitter;
    let action = actionHref;
    if (submitter) {
        // this is page-router-only, so we don't need to worry about false positives
        // from the attributes that react adds for server actions.
        if (hasUnsupportedSubmitterAttributes(submitter)) {
            return;
        }
        // client actions have `formAction="javascript:..."`. We obviously can't prefetch/navigate to that.
        if (hasReactClientActionAttributes(submitter)) {
            return;
        }
        // If the submitter specified an alternate formAction,
        // use that URL instead -- this is what a native form would do.
        // NOTE: `submitter.formAction` is unreliable, because it will give us `location.href` if it *wasn't* set
        // NOTE: this should not have `basePath` added, because we can't add it before hydration
        const submitterFormAction = submitter.getAttribute('formAction');
        if (submitterFormAction !== null) {
            if (process.env.NODE_ENV === 'development') {
                checkFormActionUrl(submitterFormAction, 'formAction');
            }
            action = submitterFormAction;
        }
    }
    const targetUrl = createFormSubmitDestinationUrl(action, formElement);
    // Finally, no more reasons for bailing out.
    event.preventDefault();
    const method = replace ? 'replace' : 'push';
    const targetHref = targetUrl.href // TODO: will pages router be happy about an absolute URL here?
    ;
    // TODO(form): Make this use a transition so that pending states work
    //
    // Unlike the app router, pages router doesn't use startTransition,
    // and can't easily be wrapped in one because of implementation details
    // (e.g. it doesn't use any react state)
    // But it's important to have this wrapped in a transition because
    // pending states from e.g. `useFormStatus` rely on that.
    // So this needs some follow up work.
    router[method](targetHref, undefined, {
        scroll
    });
}

//# sourceMappingURL=form.js.map