@remix-run/react
Advanced tools
Comparing version 0.0.0-experimental-7de3dd2b to 0.0.0-experimental-80f6d2e1
/** | ||
* @remix-run/react v0.0.0-experimental-7de3dd2b | ||
* @remix-run/react v0.0.0-experimental-80f6d2e1 | ||
* | ||
@@ -4,0 +4,0 @@ * Copyright (c) Remix Software Inc. |
/** | ||
* @remix-run/react v0.0.0-experimental-7de3dd2b | ||
* @remix-run/react v0.0.0-experimental-80f6d2e1 | ||
* | ||
@@ -39,2 +39,4 @@ * Copyright (c) Remix Software Inc. | ||
// TODO: We eventually might not want to import anything directly from `history` | ||
/** | ||
@@ -41,0 +43,0 @@ * The entry point for a Remix app when it is rendered in the browser (in |
@@ -7,7 +7,27 @@ import type { Action, Location } from "history"; | ||
import type { AppData, FormEncType, FormMethod } from "./data"; | ||
import type { EntryContext } from "./entry"; | ||
import type { EntryContext, AssetsManifest } from "./entry"; | ||
import type { AppState } from "./errors"; | ||
import type { PrefetchPageDescriptor } from "./links"; | ||
import type { ClientRoute } from "./routes"; | ||
import type { RouteData } from "./routeData"; | ||
import type { RouteMatch } from "./routeMatching"; | ||
import type { RouteModules } from "./routeModules"; | ||
import { createTransitionManager } from "./transition"; | ||
import type { Transition, Fetcher } from "./transition"; | ||
export declare function RemixEntry({ context: entryContext, action, location: historyLocation, navigator: _navigator, static: staticProp }: { | ||
interface RemixEntryContextType { | ||
manifest: AssetsManifest; | ||
matches: RouteMatch<ClientRoute>[]; | ||
routeData: { | ||
[routeId: string]: RouteData; | ||
}; | ||
actionData?: RouteData; | ||
pendingLocation?: Location; | ||
appState: AppState; | ||
routeModules: RouteModules; | ||
serverHandoffString?: string; | ||
clientRoutes: ClientRoute[]; | ||
transitionManager: ReturnType<typeof createTransitionManager>; | ||
} | ||
export declare const RemixEntryContext: React.Context<RemixEntryContextType | undefined>; | ||
export declare function RemixEntry({ context: entryContext, action, location: historyLocation, navigator: _navigator, static: staticProp, }: { | ||
context: EntryContext; | ||
@@ -25,3 +45,3 @@ action: Action; | ||
* | ||
* - "intent": Default, fetched when the user focuses or hovers the link | ||
* - "intent": Fetched when the user focuses or hovers the link | ||
* - "render": Fetched when the link is rendered | ||
@@ -37,12 +57,38 @@ * - "none": Never fetched | ||
} | ||
export declare let NavLink: React.ForwardRefExoticComponent<RemixNavLinkProps & React.RefAttributes<HTMLAnchorElement>>; | ||
export declare let Link: React.ForwardRefExoticComponent<RemixLinkProps & React.RefAttributes<HTMLAnchorElement>>; | ||
/** | ||
* A special kind of `<Link>` that knows whether or not it is "active". | ||
* | ||
* @see https://remix.run/api/remix#navlink | ||
*/ | ||
declare let NavLink: React.ForwardRefExoticComponent<RemixNavLinkProps & React.RefAttributes<HTMLAnchorElement>>; | ||
export { NavLink }; | ||
/** | ||
* This component renders an anchor tag and is the primary way the user will | ||
* navigate around your website. | ||
* | ||
* @see https://remix.run/api/remix#link | ||
*/ | ||
declare let Link: React.ForwardRefExoticComponent<RemixLinkProps & React.RefAttributes<HTMLAnchorElement>>; | ||
export { Link }; | ||
export declare function composeEventHandlers<EventType extends React.SyntheticEvent | Event>(theirHandler: ((event: EventType) => any) | undefined, ourHandler: (event: EventType) => any): (event: EventType) => any; | ||
/** | ||
* Renders the `<link>` tags for the current routes. | ||
* | ||
* @see https://remix.run/api/remix#meta-links-scripts | ||
*/ | ||
export declare function Links(): JSX.Element; | ||
/** | ||
* This component renders all of the `<link rel="prefetch">` and | ||
* `<link rel="modulepreload"/>` tags for all the assets (data, modules, css) of | ||
* a given page. | ||
* | ||
* @param props | ||
* @param props.page | ||
* @see https://remix.run/api/remix#prefetchpagelinks- | ||
*/ | ||
export declare function PrefetchPageLinks({ page, ...dataLinkProps }: PrefetchPageDescriptor): JSX.Element | null; | ||
/** | ||
* Renders the `<title>` and `<meta>` tags for the current routes. | ||
* | ||
* @see https://remix.run/api/remix#meta-links-scripts | ||
*/ | ||
@@ -58,2 +104,4 @@ export declare function Meta(): JSX.Element; | ||
* property if provided. | ||
* | ||
* @see https://remix.run/api/remix#meta-links-scripts | ||
*/ | ||
@@ -77,4 +125,4 @@ export declare function Scripts(props: ScriptProps): JSX.Element; | ||
* | ||
* Note: Remix only supports `application/x-www-form-urlencoded` right now | ||
* but will soon support `multipart/form-data` as well. | ||
* Note: Remix defaults to `application/x-www-form-urlencoded` and also | ||
* supports `multipart/form-data`. | ||
*/ | ||
@@ -103,10 +151,16 @@ encType?: FormEncType; | ||
* submitted and returns with data. | ||
* | ||
* @see https://remix.run/api/remix#form | ||
*/ | ||
export declare let Form: React.ForwardRefExoticComponent<FormProps & React.RefAttributes<HTMLFormElement>>; | ||
declare let Form: React.ForwardRefExoticComponent<FormProps & React.RefAttributes<HTMLFormElement>>; | ||
export { Form }; | ||
interface FormImplProps extends FormProps { | ||
fetchKey?: string; | ||
} | ||
export declare let FormImpl: React.ForwardRefExoticComponent<FormImplProps & React.RefAttributes<HTMLFormElement>>; | ||
declare let FormImpl: React.ForwardRefExoticComponent<FormImplProps & React.RefAttributes<HTMLFormElement>>; | ||
export { FormImpl }; | ||
/** | ||
* Resolves a `<form action>` path relative to the current route. | ||
* | ||
* @see https://remix.run/api/remix#useformaction | ||
*/ | ||
@@ -165,2 +219,4 @@ export declare function useFormAction(action?: string, method?: FormMethod): string; | ||
* some arbitrary data) to the server. | ||
* | ||
* @see https://remix.run/api/remix#usesubmit | ||
*/ | ||
@@ -177,4 +233,12 @@ export declare function useSubmit(): SubmitFunction; | ||
* `React.useCallback()`. | ||
* | ||
* @see https://remix.run/api/remix#usebeforeunload | ||
*/ | ||
export declare function useBeforeUnload(callback: () => any): void; | ||
/** | ||
* Returns the current route matches on the page. This is useful for creating | ||
* layout abstractions with your current routes. | ||
* | ||
* @see https://remix.run/api/remix#usematches | ||
*/ | ||
export declare function useMatches(): { | ||
@@ -188,6 +252,19 @@ id: string; | ||
/** | ||
* Returns the data from the current route's `loader`. | ||
* Returns the JSON parsed data from the current route's `loader`. | ||
* | ||
* @see https://remix.run/api/remix#useloaderdata | ||
*/ | ||
export declare function useLoaderData<T = AppData>(): T; | ||
/** | ||
* Returns the JSON parsed data from the current route's `action`. | ||
* | ||
* @see https://remix.run/api/remix#useactiondata | ||
*/ | ||
export declare function useActionData<T = AppData>(): T | undefined; | ||
/** | ||
* Returns everything you need to know about a page transition to build pending | ||
* navigation indicators and optimistic UI on data mutations. | ||
* | ||
* @see https://remix.run/api/remix#usetransition | ||
*/ | ||
export declare function useTransition(): Transition; | ||
@@ -203,2 +280,4 @@ declare function createFetcherForm(fetchKey: string): React.ForwardRefExoticComponent<FormProps & React.RefAttributes<HTMLFormElement>>; | ||
* for any interaction that stays on the same page. | ||
* | ||
* @see https://remix.run/api/remix#usefetcher | ||
*/ | ||
@@ -209,7 +288,8 @@ export declare function useFetcher<TData = any>(): FetcherWithComponents<TData>; | ||
* routes that need to provide pending/optimistic UI regarding the fetch. | ||
* | ||
* @see https://remix.run/api/remix#usefetchers | ||
*/ | ||
export declare function useFetchers(): Fetcher[]; | ||
export declare const LiveReload: (() => null) | (({ port }: { | ||
export declare const LiveReload: (() => null) | (({ port, }: { | ||
port?: number | undefined; | ||
}) => JSX.Element); | ||
export {}; |
/** | ||
* @remix-run/react v0.0.0-experimental-7de3dd2b | ||
* @remix-run/react v0.0.0-experimental-80f6d2e1 | ||
* | ||
@@ -296,3 +296,3 @@ * Copyright (c) Remix Software Inc. | ||
* | ||
* - "intent": Default, fetched when the user focuses or hovers the link | ||
* - "intent": Fetched when the user focuses or hovers the link | ||
* - "render": Fetched when the link is rendered | ||
@@ -348,3 +348,9 @@ * - "none": Never fetched | ||
} | ||
/** | ||
* A special kind of `<Link>` that knows whether or not it is "active". | ||
* | ||
* @see https://remix.run/api/remix#navlink | ||
*/ | ||
let NavLink = /*#__PURE__*/React__namespace.forwardRef(({ | ||
@@ -360,6 +366,14 @@ to, | ||
to: to | ||
}, prefetchHandlers, props)), shouldPrefetch ? /*#__PURE__*/React__namespace.createElement(PrefetchPageLinks, { | ||
}, props, prefetchHandlers)), shouldPrefetch ? /*#__PURE__*/React__namespace.createElement(PrefetchPageLinks, { | ||
page: href | ||
}) : null); | ||
}); | ||
NavLink.displayName = "NavLink"; | ||
/** | ||
* This component renders an anchor tag and is the primary way the user will | ||
* navigate around your website. | ||
* | ||
* @see https://remix.run/api/remix#link | ||
*/ | ||
let Link = /*#__PURE__*/React__namespace.forwardRef(({ | ||
@@ -375,6 +389,7 @@ to, | ||
to: to | ||
}, prefetchHandlers, props)), shouldPrefetch ? /*#__PURE__*/React__namespace.createElement(PrefetchPageLinks, { | ||
}, props, prefetchHandlers)), shouldPrefetch ? /*#__PURE__*/React__namespace.createElement(PrefetchPageLinks, { | ||
page: href | ||
}) : null); | ||
}); | ||
Link.displayName = "Link"; | ||
function composeEventHandlers(theirHandler, ourHandler) { | ||
@@ -391,2 +406,4 @@ return event => { | ||
* Renders the `<link>` tags for the current routes. | ||
* | ||
* @see https://remix.run/api/remix#meta-links-scripts | ||
*/ | ||
@@ -407,2 +424,12 @@ | ||
} | ||
/** | ||
* This component renders all of the `<link rel="prefetch">` and | ||
* `<link rel="modulepreload"/>` tags for all the assets (data, modules, css) of | ||
* a given page. | ||
* | ||
* @param props | ||
* @param props.page | ||
* @see https://remix.run/api/remix#prefetchpagelinks- | ||
*/ | ||
function PrefetchPageLinks({ | ||
@@ -481,2 +508,4 @@ page, | ||
* Renders the `<title>` and `<meta>` tags for the current routes. | ||
* | ||
* @see https://remix.run/api/remix#meta-links-scripts | ||
*/ | ||
@@ -553,2 +582,4 @@ | ||
* property if provided. | ||
* | ||
* @see https://remix.run/api/remix#meta-links-scripts | ||
*/ | ||
@@ -619,2 +650,4 @@ function Scripts(props) { | ||
* submitted and returns with data. | ||
* | ||
* @see https://remix.run/api/remix#form | ||
*/ | ||
@@ -626,2 +659,3 @@ let Form = /*#__PURE__*/React__namespace.forwardRef((props, ref) => { | ||
}); | ||
Form.displayName = "Form"; | ||
let FormImpl = /*#__PURE__*/React__namespace.forwardRef(({ | ||
@@ -663,6 +697,6 @@ reloadDocument = false, | ||
function handleClick(event) { | ||
if (!(event.target instanceof HTMLElement)) return; | ||
if (!(event.target instanceof Element)) return; | ||
let submitButton = event.target.closest("button,input[type=submit]"); | ||
if (submitButton && submitButton.type === "submit") { | ||
if (submitButton && submitButton.form === form && submitButton.type === "submit") { | ||
clickedButtonRef.current = submitButton; | ||
@@ -672,5 +706,5 @@ } | ||
form.addEventListener("click", handleClick); | ||
window.addEventListener("click", handleClick); | ||
return () => { | ||
form && form.removeEventListener("click", handleClick); | ||
window.removeEventListener("click", handleClick); | ||
}; | ||
@@ -695,2 +729,3 @@ }, []); | ||
}); | ||
FormImpl.displayName = "FormImpl"; | ||
@@ -703,2 +738,4 @@ function isActionRequestMethod(method) { | ||
* Resolves a `<form action>` path relative to the current route. | ||
* | ||
* @see https://remix.run/api/remix#useformaction | ||
*/ | ||
@@ -725,2 +762,4 @@ | ||
* some arbitrary data) to the server. | ||
* | ||
* @see https://remix.run/api/remix#usesubmit | ||
*/ | ||
@@ -730,2 +769,4 @@ function useSubmit() { | ||
} | ||
let defaultMethod = "get"; | ||
let defaultEncType = "application/x-www-form-urlencoded"; | ||
function useSubmitImpl(key) { | ||
@@ -745,5 +786,5 @@ let navigate = reactRouterDom.useNavigate(); | ||
let submissionTrigger = options.submissionTrigger; | ||
method = options.method || target.method; | ||
action = options.action || target.action; | ||
encType = options.encType || target.enctype; | ||
method = options.method || target.getAttribute("method") || defaultMethod; | ||
action = options.action || target.getAttribute("action") || defaultAction; | ||
encType = options.encType || target.getAttribute("enctype") || defaultEncType; | ||
formData = new FormData(target); | ||
@@ -762,5 +803,5 @@ | ||
method = options.method || target.getAttribute("formmethod") || form.method; | ||
action = options.action || target.getAttribute("formaction") || form.action; | ||
encType = options.encType || target.getAttribute("formenctype") || form.enctype; | ||
method = options.method || target.getAttribute("formmethod") || form.getAttribute("method") || defaultMethod; | ||
action = options.action || target.getAttribute("formaction") || form.getAttribute("action") || defaultAction; | ||
encType = options.encType || target.getAttribute("formenctype") || form.getAttribute("enctype") || defaultEncType; | ||
formData = new FormData(form); // Include name + value from a <button> | ||
@@ -797,2 +838,6 @@ | ||
if (typeof document === "undefined") { | ||
throw new Error("You are calling submit during the server render. " + "Try calling submit within a `useEffect` or callback instead."); | ||
} | ||
let { | ||
@@ -872,2 +917,4 @@ protocol, | ||
* `React.useCallback()`. | ||
* | ||
* @see https://remix.run/api/remix#usebeforeunload | ||
*/ | ||
@@ -884,2 +931,9 @@ | ||
} | ||
/** | ||
* Returns the current route matches on the page. This is useful for creating | ||
* layout abstractions with your current routes. | ||
* | ||
* @see https://remix.run/api/remix#usematches | ||
*/ | ||
function useMatches() { | ||
@@ -891,3 +945,3 @@ let { | ||
} = useRemixEntryContext(); | ||
return matches.map(match => { | ||
return React__namespace.useMemo(() => matches.map(match => { | ||
var _routeModules$match$r; | ||
@@ -908,6 +962,8 @@ | ||
}; | ||
}); | ||
}), [matches, routeData, routeModules]); | ||
} | ||
/** | ||
* Returns the data from the current route's `loader`. | ||
* Returns the JSON parsed data from the current route's `loader`. | ||
* | ||
* @see https://remix.run/api/remix#useloaderdata | ||
*/ | ||
@@ -918,2 +974,8 @@ | ||
} | ||
/** | ||
* Returns the JSON parsed data from the current route's `action`. | ||
* | ||
* @see https://remix.run/api/remix#useactiondata | ||
*/ | ||
function useActionData() { | ||
@@ -931,2 +993,9 @@ let { | ||
} | ||
/** | ||
* Returns everything you need to know about a page transition to build pending | ||
* navigation indicators and optimistic UI on data mutations. | ||
* | ||
* @see https://remix.run/api/remix#usetransition | ||
*/ | ||
function useTransition() { | ||
@@ -940,3 +1009,3 @@ let { | ||
function createFetcherForm(fetchKey) { | ||
return /*#__PURE__*/React__namespace.forwardRef((props, ref) => { | ||
let FetcherForm = /*#__PURE__*/React__namespace.forwardRef((props, ref) => { | ||
// TODO: make ANOTHER form w/o a fetchKey prop | ||
@@ -948,2 +1017,4 @@ return /*#__PURE__*/React__namespace.createElement(FormImpl, _rollupPluginBabelHelpers["extends"]({}, props, { | ||
}); | ||
FetcherForm.displayName = "fetcher.Form"; | ||
return FetcherForm; | ||
} | ||
@@ -956,2 +1027,4 @@ | ||
* for any interaction that stays on the same page. | ||
* | ||
* @see https://remix.run/api/remix#usefetcher | ||
*/ | ||
@@ -990,2 +1063,4 @@ function useFetcher() { | ||
* routes that need to provide pending/optimistic UI regarding the fetch. | ||
* | ||
* @see https://remix.run/api/remix#usefetchers | ||
*/ | ||
@@ -1007,21 +1082,31 @@ | ||
}) { | ||
let setupLiveReload = (port => { | ||
let protocol = location.protocol === "https:" ? "wss:" : "ws:"; | ||
let host = location.hostname; | ||
let socketPath = `${protocol}//${host}:${port}/socket`; | ||
let ws = new WebSocket(socketPath); | ||
ws.onmessage = message => { | ||
let event = JSON.parse(message.data); | ||
if (event.type === "LOG") { | ||
console.log(event.message); | ||
} | ||
if (event.type === "RELOAD") { | ||
console.log("💿 Reloading window ..."); | ||
window.location.reload(); | ||
} | ||
}; | ||
ws.onerror = error => { | ||
console.log("Remix dev asset server web socket error:"); | ||
console.error(error); | ||
}; | ||
}).toString(); | ||
return /*#__PURE__*/React__namespace.createElement("script", { | ||
suppressHydrationWarning: true, | ||
dangerouslySetInnerHTML: { | ||
__html: ` | ||
let ws = new WebSocket("ws://localhost:${port}/socket"); | ||
ws.onmessage = message => { | ||
let event = JSON.parse(message.data); | ||
if (event.type === "LOG") { | ||
console.log(event.message); | ||
} | ||
if (event.type === "RELOAD") { | ||
console.log("💿 Reloading window ..."); | ||
window.location.reload(); | ||
} | ||
}; | ||
ws.onerror = error => { | ||
console.log("Remix dev asset server web socket error:"); | ||
console.error(error); | ||
}; | ||
`.trim() | ||
__html: `(${setupLiveReload})(${JSON.stringify(port)})` | ||
} | ||
@@ -1057,2 +1142,3 @@ }); | ||
exports.RemixEntry = RemixEntry; | ||
exports.RemixEntryContext = RemixEntryContext; | ||
exports.RemixRoute = RemixRoute; | ||
@@ -1059,0 +1145,0 @@ exports.Scripts = Scripts; |
/** | ||
* @remix-run/react v0.0.0-experimental-7de3dd2b | ||
* @remix-run/react v0.0.0-experimental-80f6d2e1 | ||
* | ||
@@ -4,0 +4,0 @@ * Copyright (c) Remix Software Inc. |
@@ -31,2 +31,7 @@ import type { Location } from "history"; | ||
}): JSX.Element; | ||
/** | ||
* Returns the status code and thrown response data. | ||
* | ||
* @see https://remix.run/api/conventions#catchboundary | ||
*/ | ||
export declare function useCatch<Result extends ThrownResponse = ThrownResponse>(): Result; | ||
@@ -38,3 +43,3 @@ declare type RemixCatchBoundaryProps = React.PropsWithChildren<{ | ||
}>; | ||
export declare function RemixCatchBoundary({ catch: catchVal, component: Component, children }: RemixCatchBoundaryProps): JSX.Element; | ||
export declare function RemixCatchBoundary({ catch: catchVal, component: Component, children, }: RemixCatchBoundaryProps): JSX.Element; | ||
/** | ||
@@ -41,0 +46,0 @@ * When app's don't provide a root level CatchBoundary, we default to this. |
/** | ||
* @remix-run/react v0.0.0-experimental-7de3dd2b | ||
* @remix-run/react v0.0.0-experimental-80f6d2e1 | ||
* | ||
@@ -21,2 +21,3 @@ * Copyright (c) Remix Software Inc. | ||
// TODO: We eventually might not want to import anything directly from `history` | ||
class RemixErrorBoundary extends React__default["default"].Component { | ||
@@ -110,3 +111,3 @@ constructor(props) { | ||
console.log( | ||
"💿 Hey developer👋. You can provide a way better UX when your app throws errors than this. Check out https://remix.run/guides/errors for more information." | ||
"💿 Hey developer👋. You can provide a way better UX than this when your app throws errors. Check out https://remix.run/guides/errors for more information." | ||
); | ||
@@ -118,2 +119,8 @@ ` | ||
let RemixCatchContext = /*#__PURE__*/React__default["default"].createContext(undefined); | ||
/** | ||
* Returns the status code and thrown response data. | ||
* | ||
* @see https://remix.run/api/conventions#catchboundary | ||
*/ | ||
function useCatch() { | ||
@@ -157,3 +164,3 @@ return React.useContext(RemixCatchContext); | ||
console.log( | ||
"💿 Hey developer👋. You can provide a way better UX when your app throws 404s (and other responses) than this. Check out https://remix.run/guides/not-found for more information." | ||
"💿 Hey developer👋. You can provide a way better UX than this when your app throws 404s (and other responses). Check out https://remix.run/guides/not-found for more information." | ||
); | ||
@@ -160,0 +167,0 @@ ` |
/** | ||
* @remix-run/react v0.0.0-experimental-7de3dd2b | ||
* @remix-run/react v0.0.0-experimental-80f6d2e1 | ||
* | ||
@@ -4,0 +4,0 @@ * Copyright (c) Remix Software Inc. |
/** | ||
* @remix-run/react v0.0.0-experimental-7de3dd2b | ||
* @remix-run/react v0.0.0-experimental-80f6d2e1 | ||
* | ||
@@ -15,2 +15,4 @@ * Copyright (c) Remix Software Inc. | ||
// TODO: We eventually might not want to import anything directly from `history` | ||
/** | ||
@@ -17,0 +19,0 @@ * The entry point for a Remix app when it is rendered in the browser (in |
/** | ||
* @remix-run/react v0.0.0-experimental-7de3dd2b | ||
* @remix-run/react v0.0.0-experimental-80f6d2e1 | ||
* | ||
@@ -272,3 +272,3 @@ * Copyright (c) Remix Software Inc. | ||
* | ||
* - "intent": Default, fetched when the user focuses or hovers the link | ||
* - "intent": Fetched when the user focuses or hovers the link | ||
* - "render": Fetched when the link is rendered | ||
@@ -324,3 +324,9 @@ * - "none": Never fetched | ||
} | ||
/** | ||
* A special kind of `<Link>` that knows whether or not it is "active". | ||
* | ||
* @see https://remix.run/api/remix#navlink | ||
*/ | ||
let NavLink = /*#__PURE__*/React.forwardRef(({ | ||
@@ -336,6 +342,14 @@ to, | ||
to: to | ||
}, prefetchHandlers, props)), shouldPrefetch ? /*#__PURE__*/React.createElement(PrefetchPageLinks, { | ||
}, props, prefetchHandlers)), shouldPrefetch ? /*#__PURE__*/React.createElement(PrefetchPageLinks, { | ||
page: href | ||
}) : null); | ||
}); | ||
NavLink.displayName = "NavLink"; | ||
/** | ||
* This component renders an anchor tag and is the primary way the user will | ||
* navigate around your website. | ||
* | ||
* @see https://remix.run/api/remix#link | ||
*/ | ||
let Link = /*#__PURE__*/React.forwardRef(({ | ||
@@ -351,6 +365,7 @@ to, | ||
to: to | ||
}, prefetchHandlers, props)), shouldPrefetch ? /*#__PURE__*/React.createElement(PrefetchPageLinks, { | ||
}, props, prefetchHandlers)), shouldPrefetch ? /*#__PURE__*/React.createElement(PrefetchPageLinks, { | ||
page: href | ||
}) : null); | ||
}); | ||
Link.displayName = "Link"; | ||
function composeEventHandlers(theirHandler, ourHandler) { | ||
@@ -367,2 +382,4 @@ return event => { | ||
* Renders the `<link>` tags for the current routes. | ||
* | ||
* @see https://remix.run/api/remix#meta-links-scripts | ||
*/ | ||
@@ -383,2 +400,12 @@ | ||
} | ||
/** | ||
* This component renders all of the `<link rel="prefetch">` and | ||
* `<link rel="modulepreload"/>` tags for all the assets (data, modules, css) of | ||
* a given page. | ||
* | ||
* @param props | ||
* @param props.page | ||
* @see https://remix.run/api/remix#prefetchpagelinks- | ||
*/ | ||
function PrefetchPageLinks({ | ||
@@ -457,2 +484,4 @@ page, | ||
* Renders the `<title>` and `<meta>` tags for the current routes. | ||
* | ||
* @see https://remix.run/api/remix#meta-links-scripts | ||
*/ | ||
@@ -529,2 +558,4 @@ | ||
* property if provided. | ||
* | ||
* @see https://remix.run/api/remix#meta-links-scripts | ||
*/ | ||
@@ -595,2 +626,4 @@ function Scripts(props) { | ||
* submitted and returns with data. | ||
* | ||
* @see https://remix.run/api/remix#form | ||
*/ | ||
@@ -602,2 +635,3 @@ let Form = /*#__PURE__*/React.forwardRef((props, ref) => { | ||
}); | ||
Form.displayName = "Form"; | ||
let FormImpl = /*#__PURE__*/React.forwardRef(({ | ||
@@ -639,6 +673,6 @@ reloadDocument = false, | ||
function handleClick(event) { | ||
if (!(event.target instanceof HTMLElement)) return; | ||
if (!(event.target instanceof Element)) return; | ||
let submitButton = event.target.closest("button,input[type=submit]"); | ||
if (submitButton && submitButton.type === "submit") { | ||
if (submitButton && submitButton.form === form && submitButton.type === "submit") { | ||
clickedButtonRef.current = submitButton; | ||
@@ -648,5 +682,5 @@ } | ||
form.addEventListener("click", handleClick); | ||
window.addEventListener("click", handleClick); | ||
return () => { | ||
form && form.removeEventListener("click", handleClick); | ||
window.removeEventListener("click", handleClick); | ||
}; | ||
@@ -671,2 +705,3 @@ }, []); | ||
}); | ||
FormImpl.displayName = "FormImpl"; | ||
@@ -679,2 +714,4 @@ function isActionRequestMethod(method) { | ||
* Resolves a `<form action>` path relative to the current route. | ||
* | ||
* @see https://remix.run/api/remix#useformaction | ||
*/ | ||
@@ -701,2 +738,4 @@ | ||
* some arbitrary data) to the server. | ||
* | ||
* @see https://remix.run/api/remix#usesubmit | ||
*/ | ||
@@ -706,2 +745,4 @@ function useSubmit() { | ||
} | ||
let defaultMethod = "get"; | ||
let defaultEncType = "application/x-www-form-urlencoded"; | ||
function useSubmitImpl(key) { | ||
@@ -721,5 +762,5 @@ let navigate = useNavigate(); | ||
let submissionTrigger = options.submissionTrigger; | ||
method = options.method || target.method; | ||
action = options.action || target.action; | ||
encType = options.encType || target.enctype; | ||
method = options.method || target.getAttribute("method") || defaultMethod; | ||
action = options.action || target.getAttribute("action") || defaultAction; | ||
encType = options.encType || target.getAttribute("enctype") || defaultEncType; | ||
formData = new FormData(target); | ||
@@ -738,5 +779,5 @@ | ||
method = options.method || target.getAttribute("formmethod") || form.method; | ||
action = options.action || target.getAttribute("formaction") || form.action; | ||
encType = options.encType || target.getAttribute("formenctype") || form.enctype; | ||
method = options.method || target.getAttribute("formmethod") || form.getAttribute("method") || defaultMethod; | ||
action = options.action || target.getAttribute("formaction") || form.getAttribute("action") || defaultAction; | ||
encType = options.encType || target.getAttribute("formenctype") || form.getAttribute("enctype") || defaultEncType; | ||
formData = new FormData(form); // Include name + value from a <button> | ||
@@ -773,2 +814,6 @@ | ||
if (typeof document === "undefined") { | ||
throw new Error("You are calling submit during the server render. " + "Try calling submit within a `useEffect` or callback instead."); | ||
} | ||
let { | ||
@@ -848,2 +893,4 @@ protocol, | ||
* `React.useCallback()`. | ||
* | ||
* @see https://remix.run/api/remix#usebeforeunload | ||
*/ | ||
@@ -860,2 +907,9 @@ | ||
} | ||
/** | ||
* Returns the current route matches on the page. This is useful for creating | ||
* layout abstractions with your current routes. | ||
* | ||
* @see https://remix.run/api/remix#usematches | ||
*/ | ||
function useMatches() { | ||
@@ -867,3 +921,3 @@ let { | ||
} = useRemixEntryContext(); | ||
return matches.map(match => { | ||
return React.useMemo(() => matches.map(match => { | ||
var _routeModules$match$r; | ||
@@ -884,6 +938,8 @@ | ||
}; | ||
}); | ||
}), [matches, routeData, routeModules]); | ||
} | ||
/** | ||
* Returns the data from the current route's `loader`. | ||
* Returns the JSON parsed data from the current route's `loader`. | ||
* | ||
* @see https://remix.run/api/remix#useloaderdata | ||
*/ | ||
@@ -894,2 +950,8 @@ | ||
} | ||
/** | ||
* Returns the JSON parsed data from the current route's `action`. | ||
* | ||
* @see https://remix.run/api/remix#useactiondata | ||
*/ | ||
function useActionData() { | ||
@@ -907,2 +969,9 @@ let { | ||
} | ||
/** | ||
* Returns everything you need to know about a page transition to build pending | ||
* navigation indicators and optimistic UI on data mutations. | ||
* | ||
* @see https://remix.run/api/remix#usetransition | ||
*/ | ||
function useTransition() { | ||
@@ -916,3 +985,3 @@ let { | ||
function createFetcherForm(fetchKey) { | ||
return /*#__PURE__*/React.forwardRef((props, ref) => { | ||
let FetcherForm = /*#__PURE__*/React.forwardRef((props, ref) => { | ||
// TODO: make ANOTHER form w/o a fetchKey prop | ||
@@ -924,2 +993,4 @@ return /*#__PURE__*/React.createElement(FormImpl, _extends({}, props, { | ||
}); | ||
FetcherForm.displayName = "fetcher.Form"; | ||
return FetcherForm; | ||
} | ||
@@ -932,2 +1003,4 @@ | ||
* for any interaction that stays on the same page. | ||
* | ||
* @see https://remix.run/api/remix#usefetcher | ||
*/ | ||
@@ -966,2 +1039,4 @@ function useFetcher() { | ||
* routes that need to provide pending/optimistic UI regarding the fetch. | ||
* | ||
* @see https://remix.run/api/remix#usefetchers | ||
*/ | ||
@@ -983,21 +1058,31 @@ | ||
}) { | ||
let setupLiveReload = (port => { | ||
let protocol = location.protocol === "https:" ? "wss:" : "ws:"; | ||
let host = location.hostname; | ||
let socketPath = `${protocol}//${host}:${port}/socket`; | ||
let ws = new WebSocket(socketPath); | ||
ws.onmessage = message => { | ||
let event = JSON.parse(message.data); | ||
if (event.type === "LOG") { | ||
console.log(event.message); | ||
} | ||
if (event.type === "RELOAD") { | ||
console.log("💿 Reloading window ..."); | ||
window.location.reload(); | ||
} | ||
}; | ||
ws.onerror = error => { | ||
console.log("Remix dev asset server web socket error:"); | ||
console.error(error); | ||
}; | ||
}).toString(); | ||
return /*#__PURE__*/React.createElement("script", { | ||
suppressHydrationWarning: true, | ||
dangerouslySetInnerHTML: { | ||
__html: ` | ||
let ws = new WebSocket("ws://localhost:${port}/socket"); | ||
ws.onmessage = message => { | ||
let event = JSON.parse(message.data); | ||
if (event.type === "LOG") { | ||
console.log(event.message); | ||
} | ||
if (event.type === "RELOAD") { | ||
console.log("💿 Reloading window ..."); | ||
window.location.reload(); | ||
} | ||
}; | ||
ws.onerror = error => { | ||
console.log("Remix dev asset server web socket error:"); | ||
console.error(error); | ||
}; | ||
`.trim() | ||
__html: `(${setupLiveReload})(${JSON.stringify(port)})` | ||
} | ||
@@ -1024,2 +1109,2 @@ }); | ||
export { Form, FormImpl, Link, Links, LiveReload, Meta, NavLink, PrefetchPageLinks, RemixEntry, RemixRoute, Scripts, composeEventHandlers, useActionData, useBeforeUnload, useFetcher, useFetchers, useFormAction, useLoaderData, useMatches, useSubmit, useSubmitImpl, useTransition }; | ||
export { Form, FormImpl, Link, Links, LiveReload, Meta, NavLink, PrefetchPageLinks, RemixEntry, RemixEntryContext, RemixRoute, Scripts, composeEventHandlers, useActionData, useBeforeUnload, useFetcher, useFetchers, useFormAction, useLoaderData, useMatches, useSubmit, useSubmitImpl, useTransition }; |
/** | ||
* @remix-run/react v0.0.0-experimental-7de3dd2b | ||
* @remix-run/react v0.0.0-experimental-80f6d2e1 | ||
* | ||
@@ -4,0 +4,0 @@ * Copyright (c) Remix Software Inc. |
/** | ||
* @remix-run/react v0.0.0-experimental-7de3dd2b | ||
* @remix-run/react v0.0.0-experimental-80f6d2e1 | ||
* | ||
@@ -13,2 +13,3 @@ * Copyright (c) Remix Software Inc. | ||
// TODO: We eventually might not want to import anything directly from `history` | ||
class RemixErrorBoundary extends React__default.Component { | ||
@@ -102,3 +103,3 @@ constructor(props) { | ||
console.log( | ||
"💿 Hey developer👋. You can provide a way better UX when your app throws errors than this. Check out https://remix.run/guides/errors for more information." | ||
"💿 Hey developer👋. You can provide a way better UX than this when your app throws errors. Check out https://remix.run/guides/errors for more information." | ||
); | ||
@@ -110,2 +111,8 @@ ` | ||
let RemixCatchContext = /*#__PURE__*/React__default.createContext(undefined); | ||
/** | ||
* Returns the status code and thrown response data. | ||
* | ||
* @see https://remix.run/api/conventions#catchboundary | ||
*/ | ||
function useCatch() { | ||
@@ -149,3 +156,3 @@ return useContext(RemixCatchContext); | ||
console.log( | ||
"💿 Hey developer👋. You can provide a way better UX when your app throws 404s (and other responses) than this. Check out https://remix.run/guides/not-found for more information." | ||
"💿 Hey developer👋. You can provide a way better UX than this when your app throws 404s (and other responses). Check out https://remix.run/guides/not-found for more information." | ||
); | ||
@@ -152,0 +159,0 @@ ` |
/** | ||
* @remix-run/react v0.0.0-experimental-7de3dd2b | ||
* @remix-run/react v0.0.0-experimental-80f6d2e1 | ||
* | ||
@@ -4,0 +4,0 @@ * Copyright (c) Remix Software Inc. |
/** | ||
* @remix-run/react v0.0.0-experimental-7de3dd2b | ||
* @remix-run/react v0.0.0-experimental-80f6d2e1 | ||
* | ||
@@ -4,0 +4,0 @@ * Copyright (c) Remix Software Inc. |
/** | ||
* @remix-run/react v0.0.0-experimental-7de3dd2b | ||
* @remix-run/react v0.0.0-experimental-80f6d2e1 | ||
* | ||
@@ -14,9 +14,3 @@ * Copyright (c) Remix Software Inc. | ||
// import type { Location } from "history"; | ||
/** | ||
* Represents a `<link>` element. | ||
* | ||
* WHATWG Specification: https://html.spec.whatwg.org/multipage/semantics.html#the-link-element | ||
*/ | ||
// TODO: We eventually might not want to import anything directly from `history` | ||
//////////////////////////////////////////////////////////////////////////////// | ||
@@ -101,15 +95,9 @@ | ||
...attrs | ||
}) => { | ||
if (rel === "preload") { | ||
return { | ||
rel: "prefetch", | ||
...attrs | ||
}; | ||
} | ||
return { | ||
rel: "prefetch", | ||
as: "style", | ||
...attrs | ||
}; | ||
}) => rel === "preload" ? { | ||
rel: "prefetch", | ||
...attrs | ||
} : { | ||
rel: "prefetch", | ||
as: "style", | ||
...attrs | ||
}); | ||
@@ -130,3 +118,5 @@ } // This is ridiculously identical to transition.ts `filterMatchesToLoad` | ||
return (// param change, /users/123 -> /users/456 | ||
currentMatches[index].pathname !== match.pathname || ((_currentMatches$index = currentMatches[index].route.path) === null || _currentMatches$index === void 0 ? void 0 : _currentMatches$index.endsWith("*")) && currentMatches[index].params["*"] !== match.params["*"] | ||
currentMatches[index].pathname !== match.pathname || // splat param changed, which is not present in match.path | ||
// e.g. /files/images/avatar.jpg -> files/finances.xls | ||
((_currentMatches$index = currentMatches[index].route.path) === null || _currentMatches$index === void 0 ? void 0 : _currentMatches$index.endsWith("*")) && currentMatches[index].params["*"] !== match.params["*"] | ||
); | ||
@@ -133,0 +123,0 @@ }; // NOTE: keep this mostly up-to-date w/ the transition data diff, but this |
/** | ||
* @remix-run/react v0.0.0-experimental-7de3dd2b | ||
* @remix-run/react v0.0.0-experimental-80f6d2e1 | ||
* | ||
@@ -4,0 +4,0 @@ * Copyright (c) Remix Software Inc. |
/** | ||
* @remix-run/react v0.0.0-experimental-7de3dd2b | ||
* @remix-run/react v0.0.0-experimental-80f6d2e1 | ||
* | ||
@@ -13,3 +13,3 @@ * Copyright (c) Remix Software Inc. | ||
// TODO: export/import from react-router-dom | ||
// TODO: We eventually might not want to import anything directly from `history` | ||
function matchClientRoutes(routes, location) { | ||
@@ -16,0 +16,0 @@ let matches = matchRoutes(routes, location); |
/** | ||
* @remix-run/react v0.0.0-experimental-7de3dd2b | ||
* @remix-run/react v0.0.0-experimental-80f6d2e1 | ||
* | ||
@@ -11,2 +11,4 @@ * Copyright (c) Remix Software Inc. | ||
*/ | ||
// TODO: We eventually might not want to import anything directly from `history` | ||
// and leverage `react-router` here instead | ||
// TODO: import/export from react-router-dom | ||
@@ -16,2 +18,4 @@ | ||
* A React component that is rendered when the server throws a Response. | ||
* | ||
* @see https://remix.run/api/conventions#catchboundary | ||
*/ | ||
@@ -21,2 +25,4 @@ | ||
* A React component that is rendered when there is an error on a route. | ||
* | ||
* @see https://remix.run/api/conventions#errorboundary | ||
*/ | ||
@@ -27,2 +33,4 @@ | ||
* the document on route transitions. | ||
* | ||
* @see https://remix.run/api/remix#meta-links-scripts | ||
*/ | ||
@@ -34,2 +42,4 @@ | ||
* precedence over) tags from parent routes. | ||
* | ||
* @see https://remix.run/api/remix#meta-links-scripts | ||
*/ | ||
@@ -54,2 +64,4 @@ | ||
* to be reloaded. | ||
* | ||
* @see https://remix.run/api/conventions#unstable_shouldreload | ||
*/ | ||
@@ -63,2 +75,4 @@ | ||
* An arbitrary object that is associated with a route. | ||
* | ||
* @see https://remix.run/api/conventions#handle | ||
*/ | ||
@@ -65,0 +79,0 @@ async function loadRouteModule(route, routeModulesCache) { |
/** | ||
* @remix-run/react v0.0.0-experimental-7de3dd2b | ||
* @remix-run/react v0.0.0-experimental-80f6d2e1 | ||
* | ||
@@ -4,0 +4,0 @@ * Copyright (c) Remix Software Inc. |
/** | ||
* @remix-run/react v0.0.0-experimental-7de3dd2b | ||
* @remix-run/react v0.0.0-experimental-80f6d2e1 | ||
* | ||
@@ -25,3 +25,10 @@ * Copyright (c) Remix Software Inc. | ||
} | ||
/** | ||
* This component will emulate the browser's scroll restoration on location | ||
* changes. | ||
* | ||
* @see https://remix.run/api/remix#scrollrestoration | ||
*/ | ||
function ScrollRestoration() { | ||
@@ -37,20 +44,28 @@ useScrollRestoration(); // wait for the browser to restore it on its own | ||
}, [])); | ||
let restoreScroll = (STORAGE_KEY => { | ||
if (!window.history.state || !window.history.state.key) { | ||
let key = Math.random().toString(32).slice(2); | ||
window.history.replaceState({ | ||
key | ||
}, ""); | ||
} | ||
try { | ||
let positions = JSON.parse(sessionStorage.getItem(STORAGE_KEY) || "{}"); | ||
let storedY = positions[window.history.state.key]; | ||
if (typeof storedY === "number") { | ||
window.scrollTo(0, storedY); | ||
} | ||
} catch (error) { | ||
console.error(error); | ||
sessionStorage.removeItem(STORAGE_KEY); | ||
} | ||
}).toString(); | ||
return /*#__PURE__*/React.createElement("script", { | ||
suppressHydrationWarning: true, | ||
dangerouslySetInnerHTML: { | ||
__html: ` | ||
let STORAGE_KEY = ${JSON.stringify(STORAGE_KEY)}; | ||
if (!window.history.state || !window.history.state.key) { | ||
window.history.replaceState({ key: Math.random().toString(32).slice(2) }, null); | ||
} | ||
try { | ||
let positions = JSON.parse(sessionStorage.getItem(STORAGE_KEY) ?? '{}') | ||
let storedY = positions[window.history.state.key]; | ||
if (typeof storedY === 'number') { | ||
window.scrollTo(0, storedY) | ||
} | ||
} catch(error) { | ||
console.error(error) | ||
sessionStorage.removeItem(STORAGE_KEY) | ||
} | ||
` | ||
__html: `(${restoreScroll})(${JSON.stringify(STORAGE_KEY)})` | ||
} | ||
@@ -91,3 +106,3 @@ }); | ||
if (y) { | ||
if (y != undefined) { | ||
window.scrollTo(0, y); | ||
@@ -99,3 +114,3 @@ return; | ||
if (location.hash) { | ||
let el = document.querySelector(location.hash); | ||
let el = document.getElementById(location.hash.slice(1)); | ||
@@ -102,0 +117,0 @@ if (el) { |
/** | ||
* @remix-run/react v0.0.0-experimental-7de3dd2b | ||
* @remix-run/react v0.0.0-experimental-80f6d2e1 | ||
* | ||
@@ -15,2 +15,4 @@ * Copyright (c) Remix Software Inc. | ||
// TODO: We eventually might not want to import anything directly from `history` | ||
/** | ||
@@ -17,0 +19,0 @@ * The entry point for a Remix app when it is rendered on the server (in |
/** | ||
* @remix-run/react v0.0.0-experimental-7de3dd2b | ||
* @remix-run/react v0.0.0-experimental-80f6d2e1 | ||
* | ||
@@ -15,2 +15,3 @@ * Copyright (c) Remix Software Inc. | ||
// TODO: We eventually might not want to import anything directly from `history` | ||
class CatchValue { | ||
@@ -241,2 +242,12 @@ constructor(status, statusText, data) { | ||
init.onRedirect(result.value.location, locationState); | ||
let doneFetcher = { | ||
state: "idle", | ||
type: "done", | ||
data: result.value, | ||
submission: undefined | ||
}; | ||
state.fetchers.set(key, doneFetcher); | ||
update({ | ||
fetchers: new Map(state.fetchers) | ||
}); | ||
return; | ||
@@ -427,2 +438,6 @@ } | ||
async function handleLoaderFetch(href, key, match) { | ||
if (typeof AbortController === "undefined") { | ||
throw new Error("handleLoaderFetch was called during the server render, but it shouldn't be. " + "You are likely calling useFetcher.load() in the body of your component. " + "Try moving it to a useEffect or a callback."); | ||
} | ||
let currentFetcher = state.fetchers.get(key); | ||
@@ -913,3 +928,5 @@ let fetcher = { | ||
return (// param change, /users/123 -> /users/456 | ||
state.matches[index].pathname !== match.pathname || ((_state$matches$index$ = state.matches[index].route.path) === null || _state$matches$index$ === void 0 ? void 0 : _state$matches$index$.endsWith("*")) && state.matches[index].params["*"] !== match.params["*"] | ||
state.matches[index].pathname !== match.pathname || // splat param changed, which is not present in match.path | ||
// e.g. /files/images/avatar.jpg -> files/finances.xls | ||
((_state$matches$index$ = state.matches[index].route.path) === null || _state$matches$index$ === void 0 ? void 0 : _state$matches$index$.endsWith("*")) && state.matches[index].params["*"] !== match.params["*"] | ||
); | ||
@@ -951,3 +968,3 @@ }; | ||
createHref(url) === createHref(state.location) || // search affects all loaders | ||
url.searchParams.toString() !== state.location.search) { | ||
url.searchParams.toString() !== state.location.search.substring(1)) { | ||
return matches.filter(filterByRouteProps); | ||
@@ -954,0 +971,0 @@ } |
export type { RemixBrowserProps } from "./browser"; | ||
export { RemixBrowser } from "./browser"; | ||
export { useHref, useLocation, useNavigate, useNavigationType, useOutlet, useParams, useResolvedPath, useSearchParams, Outlet, useOutletContext } from "react-router-dom"; | ||
export type { FormProps, SubmitOptions, SubmitFunction, RemixNavLinkProps as NavLinkProps, RemixLinkProps as LinkProps } from "./components"; | ||
export { Meta, Links, Scripts, Link, NavLink, Form, PrefetchPageLinks, LiveReload, useFormAction, useSubmit, useTransition, useFetcher, useFetchers, useLoaderData, useActionData, useBeforeUnload, useMatches } from "./components"; | ||
export { useHref, useLocation, useNavigate, useNavigationType, useOutlet, useParams, useResolvedPath, useSearchParams, Outlet, useOutletContext, } from "react-router-dom"; | ||
export type { FormProps, SubmitOptions, SubmitFunction, RemixNavLinkProps as NavLinkProps, RemixLinkProps as LinkProps, } from "./components"; | ||
export { Meta, Links, Scripts, Link, NavLink, Form, PrefetchPageLinks, LiveReload, useFormAction, useSubmit, useTransition, useFetcher, useFetchers, useLoaderData, useActionData, useBeforeUnload, useMatches, } from "./components"; | ||
export type { FormMethod, FormEncType } from "./data"; | ||
@@ -7,0 +7,0 @@ export type { ThrownResponse } from "./errors"; |
/** | ||
* @remix-run/react v0.0.0-experimental-7de3dd2b | ||
* @remix-run/react v0.0.0-experimental-80f6d2e1 | ||
* | ||
@@ -4,0 +4,0 @@ * Copyright (c) Remix Software Inc. |
/** | ||
* @remix-run/react v0.0.0-experimental-7de3dd2b | ||
* @remix-run/react v0.0.0-experimental-80f6d2e1 | ||
* | ||
@@ -4,0 +4,0 @@ * Copyright (c) Remix Software Inc. |
@@ -6,2 +6,4 @@ import type { Location } from "history"; | ||
import type { RouteModules, RouteModule } from "./routeModules"; | ||
declare type Primitive = null | undefined | string | number | boolean | symbol | bigint; | ||
declare type LiteralUnion<LiteralType, BaseType extends Primitive> = LiteralType | (BaseType & Record<never, never>); | ||
/** | ||
@@ -24,3 +26,3 @@ * Represents a `<link>` element. | ||
*/ | ||
rel: "alternate" | "dns-prefetch" | "icon" | "manifest" | "modulepreload" | "next" | "pingback" | "preconnect" | "prefetch" | "preload" | "prerender" | "search" | "stylesheet" | string; | ||
rel: LiteralUnion<"alternate" | "dns-prefetch" | "icon" | "manifest" | "modulepreload" | "next" | "pingback" | "preconnect" | "prefetch" | "preload" | "prerender" | "search" | "stylesheet", string>; | ||
/** | ||
@@ -61,3 +63,3 @@ * Applicable media: "screen", "print", "(max-width: 764px)" | ||
*/ | ||
as?: "audio" | "audioworklet" | "document" | "embed" | "fetch" | "font" | "frame" | "iframe" | "image" | "manifest" | "object" | "paintworklet" | "report" | "script" | "serviceworker" | "sharedworker" | "style" | "track" | "video" | "worker" | "xslt" | string; | ||
as?: LiteralUnion<"audio" | "audioworklet" | "document" | "embed" | "fetch" | "font" | "frame" | "iframe" | "image" | "manifest" | "object" | "paintworklet" | "report" | "script" | "serviceworker" | "sharedworker" | "style" | "track" | "video" | "worker" | "xslt", string>; | ||
/** | ||
@@ -135,3 +137,3 @@ * Color to use when customizing a site's icon (for rel="mask-icon") | ||
*/ | ||
as?: string | undefined; | ||
as?: LiteralUnion<"object" | "style" | "embed" | "font" | "audio" | "iframe" | "script" | "track" | "video" | "image" | "manifest" | "document" | "audioworklet" | "fetch" | "frame" | "paintworklet" | "report" | "serviceworker" | "sharedworker" | "worker" | "xslt", string> | undefined; | ||
/** | ||
@@ -155,1 +157,2 @@ * Color to use when customizing a site's icon (for rel="mask-icon") | ||
export declare function dedupe(descriptors: LinkDescriptor[], preloads: string[]): LinkDescriptor[]; | ||
export {}; |
34
links.js
/** | ||
* @remix-run/react v0.0.0-experimental-7de3dd2b | ||
* @remix-run/react v0.0.0-experimental-80f6d2e1 | ||
* | ||
@@ -18,9 +18,3 @@ * Copyright (c) Remix Software Inc. | ||
// import type { Location } from "history"; | ||
/** | ||
* Represents a `<link>` element. | ||
* | ||
* WHATWG Specification: https://html.spec.whatwg.org/multipage/semantics.html#the-link-element | ||
*/ | ||
// TODO: We eventually might not want to import anything directly from `history` | ||
//////////////////////////////////////////////////////////////////////////////// | ||
@@ -105,15 +99,9 @@ | ||
...attrs | ||
}) => { | ||
if (rel === "preload") { | ||
return { | ||
rel: "prefetch", | ||
...attrs | ||
}; | ||
} | ||
return { | ||
rel: "prefetch", | ||
as: "style", | ||
...attrs | ||
}; | ||
}) => rel === "preload" ? { | ||
rel: "prefetch", | ||
...attrs | ||
} : { | ||
rel: "prefetch", | ||
as: "style", | ||
...attrs | ||
}); | ||
@@ -134,3 +122,5 @@ } // This is ridiculously identical to transition.ts `filterMatchesToLoad` | ||
return (// param change, /users/123 -> /users/456 | ||
currentMatches[index].pathname !== match.pathname || ((_currentMatches$index = currentMatches[index].route.path) === null || _currentMatches$index === void 0 ? void 0 : _currentMatches$index.endsWith("*")) && currentMatches[index].params["*"] !== match.params["*"] | ||
currentMatches[index].pathname !== match.pathname || // splat param changed, which is not present in match.path | ||
// e.g. /files/images/avatar.jpg -> files/finances.xls | ||
((_currentMatches$index = currentMatches[index].route.path) === null || _currentMatches$index === void 0 ? void 0 : _currentMatches$index.endsWith("*")) && currentMatches[index].params["*"] !== match.params["*"] | ||
); | ||
@@ -137,0 +127,0 @@ }; // NOTE: keep this mostly up-to-date w/ the transition data diff, but this |
@@ -1,3 +0,3 @@ | ||
export type { RemixBrowserProps, FormProps, SubmitOptions, SubmitFunction, FormMethod, FormEncType, RemixServerProps, ShouldReloadFunction, ThrownResponse, LinkProps, NavLinkProps } from "@remix-run/react"; | ||
export { RemixBrowser, Meta, Links, Scripts, Link, NavLink, Form, PrefetchPageLinks, ScrollRestoration, LiveReload, useFormAction, useSubmit, useTransition, useFetcher, useFetchers, useCatch, useLoaderData, useActionData, useBeforeUnload, useMatches, RemixServer } from "@remix-run/react"; | ||
export { Outlet, useHref, useLocation, useNavigate, useNavigationType, useOutlet, useParams, useResolvedPath, useSearchParams, useOutletContext } from "@remix-run/react"; | ||
export type { RemixBrowserProps, FormProps, SubmitOptions, SubmitFunction, FormMethod, FormEncType, RemixServerProps, ShouldReloadFunction, ThrownResponse, LinkProps, NavLinkProps, } from "@remix-run/react"; | ||
export { RemixBrowser, Meta, Links, Scripts, Link, NavLink, Form, PrefetchPageLinks, ScrollRestoration, LiveReload, useFormAction, useSubmit, useTransition, useFetcher, useFetchers, useCatch, useLoaderData, useActionData, useBeforeUnload, useMatches, RemixServer, } from "@remix-run/react"; | ||
export { Outlet, useHref, useLocation, useNavigate, useNavigationType, useOutlet, useParams, useResolvedPath, useSearchParams, useOutletContext, } from "@remix-run/react"; |
/** | ||
* @remix-run/react v0.0.0-experimental-7de3dd2b | ||
* @remix-run/react v0.0.0-experimental-80f6d2e1 | ||
* | ||
@@ -4,0 +4,0 @@ * Copyright (c) Remix Software Inc. |
/** | ||
* @remix-run/react v0.0.0-experimental-7de3dd2b | ||
* @remix-run/react v0.0.0-experimental-80f6d2e1 | ||
* | ||
@@ -4,0 +4,0 @@ * Copyright (c) Remix Software Inc. |
/** | ||
* @remix-run/react v0.0.0-experimental-7de3dd2b | ||
* @remix-run/react v0.0.0-experimental-80f6d2e1 | ||
* | ||
@@ -4,0 +4,0 @@ * Copyright (c) Remix Software Inc. |
{ | ||
"name": "@remix-run/react", | ||
"description": "React DOM bindings for Remix", | ||
"version": "0.0.0-experimental-7de3dd2b", | ||
"version": "0.0.0-experimental-80f6d2e1", | ||
"license": "MIT", | ||
@@ -25,4 +25,4 @@ "repository": { | ||
"devDependencies": { | ||
"@testing-library/jest-dom": "^5.16.1", | ||
"@testing-library/react": "^12.1.2", | ||
"@testing-library/jest-dom": "^5.16.2", | ||
"@testing-library/react": "^12.1.3", | ||
"abort-controller": "^3.0.0" | ||
@@ -29,0 +29,0 @@ }, |
/** | ||
* @remix-run/react v0.0.0-experimental-7de3dd2b | ||
* @remix-run/react v0.0.0-experimental-80f6d2e1 | ||
* | ||
@@ -17,3 +17,3 @@ * Copyright (c) Remix Software Inc. | ||
// TODO: export/import from react-router-dom | ||
// TODO: We eventually might not want to import anything directly from `history` | ||
function matchClientRoutes(routes, location) { | ||
@@ -20,0 +20,0 @@ let matches = reactRouterDom.matchRoutes(routes, location); |
@@ -23,2 +23,4 @@ import type { Location } from "history"; | ||
* A React component that is rendered when the server throws a Response. | ||
* | ||
* @see https://remix.run/api/conventions#catchboundary | ||
*/ | ||
@@ -28,2 +30,4 @@ export declare type CatchBoundaryComponent = ComponentType<{}>; | ||
* A React component that is rendered when there is an error on a route. | ||
* | ||
* @see https://remix.run/api/conventions#errorboundary | ||
*/ | ||
@@ -36,2 +40,4 @@ export declare type ErrorBoundaryComponent = ComponentType<{ | ||
* the document on route transitions. | ||
* | ||
* @see https://remix.run/api/remix#meta-links-scripts | ||
*/ | ||
@@ -45,2 +51,4 @@ export interface LinksFunction { | ||
* precedence over) tags from parent routes. | ||
* | ||
* @see https://remix.run/api/remix#meta-links-scripts | ||
*/ | ||
@@ -74,2 +82,4 @@ export interface MetaFunction { | ||
* to be reloaded. | ||
* | ||
* @see https://remix.run/api/conventions#unstable_shouldreload | ||
*/ | ||
@@ -90,4 +100,6 @@ export interface ShouldReloadFunction { | ||
* An arbitrary object that is associated with a route. | ||
* | ||
* @see https://remix.run/api/conventions#handle | ||
*/ | ||
export declare type RouteHandle = any; | ||
export declare function loadRouteModule(route: EntryRoute | ClientRoute, routeModulesCache: RouteModules): Promise<RouteModule>; |
/** | ||
* @remix-run/react v0.0.0-experimental-7de3dd2b | ||
* @remix-run/react v0.0.0-experimental-80f6d2e1 | ||
* | ||
@@ -33,2 +33,4 @@ * Copyright (c) Remix Software Inc. | ||
// TODO: We eventually might not want to import anything directly from `history` | ||
// and leverage `react-router` here instead | ||
// TODO: import/export from react-router-dom | ||
@@ -38,2 +40,4 @@ | ||
* A React component that is rendered when the server throws a Response. | ||
* | ||
* @see https://remix.run/api/conventions#catchboundary | ||
*/ | ||
@@ -43,2 +47,4 @@ | ||
* A React component that is rendered when there is an error on a route. | ||
* | ||
* @see https://remix.run/api/conventions#errorboundary | ||
*/ | ||
@@ -49,2 +55,4 @@ | ||
* the document on route transitions. | ||
* | ||
* @see https://remix.run/api/remix#meta-links-scripts | ||
*/ | ||
@@ -56,2 +64,4 @@ | ||
* precedence over) tags from parent routes. | ||
* | ||
* @see https://remix.run/api/remix#meta-links-scripts | ||
*/ | ||
@@ -76,2 +86,4 @@ | ||
* to be reloaded. | ||
* | ||
* @see https://remix.run/api/conventions#unstable_shouldreload | ||
*/ | ||
@@ -85,2 +97,4 @@ | ||
* An arbitrary object that is associated with a route. | ||
* | ||
* @see https://remix.run/api/conventions#handle | ||
*/ | ||
@@ -87,0 +101,0 @@ async function loadRouteModule(route, routeModulesCache) { |
/** | ||
* @remix-run/react v0.0.0-experimental-7de3dd2b | ||
* @remix-run/react v0.0.0-experimental-80f6d2e1 | ||
* | ||
@@ -4,0 +4,0 @@ * Copyright (c) Remix Software Inc. |
/// <reference types="react" /> | ||
/** | ||
* This component will emulate the browser's scroll restoration on location | ||
* changes. | ||
* | ||
* @see https://remix.run/api/remix#scrollrestoration | ||
*/ | ||
export declare function ScrollRestoration(): JSX.Element; |
/** | ||
* @remix-run/react v0.0.0-experimental-7de3dd2b | ||
* @remix-run/react v0.0.0-experimental-80f6d2e1 | ||
* | ||
@@ -49,3 +49,10 @@ * Copyright (c) Remix Software Inc. | ||
} | ||
/** | ||
* This component will emulate the browser's scroll restoration on location | ||
* changes. | ||
* | ||
* @see https://remix.run/api/remix#scrollrestoration | ||
*/ | ||
function ScrollRestoration() { | ||
@@ -61,20 +68,28 @@ useScrollRestoration(); // wait for the browser to restore it on its own | ||
}, [])); | ||
let restoreScroll = (STORAGE_KEY => { | ||
if (!window.history.state || !window.history.state.key) { | ||
let key = Math.random().toString(32).slice(2); | ||
window.history.replaceState({ | ||
key | ||
}, ""); | ||
} | ||
try { | ||
let positions = JSON.parse(sessionStorage.getItem(STORAGE_KEY) || "{}"); | ||
let storedY = positions[window.history.state.key]; | ||
if (typeof storedY === "number") { | ||
window.scrollTo(0, storedY); | ||
} | ||
} catch (error) { | ||
console.error(error); | ||
sessionStorage.removeItem(STORAGE_KEY); | ||
} | ||
}).toString(); | ||
return /*#__PURE__*/React__namespace.createElement("script", { | ||
suppressHydrationWarning: true, | ||
dangerouslySetInnerHTML: { | ||
__html: ` | ||
let STORAGE_KEY = ${JSON.stringify(STORAGE_KEY)}; | ||
if (!window.history.state || !window.history.state.key) { | ||
window.history.replaceState({ key: Math.random().toString(32).slice(2) }, null); | ||
} | ||
try { | ||
let positions = JSON.parse(sessionStorage.getItem(STORAGE_KEY) ?? '{}') | ||
let storedY = positions[window.history.state.key]; | ||
if (typeof storedY === 'number') { | ||
window.scrollTo(0, storedY) | ||
} | ||
} catch(error) { | ||
console.error(error) | ||
sessionStorage.removeItem(STORAGE_KEY) | ||
} | ||
` | ||
__html: `(${restoreScroll})(${JSON.stringify(STORAGE_KEY)})` | ||
} | ||
@@ -115,3 +130,3 @@ }); | ||
if (y) { | ||
if (y != undefined) { | ||
window.scrollTo(0, y); | ||
@@ -123,3 +138,3 @@ return; | ||
if (location.hash) { | ||
let el = document.querySelector(location.hash); | ||
let el = document.getElementById(location.hash.slice(1)); | ||
@@ -126,0 +141,0 @@ if (el) { |
/** | ||
* @remix-run/react v0.0.0-experimental-7de3dd2b | ||
* @remix-run/react v0.0.0-experimental-80f6d2e1 | ||
* | ||
@@ -39,2 +39,4 @@ * Copyright (c) Remix Software Inc. | ||
// TODO: We eventually might not want to import anything directly from `history` | ||
/** | ||
@@ -41,0 +43,0 @@ * The entry point for a Remix app when it is rendered on the server (in |
/** | ||
* @remix-run/react v0.0.0-experimental-7de3dd2b | ||
* @remix-run/react v0.0.0-experimental-80f6d2e1 | ||
* | ||
@@ -19,2 +19,3 @@ * Copyright (c) Remix Software Inc. | ||
// TODO: We eventually might not want to import anything directly from `history` | ||
class CatchValue { | ||
@@ -245,2 +246,12 @@ constructor(status, statusText, data) { | ||
init.onRedirect(result.value.location, locationState); | ||
let doneFetcher = { | ||
state: "idle", | ||
type: "done", | ||
data: result.value, | ||
submission: undefined | ||
}; | ||
state.fetchers.set(key, doneFetcher); | ||
update({ | ||
fetchers: new Map(state.fetchers) | ||
}); | ||
return; | ||
@@ -431,2 +442,6 @@ } | ||
async function handleLoaderFetch(href, key, match) { | ||
if (typeof AbortController === "undefined") { | ||
throw new Error("handleLoaderFetch was called during the server render, but it shouldn't be. " + "You are likely calling useFetcher.load() in the body of your component. " + "Try moving it to a useEffect or a callback."); | ||
} | ||
let currentFetcher = state.fetchers.get(key); | ||
@@ -917,3 +932,5 @@ let fetcher = { | ||
return (// param change, /users/123 -> /users/456 | ||
state.matches[index].pathname !== match.pathname || ((_state$matches$index$ = state.matches[index].route.path) === null || _state$matches$index$ === void 0 ? void 0 : _state$matches$index$.endsWith("*")) && state.matches[index].params["*"] !== match.params["*"] | ||
state.matches[index].pathname !== match.pathname || // splat param changed, which is not present in match.path | ||
// e.g. /files/images/avatar.jpg -> files/finances.xls | ||
((_state$matches$index$ = state.matches[index].route.path) === null || _state$matches$index$ === void 0 ? void 0 : _state$matches$index$.endsWith("*")) && state.matches[index].params["*"] !== match.params["*"] | ||
); | ||
@@ -955,3 +972,3 @@ }; | ||
createHref(url) === createHref(state.location) || // search affects all loaders | ||
url.searchParams.toString() !== state.location.search) { | ||
url.searchParams.toString() !== state.location.search.substring(1)) { | ||
return matches.filter(filterByRouteProps); | ||
@@ -958,0 +975,0 @@ } |
250732
7128