diff --git a/.changeset/json-text-encoding.md b/.changeset/json-text-encoding.md
new file mode 100644
index 00000000000..2def7b4345f
--- /dev/null
+++ b/.changeset/json-text-encoding.md
@@ -0,0 +1,5 @@
+---
+"@remix-run/react": minor
+---
+
+Support `application/json` and `text/plain` submission encodings in `useSubmit`/`fetcher.submit`
diff --git a/integration/fetcher-test.ts b/integration/fetcher-test.ts
index 7c7dfda98cc..2bca2fcbf15 100644
--- a/integration/fetcher-test.ts
+++ b/integration/fetcher-test.ts
@@ -148,13 +148,22 @@ test.describe("useFetcher", () => {
`,
"app/routes/fetcher-echo.jsx": js`
- import { json } from "@remix-run/node";
- import { useFetcher } from "@remix-run/react";
+ import { json } from "@remix-run/node";
+ import { useFetcher } from "@remix-run/react";
export async function action({ request }) {
await new Promise(r => setTimeout(r, 1000));
- let value = (await request.formData()).get('value');
- return json({ data: "ACTION " + value })
+ let contentType = request.headers.get('Content-Type');
+ let value;
+ if (contentType.includes('application/json')) {
+ let json = await request.json();
+ value = json === null ? json : json.value;
+ } else if (contentType.includes('text/plain')) {
+ value = await request.text();
+ } else {
+ value = (await request.formData()).get('value');
+ }
+ return json({ data: "ACTION (" + contentType + ") " + value })
}
export async function loader({ request }) {
@@ -190,6 +199,20 @@ test.describe("useFetcher", () => {
let value = document.getElementById('fetcher-input').value;
fetcher.submit({ value }, { method: 'post', action: '/fetcher-echo' })
}}>Submit
+
+
+
+
{fetcher.state === 'idle' ?
IDLE
: null}
{JSON.stringify(fetcherValues)}
@@ -253,6 +276,46 @@ test.describe("useFetcher", () => {
await page.waitForSelector(`pre:has-text("${CHEESESTEAK}")`);
});
+ test("submit can hit an action with json", async ({ page }) => {
+ let app = new PlaywrightFixture(appFixture, page);
+ await app.goto("/fetcher-echo", true);
+ await page.fill("#fetcher-input", "input value");
+ await app.clickElement("#fetcher-submit-json");
+ await page.waitForSelector(`#fetcher-idle`);
+ expect(await app.getHtml()).toMatch(
+ 'ACTION (application/json) input value"'
+ );
+ });
+
+ test("submit can hit an action with null json", async ({ page }) => {
+ let app = new PlaywrightFixture(appFixture, page);
+ await app.goto("/fetcher-echo", true);
+ await app.clickElement("#fetcher-submit-json-null");
+ await new Promise((r) => setTimeout(r, 1000));
+ await page.waitForSelector(`#fetcher-idle`);
+ expect(await app.getHtml()).toMatch('ACTION (application/json) null"');
+ });
+
+ test("submit can hit an action with text", async ({ page }) => {
+ let app = new PlaywrightFixture(appFixture, page);
+ await app.goto("/fetcher-echo", true);
+ await page.fill("#fetcher-input", "input value");
+ await app.clickElement("#fetcher-submit-text");
+ await page.waitForSelector(`#fetcher-idle`);
+ expect(await app.getHtml()).toMatch(
+ 'ACTION (text/plain;charset=UTF-8) input value"'
+ );
+ });
+
+ test("submit can hit an action with empty text", async ({ page }) => {
+ let app = new PlaywrightFixture(appFixture, page);
+ await app.goto("/fetcher-echo", true);
+ await app.clickElement("#fetcher-submit-text-empty");
+ await new Promise((r) => setTimeout(r, 1000));
+ await page.waitForSelector(`#fetcher-idle`);
+ expect(await app.getHtml()).toMatch('ACTION (text/plain;charset=UTF-8) "');
+ });
+
test("submit can hit an action only route", async ({ page }) => {
let app = new PlaywrightFixture(appFixture, page);
await app.goto("/fetcher-action-only-call");
@@ -333,8 +396,8 @@ test.describe("useFetcher", () => {
JSON.stringify([
"idle/undefined",
"submitting/undefined",
- "loading/ACTION 1",
- "idle/ACTION 1",
+ "loading/ACTION (application/x-www-form-urlencoded;charset=UTF-8) 1",
+ "idle/ACTION (application/x-www-form-urlencoded;charset=UTF-8) 1",
])
);
@@ -345,11 +408,12 @@ test.describe("useFetcher", () => {
JSON.stringify([
"idle/undefined",
"submitting/undefined",
- "loading/ACTION 1",
- "idle/ACTION 1",
- "submitting/ACTION 1", // Preserves old data during resubmissions
- "loading/ACTION 2",
- "idle/ACTION 2",
+ "loading/ACTION (application/x-www-form-urlencoded;charset=UTF-8) 1",
+ "idle/ACTION (application/x-www-form-urlencoded;charset=UTF-8) 1",
+ // Preserves old data during resubmissions
+ "submitting/ACTION (application/x-www-form-urlencoded;charset=UTF-8) 1",
+ "loading/ACTION (application/x-www-form-urlencoded;charset=UTF-8) 2",
+ "idle/ACTION (application/x-www-form-urlencoded;charset=UTF-8) 2",
])
);
});
diff --git a/integration/form-test.ts b/integration/form-test.ts
index 2a873f96bd6..9c0e5391a8f 100644
--- a/integration/form-test.ts
+++ b/integration/form-test.ts
@@ -1006,12 +1006,7 @@ test.describe("Forms", () => {
test("submits the submitter's value(s) in tree order in the form data", async ({
page,
- javaScriptEnabled,
}) => {
- test.fail(
- Boolean(javaScriptEnabled),
- "
+ )
}
- let data = useLoaderData();
- return (
-
- )
- }
- `,
+ export default function Component() {
+ let submit = useSubmit();
+ let data = useActionData();
+ return (
+ <>
+
+
+
+ {data ? data: {JSON.stringify(data)}
: null}
+ >
+ );
+ }
+ `,
},
});
@@ -64,4 +108,28 @@ test.describe("`useSubmit()` returned function", () => {
`tasks=first&tasks=second&tasks=third
`
);
});
+
+ test("submits json data", async ({ page }) => {
+ let app = new PlaywrightFixture(appFixture, page);
+ await app.goto("/action", true);
+ await app.clickElement("#submit-json");
+ await page.waitForSelector("#action-data");
+ expect(await app.getHtml()).toMatch('data: {"value":{"key":"value"}}');
+ });
+
+ test("submits text data", async ({ page }) => {
+ let app = new PlaywrightFixture(appFixture, page);
+ await app.goto("/action", true);
+ await app.clickElement("#submit-text");
+ await page.waitForSelector("#action-data");
+ expect(await app.getHtml()).toMatch('data: {"value":"raw text"}');
+ });
+
+ test("submits form data", async ({ page }) => {
+ let app = new PlaywrightFixture(appFixture, page);
+ await app.goto("/action", true);
+ await app.clickElement("#submit-formData");
+ await page.waitForSelector("#action-data");
+ expect(await app.getHtml()).toMatch('data: {"value":"key=value"}');
+ });
});
diff --git a/package.json b/package.json
index 2a19ece7deb..2a88b40c1d1 100644
--- a/package.json
+++ b/package.json
@@ -63,7 +63,7 @@
"@octokit/graphql": "^4.8.0",
"@octokit/plugin-paginate-rest": "^2.17.0",
"@octokit/rest": "^18.12.0",
- "@playwright/test": "^1.28.1",
+ "@playwright/test": "^1.35.1",
"@remix-run/changelog-github": "^0.0.5",
"@rollup/plugin-babel": "^5.2.2",
"@rollup/plugin-json": "^4.1.0",
diff --git a/packages/remix-react/components.tsx b/packages/remix-react/components.tsx
index fe116d92bcf..c77492a548d 100644
--- a/packages/remix-react/components.tsx
+++ b/packages/remix-react/components.tsx
@@ -1489,8 +1489,10 @@ export function useFetchers(): Fetcher[] {
data: f.data,
formMethod: f.formMethod,
formAction: f.formAction,
- formData: f.formData,
formEncType: f.formEncType,
+ formData: f.formData,
+ json: f.json,
+ text: f.text,
" _hasFetcherDoneAnything ": f[" _hasFetcherDoneAnything "],
});
addFetcherDeprecationWarnings(fetcher);
@@ -1523,8 +1525,10 @@ export function useFetcher(): FetcherWithComponents<
data: fetcherRR.data,
formMethod: fetcherRR.formMethod,
formAction: fetcherRR.formAction,
- formData: fetcherRR.formData,
formEncType: fetcherRR.formEncType,
+ formData: fetcherRR.formData,
+ json: fetcherRR.json,
+ text: fetcherRR.text,
" _hasFetcherDoneAnything ": fetcherRR[" _hasFetcherDoneAnything "],
});
let fetcherWithComponents = {
@@ -1575,8 +1579,16 @@ function addFetcherDeprecationWarnings(fetcher: Fetcher) {
function convertRouterFetcherToRemixFetcher(
fetcherRR: Omit, "load" | "submit" | "Form">
): Fetcher {
- let { state, formMethod, formAction, formEncType, formData, data } =
- fetcherRR;
+ let {
+ state,
+ formMethod,
+ formAction,
+ formEncType,
+ formData,
+ json,
+ text,
+ data,
+ } = fetcherRR;
let isActionSubmission =
formMethod != null &&
@@ -1589,8 +1601,10 @@ function convertRouterFetcherToRemixFetcher(
type: "done",
formMethod: undefined,
formAction: undefined,
- formData: undefined,
formEncType: undefined,
+ formData: undefined,
+ json: undefined,
+ text: undefined,
submission: undefined,
data,
};
@@ -1606,7 +1620,7 @@ function convertRouterFetcherToRemixFetcher(
formMethod &&
formAction &&
formEncType &&
- formData
+ (formData || json !== undefined || text !== undefined)
) {
if (isActionSubmission) {
// Actively submitting to an action
@@ -1614,14 +1628,21 @@ function convertRouterFetcherToRemixFetcher(
state,
type: "actionSubmission",
formMethod: formMethod.toUpperCase() as ActionSubmission["method"],
- formAction: formAction,
- formEncType: formEncType,
- formData: formData,
+ formAction,
+ formEncType,
+ formData,
+ json,
+ text,
+ // @ts-expect-error formData/json/text are mutually exclusive in the type,
+ // so TS can't be sure these meet that criteria, but as a straight
+ // assignment from the RR fetcher we know they will
submission: {
method: formMethod.toUpperCase() as ActionSubmission["method"],
action: formAction,
encType: formEncType,
- formData: formData,
+ formData,
+ json,
+ text,
key: "",
},
data,
@@ -1637,7 +1658,7 @@ function convertRouterFetcherToRemixFetcher(
}
if (state === "loading") {
- if (formMethod && formAction && formEncType && formData) {
+ if (formMethod && formAction && formEncType) {
if (isActionSubmission) {
if (data) {
// In a loading state but we have data - must be an actionReload
@@ -1645,14 +1666,21 @@ function convertRouterFetcherToRemixFetcher(
state,
type: "actionReload",
formMethod: formMethod.toUpperCase() as ActionSubmission["method"],
- formAction: formAction,
- formEncType: formEncType,
- formData: formData,
+ formAction,
+ formEncType,
+ formData,
+ json,
+ text,
+ // @ts-expect-error formData/json/text are mutually exclusive in the type,
+ // so TS can't be sure these meet that criteria, but as a straight
+ // assignment from the RR fetcher we know they will
submission: {
method: formMethod.toUpperCase() as ActionSubmission["method"],
action: formAction,
encType: formEncType,
- formData: formData,
+ formData,
+ json,
+ text,
key: "",
},
data,
@@ -1663,14 +1691,21 @@ function convertRouterFetcherToRemixFetcher(
state,
type: "actionRedirect",
formMethod: formMethod.toUpperCase() as ActionSubmission["method"],
- formAction: formAction,
- formEncType: formEncType,
- formData: formData,
+ formAction,
+ formEncType,
+ formData,
+ json,
+ text,
+ // @ts-expect-error formData/json/text are mutually exclusive in the type,
+ // so TS can't be sure these meet that criteria, but as a straight
+ // assignment from the RR fetcher we know they will
submission: {
method: formMethod.toUpperCase() as ActionSubmission["method"],
action: formAction,
encType: formEncType,
- formData: formData,
+ formData,
+ json,
+ text,
key: "",
},
data: undefined,
@@ -1684,27 +1719,36 @@ function convertRouterFetcherToRemixFetcher(
// will fix this bug.
let url = new URL(formAction, window.location.origin);
- // This typing override should be safe since this is only running for
- // GET submissions and over in @remix-run/router we have an invariant
- // if you have any non-string values in your FormData when we attempt
- // to convert them to URLSearchParams
- url.search = new URLSearchParams(
- formData.entries() as unknown as [string, string][]
- ).toString();
+ if (formData) {
+ // This typing override should be safe since this is only running for
+ // GET submissions and over in @remix-run/router we have an invariant
+ // if you have any non-string values in your FormData when we attempt
+ // to convert them to URLSearchParams
+ url.search = new URLSearchParams(
+ formData.entries() as unknown as [string, string][]
+ ).toString();
+ }
// Actively "submitting" to a loader
let fetcher: FetcherStates["SubmittingLoader"] = {
state: "submitting",
type: "loaderSubmission",
formMethod: formMethod.toUpperCase() as LoaderSubmission["method"],
- formAction: formAction,
- formEncType: formEncType,
- formData: formData,
+ formAction,
+ formEncType,
+ formData,
+ json,
+ text,
+ // @ts-expect-error formData/json/text are mutually exclusive in the type,
+ // so TS can't be sure these meet that criteria, but as a straight
+ // assignment from the RR fetcher we know they will
submission: {
method: formMethod.toUpperCase() as LoaderSubmission["method"],
action: url.pathname + url.search,
encType: formEncType,
- formData: formData,
+ formData,
+ json,
+ text,
key: "",
},
data,
@@ -1721,6 +1765,8 @@ function convertRouterFetcherToRemixFetcher(
formMethod: undefined,
formAction: undefined,
formData: undefined,
+ json: undefined,
+ text: undefined,
formEncType: undefined,
submission: undefined,
data,
diff --git a/packages/remix-react/data.ts b/packages/remix-react/data.ts
index 675b8413768..c2fde12f67e 100644
--- a/packages/remix-react/data.ts
+++ b/packages/remix-react/data.ts
@@ -40,12 +40,23 @@ export async function fetchData(
init.method = request.method;
let contentType = request.headers.get("Content-Type");
- init.body =
- // Check between word boundaries instead of startsWith() due to the last
- // paragraph of https://httpwg.org/specs/rfc9110.html#field.content-type
- contentType && /\bapplication\/x-www-form-urlencoded\b/.test(contentType)
- ? new URLSearchParams(await request.text())
- : await request.formData();
+
+ // Check between word boundaries instead of startsWith() due to the last
+ // paragraph of https://httpwg.org/specs/rfc9110.html#field.content-type
+ if (contentType && /\bapplication\/json\b/.test(contentType)) {
+ init.headers = { "Content-Type": contentType };
+ init.body = JSON.stringify(await request.json());
+ } else if (contentType && /\btext\/plain\b/.test(contentType)) {
+ init.headers = { "Content-Type": contentType };
+ init.body = await request.text();
+ } else if (
+ contentType &&
+ /\bapplication\/x-www-form-urlencoded\b/.test(contentType)
+ ) {
+ init.body = new URLSearchParams(await request.text());
+ } else {
+ init.body = await request.formData();
+ }
}
if (retry > 0) {
diff --git a/packages/remix-react/package.json b/packages/remix-react/package.json
index 29ab238282f..28de8216fba 100644
--- a/packages/remix-react/package.json
+++ b/packages/remix-react/package.json
@@ -16,8 +16,8 @@
"typings": "dist/index.d.ts",
"module": "dist/esm/index.js",
"dependencies": {
- "@remix-run/router": "1.6.3",
- "react-router-dom": "6.13.0"
+ "@remix-run/router": "1.7.0-pre.0",
+ "react-router-dom": "6.14.0-pre.0"
},
"devDependencies": {
"@remix-run/server-runtime": "1.17.1",
diff --git a/packages/remix-react/transition.ts b/packages/remix-react/transition.ts
index 713162e7767..ff937257562 100644
--- a/packages/remix-react/transition.ts
+++ b/packages/remix-react/transition.ts
@@ -75,6 +75,49 @@ export type TransitionStates = {
export type Transition = TransitionStates[keyof TransitionStates];
+// Thanks https://github.com/sindresorhus/type-fest!
+type JsonObject = { [Key in string]: JsonValue } & {
+ [Key in string]?: JsonValue | undefined;
+};
+type JsonArray = JsonValue[] | readonly JsonValue[];
+type JsonPrimitive = string | number | boolean | null;
+type JsonValue = JsonPrimitive | JsonObject | JsonArray;
+
+// Fetchers need a separate set of types to reflect the json/text submission
+// support in react-router. We do not carry that into useTransition since
+// it's deprecated
+type FetcherSubmissionDataTypes =
+ | {
+ formData: FormData;
+ json: undefined;
+ text: undefined;
+ }
+ | {
+ formData: undefined;
+ json: JsonValue;
+ text: undefined;
+ }
+ | {
+ formData: undefined;
+ json: undefined;
+ text: string;
+ };
+
+export type FetcherSubmission = {
+ action: string;
+ method: string;
+ encType: string;
+ key: string;
+} & FetcherSubmissionDataTypes;
+
+export type FetcherActionSubmission = FetcherSubmission & {
+ method: "POST" | "PUT" | "PATCH" | "DELETE";
+};
+
+export type FetcherLoaderSubmission = FetcherSubmission & {
+ method: "GET";
+};
+
// TODO: keep data around on resubmission?
export type FetcherStates = {
Idle: {
@@ -82,51 +125,49 @@ export type FetcherStates = {
type: "init";
formMethod: undefined;
formAction: undefined;
- formData: undefined;
formEncType: undefined;
+ formData: undefined;
+ json: undefined;
+ text: undefined;
submission: undefined;
data: undefined;
};
SubmittingAction: {
state: "submitting";
type: "actionSubmission";
- formMethod: ActionSubmission["method"];
+ formMethod: FetcherActionSubmission["method"];
formAction: string;
- formData: FormData;
formEncType: string;
- submission: ActionSubmission;
+ submission: FetcherActionSubmission;
data: TData | undefined;
- };
+ } & FetcherSubmissionDataTypes;
SubmittingLoader: {
state: "submitting";
type: "loaderSubmission";
- formMethod: LoaderSubmission["method"];
+ formMethod: FetcherLoaderSubmission["method"];
formAction: string;
- formData: FormData;
formEncType: string;
- submission: LoaderSubmission;
+ submission: FetcherLoaderSubmission;
data: TData | undefined;
- };
+ } & FetcherSubmissionDataTypes;
ReloadingAction: {
state: "loading";
type: "actionReload";
- formMethod: ActionSubmission["method"];
+ formMethod: FetcherActionSubmission["method"];
formAction: string;
- formData: FormData;
formEncType: string;
- submission: ActionSubmission;
+ submission: FetcherActionSubmission;
data: TData;
- };
+ } & FetcherSubmissionDataTypes;
LoadingActionRedirect: {
state: "loading";
type: "actionRedirect";
- formMethod: ActionSubmission["method"];
+ formMethod: FetcherActionSubmission["method"];
formAction: string;
- formData: FormData;
formEncType: string;
- submission: ActionSubmission;
+ submission: FetcherActionSubmission;
data: undefined;
- };
+ } & FetcherSubmissionDataTypes;
Loading: {
state: "loading";
type: "normalLoad";
@@ -134,6 +175,8 @@ export type FetcherStates = {
formAction: undefined;
formData: undefined;
formEncType: undefined;
+ json: undefined;
+ text: undefined;
submission: undefined;
data: TData | undefined;
};
@@ -142,8 +185,10 @@ export type FetcherStates = {
type: "done";
formMethod: undefined;
formAction: undefined;
- formData: undefined;
formEncType: undefined;
+ formData: undefined;
+ json: undefined;
+ text: undefined;
submission: undefined;
data: TData;
};
@@ -165,7 +210,9 @@ export const IDLE_FETCHER: FetcherStates["Idle"] = {
data: undefined,
formMethod: undefined,
formAction: undefined,
- formData: undefined,
formEncType: undefined,
+ formData: undefined,
+ json: undefined,
+ text: undefined,
submission: undefined,
};
diff --git a/packages/remix-server-runtime/package.json b/packages/remix-server-runtime/package.json
index 8d373eb52bc..222e27a0d57 100644
--- a/packages/remix-server-runtime/package.json
+++ b/packages/remix-server-runtime/package.json
@@ -16,7 +16,7 @@
"typings": "dist/index.d.ts",
"module": "dist/esm/index.js",
"dependencies": {
- "@remix-run/router": "1.6.3",
+ "@remix-run/router": "1.7.0-pre.0",
"@types/cookie": "^0.4.1",
"@web3-storage/multipart-parser": "^1.0.0",
"cookie": "^0.4.1",
diff --git a/packages/remix-testing/package.json b/packages/remix-testing/package.json
index 3d85b69276a..776a02d0424 100644
--- a/packages/remix-testing/package.json
+++ b/packages/remix-testing/package.json
@@ -18,8 +18,8 @@
"dependencies": {
"@remix-run/node": "1.17.1",
"@remix-run/react": "1.17.1",
- "@remix-run/router": "1.6.3",
- "react-router-dom": "6.13.0"
+ "@remix-run/router": "1.7.0-pre.0",
+ "react-router-dom": "6.14.0-pre.0"
},
"devDependencies": {
"@types/node": "^18.11.9",
diff --git a/yarn.lock b/yarn.lock
index a1ceb84ac7b..e226ee9eb70 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -2569,13 +2569,15 @@
tiny-glob "^0.2.9"
tslib "^2.4.0"
-"@playwright/test@^1.28.1":
- version "1.28.1"
- resolved "https://registry.npmjs.org/@playwright/test/-/test-1.28.1.tgz"
- integrity sha512-xN6spdqrNlwSn9KabIhqfZR7IWjPpFK1835tFNgjrlysaSezuX8PYUwaz38V/yI8TJLG9PkAMEXoHRXYXlpTPQ==
+"@playwright/test@^1.35.1":
+ version "1.35.1"
+ resolved "https://registry.npmjs.org/@playwright/test/-/test-1.35.1.tgz#a596b61e15b980716696f149cc7a2002f003580c"
+ integrity sha512-b5YoFe6J9exsMYg0pQAobNDR85T1nLumUYgUTtKm4d21iX2L7WqKq9dW8NGJ+2vX0etZd+Y7UeuqsxDXm9+5ZA==
dependencies:
"@types/node" "*"
- playwright-core "1.28.1"
+ playwright-core "1.35.1"
+ optionalDependencies:
+ fsevents "2.3.2"
"@remix-run/changelog-github@^0.0.5":
version "0.0.5"
@@ -2587,10 +2589,10 @@
"@changesets/types" "^5.0.0"
dotenv "^8.1.0"
-"@remix-run/router@1.6.3":
- version "1.6.3"
- resolved "https://registry.npmjs.org/@remix-run/router/-/router-1.6.3.tgz#8205baf6e17ef93be35bf62c37d2d594e9be0dad"
- integrity sha512-EXJysQ7J3veRECd0kZFQwYYd5sJMcq2O/m60zu1W2l3oVQ9xtub8jTOtYRE0+M2iomyG/W3Ps7+vp2kna0C27Q==
+"@remix-run/router@1.7.0-pre.0":
+ version "1.7.0-pre.0"
+ resolved "https://registry.npmjs.org/@remix-run/router/-/router-1.7.0-pre.0.tgz#913e0803ac70291c47537eb20397e01532dbc1a2"
+ integrity sha512-i0sJFZG0glzgAt6fXfkSHk5rsKOM8DSSH063gKO5sKUHvfQJZn8av4d/BMrwymr3KaFLqkl9m3FXepbEk7XzqA==
"@remix-run/web-blob@^3.0.3", "@remix-run/web-blob@^3.0.4":
version "3.0.4"
@@ -7167,7 +7169,7 @@ fs.realpath@^1.0.0:
resolved "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz"
integrity sha1-FQStJSMVjKpA20onh8sBQRmU6k8=
-fsevents@^2.3.2, fsevents@~2.3.2:
+fsevents@2.3.2, fsevents@^2.3.2, fsevents@~2.3.2:
version "2.3.2"
resolved "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz"
integrity sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==
@@ -10981,10 +10983,10 @@ pkg-types@^1.0.1:
mlly "^1.0.0"
pathe "^1.0.0"
-playwright-core@1.28.1:
- version "1.28.1"
- resolved "https://registry.npmjs.org/playwright-core/-/playwright-core-1.28.1.tgz"
- integrity sha512-3PixLnGPno0E8rSBJjtwqTwJe3Yw72QwBBBxNoukIj3lEeBNXwbNiKrNuB1oyQgTBw5QHUhNO3SteEtHaMK6ag==
+playwright-core@1.35.1:
+ version "1.35.1"
+ resolved "https://registry.npmjs.org/playwright-core/-/playwright-core-1.35.1.tgz#52c1e6ffaa6a8c29de1a5bdf8cce0ce290ffb81d"
+ integrity sha512-pNXb6CQ7OqmGDRspEjlxE49w+4YtR6a3X6mT1hZXeJHWmsEz7SunmvZeiG/+y1yyMZdHnnn73WKYdtV1er0Xyg==
pointer-symbol@^1.0.0:
version "1.0.0"
@@ -11435,20 +11437,20 @@ react-refresh@^0.14.0:
resolved "https://registry.npmjs.org/react-refresh/-/react-refresh-0.14.0.tgz"
integrity sha512-wViHqhAd8OHeLS/IRMJjTSDHF3U9eWi62F/MledQGPdJGDhodXJ9PBLNGr6WWL7qlH12Mt3TyTpbS+hGXMjCzQ==
-react-router-dom@6.13.0:
- version "6.13.0"
- resolved "https://registry.npmjs.org/react-router-dom/-/react-router-dom-6.13.0.tgz#6651f456bb2af42ef14f6880123b1f575539e81f"
- integrity sha512-6Nqoqd7fgwxxVGdbiMHTpDHCYPq62d7Wk1Of7B82vH7ZPwwsRaIa22zRZKPPg413R5REVNiyuQPKDG1bubcOFA==
+react-router-dom@6.14.0-pre.0:
+ version "6.14.0-pre.0"
+ resolved "https://registry.npmjs.org/react-router-dom/-/react-router-dom-6.14.0-pre.0.tgz#8e106739c776f48c0d3710aae69bac42ddf09a3f"
+ integrity sha512-NndsLa0FHP8BDUePOnpiQqunDaoY1e0PljjqTQDxHMeCZqf1148S8hl54ZF6rXoA4EuACszVSrURIrAhZ++ljg==
dependencies:
- "@remix-run/router" "1.6.3"
- react-router "6.13.0"
+ "@remix-run/router" "1.7.0-pre.0"
+ react-router "6.14.0-pre.0"
-react-router@6.13.0:
- version "6.13.0"
- resolved "https://registry.npmjs.org/react-router/-/react-router-6.13.0.tgz#7e4427a271dae0cafbdb88c56ccbd9b1434ee93f"
- integrity sha512-Si6KnfEnJw7gUQkNa70dlpI1bul46FuSxX5t5WwlUBxE25DAz2BjVkwaK8Y2s242bQrZPXCpmwLPtIO5pv4tXg==
+react-router@6.14.0-pre.0:
+ version "6.14.0-pre.0"
+ resolved "https://registry.npmjs.org/react-router/-/react-router-6.14.0-pre.0.tgz#38d8ace45232b5d6cbcaf8b68d6af76a584f5e02"
+ integrity sha512-xNXcEDQ7pjKpw4ueFhmbksnVaRuyXng4OXXBg9RsM16FyJDSUUKXruygjrDiVeyGeAGjIiDDNUX/G6EwF3aS9w==
dependencies:
- "@remix-run/router" "1.6.3"
+ "@remix-run/router" "1.7.0-pre.0"
react@^18.2.0:
version "18.2.0"