UNPKG

4.89 kBJavaScriptView Raw
1/**
2 * react-router v8.0.0
3 *
4 * Copyright (c) Remix Software Inc.
5 *
6 * This source code is licensed under the MIT license found in the
7 * LICENSE.md file in the root directory of this source tree.
8 *
9 * @license MIT
10 */
11import { warning } from "../router/history.js";
12import { stripBasename } from "../router/utils.js";
13const defaultEncType = "application/x-www-form-urlencoded";
14function isHtmlElement(object) {
15 return typeof HTMLElement !== "undefined" && object instanceof HTMLElement;
16}
17function isButtonElement(object) {
18 return isHtmlElement(object) && object.tagName.toLowerCase() === "button";
19}
20function isFormElement(object) {
21 return isHtmlElement(object) && object.tagName.toLowerCase() === "form";
22}
23function isInputElement(object) {
24 return isHtmlElement(object) && object.tagName.toLowerCase() === "input";
25}
26function isModifiedEvent(event) {
27 return !!(event.metaKey || event.altKey || event.ctrlKey || event.shiftKey);
28}
29function shouldProcessLinkClick(event, target) {
30 return event.button === 0 && (!target || target === "_self") && !isModifiedEvent(event);
31}
32/**
33Creates a URLSearchParams object using the given initializer.
34
35This is identical to `new URLSearchParams(init)` except it also
36supports arrays as values in the object form of the initializer
37instead of just strings. This is convenient when you need multiple
38values for a given key, but don't want to use an array initializer.
39
40For example, instead of:
41
42```tsx
43let searchParams = new URLSearchParams([
44['sort', 'name'],
45['sort', 'price']
46]);
47```
48you can do:
49
50```
51let searchParams = createSearchParams({
52sort: ['name', 'price']
53});
54```
55
56@category Utils
57*/
58function createSearchParams(init = "") {
59 return new URLSearchParams(typeof init === "string" || Array.isArray(init) || init instanceof URLSearchParams ? init : Object.keys(init).reduce((memo, key) => {
60 let value = init[key];
61 return memo.concat(Array.isArray(value) ? value.map((v) => [key, v]) : [[key, value]]);
62 }, []));
63}
64function getSearchParamsForLocation(locationSearch, defaultSearchParams) {
65 let searchParams = createSearchParams(locationSearch);
66 if (defaultSearchParams) defaultSearchParams.forEach((_, key) => {
67 if (!searchParams.has(key)) defaultSearchParams.getAll(key).forEach((value) => {
68 searchParams.append(key, value);
69 });
70 });
71 return searchParams;
72}
73let _formDataSupportsSubmitter = null;
74function isFormDataSubmitterSupported() {
75 if (_formDataSupportsSubmitter === null) try {
76 new FormData(document.createElement("form"), 0);
77 _formDataSupportsSubmitter = false;
78 } catch (e) {
79 _formDataSupportsSubmitter = true;
80 }
81 return _formDataSupportsSubmitter;
82}
83const supportedFormEncTypes = new Set([
84 "application/x-www-form-urlencoded",
85 "multipart/form-data",
86 "text/plain"
87]);
88function getFormEncType(encType) {
89 if (encType != null && !supportedFormEncTypes.has(encType)) {
90 warning(false, `"${encType}" is not a valid \`encType\` for \`<Form>\`/\`<fetcher.Form>\` and will default to "${defaultEncType}"`);
91 return null;
92 }
93 return encType;
94}
95function getFormSubmissionInfo(target, basename) {
96 let method;
97 let action;
98 let encType;
99 let formData;
100 let body;
101 if (isFormElement(target)) {
102 let attr = target.getAttribute("action");
103 action = attr ? stripBasename(attr, basename) : null;
104 method = target.getAttribute("method") || "get";
105 encType = getFormEncType(target.getAttribute("enctype")) || defaultEncType;
106 formData = new FormData(target);
107 } else if (isButtonElement(target) || isInputElement(target) && (target.type === "submit" || target.type === "image")) {
108 let form = target.form;
109 if (form == null) throw new Error(`Cannot submit a <button> or <input type="submit"> without a <form>`);
110 let attr = target.getAttribute("formaction") || form.getAttribute("action");
111 action = attr ? stripBasename(attr, basename) : null;
112 method = target.getAttribute("formmethod") || form.getAttribute("method") || "get";
113 encType = getFormEncType(target.getAttribute("formenctype")) || getFormEncType(form.getAttribute("enctype")) || defaultEncType;
114 formData = new FormData(form, target);
115 if (!isFormDataSubmitterSupported()) {
116 let { name, type, value } = target;
117 if (type === "image") {
118 let prefix = name ? `${name}.` : "";
119 formData.append(`${prefix}x`, "0");
120 formData.append(`${prefix}y`, "0");
121 } else if (name) formData.append(name, value);
122 }
123 } else if (isHtmlElement(target)) throw new Error("Cannot submit element that is not <form>, <button>, or <input type=\"submit|image\">");
124 else {
125 method = "get";
126 action = null;
127 encType = defaultEncType;
128 body = target;
129 }
130 if (formData && encType === "text/plain") {
131 body = formData;
132 formData = void 0;
133 }
134 return {
135 action,
136 method: method.toLowerCase(),
137 encType,
138 formData,
139 body
140 };
141}
142//#endregion
143export { createSearchParams, getFormSubmissionInfo, getSearchParamsForLocation, shouldProcessLinkClick };