diff --git a/packages/react-router/__tests__/dom/partial-hydration-test.tsx b/packages/react-router/__tests__/dom/partial-hydration-test.tsx index 27fafc232e..7f6c9e259d 100644 --- a/packages/react-router/__tests__/dom/partial-hydration-test.tsx +++ b/packages/react-router/__tests__/dom/partial-hydration-test.tsx @@ -88,6 +88,7 @@ describe("Partial Hydration Behavior", () => { } ); let { container } = render( + // eslint-disable-next-line react/jsx-pascal-case ); @@ -176,6 +177,7 @@ describe("Partial Hydration Behavior", () => { } ); let { container } = render( + // eslint-disable-next-line react/jsx-pascal-case ); diff --git a/packages/react-router/lib/components.tsx b/packages/react-router/lib/components.tsx index 8caf152e6b..9aa96dd231 100644 --- a/packages/react-router/lib/components.tsx +++ b/packages/react-router/lib/components.tsx @@ -215,11 +215,7 @@ export function RouterProvider({ let setState = React.useCallback( ( newState: RouterState, - { - deletedFetchers, - flushSync: flushSync, - viewTransitionOpts: viewTransitionOpts, - } + { deletedFetchers, flushSync, viewTransitionOpts } ) => { deletedFetchers.forEach((key) => fetcherData.current.delete(key)); newState.fetchers.forEach((fetcher, key) => { diff --git a/packages/react-router/lib/router/router.ts b/packages/react-router/lib/router/router.ts index bd7f421a7c..0ec3d5438c 100644 --- a/packages/react-router/lib/router/router.ts +++ b/packages/react-router/lib/router/router.ts @@ -998,13 +998,6 @@ export function createRouter(init: RouterInit): Router { // we don't need to update UI state if they change let blockerFunctions = new Map(); - // Map of pending patchRoutesOnNavigation() promises (keyed by path/matches) so - // that we only kick them off once for a given combo - let pendingPatchRoutes = new Map< - string, - ReturnType - >(); - // Flag to ignore the next history update, so we can revert the URL change on // a POP navigation that was blocked by the user without touching router state let unblockBlockerHistoryUpdate: (() => void) | undefined = undefined; @@ -2750,7 +2743,7 @@ export function createRouter(init: RouterInit): Router { } for (let [routeId, result] of Object.entries(results)) { - if (isRedirectDataStrategyResultResult(result)) { + if (isRedirectDataStrategyResult(result)) { let response = result.result as Response; dataResults[routeId] = { type: ResultType.redirect, @@ -2779,8 +2772,6 @@ export function createRouter(init: RouterInit): Router { fetchersToLoad: RevalidatingFetcher[], request: Request ) { - let currentMatches = state.matches; - // Kick off loaders and fetchers in parallel let loaderResultsPromise = callDataStrategy( "loader", @@ -3861,7 +3852,7 @@ export function createStaticHandler( return; } let result = results[match.route.id]; - if (isRedirectDataStrategyResultResult(result)) { + if (isRedirectDataStrategyResult(result)) { let response = result.result as Response; // Throw redirects and let the server handle them with an HTTP redirect throw normalizeRelativeRoutingRedirectResponse( @@ -5349,10 +5340,6 @@ function isHashChangeOnly(a: Location, b: Location): boolean { return false; } -function isPromise(val: unknown): val is Promise { - return typeof val === "object" && val != null && "then" in val; -} - function isDataStrategyResult(result: unknown): result is DataStrategyResult { return ( result != null && @@ -5363,7 +5350,7 @@ function isDataStrategyResult(result: unknown): result is DataStrategyResult { ); } -function isRedirectDataStrategyResultResult(result: DataStrategyResult) { +function isRedirectDataStrategyResult(result: DataStrategyResult) { return ( isResponse(result.result) && redirectStatusCodes.has(result.result.status) ); diff --git a/packages/react-router/lib/server-runtime/headers.ts b/packages/react-router/lib/server-runtime/headers.ts index 21ebc7f720..3c8cfe04b6 100644 --- a/packages/react-router/lib/server-runtime/headers.ts +++ b/packages/react-router/lib/server-runtime/headers.ts @@ -44,7 +44,7 @@ export function getDocumentHeaders( // Only expose errorHeaders to the leaf headers() function to // avoid duplication via parentHeaders let includeErrorHeaders = - errorHeaders != undefined && idx === matches.length - 1; + errorHeaders != null && idx === matches.length - 1; // Only prepend cookies from errorHeaders at the leaf renderable route // when it's not the same as loaderHeaders/actionHeaders to avoid // duplicate cookies diff --git a/packages/react-router/lib/server-runtime/jsonify.ts b/packages/react-router/lib/server-runtime/jsonify.ts deleted file mode 100644 index 43b1f97769..0000000000 --- a/packages/react-router/lib/server-runtime/jsonify.ts +++ /dev/null @@ -1,257 +0,0 @@ -import type { Equal, Expect, MutualExtends } from "./typecheck"; -import { expectType } from "./typecheck"; - -// prettier-ignore -// `Jsonify` emulates `let y = JSON.parse(JSON.stringify(x))`, but for types -// so that we can infer the shape of the data sent over the network. -export type Jsonify = - // any - IsAny extends true ? any : - - // toJSON - T extends { toJSON(): infer U } ? (U extends JsonValue ? U : unknown) : - - // primitives - T extends JsonPrimitive ? T : - T extends String ? string : - T extends Number ? number : - T extends Boolean ? boolean : - - // Promises JSON.stringify to an empty object - T extends Promise ? EmptyObject : - - // Map & Set - T extends Map ? EmptyObject : - T extends Set ? EmptyObject : - - // TypedArray - T extends TypedArray ? Record : - - // Not JSON serializable - T extends NotJson ? never : - - // tuple & array - T extends [] ? [] : - T extends readonly [infer F, ...infer R] ? [NeverToNull>, ...Jsonify] : - T extends readonly unknown[] ? Array>>: - - // object - T extends Record ? JsonifyObject : - - // unknown - unknown extends T ? unknown : - - never - -// value is always not JSON => true -// value is always JSON => false -// value is somtimes JSON, sometimes not JSON => boolean -// note: cannot be inlined as logic requires union distribution -type ValueIsNotJson = T extends NotJson ? true : false; - -// note: remove optionality so that produced values are never `undefined`, -// only `true`, `false`, or `boolean` -type IsNotJson = { [K in keyof T]-?: ValueIsNotJson }; - -type JsonifyValues = { [K in keyof T]: Jsonify }; - -// prettier-ignore -type JsonifyObject> = - // required - { [K in keyof T as - unknown extends T[K] ? never : - IsNotJson[K] extends false ? K : - never - ]: JsonifyValues[K] } & - // optional - { [K in keyof T as - unknown extends T[K] ? K : - // if the value is always JSON, then it's not optional - IsNotJson[K] extends false ? never : - // if the value is always not JSON, omit it entirely - IsNotJson[K] extends true ? never : - // if the value is mixed, then it's optional - K - ]? : JsonifyValues[K]} - -// types ------------------------------------------------------------ - -type JsonPrimitive = string | number | boolean | null; - -type JsonArray = JsonValue[] | readonly JsonValue[]; - -// prettier-ignore -type JsonObject = - { [K in string]: JsonValue } & - { [K in string]?: JsonValue } - -type JsonValue = JsonPrimitive | JsonObject | JsonArray; - -type NotJson = undefined | symbol | AnyFunction; - -type TypedArray = - | Int8Array - | Uint8Array - | Uint8ClampedArray - | Int16Array - | Uint16Array - | Int32Array - | Uint32Array - | Float32Array - | Float64Array - | BigInt64Array - | BigUint64Array; - -// tests ------------------------------------------------------------ - -// prettier-ignore -// eslint-disable-next-line @typescript-eslint/no-unused-vars -type _tests = [ - // any - Expect, any>>, - - // primitives - Expect, string>>, - Expect, number>>, - Expect, boolean>>, - Expect, null>>, - Expect, string>>, - Expect, number>>, - Expect, boolean>>, - Expect>, EmptyObject>>, - - // Map & Set - Expect>, EmptyObject>>, - Expect>, EmptyObject>>, - - // TypedArray - Expect, Record>>, - Expect, Record>>, - Expect, Record>>, - Expect, Record>>, - Expect, Record>>, - Expect, Record>>, - Expect, Record>>, - Expect, Record>>, - Expect, Record>>, - Expect, Record>>, - Expect, Record>>, - - // Not Json - Expect, never>>, - Expect, never>>, - Expect void>, never>>, - Expect, never>>, - - // toJson - Expect, "stuff">>, - Expect, string>>, - Expect, unknown>>, - Expect, unknown>>, - Expect, string>>, - - - // tuple & array - Expect, []>>, - Expect, [1, 'two', string, null, false]>>, - Expect, (string | number)[]>>, - Expect, null[]>>, - Expect, [1,2,3]>>, - - // object - Expect>, {}>>, - Expect>, {a: string}>>, - Expect>, {a?: string}>>, - Expect>, {a?: string}>>, - Expect>, {a: string, b?: string}>>, - Expect>, {}>>, - Expect>>, Record>>, - Expect>>, Record>>, - Expect}>, { payload: Record}>>, - Expect any); - optionalFunctionUnion?: string | (() => any); - optionalFunctionUnionUndefined: string | (() => any) | undefined; - - // Should be omitted - requiredFunction: () => any; - optionalFunction?: () => any; - optionalFunctionUndefined: (() => any) | undefined; - }>>, { - requiredString: string - requiredUnion: number | boolean - - optionalString?: string; - optionalUnion?: number | string; - optionalStringUndefined?: string | undefined; - optionalUnionUndefined?: number | string | undefined; - requiredFunctionUnion?: string - optionalFunctionUnion?: string; - optionalFunctionUnionUndefined?: string - }>>, - - // unknown - Expect, unknown>>, - Expect, unknown[]>>, - Expect, [unknown, 1]>>, - Expect>, {a?: unknown}>>, - Expect>, {a?: unknown, b: 'hello'}>>, - - // never - Expect, never>>, - Expect>, {a: never}>>, - Expect>, {a: never, b:string}>>, - Expect>, {a: never, b: string} | {a: string, b: never}>>, - - // class - Expect>, {a: string}>>, -]; - -class MyClass { - a: string; - b: () => string; - - constructor() { - this.a = "hello"; - this.b = () => "world"; - } -} - -// real-world example: `InvoiceLineItem` from `stripe` -type Recursive = { - a: Date; - recur?: Recursive; -}; -declare const recursive: Jsonify; -expectType<{ a: string; recur?: Jsonify }>( - recursive.recur!.recur!.recur! -); - -// real-world example: `Temporal` from `@js-temporal/polyfill` -interface BooleanWithToJson extends Boolean { - toJSON(): string; -} - -// utils ------------------------------------------------------------ - -type Pretty = { [K in keyof T]: T[K] }; - -type AnyFunction = (...args: any[]) => unknown; - -type NeverToNull = [T] extends [never] ? null : T; - -// adapted from https://github.com/sindresorhus/type-fest/blob/main/source/empty-object.d.ts -declare const emptyObjectSymbol: unique symbol; -export type EmptyObject = { [emptyObjectSymbol]?: never }; - -// adapted from https://github.com/type-challenges/type-challenges/blob/main/utils/index.d.ts -type IsAny = 0 extends 1 & T ? true : false; diff --git a/packages/react-router/lib/types.ts b/packages/react-router/lib/types.ts index 99d9265614..9198cf5244 100644 --- a/packages/react-router/lib/types.ts +++ b/packages/react-router/lib/types.ts @@ -1,6 +1,5 @@ import type { DataWithResponseInit } from "./router/utils"; import type { AppLoadContext } from "./server-runtime/data"; -import type { Jsonify } from "./server-runtime/jsonify"; import type { Serializable } from "./server-runtime/single-fetch"; export type Expect = T; diff --git a/templates/basic/postcss.config.js b/templates/basic/postcss.config.js index 2aa7205d4b..a982c6414e 100644 --- a/templates/basic/postcss.config.js +++ b/templates/basic/postcss.config.js @@ -1,6 +1,8 @@ -export default { +const config = { plugins: { tailwindcss: {}, autoprefixer: {}, }, }; + +export default config;