next 15.2.0-canary.75 → 15.2.0-canary.76
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of next might be problematic. Click here for more details.
- package/dist/bin/next +1 -1
- package/dist/build/index.js +2 -2
- package/dist/build/swc/index.js +1 -1
- package/dist/build/webpack-config.js +2 -2
- package/dist/client/app-bootstrap.js +1 -1
- package/dist/client/app-dir/form.d.ts +2 -43
- package/dist/client/app-dir/form.js +20 -144
- package/dist/client/app-dir/form.js.map +1 -1
- package/dist/client/components/react-dev-overlay/shared.d.ts +2 -0
- package/dist/client/components/react-dev-overlay/shared.js +10 -0
- package/dist/client/components/react-dev-overlay/shared.js.map +1 -1
- package/dist/client/components/react-dev-overlay/ui/components/call-stack-frame/call-stack-frame.d.ts +1 -1
- package/dist/client/components/react-dev-overlay/ui/components/call-stack-frame/call-stack-frame.js +11 -3
- package/dist/client/components/react-dev-overlay/ui/components/call-stack-frame/call-stack-frame.js.map +1 -1
- package/dist/client/components/react-dev-overlay/ui/components/errors/dev-tools-indicator/dev-tools-indicator.d.ts +3 -4
- package/dist/client/components/react-dev-overlay/ui/components/errors/dev-tools-indicator/dev-tools-indicator.js +45 -9
- package/dist/client/components/react-dev-overlay/ui/components/errors/dev-tools-indicator/dev-tools-indicator.js.map +1 -1
- package/dist/client/components/react-dev-overlay/ui/components/errors/dev-tools-indicator/dev-tools-info/dev-tools-info.d.ts +4 -4
- package/dist/client/components/react-dev-overlay/ui/components/errors/dev-tools-indicator/dev-tools-info/dev-tools-info.js +5 -4
- package/dist/client/components/react-dev-overlay/ui/components/errors/dev-tools-indicator/dev-tools-info/dev-tools-info.js.map +1 -1
- package/dist/client/components/react-dev-overlay/ui/components/errors/dev-tools-indicator/dev-tools-info/route-info.d.ts +1 -1
- package/dist/client/components/react-dev-overlay/ui/components/errors/dev-tools-indicator/dev-tools-info/route-info.js +1 -1
- package/dist/client/components/react-dev-overlay/ui/components/errors/dev-tools-indicator/dev-tools-info/route-info.js.map +1 -1
- package/dist/client/components/react-dev-overlay/ui/components/errors/dev-tools-indicator/dev-tools-info/turbopack-info.d.ts +1 -1
- package/dist/client/components/react-dev-overlay/ui/components/errors/dev-tools-indicator/dev-tools-info/turbopack-info.js +1 -1
- package/dist/client/components/react-dev-overlay/ui/components/errors/dev-tools-indicator/dev-tools-info/turbopack-info.js.map +1 -1
- package/dist/client/components/react-dev-overlay/ui/components/errors/dev-tools-indicator/dev-tools-info/user-preferences.d.ts +10 -0
- package/dist/client/components/react-dev-overlay/ui/components/errors/dev-tools-indicator/dev-tools-info/user-preferences.js +254 -0
- package/dist/client/components/react-dev-overlay/ui/components/errors/dev-tools-indicator/dev-tools-info/user-preferences.js.map +1 -0
- package/dist/client/components/react-dev-overlay/ui/components/shadow-portal.js +12 -0
- package/dist/client/components/react-dev-overlay/ui/components/shadow-portal.js.map +1 -1
- package/dist/client/components/react-dev-overlay/ui/icons/dark-icon.d.ts +1 -0
- package/dist/client/components/react-dev-overlay/ui/icons/dark-icon.js +34 -0
- package/dist/client/components/react-dev-overlay/ui/icons/dark-icon.js.map +1 -0
- package/dist/client/components/react-dev-overlay/ui/icons/external.d.ts +1 -0
- package/dist/client/components/react-dev-overlay/ui/icons/external.js +31 -3
- package/dist/client/components/react-dev-overlay/ui/icons/external.js.map +1 -1
- package/dist/client/components/react-dev-overlay/ui/icons/eye-icon.d.ts +1 -0
- package/dist/client/components/react-dev-overlay/ui/icons/eye-icon.js +33 -0
- package/dist/client/components/react-dev-overlay/ui/icons/eye-icon.js.map +1 -0
- package/dist/client/components/react-dev-overlay/ui/icons/gear-icon.d.ts +1 -0
- package/dist/client/components/react-dev-overlay/ui/icons/gear-icon.js +34 -0
- package/dist/client/components/react-dev-overlay/ui/icons/gear-icon.js.map +1 -0
- package/dist/client/components/react-dev-overlay/ui/icons/light-icon.d.ts +1 -0
- package/dist/client/components/react-dev-overlay/ui/icons/light-icon.js +48 -0
- package/dist/client/components/react-dev-overlay/ui/icons/light-icon.js.map +1 -0
- package/dist/client/components/react-dev-overlay/ui/styles/base.js +14 -2
- package/dist/client/components/react-dev-overlay/ui/styles/base.js.map +1 -1
- package/dist/client/components/react-dev-overlay/ui/styles/colors.js +16 -4
- package/dist/client/components/react-dev-overlay/ui/styles/colors.js.map +1 -1
- package/dist/client/components/react-dev-overlay/ui/styles/component-styles.js +3 -1
- package/dist/client/components/react-dev-overlay/ui/styles/component-styles.js.map +1 -1
- package/dist/client/form-shared.d.ts +50 -0
- package/dist/client/form-shared.js +155 -0
- package/dist/client/form-shared.js.map +1 -0
- package/dist/client/form.d.ts +6 -41
- package/dist/client/form.js +38 -196
- package/dist/client/form.js.map +1 -1
- package/dist/client/index.js +1 -1
- package/dist/compiled/next-server/app-page-experimental.runtime.dev.js +3 -3
- package/dist/compiled/next-server/app-page-experimental.runtime.dev.js.map +1 -1
- package/dist/compiled/next-server/app-page.runtime.dev.js +3 -3
- package/dist/compiled/next-server/app-page.runtime.dev.js.map +1 -1
- package/dist/esm/build/index.js +2 -2
- package/dist/esm/build/swc/index.js +1 -1
- package/dist/esm/build/webpack-config.js +2 -2
- package/dist/esm/client/app-bootstrap.js +1 -1
- package/dist/esm/client/app-dir/form.js +17 -141
- package/dist/esm/client/app-dir/form.js.map +1 -1
- package/dist/esm/client/components/react-dev-overlay/shared.js +2 -0
- package/dist/esm/client/components/react-dev-overlay/shared.js.map +1 -1
- package/dist/esm/client/components/react-dev-overlay/ui/components/call-stack-frame/call-stack-frame.js +12 -4
- package/dist/esm/client/components/react-dev-overlay/ui/components/call-stack-frame/call-stack-frame.js.map +1 -1
- package/dist/esm/client/components/react-dev-overlay/ui/components/errors/dev-tools-indicator/dev-tools-indicator.js +44 -9
- package/dist/esm/client/components/react-dev-overlay/ui/components/errors/dev-tools-indicator/dev-tools-indicator.js.map +1 -1
- package/dist/esm/client/components/react-dev-overlay/ui/components/errors/dev-tools-indicator/dev-tools-info/dev-tools-info.js +5 -4
- package/dist/esm/client/components/react-dev-overlay/ui/components/errors/dev-tools-indicator/dev-tools-info/dev-tools-info.js.map +1 -1
- package/dist/esm/client/components/react-dev-overlay/ui/components/errors/dev-tools-indicator/dev-tools-info/route-info.js +1 -1
- package/dist/esm/client/components/react-dev-overlay/ui/components/errors/dev-tools-indicator/dev-tools-info/route-info.js.map +1 -1
- package/dist/esm/client/components/react-dev-overlay/ui/components/errors/dev-tools-indicator/dev-tools-info/turbopack-info.js +1 -1
- package/dist/esm/client/components/react-dev-overlay/ui/components/errors/dev-tools-indicator/dev-tools-info/turbopack-info.js.map +1 -1
- package/dist/esm/client/components/react-dev-overlay/ui/components/errors/dev-tools-indicator/dev-tools-info/user-preferences.js +225 -0
- package/dist/esm/client/components/react-dev-overlay/ui/components/errors/dev-tools-indicator/dev-tools-info/user-preferences.js.map +1 -0
- package/dist/esm/client/components/react-dev-overlay/ui/components/shadow-portal.js +12 -0
- package/dist/esm/client/components/react-dev-overlay/ui/components/shadow-portal.js.map +1 -1
- package/dist/esm/client/components/react-dev-overlay/ui/icons/dark-icon.js +18 -0
- package/dist/esm/client/components/react-dev-overlay/ui/icons/dark-icon.js.map +1 -0
- package/dist/esm/client/components/react-dev-overlay/ui/icons/external.js +16 -0
- package/dist/esm/client/components/react-dev-overlay/ui/icons/external.js.map +1 -1
- package/dist/esm/client/components/react-dev-overlay/ui/icons/eye-icon.js +17 -0
- package/dist/esm/client/components/react-dev-overlay/ui/icons/eye-icon.js.map +1 -0
- package/dist/esm/client/components/react-dev-overlay/ui/icons/gear-icon.js +18 -0
- package/dist/esm/client/components/react-dev-overlay/ui/icons/gear-icon.js.map +1 -0
- package/dist/esm/client/components/react-dev-overlay/ui/icons/light-icon.js +32 -0
- package/dist/esm/client/components/react-dev-overlay/ui/icons/light-icon.js.map +1 -0
- package/dist/esm/client/components/react-dev-overlay/ui/styles/base.js +14 -2
- package/dist/esm/client/components/react-dev-overlay/ui/styles/base.js.map +1 -1
- package/dist/esm/client/components/react-dev-overlay/ui/styles/colors.js +16 -4
- package/dist/esm/client/components/react-dev-overlay/ui/styles/colors.js.map +1 -1
- package/dist/esm/client/components/react-dev-overlay/ui/styles/component-styles.js +3 -1
- package/dist/esm/client/components/react-dev-overlay/ui/styles/component-styles.js.map +1 -1
- package/dist/esm/client/form-shared.js +103 -0
- package/dist/esm/client/form-shared.js.map +1 -0
- package/dist/esm/client/form.js +35 -193
- package/dist/esm/client/form.js.map +1 -1
- package/dist/esm/client/index.js +1 -1
- package/dist/esm/server/config.js +1 -1
- package/dist/esm/server/dev/hot-reloader-turbopack.js +1 -1
- package/dist/esm/server/dev/hot-reloader-webpack.js +1 -1
- package/dist/esm/server/lib/app-info-log.js +1 -1
- package/dist/esm/server/lib/start-server.js +1 -1
- package/dist/server/config.js +1 -1
- package/dist/server/dev/hot-reloader-turbopack.js +1 -1
- package/dist/server/dev/hot-reloader-webpack.js +1 -1
- package/dist/server/lib/app-info-log.js +1 -1
- package/dist/server/lib/start-server.js +1 -1
- package/dist/telemetry/anonymous-meta.js +1 -1
- package/dist/telemetry/events/session-stopped.js +2 -2
- package/dist/telemetry/events/version.js +2 -2
- package/package.json +24 -24
package/dist/client/form.js
CHANGED
@@ -6,99 +6,56 @@ Object.defineProperty(exports, "__esModule", {
|
|
6
6
|
Object.defineProperty(exports, "default", {
|
7
7
|
enumerable: true,
|
8
8
|
get: function() {
|
9
|
-
return
|
9
|
+
return _default;
|
10
10
|
}
|
11
11
|
});
|
12
12
|
const _jsxruntime = require("react/jsx-runtime");
|
13
13
|
const _react = require("react");
|
14
14
|
const _addbasepath = require("./add-base-path");
|
15
|
-
const _useintersection = require("./use-intersection");
|
16
|
-
const _usemergedref = require("./use-merged-ref");
|
17
|
-
const _approutercontextsharedruntime = require("../shared/lib/app-router-context.shared-runtime");
|
18
|
-
const _routerreducertypes = require("./components/router-reducer/router-reducer-types");
|
19
15
|
const _routercontextsharedruntime = require("../shared/lib/router-context.shared-runtime");
|
20
|
-
const
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
];
|
25
|
-
function Form(param) {
|
26
|
-
let { replace, scroll, prefetch: prefetchProp, ref: externalRef, ...props } = param;
|
27
|
-
const router = useAppOrPagesRouter();
|
16
|
+
const _formshared = require("./form-shared");
|
17
|
+
const Form = /*#__PURE__*/ (0, _react.forwardRef)(function FormComponent(param, ref) {
|
18
|
+
let { replace, scroll, prefetch: prefetchProp, ...props } = param;
|
19
|
+
const router = (0, _react.useContext)(_routercontextsharedruntime.RouterContext);
|
28
20
|
const actionProp = props.action;
|
29
21
|
const isNavigatingForm = typeof actionProp === 'string';
|
30
22
|
// Validate `action`
|
31
23
|
if (process.env.NODE_ENV === 'development') {
|
32
24
|
if (isNavigatingForm) {
|
33
|
-
|
25
|
+
(0, _formshared.checkFormActionUrl)(actionProp, 'action');
|
34
26
|
}
|
35
27
|
}
|
36
28
|
// Validate `prefetch`
|
37
29
|
if (process.env.NODE_ENV === 'development') {
|
38
|
-
if (!(prefetchProp === undefined || prefetchProp === false || prefetchProp === null)) {
|
39
|
-
console.error('The `prefetch` prop of <Form> must be `false` or `null`');
|
40
|
-
}
|
41
30
|
if (prefetchProp !== undefined) {
|
42
|
-
|
43
|
-
console.error('Passing `prefetch` to a <Form> has no effect in the pages directory.');
|
44
|
-
} else if (!isNavigatingForm) {
|
45
|
-
console.error('Passing `prefetch` to a <Form> whose `action` is a function has no effect.');
|
46
|
-
}
|
31
|
+
console.error('Passing `prefetch` to a <Form> has no effect in the pages directory.');
|
47
32
|
}
|
48
33
|
}
|
49
|
-
const prefetch = prefetchProp === false || prefetchProp === null ? prefetchProp : null;
|
50
34
|
// Validate `scroll` and `replace`
|
51
35
|
if (process.env.NODE_ENV === 'development') {
|
52
36
|
if (!isNavigatingForm && (replace !== undefined || scroll !== undefined)) {
|
53
|
-
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' + ' `
|
37
|
+
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');
|
54
38
|
}
|
55
39
|
}
|
56
40
|
// Clean up any unsupported form props (and warn if present)
|
57
|
-
for (const key of DISALLOWED_FORM_PROPS){
|
41
|
+
for (const key of _formshared.DISALLOWED_FORM_PROPS){
|
58
42
|
if (key in props) {
|
59
43
|
if (process.env.NODE_ENV === 'development') {
|
60
|
-
console.error("<Form> does not support changing `" + key + "`.
|
44
|
+
console.error("<Form> does not support changing `" + key + "`.");
|
61
45
|
}
|
62
46
|
delete props[key];
|
63
47
|
}
|
64
48
|
}
|
65
|
-
const isPrefetchEnabled = // there is no notion of instant loading states in pages dir, so prefetching is pointless
|
66
|
-
isAppRouter(router) && // if we don't have an action path, we can't preload anything anyway.
|
67
|
-
isNavigatingForm && prefetch === null;
|
68
|
-
const [setIntersectionRef, isVisible] = (0, _useintersection.useIntersection)({
|
69
|
-
rootMargin: '200px',
|
70
|
-
disabled: !isPrefetchEnabled
|
71
|
-
});
|
72
|
-
const ownRef = (0, _usemergedref.useMergedRef)(setIntersectionRef, externalRef != null ? externalRef : null);
|
73
|
-
(0, _react.useEffect)(()=>{
|
74
|
-
if (!isVisible || !isPrefetchEnabled) {
|
75
|
-
return;
|
76
|
-
}
|
77
|
-
try {
|
78
|
-
const prefetchKind = _routerreducertypes.PrefetchKind.AUTO;
|
79
|
-
router.prefetch(actionProp, {
|
80
|
-
kind: prefetchKind
|
81
|
-
});
|
82
|
-
} catch (err) {
|
83
|
-
console.error(err);
|
84
|
-
}
|
85
|
-
}, [
|
86
|
-
isPrefetchEnabled,
|
87
|
-
isVisible,
|
88
|
-
actionProp,
|
89
|
-
prefetch,
|
90
|
-
router
|
91
|
-
]);
|
92
49
|
if (!isNavigatingForm) {
|
93
50
|
return /*#__PURE__*/ (0, _jsxruntime.jsx)("form", {
|
94
51
|
...props,
|
95
|
-
ref:
|
52
|
+
ref: ref
|
96
53
|
});
|
97
54
|
}
|
98
55
|
const actionHref = (0, _addbasepath.addBasePath)(actionProp);
|
99
56
|
return /*#__PURE__*/ (0, _jsxruntime.jsx)("form", {
|
100
57
|
...props,
|
101
|
-
ref:
|
58
|
+
ref: ref,
|
102
59
|
action: actionHref,
|
103
60
|
onSubmit: (event)=>onFormSubmit(event, {
|
104
61
|
router,
|
@@ -108,7 +65,8 @@ function Form(param) {
|
|
108
65
|
onSubmit: props.onSubmit
|
109
66
|
})
|
110
67
|
});
|
111
|
-
}
|
68
|
+
});
|
69
|
+
const _default = Form;
|
112
70
|
function onFormSubmit(event, param) {
|
113
71
|
let { actionHref, onSubmit, replace, scroll, router } = param;
|
114
72
|
if (typeof onSubmit === 'function') {
|
@@ -119,23 +77,22 @@ function onFormSubmit(event, param) {
|
|
119
77
|
return;
|
120
78
|
}
|
121
79
|
}
|
80
|
+
if (!router) {
|
81
|
+
// Form was somehow used outside of the router (but not in app/, the implementation is forked!).
|
82
|
+
// We can't perform a soft navigation, so let the native submit handling do its thing.
|
83
|
+
return;
|
84
|
+
}
|
122
85
|
const formElement = event.currentTarget;
|
123
86
|
const submitter = event.nativeEvent.submitter;
|
124
87
|
let action = actionHref;
|
125
88
|
if (submitter) {
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
// we'd bail out anyway, but we just do it silently.
|
130
|
-
if (hasReactServerActionAttributes(submitter)) {
|
131
|
-
return;
|
132
|
-
}
|
133
|
-
}
|
134
|
-
if (hasUnsupportedSubmitterAttributes(submitter)) {
|
89
|
+
// this is page-router-only, so we don't need to worry about false positives
|
90
|
+
// from the attributes that react adds for server actions.
|
91
|
+
if ((0, _formshared.hasUnsupportedSubmitterAttributes)(submitter)) {
|
135
92
|
return;
|
136
93
|
}
|
137
94
|
// client actions have `formAction="javascript:..."`. We obviously can't prefetch/navigate to that.
|
138
|
-
if (hasReactClientActionAttributes(submitter)) {
|
95
|
+
if ((0, _formshared.hasReactClientActionAttributes)(submitter)) {
|
139
96
|
return;
|
140
97
|
}
|
141
98
|
// If the submitter specified an alternate formAction,
|
@@ -145,143 +102,28 @@ function onFormSubmit(event, param) {
|
|
145
102
|
const submitterFormAction = submitter.getAttribute('formAction');
|
146
103
|
if (submitterFormAction !== null) {
|
147
104
|
if (process.env.NODE_ENV === 'development') {
|
148
|
-
|
105
|
+
(0, _formshared.checkFormActionUrl)(submitterFormAction, 'formAction');
|
149
106
|
}
|
150
107
|
action = submitterFormAction;
|
151
108
|
}
|
152
109
|
}
|
153
|
-
|
154
|
-
try {
|
155
|
-
// NOTE: It might be more correct to resolve URLs relative to `document.baseURI`,
|
156
|
-
// but we already do it relative to `location.href` elsewhere:
|
157
|
-
// (see e.g. https://github.com/vercel/next.js/blob/bb0e6722f87ceb2d43015f5b8a413d0072f2badf/packages/next/src/client/components/app-router.tsx#L146)
|
158
|
-
// so it's better to stay consistent.
|
159
|
-
const base = window.location.href;
|
160
|
-
targetUrl = new URL(action, base);
|
161
|
-
} catch (err) {
|
162
|
-
throw Object.defineProperty(new Error('Cannot parse form action "' + action + '" as a URL', {
|
163
|
-
cause: err
|
164
|
-
}), "__NEXT_ERROR_CODE", {
|
165
|
-
value: "E152",
|
166
|
-
enumerable: false,
|
167
|
-
configurable: true
|
168
|
-
});
|
169
|
-
}
|
170
|
-
if (targetUrl.searchParams.size) {
|
171
|
-
// url-encoded HTML forms *overwrite* any search params in the `action` url:
|
172
|
-
//
|
173
|
-
// "Let `query` be the result of running the application/x-www-form-urlencoded serializer [...]"
|
174
|
-
// "Set parsed action's query component to `query`."
|
175
|
-
// https://html.spec.whatwg.org/multipage/form-control-infrastructure.html#submit-mutate-action
|
176
|
-
//
|
177
|
-
// We need to match that.
|
178
|
-
// (note that all other parts of the URL, like `hash`, are preserved)
|
179
|
-
targetUrl.search = '';
|
180
|
-
}
|
181
|
-
const formData = new FormData(formElement);
|
182
|
-
for (let [name, value] of formData){
|
183
|
-
if (typeof value !== 'string') {
|
184
|
-
// For file inputs, the native browser behavior is to use the filename as the value instead:
|
185
|
-
//
|
186
|
-
// "If entry's value is a File object, then let value be entry's value's name. Otherwise, let value be entry's value."
|
187
|
-
// https://html.spec.whatwg.org/multipage/form-control-infrastructure.html#converting-an-entry-list-to-a-list-of-name-value-pairs
|
188
|
-
//
|
189
|
-
if (process.env.NODE_ENV === 'development') {
|
190
|
-
console.warn("<Form> only supports file inputs if `action` is a function. File inputs cannot be used if `action` is a string, " + "because files cannot be encoded as search params.");
|
191
|
-
}
|
192
|
-
value = value.name;
|
193
|
-
}
|
194
|
-
targetUrl.searchParams.append(name, value);
|
195
|
-
}
|
110
|
+
const targetUrl = (0, _formshared.createFormSubmitDestinationUrl)(action, formElement);
|
196
111
|
// Finally, no more reasons for bailing out.
|
197
112
|
event.preventDefault();
|
198
113
|
const method = replace ? 'replace' : 'push';
|
199
|
-
const targetHref = targetUrl.href
|
200
|
-
|
201
|
-
|
202
|
-
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
|
207
|
-
|
208
|
-
|
209
|
-
|
210
|
-
|
211
|
-
|
212
|
-
// So this needs some follow up work.
|
213
|
-
router[method](targetHref, undefined, {
|
214
|
-
scroll
|
215
|
-
});
|
216
|
-
}
|
217
|
-
}
|
218
|
-
function isAppRouter(router) {
|
219
|
-
return !('asPath' in router);
|
220
|
-
}
|
221
|
-
function useAppOrPagesRouter() {
|
222
|
-
const pagesRouter = (0, _react.useContext)(_routercontextsharedruntime.RouterContext);
|
223
|
-
const appRouter = (0, _react.useContext)(_approutercontextsharedruntime.AppRouterContext);
|
224
|
-
if (pagesRouter) {
|
225
|
-
return pagesRouter;
|
226
|
-
} else {
|
227
|
-
// We're in the app directory if there is no pages router.
|
228
|
-
return appRouter;
|
229
|
-
}
|
230
|
-
}
|
231
|
-
function checkActionUrl(action, source) {
|
232
|
-
const aPropName = source === 'action' ? "an `action`" : "a `formAction`";
|
233
|
-
let testUrl;
|
234
|
-
try {
|
235
|
-
testUrl = new URL(action, 'http://n');
|
236
|
-
} catch (err) {
|
237
|
-
console.error("<Form> received " + aPropName + ' that cannot be parsed as a URL: "' + action + '".');
|
238
|
-
return;
|
239
|
-
}
|
240
|
-
// url-encoded HTML forms ignore any queryparams in the `action` url. We need to match that.
|
241
|
-
if (testUrl.searchParams.size) {
|
242
|
-
console.warn("<Form> received " + aPropName + ' that contains search params: "' + action + '". This is not supported, and they will be ignored. ' + 'If you need to pass in additional search params, use an `<input type="hidden" />` instead.');
|
243
|
-
}
|
244
|
-
}
|
245
|
-
const isSupportedEncType = (value)=>value === 'application/x-www-form-urlencoded';
|
246
|
-
const isSupportedMethod = (value)=>value === 'get';
|
247
|
-
const isSupportedTarget = (value)=>value === '_self';
|
248
|
-
function hasUnsupportedSubmitterAttributes(submitter) {
|
249
|
-
// A submitter can override `encType` for the form.
|
250
|
-
const formEncType = submitter.getAttribute('formEncType');
|
251
|
-
if (formEncType !== null && !isSupportedEncType(formEncType)) {
|
252
|
-
if (process.env.NODE_ENV === 'development') {
|
253
|
-
console.error("<Form>'s `encType` was set to an unsupported value via `formEncType=\"" + formEncType + '"`. ' + "This will disable <Form>'s navigation functionality. If you need this, use a native <form> element instead.");
|
254
|
-
}
|
255
|
-
return true;
|
256
|
-
}
|
257
|
-
// A submitter can override `method` for the form.
|
258
|
-
const formMethod = submitter.getAttribute('formMethod');
|
259
|
-
if (formMethod !== null && !isSupportedMethod(formMethod)) {
|
260
|
-
if (process.env.NODE_ENV === 'development') {
|
261
|
-
console.error("<Form>'s `method` was set to an unsupported value via `formMethod=\"" + formMethod + '"`. ' + "This will disable <Form>'s navigation functionality. If you need this, use a native <form> element instead.");
|
262
|
-
}
|
263
|
-
return true;
|
264
|
-
}
|
265
|
-
// A submitter can override `target` for the form.
|
266
|
-
const formTarget = submitter.getAttribute('formTarget');
|
267
|
-
if (formTarget !== null && !isSupportedTarget(formTarget)) {
|
268
|
-
if (process.env.NODE_ENV === 'development') {
|
269
|
-
console.error("<Form>'s `target` was set to an unsupported value via `formTarget=\"" + formTarget + '"`. ' + "This will disable <Form>'s navigation functionality. If you need this, use a native <form> element instead.");
|
270
|
-
}
|
271
|
-
return true;
|
272
|
-
}
|
273
|
-
return false;
|
274
|
-
}
|
275
|
-
function hasReactServerActionAttributes(submitter) {
|
276
|
-
// https://github.com/facebook/react/blob/942eb80381b96f8410eab1bef1c539bed1ab0eb1/packages/react-client/src/ReactFlightReplyClient.js#L931-L934
|
277
|
-
const name = submitter.getAttribute('name');
|
278
|
-
return name && (name.startsWith('$ACTION_ID_') || name.startsWith('$ACTION_REF_'));
|
279
|
-
}
|
280
|
-
function hasReactClientActionAttributes(submitter) {
|
281
|
-
// CSR: https://github.com/facebook/react/blob/942eb80381b96f8410eab1bef1c539bed1ab0eb1/packages/react-dom-bindings/src/client/ReactDOMComponent.js#L482-L487
|
282
|
-
// SSR: https://github.com/facebook/react/blob/942eb80381b96f8410eab1bef1c539bed1ab0eb1/packages/react-dom-bindings/src/client/ReactDOMComponent.js#L2401
|
283
|
-
const action = submitter.getAttribute('formAction');
|
284
|
-
return action && /\s*javascript:/i.test(action);
|
114
|
+
const targetHref = targetUrl.href // TODO: will pages router be happy about an absolute URL here?
|
115
|
+
;
|
116
|
+
// TODO(form): Make this use a transition so that pending states work
|
117
|
+
//
|
118
|
+
// Unlike the app router, pages router doesn't use startTransition,
|
119
|
+
// and can't easily be wrapped in one because of implementation details
|
120
|
+
// (e.g. it doesn't use any react state)
|
121
|
+
// But it's important to have this wrapped in a transition because
|
122
|
+
// pending states from e.g. `useFormStatus` rely on that.
|
123
|
+
// So this needs some follow up work.
|
124
|
+
router[method](targetHref, undefined, {
|
125
|
+
scroll
|
126
|
+
});
|
285
127
|
}
|
286
128
|
|
287
129
|
if ((typeof exports.default === 'function' || (typeof exports.default === 'object' && exports.default !== null)) && typeof exports.default.__esModule === 'undefined') {
|
package/dist/client/form.js.map
CHANGED
@@ -1 +1 @@
|
|
1
|
-
{"version":3,"sources":["../../src/client/form.tsx"],"sourcesContent":["'use client'\n\nimport { useEffect, type HTMLProps, type FormEvent, useContext } from 'react'\nimport { addBasePath } from './add-base-path'\nimport { useIntersection } from './use-intersection'\nimport { useMergedRef } from './use-merged-ref'\nimport {\n AppRouterContext,\n type AppRouterInstance,\n} from '../shared/lib/app-router-context.shared-runtime'\nimport { PrefetchKind } from './components/router-reducer/router-reducer-types'\nimport { RouterContext } from '../shared/lib/router-context.shared-runtime'\nimport type { NextRouter } from './router'\n\nconst DISALLOWED_FORM_PROPS = ['method', 'encType', 'target'] as const\n\ntype HTMLFormProps = HTMLProps<HTMLFormElement>\ntype DisallowedFormProps = (typeof DISALLOWED_FORM_PROPS)[number]\n\ntype InternalFormProps = {\n /**\n * `action` can be either a `string` or a function.\n * - If `action` is a string, it will be interpreted as a path or URL to navigate to when the form is submitted.\n * The path will be prefetched when the form becomes visible.\n * - If `action` is a function, it will be called when the form is submitted. See the [React docs](https://react.dev/reference/react-dom/components/form#props) for more.\n */\n action: NonNullable<HTMLFormProps['action']>\n /**\n * Controls how the route specified by `action` is prefetched.\n * Any `<Form />` that is in the viewport (initially or through scroll) will be prefetched.\n * Prefetch can be disabled by passing `prefetch={false}`. Prefetching is only enabled in production.\n *\n * Options:\n * - `null` (default): For statically generated pages, this will prefetch the full React Server Component data. For dynamic pages, this will prefetch up to the nearest route segment with a [`loading.js`](https://nextjs.org/docs/app/api-reference/file-conventions/loading) file. If there is no loading file, it will not fetch the full tree to avoid fetching too much data.\n * - `false`: This will not prefetch any data.\n *\n * In pages dir, prefetching is not supported, and passing this prop will emit a warning.\n *\n * @defaultValue `null`\n */\n prefetch?: false | null\n /**\n * Whether submitting the form should replace the current `history` state instead of adding a new url into the stack.\n * Only valid if `action` is a string.\n *\n * @defaultValue `false`\n */\n replace?: boolean\n /**\n * Override the default scroll behavior when navigating.\n * Only valid if `action` is a string.\n *\n * @defaultValue `true`\n */\n scroll?: boolean\n} & Omit<HTMLFormProps, 'action' | DisallowedFormProps>\n\n// `RouteInferType` is a stub here to avoid breaking `typedRoutes` when the type\n// isn't generated yet. It will be replaced when the webpack plugin runs.\n// eslint-disable-next-line @typescript-eslint/no-unused-vars\nexport type FormProps<RouteInferType = any> = InternalFormProps\n\nexport default function Form({\n replace,\n scroll,\n prefetch: prefetchProp,\n ref: externalRef,\n ...props\n}: FormProps) {\n const router = useAppOrPagesRouter()\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 checkActionUrl(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 <Form> must be `false` or `null`')\n }\n\n if (prefetchProp !== undefined) {\n if (!isAppRouter(router)) {\n console.error(\n 'Passing `prefetch` to a <Form> has no effect in the pages directory.'\n )\n } else if (!isNavigatingForm) {\n console.error(\n 'Passing `prefetch` to a <Form> whose `action` is a function has no effect.'\n )\n }\n }\n }\n\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 <Form> 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 `<Form> 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<string, unknown>)[key]\n }\n }\n\n const isPrefetchEnabled =\n // there is no notion of instant loading states in pages dir, so prefetching is pointless\n isAppRouter(router) &&\n // if we don't have an action path, we can't preload anything anyway.\n isNavigatingForm &&\n prefetch === null\n\n const [setIntersectionRef, isVisible] = useIntersection({\n rootMargin: '200px',\n disabled: !isPrefetchEnabled,\n })\n\n const ownRef = useMergedRef<HTMLFormElement>(\n setIntersectionRef,\n externalRef ?? null\n )\n\n useEffect(() => {\n if (!isVisible || !isPrefetchEnabled) {\n return\n }\n\n try {\n const prefetchKind = PrefetchKind.AUTO\n router.prefetch(actionProp, { kind: prefetchKind })\n } catch (err) {\n console.error(err)\n }\n }, [isPrefetchEnabled, isVisible, actionProp, prefetch, router])\n\n if (!isNavigatingForm) {\n return <form {...props} ref={ownRef} />\n }\n\n const actionHref = addBasePath(actionProp)\n\n return (\n <form\n {...props}\n ref={ownRef}\n action={actionHref}\n onSubmit={(event) =>\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<HTMLFormElement>,\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: SomeRouter\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 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 checkActionUrl(submitterFormAction, 'formAction')\n }\n action = submitterFormAction\n }\n }\n\n let targetUrl: URL\n try {\n // NOTE: It might be more correct to resolve URLs relative to `document.baseURI`,\n // but we already do it relative to `location.href` elsewhere:\n // (see e.g. https://github.com/vercel/next.js/blob/bb0e6722f87ceb2d43015f5b8a413d0072f2badf/packages/next/src/client/components/app-router.tsx#L146)\n // so it's better to stay consistent.\n const base = window.location.href\n targetUrl = new URL(action, base)\n } catch (err) {\n throw new Error(`Cannot parse form action \"${action}\" as a URL`, {\n cause: err,\n })\n }\n if (targetUrl.searchParams.size) {\n // url-encoded HTML forms *overwrite* any search params in the `action` url:\n //\n // \"Let `query` be the result of running the application/x-www-form-urlencoded serializer [...]\"\n // \"Set parsed action's query component to `query`.\"\n // https://html.spec.whatwg.org/multipage/form-control-infrastructure.html#submit-mutate-action\n //\n // We need to match that.\n // (note that all other parts of the URL, like `hash`, are preserved)\n targetUrl.search = ''\n }\n\n const formData = new FormData(formElement)\n\n for (let [name, value] of formData) {\n if (typeof value !== 'string') {\n // For file inputs, the native browser behavior is to use the filename as the value instead:\n //\n // \"If entry's value is a File object, then let value be entry's value's name. Otherwise, let value be entry's value.\"\n // https://html.spec.whatwg.org/multipage/form-control-infrastructure.html#converting-an-entry-list-to-a-list-of-name-value-pairs\n //\n if (process.env.NODE_ENV === 'development') {\n console.warn(\n `<Form> only supports file inputs if \\`action\\` is a function. File inputs cannot be used if \\`action\\` is a string, ` +\n `because files cannot be encoded as search params.`\n )\n }\n value = value.name\n }\n\n targetUrl.searchParams.append(name, value)\n }\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 if (isAppRouter(router)) {\n router[method](targetHref, { scroll })\n } else {\n // TODO(form): Make this use a transition so that pending states work\n //\n // Unlike the app router, pages router doesn't use startTransition,\n // and can't easily be wrapped in one because of implementation details\n // (e.g. it doesn't use any react state)\n // But it's important to have this wrapped in a transition because\n // pending states from e.g. `useFormStatus` rely on that.\n // So this needs some follow up work.\n router[method](targetHref, undefined, { scroll })\n }\n}\n\ntype SomeRouter = AppRouterInstance | NextRouter\n\nfunction isAppRouter(router: SomeRouter): router is AppRouterInstance {\n return !('asPath' in router)\n}\n\nfunction useAppOrPagesRouter(): SomeRouter {\n const pagesRouter = useContext(RouterContext)\n const appRouter = useContext(AppRouterContext)\n if (pagesRouter) {\n return pagesRouter\n } else {\n // We're in the app directory if there is no pages router.\n return appRouter!\n }\n}\n\nfunction checkActionUrl(action: string, source: 'action' | 'formAction') {\n const aPropName = source === 'action' ? `an \\`action\\`` : `a \\`formAction\\``\n\n let testUrl: URL\n try {\n testUrl = new URL(action, 'http://n')\n } catch (err) {\n console.error(\n `<Form> received ${aPropName} that cannot be parsed as a URL: \"${action}\".`\n )\n return\n }\n\n // url-encoded HTML forms ignore any queryparams in the `action` url. We need to match that.\n if (testUrl.searchParams.size) {\n console.warn(\n `<Form> received ${aPropName} that contains search params: \"${action}\". This is not supported, and they will be ignored. ` +\n `If you need to pass in additional search params, use an \\`<input type=\"hidden\" />\\` instead.`\n )\n }\n}\n\nconst isSupportedEncType = (value: string) =>\n value === 'application/x-www-form-urlencoded'\nconst isSupportedMethod = (value: string) => value === 'get'\nconst isSupportedTarget = (value: string) => value === '_self'\n\nfunction hasUnsupportedSubmitterAttributes(submitter: HTMLElement): boolean {\n // A submitter can override `encType` for the form.\n const formEncType = submitter.getAttribute('formEncType')\n if (formEncType !== null && !isSupportedEncType(formEncType)) {\n if (process.env.NODE_ENV === 'development') {\n console.error(\n `<Form>'s \\`encType\\` was set to an unsupported value via \\`formEncType=\"${formEncType}\"\\`. ` +\n `This will disable <Form>'s navigation functionality. If you need this, use a native <form> element instead.`\n )\n }\n return true\n }\n\n // A submitter can override `method` for the form.\n const formMethod = submitter.getAttribute('formMethod')\n if (formMethod !== null && !isSupportedMethod(formMethod)) {\n if (process.env.NODE_ENV === 'development') {\n console.error(\n `<Form>'s \\`method\\` was set to an unsupported value via \\`formMethod=\"${formMethod}\"\\`. ` +\n `This will disable <Form>'s navigation functionality. If you need this, use a native <form> element instead.`\n )\n }\n return true\n }\n\n // A submitter can override `target` for the form.\n const formTarget = submitter.getAttribute('formTarget')\n if (formTarget !== null && !isSupportedTarget(formTarget)) {\n if (process.env.NODE_ENV === 'development') {\n console.error(\n `<Form>'s \\`target\\` was set to an unsupported value via \\`formTarget=\"${formTarget}\"\\`. ` +\n `This will disable <Form>'s navigation functionality. If you need this, use a native <form> element instead.`\n )\n }\n return true\n }\n\n return false\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\nfunction hasReactClientActionAttributes(submitter: HTMLElement) {\n // CSR: https://github.com/facebook/react/blob/942eb80381b96f8410eab1bef1c539bed1ab0eb1/packages/react-dom-bindings/src/client/ReactDOMComponent.js#L482-L487\n // SSR: https://github.com/facebook/react/blob/942eb80381b96f8410eab1bef1c539bed1ab0eb1/packages/react-dom-bindings/src/client/ReactDOMComponent.js#L2401\n const action = submitter.getAttribute('formAction')\n return action && /\\s*javascript:/i.test(action)\n}\n"],"names":["Form","DISALLOWED_FORM_PROPS","replace","scroll","prefetch","prefetchProp","ref","externalRef","props","router","useAppOrPagesRouter","actionProp","action","isNavigatingForm","process","env","NODE_ENV","checkActionUrl","undefined","console","error","isAppRouter","key","isPrefetchEnabled","setIntersectionRef","isVisible","useIntersection","rootMargin","disabled","ownRef","useMergedRef","useEffect","prefetchKind","PrefetchKind","AUTO","kind","err","form","actionHref","addBasePath","onSubmit","event","onFormSubmit","defaultPrevented","formElement","currentTarget","submitter","nativeEvent","hasReactServerActionAttributes","hasUnsupportedSubmitterAttributes","hasReactClientActionAttributes","submitterFormAction","getAttribute","targetUrl","base","window","location","href","URL","Error","cause","searchParams","size","search","formData","FormData","name","value","warn","append","preventDefault","method","targetHref","pagesRouter","useContext","RouterContext","appRouter","AppRouterContext","source","aPropName","testUrl","isSupportedEncType","isSupportedMethod","isSupportedTarget","formEncType","formMethod","formTarget","startsWith","test"],"mappings":"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"}
|
1
|
+
{"version":3,"sources":["../../src/client/form.tsx"],"sourcesContent":["'use client'\n\nimport { type FormEvent, useContext, forwardRef } from 'react'\nimport { addBasePath } from './add-base-path'\nimport { RouterContext } from '../shared/lib/router-context.shared-runtime'\nimport type { NextRouter } from './router'\nimport {\n checkFormActionUrl,\n createFormSubmitDestinationUrl,\n DISALLOWED_FORM_PROPS,\n hasReactClientActionAttributes,\n hasUnsupportedSubmitterAttributes,\n type FormProps,\n} from './form-shared'\n\nexport type { FormProps }\n\nconst Form = forwardRef<HTMLFormElement, FormProps>(function FormComponent(\n { replace, scroll, prefetch: prefetchProp, ...props },\n ref\n) {\n const router = useContext(RouterContext)\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 (prefetchProp !== undefined) {\n console.error(\n 'Passing `prefetch` to a <Form> has no effect in the pages directory.'\n )\n }\n }\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 <Form> 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 ' `router.replace()` - https://nextjs.org/docs/pages/api-reference/functions/use-router#routerreplace\\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(`<Form> does not support changing \\`${key}\\`.`)\n }\n delete (props as Record<string, unknown>)[key]\n }\n }\n\n if (!isNavigatingForm) {\n return <form {...props} ref={ref} />\n }\n\n const actionHref = addBasePath(actionProp)\n\n return (\n <form\n {...props}\n ref={ref}\n action={actionHref}\n onSubmit={(event) =>\n onFormSubmit(event, {\n router,\n actionHref,\n replace,\n scroll,\n onSubmit: props.onSubmit,\n })\n }\n />\n )\n})\n\nexport default Form\n\nfunction onFormSubmit(\n event: FormEvent<HTMLFormElement>,\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: NextRouter | 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 app/, 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 // this is page-router-only, so we don't need to worry about false positives\n // from the attributes that react adds for server actions.\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 // TODO: will pages router be happy about an absolute URL here?\n\n // TODO(form): Make this use a transition so that pending states work\n //\n // Unlike the app router, pages router doesn't use startTransition,\n // and can't easily be wrapped in one because of implementation details\n // (e.g. it doesn't use any react state)\n // But it's important to have this wrapped in a transition because\n // pending states from e.g. `useFormStatus` rely on that.\n // So this needs some follow up work.\n router[method](targetHref, undefined, { scroll })\n}\n"],"names":["Form","forwardRef","FormComponent","ref","replace","scroll","prefetch","prefetchProp","props","router","useContext","RouterContext","actionProp","action","isNavigatingForm","process","env","NODE_ENV","checkFormActionUrl","undefined","console","error","key","DISALLOWED_FORM_PROPS","form","actionHref","addBasePath","onSubmit","event","onFormSubmit","defaultPrevented","formElement","currentTarget","submitter","nativeEvent","hasUnsupportedSubmitterAttributes","hasReactClientActionAttributes","submitterFormAction","getAttribute","targetUrl","createFormSubmitDestinationUrl","preventDefault","method","targetHref","href"],"mappings":"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"}
|
package/dist/client/index.js
CHANGED
@@ -61,7 +61,7 @@ const _hooksclientcontextsharedruntime = require("../shared/lib/hooks-client-con
|
|
61
61
|
const _onrecoverableerror = require("./react-client-callbacks/on-recoverable-error");
|
62
62
|
const _tracer = /*#__PURE__*/ _interop_require_default._(require("./tracing/tracer"));
|
63
63
|
const _isnextroutererror = require("./components/is-next-router-error");
|
64
|
-
const version = "15.2.0-canary.
|
64
|
+
const version = "15.2.0-canary.76";
|
65
65
|
let router;
|
66
66
|
const emitter = (0, _mitt.default)();
|
67
67
|
const looseToArray = (input)=>[].slice.call(input);
|