Spaces:
Sleeping
Sleeping
File size: 7,506 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 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 | 'use client';
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
Object.defineProperty(exports, "default", {
enumerable: true,
get: function() {
return Form;
}
});
const _jsxruntime = require("react/jsx-runtime");
const _react = require("react");
const _addbasepath = require("../add-base-path");
const _usemergedref = require("../use-merged-ref");
const _approutercontextsharedruntime = require("../../shared/lib/app-router-context.shared-runtime");
const _formshared = require("../form-shared");
const _links = require("../components/links");
const _segmentcache = require("../components/segment-cache");
function Form(param) {
let { replace, scroll, prefetch: prefetchProp, ref: externalRef, ...props } = param;
const router = (0, _react.useContext)(_approutercontextsharedruntime.AppRouterContext);
const actionProp = props.action;
const isNavigatingForm = typeof actionProp === 'string';
// Validate `action`
if (process.env.NODE_ENV === 'development') {
if (isNavigatingForm) {
(0, _formshared.checkFormActionUrl)(actionProp, 'action');
}
}
// Validate `prefetch`
if (process.env.NODE_ENV === 'development') {
if (!(prefetchProp === undefined || prefetchProp === false || prefetchProp === null)) {
console.error('The `prefetch` prop of <Form> must be `false` or `null`');
}
if (prefetchProp !== undefined && !isNavigatingForm) {
console.error('Passing `prefetch` to a <Form> whose `action` is a function has no effect.');
}
}
// TODO(runtime-ppr): allow runtime prefetches in Form
const prefetch = prefetchProp === false || prefetchProp === null ? prefetchProp : null;
// 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' + ' `redirect()` - https://nextjs.org/docs/app/api-reference/functions/redirect#parameters\n' + ' `router.replace()` - https://nextjs.org/docs/app/api-reference/functions/use-router#userouter\n');
}
}
// Clean up any unsupported form props (and warn if present)
for (const key of _formshared.DISALLOWED_FORM_PROPS){
if (key in props) {
if (process.env.NODE_ENV === 'development') {
console.error("<Form> does not support changing `" + key + "`. " + (isNavigatingForm ? "If you'd like to use it to perform a mutation, consider making `action` a function instead.\n" + "Learn more: https://nextjs.org/docs/app/building-your-application/data-fetching/server-actions-and-mutations" : ''));
}
delete props[key];
}
}
const isPrefetchEnabled = // if we don't have an action path, we can't prefetch anything.
!!router && isNavigatingForm && prefetch === null;
const observeFormVisibilityOnMount = (0, _react.useCallback)((element)=>{
if (isPrefetchEnabled && router !== null) {
(0, _links.mountFormInstance)(element, actionProp, router, // We default to PPR. We'll discover whether or not the route supports it with the initial prefetch.
_segmentcache.FetchStrategy.PPR);
}
return ()=>{
(0, _links.unmountPrefetchableInstance)(element);
};
}, [
isPrefetchEnabled,
actionProp,
router
]);
const mergedRef = (0, _usemergedref.useMergedRef)(observeFormVisibilityOnMount, externalRef != null ? externalRef : null);
if (!isNavigatingForm) {
return /*#__PURE__*/ (0, _jsxruntime.jsx)("form", {
...props,
ref: mergedRef
});
}
const actionHref = (0, _addbasepath.addBasePath)(actionProp);
return /*#__PURE__*/ (0, _jsxruntime.jsx)("form", {
...props,
ref: mergedRef,
action: actionHref,
onSubmit: (event)=>onFormSubmit(event, {
router,
actionHref,
replace,
scroll,
onSubmit: props.onSubmit
})
});
}
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 pages, 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) {
if (process.env.NODE_ENV === 'development') {
// the way server actions are encoded (e.g. `formMethod="post")
// causes some unnecessary dev-mode warnings from `hasUnsupportedSubmitterAttributes`.
// we'd bail out anyway, but we just do it silently.
if (hasReactServerActionAttributes(submitter)) {
return;
}
}
if ((0, _formshared.hasUnsupportedSubmitterAttributes)(submitter)) {
return;
}
// client actions have `formAction="javascript:..."`. We obviously can't prefetch/navigate to that.
if ((0, _formshared.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') {
(0, _formshared.checkFormActionUrl)(submitterFormAction, 'formAction');
}
action = submitterFormAction;
}
}
const targetUrl = (0, _formshared.createFormSubmitDestinationUrl)(action, formElement);
// Finally, no more reasons for bailing out.
event.preventDefault();
const method = replace ? 'replace' : 'push';
const targetHref = targetUrl.href;
router[method](targetHref, {
scroll
});
}
function hasReactServerActionAttributes(submitter) {
// https://github.com/facebook/react/blob/942eb80381b96f8410eab1bef1c539bed1ab0eb1/packages/react-client/src/ReactFlightReplyClient.js#L931-L934
const name = submitter.getAttribute('name');
return name && (name.startsWith('$ACTION_ID_') || name.startsWith('$ACTION_REF_'));
}
if ((typeof exports.default === 'function' || (typeof exports.default === 'object' && exports.default !== null)) && typeof exports.default.__esModule === 'undefined') {
Object.defineProperty(exports.default, '__esModule', { value: true });
Object.assign(exports.default, exports);
module.exports = exports.default;
}
//# sourceMappingURL=form.js.map |