inital commit

This commit is contained in:
2026-01-01 15:25:19 +05:30
commit f0ae49465a
36361 changed files with 4894111 additions and 0 deletions

View File

@@ -0,0 +1,59 @@
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
import { PureComponent } from 'react';
import { RuntimeErrorHandler } from '../../errors/runtime-error-handler';
import { ErrorBoundary, GlobalError as DefaultGlobalError } from '../../error-boundary';
function ErroredHtml(param) {
let { globalError: [GlobalError, globalErrorStyles], error } = param;
if (!error) {
return /*#__PURE__*/ _jsxs("html", {
children: [
/*#__PURE__*/ _jsx("head", {}),
/*#__PURE__*/ _jsx("body", {})
]
});
}
return /*#__PURE__*/ _jsxs(ErrorBoundary, {
errorComponent: DefaultGlobalError,
children: [
globalErrorStyles,
/*#__PURE__*/ _jsx(GlobalError, {
error: error
})
]
});
}
export class AppDevOverlayErrorBoundary extends PureComponent {
static getDerivedStateFromError(error) {
if (!error.stack) {
return {
isReactError: false,
reactError: null
};
}
RuntimeErrorHandler.hadRuntimeError = true;
return {
isReactError: true,
reactError: error
};
}
componentDidCatch() {
this.props.onError(this.state.isReactError);
}
render() {
const { children, globalError } = this.props;
const { isReactError, reactError } = this.state;
const fallback = /*#__PURE__*/ _jsx(ErroredHtml, {
globalError: globalError,
error: reactError
});
return isReactError ? fallback : children;
}
constructor(...args){
super(...args), this.state = {
isReactError: false,
reactError: null
};
}
}
//# sourceMappingURL=app-dev-overlay-error-boundary.js.map

View File

@@ -0,0 +1 @@
{"version":3,"sources":["../../../../../src/client/components/react-dev-overlay/app/app-dev-overlay-error-boundary.tsx"],"sourcesContent":["import { PureComponent } from 'react'\nimport { RuntimeErrorHandler } from '../../errors/runtime-error-handler'\nimport {\n ErrorBoundary,\n type GlobalErrorComponent,\n GlobalError as DefaultGlobalError,\n} from '../../error-boundary'\n\ntype AppDevOverlayErrorBoundaryProps = {\n children: React.ReactNode\n globalError: [GlobalErrorComponent, React.ReactNode]\n onError: (value: boolean) => void\n}\n\ntype AppDevOverlayErrorBoundaryState = {\n isReactError: boolean\n reactError: unknown\n}\n\nfunction ErroredHtml({\n globalError: [GlobalError, globalErrorStyles],\n error,\n}: {\n globalError: [GlobalErrorComponent, React.ReactNode]\n error: unknown\n}) {\n if (!error) {\n return (\n <html>\n <head />\n <body />\n </html>\n )\n }\n return (\n <ErrorBoundary errorComponent={DefaultGlobalError}>\n {globalErrorStyles}\n <GlobalError error={error} />\n </ErrorBoundary>\n )\n}\n\nexport class AppDevOverlayErrorBoundary extends PureComponent<\n AppDevOverlayErrorBoundaryProps,\n AppDevOverlayErrorBoundaryState\n> {\n state = { isReactError: false, reactError: null }\n\n static getDerivedStateFromError(error: Error) {\n if (!error.stack) {\n return { isReactError: false, reactError: null }\n }\n\n RuntimeErrorHandler.hadRuntimeError = true\n\n return {\n isReactError: true,\n reactError: error,\n }\n }\n\n componentDidCatch() {\n this.props.onError(this.state.isReactError)\n }\n\n render() {\n const { children, globalError } = this.props\n const { isReactError, reactError } = this.state\n\n const fallback = (\n <ErroredHtml globalError={globalError} error={reactError} />\n )\n\n return isReactError ? fallback : children\n }\n}\n"],"names":["PureComponent","RuntimeErrorHandler","ErrorBoundary","GlobalError","DefaultGlobalError","ErroredHtml","globalError","globalErrorStyles","error","html","head","body","errorComponent","AppDevOverlayErrorBoundary","getDerivedStateFromError","stack","isReactError","reactError","hadRuntimeError","componentDidCatch","props","onError","state","render","children","fallback"],"mappings":";AAAA,SAASA,aAAa,QAAQ,QAAO;AACrC,SAASC,mBAAmB,QAAQ,qCAAoC;AACxE,SACEC,aAAa,EAEbC,eAAeC,kBAAkB,QAC5B,uBAAsB;AAa7B,SAASC,YAAY,KAMpB;IANoB,IAAA,EACnBC,aAAa,CAACH,aAAaI,kBAAkB,EAC7CC,KAAK,EAIN,GANoB;IAOnB,IAAI,CAACA,OAAO;QACV,qBACE,MAACC;;8BACC,KAACC;8BACD,KAACC;;;IAGP;IACA,qBACE,MAACT;QAAcU,gBAAgBR;;YAC5BG;0BACD,KAACJ;gBAAYK,OAAOA;;;;AAG1B;AAEA,OAAO,MAAMK,mCAAmCb;IAM9C,OAAOc,yBAAyBN,KAAY,EAAE;QAC5C,IAAI,CAACA,MAAMO,KAAK,EAAE;YAChB,OAAO;gBAAEC,cAAc;gBAAOC,YAAY;YAAK;QACjD;QAEAhB,oBAAoBiB,eAAe,GAAG;QAEtC,OAAO;YACLF,cAAc;YACdC,YAAYT;QACd;IACF;IAEAW,oBAAoB;QAClB,IAAI,CAACC,KAAK,CAACC,OAAO,CAAC,IAAI,CAACC,KAAK,CAACN,YAAY;IAC5C;IAEAO,SAAS;QACP,MAAM,EAAEC,QAAQ,EAAElB,WAAW,EAAE,GAAG,IAAI,CAACc,KAAK;QAC5C,MAAM,EAAEJ,YAAY,EAAEC,UAAU,EAAE,GAAG,IAAI,CAACK,KAAK;QAE/C,MAAMG,yBACJ,KAACpB;YAAYC,aAAaA;YAAaE,OAAOS;;QAGhD,OAAOD,eAAeS,WAAWD;IACnC;;QAhCK,qBAILF,QAAQ;YAAEN,cAAc;YAAOC,YAAY;QAAK;;AA6BlD"}

View File

@@ -0,0 +1,79 @@
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
import { useEffect, useState } from 'react';
import { AppDevOverlayErrorBoundary } from './app-dev-overlay-error-boundary';
import { FontStyles } from '../font/font-styles';
import { DevOverlay } from '../ui/dev-overlay';
import { handleClientError } from '../../errors/use-error-handler';
import { isNextRouterError } from '../../is-next-router-error';
function readSsrError() {
if (typeof document === 'undefined') {
return null;
}
const ssrErrorTemplateTag = document.querySelector('template[data-next-error-message]');
if (ssrErrorTemplateTag) {
const message = ssrErrorTemplateTag.getAttribute('data-next-error-message');
const stack = ssrErrorTemplateTag.getAttribute('data-next-error-stack');
const digest = ssrErrorTemplateTag.getAttribute('data-next-error-digest');
const error = Object.defineProperty(new Error(message), "__NEXT_ERROR_CODE", {
value: "E394",
enumerable: false,
configurable: true
});
if (digest) {
;
error.digest = digest;
}
// Skip Next.js SSR'd internal errors that which will be handled by the error boundaries.
if (isNextRouterError(error)) {
return null;
}
error.stack = stack || '';
return error;
}
return null;
}
// Needs to be in the same error boundary as the shell.
// If it commits, we know we recovered from an SSR error.
// If it doesn't commit, we errored again and React will take care of error reporting.
function ReplaySsrOnlyErrors() {
if (process.env.NODE_ENV !== 'production') {
// Need to read during render. The attributes will be gone after commit.
const ssrError = readSsrError();
// eslint-disable-next-line react-hooks/rules-of-hooks
useEffect(()=>{
if (ssrError !== null) {
// TODO(veil): Produces wrong Owner Stack
// TODO(veil): Mark as recoverable error
// TODO(veil): console.error
handleClientError(ssrError, []);
}
}, [
ssrError
]);
}
return null;
}
export function AppDevOverlay(param) {
let { state, globalError, children } = param;
const [isErrorOverlayOpen, setIsErrorOverlayOpen] = useState(false);
return /*#__PURE__*/ _jsxs(_Fragment, {
children: [
/*#__PURE__*/ _jsxs(AppDevOverlayErrorBoundary, {
globalError: globalError,
onError: setIsErrorOverlayOpen,
children: [
/*#__PURE__*/ _jsx(ReplaySsrOnlyErrors, {}),
children
]
}),
/*#__PURE__*/ _jsx(FontStyles, {}),
/*#__PURE__*/ _jsx(DevOverlay, {
state: state,
isErrorOverlayOpen: isErrorOverlayOpen,
setIsErrorOverlayOpen: setIsErrorOverlayOpen
})
]
});
}
//# sourceMappingURL=app-dev-overlay.js.map

View File

@@ -0,0 +1 @@
{"version":3,"sources":["../../../../../src/client/components/react-dev-overlay/app/app-dev-overlay.tsx"],"sourcesContent":["import type { OverlayState } from '../shared'\nimport type { GlobalErrorComponent } from '../../error-boundary'\n\nimport { useEffect, useState } from 'react'\nimport { AppDevOverlayErrorBoundary } from './app-dev-overlay-error-boundary'\nimport { FontStyles } from '../font/font-styles'\nimport { DevOverlay } from '../ui/dev-overlay'\nimport { handleClientError } from '../../errors/use-error-handler'\nimport { isNextRouterError } from '../../is-next-router-error'\n\nfunction readSsrError(): Error | null {\n if (typeof document === 'undefined') {\n return null\n }\n\n const ssrErrorTemplateTag = document.querySelector(\n 'template[data-next-error-message]'\n )\n if (ssrErrorTemplateTag) {\n const message: string = ssrErrorTemplateTag.getAttribute(\n 'data-next-error-message'\n )!\n const stack = ssrErrorTemplateTag.getAttribute('data-next-error-stack')\n const digest = ssrErrorTemplateTag.getAttribute('data-next-error-digest')\n const error = new Error(message)\n if (digest) {\n ;(error as any).digest = digest\n }\n // Skip Next.js SSR'd internal errors that which will be handled by the error boundaries.\n if (isNextRouterError(error)) {\n return null\n }\n error.stack = stack || ''\n return error\n }\n\n return null\n}\n\n// Needs to be in the same error boundary as the shell.\n// If it commits, we know we recovered from an SSR error.\n// If it doesn't commit, we errored again and React will take care of error reporting.\nfunction ReplaySsrOnlyErrors() {\n if (process.env.NODE_ENV !== 'production') {\n // Need to read during render. The attributes will be gone after commit.\n const ssrError = readSsrError()\n // eslint-disable-next-line react-hooks/rules-of-hooks\n useEffect(() => {\n if (ssrError !== null) {\n // TODO(veil): Produces wrong Owner Stack\n // TODO(veil): Mark as recoverable error\n // TODO(veil): console.error\n handleClientError(ssrError, [])\n }\n }, [ssrError])\n }\n\n return null\n}\n\nexport function AppDevOverlay({\n state,\n globalError,\n children,\n}: {\n state: OverlayState\n globalError: [GlobalErrorComponent, React.ReactNode]\n children: React.ReactNode\n}) {\n const [isErrorOverlayOpen, setIsErrorOverlayOpen] = useState(false)\n\n return (\n <>\n <AppDevOverlayErrorBoundary\n globalError={globalError}\n onError={setIsErrorOverlayOpen}\n >\n <ReplaySsrOnlyErrors />\n {children}\n </AppDevOverlayErrorBoundary>\n\n {/* Fonts can only be loaded outside the Shadow DOM. */}\n <FontStyles />\n <DevOverlay\n state={state}\n isErrorOverlayOpen={isErrorOverlayOpen}\n setIsErrorOverlayOpen={setIsErrorOverlayOpen}\n />\n </>\n )\n}\n"],"names":["useEffect","useState","AppDevOverlayErrorBoundary","FontStyles","DevOverlay","handleClientError","isNextRouterError","readSsrError","document","ssrErrorTemplateTag","querySelector","message","getAttribute","stack","digest","error","Error","ReplaySsrOnlyErrors","process","env","NODE_ENV","ssrError","AppDevOverlay","state","globalError","children","isErrorOverlayOpen","setIsErrorOverlayOpen","onError"],"mappings":";AAGA,SAASA,SAAS,EAAEC,QAAQ,QAAQ,QAAO;AAC3C,SAASC,0BAA0B,QAAQ,mCAAkC;AAC7E,SAASC,UAAU,QAAQ,sBAAqB;AAChD,SAASC,UAAU,QAAQ,oBAAmB;AAC9C,SAASC,iBAAiB,QAAQ,iCAAgC;AAClE,SAASC,iBAAiB,QAAQ,6BAA4B;AAE9D,SAASC;IACP,IAAI,OAAOC,aAAa,aAAa;QACnC,OAAO;IACT;IAEA,MAAMC,sBAAsBD,SAASE,aAAa,CAChD;IAEF,IAAID,qBAAqB;QACvB,MAAME,UAAkBF,oBAAoBG,YAAY,CACtD;QAEF,MAAMC,QAAQJ,oBAAoBG,YAAY,CAAC;QAC/C,MAAME,SAASL,oBAAoBG,YAAY,CAAC;QAChD,MAAMG,QAAQ,qBAAkB,CAAlB,IAAIC,MAAML,UAAV,qBAAA;mBAAA;wBAAA;0BAAA;QAAiB;QAC/B,IAAIG,QAAQ;;YACRC,MAAcD,MAAM,GAAGA;QAC3B;QACA,yFAAyF;QACzF,IAAIR,kBAAkBS,QAAQ;YAC5B,OAAO;QACT;QACAA,MAAMF,KAAK,GAAGA,SAAS;QACvB,OAAOE;IACT;IAEA,OAAO;AACT;AAEA,uDAAuD;AACvD,yDAAyD;AACzD,sFAAsF;AACtF,SAASE;IACP,IAAIC,QAAQC,GAAG,CAACC,QAAQ,KAAK,cAAc;QACzC,wEAAwE;QACxE,MAAMC,WAAWd;QACjB,sDAAsD;QACtDP,UAAU;YACR,IAAIqB,aAAa,MAAM;gBACrB,yCAAyC;gBACzC,wCAAwC;gBACxC,4BAA4B;gBAC5BhB,kBAAkBgB,UAAU,EAAE;YAChC;QACF,GAAG;YAACA;SAAS;IACf;IAEA,OAAO;AACT;AAEA,OAAO,SAASC,cAAc,KAQ7B;IAR6B,IAAA,EAC5BC,KAAK,EACLC,WAAW,EACXC,QAAQ,EAKT,GAR6B;IAS5B,MAAM,CAACC,oBAAoBC,sBAAsB,GAAG1B,SAAS;IAE7D,qBACE;;0BACE,MAACC;gBACCsB,aAAaA;gBACbI,SAASD;;kCAET,KAACV;oBACAQ;;;0BAIH,KAACtB;0BACD,KAACC;gBACCmB,OAAOA;gBACPG,oBAAoBA;gBACpBC,uBAAuBA;;;;AAI/B"}

View File

@@ -0,0 +1,54 @@
import { jsx as _jsx } from "react/jsx-runtime";
import React from 'react';
import { AppDevOverlay } from './app-dev-overlay';
import { getSocketUrl } from '../utils/get-socket-url';
import { INITIAL_OVERLAY_STATE } from '../shared';
import { HMR_ACTIONS_SENT_TO_BROWSER } from '../../../../server/dev/hot-reloader-types';
import GlobalError from '../../error-boundary';
// if an error is thrown while rendering an RSC stream, this will catch it in dev
// and show the error overlay
export function createRootLevelDevOverlayElement(reactEl) {
const rootLayoutMissingTags = window.__next_root_layout_missing_tags;
const hasMissingTags = !!(rootLayoutMissingTags == null ? void 0 : rootLayoutMissingTags.length);
const socketUrl = getSocketUrl(process.env.__NEXT_ASSET_PREFIX || '');
const socket = new window.WebSocket("" + socketUrl + "/_next/webpack-hmr");
// add minimal "hot reload" support for RSC errors
const handler = (event)=>{
let obj;
try {
obj = JSON.parse(event.data);
} catch (e) {}
if (!obj || !('action' in obj)) {
return;
}
if (obj.action === HMR_ACTIONS_SENT_TO_BROWSER.SERVER_COMPONENT_CHANGES) {
window.location.reload();
}
};
socket.addEventListener('message', handler);
const FallbackLayout = hasMissingTags ? (param)=>{
let { children } = param;
return /*#__PURE__*/ _jsx("html", {
id: "__next_error__",
children: /*#__PURE__*/ _jsx("body", {
children: children
})
});
} : React.Fragment;
return /*#__PURE__*/ _jsx(FallbackLayout, {
children: /*#__PURE__*/ _jsx(AppDevOverlay, {
state: {
...INITIAL_OVERLAY_STATE,
rootLayoutMissingTags,
routerType: 'app'
},
globalError: [
GlobalError,
null
],
children: reactEl
})
});
}
//# sourceMappingURL=client-entry.js.map

View File

@@ -0,0 +1 @@
{"version":3,"sources":["../../../../../src/client/components/react-dev-overlay/app/client-entry.tsx"],"sourcesContent":["import React from 'react'\nimport { AppDevOverlay } from './app-dev-overlay'\nimport { getSocketUrl } from '../utils/get-socket-url'\nimport { INITIAL_OVERLAY_STATE } from '../shared'\nimport { HMR_ACTIONS_SENT_TO_BROWSER } from '../../../../server/dev/hot-reloader-types'\nimport GlobalError from '../../error-boundary'\n\n// if an error is thrown while rendering an RSC stream, this will catch it in dev\n// and show the error overlay\nexport function createRootLevelDevOverlayElement(reactEl: React.ReactElement) {\n const rootLayoutMissingTags = window.__next_root_layout_missing_tags\n const hasMissingTags = !!rootLayoutMissingTags?.length\n const socketUrl = getSocketUrl(process.env.__NEXT_ASSET_PREFIX || '')\n const socket = new window.WebSocket(`${socketUrl}/_next/webpack-hmr`)\n\n // add minimal \"hot reload\" support for RSC errors\n const handler = (event: MessageEvent) => {\n let obj\n try {\n obj = JSON.parse(event.data)\n } catch {}\n\n if (!obj || !('action' in obj)) {\n return\n }\n\n if (obj.action === HMR_ACTIONS_SENT_TO_BROWSER.SERVER_COMPONENT_CHANGES) {\n window.location.reload()\n }\n }\n\n socket.addEventListener('message', handler)\n\n const FallbackLayout = hasMissingTags\n ? ({ children }: { children: React.ReactNode }) => (\n <html id=\"__next_error__\">\n <body>{children}</body>\n </html>\n )\n : React.Fragment\n\n return (\n <FallbackLayout>\n <AppDevOverlay\n state={{\n ...INITIAL_OVERLAY_STATE,\n rootLayoutMissingTags,\n routerType: 'app',\n }}\n globalError={[GlobalError, null]}\n >\n {reactEl}\n </AppDevOverlay>\n </FallbackLayout>\n )\n}\n"],"names":["React","AppDevOverlay","getSocketUrl","INITIAL_OVERLAY_STATE","HMR_ACTIONS_SENT_TO_BROWSER","GlobalError","createRootLevelDevOverlayElement","reactEl","rootLayoutMissingTags","window","__next_root_layout_missing_tags","hasMissingTags","length","socketUrl","process","env","__NEXT_ASSET_PREFIX","socket","WebSocket","handler","event","obj","JSON","parse","data","action","SERVER_COMPONENT_CHANGES","location","reload","addEventListener","FallbackLayout","children","html","id","body","Fragment","state","routerType","globalError"],"mappings":";AAAA,OAAOA,WAAW,QAAO;AACzB,SAASC,aAAa,QAAQ,oBAAmB;AACjD,SAASC,YAAY,QAAQ,0BAAyB;AACtD,SAASC,qBAAqB,QAAQ,YAAW;AACjD,SAASC,2BAA2B,QAAQ,4CAA2C;AACvF,OAAOC,iBAAiB,uBAAsB;AAE9C,iFAAiF;AACjF,6BAA6B;AAC7B,OAAO,SAASC,iCAAiCC,OAA2B;IAC1E,MAAMC,wBAAwBC,OAAOC,+BAA+B;IACpE,MAAMC,iBAAiB,CAAC,EAACH,yCAAAA,sBAAuBI,MAAM;IACtD,MAAMC,YAAYX,aAAaY,QAAQC,GAAG,CAACC,mBAAmB,IAAI;IAClE,MAAMC,SAAS,IAAIR,OAAOS,SAAS,CAAC,AAAC,KAAEL,YAAU;IAEjD,kDAAkD;IAClD,MAAMM,UAAU,CAACC;QACf,IAAIC;QACJ,IAAI;YACFA,MAAMC,KAAKC,KAAK,CAACH,MAAMI,IAAI;QAC7B,EAAE,UAAM,CAAC;QAET,IAAI,CAACH,OAAO,CAAE,CAAA,YAAYA,GAAE,GAAI;YAC9B;QACF;QAEA,IAAIA,IAAII,MAAM,KAAKrB,4BAA4BsB,wBAAwB,EAAE;YACvEjB,OAAOkB,QAAQ,CAACC,MAAM;QACxB;IACF;IAEAX,OAAOY,gBAAgB,CAAC,WAAWV;IAEnC,MAAMW,iBAAiBnB,iBACnB;YAAC,EAAEoB,QAAQ,EAAiC;6BAC1C,KAACC;YAAKC,IAAG;sBACP,cAAA,KAACC;0BAAMH;;;QAGX/B,MAAMmC,QAAQ;IAElB,qBACE,KAACL;kBACC,cAAA,KAAC7B;YACCmC,OAAO;gBACL,GAAGjC,qBAAqB;gBACxBK;gBACA6B,YAAY;YACd;YACAC,aAAa;gBAACjC;gBAAa;aAAK;sBAE/BE;;;AAIT"}

View File

@@ -0,0 +1,556 @@
import { jsx as _jsx } from "react/jsx-runtime";
import { useCallback, useEffect, startTransition, useMemo, useRef, useSyncExternalStore } from 'react';
import stripAnsi from 'next/dist/compiled/strip-ansi';
import formatWebpackMessages from '../utils/format-webpack-messages';
import { useRouter } from '../../navigation';
import { ACTION_BEFORE_REFRESH, ACTION_BUILD_ERROR, ACTION_BUILD_OK, ACTION_DEBUG_INFO, ACTION_DEV_INDICATOR, ACTION_REFRESH, ACTION_STATIC_INDICATOR, ACTION_UNHANDLED_ERROR, ACTION_UNHANDLED_REJECTION, ACTION_VERSION_INFO, useErrorOverlayReducer } from '../shared';
import { parseStack } from '../utils/parse-stack';
import { AppDevOverlay } from './app-dev-overlay';
import { useErrorHandler } from '../../errors/use-error-handler';
import { RuntimeErrorHandler } from '../../errors/runtime-error-handler';
import { useSendMessage, useTurbopack, useWebsocket, useWebsocketPing } from '../utils/use-websocket';
import { parseComponentStack } from '../utils/parse-component-stack';
import { HMR_ACTIONS_SENT_TO_BROWSER } from '../../../../server/dev/hot-reloader-types';
import { extractModulesFromTurbopackMessage } from '../../../../server/dev/extract-modules-from-turbopack-message';
import { REACT_REFRESH_FULL_RELOAD_FROM_ERROR } from '../shared';
import { useUntrackedPathname } from '../../navigation-untracked';
import { getReactStitchedError } from '../../errors/stitched-error';
import { shouldRenderRootLevelErrorOverlay } from '../../../lib/is-error-thrown-while-rendering-rsc';
import { handleDevBuildIndicatorHmrEvents } from '../../../dev/dev-build-indicator/internal/handle-dev-build-indicator-hmr-events';
let mostRecentCompilationHash = null;
let __nextDevClientId = Math.round(Math.random() * 100 + Date.now());
let reloading = false;
let startLatency = null;
let turbopackLastUpdateLatency = null;
let turbopackUpdatedModules = new Set();
let pendingHotUpdateWebpack = Promise.resolve();
let resolvePendingHotUpdateWebpack = ()=>{};
function setPendingHotUpdateWebpack() {
pendingHotUpdateWebpack = new Promise((resolve)=>{
resolvePendingHotUpdateWebpack = ()=>{
resolve();
};
});
}
export function waitForWebpackRuntimeHotUpdate() {
return pendingHotUpdateWebpack;
}
function handleBeforeHotUpdateWebpack(dispatcher, hasUpdates) {
if (hasUpdates) {
dispatcher.onBeforeRefresh();
}
}
function handleSuccessfulHotUpdateWebpack(dispatcher, sendMessage, updatedModules) {
resolvePendingHotUpdateWebpack();
dispatcher.onBuildOk();
reportHmrLatency(sendMessage, updatedModules);
dispatcher.onRefresh();
}
function reportHmrLatency(sendMessage, updatedModules) {
if (!startLatency) return;
// turbopack has a debounce for the "built" event which we don't want to
// incorrectly show in this number, use the last TURBOPACK_MESSAGE time
let endLatency = turbopackLastUpdateLatency != null ? turbopackLastUpdateLatency : Date.now();
const latency = endLatency - startLatency;
console.log("[Fast Refresh] done in " + latency + "ms");
sendMessage(JSON.stringify({
event: 'client-hmr-latency',
id: window.__nextDevClientId,
startTime: startLatency,
endTime: endLatency,
page: window.location.pathname,
updatedModules,
// Whether the page (tab) was hidden at the time the event occurred.
// This can impact the accuracy of the event's timing.
isPageHidden: document.visibilityState === 'hidden'
}));
}
// There is a newer version of the code available.
function handleAvailableHash(hash) {
// Update last known compilation hash.
mostRecentCompilationHash = hash;
}
/**
* Is there a newer version of this code available?
* For webpack: Check if the hash changed compared to __webpack_hash__
* For Turbopack: Always true because it doesn't have __webpack_hash__
*/ function isUpdateAvailable() {
if (process.env.TURBOPACK) {
return true;
}
/* globals __webpack_hash__ */ // __webpack_hash__ is the hash of the current compilation.
// It's a global variable injected by Webpack.
return mostRecentCompilationHash !== __webpack_hash__;
}
// Webpack disallows updates in other states.
function canApplyUpdates() {
// @ts-expect-error module.hot exists
return module.hot.status() === 'idle';
}
function afterApplyUpdates(fn) {
if (canApplyUpdates()) {
fn();
} else {
function handler(status) {
if (status === 'idle') {
// @ts-expect-error module.hot exists
module.hot.removeStatusHandler(handler);
fn();
}
}
// @ts-expect-error module.hot exists
module.hot.addStatusHandler(handler);
}
}
function performFullReload(err, sendMessage) {
const stackTrace = err && (err.stack && err.stack.split('\n').slice(0, 5).join('\n') || err.message || err + '');
sendMessage(JSON.stringify({
event: 'client-full-reload',
stackTrace,
hadRuntimeError: !!RuntimeErrorHandler.hadRuntimeError,
dependencyChain: err ? err.dependencyChain : undefined
}));
if (reloading) return;
reloading = true;
window.location.reload();
}
// Attempt to update code on the fly, fall back to a hard reload.
function tryApplyUpdates(onBeforeUpdate, onHotUpdateSuccess, sendMessage, dispatcher) {
if (!isUpdateAvailable() || !canApplyUpdates()) {
resolvePendingHotUpdateWebpack();
dispatcher.onBuildOk();
reportHmrLatency(sendMessage, []);
return;
}
function handleApplyUpdates(err, updatedModules) {
if (err || RuntimeErrorHandler.hadRuntimeError || !updatedModules) {
if (err) {
console.warn('[Fast Refresh] performing full reload\n\n' + "Fast Refresh will perform a full reload when you edit a file that's imported by modules outside of the React rendering tree.\n" + 'You might have a file which exports a React component but also exports a value that is imported by a non-React component file.\n' + 'Consider migrating the non-React component export to a separate file and importing it into both files.\n\n' + 'It is also possible the parent component of the component you edited is a class component, which disables Fast Refresh.\n' + 'Fast Refresh requires at least one parent function component in your React tree.');
} else if (RuntimeErrorHandler.hadRuntimeError) {
console.warn(REACT_REFRESH_FULL_RELOAD_FROM_ERROR);
}
performFullReload(err, sendMessage);
return;
}
const hasUpdates = Boolean(updatedModules.length);
if (typeof onHotUpdateSuccess === 'function') {
// Maybe we want to do something.
onHotUpdateSuccess(updatedModules);
}
if (isUpdateAvailable()) {
// While we were updating, there was a new update! Do it again.
tryApplyUpdates(hasUpdates ? ()=>{} : onBeforeUpdate, hasUpdates ? ()=>dispatcher.onBuildOk() : onHotUpdateSuccess, sendMessage, dispatcher);
} else {
dispatcher.onBuildOk();
if (process.env.__NEXT_TEST_MODE) {
afterApplyUpdates(()=>{
if (self.__NEXT_HMR_CB) {
self.__NEXT_HMR_CB();
self.__NEXT_HMR_CB = null;
}
});
}
}
}
// https://webpack.js.org/api/hot-module-replacement/#check
// @ts-expect-error module.hot exists
module.hot.check(/* autoApply */ false).then((updatedModules)=>{
if (!updatedModules) {
return null;
}
if (typeof onBeforeUpdate === 'function') {
const hasUpdates = Boolean(updatedModules.length);
onBeforeUpdate(hasUpdates);
}
// https://webpack.js.org/api/hot-module-replacement/#apply
// @ts-expect-error module.hot exists
return module.hot.apply();
}).then((updatedModules)=>{
handleApplyUpdates(null, updatedModules);
}, (err)=>{
handleApplyUpdates(err, null);
});
}
/** Handles messages from the sevrer for the App Router. */ function processMessage(obj, sendMessage, processTurbopackMessage, router, dispatcher, appIsrManifestRef, pathnameRef) {
if (!('action' in obj)) {
return;
}
function handleErrors(errors) {
// "Massage" webpack messages.
const formatted = formatWebpackMessages({
errors: errors,
warnings: []
});
// Only show the first error.
dispatcher.onBuildError(formatted.errors[0]);
// Also log them to the console.
for(let i = 0; i < formatted.errors.length; i++){
console.error(stripAnsi(formatted.errors[i]));
}
// Do not attempt to reload now.
// We will reload on next success instead.
if (process.env.__NEXT_TEST_MODE) {
if (self.__NEXT_HMR_CB) {
self.__NEXT_HMR_CB(formatted.errors[0]);
self.__NEXT_HMR_CB = null;
}
}
}
function handleHotUpdate() {
if (process.env.TURBOPACK) {
dispatcher.onBuildOk();
reportHmrLatency(sendMessage, [
...turbopackUpdatedModules
]);
} else {
tryApplyUpdates(function onBeforeHotUpdate(hasUpdates) {
handleBeforeHotUpdateWebpack(dispatcher, hasUpdates);
}, function onSuccessfulHotUpdate(webpackUpdatedModules) {
// Only dismiss it when we're sure it's a hot update.
// Otherwise it would flicker right before the reload.
handleSuccessfulHotUpdateWebpack(dispatcher, sendMessage, webpackUpdatedModules);
}, sendMessage, dispatcher);
}
}
switch(obj.action){
case HMR_ACTIONS_SENT_TO_BROWSER.ISR_MANIFEST:
{
if (process.env.__NEXT_DEV_INDICATOR) {
if (appIsrManifestRef) {
appIsrManifestRef.current = obj.data;
// handle initial status on receiving manifest
// navigation is handled in useEffect for pathname changes
// as we'll receive the updated manifest before usePathname
// triggers for new value
if (pathnameRef.current in obj.data) {
dispatcher.onStaticIndicator(true);
} else {
dispatcher.onStaticIndicator(false);
}
}
}
break;
}
case HMR_ACTIONS_SENT_TO_BROWSER.BUILDING:
{
startLatency = Date.now();
turbopackLastUpdateLatency = null;
turbopackUpdatedModules.clear();
if (!process.env.TURBOPACK) {
setPendingHotUpdateWebpack();
}
console.log('[Fast Refresh] rebuilding');
break;
}
case HMR_ACTIONS_SENT_TO_BROWSER.BUILT:
case HMR_ACTIONS_SENT_TO_BROWSER.SYNC:
{
if (obj.hash) {
handleAvailableHash(obj.hash);
}
const { errors, warnings } = obj;
// Is undefined when it's a 'built' event
if ('versionInfo' in obj) dispatcher.onVersionInfo(obj.versionInfo);
if ('debug' in obj && obj.debug) dispatcher.onDebugInfo(obj.debug);
if ('devIndicator' in obj) dispatcher.onDevIndicator(obj.devIndicator);
const hasErrors = Boolean(errors && errors.length);
// Compilation with errors (e.g. syntax error or missing modules).
if (hasErrors) {
sendMessage(JSON.stringify({
event: 'client-error',
errorCount: errors.length,
clientId: __nextDevClientId
}));
handleErrors(errors);
return;
}
const hasWarnings = Boolean(warnings && warnings.length);
if (hasWarnings) {
sendMessage(JSON.stringify({
event: 'client-warning',
warningCount: warnings.length,
clientId: __nextDevClientId
}));
// Print warnings to the console.
const formattedMessages = formatWebpackMessages({
warnings: warnings,
errors: []
});
for(let i = 0; i < formattedMessages.warnings.length; i++){
if (i === 5) {
console.warn('There were more warnings in other files.\n' + 'You can find a complete log in the terminal.');
break;
}
console.warn(stripAnsi(formattedMessages.warnings[i]));
}
// No early return here as we need to apply modules in the same way between warnings only and compiles without warnings
}
sendMessage(JSON.stringify({
event: 'client-success',
clientId: __nextDevClientId
}));
if (obj.action === HMR_ACTIONS_SENT_TO_BROWSER.BUILT) {
// Handle hot updates
handleHotUpdate();
}
return;
}
case HMR_ACTIONS_SENT_TO_BROWSER.TURBOPACK_CONNECTED:
{
processTurbopackMessage({
type: HMR_ACTIONS_SENT_TO_BROWSER.TURBOPACK_CONNECTED,
data: {
sessionId: obj.data.sessionId
}
});
break;
}
case HMR_ACTIONS_SENT_TO_BROWSER.TURBOPACK_MESSAGE:
{
dispatcher.onBeforeRefresh();
processTurbopackMessage({
type: HMR_ACTIONS_SENT_TO_BROWSER.TURBOPACK_MESSAGE,
data: obj.data
});
dispatcher.onRefresh();
if (RuntimeErrorHandler.hadRuntimeError) {
console.warn(REACT_REFRESH_FULL_RELOAD_FROM_ERROR);
performFullReload(null, sendMessage);
}
for (const module1 of extractModulesFromTurbopackMessage(obj.data)){
turbopackUpdatedModules.add(module1);
}
turbopackLastUpdateLatency = Date.now();
break;
}
// TODO-APP: make server component change more granular
case HMR_ACTIONS_SENT_TO_BROWSER.SERVER_COMPONENT_CHANGES:
{
sendMessage(JSON.stringify({
event: 'server-component-reload-page',
clientId: __nextDevClientId,
hash: obj.hash
}));
// Store the latest hash in a session cookie so that it's sent back to the
// server with any subsequent requests.
document.cookie = "__next_hmr_refresh_hash__=" + obj.hash;
if (RuntimeErrorHandler.hadRuntimeError) {
if (reloading) return;
reloading = true;
return window.location.reload();
}
startTransition(()=>{
router.hmrRefresh();
dispatcher.onRefresh();
});
if (process.env.__NEXT_TEST_MODE) {
if (self.__NEXT_HMR_CB) {
self.__NEXT_HMR_CB();
self.__NEXT_HMR_CB = null;
}
}
return;
}
case HMR_ACTIONS_SENT_TO_BROWSER.RELOAD_PAGE:
{
sendMessage(JSON.stringify({
event: 'client-reload-page',
clientId: __nextDevClientId
}));
if (reloading) return;
reloading = true;
return window.location.reload();
}
case HMR_ACTIONS_SENT_TO_BROWSER.ADDED_PAGE:
case HMR_ACTIONS_SENT_TO_BROWSER.REMOVED_PAGE:
{
// TODO-APP: potentially only refresh if the currently viewed page was added/removed.
return router.hmrRefresh();
}
case HMR_ACTIONS_SENT_TO_BROWSER.SERVER_ERROR:
{
const { errorJSON } = obj;
if (errorJSON) {
const { message, stack } = JSON.parse(errorJSON);
const error = Object.defineProperty(new Error(message), "__NEXT_ERROR_CODE", {
value: "E394",
enumerable: false,
configurable: true
});
error.stack = stack;
handleErrors([
error
]);
}
return;
}
case HMR_ACTIONS_SENT_TO_BROWSER.DEV_PAGES_MANIFEST_UPDATE:
{
return;
}
default:
{}
}
}
export default function HotReload(param) {
let { assetPrefix, children, globalError } = param;
const [state, dispatch] = useErrorOverlayReducer('app');
const dispatcher = useMemo(()=>{
return {
onBuildOk () {
dispatch({
type: ACTION_BUILD_OK
});
},
onBuildError (message) {
dispatch({
type: ACTION_BUILD_ERROR,
message
});
},
onBeforeRefresh () {
dispatch({
type: ACTION_BEFORE_REFRESH
});
},
onRefresh () {
dispatch({
type: ACTION_REFRESH
});
},
onVersionInfo (versionInfo) {
dispatch({
type: ACTION_VERSION_INFO,
versionInfo
});
},
onStaticIndicator (status) {
dispatch({
type: ACTION_STATIC_INDICATOR,
staticIndicator: status
});
},
onDebugInfo (debugInfo) {
dispatch({
type: ACTION_DEBUG_INFO,
debugInfo
});
},
onDevIndicator (devIndicator) {
dispatch({
type: ACTION_DEV_INDICATOR,
devIndicator
});
}
};
}, [
dispatch
]);
// We render a separate error overlay at the root when an error is thrown from rendering RSC, so
// we should not render an additional error overlay in the descendent. However, we need to
// keep rendering these hooks to ensure HMR works when the error is addressed.
const shouldRenderErrorOverlay = useSyncExternalStore(()=>()=>{}, ()=>!shouldRenderRootLevelErrorOverlay(), ()=>true);
const handleOnUnhandledError = useCallback((error)=>{
const errorDetails = error.details;
// Component stack is added to the error in use-error-handler in case there was a hydration error
const componentStackTrace = error._componentStack || (errorDetails == null ? void 0 : errorDetails.componentStack);
const warning = errorDetails == null ? void 0 : errorDetails.warning;
dispatch({
type: ACTION_UNHANDLED_ERROR,
reason: error,
frames: parseStack(error.stack || ''),
componentStackFrames: typeof componentStackTrace === 'string' ? parseComponentStack(componentStackTrace) : undefined,
warning
});
}, [
dispatch
]);
const handleOnUnhandledRejection = useCallback((reason)=>{
const stitchedError = getReactStitchedError(reason);
dispatch({
type: ACTION_UNHANDLED_REJECTION,
reason: stitchedError,
frames: parseStack(stitchedError.stack || '')
});
}, [
dispatch
]);
useErrorHandler(handleOnUnhandledError, handleOnUnhandledRejection);
const webSocketRef = useWebsocket(assetPrefix);
useWebsocketPing(webSocketRef);
const sendMessage = useSendMessage(webSocketRef);
const processTurbopackMessage = useTurbopack(sendMessage, (err)=>performFullReload(err, sendMessage));
const router = useRouter();
// We don't want access of the pathname for the dev tools to trigger a dynamic
// access (as the dev overlay will never be present in production).
const pathname = useUntrackedPathname();
const appIsrManifestRef = useRef({});
const pathnameRef = useRef(pathname);
if (process.env.__NEXT_DEV_INDICATOR) {
// this conditional is only for dead-code elimination which
// isn't a runtime conditional only build-time so ignore hooks rule
// eslint-disable-next-line react-hooks/rules-of-hooks
useEffect(()=>{
pathnameRef.current = pathname;
const appIsrManifest = appIsrManifestRef.current;
if (appIsrManifest) {
if (pathname && pathname in appIsrManifest) {
try {
dispatcher.onStaticIndicator(true);
} catch (reason) {
let message = '';
if (reason instanceof DOMException) {
var _reason_stack;
// Most likely a SecurityError, because of an unavailable localStorage
message = (_reason_stack = reason.stack) != null ? _reason_stack : reason.message;
} else if (reason instanceof Error) {
var _reason_stack1;
message = 'Error: ' + reason.message + '\n' + ((_reason_stack1 = reason.stack) != null ? _reason_stack1 : '');
} else {
message = 'Unexpected Exception: ' + reason;
}
console.warn('[HMR] ' + message);
}
} else {
dispatcher.onStaticIndicator(false);
}
}
}, [
pathname,
dispatcher
]);
}
useEffect(()=>{
const websocket = webSocketRef.current;
if (!websocket) return;
const handler = (event)=>{
try {
const obj = JSON.parse(event.data);
handleDevBuildIndicatorHmrEvents(obj);
processMessage(obj, sendMessage, processTurbopackMessage, router, dispatcher, appIsrManifestRef, pathnameRef);
} catch (err) {
var _err_stack;
console.warn('[HMR] Invalid message: ' + JSON.stringify(event.data) + '\n' + ((_err_stack = err == null ? void 0 : err.stack) != null ? _err_stack : ''));
}
};
websocket.addEventListener('message', handler);
return ()=>websocket.removeEventListener('message', handler);
}, [
sendMessage,
router,
webSocketRef,
dispatcher,
processTurbopackMessage,
appIsrManifestRef
]);
if (shouldRenderErrorOverlay) {
return /*#__PURE__*/ _jsx(AppDevOverlay, {
state: state,
globalError: globalError,
children: children
});
}
return children;
}
//# sourceMappingURL=hot-reloader-client.js.map

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,25 @@
import { _ as _tagged_template_literal_loose } from "@swc/helpers/_/_tagged_template_literal_loose";
function _templateObject() {
const data = _tagged_template_literal_loose([
"\n /* latin-ext */\n @font-face {\n font-family: '__nextjs-Geist';\n font-style: normal;\n font-weight: 400 600;\n font-display: swap;\n src: url(/__nextjs_font/geist-latin-ext.woff2) format('woff2');\n unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7,\n U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F,\n U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F,\n U+A720-A7FF;\n }\n /* latin-ext */\n @font-face {\n font-family: '__nextjs-Geist Mono';\n font-style: normal;\n font-weight: 400 600;\n font-display: swap;\n src: url(/__nextjs_font/geist-mono-latin-ext.woff2) format('woff2');\n unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7,\n U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F,\n U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F,\n U+A720-A7FF;\n }\n /* latin */\n @font-face {\n font-family: '__nextjs-Geist';\n font-style: normal;\n font-weight: 400 600;\n font-display: swap;\n src: url(/__nextjs_font/geist-latin.woff2) format('woff2');\n unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6,\n U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122,\n U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;\n }\n /* latin */\n @font-face {\n font-family: '__nextjs-Geist Mono';\n font-style: normal;\n font-weight: 400 600;\n font-display: swap;\n src: url(/__nextjs_font/geist-mono-latin.woff2) format('woff2');\n unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6,\n U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122,\n U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;\n }\n "
]);
_templateObject = function() {
return data;
};
return data;
}
import { css } from '../utils/css';
import { useInsertionEffect } from 'react';
export const FontStyles = ()=>{
useInsertionEffect(()=>{
const style = document.createElement('style');
style.textContent = css(_templateObject());
document.head.appendChild(style);
return ()=>{
document.head.removeChild(style);
};
}, []);
return null;
};
//# sourceMappingURL=font-styles.js.map

View File

@@ -0,0 +1 @@
{"version":3,"sources":["../../../../../src/client/components/react-dev-overlay/font/font-styles.tsx"],"sourcesContent":["import { css } from '../utils/css'\nimport { useInsertionEffect } from 'react'\n\nexport const FontStyles = () => {\n useInsertionEffect(() => {\n const style = document.createElement('style')\n style.textContent = css`\n /* latin-ext */\n @font-face {\n font-family: '__nextjs-Geist';\n font-style: normal;\n font-weight: 400 600;\n font-display: swap;\n src: url(/__nextjs_font/geist-latin-ext.woff2) format('woff2');\n unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7,\n U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F,\n U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F,\n U+A720-A7FF;\n }\n /* latin-ext */\n @font-face {\n font-family: '__nextjs-Geist Mono';\n font-style: normal;\n font-weight: 400 600;\n font-display: swap;\n src: url(/__nextjs_font/geist-mono-latin-ext.woff2) format('woff2');\n unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7,\n U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F,\n U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F,\n U+A720-A7FF;\n }\n /* latin */\n @font-face {\n font-family: '__nextjs-Geist';\n font-style: normal;\n font-weight: 400 600;\n font-display: swap;\n src: url(/__nextjs_font/geist-latin.woff2) format('woff2');\n unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6,\n U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122,\n U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;\n }\n /* latin */\n @font-face {\n font-family: '__nextjs-Geist Mono';\n font-style: normal;\n font-weight: 400 600;\n font-display: swap;\n src: url(/__nextjs_font/geist-mono-latin.woff2) format('woff2');\n unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6,\n U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122,\n U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;\n }\n `\n document.head.appendChild(style)\n\n return () => {\n document.head.removeChild(style)\n }\n }, [])\n\n return null\n}\n"],"names":["css","useInsertionEffect","FontStyles","style","document","createElement","textContent","head","appendChild","removeChild"],"mappings":";;;;;;;;;;AAAA,SAASA,GAAG,QAAQ,eAAc;AAClC,SAASC,kBAAkB,QAAQ,QAAO;AAE1C,OAAO,MAAMC,aAAa;IACxBD,mBAAmB;QACjB,MAAME,QAAQC,SAASC,aAAa,CAAC;QACrCF,MAAMG,WAAW,GAAGN;QAgDpBI,SAASG,IAAI,CAACC,WAAW,CAACL;QAE1B,OAAO;YACLC,SAASG,IAAI,CAACE,WAAW,CAACN;QAC5B;IACF,GAAG,EAAE;IAEL,OAAO;AACT,EAAC"}

View File

@@ -0,0 +1,54 @@
import path from 'path';
import * as fs from 'fs/promises';
import { constants } from 'fs';
import * as Log from '../../../../build/output/log';
import { middlewareResponse } from '../server/middleware-response';
const FONT_PREFIX = '/__nextjs_font/';
const VALID_FONTS = [
'geist-latin-ext.woff2',
'geist-mono-latin-ext.woff2',
'geist-latin.woff2',
'geist-mono-latin.woff2'
];
const FONT_HEADERS = {
'Content-Type': 'font/woff2',
'Cache-Control': 'public, max-age=31536000, immutable'
};
export function getDevOverlayFontMiddleware() {
return async function devOverlayFontMiddleware(req, res, next) {
try {
const { pathname } = new URL("http://n" + req.url);
if (!pathname.startsWith(FONT_PREFIX)) {
return next();
}
const fontFile = pathname.replace(FONT_PREFIX, '');
if (!VALID_FONTS.includes(fontFile)) {
return middlewareResponse.notFound(res);
}
const fontPath = path.resolve(__dirname, fontFile);
const fileExists = await checkFileExists(fontPath);
if (!fileExists) {
return middlewareResponse.notFound(res);
}
const fontData = await fs.readFile(fontPath);
Object.entries(FONT_HEADERS).forEach((param)=>{
let [key, value] = param;
res.setHeader(key, value);
});
res.end(fontData);
} catch (err) {
Log.error('Failed to serve font:', err instanceof Error ? err.message : err);
return middlewareResponse.internalServerError(res);
}
};
}
async function checkFileExists(filePath) {
try {
await fs.access(filePath, constants.F_OK);
return true;
} catch (e) {
return false;
}
}
//# sourceMappingURL=get-dev-overlay-font-middleware.js.map

View File

@@ -0,0 +1 @@
{"version":3,"sources":["../../../../../src/client/components/react-dev-overlay/font/get-dev-overlay-font-middleware.ts"],"sourcesContent":["import type { ServerResponse, IncomingMessage } from 'http'\nimport path from 'path'\nimport * as fs from 'fs/promises'\nimport { constants } from 'fs'\nimport * as Log from '../../../../build/output/log'\nimport { middlewareResponse } from '../server/middleware-response'\n\nconst FONT_PREFIX = '/__nextjs_font/'\n\nconst VALID_FONTS = [\n 'geist-latin-ext.woff2',\n 'geist-mono-latin-ext.woff2',\n 'geist-latin.woff2',\n 'geist-mono-latin.woff2',\n]\n\nconst FONT_HEADERS = {\n 'Content-Type': 'font/woff2',\n 'Cache-Control': 'public, max-age=31536000, immutable',\n} as const\n\nexport function getDevOverlayFontMiddleware() {\n return async function devOverlayFontMiddleware(\n req: IncomingMessage,\n res: ServerResponse,\n next: () => void\n ): Promise<void> {\n try {\n const { pathname } = new URL(`http://n${req.url}`)\n\n if (!pathname.startsWith(FONT_PREFIX)) {\n return next()\n }\n\n const fontFile = pathname.replace(FONT_PREFIX, '')\n if (!VALID_FONTS.includes(fontFile)) {\n return middlewareResponse.notFound(res)\n }\n\n const fontPath = path.resolve(__dirname, fontFile)\n const fileExists = await checkFileExists(fontPath)\n\n if (!fileExists) {\n return middlewareResponse.notFound(res)\n }\n\n const fontData = await fs.readFile(fontPath)\n Object.entries(FONT_HEADERS).forEach(([key, value]) => {\n res.setHeader(key, value)\n })\n res.end(fontData)\n } catch (err) {\n Log.error(\n 'Failed to serve font:',\n err instanceof Error ? err.message : err\n )\n return middlewareResponse.internalServerError(res)\n }\n }\n}\n\nasync function checkFileExists(filePath: string): Promise<boolean> {\n try {\n await fs.access(filePath, constants.F_OK)\n return true\n } catch {\n return false\n }\n}\n"],"names":["path","fs","constants","Log","middlewareResponse","FONT_PREFIX","VALID_FONTS","FONT_HEADERS","getDevOverlayFontMiddleware","devOverlayFontMiddleware","req","res","next","pathname","URL","url","startsWith","fontFile","replace","includes","notFound","fontPath","resolve","__dirname","fileExists","checkFileExists","fontData","readFile","Object","entries","forEach","key","value","setHeader","end","err","error","Error","message","internalServerError","filePath","access","F_OK"],"mappings":"AACA,OAAOA,UAAU,OAAM;AACvB,YAAYC,QAAQ,cAAa;AACjC,SAASC,SAAS,QAAQ,KAAI;AAC9B,YAAYC,SAAS,+BAA8B;AACnD,SAASC,kBAAkB,QAAQ,gCAA+B;AAElE,MAAMC,cAAc;AAEpB,MAAMC,cAAc;IAClB;IACA;IACA;IACA;CACD;AAED,MAAMC,eAAe;IACnB,gBAAgB;IAChB,iBAAiB;AACnB;AAEA,OAAO,SAASC;IACd,OAAO,eAAeC,yBACpBC,GAAoB,EACpBC,GAAmB,EACnBC,IAAgB;QAEhB,IAAI;YACF,MAAM,EAAEC,QAAQ,EAAE,GAAG,IAAIC,IAAI,AAAC,aAAUJ,IAAIK,GAAG;YAE/C,IAAI,CAACF,SAASG,UAAU,CAACX,cAAc;gBACrC,OAAOO;YACT;YAEA,MAAMK,WAAWJ,SAASK,OAAO,CAACb,aAAa;YAC/C,IAAI,CAACC,YAAYa,QAAQ,CAACF,WAAW;gBACnC,OAAOb,mBAAmBgB,QAAQ,CAACT;YACrC;YAEA,MAAMU,WAAWrB,KAAKsB,OAAO,CAACC,WAAWN;YACzC,MAAMO,aAAa,MAAMC,gBAAgBJ;YAEzC,IAAI,CAACG,YAAY;gBACf,OAAOpB,mBAAmBgB,QAAQ,CAACT;YACrC;YAEA,MAAMe,WAAW,MAAMzB,GAAG0B,QAAQ,CAACN;YACnCO,OAAOC,OAAO,CAACtB,cAAcuB,OAAO,CAAC;oBAAC,CAACC,KAAKC,MAAM;gBAChDrB,IAAIsB,SAAS,CAACF,KAAKC;YACrB;YACArB,IAAIuB,GAAG,CAACR;QACV,EAAE,OAAOS,KAAK;YACZhC,IAAIiC,KAAK,CACP,yBACAD,eAAeE,QAAQF,IAAIG,OAAO,GAAGH;YAEvC,OAAO/B,mBAAmBmC,mBAAmB,CAAC5B;QAChD;IACF;AACF;AAEA,eAAec,gBAAgBe,QAAgB;IAC7C,IAAI;QACF,MAAMvC,GAAGwC,MAAM,CAACD,UAAUtC,UAAUwC,IAAI;QACxC,OAAO;IACT,EAAE,UAAM;QACN,OAAO;IACT;AACF"}

View File

@@ -0,0 +1,38 @@
let handlers = new Set();
let queue = [];
function drain() {
// Draining should never happen synchronously in case multiple handlers are
// registered.
setTimeout(function() {
while(// Until we are out of events:
Boolean(queue.length) && // Or, if all handlers removed themselves as a result of handling the
// event(s)
Boolean(handlers.size)){
const ev = queue.shift();
handlers.forEach((handler)=>handler(ev));
}
}, 1);
}
export function emit(ev) {
queue.push(Object.freeze({
...ev
}));
drain();
}
export function on(fn) {
if (handlers.has(fn)) {
return false;
}
handlers.add(fn);
drain();
return true;
}
export function off(fn) {
if (handlers.has(fn)) {
handlers.delete(fn);
return true;
}
return false;
}
//# sourceMappingURL=bus.js.map

View File

@@ -0,0 +1 @@
{"version":3,"sources":["../../../../../src/client/components/react-dev-overlay/pages/bus.ts"],"sourcesContent":["import type { BusEvent } from '../shared'\n\nexport type BusEventHandler = (ev: BusEvent) => void\n\nlet handlers: Set<BusEventHandler> = new Set()\nlet queue: BusEvent[] = []\n\nfunction drain() {\n // Draining should never happen synchronously in case multiple handlers are\n // registered.\n setTimeout(function () {\n while (\n // Until we are out of events:\n Boolean(queue.length) &&\n // Or, if all handlers removed themselves as a result of handling the\n // event(s)\n Boolean(handlers.size)\n ) {\n const ev = queue.shift()!\n handlers.forEach((handler) => handler(ev))\n }\n }, 1)\n}\n\nexport function emit(ev: BusEvent): void {\n queue.push(Object.freeze({ ...ev }))\n drain()\n}\n\nexport function on(fn: BusEventHandler): boolean {\n if (handlers.has(fn)) {\n return false\n }\n\n handlers.add(fn)\n drain()\n return true\n}\n\nexport function off(fn: BusEventHandler): boolean {\n if (handlers.has(fn)) {\n handlers.delete(fn)\n return true\n }\n\n return false\n}\n"],"names":["handlers","Set","queue","drain","setTimeout","Boolean","length","size","ev","shift","forEach","handler","emit","push","Object","freeze","on","fn","has","add","off","delete"],"mappings":"AAIA,IAAIA,WAAiC,IAAIC;AACzC,IAAIC,QAAoB,EAAE;AAE1B,SAASC;IACP,2EAA2E;IAC3E,cAAc;IACdC,WAAW;QACT,MACE,8BAA8B;QAC9BC,QAAQH,MAAMI,MAAM,KACpB,qEAAqE;QACrE,WAAW;QACXD,QAAQL,SAASO,IAAI,EACrB;YACA,MAAMC,KAAKN,MAAMO,KAAK;YACtBT,SAASU,OAAO,CAAC,CAACC,UAAYA,QAAQH;QACxC;IACF,GAAG;AACL;AAEA,OAAO,SAASI,KAAKJ,EAAY;IAC/BN,MAAMW,IAAI,CAACC,OAAOC,MAAM,CAAC;QAAE,GAAGP,EAAE;IAAC;IACjCL;AACF;AAEA,OAAO,SAASa,GAAGC,EAAmB;IACpC,IAAIjB,SAASkB,GAAG,CAACD,KAAK;QACpB,OAAO;IACT;IAEAjB,SAASmB,GAAG,CAACF;IACbd;IACA,OAAO;AACT;AAEA,OAAO,SAASiB,IAAIH,EAAmB;IACrC,IAAIjB,SAASkB,GAAG,CAACD,KAAK;QACpBjB,SAASqB,MAAM,CAACJ;QAChB,OAAO;IACT;IAEA,OAAO;AACT"}

View File

@@ -0,0 +1,127 @@
import * as Bus from './bus';
import { parseStack } from '../utils/parse-stack';
import { parseComponentStack } from '../utils/parse-component-stack';
import { hydrationErrorState, storeHydrationErrorStateFromConsoleArgs } from '../../errors/hydration-error-info';
import { ACTION_BEFORE_REFRESH, ACTION_BUILD_ERROR, ACTION_BUILD_OK, ACTION_DEV_INDICATOR, ACTION_REFRESH, ACTION_STATIC_INDICATOR, ACTION_UNHANDLED_ERROR, ACTION_UNHANDLED_REJECTION, ACTION_VERSION_INFO } from '../shared';
import { attachHydrationErrorState } from '../../errors/attach-hydration-error-state';
let isRegistered = false;
let stackTraceLimit = undefined;
function handleError(error) {
if (!error || !(error instanceof Error) || typeof error.stack !== 'string') {
// A non-error was thrown, we don't have anything to show. :-(
return;
}
attachHydrationErrorState(error);
const componentStackTrace = error._componentStack || hydrationErrorState.componentStack;
const componentStackFrames = typeof componentStackTrace === 'string' ? parseComponentStack(componentStackTrace) : undefined;
// Skip ModuleBuildError and ModuleNotFoundError, as it will be sent through onBuildError callback.
// This is to avoid same error as different type showing up on client to cause flashing.
if (error.name !== 'ModuleBuildError' && error.name !== 'ModuleNotFoundError') {
Bus.emit({
type: ACTION_UNHANDLED_ERROR,
reason: error,
frames: parseStack(error.stack),
componentStackFrames
});
}
}
let origConsoleError = console.error;
function nextJsHandleConsoleError() {
for(var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++){
args[_key] = arguments[_key];
}
// See https://github.com/facebook/react/blob/d50323eb845c5fde0d720cae888bf35dedd05506/packages/react-reconciler/src/ReactFiberErrorLogger.js#L78
const error = process.env.NODE_ENV !== 'production' ? args[1] : args[0];
storeHydrationErrorStateFromConsoleArgs(...args);
handleError(error);
origConsoleError.apply(window.console, args);
}
function onUnhandledError(event) {
const error = event == null ? void 0 : event.error;
handleError(error);
}
function onUnhandledRejection(ev) {
const reason = ev == null ? void 0 : ev.reason;
if (!reason || !(reason instanceof Error) || typeof reason.stack !== 'string') {
// A non-error was thrown, we don't have anything to show. :-(
return;
}
const e = reason;
Bus.emit({
type: ACTION_UNHANDLED_REJECTION,
reason: reason,
frames: parseStack(e.stack)
});
}
export function register() {
if (isRegistered) {
return;
}
isRegistered = true;
try {
const limit = Error.stackTraceLimit;
Error.stackTraceLimit = 50;
stackTraceLimit = limit;
} catch (e) {}
window.addEventListener('error', onUnhandledError);
window.addEventListener('unhandledrejection', onUnhandledRejection);
window.console.error = nextJsHandleConsoleError;
}
export function unregister() {
if (!isRegistered) {
return;
}
isRegistered = false;
if (stackTraceLimit !== undefined) {
try {
Error.stackTraceLimit = stackTraceLimit;
} catch (e) {}
stackTraceLimit = undefined;
}
window.removeEventListener('error', onUnhandledError);
window.removeEventListener('unhandledrejection', onUnhandledRejection);
window.console.error = origConsoleError;
}
export function onBuildOk() {
Bus.emit({
type: ACTION_BUILD_OK
});
}
export function onBuildError(message) {
Bus.emit({
type: ACTION_BUILD_ERROR,
message
});
}
export function onRefresh() {
Bus.emit({
type: ACTION_REFRESH
});
}
export function onBeforeRefresh() {
Bus.emit({
type: ACTION_BEFORE_REFRESH
});
}
export function onVersionInfo(versionInfo) {
Bus.emit({
type: ACTION_VERSION_INFO,
versionInfo
});
}
export function onStaticIndicator(isStatic) {
Bus.emit({
type: ACTION_STATIC_INDICATOR,
staticIndicator: isStatic
});
}
export function onDevIndicator(devIndicatorsState) {
Bus.emit({
type: ACTION_DEV_INDICATOR,
devIndicator: devIndicatorsState
});
}
export { getErrorByType } from '../utils/get-error-by-type';
export { getServerError } from '../utils/node-stack-frames';
//# sourceMappingURL=client.js.map

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,27 @@
import React from 'react';
import * as Bus from './bus';
import { useErrorOverlayReducer } from '../shared';
import { Router } from '../../../router';
export const usePagesDevOverlay = ()=>{
const [state, dispatch] = useErrorOverlayReducer('pages');
React.useEffect(()=>{
Bus.on(dispatch);
const { handleStaticIndicator } = require('./hot-reloader-client');
Router.events.on('routeChangeComplete', handleStaticIndicator);
return function() {
Router.events.off('routeChangeComplete', handleStaticIndicator);
Bus.off(dispatch);
};
}, [
dispatch
]);
const onComponentError = React.useCallback((_error, _componentStack)=>{
// TODO: special handling
}, []);
return {
state,
onComponentError
};
};
//# sourceMappingURL=hooks.js.map

View File

@@ -0,0 +1 @@
{"version":3,"sources":["../../../../../src/client/components/react-dev-overlay/pages/hooks.ts"],"sourcesContent":["import React from 'react'\nimport * as Bus from './bus'\nimport { useErrorOverlayReducer } from '../shared'\nimport { Router } from '../../../router'\n\nexport const usePagesDevOverlay = () => {\n const [state, dispatch] = useErrorOverlayReducer('pages')\n\n React.useEffect(() => {\n Bus.on(dispatch)\n\n const { handleStaticIndicator } =\n require('./hot-reloader-client') as typeof import('./hot-reloader-client')\n\n Router.events.on('routeChangeComplete', handleStaticIndicator)\n\n return function () {\n Router.events.off('routeChangeComplete', handleStaticIndicator)\n Bus.off(dispatch)\n }\n }, [dispatch])\n\n const onComponentError = React.useCallback(\n (_error: Error, _componentStack: string | null) => {\n // TODO: special handling\n },\n []\n )\n\n return {\n state,\n onComponentError,\n }\n}\n"],"names":["React","Bus","useErrorOverlayReducer","Router","usePagesDevOverlay","state","dispatch","useEffect","on","handleStaticIndicator","require","events","off","onComponentError","useCallback","_error","_componentStack"],"mappings":"AAAA,OAAOA,WAAW,QAAO;AACzB,YAAYC,SAAS,QAAO;AAC5B,SAASC,sBAAsB,QAAQ,YAAW;AAClD,SAASC,MAAM,QAAQ,kBAAiB;AAExC,OAAO,MAAMC,qBAAqB;IAChC,MAAM,CAACC,OAAOC,SAAS,GAAGJ,uBAAuB;IAEjDF,MAAMO,SAAS,CAAC;QACdN,IAAIO,EAAE,CAACF;QAEP,MAAM,EAAEG,qBAAqB,EAAE,GAC7BC,QAAQ;QAEVP,OAAOQ,MAAM,CAACH,EAAE,CAAC,uBAAuBC;QAExC,OAAO;YACLN,OAAOQ,MAAM,CAACC,GAAG,CAAC,uBAAuBH;YACzCR,IAAIW,GAAG,CAACN;QACV;IACF,GAAG;QAACA;KAAS;IAEb,MAAMO,mBAAmBb,MAAMc,WAAW,CACxC,CAACC,QAAeC;IACd,yBAAyB;IAC3B,GACA,EAAE;IAGJ,OAAO;QACLX;QACAQ;IACF;AACF,EAAC"}

View File

@@ -0,0 +1,433 @@
// TODO: Remove use of `any` type. Fix no-use-before-define violations.
/* eslint-disable @typescript-eslint/no-use-before-define */ /**
* MIT License
*
* Copyright (c) 2013-present, Facebook, Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/ // This file is a modified version of the Create React App HMR dev client that
// can be found here:
// https://github.com/facebook/create-react-app/blob/v3.4.1/packages/react-dev-utils/webpackHotDevClient.js
import { register, onBuildError, onBuildOk, onBeforeRefresh, onRefresh, onVersionInfo, onStaticIndicator, onDevIndicator } from './client';
import stripAnsi from 'next/dist/compiled/strip-ansi';
import { addMessageListener, sendMessage } from './websocket';
import formatWebpackMessages from '../utils/format-webpack-messages';
import { HMR_ACTIONS_SENT_TO_BROWSER } from '../../../../server/dev/hot-reloader-types';
import { extractModulesFromTurbopackMessage } from '../../../../server/dev/extract-modules-from-turbopack-message';
import { REACT_REFRESH_FULL_RELOAD_FROM_ERROR } from '../shared';
import { RuntimeErrorHandler } from '../../errors/runtime-error-handler';
window.__nextDevClientId = Math.round(Math.random() * 100 + Date.now());
let customHmrEventHandler;
let turbopackMessageListeners = [];
let MODE = 'webpack';
export default function connect(mode) {
MODE = mode;
register();
addMessageListener((payload)=>{
if (!('action' in payload)) {
return;
}
try {
processMessage(payload);
} catch (err) {
var _err_stack;
console.warn('[HMR] Invalid message: ' + JSON.stringify(payload) + '\n' + ((_err_stack = err == null ? void 0 : err.stack) != null ? _err_stack : ''));
}
});
return {
subscribeToHmrEvent (handler) {
customHmrEventHandler = handler;
},
onUnrecoverableError () {
RuntimeErrorHandler.hadRuntimeError = true;
},
addTurbopackMessageListener (cb) {
turbopackMessageListeners.push(cb);
},
sendTurbopackMessage (msg) {
sendMessage(msg);
},
handleUpdateError (err) {
performFullReload(err);
}
};
}
// Remember some state related to hot module replacement.
var isFirstCompilation = true;
var mostRecentCompilationHash = null;
var hasCompileErrors = false;
function clearOutdatedErrors() {
// Clean up outdated compile errors, if any.
if (typeof console !== 'undefined' && typeof console.clear === 'function') {
if (hasCompileErrors) {
console.clear();
}
}
}
// Successful compilation.
function handleSuccess() {
clearOutdatedErrors();
if (MODE === 'webpack') {
const isHotUpdate = !isFirstCompilation || window.__NEXT_DATA__.page !== '/_error' && isUpdateAvailable();
isFirstCompilation = false;
hasCompileErrors = false;
// Attempt to apply hot updates or reload.
if (isHotUpdate) {
tryApplyUpdates(onBeforeFastRefresh, onFastRefresh);
}
} else {
reportHmrLatency([
...turbopackUpdatedModules
]);
onBuildOk();
}
}
// Compilation with warnings (e.g. ESLint).
function handleWarnings(warnings) {
clearOutdatedErrors();
const isHotUpdate = !isFirstCompilation;
isFirstCompilation = false;
hasCompileErrors = false;
function printWarnings() {
// Print warnings to the console.
const formatted = formatWebpackMessages({
warnings: warnings,
errors: []
});
if (typeof console !== 'undefined' && typeof console.warn === 'function') {
var _formatted_warnings;
for(let i = 0; i < ((_formatted_warnings = formatted.warnings) == null ? void 0 : _formatted_warnings.length); i++){
if (i === 5) {
console.warn('There were more warnings in other files.\n' + 'You can find a complete log in the terminal.');
break;
}
console.warn(stripAnsi(formatted.warnings[i]));
}
}
}
printWarnings();
// Attempt to apply hot updates or reload.
if (isHotUpdate) {
tryApplyUpdates(onBeforeFastRefresh, onFastRefresh);
}
}
// Compilation with errors (e.g. syntax error or missing modules).
function handleErrors(errors) {
clearOutdatedErrors();
isFirstCompilation = false;
hasCompileErrors = true;
// "Massage" webpack messages.
var formatted = formatWebpackMessages({
errors: errors,
warnings: []
});
// Only show the first error.
onBuildError(formatted.errors[0]);
// Also log them to the console.
if (typeof console !== 'undefined' && typeof console.error === 'function') {
for(var i = 0; i < formatted.errors.length; i++){
console.error(stripAnsi(formatted.errors[i]));
}
}
// Do not attempt to reload now.
// We will reload on next success instead.
if (process.env.__NEXT_TEST_MODE) {
if (self.__NEXT_HMR_CB) {
self.__NEXT_HMR_CB(formatted.errors[0]);
self.__NEXT_HMR_CB = null;
}
}
}
let startLatency = null;
let turbopackLastUpdateLatency = null;
let turbopackUpdatedModules = new Set();
let isrManifest = {};
function onBeforeFastRefresh(updatedModules) {
if (updatedModules.length > 0) {
// Only trigger a pending state if we have updates to apply
// (cf. onFastRefresh)
onBeforeRefresh();
}
}
function onFastRefresh(updatedModules) {
if (updatedModules === void 0) updatedModules = [];
onBuildOk();
if (updatedModules.length === 0) {
return;
}
onRefresh();
reportHmrLatency();
}
function reportHmrLatency(updatedModules) {
if (updatedModules === void 0) updatedModules = [];
if (!startLatency) return;
// turbopack has a debounce for the BUILT event which we don't want to
// incorrectly show in this number, use the last TURBOPACK_MESSAGE time
let endLatency = turbopackLastUpdateLatency != null ? turbopackLastUpdateLatency : Date.now();
const latency = endLatency - startLatency;
console.log("[Fast Refresh] done in " + latency + "ms");
sendMessage(JSON.stringify({
event: 'client-hmr-latency',
id: window.__nextDevClientId,
startTime: startLatency,
endTime: endLatency,
page: window.location.pathname,
updatedModules,
// Whether the page (tab) was hidden at the time the event occurred.
// This can impact the accuracy of the event's timing.
isPageHidden: document.visibilityState === 'hidden'
}));
if (self.__NEXT_HMR_LATENCY_CB) {
self.__NEXT_HMR_LATENCY_CB(latency);
}
}
// There is a newer version of the code available.
function handleAvailableHash(hash) {
// Update last known compilation hash.
mostRecentCompilationHash = hash;
}
export function handleStaticIndicator() {
if (process.env.__NEXT_DEV_INDICATOR) {
var _window_next_router_components__app;
const routeInfo = window.next.router.components[window.next.router.pathname];
const pageComponent = routeInfo == null ? void 0 : routeInfo.Component;
const appComponent = (_window_next_router_components__app = window.next.router.components['/_app']) == null ? void 0 : _window_next_router_components__app.Component;
const isDynamicPage = Boolean(pageComponent == null ? void 0 : pageComponent.getInitialProps) || Boolean(routeInfo.__N_SSP);
const hasAppGetInitialProps = Boolean(appComponent == null ? void 0 : appComponent.getInitialProps) && (appComponent == null ? void 0 : appComponent.getInitialProps) !== (appComponent == null ? void 0 : appComponent.origGetInitialProps);
const isPageStatic = window.location.pathname in isrManifest || !isDynamicPage && !hasAppGetInitialProps;
onStaticIndicator(isPageStatic);
}
}
/** Handles messages from the sevrer for the Pages Router. */ function processMessage(obj) {
if (!('action' in obj)) {
return;
}
// Use turbopack message for analytics, (still need built for webpack)
switch(obj.action){
case HMR_ACTIONS_SENT_TO_BROWSER.ISR_MANIFEST:
{
isrManifest = obj.data;
handleStaticIndicator();
break;
}
case HMR_ACTIONS_SENT_TO_BROWSER.BUILDING:
{
startLatency = Date.now();
turbopackLastUpdateLatency = null;
turbopackUpdatedModules.clear();
console.log('[Fast Refresh] rebuilding');
break;
}
case HMR_ACTIONS_SENT_TO_BROWSER.BUILT:
case HMR_ACTIONS_SENT_TO_BROWSER.SYNC:
{
if (obj.hash) handleAvailableHash(obj.hash);
const { errors, warnings } = obj;
// Is undefined when it's a 'built' event
if ('versionInfo' in obj) onVersionInfo(obj.versionInfo);
if ('devIndicator' in obj) onDevIndicator(obj.devIndicator);
const hasErrors = Boolean(errors && errors.length);
if (hasErrors) {
sendMessage(JSON.stringify({
event: 'client-error',
errorCount: errors.length,
clientId: window.__nextDevClientId
}));
return handleErrors(errors);
}
const hasWarnings = Boolean(warnings && warnings.length);
if (hasWarnings) {
sendMessage(JSON.stringify({
event: 'client-warning',
warningCount: warnings.length,
clientId: window.__nextDevClientId
}));
return handleWarnings(warnings);
}
sendMessage(JSON.stringify({
event: 'client-success',
clientId: window.__nextDevClientId
}));
return handleSuccess();
}
case HMR_ACTIONS_SENT_TO_BROWSER.SERVER_COMPONENT_CHANGES:
{
if (hasCompileErrors || RuntimeErrorHandler.hadRuntimeError) {
window.location.reload();
}
return;
}
case HMR_ACTIONS_SENT_TO_BROWSER.SERVER_ERROR:
{
const { errorJSON } = obj;
if (errorJSON) {
const { message, stack } = JSON.parse(errorJSON);
const error = Object.defineProperty(new Error(message), "__NEXT_ERROR_CODE", {
value: "E394",
enumerable: false,
configurable: true
});
error.stack = stack;
handleErrors([
error
]);
}
return;
}
case HMR_ACTIONS_SENT_TO_BROWSER.TURBOPACK_CONNECTED:
{
for (const listener of turbopackMessageListeners){
listener({
type: HMR_ACTIONS_SENT_TO_BROWSER.TURBOPACK_CONNECTED,
data: obj.data
});
}
break;
}
case HMR_ACTIONS_SENT_TO_BROWSER.TURBOPACK_MESSAGE:
{
const updatedModules = extractModulesFromTurbopackMessage(obj.data);
onBeforeFastRefresh([
...updatedModules
]);
for (const listener of turbopackMessageListeners){
listener({
type: HMR_ACTIONS_SENT_TO_BROWSER.TURBOPACK_MESSAGE,
data: obj.data
});
}
if (RuntimeErrorHandler.hadRuntimeError) {
console.warn(REACT_REFRESH_FULL_RELOAD_FROM_ERROR);
performFullReload(null);
}
onRefresh();
for (const module1 of updatedModules){
turbopackUpdatedModules.add(module1);
}
turbopackLastUpdateLatency = Date.now();
break;
}
default:
{
if (customHmrEventHandler) {
customHmrEventHandler(obj);
break;
}
break;
}
}
}
// Is there a newer version of this code available?
function isUpdateAvailable() {
/* globals __webpack_hash__ */ // __webpack_hash__ is the hash of the current compilation.
// It's a global variable injected by Webpack.
return mostRecentCompilationHash !== __webpack_hash__;
}
// Webpack disallows updates in other states.
function canApplyUpdates() {
// @ts-expect-error TODO: module.hot exists but type needs to be added. Can't use `as any` here as webpack parses for `module.hot` calls.
return module.hot.status() === 'idle';
}
function afterApplyUpdates(fn) {
if (canApplyUpdates()) {
fn();
} else {
function handler(status) {
if (status === 'idle') {
// @ts-expect-error TODO: module.hot exists but type needs to be added. Can't use `as any` here as webpack parses for `module.hot` calls.
module.hot.removeStatusHandler(handler);
fn();
}
}
// @ts-expect-error TODO: module.hot exists but type needs to be added. Can't use `as any` here as webpack parses for `module.hot` calls.
module.hot.addStatusHandler(handler);
}
}
// Attempt to update code on the fly, fall back to a hard reload.
function tryApplyUpdates(onBeforeHotUpdate, onHotUpdateSuccess) {
// @ts-expect-error TODO: module.hot exists but type needs to be added. Can't use `as any` here as webpack parses for `module.hot` calls.
if (!module.hot) {
// HotModuleReplacementPlugin is not in Webpack configuration.
console.error('HotModuleReplacementPlugin is not in Webpack configuration.');
// window.location.reload();
return;
}
if (!isUpdateAvailable() || !canApplyUpdates()) {
onBuildOk();
return;
}
function handleApplyUpdates(err, updatedModules) {
if (err || RuntimeErrorHandler.hadRuntimeError || !updatedModules) {
if (err) {
console.warn('[Fast Refresh] performing full reload\n\n' + "Fast Refresh will perform a full reload when you edit a file that's imported by modules outside of the React rendering tree.\n" + 'You might have a file which exports a React component but also exports a value that is imported by a non-React component file.\n' + 'Consider migrating the non-React component export to a separate file and importing it into both files.\n\n' + 'It is also possible the parent component of the component you edited is a class component, which disables Fast Refresh.\n' + 'Fast Refresh requires at least one parent function component in your React tree.');
} else if (RuntimeErrorHandler.hadRuntimeError) {
console.warn('[Fast Refresh] performing full reload because your application had an unrecoverable error');
}
performFullReload(err);
return;
}
if (typeof onHotUpdateSuccess === 'function') {
// Maybe we want to do something.
onHotUpdateSuccess(updatedModules);
}
if (isUpdateAvailable()) {
// While we were updating, there was a new update! Do it again.
// However, this time, don't trigger a pending refresh state.
tryApplyUpdates(updatedModules.length > 0 ? undefined : onBeforeHotUpdate, updatedModules.length > 0 ? onBuildOk : onHotUpdateSuccess);
} else {
onBuildOk();
if (process.env.__NEXT_TEST_MODE) {
afterApplyUpdates(()=>{
if (self.__NEXT_HMR_CB) {
self.__NEXT_HMR_CB();
self.__NEXT_HMR_CB = null;
}
});
}
}
}
// https://webpack.js.org/api/hot-module-replacement/#check
// @ts-expect-error TODO: module.hot exists but type needs to be added. Can't use `as any` here as webpack parses for `module.hot` calls.
module.hot.check(/* autoApply */ false).then((updatedModules)=>{
if (!updatedModules) {
return null;
}
if (typeof onBeforeHotUpdate === 'function') {
onBeforeHotUpdate(updatedModules);
}
// @ts-expect-error TODO: module.hot exists but type needs to be added. Can't use `as any` here as webpack parses for `module.hot` calls.
return module.hot.apply();
}).then((updatedModules)=>{
handleApplyUpdates(null, updatedModules);
}, (err)=>{
handleApplyUpdates(err, null);
});
}
export function performFullReload(err) {
const stackTrace = err && (err.stack && err.stack.split('\n').slice(0, 5).join('\n') || err.message || err + '');
sendMessage(JSON.stringify({
event: 'client-full-reload',
stackTrace,
hadRuntimeError: !!RuntimeErrorHandler.hadRuntimeError,
dependencyChain: err ? err.dependencyChain : undefined
}));
window.location.reload();
}
//# sourceMappingURL=hot-reloader-client.js.map

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,28 @@
import React from 'react';
export class PagesDevOverlayErrorBoundary extends React.PureComponent {
static getDerivedStateFromError(error) {
return {
error
};
}
componentDidCatch(error, // Loosely typed because it depends on the React version and was
// accidentally excluded in some versions.
errorInfo) {
this.props.onError(error, (errorInfo == null ? void 0 : errorInfo.componentStack) || null);
this.setState({
error
});
}
// Explicit type is needed to avoid the generated `.d.ts` having a wide return type that could be specific to the `@types/react` version.
render() {
// The component has to be unmounted or else it would continue to error
return this.state.error ? null : this.props.children;
}
constructor(...args){
super(...args), this.state = {
error: null
};
}
}
//# sourceMappingURL=pages-dev-overlay-error-boundary.js.map

View File

@@ -0,0 +1 @@
{"version":3,"sources":["../../../../../src/client/components/react-dev-overlay/pages/pages-dev-overlay-error-boundary.tsx"],"sourcesContent":["import React from 'react'\n\ntype PagesDevOverlayErrorBoundaryProps = {\n children?: React.ReactNode\n onError: (error: Error, componentStack: string | null) => void\n}\ntype PagesDevOverlayErrorBoundaryState = { error: Error | null }\n\nexport class PagesDevOverlayErrorBoundary extends React.PureComponent<\n PagesDevOverlayErrorBoundaryProps,\n PagesDevOverlayErrorBoundaryState\n> {\n state = { error: null }\n\n static getDerivedStateFromError(error: Error) {\n return { error }\n }\n\n componentDidCatch(\n error: Error,\n // Loosely typed because it depends on the React version and was\n // accidentally excluded in some versions.\n errorInfo?: { componentStack?: string | null }\n ) {\n this.props.onError(error, errorInfo?.componentStack || null)\n this.setState({ error })\n }\n\n // Explicit type is needed to avoid the generated `.d.ts` having a wide return type that could be specific to the `@types/react` version.\n render(): React.ReactNode {\n // The component has to be unmounted or else it would continue to error\n return this.state.error ? null : this.props.children\n }\n}\n"],"names":["React","PagesDevOverlayErrorBoundary","PureComponent","getDerivedStateFromError","error","componentDidCatch","errorInfo","props","onError","componentStack","setState","render","state","children"],"mappings":"AAAA,OAAOA,WAAW,QAAO;AAQzB,OAAO,MAAMC,qCAAqCD,MAAME,aAAa;IAMnE,OAAOC,yBAAyBC,KAAY,EAAE;QAC5C,OAAO;YAAEA;QAAM;IACjB;IAEAC,kBACED,KAAY,EACZ,gEAAgE;IAChE,0CAA0C;IAC1CE,SAA8C,EAC9C;QACA,IAAI,CAACC,KAAK,CAACC,OAAO,CAACJ,OAAOE,CAAAA,6BAAAA,UAAWG,cAAc,KAAI;QACvD,IAAI,CAACC,QAAQ,CAAC;YAAEN;QAAM;IACxB;IAEA,yIAAyI;IACzIO,SAA0B;QACxB,uEAAuE;QACvE,OAAO,IAAI,CAACC,KAAK,CAACR,KAAK,GAAG,OAAO,IAAI,CAACG,KAAK,CAACM,QAAQ;IACtD;;QAxBK,qBAILD,QAAQ;YAAER,OAAO;QAAK;;AAqBxB"}

View File

@@ -0,0 +1,27 @@
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
import { useState } from 'react';
import { PagesDevOverlayErrorBoundary } from './pages-dev-overlay-error-boundary';
import { usePagesDevOverlay } from './hooks';
import { FontStyles } from '../font/font-styles';
import { DevOverlay } from '../ui/dev-overlay';
export function PagesDevOverlay(param) {
let { children } = param;
const { state, onComponentError } = usePagesDevOverlay();
const [isErrorOverlayOpen, setIsErrorOverlayOpen] = useState(true);
return /*#__PURE__*/ _jsxs(_Fragment, {
children: [
/*#__PURE__*/ _jsx(PagesDevOverlayErrorBoundary, {
onError: onComponentError,
children: children != null ? children : null
}),
/*#__PURE__*/ _jsx(FontStyles, {}),
/*#__PURE__*/ _jsx(DevOverlay, {
state: state,
isErrorOverlayOpen: isErrorOverlayOpen,
setIsErrorOverlayOpen: setIsErrorOverlayOpen
})
]
});
}
//# sourceMappingURL=pages-dev-overlay.js.map

View File

@@ -0,0 +1 @@
{"version":3,"sources":["../../../../../src/client/components/react-dev-overlay/pages/pages-dev-overlay.tsx"],"sourcesContent":["import { useState } from 'react'\nimport { PagesDevOverlayErrorBoundary } from './pages-dev-overlay-error-boundary'\nimport { usePagesDevOverlay } from './hooks'\nimport { FontStyles } from '../font/font-styles'\nimport { DevOverlay } from '../ui/dev-overlay'\n\nexport type ErrorType = 'runtime' | 'build'\n\nexport type PagesDevOverlayType = typeof PagesDevOverlay\n\ninterface PagesDevOverlayProps {\n children?: React.ReactNode\n}\n\nexport function PagesDevOverlay({ children }: PagesDevOverlayProps) {\n const { state, onComponentError } = usePagesDevOverlay()\n\n const [isErrorOverlayOpen, setIsErrorOverlayOpen] = useState(true)\n\n return (\n <>\n <PagesDevOverlayErrorBoundary onError={onComponentError}>\n {children ?? null}\n </PagesDevOverlayErrorBoundary>\n\n {/* Fonts can only be loaded outside the Shadow DOM. */}\n <FontStyles />\n <DevOverlay\n state={state}\n isErrorOverlayOpen={isErrorOverlayOpen}\n setIsErrorOverlayOpen={setIsErrorOverlayOpen}\n />\n </>\n )\n}\n"],"names":["useState","PagesDevOverlayErrorBoundary","usePagesDevOverlay","FontStyles","DevOverlay","PagesDevOverlay","children","state","onComponentError","isErrorOverlayOpen","setIsErrorOverlayOpen","onError"],"mappings":";AAAA,SAASA,QAAQ,QAAQ,QAAO;AAChC,SAASC,4BAA4B,QAAQ,qCAAoC;AACjF,SAASC,kBAAkB,QAAQ,UAAS;AAC5C,SAASC,UAAU,QAAQ,sBAAqB;AAChD,SAASC,UAAU,QAAQ,oBAAmB;AAU9C,OAAO,SAASC,gBAAgB,KAAkC;IAAlC,IAAA,EAAEC,QAAQ,EAAwB,GAAlC;IAC9B,MAAM,EAAEC,KAAK,EAAEC,gBAAgB,EAAE,GAAGN;IAEpC,MAAM,CAACO,oBAAoBC,sBAAsB,GAAGV,SAAS;IAE7D,qBACE;;0BACE,KAACC;gBAA6BU,SAASH;0BACpCF,mBAAAA,WAAY;;0BAIf,KAACH;0BACD,KAACC;gBACCG,OAAOA;gBACPE,oBAAoBA;gBACpBC,uBAAuBA;;;;AAI/B"}

View File

@@ -0,0 +1,72 @@
import { HMR_ACTIONS_SENT_TO_BROWSER } from '../../../../server/dev/hot-reloader-types';
import { getSocketUrl } from '../utils/get-socket-url';
let source;
const eventCallbacks = [];
export function addMessageListener(callback) {
eventCallbacks.push(callback);
}
export function sendMessage(data) {
if (!source || source.readyState !== source.OPEN) return;
return source.send(data);
}
let reconnections = 0;
let reloading = false;
let serverSessionId = null;
export function connectHMR(options) {
function init() {
if (source) source.close();
function handleOnline() {
reconnections = 0;
window.console.log('[HMR] connected');
}
function handleMessage(event) {
// While the page is reloading, don't respond to any more messages.
// On reconnect, the server may send an empty list of changes if it was restarted.
if (reloading) {
return;
}
// Coerce into HMR_ACTION_TYPES as that is the format.
const msg = JSON.parse(event.data);
if ('action' in msg && msg.action === HMR_ACTIONS_SENT_TO_BROWSER.TURBOPACK_CONNECTED) {
if (serverSessionId !== null && serverSessionId !== msg.data.sessionId) {
// Either the server's session id has changed and it's a new server, or
// it's been too long since we disconnected and we should reload the page.
// There could be 1) unhandled server errors and/or 2) stale content.
// Perform a hard reload of the page.
window.location.reload();
reloading = true;
return;
}
serverSessionId = msg.data.sessionId;
}
for (const eventCallback of eventCallbacks){
eventCallback(msg);
}
}
let timer;
function handleDisconnect() {
source.onerror = null;
source.onclose = null;
source.close();
reconnections++;
// After 25 reconnects we'll want to reload the page as it indicates the dev server is no longer running.
if (reconnections > 25) {
reloading = true;
window.location.reload();
return;
}
clearTimeout(timer);
// Try again after 5 seconds
timer = setTimeout(init, reconnections > 5 ? 5000 : 1000);
}
const url = getSocketUrl(options.assetPrefix);
source = new window.WebSocket("" + url + options.path);
source.onopen = handleOnline;
source.onerror = handleDisconnect;
source.onclose = handleDisconnect;
source.onmessage = handleMessage;
}
init();
}
//# sourceMappingURL=websocket.js.map

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,27 @@
import { eventErrorFeedback } from '../../../../telemetry/events/error-feedback';
import { middlewareResponse } from './middleware-response';
// Handles HTTP requests to /__nextjs_error_feedback endpoint for collecting user feedback on error messages
export function getNextErrorFeedbackMiddleware(telemetry) {
return async function(req, res, next) {
const { pathname, searchParams } = new URL("http://n" + req.url);
if (pathname !== '/__nextjs_error_feedback') {
return next();
}
try {
const errorCode = searchParams.get('errorCode');
const wasHelpful = searchParams.get('wasHelpful');
if (!errorCode || !wasHelpful) {
return middlewareResponse.badRequest(res);
}
await telemetry.record(eventErrorFeedback({
errorCode,
wasHelpful: wasHelpful === 'true'
}));
return middlewareResponse.noContent(res);
} catch (error) {
return middlewareResponse.internalServerError(res);
}
};
}
//# sourceMappingURL=get-next-error-feedback-middleware.js.map

View File

@@ -0,0 +1 @@
{"version":3,"sources":["../../../../../src/client/components/react-dev-overlay/server/get-next-error-feedback-middleware.ts"],"sourcesContent":["import { eventErrorFeedback } from '../../../../telemetry/events/error-feedback'\nimport { middlewareResponse } from './middleware-response'\nimport type { ServerResponse, IncomingMessage } from 'http'\nimport type { Telemetry } from '../../../../telemetry/storage'\n\n// Handles HTTP requests to /__nextjs_error_feedback endpoint for collecting user feedback on error messages\nexport function getNextErrorFeedbackMiddleware(telemetry: Telemetry) {\n return async function (\n req: IncomingMessage,\n res: ServerResponse,\n next: () => void\n ): Promise<void> {\n const { pathname, searchParams } = new URL(`http://n${req.url}`)\n\n if (pathname !== '/__nextjs_error_feedback') {\n return next()\n }\n\n try {\n const errorCode = searchParams.get('errorCode')\n const wasHelpful = searchParams.get('wasHelpful')\n\n if (!errorCode || !wasHelpful) {\n return middlewareResponse.badRequest(res)\n }\n\n await telemetry.record(\n eventErrorFeedback({\n errorCode,\n wasHelpful: wasHelpful === 'true',\n })\n )\n\n return middlewareResponse.noContent(res)\n } catch (error) {\n return middlewareResponse.internalServerError(res)\n }\n }\n}\n"],"names":["eventErrorFeedback","middlewareResponse","getNextErrorFeedbackMiddleware","telemetry","req","res","next","pathname","searchParams","URL","url","errorCode","get","wasHelpful","badRequest","record","noContent","error","internalServerError"],"mappings":"AAAA,SAASA,kBAAkB,QAAQ,8CAA6C;AAChF,SAASC,kBAAkB,QAAQ,wBAAuB;AAI1D,4GAA4G;AAC5G,OAAO,SAASC,+BAA+BC,SAAoB;IACjE,OAAO,eACLC,GAAoB,EACpBC,GAAmB,EACnBC,IAAgB;QAEhB,MAAM,EAAEC,QAAQ,EAAEC,YAAY,EAAE,GAAG,IAAIC,IAAI,AAAC,aAAUL,IAAIM,GAAG;QAE7D,IAAIH,aAAa,4BAA4B;YAC3C,OAAOD;QACT;QAEA,IAAI;YACF,MAAMK,YAAYH,aAAaI,GAAG,CAAC;YACnC,MAAMC,aAAaL,aAAaI,GAAG,CAAC;YAEpC,IAAI,CAACD,aAAa,CAACE,YAAY;gBAC7B,OAAOZ,mBAAmBa,UAAU,CAACT;YACvC;YAEA,MAAMF,UAAUY,MAAM,CACpBf,mBAAmB;gBACjBW;gBACAE,YAAYA,eAAe;YAC7B;YAGF,OAAOZ,mBAAmBe,SAAS,CAACX;QACtC,EAAE,OAAOY,OAAO;YACd,OAAOhB,mBAAmBiB,mBAAmB,CAACb;QAChD;IACF;AACF"}

View File

@@ -0,0 +1,34 @@
import { inspect } from 'util';
export const middlewareResponse = {
noContent (res) {
res.statusCode = 204;
res.end('No Content');
},
badRequest (res) {
res.statusCode = 400;
res.end('Bad Request');
},
notFound (res) {
res.statusCode = 404;
res.end('Not Found');
},
methodNotAllowed (res) {
res.statusCode = 405;
res.end('Method Not Allowed');
},
internalServerError (res, error) {
res.statusCode = 500;
res.setHeader('Content-Type', 'text/plain');
res.end(error !== undefined ? inspect(error, {
colors: false
}) : 'Internal Server Error');
},
json (res, data) {
res.setHeader('Content-Type', 'application/json').end(Buffer.from(JSON.stringify(data)));
},
jsonString (res, data) {
res.setHeader('Content-Type', 'application/json').end(Buffer.from(data));
}
};
//# sourceMappingURL=middleware-response.js.map

View File

@@ -0,0 +1 @@
{"version":3,"sources":["../../../../../src/client/components/react-dev-overlay/server/middleware-response.ts"],"sourcesContent":["import type { ServerResponse } from 'http'\nimport { inspect } from 'util'\n\nexport const middlewareResponse = {\n noContent(res: ServerResponse) {\n res.statusCode = 204\n res.end('No Content')\n },\n badRequest(res: ServerResponse) {\n res.statusCode = 400\n res.end('Bad Request')\n },\n notFound(res: ServerResponse) {\n res.statusCode = 404\n res.end('Not Found')\n },\n methodNotAllowed(res: ServerResponse) {\n res.statusCode = 405\n res.end('Method Not Allowed')\n },\n internalServerError(res: ServerResponse, error?: unknown) {\n res.statusCode = 500\n res.setHeader('Content-Type', 'text/plain')\n res.end(\n error !== undefined\n ? inspect(error, { colors: false })\n : 'Internal Server Error'\n )\n },\n json(res: ServerResponse, data: any) {\n res\n .setHeader('Content-Type', 'application/json')\n .end(Buffer.from(JSON.stringify(data)))\n },\n jsonString(res: ServerResponse, data: string) {\n res.setHeader('Content-Type', 'application/json').end(Buffer.from(data))\n },\n}\n"],"names":["inspect","middlewareResponse","noContent","res","statusCode","end","badRequest","notFound","methodNotAllowed","internalServerError","error","setHeader","undefined","colors","json","data","Buffer","from","JSON","stringify","jsonString"],"mappings":"AACA,SAASA,OAAO,QAAQ,OAAM;AAE9B,OAAO,MAAMC,qBAAqB;IAChCC,WAAUC,GAAmB;QAC3BA,IAAIC,UAAU,GAAG;QACjBD,IAAIE,GAAG,CAAC;IACV;IACAC,YAAWH,GAAmB;QAC5BA,IAAIC,UAAU,GAAG;QACjBD,IAAIE,GAAG,CAAC;IACV;IACAE,UAASJ,GAAmB;QAC1BA,IAAIC,UAAU,GAAG;QACjBD,IAAIE,GAAG,CAAC;IACV;IACAG,kBAAiBL,GAAmB;QAClCA,IAAIC,UAAU,GAAG;QACjBD,IAAIE,GAAG,CAAC;IACV;IACAI,qBAAoBN,GAAmB,EAAEO,KAAe;QACtDP,IAAIC,UAAU,GAAG;QACjBD,IAAIQ,SAAS,CAAC,gBAAgB;QAC9BR,IAAIE,GAAG,CACLK,UAAUE,YACNZ,QAAQU,OAAO;YAAEG,QAAQ;QAAM,KAC/B;IAER;IACAC,MAAKX,GAAmB,EAAEY,IAAS;QACjCZ,IACGQ,SAAS,CAAC,gBAAgB,oBAC1BN,GAAG,CAACW,OAAOC,IAAI,CAACC,KAAKC,SAAS,CAACJ;IACpC;IACAK,YAAWjB,GAAmB,EAAEY,IAAY;QAC1CZ,IAAIQ,SAAS,CAAC,gBAAgB,oBAAoBN,GAAG,CAACW,OAAOC,IAAI,CAACF;IACpE;AACF,EAAC"}

View File

@@ -0,0 +1,361 @@
import { getOriginalCodeFrame } from './shared';
import { middlewareResponse } from './middleware-response';
import fs, { constants as FS } from 'fs/promises';
import path from 'path';
import url from 'url';
import { launchEditor } from '../utils/launch-editor';
import { SourceMapConsumer } from 'next/dist/compiled/source-map08';
import { getSourceMapFromFile } from '../utils/get-source-map-from-file';
import { findSourceMap } from 'node:module';
import { pathToFileURL } from 'node:url';
import { inspect } from 'node:util';
function shouldIgnorePath(modulePath) {
return modulePath.includes('node_modules') || // Only relevant for when Next.js is symlinked e.g. in the Next.js monorepo
modulePath.includes('next/dist') || modulePath.startsWith('node:');
}
const currentSourcesByFile = new Map();
async function batchedTraceSource(project, frame) {
const file = frame.file ? decodeURIComponent(frame.file) : undefined;
if (!file) return;
// For node internals they cannot traced the actual source code with project.traceSource,
// we need an early return to indicate it's ignored to avoid the unknown scheme error from `project.traceSource`.
if (file.startsWith('node:')) {
var _frame_line, _frame_column, _frame_methodName;
return {
frame: {
file,
lineNumber: (_frame_line = frame.line) != null ? _frame_line : 0,
column: (_frame_column = frame.column) != null ? _frame_column : 0,
methodName: (_frame_methodName = frame.methodName) != null ? _frame_methodName : '<unknown>',
ignored: true,
arguments: []
},
source: null
};
}
const currentDirectoryFileUrl = pathToFileURL(process.cwd()).href;
const sourceFrame = await project.traceSource(frame, currentDirectoryFileUrl);
if (!sourceFrame) {
var _frame_line1, _frame_column1, _frame_methodName1;
return {
frame: {
file,
lineNumber: (_frame_line1 = frame.line) != null ? _frame_line1 : 0,
column: (_frame_column1 = frame.column) != null ? _frame_column1 : 0,
methodName: (_frame_methodName1 = frame.methodName) != null ? _frame_methodName1 : '<unknown>',
ignored: shouldIgnorePath(file),
arguments: []
},
source: null
};
}
let source = null;
const originalFile = sourceFrame.originalFile;
// Don't look up source for node_modules or internals. These can often be large bundled files.
const ignored = shouldIgnorePath(originalFile != null ? originalFile : sourceFrame.file) || // isInternal means resource starts with turbopack:///[turbopack]
!!sourceFrame.isInternal;
if (originalFile && !ignored) {
let sourcePromise = currentSourcesByFile.get(originalFile);
if (!sourcePromise) {
sourcePromise = project.getSourceForAsset(originalFile);
currentSourcesByFile.set(originalFile, sourcePromise);
setTimeout(()=>{
// Cache file reads for 100ms, as frames will often reference the same
// files and can be large.
currentSourcesByFile.delete(originalFile);
}, 100);
}
source = await sourcePromise;
}
var _sourceFrame_line, _sourceFrame_column, // We ignore the sourcemapped name since it won't be the correct name.
// The callsite will point to the column of the variable name instead of the
// name of the enclosing function.
// TODO(NDX-531): Spy on prepareStackTrace to get the enclosing line number for method name mapping.
_frame_methodName2;
// TODO: get ignoredList from turbopack source map
const ignorableFrame = {
file: sourceFrame.file,
lineNumber: (_sourceFrame_line = sourceFrame.line) != null ? _sourceFrame_line : 0,
column: (_sourceFrame_column = sourceFrame.column) != null ? _sourceFrame_column : 0,
methodName: (_frame_methodName2 = frame.methodName) != null ? _frame_methodName2 : '<unknown>',
ignored,
arguments: []
};
return {
frame: ignorableFrame,
source
};
}
function parseFile(fileParam) {
if (!fileParam) {
return undefined;
}
// rsc://React/Server/file://<filename>?42 => file://<filename>
return fileParam.replace(/^rsc:\/\/React\/[^/]+\//, '').replace(/\?\d+$/, '');
}
function createStackFrames(body) {
const { frames, isServer } = body;
return frames.map((frame)=>{
const file = parseFile(frame.file);
if (!file) {
return undefined;
}
var _frame_methodName, _frame_lineNumber, _frame_column;
return {
file,
methodName: (_frame_methodName = frame.methodName) != null ? _frame_methodName : '<unknown>',
line: (_frame_lineNumber = frame.lineNumber) != null ? _frame_lineNumber : 0,
column: (_frame_column = frame.column) != null ? _frame_column : 0,
isServer
};
}).filter((f)=>f !== undefined);
}
function createStackFrame(searchParams) {
const file = parseFile(searchParams.get('file'));
if (!file) {
return undefined;
}
var _searchParams_get, _searchParams_get1, _searchParams_get2;
return {
file,
methodName: (_searchParams_get = searchParams.get('methodName')) != null ? _searchParams_get : '<unknown>',
line: parseInt((_searchParams_get1 = searchParams.get('lineNumber')) != null ? _searchParams_get1 : '0', 10) || 0,
column: parseInt((_searchParams_get2 = searchParams.get('column')) != null ? _searchParams_get2 : '0', 10) || 0,
isServer: searchParams.get('isServer') === 'true'
};
}
/**
* Finds the sourcemap payload applicable to a given frame.
* Equal to the input unless an Index Source Map is used.
*/ function findApplicableSourceMapPayload(frame, payload) {
if ('sections' in payload) {
var _frame_line;
const frameLine = (_frame_line = frame.line) != null ? _frame_line : 0;
var _frame_column;
const frameColumn = (_frame_column = frame.column) != null ? _frame_column : 0;
// Sections must not overlap and must be sorted: https://tc39.es/source-map/#section-object
// Therefore the last section that has an offset less than or equal to the frame is the applicable one.
// TODO(veil): Binary search
let section = payload.sections[0];
for(let i = 0; i < payload.sections.length && payload.sections[i].offset.line <= frameLine && payload.sections[i].offset.column <= frameColumn; i++){
section = payload.sections[i];
}
return section === undefined ? undefined : section.map;
} else {
return payload;
}
}
/**
* @returns 1-based lines and 0-based columns
*/ async function nativeTraceSource(frame) {
const sourceURL = decodeURIComponent(frame.file);
let sourceMapPayload;
try {
var _findSourceMap;
sourceMapPayload = (_findSourceMap = findSourceMap(sourceURL)) == null ? void 0 : _findSourceMap.payload;
} catch (cause) {
throw Object.defineProperty(new Error("" + sourceURL + ": Invalid source map. Only conformant source maps can be used to find the original code.", {
cause
}), "__NEXT_ERROR_CODE", {
value: "E635",
enumerable: false,
configurable: true
});
}
if (sourceMapPayload !== undefined) {
let consumer;
try {
consumer = await new SourceMapConsumer(sourceMapPayload);
} catch (cause) {
throw Object.defineProperty(new Error("" + sourceURL + ": Invalid source map. Only conformant source maps can be used to find the original code.", {
cause
}), "__NEXT_ERROR_CODE", {
value: "E635",
enumerable: false,
configurable: true
});
}
let traced;
try {
var _frame_line, _frame_column;
const originalPosition = consumer.originalPositionFor({
line: (_frame_line = frame.line) != null ? _frame_line : 1,
// 0-based columns out requires 0-based columns in.
column: ((_frame_column = frame.column) != null ? _frame_column : 1) - 1
});
if (originalPosition.source === null) {
traced = null;
} else {
var _consumer_sourceContentFor;
const sourceContent = (_consumer_sourceContentFor = consumer.sourceContentFor(originalPosition.source, /* returnNullOnMissing */ true)) != null ? _consumer_sourceContentFor : null;
traced = {
originalPosition,
sourceContent
};
}
} finally{
consumer.destroy();
}
if (traced !== null) {
var // We ignore the sourcemapped name since it won't be the correct name.
// The callsite will point to the column of the variable name instead of the
// name of the enclosing function.
// TODO(NDX-531): Spy on prepareStackTrace to get the enclosing line number for method name mapping.
_frame_methodName_replace, _frame_methodName;
const { originalPosition, sourceContent } = traced;
const applicableSourceMap = findApplicableSourceMapPayload(frame, sourceMapPayload);
// TODO(veil): Upstream a method to sourcemap consumer that immediately says if a frame is ignored or not.
let ignored = false;
if (applicableSourceMap === undefined) {
console.error('No applicable source map found in sections for frame', frame);
} else {
var _applicableSourceMap_ignoreList;
// TODO: O(n^2). Consider moving `ignoreList` into a Set
const sourceIndex = applicableSourceMap.sources.indexOf(originalPosition.source);
var _applicableSourceMap_ignoreList_includes;
ignored = (_applicableSourceMap_ignoreList_includes = (_applicableSourceMap_ignoreList = applicableSourceMap.ignoreList) == null ? void 0 : _applicableSourceMap_ignoreList.includes(sourceIndex)) != null ? _applicableSourceMap_ignoreList_includes : // When sourcemap is not available, fallback to checking `frame.file`.
// e.g. In pages router, nextjs server code is not bundled into the page.
shouldIgnorePath(frame.file);
}
var _originalPosition_column, _originalPosition_line;
const originalStackFrame = {
methodName: ((_frame_methodName = frame.methodName) == null ? void 0 : (_frame_methodName_replace = _frame_methodName.replace('__WEBPACK_DEFAULT_EXPORT__', 'default')) == null ? void 0 : _frame_methodName_replace.replace('__webpack_exports__.', '')) || '<unknown>',
column: ((_originalPosition_column = originalPosition.column) != null ? _originalPosition_column : 0) + 1,
file: originalPosition.source,
lineNumber: (_originalPosition_line = originalPosition.line) != null ? _originalPosition_line : 0,
// TODO: c&p from async createOriginalStackFrame but why not frame.arguments?
arguments: [],
ignored
};
return {
frame: originalStackFrame,
source: sourceContent
};
}
}
return undefined;
}
async function createOriginalStackFrame(project, projectPath, frame) {
var _ref;
const traced = (_ref = await nativeTraceSource(frame)) != null ? _ref : // TODO(veil): When would the bundler know more than native?
// If it's faster, try the bundler first and fall back to native later.
await batchedTraceSource(project, frame);
if (!traced) {
return null;
}
let normalizedStackFrameLocation = traced.frame.file;
if (normalizedStackFrameLocation !== null && normalizedStackFrameLocation.startsWith('file://')) {
normalizedStackFrameLocation = path.relative(projectPath, url.fileURLToPath(normalizedStackFrameLocation));
}
return {
originalStackFrame: {
arguments: traced.frame.arguments,
column: traced.frame.column,
file: normalizedStackFrameLocation,
ignored: traced.frame.ignored,
lineNumber: traced.frame.lineNumber,
methodName: traced.frame.methodName
},
originalCodeFrame: getOriginalCodeFrame(traced.frame, traced.source)
};
}
export function getOverlayMiddleware(project, projectPath) {
return async function(req, res, next) {
const { pathname, searchParams } = new URL(req.url, 'http://n');
if (pathname === '/__nextjs_original-stack-frames') {
if (req.method !== 'POST') {
return middlewareResponse.badRequest(res);
}
const body = await new Promise((resolve, reject)=>{
let data = '';
req.on('data', (chunk)=>{
data += chunk;
});
req.on('end', ()=>resolve(data));
req.on('error', reject);
});
const request = JSON.parse(body);
const stackFrames = createStackFrames(request);
const result = await Promise.all(stackFrames.map(async (frame)=>{
try {
const stackFrame = await createOriginalStackFrame(project, projectPath, frame);
if (stackFrame === null) {
return {
status: 'rejected',
reason: 'Failed to create original stack frame'
};
}
return {
status: 'fulfilled',
value: stackFrame
};
} catch (error) {
return {
status: 'rejected',
reason: inspect(error, {
colors: false
})
};
}
}));
return middlewareResponse.json(res, result);
} else if (pathname === '/__nextjs_launch-editor') {
const frame = createStackFrame(searchParams);
if (!frame) return middlewareResponse.badRequest(res);
const fileExists = await fs.access(frame.file, FS.F_OK).then(()=>true, ()=>false);
if (!fileExists) return middlewareResponse.notFound(res);
try {
var _frame_line, _frame_column;
launchEditor(frame.file, (_frame_line = frame.line) != null ? _frame_line : 1, (_frame_column = frame.column) != null ? _frame_column : 1);
} catch (err) {
console.log('Failed to launch editor:', err);
return middlewareResponse.internalServerError(res);
}
return middlewareResponse.noContent(res);
}
return next();
};
}
export function getSourceMapMiddleware(project) {
return async function(req, res, next) {
const { pathname, searchParams } = new URL(req.url, 'http://n');
if (pathname !== '/__nextjs_source-map') {
return next();
}
let filename = searchParams.get('filename');
if (!filename) {
return middlewareResponse.badRequest(res);
}
// TODO(veil): Always try the native version first.
// Externals could also be files that aren't bundled via Webpack.
if (filename.startsWith('webpack://') || filename.startsWith('webpack-internal:///')) {
const sourceMap = findSourceMap(filename);
if (sourceMap) {
return middlewareResponse.json(res, sourceMap.payload);
}
return middlewareResponse.noContent(res);
}
try {
// Turbopack chunk filenames might be URL-encoded.
filename = decodeURI(filename);
if (path.isAbsolute(filename)) {
filename = url.pathToFileURL(filename).href;
}
const sourceMapString = await project.getSourceMap(filename);
if (sourceMapString) {
return middlewareResponse.jsonString(res, sourceMapString);
}
if (filename.startsWith('file:')) {
const sourceMap = await getSourceMapFromFile(filename);
if (sourceMap) {
return middlewareResponse.json(res, sourceMap);
}
}
} catch (error) {
console.error('Failed to get source map:', error);
}
middlewareResponse.noContent(res);
};
}
//# sourceMappingURL=middleware-turbopack.js.map

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,440 @@
import { constants as FS, promises as fs } from 'fs';
import { findSourceMap } from 'module';
import path from 'path';
import { fileURLToPath, pathToFileURL } from 'url';
import { SourceMapConsumer } from 'next/dist/compiled/source-map08';
import { getSourceMapFromFile } from '../utils/get-source-map-from-file';
import { launchEditor } from '../utils/launch-editor';
import { getOriginalCodeFrame } from './shared';
import { middlewareResponse } from './middleware-response';
export { getServerError } from '../utils/node-stack-frames';
export { parseStack } from '../utils/parse-stack';
export { getSourceMapFromFile };
import { formatFrameSourceFile } from '../utils/webpack-module-path';
import { inspect } from 'util';
function shouldIgnoreSource(sourceURL) {
return sourceURL.includes('node_modules') || // Only relevant for when Next.js is symlinked e.g. in the Next.js monorepo
sourceURL.includes('next/dist') || sourceURL.startsWith('node:');
}
function getModuleById(id, compilation) {
const { chunkGraph, modules } = compilation;
return [
...modules
].find((module)=>chunkGraph.getModuleId(module) === id);
}
function findModuleNotFoundFromError(errorMessage) {
var _errorMessage_match;
return errorMessage == null ? void 0 : (_errorMessage_match = errorMessage.match(/'([^']+)' module/)) == null ? void 0 : _errorMessage_match[1];
}
function getSourcePath(source) {
if (source.startsWith('file://')) {
return fileURLToPath(source);
}
return source.replace(/^(webpack:\/\/\/|webpack:\/\/|webpack:\/\/_N_E\/)/, '');
}
/**
* @returns 1-based lines and 0-based columns
*/ async function findOriginalSourcePositionAndContent(sourceMap, position) {
let consumer;
try {
consumer = await new SourceMapConsumer(sourceMap);
} catch (cause) {
throw Object.defineProperty(new Error("" + sourceMap.file + ": Invalid source map. Only conformant source maps can be used to find the original code.", {
cause
}), "__NEXT_ERROR_CODE", {
value: "E635",
enumerable: false,
configurable: true
});
}
try {
var _position_lineNumber, _position_column;
const sourcePosition = consumer.originalPositionFor({
line: (_position_lineNumber = position.lineNumber) != null ? _position_lineNumber : 1,
// 0-based columns out requires 0-based columns in.
column: ((_position_column = position.column) != null ? _position_column : 1) - 1
});
if (!sourcePosition.source) {
return null;
}
var _consumer_sourceContentFor;
const sourceContent = (_consumer_sourceContentFor = consumer.sourceContentFor(sourcePosition.source, /* returnNullOnMissing */ true)) != null ? _consumer_sourceContentFor : null;
return {
sourcePosition,
sourceContent
};
} finally{
consumer.destroy();
}
}
export function getIgnoredSources(sourceMap) {
var _sourceMap_ignoreList;
const ignoreList = new Set((_sourceMap_ignoreList = sourceMap.ignoreList) != null ? _sourceMap_ignoreList : []);
var _sourceMap_sources;
const moduleFilenames = (_sourceMap_sources = sourceMap == null ? void 0 : sourceMap.sources) != null ? _sourceMap_sources : [];
for(let index = 0; index < moduleFilenames.length; index++){
// bundlerFilePath case: webpack://./app/page.tsx
const webpackSourceURL = moduleFilenames[index];
// Format the path to the normal file path
const formattedFilePath = formatFrameSourceFile(webpackSourceURL);
if (shouldIgnoreSource(formattedFilePath)) {
ignoreList.add(index);
}
}
const ignoredSources = sourceMap.sources.map((source, index)=>{
var _sourceMap_sourcesContent;
var _sourceMap_sourcesContent_index;
return {
url: source,
ignored: ignoreList.has(sourceMap.sources.indexOf(source)),
content: (_sourceMap_sourcesContent_index = (_sourceMap_sourcesContent = sourceMap.sourcesContent) == null ? void 0 : _sourceMap_sourcesContent[index]) != null ? _sourceMap_sourcesContent_index : null
};
});
return ignoredSources;
}
function isIgnoredSource(source, sourcePosition) {
if (sourcePosition.source == null) {
return true;
}
for (const ignoredSource of source.ignoredSources){
if (ignoredSource.ignored && ignoredSource.url === sourcePosition.source) {
return true;
}
}
return false;
}
function findOriginalSourcePositionAndContentFromCompilation(moduleId, importedModule, compilation) {
var _module_buildInfo_importLocByPath, _module_buildInfo;
const module = getModuleById(moduleId, compilation);
var _module_buildInfo_importLocByPath_get;
return (_module_buildInfo_importLocByPath_get = module == null ? void 0 : (_module_buildInfo = module.buildInfo) == null ? void 0 : (_module_buildInfo_importLocByPath = _module_buildInfo.importLocByPath) == null ? void 0 : _module_buildInfo_importLocByPath.get(importedModule)) != null ? _module_buildInfo_importLocByPath_get : null;
}
export async function createOriginalStackFrame(param) {
let { source, rootDirectory, frame, errorMessage } = param;
var // We ignore the sourcemapped name since it won't be the correct name.
// The callsite will point to the column of the variable name instead of the
// name of the enclosing function.
// TODO(NDX-531): Spy on prepareStackTrace to get the enclosing line number for method name mapping.
// default is not a valid identifier in JS so webpack uses a custom variable when it's an unnamed default export
// Resolve it back to `default` for the method name if the source position didn't have the method.
_frame_methodName_replace, _frame_methodName;
const moduleNotFound = findModuleNotFoundFromError(errorMessage);
const result = await (()=>{
if (moduleNotFound) {
if (source.type === 'file') {
return undefined;
}
return findOriginalSourcePositionAndContentFromCompilation(source.moduleId, moduleNotFound, source.compilation);
}
return findOriginalSourcePositionAndContent(source.sourceMap, frame);
})();
if (!result) {
return null;
}
const { sourcePosition, sourceContent } = result;
if (!sourcePosition.source) {
return null;
}
const ignored = isIgnoredSource(source, sourcePosition) || // If the source file is externals, should be excluded even it's not ignored source.
// e.g. webpack://next/dist/.. needs to be ignored
shouldIgnoreSource(source.moduleURL);
const sourcePath = getSourcePath(// When sourcePosition.source is the loader path the modulePath is generally better.
(sourcePosition.source.includes('|') ? source.moduleURL : sourcePosition.source) || source.moduleURL);
const filePath = path.resolve(rootDirectory, sourcePath);
const resolvedFilePath = path.relative(rootDirectory, filePath);
var _sourcePosition_column;
const traced = {
file: resolvedFilePath,
lineNumber: sourcePosition.line,
column: ((_sourcePosition_column = sourcePosition.column) != null ? _sourcePosition_column : 0) + 1,
methodName: (_frame_methodName = frame.methodName) == null ? void 0 : (_frame_methodName_replace = _frame_methodName.replace('__WEBPACK_DEFAULT_EXPORT__', 'default')) == null ? void 0 : _frame_methodName_replace.replace('__webpack_exports__.', ''),
arguments: [],
ignored
};
return {
originalStackFrame: traced,
originalCodeFrame: getOriginalCodeFrame(traced, sourceContent)
};
}
async function getSourceMapFromCompilation(id, compilation) {
try {
const module = getModuleById(id, compilation);
if (!module) {
return undefined;
}
// @ts-expect-error The types for `CodeGenerationResults.get` require a
// runtime to be passed as second argument, but apparently it also works
// without it.
const codeGenerationResult = compilation.codeGenerationResults.get(module);
const source = codeGenerationResult == null ? void 0 : codeGenerationResult.sources.get('javascript');
var _source_map;
return (_source_map = source == null ? void 0 : source.map()) != null ? _source_map : undefined;
} catch (err) {
console.error('Failed to lookup module by ID ("' + id + '"):', err);
return undefined;
}
}
async function getSource(sourceURL, options) {
const { getCompilations } = options;
// Rspack is now using file:// URLs for source maps. Remove the rsc prefix to produce the file:/// url.
sourceURL = sourceURL.replace(/(.*)\/(?=file:\/\/)/, '');
let nativeSourceMap;
try {
nativeSourceMap = findSourceMap(sourceURL);
} catch (cause) {
throw Object.defineProperty(new Error("" + sourceURL + ": Invalid source map. Only conformant source maps can be used to find the original code.", {
cause
}), "__NEXT_ERROR_CODE", {
value: "E635",
enumerable: false,
configurable: true
});
}
if (nativeSourceMap !== undefined) {
const sourceMapPayload = nativeSourceMap.payload;
return {
type: 'file',
sourceMap: sourceMapPayload,
ignoredSources: getIgnoredSources(sourceMapPayload),
moduleURL: sourceURL
};
}
if (path.isAbsolute(sourceURL)) {
sourceURL = pathToFileURL(sourceURL).href;
}
if (sourceURL.startsWith('file:')) {
const sourceMap = await getSourceMapFromFile(sourceURL);
return sourceMap ? {
type: 'file',
sourceMap,
ignoredSources: getIgnoredSources(sourceMap),
moduleURL: sourceURL
} : undefined;
}
// webpack-internal:///./src/hello.tsx => ./src/hello.tsx
// rsc://React/Server/webpack-internal:///(rsc)/./src/hello.tsx?42 => (rsc)/./src/hello.tsx
// webpack://_N_E/./src/hello.tsx => ./src/hello.tsx
const moduleId = sourceURL.replace(/^(rsc:\/\/React\/[^/]+\/)?(webpack-internal:\/\/\/|webpack:\/\/(_N_E\/)?)/, '').replace(/\?\d+$/, '');
// (rsc)/./src/hello.tsx => ./src/hello.tsx
const moduleURL = moduleId.replace(/^(\(.*\)\/?)/, '');
for (const compilation of getCompilations()){
const sourceMap = await getSourceMapFromCompilation(moduleId, compilation);
if (sourceMap) {
const ignoredSources = getIgnoredSources(sourceMap);
return {
type: 'bundle',
sourceMap,
compilation,
moduleId,
moduleURL,
ignoredSources
};
}
}
return undefined;
}
function getOriginalStackFrames(param) {
let { isServer, isEdgeServer, isAppDirectory, frames, clientStats, serverStats, edgeServerStats, rootDirectory } = param;
return Promise.all(frames.map((frame)=>getOriginalStackFrame({
isServer,
isEdgeServer,
isAppDirectory,
frame,
clientStats,
serverStats,
edgeServerStats,
rootDirectory
}).then((value)=>{
return {
status: 'fulfilled',
value
};
}, (reason)=>{
return {
status: 'rejected',
reason: inspect(reason, {
colors: false
})
};
})));
}
async function getOriginalStackFrame(param) {
let { isServer, isEdgeServer, isAppDirectory, frame, clientStats, serverStats, edgeServerStats, rootDirectory } = param;
var _frame_file;
const filename = (_frame_file = frame.file) != null ? _frame_file : '';
const source = await getSource(filename, {
getCompilations: ()=>{
const compilations = [];
// Try Client Compilation first. In `pages` we leverage
// `isClientError` to check. In `app` it depends on if it's a server
// / client component and when the code throws. E.g. during HTML
// rendering it's the server/edge compilation.
if (!isEdgeServer && !isServer || isAppDirectory) {
var _clientStats;
const compilation = (_clientStats = clientStats()) == null ? void 0 : _clientStats.compilation;
if (compilation) {
compilations.push(compilation);
}
}
// Try Server Compilation. In `pages` this could be something
// imported in getServerSideProps/getStaticProps as the code for
// those is tree-shaken. In `app` this finds server components and
// code that was imported from a server component. It also covers
// when client component code throws during HTML rendering.
if (isServer || isAppDirectory) {
var _serverStats;
const compilation = (_serverStats = serverStats()) == null ? void 0 : _serverStats.compilation;
if (compilation) {
compilations.push(compilation);
}
}
// Try Edge Server Compilation. Both cases are the same as Server
// Compilation, main difference is that it covers `runtime: 'edge'`
// pages/app routes.
if (isEdgeServer || isAppDirectory) {
var _edgeServerStats;
const compilation = (_edgeServerStats = edgeServerStats()) == null ? void 0 : _edgeServerStats.compilation;
if (compilation) {
compilations.push(compilation);
}
}
return compilations;
}
});
let defaultNormalizedStackFrameLocation = frame.file;
if (defaultNormalizedStackFrameLocation !== null && defaultNormalizedStackFrameLocation.startsWith('file://')) {
defaultNormalizedStackFrameLocation = path.relative(rootDirectory, fileURLToPath(defaultNormalizedStackFrameLocation));
}
var _frame_column;
// This stack frame is used for the one that couldn't locate the source or source mapped frame
const defaultStackFrame = {
file: defaultNormalizedStackFrameLocation,
lineNumber: frame.lineNumber,
column: (_frame_column = frame.column) != null ? _frame_column : 1,
methodName: frame.methodName,
ignored: shouldIgnoreSource(filename),
arguments: []
};
if (!source) {
// return original stack frame with no source map
return {
originalStackFrame: defaultStackFrame,
originalCodeFrame: null
};
}
const originalStackFrameResponse = await createOriginalStackFrame({
frame,
source,
rootDirectory
});
if (!originalStackFrameResponse) {
return {
originalStackFrame: defaultStackFrame,
originalCodeFrame: null
};
}
return originalStackFrameResponse;
}
export function getOverlayMiddleware(options) {
const { rootDirectory, clientStats, serverStats, edgeServerStats } = options;
return async function(req, res, next) {
const { pathname, searchParams } = new URL("http://n" + req.url);
if (pathname === '/__nextjs_original-stack-frames') {
if (req.method !== 'POST') {
return middlewareResponse.badRequest(res);
}
const body = await new Promise((resolve, reject)=>{
let data = '';
req.on('data', (chunk)=>{
data += chunk;
});
req.on('end', ()=>resolve(data));
req.on('error', reject);
});
try {
const { frames, isServer, isEdgeServer, isAppDirectory } = JSON.parse(body);
return middlewareResponse.json(res, await getOriginalStackFrames({
isServer,
isEdgeServer,
isAppDirectory,
frames: frames.map((frame)=>{
var _frame_lineNumber, _frame_column;
return {
...frame,
lineNumber: (_frame_lineNumber = frame.lineNumber) != null ? _frame_lineNumber : 0,
column: (_frame_column = frame.column) != null ? _frame_column : 0
};
}),
clientStats,
serverStats,
edgeServerStats,
rootDirectory
}));
} catch (err) {
return middlewareResponse.badRequest(res);
}
} else if (pathname === '/__nextjs_launch-editor') {
var _searchParams_get, _searchParams_get1;
const frame = {
file: searchParams.get('file'),
methodName: searchParams.get('methodName'),
lineNumber: parseInt((_searchParams_get = searchParams.get('lineNumber')) != null ? _searchParams_get : '0', 10) || 0,
column: parseInt((_searchParams_get1 = searchParams.get('column')) != null ? _searchParams_get1 : '0', 10) || 0,
arguments: searchParams.getAll('arguments').filter(Boolean)
};
if (!frame.file) return middlewareResponse.badRequest(res);
// frame files may start with their webpack layer, like (middleware)/middleware.js
const filePath = path.resolve(rootDirectory, frame.file.replace(/^\([^)]+\)\//, ''));
const fileExists = await fs.access(filePath, FS.F_OK).then(()=>true, ()=>false);
if (!fileExists) return middlewareResponse.notFound(res);
try {
var _frame_column;
launchEditor(filePath, frame.lineNumber, (_frame_column = frame.column) != null ? _frame_column : 1);
} catch (err) {
console.log('Failed to launch editor:', err);
return middlewareResponse.internalServerError(res);
}
return middlewareResponse.noContent(res);
}
return next();
};
}
export function getSourceMapMiddleware(options) {
const { clientStats, serverStats, edgeServerStats } = options;
return async function(req, res, next) {
const { pathname, searchParams } = new URL("http://n" + req.url);
if (pathname !== '/__nextjs_source-map') {
return next();
}
const filename = searchParams.get('filename');
if (!filename) {
return middlewareResponse.badRequest(res);
}
let source;
try {
source = await getSource(filename, {
getCompilations: ()=>{
const compilations = [];
for (const stats of [
clientStats(),
serverStats(),
edgeServerStats()
]){
if (stats == null ? void 0 : stats.compilation) {
compilations.push(stats.compilation);
}
}
return compilations;
}
});
} catch (error) {
return middlewareResponse.internalServerError(res, error);
}
if (!source) {
return middlewareResponse.noContent(res);
}
return middlewareResponse.json(res, source.sourceMap);
};
}
//# sourceMappingURL=middleware-webpack.js.map

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,24 @@
import { codeFrameColumns } from 'next/dist/compiled/babel/code-frame';
import isInternal from '../../../../shared/lib/is-internal';
/**
* It looks up the code frame of the traced source.
* @note It ignores Next.js/React internals, as these can often be huge bundled files.
*/ export function getOriginalCodeFrame(frame, source, colors) {
if (colors === void 0) colors = process.stdout.isTTY;
if (!source || isInternal(frame.file)) {
return null;
}
var _frame_lineNumber, _frame_column;
return codeFrameColumns(source, {
start: {
// 1-based, but -1 means start line without highlighting
line: (_frame_lineNumber = frame.lineNumber) != null ? _frame_lineNumber : -1,
// 1-based, but 0 means whole line without column highlighting
column: (_frame_column = frame.column) != null ? _frame_column : 0
}
}, {
forceColor: colors
});
}
//# sourceMappingURL=shared.js.map

View File

@@ -0,0 +1 @@
{"version":3,"sources":["../../../../../src/client/components/react-dev-overlay/server/shared.ts"],"sourcesContent":["import type { StackFrame } from 'stacktrace-parser'\nimport { codeFrameColumns } from 'next/dist/compiled/babel/code-frame'\nimport isInternal from '../../../../shared/lib/is-internal'\n\nexport interface OriginalStackFramesRequest {\n frames: StackFrame[]\n isServer: boolean\n isEdgeServer: boolean\n isAppDirectory: boolean\n}\n\nexport type OriginalStackFramesResponse = OriginalStackFrameResponseResult[]\n\nexport type OriginalStackFrameResponseResult =\n PromiseSettledResult<OriginalStackFrameResponse>\n\nexport interface OriginalStackFrameResponse {\n originalStackFrame?: (StackFrame & { ignored: boolean }) | null\n originalCodeFrame?: string | null\n}\n\n/**\n * It looks up the code frame of the traced source.\n * @note It ignores Next.js/React internals, as these can often be huge bundled files.\n */\nexport function getOriginalCodeFrame(\n frame: StackFrame,\n source: string | null,\n colors: boolean = process.stdout.isTTY\n): string | null {\n if (!source || isInternal(frame.file)) {\n return null\n }\n\n return codeFrameColumns(\n source,\n {\n start: {\n // 1-based, but -1 means start line without highlighting\n line: frame.lineNumber ?? -1,\n // 1-based, but 0 means whole line without column highlighting\n column: frame.column ?? 0,\n },\n },\n { forceColor: colors }\n )\n}\n"],"names":["codeFrameColumns","isInternal","getOriginalCodeFrame","frame","source","colors","process","stdout","isTTY","file","start","line","lineNumber","column","forceColor"],"mappings":"AACA,SAASA,gBAAgB,QAAQ,sCAAqC;AACtE,OAAOC,gBAAgB,qCAAoC;AAmB3D;;;CAGC,GACD,OAAO,SAASC,qBACdC,KAAiB,EACjBC,MAAqB,EACrBC,MAAsC;IAAtCA,IAAAA,mBAAAA,SAAkBC,QAAQC,MAAM,CAACC,KAAK;IAEtC,IAAI,CAACJ,UAAUH,WAAWE,MAAMM,IAAI,GAAG;QACrC,OAAO;IACT;QAOYN,mBAEEA;IAPd,OAAOH,iBACLI,QACA;QACEM,OAAO;YACL,wDAAwD;YACxDC,MAAMR,CAAAA,oBAAAA,MAAMS,UAAU,YAAhBT,oBAAoB,CAAC;YAC3B,8DAA8D;YAC9DU,QAAQV,CAAAA,gBAAAA,MAAMU,MAAM,YAAZV,gBAAgB;QAC1B;IACF,GACA;QAAEW,YAAYT;IAAO;AAEzB"}

View File

@@ -0,0 +1,167 @@
var _process_env___NEXT_DEV_INDICATOR;
import { useReducer } from 'react';
export const ACTION_STATIC_INDICATOR = 'static-indicator';
export const ACTION_BUILD_OK = 'build-ok';
export const ACTION_BUILD_ERROR = 'build-error';
export const ACTION_BEFORE_REFRESH = 'before-fast-refresh';
export const ACTION_REFRESH = 'fast-refresh';
export const ACTION_VERSION_INFO = 'version-info';
export const ACTION_UNHANDLED_ERROR = 'unhandled-error';
export const ACTION_UNHANDLED_REJECTION = 'unhandled-rejection';
export const ACTION_DEBUG_INFO = 'debug-info';
export const ACTION_DEV_INDICATOR = 'dev-indicator';
export const STORAGE_KEY_THEME = '__nextjs-dev-tools-theme';
export const STORAGE_KEY_POSITION = '__nextjs-dev-tools-position';
function pushErrorFilterDuplicates(errors, err) {
return [
...errors.filter((e)=>{
// Filter out duplicate errors
return e.event.reason.stack !== err.event.reason.stack;
}),
err
];
}
const shouldDisableDevIndicator = ((_process_env___NEXT_DEV_INDICATOR = process.env.__NEXT_DEV_INDICATOR) == null ? void 0 : _process_env___NEXT_DEV_INDICATOR.toString()) === 'false';
export const INITIAL_OVERLAY_STATE = {
nextId: 1,
buildError: null,
errors: [],
notFound: false,
staticIndicator: false,
// To prevent flickering, set the initial state to disabled.
disableDevIndicator: true,
refreshState: {
type: 'idle'
},
rootLayoutMissingTags: [],
versionInfo: {
installed: '0.0.0',
staleness: 'unknown'
},
debugInfo: {
devtoolsFrontendUrl: undefined
}
};
function getInitialState(routerType) {
return {
...INITIAL_OVERLAY_STATE,
routerType
};
}
export function useErrorOverlayReducer(routerType) {
return useReducer((_state, action)=>{
switch(action.type){
case ACTION_DEBUG_INFO:
{
return {
..._state,
debugInfo: action.debugInfo
};
}
case ACTION_STATIC_INDICATOR:
{
return {
..._state,
staticIndicator: action.staticIndicator
};
}
case ACTION_BUILD_OK:
{
return {
..._state,
buildError: null
};
}
case ACTION_BUILD_ERROR:
{
return {
..._state,
buildError: action.message
};
}
case ACTION_BEFORE_REFRESH:
{
return {
..._state,
refreshState: {
type: 'pending',
errors: []
}
};
}
case ACTION_REFRESH:
{
return {
..._state,
buildError: null,
errors: // Errors can come in during updates. In this case, UNHANDLED_ERROR
// and UNHANDLED_REJECTION events might be dispatched between the
// BEFORE_REFRESH and the REFRESH event. We want to keep those errors
// around until the next refresh. Otherwise we run into a race
// condition where those errors would be cleared on refresh completion
// before they can be displayed.
_state.refreshState.type === 'pending' ? _state.refreshState.errors : [],
refreshState: {
type: 'idle'
}
};
}
case ACTION_UNHANDLED_ERROR:
case ACTION_UNHANDLED_REJECTION:
{
switch(_state.refreshState.type){
case 'idle':
{
return {
..._state,
nextId: _state.nextId + 1,
errors: pushErrorFilterDuplicates(_state.errors, {
id: _state.nextId,
event: action
})
};
}
case 'pending':
{
return {
..._state,
nextId: _state.nextId + 1,
refreshState: {
..._state.refreshState,
errors: pushErrorFilterDuplicates(_state.refreshState.errors, {
id: _state.nextId,
event: action
})
}
};
}
default:
// eslint-disable-next-line @typescript-eslint/no-unused-vars
const _ = _state.refreshState;
return _state;
}
}
case ACTION_VERSION_INFO:
{
return {
..._state,
versionInfo: action.versionInfo
};
}
case ACTION_DEV_INDICATOR:
{
return {
..._state,
disableDevIndicator: shouldDisableDevIndicator || !!action.devIndicator.disabledUntil
};
}
default:
{
return _state;
}
}
}, getInitialState(routerType));
}
export const REACT_REFRESH_FULL_RELOAD_FROM_ERROR = '[Fast Refresh] performing full reload because your application had an unrecoverable error';
//# sourceMappingURL=shared.js.map

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,3 @@
export { };
//# sourceMappingURL=types.js.map

View File

@@ -0,0 +1 @@
{"version":3,"sources":["../../../../src/client/components/react-dev-overlay/types.ts"],"sourcesContent":["export type DebugInfo = {\n devtoolsFrontendUrl: string | undefined\n}\n"],"names":[],"mappings":"AAAA,WAEC"}

View File

@@ -0,0 +1,66 @@
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
import { HotlinkedText } from '../hot-linked-text';
import { ExternalIcon, SourceMappingErrorIcon } from '../../icons/external';
import { getFrameSource } from '../../../utils/stack-frame';
import { useOpenInEditor } from '../../utils/use-open-in-editor';
export const CallStackFrame = function CallStackFrame(param) {
let { frame } = param;
var _frame_originalStackFrame;
// TODO: ability to expand resolved frames
const f = (_frame_originalStackFrame = frame.originalStackFrame) != null ? _frame_originalStackFrame : frame.sourceStackFrame;
const hasSource = Boolean(frame.originalCodeFrame);
const open = useOpenInEditor(hasSource ? {
file: f.file,
lineNumber: f.lineNumber,
column: f.column
} : undefined);
// Format method to strip out the webpack layer prefix.
// e.g. (app-pages-browser)/./app/page.tsx -> ./app/page.tsx
const formattedMethod = f.methodName.replace(/^\([\w-]+\)\//, '');
// Formatted file source could be empty. e.g. <anonymous> will be formatted to empty string,
// we'll skip rendering the frame in this case.
const fileSource = getFrameSource(f);
if (!fileSource) {
return null;
}
return /*#__PURE__*/ _jsxs("div", {
"data-nextjs-call-stack-frame": true,
"data-nextjs-call-stack-frame-no-source": !hasSource,
"data-nextjs-call-stack-frame-ignored": frame.ignored,
children: [
/*#__PURE__*/ _jsxs("div", {
className: "call-stack-frame-method-name",
children: [
/*#__PURE__*/ _jsx(HotlinkedText, {
text: formattedMethod
}),
hasSource && /*#__PURE__*/ _jsx("button", {
onClick: open,
className: "open-in-editor-button",
children: /*#__PURE__*/ _jsx(ExternalIcon, {
width: 16,
height: 16
})
}),
frame.error ? /*#__PURE__*/ _jsx("button", {
className: "source-mapping-error-button",
onClick: ()=>console.error(frame.reason),
title: "Sourcemapping failed. Click to log cause of error.",
children: /*#__PURE__*/ _jsx(SourceMappingErrorIcon, {
width: 16,
height: 16
})
}) : null
]
}),
/*#__PURE__*/ _jsx("span", {
className: "call-stack-frame-file-source",
"data-has-source": hasSource,
children: fileSource
})
]
});
};
export const CALL_STACK_FRAME_STYLES = '\n [data-nextjs-call-stack-frame-no-source] {\n padding: 6px 8px;\n margin-bottom: 4px;\n\n border-radius: var(--rounded-lg);\n }\n\n [data-nextjs-call-stack-frame-no-source]:last-child {\n margin-bottom: 0;\n }\n\n [data-nextjs-call-stack-frame-ignored="true"] {\n opacity: 0.6;\n }\n\n [data-nextjs-call-stack-frame] {\n user-select: text;\n display: block;\n box-sizing: border-box;\n\n user-select: text;\n -webkit-user-select: text;\n -moz-user-select: text;\n -ms-user-select: text;\n\n padding: 6px 8px;\n\n border-radius: var(--rounded-lg);\n }\n\n .call-stack-frame-method-name {\n display: flex;\n align-items: center;\n gap: 4px;\n\n margin-bottom: 4px;\n font-family: var(--font-stack-monospace);\n\n color: var(--color-gray-1000);\n font-size: var(--size-14);\n font-weight: 500;\n line-height: var(--size-20);\n\n svg {\n width: var(--size-16px);\n height: var(--size-16px);\n }\n }\n\n .open-in-editor-button, .source-mapping-error-button {\n display: flex;\n align-items: center;\n justify-content: center;\n border-radius: var(--rounded-full);\n padding: 4px;\n color: var(--color-font);\n\n svg {\n width: var(--size-16);\n height: var(--size-16);\n }\n\n &:focus-visible {\n outline: var(--focus-ring);\n outline-offset: -2px;\n }\n\n &:hover {\n background: var(--color-gray-100);\n }\n }\n\n .call-stack-frame-file-source {\n color: var(--color-gray-900);\n font-size: var(--size-14);\n line-height: var(--size-20);\n }\n';
//# sourceMappingURL=call-stack-frame.js.map

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,105 @@
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
import Anser from 'next/dist/compiled/anser';
import stripAnsi from 'next/dist/compiled/strip-ansi';
import { useMemo } from 'react';
import { HotlinkedText } from '../hot-linked-text';
import { getFrameSource } from '../../../utils/stack-frame';
import { useOpenInEditor } from '../../utils/use-open-in-editor';
import { ExternalIcon } from '../../icons/external';
import { FileIcon } from '../../icons/file';
export function CodeFrame(param) {
let { stackFrame, codeFrame } = param;
var _stackFrame_file;
// Strip leading spaces out of the code frame:
const formattedFrame = useMemo(()=>{
const lines = codeFrame.split(/\r?\n/g);
// Find the minimum length of leading spaces after `|` in the code frame
const miniLeadingSpacesLength = lines.map((line)=>/^>? +\d+ +\| [ ]+/.exec(stripAnsi(line)) === null ? null : /^>? +\d+ +\| ( *)/.exec(stripAnsi(line))).filter(Boolean).map((v)=>v.pop()).reduce((c, n)=>isNaN(c) ? n.length : Math.min(c, n.length), NaN);
// When the minimum length of leading spaces is greater than 1, remove them
// from the code frame to help the indentation looks better when there's a lot leading spaces.
if (miniLeadingSpacesLength > 1) {
return lines.map((line, a)=>~(a = line.indexOf('|')) ? line.substring(0, a) + line.substring(a).replace("^\\ {" + miniLeadingSpacesLength + "}", '') : line).join('\n');
}
return lines.join('\n');
}, [
codeFrame
]);
const decoded = useMemo(()=>{
return Anser.ansiToJson(formattedFrame, {
json: true,
use_classes: true,
remove_empty: true
});
}, [
formattedFrame
]);
const open = useOpenInEditor({
file: stackFrame.file,
lineNumber: stackFrame.lineNumber,
column: stackFrame.column
});
const fileExtension = stackFrame == null ? void 0 : (_stackFrame_file = stackFrame.file) == null ? void 0 : _stackFrame_file.split('.').pop();
// TODO: make the caret absolute
return /*#__PURE__*/ _jsxs("div", {
"data-nextjs-codeframe": true,
children: [
/*#__PURE__*/ _jsx("div", {
className: "code-frame-header",
children: /*#__PURE__*/ _jsxs("p", {
className: "code-frame-link",
children: [
/*#__PURE__*/ _jsx("span", {
className: "code-frame-icon",
children: /*#__PURE__*/ _jsx(FileIcon, {
lang: fileExtension
})
}),
/*#__PURE__*/ _jsxs("span", {
"data-text": true,
children: [
getFrameSource(stackFrame),
" @",
' ',
/*#__PURE__*/ _jsx(HotlinkedText, {
text: stackFrame.methodName
})
]
}),
/*#__PURE__*/ _jsx("button", {
"aria-label": "Open in editor",
"data-with-open-in-editor-link-source-file": true,
onClick: open,
children: /*#__PURE__*/ _jsx("span", {
className: "code-frame-icon",
"data-icon": "right",
children: /*#__PURE__*/ _jsx(ExternalIcon, {
width: 16,
height: 16
})
})
})
]
})
}),
/*#__PURE__*/ _jsx("pre", {
className: "code-frame-pre",
children: decoded.map((entry, index)=>/*#__PURE__*/ _jsx("span", {
style: {
color: entry.fg ? "var(--color-" + entry.fg + ")" : undefined,
...entry.decoration === 'bold' ? // having longer width than expected on Geist Mono font-weight
// above 600, hence a temporary fix is to use 500 for bold.
{
fontWeight: 500
} : entry.decoration === 'italic' ? {
fontStyle: 'italic'
} : undefined
},
children: entry.content
}, "frame-" + index))
})
]
});
}
export const CODE_FRAME_STYLES = "\n [data-nextjs-codeframe] {\n background-color: var(--color-background-200);\n overflow: hidden;\n color: var(--color-gray-1000);\n text-overflow: ellipsis;\n border: 1px solid var(--color-gray-400);\n border-radius: 8px;\n font-family: var(--font-stack-monospace);\n font-size: var(--size-12);\n line-height: var(--size-16);\n margin: 8px 0;\n\n svg {\n width: var(--size-16);\n height: var(--size-16);\n }\n }\n\n .code-frame-link,\n .code-frame-pre {\n padding: 12px;\n }\n\n .code-frame-link svg {\n flex-shrink: 0;\n }\n\n .code-frame-link [data-text] {\n display: inline-flex;\n text-align: left;\n margin: auto 6px;\n }\n\n .code-frame-pre {\n white-space: pre-wrap;\n }\n\n .code-frame-header {\n width: 100%;\n transition: background 100ms ease-out;\n border-radius: 8px 8px 0 0;\n border-bottom: 1px solid var(--color-gray-400);\n }\n\n [data-with-open-in-editor-link-source-file] {\n padding: 4px;\n margin: -4px 0 -4px auto;\n border-radius: var(--rounded-full);\n margin-left: auto;\n\n &:focus-visible {\n outline: var(--focus-ring);\n outline-offset: -2px;\n }\n\n &:hover {\n background: var(--color-gray-100);\n }\n }\n\n [data-nextjs-codeframe]::selection,\n [data-nextjs-codeframe] *::selection {\n background-color: var(--color-ansi-selection);\n }\n\n [data-nextjs-codeframe] *:not(a) {\n color: inherit;\n background-color: transparent;\n font-family: var(--font-stack-monospace);\n }\n\n [data-nextjs-codeframe] > * {\n margin: 0;\n }\n\n .code-frame-link {\n display: flex;\n margin: 0;\n outline: 0;\n }\n .code-frame-link [data-icon='right'] {\n margin-left: auto;\n }\n\n [data-nextjs-codeframe] div > pre {\n overflow: hidden;\n display: inline-block;\n }\n\n [data-nextjs-codeframe] svg {\n color: var(--color-gray-900);\n }\n";
//# sourceMappingURL=code-frame.js.map

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,213 @@
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
import * as React from 'react';
import { cx } from '../../utils/cx';
function useCopyLegacy(content) {
// This would be simpler with useActionState but we need to support React 18 here.
// React 18 also doesn't have async transitions.
const [copyState, dispatch] = React.useReducer((state, action)=>{
if (action.type === 'reset') {
return {
state: 'initial'
};
}
if (action.type === 'copied') {
return {
state: 'success'
};
}
if (action.type === 'copying') {
return {
state: 'pending'
};
}
if (action.type === 'error') {
return {
state: 'error',
error: action.error
};
}
return state;
}, {
state: 'initial'
});
function copy() {
if (isPending) {
return;
}
if (!navigator.clipboard) {
dispatch({
type: 'error',
error: Object.defineProperty(new Error('Copy to clipboard is not supported in this browser'), "__NEXT_ERROR_CODE", {
value: "E376",
enumerable: false,
configurable: true
})
});
} else {
dispatch({
type: 'copying'
});
navigator.clipboard.writeText(content).then(()=>{
dispatch({
type: 'copied'
});
}, (error)=>{
dispatch({
type: 'error',
error
});
});
}
}
const reset = React.useCallback(()=>{
dispatch({
type: 'reset'
});
}, []);
const isPending = copyState.state === 'pending';
return [
copyState,
copy,
reset,
isPending
];
}
function useCopyModern(content) {
const [copyState, dispatch, isPending] = React.useActionState((state, action)=>{
if (action === 'reset') {
return {
state: 'initial'
};
}
if (action === 'copy') {
if (!navigator.clipboard) {
return {
state: 'error',
error: Object.defineProperty(new Error('Copy to clipboard is not supported in this browser'), "__NEXT_ERROR_CODE", {
value: "E376",
enumerable: false,
configurable: true
})
};
}
return navigator.clipboard.writeText(content).then(()=>{
return {
state: 'success'
};
}, (error)=>{
return {
state: 'error',
error
};
});
}
return state;
}, {
state: 'initial'
});
function copy() {
React.startTransition(()=>{
dispatch('copy');
});
}
const reset = React.useCallback(()=>{
dispatch('reset');
}, [
// TODO: `dispatch` from `useActionState` is not reactive.
// Remove from dependencies once https://github.com/facebook/react/pull/29665 is released.
dispatch
]);
return [
copyState,
copy,
reset,
isPending
];
}
const useCopy = typeof React.useActionState === 'function' ? useCopyModern : useCopyLegacy;
export function CopyButton(param) {
let { actionLabel, successLabel, content, icon, disabled, ...props } = param;
const [copyState, copy, reset, isPending] = useCopy(content);
const error = copyState.state === 'error' ? copyState.error : null;
React.useEffect(()=>{
if (error !== null) {
// Additional console.error to get the stack.
console.error(error);
}
}, [
error
]);
React.useEffect(()=>{
if (copyState.state === 'success') {
const timeoutId = setTimeout(()=>{
reset();
}, 2000);
return ()=>{
clearTimeout(timeoutId);
};
}
}, [
isPending,
copyState.state,
reset
]);
const isDisabled = isPending || disabled;
const label = copyState.state === 'success' ? successLabel : actionLabel;
// Assign default icon
const renderedIcon = copyState.state === 'success' ? /*#__PURE__*/ _jsx(CopySuccessIcon, {}) : icon || /*#__PURE__*/ _jsx(CopyIcon, {
width: 14,
height: 14,
className: "error-overlay-toolbar-button-icon"
});
return /*#__PURE__*/ _jsxs("button", {
...props,
type: "button",
title: label,
"aria-label": label,
"aria-disabled": isDisabled,
disabled: isDisabled,
"data-nextjs-copy-button": true,
className: cx(props.className, 'nextjs-data-copy-button', "nextjs-data-copy-button--" + copyState.state),
onClick: ()=>{
if (!isDisabled) {
copy();
}
},
children: [
renderedIcon,
copyState.state === 'error' ? " " + copyState.error : null
]
});
}
function CopyIcon(props) {
return /*#__PURE__*/ _jsx("svg", {
width: "14",
height: "14",
viewBox: "0 0 14 14",
fill: "none",
xmlns: "http://www.w3.org/2000/svg",
...props,
children: /*#__PURE__*/ _jsx("path", {
fillRule: "evenodd",
clipRule: "evenodd",
d: "M2.406.438c-.845 0-1.531.685-1.531 1.53v6.563c0 .846.686 1.531 1.531 1.531H3.937V8.75H2.406a.219.219 0 0 1-.219-.219V1.97c0-.121.098-.219.22-.219h4.812c.12 0 .218.098.218.219v.656H8.75v-.656c0-.846-.686-1.532-1.531-1.532H2.406zm4.375 3.5c-.845 0-1.531.685-1.531 1.53v6.563c0 .846.686 1.531 1.531 1.531h4.813c.845 0 1.531-.685 1.531-1.53V5.468c0-.846-.686-1.532-1.531-1.532H6.78zm-.218 1.53c0-.12.097-.218.218-.218h4.813c.12 0 .219.098.219.219v6.562c0 .121-.098.219-.22.219H6.782a.219.219 0 0 1-.218-.219V5.47z",
fill: "currentColor"
})
});
}
function CopySuccessIcon() {
return /*#__PURE__*/ _jsx("svg", {
height: "16",
xlinkTitle: "copied",
viewBox: "0 0 16 16",
width: "16",
stroke: "currentColor",
fill: "currentColor",
children: /*#__PURE__*/ _jsx("path", {
d: "M13.78 4.22a.75.75 0 0 1 0 1.06l-7.25 7.25a.75.75 0 0 1-1.06 0L2.22 9.28a.751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018L6 10.94l6.72-6.72a.75.75 0 0 1 1.06 0Z"
})
});
}
export const COPY_BUTTON_STYLES = "\n .nextjs-data-copy-button {\n color: inherit;\n\n svg {\n width: var(--size-16);\n height: var(--size-16);\n }\n }\n .nextjs-data-copy-button--initial:hover {\n cursor: pointer;\n }\n .nextjs-data-copy-button--error,\n .nextjs-data-copy-button--error:hover {\n color: var(--color-ansi-red);\n }\n .nextjs-data-copy-button--success {\n color: var(--color-ansi-green);\n }\n";
//# sourceMappingURL=index.js.map

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,13 @@
import { jsx as _jsx } from "react/jsx-runtime";
import * as React from 'react';
const DialogBody = function DialogBody(param) {
let { children, className } = param;
return /*#__PURE__*/ _jsx("div", {
"data-nextjs-dialog-body": true,
className: className,
children: children
});
};
export { DialogBody };
//# sourceMappingURL=dialog-body.js.map

View File

@@ -0,0 +1 @@
{"version":3,"sources":["../../../../../../../src/client/components/react-dev-overlay/ui/components/dialog/dialog-body.tsx"],"sourcesContent":["import * as React from 'react'\n\nexport type DialogBodyProps = {\n children?: React.ReactNode\n className?: string\n}\n\nconst DialogBody: React.FC<DialogBodyProps> = function DialogBody({\n children,\n className,\n}) {\n return (\n <div data-nextjs-dialog-body className={className}>\n {children}\n </div>\n )\n}\n\nexport { DialogBody }\n"],"names":["React","DialogBody","children","className","div","data-nextjs-dialog-body"],"mappings":";AAAA,YAAYA,WAAW,QAAO;AAO9B,MAAMC,aAAwC,SAASA,WAAW,KAGjE;IAHiE,IAAA,EAChEC,QAAQ,EACRC,SAAS,EACV,GAHiE;IAIhE,qBACE,KAACC;QAAIC,yBAAuB;QAACF,WAAWA;kBACrCD;;AAGP;AAEA,SAASD,UAAU,GAAE"}

View File

@@ -0,0 +1,13 @@
import { jsx as _jsx } from "react/jsx-runtime";
import * as React from 'react';
const DialogContent = function DialogContent(param) {
let { children, className } = param;
return /*#__PURE__*/ _jsx("div", {
"data-nextjs-dialog-content": true,
className: className,
children: children
});
};
export { DialogContent };
//# sourceMappingURL=dialog-content.js.map

View File

@@ -0,0 +1 @@
{"version":3,"sources":["../../../../../../../src/client/components/react-dev-overlay/ui/components/dialog/dialog-content.tsx"],"sourcesContent":["import * as React from 'react'\n\nexport type DialogContentProps = {\n children?: React.ReactNode\n className?: string\n}\n\nconst DialogContent: React.FC<DialogContentProps> = function DialogContent({\n children,\n className,\n}) {\n return (\n <div data-nextjs-dialog-content className={className}>\n {children}\n </div>\n )\n}\n\nexport { DialogContent }\n"],"names":["React","DialogContent","children","className","div","data-nextjs-dialog-content"],"mappings":";AAAA,YAAYA,WAAW,QAAO;AAO9B,MAAMC,gBAA8C,SAASA,cAAc,KAG1E;IAH0E,IAAA,EACzEC,QAAQ,EACRC,SAAS,EACV,GAH0E;IAIzE,qBACE,KAACC;QAAIC,4BAA0B;QAACF,WAAWA;kBACxCD;;AAGP;AAEA,SAASD,aAAa,GAAE"}

View File

@@ -0,0 +1,11 @@
import { jsx as _jsx } from "react/jsx-runtime";
export function DialogFooter(param) {
let { children, className } = param;
return /*#__PURE__*/ _jsx("div", {
"data-nextjs-dialog-footer": true,
className: className,
children: children
});
}
//# sourceMappingURL=dialog-footer.js.map

View File

@@ -0,0 +1 @@
{"version":3,"sources":["../../../../../../../src/client/components/react-dev-overlay/ui/components/dialog/dialog-footer.tsx"],"sourcesContent":["export type DialogFooterProps = {\n children?: React.ReactNode\n className?: string\n}\n\nexport function DialogFooter({ children, className }: DialogFooterProps) {\n return (\n <div data-nextjs-dialog-footer className={className}>\n {children}\n </div>\n )\n}\n"],"names":["DialogFooter","children","className","div","data-nextjs-dialog-footer"],"mappings":";AAKA,OAAO,SAASA,aAAa,KAA0C;IAA1C,IAAA,EAAEC,QAAQ,EAAEC,SAAS,EAAqB,GAA1C;IAC3B,qBACE,KAACC;QAAIC,2BAAyB;QAACF,WAAWA;kBACvCD;;AAGP"}

View File

@@ -0,0 +1,13 @@
import { jsx as _jsx } from "react/jsx-runtime";
import * as React from 'react';
const DialogHeader = function DialogHeader(param) {
let { children, className } = param;
return /*#__PURE__*/ _jsx("div", {
"data-nextjs-dialog-header": true,
className: className,
children: children
});
};
export { DialogHeader };
//# sourceMappingURL=dialog-header.js.map

View File

@@ -0,0 +1 @@
{"version":3,"sources":["../../../../../../../src/client/components/react-dev-overlay/ui/components/dialog/dialog-header.tsx"],"sourcesContent":["import * as React from 'react'\n\nexport type DialogHeaderProps = {\n children?: React.ReactNode\n className?: string\n}\n\nconst DialogHeader: React.FC<DialogHeaderProps> = function DialogHeader({\n children,\n className,\n}) {\n return (\n <div data-nextjs-dialog-header className={className}>\n {children}\n </div>\n )\n}\n\nexport { DialogHeader }\n"],"names":["React","DialogHeader","children","className","div","data-nextjs-dialog-header"],"mappings":";AAAA,YAAYA,WAAW,QAAO;AAO9B,MAAMC,eAA4C,SAASA,aAAa,KAGvE;IAHuE,IAAA,EACtEC,QAAQ,EACRC,SAAS,EACV,GAHuE;IAItE,qBACE,KAACC;QAAIC,2BAAyB;QAACF,WAAWA;kBACvCD;;AAGP;AAEA,SAASD,YAAY,GAAE"}

View File

@@ -0,0 +1,85 @@
import { jsx as _jsx } from "react/jsx-runtime";
import * as React from 'react';
import { useOnClickOutside } from '../../hooks/use-on-click-outside';
import { useMeasureHeight } from '../../hooks/use-measure-height';
const CSS_SELECTORS_TO_EXCLUDE_ON_CLICK_OUTSIDE = [
'[data-next-mark]',
'[data-issues-open]',
'#nextjs-dev-tools-menu',
'[data-nextjs-error-overlay-nav]',
'[data-info-popover]'
];
const Dialog = function Dialog(param) {
let { children, type, className, onClose, 'aria-labelledby': ariaLabelledBy, 'aria-describedby': ariaDescribedBy, dialogResizerRef, ...props } = param;
const dialogRef = React.useRef(null);
const [role, setRole] = React.useState(typeof document !== 'undefined' && document.hasFocus() ? 'dialog' : undefined);
const ref = React.useRef(null);
const [height, pristine] = useMeasureHeight(ref);
useOnClickOutside(dialogRef.current, CSS_SELECTORS_TO_EXCLUDE_ON_CLICK_OUTSIDE, (e)=>{
e.preventDefault();
return onClose == null ? void 0 : onClose();
});
React.useEffect(()=>{
if (dialogRef.current == null) {
return;
}
function handleFocus() {
// safari will force itself as the active application when a background page triggers any sort of autofocus
// this is a workaround to only set the dialog role if the document has focus
setRole(document.hasFocus() ? 'dialog' : undefined);
}
window.addEventListener('focus', handleFocus);
window.addEventListener('blur', handleFocus);
return ()=>{
window.removeEventListener('focus', handleFocus);
window.removeEventListener('blur', handleFocus);
};
}, []);
React.useEffect(()=>{
const dialog = dialogRef.current;
const root = dialog == null ? void 0 : dialog.getRootNode();
const initialActiveElement = root instanceof ShadowRoot ? root == null ? void 0 : root.activeElement : null;
// Trap focus within the dialog
dialog == null ? void 0 : dialog.focus();
return ()=>{
// Blur first to avoid getting stuck, in case `activeElement` is missing
dialog == null ? void 0 : dialog.blur();
// Restore focus to the previously active element
initialActiveElement == null ? void 0 : initialActiveElement.focus();
};
}, []);
return /*#__PURE__*/ _jsx("div", {
ref: dialogRef,
tabIndex: -1,
"data-nextjs-dialog": true,
role: role,
"aria-labelledby": ariaLabelledBy,
"aria-describedby": ariaDescribedBy,
"aria-modal": "true",
className: className,
onKeyDown: (e)=>{
if (e.key === 'Escape') {
onClose == null ? void 0 : onClose();
}
},
...props,
children: /*#__PURE__*/ _jsx("div", {
ref: dialogResizerRef,
"data-nextjs-dialog-sizer": true,
// [x] Don't animate on initial load
// [x] No duplicate elements
// [x] Responds to content growth
style: {
height,
transition: pristine ? undefined : 'height 250ms var(--timing-swift)'
},
children: /*#__PURE__*/ _jsx("div", {
ref: ref,
children: children
})
})
});
};
export { Dialog };
//# sourceMappingURL=dialog.js.map

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,8 @@
export { Dialog } from './dialog';
export { DialogBody } from './dialog-body';
export { DialogContent } from './dialog-content';
export { DialogHeader } from './dialog-header';
export { DialogFooter } from './dialog-footer';
export { styles } from './styles';
//# sourceMappingURL=index.js.map

View File

@@ -0,0 +1 @@
{"version":3,"sources":["../../../../../../../src/client/components/react-dev-overlay/ui/components/dialog/index.ts"],"sourcesContent":["export { Dialog } from './dialog'\nexport { DialogBody } from './dialog-body'\nexport { DialogContent } from './dialog-content'\nexport { DialogHeader } from './dialog-header'\nexport { DialogFooter } from './dialog-footer'\nexport { styles } from './styles'\n"],"names":["Dialog","DialogBody","DialogContent","DialogHeader","DialogFooter","styles"],"mappings":"AAAA,SAASA,MAAM,QAAQ,WAAU;AACjC,SAASC,UAAU,QAAQ,gBAAe;AAC1C,SAASC,aAAa,QAAQ,mBAAkB;AAChD,SAASC,YAAY,QAAQ,kBAAiB;AAC9C,SAASC,YAAY,QAAQ,kBAAiB;AAC9C,SAASC,MAAM,QAAQ,WAAU"}

View File

@@ -0,0 +1,4 @@
const styles = "\n [data-nextjs-dialog-root] {\n --next-dialog-radius: var(--rounded-xl);\n --next-dialog-footer-height: var(--size-48);\n --next-dialog-max-width: 960px;\n --next-dialog-row-padding: 16px;\n --next-dialog-container-padding: 12px;\n\n display: flex;\n flex-direction: column-reverse;\n width: 100%;\n max-height: calc(100% - 56px);\n max-width: var(--next-dialog-max-width);\n margin-right: auto;\n margin-left: auto;\n scale: 0.98;\n opacity: 0;\n transition-property: scale, opacity;\n transition-duration: var(--transition-duration);\n transition-timing-function: var(--timing-overlay);\n\n &[data-rendered='true'] {\n opacity: 1;\n scale: 1;\n }\n }\n\n [data-nextjs-dialog] {\n outline: none;\n overflow: hidden;\n }\n [data-nextjs-dialog]::-webkit-scrollbar {\n width: 6px;\n border-radius: 0 0 1rem 1rem;\n margin-bottom: 1rem;\n }\n [data-nextjs-dialog]::-webkit-scrollbar-button {\n display: none;\n }\n [data-nextjs-dialog]::-webkit-scrollbar-track {\n border-radius: 0 0 1rem 1rem;\n background-color: var(--color-background-100);\n }\n [data-nextjs-dialog]::-webkit-scrollbar-thumb {\n border-radius: 1rem;\n background-color: var(--color-gray-500);\n }\n\n \n [data-nextjs-dialog-sizer] {\n overflow: hidden;\n border-radius: inherit;\n }\n\n [data-nextjs-dialog-backdrop] {\n opacity: 0;\n transition: opacity var(--transition-duration) var(--timing-overlay);\n }\n\n [data-nextjs-dialog-overlay][data-rendered='true']\n [data-nextjs-dialog-backdrop] {\n opacity: 1;\n }\n\n [data-nextjs-dialog-content] {\n overflow-y: auto;\n border: none;\n margin: 0;\n display: flex;\n flex-direction: column;\n position: relative;\n padding: 16px 12px;\n }\n\n /* Account for the footer height, when present */\n [data-nextjs-dialog][data-has-footer='true'] [data-nextjs-dialog-body] {\n margin-bottom: var(--next-dialog-footer-height);\n }\n\n [data-nextjs-dialog-content] > [data-nextjs-dialog-header] {\n flex-shrink: 0;\n margin-bottom: 8px;\n }\n\n [data-nextjs-dialog-content] > [data-nextjs-dialog-body] {\n position: relative;\n flex: 1 1 auto;\n }\n\n [data-nextjs-dialog-footer] {\n /* Subtract border width */\n width: calc(100% - 2px);\n /* \n We make this element fixed to anchor it to the bottom during the height transition.\n If you make this relative it will jump during the transition and not collapse or expand smoothly.\n If you make this absolute it will remain stuck at its initial position when scrolling the dialog.\n */\n position: fixed;\n bottom: 1px;\n min-height: var(--next-dialog-footer-height);\n border-radius: 0 0 var(--next-dialog-radius) var(--next-dialog-radius);\n overflow: hidden;\n\n > * {\n min-height: var(--next-dialog-footer-height);\n }\n }\n\n @media (max-height: 812px) {\n [data-nextjs-dialog-overlay] {\n max-height: calc(100% - 15px);\n }\n }\n\n @media (min-width: 576px) {\n [data-nextjs-dialog-root] {\n --next-dialog-max-width: 540px;\n }\n }\n\n @media (min-width: 768px) {\n [data-nextjs-dialog-root] {\n --next-dialog-max-width: 720px;\n }\n }\n\n @media (min-width: 992px) {\n [data-nextjs-dialog-root] {\n --next-dialog-max-width: 960px;\n }\n }\n";
export { styles };
//# sourceMappingURL=styles.js.map

View File

@@ -0,0 +1 @@
{"version":3,"sources":["../../../../../../../src/client/components/react-dev-overlay/ui/components/dialog/styles.ts"],"sourcesContent":["const styles = `\n [data-nextjs-dialog-root] {\n --next-dialog-radius: var(--rounded-xl);\n --next-dialog-footer-height: var(--size-48);\n --next-dialog-max-width: 960px;\n --next-dialog-row-padding: 16px;\n --next-dialog-container-padding: 12px;\n\n display: flex;\n flex-direction: column-reverse;\n width: 100%;\n max-height: calc(100% - 56px);\n max-width: var(--next-dialog-max-width);\n margin-right: auto;\n margin-left: auto;\n scale: 0.98;\n opacity: 0;\n transition-property: scale, opacity;\n transition-duration: var(--transition-duration);\n transition-timing-function: var(--timing-overlay);\n\n &[data-rendered='true'] {\n opacity: 1;\n scale: 1;\n }\n }\n\n [data-nextjs-dialog] {\n outline: none;\n overflow: hidden;\n }\n [data-nextjs-dialog]::-webkit-scrollbar {\n width: 6px;\n border-radius: 0 0 1rem 1rem;\n margin-bottom: 1rem;\n }\n [data-nextjs-dialog]::-webkit-scrollbar-button {\n display: none;\n }\n [data-nextjs-dialog]::-webkit-scrollbar-track {\n border-radius: 0 0 1rem 1rem;\n background-color: var(--color-background-100);\n }\n [data-nextjs-dialog]::-webkit-scrollbar-thumb {\n border-radius: 1rem;\n background-color: var(--color-gray-500);\n }\n\n ${\n '' /* Place overflow: hidden on this so we can break out from [data-nextjs-dialog] */\n }\n [data-nextjs-dialog-sizer] {\n overflow: hidden;\n border-radius: inherit;\n }\n\n [data-nextjs-dialog-backdrop] {\n opacity: 0;\n transition: opacity var(--transition-duration) var(--timing-overlay);\n }\n\n [data-nextjs-dialog-overlay][data-rendered='true']\n [data-nextjs-dialog-backdrop] {\n opacity: 1;\n }\n\n [data-nextjs-dialog-content] {\n overflow-y: auto;\n border: none;\n margin: 0;\n display: flex;\n flex-direction: column;\n position: relative;\n padding: 16px 12px;\n }\n\n /* Account for the footer height, when present */\n [data-nextjs-dialog][data-has-footer='true'] [data-nextjs-dialog-body] {\n margin-bottom: var(--next-dialog-footer-height);\n }\n\n [data-nextjs-dialog-content] > [data-nextjs-dialog-header] {\n flex-shrink: 0;\n margin-bottom: 8px;\n }\n\n [data-nextjs-dialog-content] > [data-nextjs-dialog-body] {\n position: relative;\n flex: 1 1 auto;\n }\n\n [data-nextjs-dialog-footer] {\n /* Subtract border width */\n width: calc(100% - 2px);\n /* \n We make this element fixed to anchor it to the bottom during the height transition.\n If you make this relative it will jump during the transition and not collapse or expand smoothly.\n If you make this absolute it will remain stuck at its initial position when scrolling the dialog.\n */\n position: fixed;\n bottom: 1px;\n min-height: var(--next-dialog-footer-height);\n border-radius: 0 0 var(--next-dialog-radius) var(--next-dialog-radius);\n overflow: hidden;\n\n > * {\n min-height: var(--next-dialog-footer-height);\n }\n }\n\n @media (max-height: 812px) {\n [data-nextjs-dialog-overlay] {\n max-height: calc(100% - 15px);\n }\n }\n\n @media (min-width: 576px) {\n [data-nextjs-dialog-root] {\n --next-dialog-max-width: 540px;\n }\n }\n\n @media (min-width: 768px) {\n [data-nextjs-dialog-root] {\n --next-dialog-max-width: 720px;\n }\n }\n\n @media (min-width: 992px) {\n [data-nextjs-dialog-root] {\n --next-dialog-max-width: 960px;\n }\n }\n`\n\nexport { styles }\n"],"names":["styles"],"mappings":"AAAA,MAAMA,SAAU;AAuIhB,SAASA,MAAM,GAAE"}

View File

@@ -0,0 +1,86 @@
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
import { useMemo, useState, useRef } from 'react';
import { CallStackFrame } from '../../call-stack-frame/call-stack-frame';
export function CallStack(param) {
let { frames, dialogResizerRef } = param;
const initialDialogHeight = useRef(NaN);
const [isIgnoreListOpen, setIsIgnoreListOpen] = useState(false);
const ignoredFramesTally = useMemo(()=>{
return frames.reduce((tally, frame)=>tally + (frame.ignored ? 1 : 0), 0);
}, [
frames
]);
function onToggleIgnoreList() {
const dialog = dialogResizerRef == null ? void 0 : dialogResizerRef.current;
if (!dialog) {
return;
}
const { height: currentHeight } = dialog == null ? void 0 : dialog.getBoundingClientRect();
if (!initialDialogHeight.current) {
initialDialogHeight.current = currentHeight;
}
if (isIgnoreListOpen) {
function onTransitionEnd() {
dialog.removeEventListener('transitionend', onTransitionEnd);
setIsIgnoreListOpen(false);
}
dialog.style.height = "" + initialDialogHeight.current + "px";
dialog.addEventListener('transitionend', onTransitionEnd);
} else {
setIsIgnoreListOpen(true);
}
}
return /*#__PURE__*/ _jsxs("div", {
className: "error-overlay-call-stack-container",
children: [
/*#__PURE__*/ _jsxs("div", {
className: "error-overlay-call-stack-header",
children: [
/*#__PURE__*/ _jsxs("p", {
className: "error-overlay-call-stack-title",
children: [
"Call Stack",
' ',
/*#__PURE__*/ _jsx("span", {
className: "error-overlay-call-stack-count",
children: frames.length
})
]
}),
ignoredFramesTally > 0 && /*#__PURE__*/ _jsxs("button", {
"data-expand-ignore-button": isIgnoreListOpen,
className: "error-overlay-call-stack-ignored-list-toggle-button",
onClick: onToggleIgnoreList,
children: [
(isIgnoreListOpen ? 'Hide' : 'Show') + " " + ignoredFramesTally + " ignore-listed frame(s)",
/*#__PURE__*/ _jsx(ChevronUpDown, {})
]
})
]
}),
frames.map((frame, frameIndex)=>{
return !frame.ignored || isIgnoreListOpen ? /*#__PURE__*/ _jsx(CallStackFrame, {
frame: frame
}, frameIndex) : null;
})
]
});
}
function ChevronUpDown() {
return /*#__PURE__*/ _jsx("svg", {
width: "16",
height: "16",
viewBox: "0 0 16 16",
fill: "none",
xmlns: "http://www.w3.org/2000/svg",
children: /*#__PURE__*/ _jsx("path", {
fillRule: "evenodd",
clipRule: "evenodd",
d: "M8.70722 2.39641C8.3167 2.00588 7.68353 2.00588 7.29301 2.39641L4.46978 5.21963L3.93945 5.74996L5.00011 6.81062L5.53044 6.28029L8.00011 3.81062L10.4698 6.28029L11.0001 6.81062L12.0608 5.74996L11.5304 5.21963L8.70722 2.39641ZM5.53044 9.71963L5.00011 9.1893L3.93945 10.25L4.46978 10.7803L7.29301 13.6035C7.68353 13.994 8.3167 13.994 8.70722 13.6035L11.5304 10.7803L12.0608 10.25L11.0001 9.1893L10.4698 9.71963L8.00011 12.1893L5.53044 9.71963Z",
fill: "currentColor"
})
});
}
export const CALL_STACK_STYLES = "\n .error-overlay-call-stack-container {\n position: relative;\n margin-top: 8px;\n }\n\n .error-overlay-call-stack-header {\n display: flex;\n justify-content: space-between;\n align-items: center;\n min-height: var(--size-28);\n padding: 8px 8px 12px 4px;\n width: 100%;\n }\n\n .error-overlay-call-stack-title {\n display: flex;\n justify-content: space-between;\n align-items: center;\n gap: 8px;\n\n margin: 0;\n\n color: var(--color-gray-1000);\n font-size: var(--size-16);\n font-weight: 500;\n }\n\n .error-overlay-call-stack-count {\n display: flex;\n justify-content: center;\n align-items: center;\n\n width: var(--size-20);\n height: var(--size-20);\n gap: 4px;\n\n color: var(--color-gray-1000);\n text-align: center;\n font-size: var(--size-11);\n font-weight: 500;\n line-height: var(--size-16);\n\n border-radius: var(--rounded-full);\n background: var(--color-gray-300);\n }\n\n .error-overlay-call-stack-ignored-list-toggle-button {\n all: unset;\n display: flex;\n align-items: center;\n gap: 6px;\n color: var(--color-gray-900);\n font-size: var(--size-14);\n line-height: var(--size-20);\n border-radius: 6px;\n padding: 4px 6px;\n margin-right: -6px;\n transition: background 150ms ease;\n\n &:hover {\n background: var(--color-gray-100);\n }\n\n &:focus {\n outline: var(--focus-ring);\n }\n\n svg {\n width: var(--size-16);\n height: var(--size-16);\n }\n }\n";
//# sourceMappingURL=call-stack.js.map

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,373 @@
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
import { STORAGE_KEY_POSITION } from '../../../../shared';
import { useState, useEffect, useRef, createContext, useContext } from 'react';
import { Toast } from '../../toast';
import { NextLogo } from './next-logo';
import { useIsDevBuilding } from '../../../../../../dev/dev-build-indicator/internal/initialize';
import { useIsDevRendering } from '../../../../utils/dev-indicator/dev-render-indicator';
import { useDelayedRender } from '../../../hooks/use-delayed-render';
import { TurbopackInfo } from './dev-tools-info/turbopack-info';
import { RouteInfo } from './dev-tools-info/route-info';
import GearIcon from '../../../icons/gear-icon';
import { UserPreferences } from './dev-tools-info/user-preferences';
import { MENU_CURVE, MENU_DURATION_MS, useClickOutside, useFocusTrap } from './utils';
// TODO: add E2E tests to cover different scenarios
const INDICATOR_POSITION = process.env.__NEXT_DEV_INDICATOR_POSITION || 'bottom-left';
export function DevToolsIndicator(param) {
let { state, errorCount, isBuildError, setIsErrorOverlayOpen } = param;
const [isDevToolsIndicatorVisible, setIsDevToolsIndicatorVisible] = useState(true);
return /*#__PURE__*/ _jsx(DevToolsPopover, {
routerType: state.routerType,
semver: state.versionInfo.installed,
issueCount: errorCount,
isStaticRoute: state.staticIndicator,
hide: ()=>{
setIsDevToolsIndicatorVisible(false);
fetch('/__nextjs_disable_dev_indicator', {
method: 'POST'
});
},
setIsErrorOverlayOpen: setIsErrorOverlayOpen,
isTurbopack: !!process.env.TURBOPACK,
disabled: state.disableDevIndicator || !isDevToolsIndicatorVisible,
isBuildError: isBuildError
});
}
const Context = /*#__PURE__*/ createContext({});
function getInitialPosition() {
if (typeof localStorage !== 'undefined' && localStorage.getItem(STORAGE_KEY_POSITION)) {
return localStorage.getItem(STORAGE_KEY_POSITION);
}
return INDICATOR_POSITION;
}
const OVERLAYS = {
Root: 'root',
Turbo: 'turbo',
Route: 'route',
Preferences: 'preferences'
};
function DevToolsPopover(param) {
let { routerType, disabled, issueCount, isStaticRoute, isTurbopack, isBuildError, hide, setIsErrorOverlayOpen } = param;
const menuRef = useRef(null);
const triggerRef = useRef(null);
const [open, setOpen] = useState(null);
const [position, setPosition] = useState(getInitialPosition());
const [selectedIndex, setSelectedIndex] = useState(-1);
const isMenuOpen = open === OVERLAYS.Root;
const isTurbopackInfoOpen = open === OVERLAYS.Turbo;
const isRouteInfoOpen = open === OVERLAYS.Route;
const isPreferencesOpen = open === OVERLAYS.Preferences;
const { mounted: menuMounted, rendered: menuRendered } = useDelayedRender(isMenuOpen, {
// Intentionally no fade in, makes the UI feel more immediate
enterDelay: 0,
// Graceful fade out to confirm that the UI did not break
exitDelay: MENU_DURATION_MS
});
// Features to make the menu accessible
useFocusTrap(menuRef, triggerRef, isMenuOpen);
useClickOutside(menuRef, triggerRef, isMenuOpen, closeMenu);
useEffect(()=>{
if (open === null) {
// Avoid flashing selected state
const id = setTimeout(()=>{
setSelectedIndex(-1);
}, MENU_DURATION_MS);
return ()=>clearTimeout(id);
}
}, [
open
]);
function select(index) {
var _menuRef_current;
if (index === 'first') {
setTimeout(()=>{
var _menuRef_current;
const all = (_menuRef_current = menuRef.current) == null ? void 0 : _menuRef_current.querySelectorAll('[role="menuitem"]');
if (all) {
const firstIndex = all[0].getAttribute('data-index');
select(Number(firstIndex));
}
});
return;
}
if (index === 'last') {
setTimeout(()=>{
var _menuRef_current;
const all = (_menuRef_current = menuRef.current) == null ? void 0 : _menuRef_current.querySelectorAll('[role="menuitem"]');
if (all) {
const lastIndex = all.length - 1;
select(lastIndex);
}
});
return;
}
const el = (_menuRef_current = menuRef.current) == null ? void 0 : _menuRef_current.querySelector('[data-index="' + index + '"]');
if (el) {
setSelectedIndex(index);
el == null ? void 0 : el.focus();
}
}
function onMenuKeydown(e) {
e.preventDefault();
switch(e.key){
case 'ArrowDown':
const next = selectedIndex + 1;
select(next);
break;
case 'ArrowUp':
const prev = selectedIndex - 1;
select(prev);
break;
case 'Home':
select('first');
break;
case 'End':
select('last');
break;
default:
break;
}
}
function openErrorOverlay() {
setOpen(null);
if (issueCount > 0) {
setIsErrorOverlayOpen(true);
}
}
function toggleErrorOverlay() {
setIsErrorOverlayOpen((prev)=>!prev);
}
function openRootMenu() {
setOpen((prevOpen)=>{
if (prevOpen === null) select('first');
return OVERLAYS.Root;
});
}
function onTriggerClick() {
if (open === OVERLAYS.Root) {
setOpen(null);
} else {
openRootMenu();
setTimeout(()=>{
select('first');
});
}
}
function closeMenu() {
// Only close when we were on `Root`,
// otherwise it will close other overlays
setOpen((prevOpen)=>{
if (prevOpen === OVERLAYS.Root) {
return null;
}
return prevOpen;
});
}
function handleHideDevtools() {
setOpen(null);
hide();
}
const [vertical, horizontal] = position.split('-', 2);
const popover = {
[vertical]: 'calc(100% + 8px)',
[horizontal]: 0
};
return /*#__PURE__*/ _jsxs(Toast, {
"data-nextjs-toast": true,
style: {
'--animate-out-duration-ms': "" + MENU_DURATION_MS + "ms",
'--animate-out-timing-function': MENU_CURVE,
boxShadow: 'none',
zIndex: 2147483647,
// Reset the toast component's default positions.
bottom: 'initial',
left: 'initial',
[vertical]: '20px',
[horizontal]: '20px'
},
children: [
/*#__PURE__*/ _jsx(NextLogo, {
ref: triggerRef,
"aria-haspopup": "menu",
"aria-expanded": isMenuOpen,
"aria-controls": "nextjs-dev-tools-menu",
"aria-label": "" + (isMenuOpen ? 'Close' : 'Open') + " Next.js Dev Tools",
"data-nextjs-dev-tools-button": true,
disabled: disabled,
issueCount: issueCount,
onTriggerClick: onTriggerClick,
toggleErrorOverlay: toggleErrorOverlay,
isDevBuilding: useIsDevBuilding(),
isDevRendering: useIsDevRendering(),
isBuildError: isBuildError
}),
/*#__PURE__*/ _jsx(RouteInfo, {
isOpen: isRouteInfoOpen,
close: openRootMenu,
triggerRef: triggerRef,
style: popover,
routerType: routerType,
routeType: isStaticRoute ? 'Static' : 'Dynamic'
}),
/*#__PURE__*/ _jsx(TurbopackInfo, {
isOpen: isTurbopackInfoOpen,
close: openRootMenu,
triggerRef: triggerRef,
style: popover
}),
/*#__PURE__*/ _jsx(UserPreferences, {
isOpen: isPreferencesOpen,
close: openRootMenu,
triggerRef: triggerRef,
style: popover,
hide: handleHideDevtools,
setPosition: setPosition,
position: position
}),
menuMounted && /*#__PURE__*/ _jsx("div", {
ref: menuRef,
id: "nextjs-dev-tools-menu",
role: "menu",
dir: "ltr",
"aria-orientation": "vertical",
"aria-label": "Next.js Dev Tools Items",
tabIndex: -1,
className: "dev-tools-indicator-menu",
onKeyDown: onMenuKeydown,
"data-rendered": menuRendered,
style: popover,
children: /*#__PURE__*/ _jsxs(Context.Provider, {
value: {
closeMenu,
selectedIndex,
setSelectedIndex
},
children: [
/*#__PURE__*/ _jsxs("div", {
className: "dev-tools-indicator-inner",
children: [
issueCount > 0 && /*#__PURE__*/ _jsx(MenuItem, {
title: issueCount + " " + (issueCount === 1 ? 'issue' : 'issues') + " found. Click to view details in the dev overlay.",
index: 0,
label: "Issues",
value: /*#__PURE__*/ _jsx(IssueCount, {
children: issueCount
}),
onClick: openErrorOverlay
}),
/*#__PURE__*/ _jsx(MenuItem, {
title: "Current route is " + (isStaticRoute ? 'static' : 'dynamic') + ".",
label: "Route",
index: 1,
value: isStaticRoute ? 'Static' : 'Dynamic',
onClick: ()=>setOpen(OVERLAYS.Route),
"data-nextjs-route-type": isStaticRoute ? 'static' : 'dynamic'
}),
isTurbopack ? /*#__PURE__*/ _jsx(MenuItem, {
title: "Turbopack is enabled.",
label: "Turbopack",
value: "Enabled"
}) : /*#__PURE__*/ _jsx(MenuItem, {
index: 2,
title: "Learn about Turbopack and how to enable it in your application.",
label: "Try Turbopack",
value: /*#__PURE__*/ _jsx(ChevronRight, {}),
onClick: ()=>setOpen(OVERLAYS.Turbo)
})
]
}),
/*#__PURE__*/ _jsx("div", {
className: "dev-tools-indicator-footer",
children: /*#__PURE__*/ _jsx(MenuItem, {
"data-preferences": true,
label: "Preferences",
value: /*#__PURE__*/ _jsx(GearIcon, {}),
onClick: ()=>setOpen(OVERLAYS.Preferences),
index: isTurbopack ? 2 : 3
})
})
]
})
})
]
});
}
function ChevronRight() {
return /*#__PURE__*/ _jsx("svg", {
xmlns: "http://www.w3.org/2000/svg",
width: "16",
height: "16",
viewBox: "0 0 16 16",
fill: "none",
children: /*#__PURE__*/ _jsx("path", {
fill: "#666",
fillRule: "evenodd",
clipRule: "evenodd",
d: "M5.50011 1.93945L6.03044 2.46978L10.8537 7.293C11.2442 7.68353 11.2442 8.31669 10.8537 8.70722L6.03044 13.5304L5.50011 14.0608L4.43945 13.0001L4.96978 12.4698L9.43945 8.00011L4.96978 3.53044L4.43945 3.00011L5.50011 1.93945Z"
})
});
}
function MenuItem(param) {
let { index, label, value, onClick, href, ...props } = param;
const isInteractive = typeof onClick === 'function' || typeof href === 'string';
const { closeMenu, selectedIndex, setSelectedIndex } = useContext(Context);
const selected = selectedIndex === index;
function click() {
if (isInteractive) {
onClick == null ? void 0 : onClick();
closeMenu();
if (href) {
window.open(href, '_blank', 'noopener, noreferrer');
}
}
}
return /*#__PURE__*/ _jsxs("div", {
className: "dev-tools-indicator-item",
"data-index": index,
"data-selected": selected,
onClick: click,
// Needs `onMouseMove` instead of enter to work together
// with keyboard and mouse input
onMouseMove: ()=>{
if (isInteractive && index !== undefined && selectedIndex !== index) {
setSelectedIndex(index);
}
},
onMouseLeave: ()=>setSelectedIndex(-1),
onKeyDown: (e)=>{
if (e.key === 'Enter' || e.key === ' ') {
click();
}
},
role: isInteractive ? 'menuitem' : undefined,
tabIndex: selected ? 0 : -1,
...props,
children: [
/*#__PURE__*/ _jsx("span", {
className: "dev-tools-indicator-label",
children: label
}),
/*#__PURE__*/ _jsx("span", {
className: "dev-tools-indicator-value",
children: value
})
]
});
}
function IssueCount(param) {
let { children } = param;
return /*#__PURE__*/ _jsxs("span", {
className: "dev-tools-indicator-issue-count",
"data-has-issues": children > 0,
children: [
/*#__PURE__*/ _jsx("span", {
className: "dev-tools-indicator-issue-count-indicator"
}),
children
]
});
}
//////////////////////////////////////////////////////////////////////////////////////
export const DEV_TOOLS_INDICATOR_STYLES = "\n .dev-tools-indicator-menu {\n -webkit-font-smoothing: antialiased;\n display: flex;\n flex-direction: column;\n align-items: flex-start;\n background: var(--color-background-100);\n border: 1px solid var(--color-gray-alpha-400);\n background-clip: padding-box;\n box-shadow: var(--shadow-menu);\n border-radius: var(--rounded-xl);\n position: absolute;\n font-family: var(--font-stack-sans);\n z-index: 1000;\n overflow: hidden;\n opacity: 0;\n outline: 0;\n min-width: 248px;\n transition: opacity var(--animate-out-duration-ms)\n var(--animate-out-timing-function);\n\n &[data-rendered='true'] {\n opacity: 1;\n scale: 1;\n }\n }\n\n .dev-tools-indicator-inner {\n padding: 6px;\n width: 100%;\n }\n\n .dev-tools-indicator-item {\n display: flex;\n align-items: center;\n padding: 8px 6px;\n height: var(--size-36);\n border-radius: 6px;\n text-decoration: none !important;\n user-select: none;\n white-space: nowrap;\n\n svg {\n width: var(--size-16);\n height: var(--size-16);\n }\n\n &:focus-visible {\n outline: 0;\n }\n }\n\n .dev-tools-indicator-footer {\n background: var(--color-background-200);\n padding: 6px;\n border-top: 1px solid var(--color-gray-400);\n width: 100%;\n }\n\n .dev-tools-indicator-item[data-selected='true'] {\n cursor: pointer;\n background-color: var(--color-gray-200);\n }\n\n .dev-tools-indicator-label {\n font-size: var(--size-14);\n line-height: var(--size-20);\n color: var(--color-gray-1000);\n }\n\n .dev-tools-indicator-value {\n font-size: var(--size-14);\n line-height: var(--size-20);\n color: var(--color-gray-900);\n margin-left: auto;\n }\n\n .dev-tools-indicator-issue-count {\n --color-primary: var(--color-gray-800);\n --color-secondary: var(--color-gray-100);\n display: flex;\n flex-direction: row;\n align-items: center;\n justify-content: center;\n gap: 8px;\n min-width: var(--size-40);\n height: var(--size-24);\n background: var(--color-background-100);\n border: 1px solid var(--color-gray-alpha-400);\n background-clip: padding-box;\n box-shadow: var(--shadow-small);\n padding: 2px;\n color: var(--color-gray-1000);\n border-radius: 128px;\n font-weight: 500;\n font-size: var(--size-13);\n font-variant-numeric: tabular-nums;\n\n &[data-has-issues='true'] {\n --color-primary: var(--color-red-800);\n --color-secondary: var(--color-red-100);\n }\n\n .dev-tools-indicator-issue-count-indicator {\n width: var(--size-8);\n height: var(--size-8);\n background: var(--color-primary);\n box-shadow: 0 0 0 2px var(--color-secondary);\n border-radius: 50%;\n }\n }\n\n .dev-tools-indicator-shortcut {\n display: flex;\n gap: 4px;\n\n kbd {\n width: var(--size-20);\n height: var(--size-20);\n display: flex;\n justify-content: center;\n align-items: center;\n border-radius: var(--rounded-md);\n border: 1px solid var(--color-gray-400);\n font-family: var(--font-stack-sans);\n background: var(--color-background-100);\n color: var(--color-gray-1000);\n text-align: center;\n font-size: var(--size-12);\n line-height: var(--size-16);\n }\n }\n";
//# sourceMappingURL=dev-tools-indicator.js.map

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,63 @@
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
import { useRef } from 'react';
import { MENU_DURATION_MS, useClickOutside, useFocusTrap } from '../utils';
import { useDelayedRender } from '../../../../hooks/use-delayed-render';
export function DevToolsInfo(param) {
let { title, children, learnMoreLink, isOpen, triggerRef, close, ...props } = param;
const ref = useRef(null);
const closeButtonRef = useRef(null);
const { mounted, rendered } = useDelayedRender(isOpen, {
// Intentionally no fade in, makes the UI feel more immediate
enterDelay: 0,
// Graceful fade out to confirm that the UI did not break
exitDelay: MENU_DURATION_MS
});
useFocusTrap(ref, triggerRef, isOpen, ()=>{
var // Bring focus to close button, so the user can easily close the overlay
_closeButtonRef_current;
(_closeButtonRef_current = closeButtonRef.current) == null ? void 0 : _closeButtonRef_current.focus();
});
useClickOutside(ref, triggerRef, isOpen, close);
if (!mounted) {
return null;
}
return /*#__PURE__*/ _jsx("div", {
tabIndex: -1,
role: "dialog",
ref: ref,
"data-info-popover": true,
...props,
"data-rendered": rendered,
children: /*#__PURE__*/ _jsxs("div", {
className: "dev-tools-info-container",
children: [
/*#__PURE__*/ _jsx("h1", {
className: "dev-tools-info-title",
children: title
}),
children,
/*#__PURE__*/ _jsxs("div", {
className: "dev-tools-info-button-container",
children: [
/*#__PURE__*/ _jsx("button", {
ref: closeButtonRef,
className: "dev-tools-info-close-button",
onClick: close,
children: "Close"
}),
learnMoreLink && /*#__PURE__*/ _jsx("a", {
className: "dev-tools-info-learn-more-button",
href: learnMoreLink,
target: "_blank",
rel: "noreferrer noopener",
children: "Learn More"
})
]
})
]
})
});
}
export const DEV_TOOLS_INFO_STYLES = "\n [data-info-popover] {\n -webkit-font-smoothing: antialiased;\n display: flex;\n flex-direction: column;\n align-items: flex-start;\n background: var(--color-background-100);\n border: 1px solid var(--color-gray-alpha-400);\n background-clip: padding-box;\n box-shadow: var(--shadow-menu);\n border-radius: var(--rounded-xl);\n position: absolute;\n font-family: var(--font-stack-sans);\n z-index: 1000;\n overflow: hidden;\n opacity: 0;\n outline: 0;\n min-width: 350px;\n transition: opacity var(--animate-out-duration-ms)\n var(--animate-out-timing-function);\n\n &[data-rendered='true'] {\n opacity: 1;\n scale: 1;\n }\n\n button:focus-visible {\n outline: var(--focus-ring);\n }\n }\n\n .dev-tools-info-container {\n padding: 12px;\n }\n\n .dev-tools-info-title {\n padding: 8px 6px;\n color: var(--color-gray-1000);\n font-size: var(--size-16);\n font-weight: 600;\n line-height: var(--size-20);\n margin: 0;\n }\n\n .dev-tools-info-article {\n padding: 8px 6px;\n color: var(--color-gray-1000);\n font-size: var(--size-14);\n line-height: var(--size-20);\n margin: 0;\n }\n .dev-tools-info-paragraph {\n &:last-child {\n margin-bottom: 0;\n }\n }\n\n .dev-tools-info-button-container {\n display: flex;\n justify-content: space-between;\n align-items: center;\n padding: 8px 6px;\n }\n\n .dev-tools-info-close-button {\n padding: 0 8px;\n height: var(--size-28);\n font-size: var(--size-14);\n font-weight: 500;\n line-height: var(--size-20);\n transition: background var(--duration-short) ease;\n color: var(--color-gray-1000);\n border-radius: var(--rounded-md-2);\n border: 1px solid var(--color-gray-alpha-400);\n background: var(--color-background-200);\n }\n\n .dev-tools-info-close-button:hover {\n background: var(--color-gray-400);\n }\n\n .dev-tools-info-learn-more-button {\n align-content: center;\n padding: 0 8px;\n height: var(--size-28);\n font-size: var(--size-14);\n font-weight: 500;\n line-height: var(--size-20);\n transition: background var(--duration-short) ease;\n color: var(--color-background-100);\n border-radius: var(--rounded-md-2);\n background: var(--color-gray-1000);\n }\n\n .dev-tools-info-learn-more-button:hover {\n text-decoration: none;\n color: var(--color-background-100);\n opacity: 0.9;\n }\n";
//# sourceMappingURL=dev-tools-info.js.map

View File

@@ -0,0 +1,148 @@
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
import { DevToolsInfo } from './dev-tools-info';
function StaticRouteContent(param) {
let { routerType } = param;
return /*#__PURE__*/ _jsxs("article", {
className: "dev-tools-info-article",
children: [
/*#__PURE__*/ _jsxs("p", {
className: "dev-tools-info-paragraph",
children: [
"The path",
' ',
/*#__PURE__*/ _jsx("code", {
className: "dev-tools-info-code",
children: window.location.pathname
}),
' ',
'is marked as "static" since it will be prerendered during the build time.'
]
}),
/*#__PURE__*/ _jsxs("p", {
className: "dev-tools-info-paragraph",
children: [
"With Static Rendering, routes are rendered at build time, or in the background after",
' ',
/*#__PURE__*/ _jsx("a", {
className: "dev-tools-info-link",
href: routerType === 'pages' ? 'https://nextjs.org/docs/pages/building-your-application/data-fetching/incremental-static-regeneration' : "https://nextjs.org/docs/app/building-your-application/data-fetching/incremental-static-regeneration",
target: "_blank",
rel: "noopener noreferrer",
children: "data revalidation"
}),
"."
]
}),
/*#__PURE__*/ _jsx("p", {
className: "dev-tools-info-paragraph",
children: "Static rendering is useful when a route has data that is not personalized to the user and can be known at build time, such as a static blog post or a product page."
})
]
});
}
function DynamicRouteContent(param) {
let { routerType } = param;
return /*#__PURE__*/ _jsxs("article", {
className: "dev-tools-info-article",
children: [
/*#__PURE__*/ _jsxs("p", {
className: "dev-tools-info-paragraph",
children: [
"The path",
' ',
/*#__PURE__*/ _jsx("code", {
className: "dev-tools-info-code",
children: window.location.pathname
}),
' ',
'is marked as "dynamic" since it will be rendered for each user at',
' ',
/*#__PURE__*/ _jsx("strong", {
children: "request time"
}),
"."
]
}),
/*#__PURE__*/ _jsx("p", {
className: "dev-tools-info-paragraph",
children: "Dynamic rendering is useful when a route has data that is personalized to the user or has information that can only be known at request time, such as cookies or the URL's search params."
}),
routerType === 'pages' ? /*#__PURE__*/ _jsxs("p", {
className: "dev-tools-info-pagraph",
children: [
"Exporting the",
' ',
/*#__PURE__*/ _jsx("a", {
className: "dev-tools-info-link",
href: "https://nextjs.org/docs/pages/building-your-application/data-fetching/get-server-side-props",
target: "_blank",
rel: "noopener noreferrer",
children: "getServerSideProps"
}),
' ',
"function will opt the route into dynamic rendering. This function will be called by the server on every request."
]
}) : /*#__PURE__*/ _jsxs("p", {
className: "dev-tools-info-paragraph",
children: [
"During rendering, if a",
' ',
/*#__PURE__*/ _jsx("a", {
className: "dev-tools-info-link",
href: "https://nextjs.org/docs/app/building-your-application/rendering/server-components#dynamic-apis",
target: "_blank",
rel: "noopener noreferrer",
children: "Dynamic API"
}),
' ',
"or a",
' ',
/*#__PURE__*/ _jsx("a", {
className: "dev-tools-info-link",
href: "https://nextjs.org/docs/app/api-reference/functions/fetch",
target: "_blank",
rel: "noopener noreferrer",
children: "fetch"
}),
' ',
"option of",
' ',
/*#__PURE__*/ _jsx("code", {
className: "dev-tools-info-code",
children: "{ cache: 'no-store' }"
}),
' ',
"is discovered, Next.js will switch to dynamically rendering the whole route."
]
})
]
});
}
const learnMoreLink = {
pages: {
static: 'https://nextjs.org/docs/pages/building-your-application/rendering/static-site-generation',
dynamic: 'https://nextjs.org/docs/pages/building-your-application/rendering/server-side-rendering'
},
app: {
static: 'https://nextjs.org/docs/app/building-your-application/rendering/server-components#static-rendering-default',
dynamic: 'https://nextjs.org/docs/app/building-your-application/rendering/server-components#dynamic-rendering'
}
};
export function RouteInfo(param) {
let { routeType, routerType, ...props } = param;
const isStaticRoute = routeType === 'Static';
const learnMore = isStaticRoute ? learnMoreLink[routerType].static : learnMoreLink[routerType].dynamic;
return /*#__PURE__*/ _jsx(DevToolsInfo, {
title: "" + routeType + " Route",
learnMoreLink: learnMore,
...props,
children: isStaticRoute ? /*#__PURE__*/ _jsx(StaticRouteContent, {
routerType: routerType
}) : /*#__PURE__*/ _jsx(DynamicRouteContent, {
routerType: routerType
})
});
}
export const DEV_TOOLS_INFO_ROUTE_INFO_STYLES = "";
//# sourceMappingURL=route-info.js.map

View File

@@ -0,0 +1,170 @@
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
import { DevToolsInfo } from './dev-tools-info';
import { CopyButton } from '../../../copy-button';
export function TurbopackInfo(props) {
return /*#__PURE__*/ _jsxs(DevToolsInfo, {
title: "Turbopack",
learnMoreLink: "https://nextjs.org/docs/app/api-reference/turbopack",
...props,
children: [
/*#__PURE__*/ _jsxs("article", {
className: "dev-tools-info-article",
children: [
/*#__PURE__*/ _jsxs("p", {
className: "dev-tools-info-paragraph",
children: [
"Turbopack is an incremental bundler optimized for JavaScript and TypeScript, written in Rust, and built into Next.js. Turbopack can be used in Next.js in both the",
' ',
/*#__PURE__*/ _jsx("code", {
className: "dev-tools-info-code",
children: "pages"
}),
" and",
' ',
/*#__PURE__*/ _jsx("code", {
className: "dev-tools-info-code",
children: "app"
}),
" directories for faster local development."
]
}),
/*#__PURE__*/ _jsxs("p", {
className: "dev-tools-info-paragraph",
children: [
"To enable Turbopack, use the",
' ',
/*#__PURE__*/ _jsx("code", {
className: "dev-tools-info-code",
children: "--turbopack"
}),
" flag when running the Next.js development server."
]
})
]
}),
/*#__PURE__*/ _jsx("div", {
className: "dev-tools-info-code-block-container",
children: /*#__PURE__*/ _jsxs("div", {
className: "dev-tools-info-code-block",
children: [
/*#__PURE__*/ _jsx(CopyButton, {
actionLabel: "Copy Next.js Turbopack Command",
successLabel: "Next.js Turbopack Command Copied",
content: '--turbopack',
className: "dev-tools-info-copy-button"
}),
/*#__PURE__*/ _jsx("pre", {
className: "dev-tools-info-code-block-pre",
children: /*#__PURE__*/ _jsxs("code", {
children: [
/*#__PURE__*/ _jsx("div", {
className: "dev-tools-info-code-block-line",
children: ' '
}),
/*#__PURE__*/ _jsx("div", {
className: "dev-tools-info-code-block-line",
children: '{'
}),
/*#__PURE__*/ _jsxs("div", {
className: "dev-tools-info-code-block-line",
children: [
' ',
/*#__PURE__*/ _jsx("span", {
className: "dev-tools-info-code-block-json-key",
children: '"scripts"'
}),
": ",
'{'
]
}),
/*#__PURE__*/ _jsxs("div", {
className: "dev-tools-info-code-block-line dev-tools-info-highlight",
children: [
' ',
/*#__PURE__*/ _jsx("span", {
className: "dev-tools-info-code-block-json-key",
children: '"dev"'
}),
":",
' ',
/*#__PURE__*/ _jsx("span", {
className: "dev-tools-info-code-block-json-value",
children: '"next dev --turbopack"'
}),
","
]
}),
/*#__PURE__*/ _jsxs("div", {
className: "dev-tools-info-code-block-line",
children: [
' ',
/*#__PURE__*/ _jsx("span", {
className: "dev-tools-info-code-block-json-key",
children: '"build"'
}),
":",
' ',
/*#__PURE__*/ _jsx("span", {
className: "dev-tools-info-code-block-json-value",
children: '"next build"'
}),
","
]
}),
/*#__PURE__*/ _jsxs("div", {
className: "dev-tools-info-code-block-line",
children: [
' ',
/*#__PURE__*/ _jsx("span", {
className: "dev-tools-info-code-block-json-key",
children: '"start"'
}),
":",
' ',
/*#__PURE__*/ _jsx("span", {
className: "dev-tools-info-code-block-json-value",
children: '"next start"'
}),
","
]
}),
/*#__PURE__*/ _jsxs("div", {
className: "dev-tools-info-code-block-line",
children: [
' ',
/*#__PURE__*/ _jsx("span", {
className: "dev-tools-info-code-block-json-key",
children: '"lint"'
}),
":",
' ',
/*#__PURE__*/ _jsx("span", {
className: "dev-tools-info-code-block-json-value",
children: '"next lint"'
})
]
}),
/*#__PURE__*/ _jsx("div", {
className: "dev-tools-info-code-block-line",
children: ' }'
}),
/*#__PURE__*/ _jsx("div", {
className: "dev-tools-info-code-block-line",
children: '}'
}),
/*#__PURE__*/ _jsx("div", {
className: "dev-tools-info-code-block-line",
children: ' '
})
]
})
})
]
})
})
]
});
}
export const DEV_TOOLS_INFO_TURBOPACK_INFO_STYLES = "\n .dev-tools-info-code {\n background: var(--color-gray-400);\n color: var(--color-gray-1000);\n font-family: var(--font-stack-monospace);\n padding: 2px 4px;\n margin: 0;\n font-size: var(--size-13);\n white-space: break-spaces;\n border-radius: var(--rounded-md-2);\n }\n\n .dev-tools-info-code-block-container {\n padding: 6px;\n }\n\n .dev-tools-info-code-block {\n position: relative;\n background: var(--color-background-200);\n border: 1px solid var(--color-gray-alpha-400);\n border-radius: var(--rounded-md-2);\n min-width: 326px;\n }\n\n .dev-tools-info-code-block-pre {\n margin: 0;\n font-family: var(--font-stack-monospace);\n font-size: var(--size-12);\n }\n\n .dev-tools-info-copy-button {\n position: absolute;\n\n display: flex;\n justify-content: center;\n align-items: center;\n right: 8px;\n top: 8px;\n padding: 4px;\n height: var(--size-24);\n width: var(--size-24);\n border-radius: var(--rounded-md-2);\n border: 1px solid var(--color-gray-alpha-400);\n background: var(--color-background-100);\n }\n\n .dev-tools-info-code-block-line {\n display: block;\n line-height: 1.5;\n padding: 0 16px;\n }\n\n .dev-tools-info-code-block-line.dev-tools-info-highlight {\n border-left: 2px solid var(--color-blue-900);\n background: var(--color-blue-400);\n }\n\n .dev-tools-info-code-block-json-key {\n color: var(--color-syntax-keyword);\n }\n\n .dev-tools-info-code-block-json-value {\n color: var(--color-syntax-link);\n }\n";
//# sourceMappingURL=turbopack-info.js.map

View File

@@ -0,0 +1,243 @@
import { _ as _tagged_template_literal_loose } from "@swc/helpers/_/_tagged_template_literal_loose";
function _templateObject() {
const data = _tagged_template_literal_loose([
"\n .preferences-container {\n padding: 8px 6px;\n width: 100%;\n }\n\n @media (min-width: 576px) {\n .preferences-container {\n width: 480px;\n }\n }\n\n .preference-section:first-child {\n padding-top: 0;\n }\n\n .preference-section {\n padding: 12px 0;\n border-bottom: 1px solid var(--color-gray-400);\n display: flex;\n justify-content: space-between;\n align-items: center;\n gap: 24px;\n }\n\n .preference-section:last-child {\n border-bottom: none;\n }\n\n .preference-header {\n margin-bottom: 0;\n flex: 1;\n }\n\n .preference-header label {\n font-size: var(--size-14);\n font-weight: 500;\n color: var(--color-gray-1000);\n margin: 0;\n }\n\n .preference-description {\n color: var(--color-gray-900);\n font-size: var(--size-14);\n margin: 0;\n }\n\n .preference-icon {\n display: flex;\n align-items: center;\n width: 16px;\n height: 16px;\n }\n\n .select-button,\n .action-button {\n display: flex;\n align-items: center;\n gap: 8px;\n background: var(--color-background-100);\n border: 1px solid var(--color-gray-400);\n border-radius: var(--rounded-lg);\n font-weight: 400;\n font-size: var(--size-14);\n color: var(--color-gray-1000);\n padding: 6px 8px;\n\n &:hover {\n background: var(--color-gray-100);\n }\n }\n\n .preference-control-select {\n padding: 6px 8px;\n display: flex;\n align-items: center;\n gap: 8px;\n border-radius: var(--rounded-lg);\n border: 1px solid var(--color-gray-400);\n\n &:hover {\n background: var(--color-gray-100);\n }\n\n &:focus-within {\n outline: var(--focus-ring);\n }\n }\n\n .preference-control-select select {\n font-size: var(--size-14);\n font-weight: 400;\n border: none;\n padding: 0 6px 0 0;\n border-radius: 0;\n outline: none;\n background: none;\n }\n\n :global(.icon) {\n width: 18px;\n height: 18px;\n color: #666;\n }\n"
]);
_templateObject = function() {
return data;
};
return data;
}
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
import { useState } from 'react';
import { css } from '../../../../../utils/css';
import EyeIcon from '../../../../icons/eye-icon';
import { STORAGE_KEY_POSITION, STORAGE_KEY_THEME } from '../../../../../shared';
import LightIcon from '../../../../icons/light-icon';
import DarkIcon from '../../../../icons/dark-icon';
import SystemIcon from '../../../../icons/system-icon';
import { DevToolsInfo } from './dev-tools-info';
function getInitialPreference() {
if (typeof localStorage === 'undefined') {
return 'system';
}
const theme = localStorage.getItem(STORAGE_KEY_THEME);
return theme === 'dark' || theme === 'light' ? theme : 'system';
}
export function UserPreferences(param) {
let { setPosition, position, hide, ...props } = param;
// derive initial theme from system preference
const [theme, setTheme] = useState(getInitialPreference());
const handleThemeChange = (e)=>{
const portal = document.querySelector('nextjs-portal');
if (!portal) return;
setTheme(e.target.value);
if (e.target.value === 'system') {
portal.classList.remove('dark');
portal.classList.remove('light');
localStorage.removeItem(STORAGE_KEY_THEME);
return;
}
if (e.target.value === 'dark') {
portal.classList.add('dark');
portal.classList.remove('light');
localStorage.setItem(STORAGE_KEY_THEME, 'dark');
} else {
portal.classList.remove('dark');
portal.classList.add('light');
localStorage.setItem(STORAGE_KEY_THEME, 'light');
}
};
function handlePositionChange(e) {
setPosition(e.target.value);
localStorage.setItem(STORAGE_KEY_POSITION, e.target.value);
}
return /*#__PURE__*/ _jsx(DevToolsInfo, {
title: "Preferences",
...props,
children: /*#__PURE__*/ _jsxs("div", {
className: "preferences-container",
children: [
/*#__PURE__*/ _jsxs("div", {
className: "preference-section",
children: [
/*#__PURE__*/ _jsxs("div", {
className: "preference-header",
children: [
/*#__PURE__*/ _jsx("label", {
htmlFor: "theme",
children: "Theme"
}),
/*#__PURE__*/ _jsx("p", {
className: "preference-description",
children: "Select your theme preference."
})
]
}),
/*#__PURE__*/ _jsxs("div", {
className: "preference-control-select",
children: [
/*#__PURE__*/ _jsx("div", {
className: "preference-icon",
children: /*#__PURE__*/ _jsx(ThemeIcon, {
theme: theme
})
}),
/*#__PURE__*/ _jsxs("select", {
id: "theme",
name: "theme",
className: "select-button",
value: theme,
onChange: handleThemeChange,
children: [
/*#__PURE__*/ _jsx("option", {
value: "system",
children: "System"
}),
/*#__PURE__*/ _jsx("option", {
value: "light",
children: "Light"
}),
/*#__PURE__*/ _jsx("option", {
value: "dark",
children: "Dark"
})
]
})
]
})
]
}),
/*#__PURE__*/ _jsxs("div", {
className: "preference-section",
children: [
/*#__PURE__*/ _jsxs("div", {
className: "preference-header",
children: [
/*#__PURE__*/ _jsx("label", {
htmlFor: "position",
children: "Position"
}),
/*#__PURE__*/ _jsx("p", {
className: "preference-description",
children: "Adjust the placement of your dev tools."
})
]
}),
/*#__PURE__*/ _jsx("div", {
className: "preference-control-select",
children: /*#__PURE__*/ _jsxs("select", {
id: "position",
name: "position",
className: "select-button",
value: position,
onChange: handlePositionChange,
children: [
/*#__PURE__*/ _jsx("option", {
value: "bottom-left",
children: "Bottom Left"
}),
/*#__PURE__*/ _jsx("option", {
value: "bottom-right",
children: "Bottom Right"
}),
/*#__PURE__*/ _jsx("option", {
value: "top-left",
children: "Top Left"
}),
/*#__PURE__*/ _jsx("option", {
value: "top-right",
children: "Top Right"
})
]
})
})
]
}),
/*#__PURE__*/ _jsxs("div", {
className: "preference-section",
children: [
/*#__PURE__*/ _jsxs("div", {
className: "preference-header",
children: [
/*#__PURE__*/ _jsx("label", {
htmlFor: "hide-dev-tools",
children: "Hide Dev Tools for this session"
}),
/*#__PURE__*/ _jsx("p", {
className: "preference-description",
children: "Hide Dev Tools until you restart your dev server, or 1 day."
})
]
}),
/*#__PURE__*/ _jsx("div", {
className: "preference-control",
children: /*#__PURE__*/ _jsxs("button", {
id: "hide-dev-tools",
name: "hide-dev-tools",
"data-hide-dev-tools": true,
className: "action-button",
onClick: hide,
children: [
/*#__PURE__*/ _jsx("div", {
className: "preference-icon",
children: /*#__PURE__*/ _jsx(EyeIcon, {})
}),
/*#__PURE__*/ _jsx("span", {
children: "Hide"
})
]
})
})
]
}),
/*#__PURE__*/ _jsx("div", {
className: "preference-section",
children: /*#__PURE__*/ _jsxs("div", {
className: "preference-header",
children: [
/*#__PURE__*/ _jsx("label", {
children: "Disable Dev Tools for this project"
}),
/*#__PURE__*/ _jsxs("p", {
className: "preference-description",
children: [
"To disable this UI completely, set",
' ',
/*#__PURE__*/ _jsx("code", {
className: "dev-tools-info-code",
children: "devIndicators: false"
}),
' ',
"in your ",
/*#__PURE__*/ _jsx("code", {
className: "dev-tools-info-code",
children: "next.config"
}),
' ',
"file."
]
})
]
})
})
]
})
});
}
function ThemeIcon(param) {
let { theme } = param;
switch(theme){
case 'system':
return /*#__PURE__*/ _jsx(SystemIcon, {});
case 'dark':
return /*#__PURE__*/ _jsx(DarkIcon, {});
case 'light':
return /*#__PURE__*/ _jsx(LightIcon, {});
default:
return null;
}
}
export const DEV_TOOLS_INFO_USER_PREFERENCES_STYLES = css(_templateObject());
//# sourceMappingURL=user-preferences.js.map

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,67 @@
import { useEffect, useRef, useState } from 'react';
/**
* A React hook that ensures a loading state persists
* at least up to the next multiple of a given interval (default: 750ms).
*
* For example, if you're done loading at 1200ms, it forces you to wait
* until 1500ms. If its 1800ms, it waits until 2250ms, etc.
*
* @param isLoadingTrigger - Boolean that triggers the loading state
* @param interval - The time interval multiple in ms (default: 750ms)
* @returns Current loading state that respects multiples of the interval
*/ export function useMinimumLoadingTimeMultiple(isLoadingTrigger, interval) {
if (interval === void 0) interval = 750;
const [isLoading, setIsLoading] = useState(false);
const loadStartTimeRef = useRef(null);
const timeoutIdRef = useRef(null);
useEffect(()=>{
// Clear any pending timeout to avoid overlap
if (timeoutIdRef.current) {
clearTimeout(timeoutIdRef.current);
timeoutIdRef.current = null;
}
if (isLoadingTrigger) {
// If we enter "loading" state, record start time if not already
if (loadStartTimeRef.current === null) {
loadStartTimeRef.current = Date.now();
}
setIsLoading(true);
} else {
// If we're exiting the "loading" state:
if (loadStartTimeRef.current === null) {
// No start time was recorded, so just stop loading immediately
setIsLoading(false);
} else {
// How long we've been "loading"
const timeDiff = Date.now() - loadStartTimeRef.current;
// Next multiple of `interval` after `timeDiff`
const nextMultiple = interval * Math.ceil(timeDiff / interval);
// Remaining time needed to reach that multiple
const remainingTime = nextMultiple - timeDiff;
if (remainingTime > 0) {
// If not yet at that multiple, schedule the final step
timeoutIdRef.current = setTimeout(()=>{
setIsLoading(false);
loadStartTimeRef.current = null;
}, remainingTime);
} else {
// We're already past the multiple boundary
setIsLoading(false);
loadStartTimeRef.current = null;
}
}
}
// Cleanup when effect is about to re-run or component unmounts
return ()=>{
if (timeoutIdRef.current) {
clearTimeout(timeoutIdRef.current);
}
};
}, [
isLoadingTrigger,
interval
]);
return isLoading;
}
//# sourceMappingURL=use-minimum-loading-time-multiple.js.map

View File

@@ -0,0 +1 @@
{"version":3,"sources":["../../../../../../../../src/client/components/react-dev-overlay/ui/components/errors/dev-tools-indicator/use-minimum-loading-time-multiple.tsx"],"sourcesContent":["import { useEffect, useRef, useState } from 'react'\n\n/**\n * A React hook that ensures a loading state persists\n * at least up to the next multiple of a given interval (default: 750ms).\n *\n * For example, if you're done loading at 1200ms, it forces you to wait\n * until 1500ms. If its 1800ms, it waits until 2250ms, etc.\n *\n * @param isLoadingTrigger - Boolean that triggers the loading state\n * @param interval - The time interval multiple in ms (default: 750ms)\n * @returns Current loading state that respects multiples of the interval\n */\nexport function useMinimumLoadingTimeMultiple(\n isLoadingTrigger: boolean,\n interval = 750\n) {\n const [isLoading, setIsLoading] = useState(false)\n const loadStartTimeRef = useRef<number | null>(null)\n const timeoutIdRef = useRef<NodeJS.Timeout | null>(null)\n\n useEffect(() => {\n // Clear any pending timeout to avoid overlap\n if (timeoutIdRef.current) {\n clearTimeout(timeoutIdRef.current)\n timeoutIdRef.current = null\n }\n\n if (isLoadingTrigger) {\n // If we enter \"loading\" state, record start time if not already\n if (loadStartTimeRef.current === null) {\n loadStartTimeRef.current = Date.now()\n }\n setIsLoading(true)\n } else {\n // If we're exiting the \"loading\" state:\n if (loadStartTimeRef.current === null) {\n // No start time was recorded, so just stop loading immediately\n setIsLoading(false)\n } else {\n // How long we've been \"loading\"\n const timeDiff = Date.now() - loadStartTimeRef.current\n\n // Next multiple of `interval` after `timeDiff`\n const nextMultiple = interval * Math.ceil(timeDiff / interval)\n\n // Remaining time needed to reach that multiple\n const remainingTime = nextMultiple - timeDiff\n\n if (remainingTime > 0) {\n // If not yet at that multiple, schedule the final step\n timeoutIdRef.current = setTimeout(() => {\n setIsLoading(false)\n loadStartTimeRef.current = null\n }, remainingTime)\n } else {\n // We're already past the multiple boundary\n setIsLoading(false)\n loadStartTimeRef.current = null\n }\n }\n }\n\n // Cleanup when effect is about to re-run or component unmounts\n return () => {\n if (timeoutIdRef.current) {\n clearTimeout(timeoutIdRef.current)\n }\n }\n }, [isLoadingTrigger, interval])\n\n return isLoading\n}\n"],"names":["useEffect","useRef","useState","useMinimumLoadingTimeMultiple","isLoadingTrigger","interval","isLoading","setIsLoading","loadStartTimeRef","timeoutIdRef","current","clearTimeout","Date","now","timeDiff","nextMultiple","Math","ceil","remainingTime","setTimeout"],"mappings":"AAAA,SAASA,SAAS,EAAEC,MAAM,EAAEC,QAAQ,QAAQ,QAAO;AAEnD;;;;;;;;;;CAUC,GACD,OAAO,SAASC,8BACdC,gBAAyB,EACzBC,QAAc;IAAdA,IAAAA,qBAAAA,WAAW;IAEX,MAAM,CAACC,WAAWC,aAAa,GAAGL,SAAS;IAC3C,MAAMM,mBAAmBP,OAAsB;IAC/C,MAAMQ,eAAeR,OAA8B;IAEnDD,UAAU;QACR,6CAA6C;QAC7C,IAAIS,aAAaC,OAAO,EAAE;YACxBC,aAAaF,aAAaC,OAAO;YACjCD,aAAaC,OAAO,GAAG;QACzB;QAEA,IAAIN,kBAAkB;YACpB,gEAAgE;YAChE,IAAII,iBAAiBE,OAAO,KAAK,MAAM;gBACrCF,iBAAiBE,OAAO,GAAGE,KAAKC,GAAG;YACrC;YACAN,aAAa;QACf,OAAO;YACL,wCAAwC;YACxC,IAAIC,iBAAiBE,OAAO,KAAK,MAAM;gBACrC,+DAA+D;gBAC/DH,aAAa;YACf,OAAO;gBACL,gCAAgC;gBAChC,MAAMO,WAAWF,KAAKC,GAAG,KAAKL,iBAAiBE,OAAO;gBAEtD,+CAA+C;gBAC/C,MAAMK,eAAeV,WAAWW,KAAKC,IAAI,CAACH,WAAWT;gBAErD,+CAA+C;gBAC/C,MAAMa,gBAAgBH,eAAeD;gBAErC,IAAII,gBAAgB,GAAG;oBACrB,uDAAuD;oBACvDT,aAAaC,OAAO,GAAGS,WAAW;wBAChCZ,aAAa;wBACbC,iBAAiBE,OAAO,GAAG;oBAC7B,GAAGQ;gBACL,OAAO;oBACL,2CAA2C;oBAC3CX,aAAa;oBACbC,iBAAiBE,OAAO,GAAG;gBAC7B;YACF;QACF;QAEA,+DAA+D;QAC/D,OAAO;YACL,IAAID,aAAaC,OAAO,EAAE;gBACxBC,aAAaF,aAAaC,OAAO;YACnC;QACF;IACF,GAAG;QAACN;QAAkBC;KAAS;IAE/B,OAAOC;AACT"}

View File

@@ -0,0 +1,97 @@
import { useEffect } from 'react';
export function useFocusTrap(rootRef, triggerRef, active, onOpenFocus) {
useEffect(()=>{
let rootNode = null;
function onTab(e) {
if (e.key !== 'Tab' || rootNode === null) {
return;
}
const [firstFocusableNode, lastFocusableNode] = getFocusableNodes(rootNode);
const activeElement = getActiveElement(rootNode);
if (e.shiftKey) {
if (activeElement === firstFocusableNode) {
lastFocusableNode == null ? void 0 : lastFocusableNode.focus();
e.preventDefault();
}
} else {
if (activeElement === lastFocusableNode) {
firstFocusableNode == null ? void 0 : firstFocusableNode.focus();
e.preventDefault();
}
}
}
const id = setTimeout(()=>{
// Grab this on next tick to ensure the content is mounted
rootNode = rootRef.current;
if (active) {
if (onOpenFocus) {
onOpenFocus();
} else {
rootNode == null ? void 0 : rootNode.focus();
}
rootNode == null ? void 0 : rootNode.addEventListener('keydown', onTab);
} else {
const activeElement = getActiveElement(rootNode);
// Only restore focus if the focus was previously on the content.
// This avoids us accidentally focusing on mount when the
// user could want to interact with their own app instead.
if (triggerRef && (rootNode == null ? void 0 : rootNode.contains(activeElement))) {
var _triggerRef_current;
(_triggerRef_current = triggerRef.current) == null ? void 0 : _triggerRef_current.focus();
}
}
});
return ()=>{
clearTimeout(id);
rootNode == null ? void 0 : rootNode.removeEventListener('keydown', onTab);
};
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [
active
]);
}
function getActiveElement(node) {
const root = node == null ? void 0 : node.getRootNode();
return root instanceof ShadowRoot ? root == null ? void 0 : root.activeElement : null;
}
function getFocusableNodes(node) {
const focusableElements = node.querySelectorAll('button, [href], input, select, textarea, [tabindex]:not([tabindex="-1"])');
if (!focusableElements) return [];
return [
focusableElements[0],
focusableElements[focusableElements.length - 1]
];
}
//////////////////////////////////////////////////////////////////////////////////////
export function useClickOutside(rootRef, triggerRef, active, close) {
useEffect(()=>{
if (!active) {
return;
}
function handleClickOutside(event) {
var _rootRef_current, _triggerRef_current;
if (!(((_rootRef_current = rootRef.current) == null ? void 0 : _rootRef_current.getBoundingClientRect()) ? event.clientX >= rootRef.current.getBoundingClientRect().left && event.clientX <= rootRef.current.getBoundingClientRect().right && event.clientY >= rootRef.current.getBoundingClientRect().top && event.clientY <= rootRef.current.getBoundingClientRect().bottom : false) && !(((_triggerRef_current = triggerRef.current) == null ? void 0 : _triggerRef_current.getBoundingClientRect()) ? event.clientX >= triggerRef.current.getBoundingClientRect().left && event.clientX <= triggerRef.current.getBoundingClientRect().right && event.clientY >= triggerRef.current.getBoundingClientRect().top && event.clientY <= triggerRef.current.getBoundingClientRect().bottom : false)) {
close();
}
}
function handleKeyDown(event) {
if (event.key === 'Escape') {
close();
}
}
document.addEventListener('mousedown', handleClickOutside);
document.addEventListener('keydown', handleKeyDown);
return ()=>{
document.removeEventListener('mousedown', handleClickOutside);
document.removeEventListener('keydown', handleKeyDown);
};
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [
active
]);
}
//////////////////////////////////////////////////////////////////////////////////////
export const MENU_DURATION_MS = 200;
export const MENU_CURVE = 'cubic-bezier(0.175, 0.885, 0.32, 1.1)';
//# sourceMappingURL=utils.js.map

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,12 @@
import { jsx as _jsx } from "react/jsx-runtime";
import { DialogBody } from '../../dialog';
export function ErrorOverlayDialogBody(param) {
let { children } = param;
return /*#__PURE__*/ _jsx(DialogBody, {
className: "nextjs-container-errors-body",
children: children
});
}
export const DIALOG_BODY_STYLES = "";
//# sourceMappingURL=body.js.map

View File

@@ -0,0 +1 @@
{"version":3,"sources":["../../../../../../../../src/client/components/react-dev-overlay/ui/components/errors/dialog/body.tsx"],"sourcesContent":["import { DialogBody } from '../../dialog'\n\ntype ErrorOverlayDialogBodyProps = {\n children?: React.ReactNode\n onClose?: () => void\n}\n\nexport function ErrorOverlayDialogBody({\n children,\n}: ErrorOverlayDialogBodyProps) {\n return (\n <DialogBody className=\"nextjs-container-errors-body\">{children}</DialogBody>\n )\n}\n\nexport const DIALOG_BODY_STYLES = ``\n"],"names":["DialogBody","ErrorOverlayDialogBody","children","className","DIALOG_BODY_STYLES"],"mappings":";AAAA,SAASA,UAAU,QAAQ,eAAc;AAOzC,OAAO,SAASC,uBAAuB,KAET;IAFS,IAAA,EACrCC,QAAQ,EACoB,GAFS;IAGrC,qBACE,KAACF;QAAWG,WAAU;kBAAgCD;;AAE1D;AAEA,OAAO,MAAME,qBAAsB,GAAC"}

View File

@@ -0,0 +1,17 @@
import { jsx as _jsx } from "react/jsx-runtime";
import { Dialog } from '../../dialog/dialog';
export function ErrorOverlayDialog(param) {
let { children, onClose, ...props } = param;
return /*#__PURE__*/ _jsx(Dialog, {
type: "error",
"aria-labelledby": "nextjs__container_errors_label",
"aria-describedby": "nextjs__container_errors_desc",
onClose: onClose,
className: "error-overlay-dialog",
...props,
children: children
});
}
export const DIALOG_STYLES = "\n .error-overlay-dialog {\n overflow-y: auto;\n -webkit-font-smoothing: antialiased;\n background: var(--color-background-100);\n background-clip: padding-box;\n border: 1px solid var(--color-gray-400);\n border-radius: var(--rounded-xl);\n box-shadow: var(--shadow-menu);\n position: relative;\n\n &:has(\n ~ [data-nextjs-error-overlay-nav] .error-overlay-notch[data-side='left']\n ) {\n border-top-left-radius: 0;\n }\n\n &:has(\n ~ [data-nextjs-error-overlay-nav]\n .error-overlay-notch[data-side='right']\n ) {\n border-top-right-radius: 0;\n }\n }\n";
//# sourceMappingURL=dialog.js.map

View File

@@ -0,0 +1 @@
{"version":3,"sources":["../../../../../../../../src/client/components/react-dev-overlay/ui/components/errors/dialog/dialog.tsx"],"sourcesContent":["import { Dialog } from '../../dialog/dialog'\n\ntype ErrorOverlayDialogProps = {\n children?: React.ReactNode\n onClose?: () => void\n dialogResizerRef?: React.RefObject<HTMLDivElement | null>\n}\n\nexport function ErrorOverlayDialog({\n children,\n onClose,\n ...props\n}: ErrorOverlayDialogProps) {\n return (\n <Dialog\n type=\"error\"\n aria-labelledby=\"nextjs__container_errors_label\"\n aria-describedby=\"nextjs__container_errors_desc\"\n onClose={onClose}\n className=\"error-overlay-dialog\"\n {...props}\n >\n {children}\n </Dialog>\n )\n}\n\nexport const DIALOG_STYLES = `\n .error-overlay-dialog {\n overflow-y: auto;\n -webkit-font-smoothing: antialiased;\n background: var(--color-background-100);\n background-clip: padding-box;\n border: 1px solid var(--color-gray-400);\n border-radius: var(--rounded-xl);\n box-shadow: var(--shadow-menu);\n position: relative;\n\n &:has(\n ~ [data-nextjs-error-overlay-nav] .error-overlay-notch[data-side='left']\n ) {\n border-top-left-radius: 0;\n }\n\n &:has(\n ~ [data-nextjs-error-overlay-nav]\n .error-overlay-notch[data-side='right']\n ) {\n border-top-right-radius: 0;\n }\n }\n`\n"],"names":["Dialog","ErrorOverlayDialog","children","onClose","props","type","aria-labelledby","aria-describedby","className","DIALOG_STYLES"],"mappings":";AAAA,SAASA,MAAM,QAAQ,sBAAqB;AAQ5C,OAAO,SAASC,mBAAmB,KAIT;IAJS,IAAA,EACjCC,QAAQ,EACRC,OAAO,EACP,GAAGC,OACqB,GAJS;IAKjC,qBACE,KAACJ;QACCK,MAAK;QACLC,mBAAgB;QAChBC,oBAAiB;QACjBJ,SAASA;QACTK,WAAU;QACT,GAAGJ,KAAK;kBAERF;;AAGP;AAEA,OAAO,MAAMO,gBAAiB,+nBAwB7B"}

View File

@@ -0,0 +1,12 @@
import { jsx as _jsx } from "react/jsx-runtime";
import { DialogHeader } from '../../dialog/dialog-header';
export function ErrorOverlayDialogHeader(param) {
let { children } = param;
return /*#__PURE__*/ _jsx(DialogHeader, {
className: "nextjs-container-errors-header",
children: children
});
}
export const DIALOG_HEADER_STYLES = "\n .nextjs-container-errors-header {\n position: relative;\n }\n .nextjs-container-errors-header > h1 {\n font-size: var(--size-20);\n line-height: var(--size-24);\n font-weight: bold;\n margin: calc(16px * 1.5) 0;\n color: var(--color-title-h1);\n }\n .nextjs-container-errors-header small {\n font-size: var(--size-14);\n color: var(--color-accents-1);\n margin-left: 16px;\n }\n .nextjs-container-errors-header small > span {\n font-family: var(--font-stack-monospace);\n }\n .nextjs-container-errors-header > div > small {\n margin: 0;\n margin-top: 4px;\n }\n .nextjs-container-errors-header > p > a {\n color: inherit;\n font-weight: bold;\n }\n .nextjs-container-errors-header\n > .nextjs-container-build-error-version-status {\n position: absolute;\n top: 16px;\n right: 16px;\n }\n";
//# sourceMappingURL=header.js.map

View File

@@ -0,0 +1 @@
{"version":3,"sources":["../../../../../../../../src/client/components/react-dev-overlay/ui/components/errors/dialog/header.tsx"],"sourcesContent":["import { DialogHeader } from '../../dialog/dialog-header'\n\ntype ErrorOverlayDialogHeaderProps = {\n children?: React.ReactNode\n}\n\nexport function ErrorOverlayDialogHeader({\n children,\n}: ErrorOverlayDialogHeaderProps) {\n return (\n <DialogHeader className=\"nextjs-container-errors-header\">\n {children}\n </DialogHeader>\n )\n}\n\nexport const DIALOG_HEADER_STYLES = `\n .nextjs-container-errors-header {\n position: relative;\n }\n .nextjs-container-errors-header > h1 {\n font-size: var(--size-20);\n line-height: var(--size-24);\n font-weight: bold;\n margin: calc(16px * 1.5) 0;\n color: var(--color-title-h1);\n }\n .nextjs-container-errors-header small {\n font-size: var(--size-14);\n color: var(--color-accents-1);\n margin-left: 16px;\n }\n .nextjs-container-errors-header small > span {\n font-family: var(--font-stack-monospace);\n }\n .nextjs-container-errors-header > div > small {\n margin: 0;\n margin-top: 4px;\n }\n .nextjs-container-errors-header > p > a {\n color: inherit;\n font-weight: bold;\n }\n .nextjs-container-errors-header\n > .nextjs-container-build-error-version-status {\n position: absolute;\n top: 16px;\n right: 16px;\n }\n`\n"],"names":["DialogHeader","ErrorOverlayDialogHeader","children","className","DIALOG_HEADER_STYLES"],"mappings":";AAAA,SAASA,YAAY,QAAQ,6BAA4B;AAMzD,OAAO,SAASC,yBAAyB,KAET;IAFS,IAAA,EACvCC,QAAQ,EACsB,GAFS;IAGvC,qBACE,KAACF;QAAaG,WAAU;kBACrBD;;AAGP;AAEA,OAAO,MAAME,uBAAwB,61BAiCpC"}

View File

@@ -0,0 +1,11 @@
import { jsx as _jsx } from "react/jsx-runtime";
export function EnvironmentNameLabel(param) {
let { environmentName } = param;
return /*#__PURE__*/ _jsx("span", {
"data-nextjs-environment-name-label": true,
children: environmentName
});
}
export const ENVIRONMENT_NAME_LABEL_STYLES = "\n [data-nextjs-environment-name-label] {\n padding: 2px 6px;\n margin: 0;\n border-radius: var(--rounded-md-2);\n background: var(--color-gray-100);\n font-weight: 600;\n font-size: var(--size-12);\n color: var(--color-gray-900);\n font-family: var(--font-stack-monospace);\n line-height: var(--size-20);\n }\n";
//# sourceMappingURL=environment-name-label.js.map

View File

@@ -0,0 +1 @@
{"version":3,"sources":["../../../../../../../../src/client/components/react-dev-overlay/ui/components/errors/environment-name-label/environment-name-label.tsx"],"sourcesContent":["export function EnvironmentNameLabel({\n environmentName,\n}: {\n environmentName: string\n}) {\n return <span data-nextjs-environment-name-label>{environmentName}</span>\n}\n\nexport const ENVIRONMENT_NAME_LABEL_STYLES = `\n [data-nextjs-environment-name-label] {\n padding: 2px 6px;\n margin: 0;\n border-radius: var(--rounded-md-2);\n background: var(--color-gray-100);\n font-weight: 600;\n font-size: var(--size-12);\n color: var(--color-gray-900);\n font-family: var(--font-stack-monospace);\n line-height: var(--size-20);\n }\n`\n"],"names":["EnvironmentNameLabel","environmentName","span","data-nextjs-environment-name-label","ENVIRONMENT_NAME_LABEL_STYLES"],"mappings":";AAAA,OAAO,SAASA,qBAAqB,KAIpC;IAJoC,IAAA,EACnCC,eAAe,EAGhB,GAJoC;IAKnC,qBAAO,KAACC;QAAKC,oCAAkC;kBAAEF;;AACnD;AAEA,OAAO,MAAMG,gCAAiC,uVAY7C"}

View File

@@ -0,0 +1,43 @@
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
import { useState, useRef, useLayoutEffect } from 'react';
export function ErrorMessage(param) {
let { errorMessage } = param;
const [isExpanded, setIsExpanded] = useState(false);
const [shouldTruncate, setShouldTruncate] = useState(false);
const messageRef = useRef(null);
useLayoutEffect(()=>{
if (messageRef.current) {
setShouldTruncate(messageRef.current.scrollHeight > 200);
}
}, [
errorMessage
]);
return /*#__PURE__*/ _jsxs("div", {
className: "nextjs__container_errors_wrapper",
children: [
/*#__PURE__*/ _jsx("p", {
ref: messageRef,
id: "nextjs__container_errors_desc",
className: "nextjs__container_errors_desc " + (shouldTruncate && !isExpanded ? 'truncated' : ''),
children: errorMessage
}),
shouldTruncate && !isExpanded && /*#__PURE__*/ _jsxs(_Fragment, {
children: [
/*#__PURE__*/ _jsx("div", {
className: "nextjs__container_errors_gradient_overlay"
}),
/*#__PURE__*/ _jsx("button", {
onClick: ()=>setIsExpanded(true),
className: "nextjs__container_errors_expand_button",
"aria-expanded": isExpanded,
"aria-controls": "nextjs__container_errors_desc",
children: "Show More"
})
]
})
]
});
}
export const styles = "\n .nextjs__container_errors_wrapper {\n position: relative;\n }\n\n .nextjs__container_errors_desc {\n margin: 0;\n margin-left: 4px;\n color: var(--color-red-900);\n font-weight: 500;\n font-size: var(--size-16);\n letter-spacing: -0.32px;\n line-height: var(--size-24);\n overflow-wrap: break-word;\n white-space: pre-wrap;\n }\n\n .nextjs__container_errors_desc.truncated {\n max-height: 200px;\n overflow: hidden;\n }\n\n .nextjs__container_errors_gradient_overlay {\n position: absolute;\n bottom: 0;\n left: 0;\n right: 0;\n height: 85px;\n background: linear-gradient(\n 180deg,\n rgba(250, 250, 250, 0) 0%,\n var(--color-background-100) 100%\n );\n }\n\n .nextjs__container_errors_expand_button {\n position: absolute;\n bottom: 10px;\n left: 50%;\n transform: translateX(-50%);\n display: flex;\n align-items: center;\n padding: 6px 8px;\n background: var(--color-background-100);\n border: 1px solid var(--color-gray-alpha-400);\n border-radius: 999px;\n box-shadow:\n 0px 2px 2px var(--color-gray-alpha-100),\n 0px 8px 8px -8px var(--color-gray-alpha-100);\n font-size: var(--size-13);\n cursor: pointer;\n color: var(--color-gray-900);\n font-weight: 500;\n transition: background-color 0.2s ease;\n }\n\n .nextjs__container_errors_expand_button:hover {\n background: var(--color-gray-100);\n }\n";
//# sourceMappingURL=error-message.js.map

View File

@@ -0,0 +1 @@
{"version":3,"sources":["../../../../../../../../src/client/components/react-dev-overlay/ui/components/errors/error-message/error-message.tsx"],"sourcesContent":["import { useState, useRef, useLayoutEffect } from 'react'\n\nexport type ErrorMessageType = React.ReactNode\n\ntype ErrorMessageProps = {\n errorMessage: ErrorMessageType\n}\n\nexport function ErrorMessage({ errorMessage }: ErrorMessageProps) {\n const [isExpanded, setIsExpanded] = useState(false)\n const [shouldTruncate, setShouldTruncate] = useState(false)\n const messageRef = useRef<HTMLParagraphElement>(null)\n\n useLayoutEffect(() => {\n if (messageRef.current) {\n setShouldTruncate(messageRef.current.scrollHeight > 200)\n }\n }, [errorMessage])\n\n return (\n <div className=\"nextjs__container_errors_wrapper\">\n <p\n ref={messageRef}\n id=\"nextjs__container_errors_desc\"\n className={`nextjs__container_errors_desc ${shouldTruncate && !isExpanded ? 'truncated' : ''}`}\n >\n {errorMessage}\n </p>\n {shouldTruncate && !isExpanded && (\n <>\n <div className=\"nextjs__container_errors_gradient_overlay\" />\n <button\n onClick={() => setIsExpanded(true)}\n className=\"nextjs__container_errors_expand_button\"\n aria-expanded={isExpanded}\n aria-controls=\"nextjs__container_errors_desc\"\n >\n Show More\n </button>\n </>\n )}\n </div>\n )\n}\n\nexport const styles = `\n .nextjs__container_errors_wrapper {\n position: relative;\n }\n\n .nextjs__container_errors_desc {\n margin: 0;\n margin-left: 4px;\n color: var(--color-red-900);\n font-weight: 500;\n font-size: var(--size-16);\n letter-spacing: -0.32px;\n line-height: var(--size-24);\n overflow-wrap: break-word;\n white-space: pre-wrap;\n }\n\n .nextjs__container_errors_desc.truncated {\n max-height: 200px;\n overflow: hidden;\n }\n\n .nextjs__container_errors_gradient_overlay {\n position: absolute;\n bottom: 0;\n left: 0;\n right: 0;\n height: 85px;\n background: linear-gradient(\n 180deg,\n rgba(250, 250, 250, 0) 0%,\n var(--color-background-100) 100%\n );\n }\n\n .nextjs__container_errors_expand_button {\n position: absolute;\n bottom: 10px;\n left: 50%;\n transform: translateX(-50%);\n display: flex;\n align-items: center;\n padding: 6px 8px;\n background: var(--color-background-100);\n border: 1px solid var(--color-gray-alpha-400);\n border-radius: 999px;\n box-shadow:\n 0px 2px 2px var(--color-gray-alpha-100),\n 0px 8px 8px -8px var(--color-gray-alpha-100);\n font-size: var(--size-13);\n cursor: pointer;\n color: var(--color-gray-900);\n font-weight: 500;\n transition: background-color 0.2s ease;\n }\n\n .nextjs__container_errors_expand_button:hover {\n background: var(--color-gray-100);\n }\n`\n"],"names":["useState","useRef","useLayoutEffect","ErrorMessage","errorMessage","isExpanded","setIsExpanded","shouldTruncate","setShouldTruncate","messageRef","current","scrollHeight","div","className","p","ref","id","button","onClick","aria-expanded","aria-controls","styles"],"mappings":";AAAA,SAASA,QAAQ,EAAEC,MAAM,EAAEC,eAAe,QAAQ,QAAO;AAQzD,OAAO,SAASC,aAAa,KAAmC;IAAnC,IAAA,EAAEC,YAAY,EAAqB,GAAnC;IAC3B,MAAM,CAACC,YAAYC,cAAc,GAAGN,SAAS;IAC7C,MAAM,CAACO,gBAAgBC,kBAAkB,GAAGR,SAAS;IACrD,MAAMS,aAAaR,OAA6B;IAEhDC,gBAAgB;QACd,IAAIO,WAAWC,OAAO,EAAE;YACtBF,kBAAkBC,WAAWC,OAAO,CAACC,YAAY,GAAG;QACtD;IACF,GAAG;QAACP;KAAa;IAEjB,qBACE,MAACQ;QAAIC,WAAU;;0BACb,KAACC;gBACCC,KAAKN;gBACLO,IAAG;gBACHH,WAAW,AAAC,mCAAgCN,CAAAA,kBAAkB,CAACF,aAAa,cAAc,EAAC;0BAE1FD;;YAEFG,kBAAkB,CAACF,4BAClB;;kCACE,KAACO;wBAAIC,WAAU;;kCACf,KAACI;wBACCC,SAAS,IAAMZ,cAAc;wBAC7BO,WAAU;wBACVM,iBAAed;wBACfe,iBAAc;kCACf;;;;;;AAOX;AAEA,OAAO,MAAMC,SAAU,i7CA2DtB"}

View File

@@ -0,0 +1,27 @@
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
export function ErrorOverlayBottomStack(param) {
let { errorCount, activeIdx } = param;
// If there are more than 2 errors to navigate, the stack count should remain at 2.
const stackCount = Math.min(errorCount - activeIdx - 1, 2);
return /*#__PURE__*/ _jsx("div", {
"aria-hidden": true,
className: "error-overlay-bottom-stack",
children: /*#__PURE__*/ _jsxs("div", {
className: "error-overlay-bottom-stack-stack",
"data-stack-count": stackCount,
children: [
/*#__PURE__*/ _jsx("div", {
className: "error-overlay-bottom-stack-layer error-overlay-bottom-stack-layer-1",
children: "1"
}),
/*#__PURE__*/ _jsx("div", {
className: "error-overlay-bottom-stack-layer error-overlay-bottom-stack-layer-2",
children: "2"
})
]
})
});
}
export const styles = "\n .error-overlay-bottom-stack-layer {\n width: 100%;\n height: var(--stack-layer-height);\n position: relative;\n border: 1px solid var(--color-gray-400);\n border-radius: var(--rounded-xl);\n background: var(--color-background-200);\n transition:\n translate 350ms var(--timing-swift),\n box-shadow 350ms var(--timing-swift);\n }\n\n .error-overlay-bottom-stack-layer-1 {\n width: calc(100% - var(--size-24));\n }\n\n .error-overlay-bottom-stack-layer-2 {\n width: calc(100% - var(--size-48));\n z-index: -1;\n }\n\n .error-overlay-bottom-stack {\n width: 100%;\n position: absolute;\n bottom: -1px;\n height: 0;\n overflow: visible;\n }\n\n .error-overlay-bottom-stack-stack {\n --stack-layer-height: 44px;\n --stack-layer-height-half: calc(var(--stack-layer-height) / 2);\n --stack-layer-trim: 13px;\n --shadow: 0px 0.925px 0.925px 0px rgba(0, 0, 0, 0.02),\n 0px 3.7px 7.4px -3.7px rgba(0, 0, 0, 0.04),\n 0px 14.8px 22.2px -7.4px rgba(0, 0, 0, 0.06);\n\n display: grid;\n place-items: center center;\n width: 100%;\n position: fixed;\n overflow: hidden;\n z-index: -1;\n max-width: var(--next-dialog-max-width);\n\n .error-overlay-bottom-stack-layer {\n grid-area: 1 / 1;\n /* Hide */\n translate: 0 calc(var(--stack-layer-height) * -1);\n }\n\n &[data-stack-count='1'],\n &[data-stack-count='2'] {\n .error-overlay-bottom-stack-layer-1 {\n translate: 0\n calc(var(--stack-layer-height-half) * -1 - var(--stack-layer-trim));\n }\n }\n\n &[data-stack-count='2'] {\n .error-overlay-bottom-stack-layer-2 {\n translate: 0 calc(var(--stack-layer-trim) * -1 * 2);\n }\n }\n\n /* Only the bottom stack should have the shadow */\n &[data-stack-count='1'] .error-overlay-bottom-stack-layer-1 {\n box-shadow: var(--shadow);\n }\n\n &[data-stack-count='2'] {\n .error-overlay-bottom-stack-layer-2 {\n box-shadow: var(--shadow);\n }\n }\n }\n";
//# sourceMappingURL=index.js.map

View File

@@ -0,0 +1 @@
{"version":3,"sources":["../../../../../../../../src/client/components/react-dev-overlay/ui/components/errors/error-overlay-bottom-stack/index.tsx"],"sourcesContent":["export function ErrorOverlayBottomStack({\n errorCount,\n activeIdx,\n}: {\n errorCount: number\n activeIdx: number\n}) {\n // If there are more than 2 errors to navigate, the stack count should remain at 2.\n const stackCount = Math.min(errorCount - activeIdx - 1, 2)\n return (\n <div aria-hidden className=\"error-overlay-bottom-stack\">\n <div\n className=\"error-overlay-bottom-stack-stack\"\n data-stack-count={stackCount}\n >\n <div className=\"error-overlay-bottom-stack-layer error-overlay-bottom-stack-layer-1\">\n 1\n </div>\n <div className=\"error-overlay-bottom-stack-layer error-overlay-bottom-stack-layer-2\">\n 2\n </div>\n </div>\n </div>\n )\n}\n\nexport const styles = `\n .error-overlay-bottom-stack-layer {\n width: 100%;\n height: var(--stack-layer-height);\n position: relative;\n border: 1px solid var(--color-gray-400);\n border-radius: var(--rounded-xl);\n background: var(--color-background-200);\n transition:\n translate 350ms var(--timing-swift),\n box-shadow 350ms var(--timing-swift);\n }\n\n .error-overlay-bottom-stack-layer-1 {\n width: calc(100% - var(--size-24));\n }\n\n .error-overlay-bottom-stack-layer-2 {\n width: calc(100% - var(--size-48));\n z-index: -1;\n }\n\n .error-overlay-bottom-stack {\n width: 100%;\n position: absolute;\n bottom: -1px;\n height: 0;\n overflow: visible;\n }\n\n .error-overlay-bottom-stack-stack {\n --stack-layer-height: 44px;\n --stack-layer-height-half: calc(var(--stack-layer-height) / 2);\n --stack-layer-trim: 13px;\n --shadow: 0px 0.925px 0.925px 0px rgba(0, 0, 0, 0.02),\n 0px 3.7px 7.4px -3.7px rgba(0, 0, 0, 0.04),\n 0px 14.8px 22.2px -7.4px rgba(0, 0, 0, 0.06);\n\n display: grid;\n place-items: center center;\n width: 100%;\n position: fixed;\n overflow: hidden;\n z-index: -1;\n max-width: var(--next-dialog-max-width);\n\n .error-overlay-bottom-stack-layer {\n grid-area: 1 / 1;\n /* Hide */\n translate: 0 calc(var(--stack-layer-height) * -1);\n }\n\n &[data-stack-count='1'],\n &[data-stack-count='2'] {\n .error-overlay-bottom-stack-layer-1 {\n translate: 0\n calc(var(--stack-layer-height-half) * -1 - var(--stack-layer-trim));\n }\n }\n\n &[data-stack-count='2'] {\n .error-overlay-bottom-stack-layer-2 {\n translate: 0 calc(var(--stack-layer-trim) * -1 * 2);\n }\n }\n\n /* Only the bottom stack should have the shadow */\n &[data-stack-count='1'] .error-overlay-bottom-stack-layer-1 {\n box-shadow: var(--shadow);\n }\n\n &[data-stack-count='2'] {\n .error-overlay-bottom-stack-layer-2 {\n box-shadow: var(--shadow);\n }\n }\n }\n`\n"],"names":["ErrorOverlayBottomStack","errorCount","activeIdx","stackCount","Math","min","div","aria-hidden","className","data-stack-count","styles"],"mappings":";AAAA,OAAO,SAASA,wBAAwB,KAMvC;IANuC,IAAA,EACtCC,UAAU,EACVC,SAAS,EAIV,GANuC;IAOtC,mFAAmF;IACnF,MAAMC,aAAaC,KAAKC,GAAG,CAACJ,aAAaC,YAAY,GAAG;IACxD,qBACE,KAACI;QAAIC,aAAW;QAACC,WAAU;kBACzB,cAAA,MAACF;YACCE,WAAU;YACVC,oBAAkBN;;8BAElB,KAACG;oBAAIE,WAAU;8BAAsE;;8BAGrF,KAACF;oBAAIE,WAAU;8BAAsE;;;;;AAM7F;AAEA,OAAO,MAAME,SAAU,6gEA6EtB"}

View File

@@ -0,0 +1,84 @@
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
import { useState, useCallback } from 'react';
import { ThumbsUp } from '../../../../icons/thumbs/thumbs-up';
import { ThumbsDown } from '../../../../icons/thumbs/thumbs-down';
import { cx } from '../../../../utils/cx';
export function ErrorFeedback(param) {
let { errorCode, className } = param;
const [votedMap, setVotedMap] = useState({});
const voted = votedMap[errorCode];
const hasVoted = voted !== undefined;
const disabled = process.env.__NEXT_TELEMETRY_DISABLED;
const handleFeedback = useCallback(async (wasHelpful)=>{
// Optimistically set feedback state without loading/error states to keep implementation simple
setVotedMap((prev)=>({
...prev,
[errorCode]: wasHelpful
}));
try {
const response = await fetch((process.env.__NEXT_ROUTER_BASEPATH || '') + "/__nextjs_error_feedback?" + new URLSearchParams({
errorCode,
wasHelpful: wasHelpful.toString()
}));
if (!response.ok) {
// Handle non-2xx HTTP responses here if needed
console.error('Failed to record feedback on the server.');
}
} catch (error) {
console.error('Failed to record feedback:', error);
}
}, [
errorCode
]);
return /*#__PURE__*/ _jsx("div", {
className: cx('error-feedback', className),
role: "region",
"aria-label": "Error feedback",
children: hasVoted ? /*#__PURE__*/ _jsx("p", {
className: "error-feedback-thanks",
role: "status",
"aria-live": "polite",
children: "Thanks for your feedback!"
}) : /*#__PURE__*/ _jsxs(_Fragment, {
children: [
/*#__PURE__*/ _jsx("p", {
children: /*#__PURE__*/ _jsx("a", {
href: "https://nextjs.org/telemetry#error-feedback",
rel: "noopener noreferrer",
target: "_blank",
children: "Was this helpful?"
})
}),
/*#__PURE__*/ _jsx("button", {
"aria-disabled": disabled ? 'true' : undefined,
"aria-label": "Mark as helpful",
onClick: disabled ? undefined : ()=>handleFeedback(true),
className: cx('feedback-button', voted === true && 'voted'),
title: disabled ? 'Feedback disabled due to setting NEXT_TELEMETRY_DISABLED' : undefined,
type: "button",
children: /*#__PURE__*/ _jsx(ThumbsUp, {
"aria-hidden": "true"
})
}),
/*#__PURE__*/ _jsx("button", {
"aria-disabled": disabled ? 'true' : undefined,
"aria-label": "Mark as not helpful",
onClick: disabled ? undefined : ()=>handleFeedback(false),
className: cx('feedback-button', voted === false && 'voted'),
title: disabled ? 'Feedback disabled due to setting NEXT_TELEMETRY_DISABLED' : undefined,
type: "button",
children: /*#__PURE__*/ _jsx(ThumbsDown, {
"aria-hidden": "true",
// Optical alignment
style: {
translate: '1px 1px'
}
})
})
]
})
});
}
export const styles = "\n .error-feedback {\n display: flex;\n align-items: center;\n gap: 8px;\n white-space: nowrap;\n color: var(--color-gray-900);\n }\n\n .error-feedback-thanks {\n height: var(--size-24);\n display: flex;\n align-items: center;\n padding-right: 4px; /* To match the 4px inner padding of the thumbs up and down icons */\n }\n\n .feedback-button {\n background: none;\n border: none;\n border-radius: var(--rounded-md);\n width: var(--size-24);\n height: var(--size-24);\n display: flex;\n align-items: center;\n justify-content: center;\n cursor: pointer;\n\n &:focus {\n outline: var(--focus-ring);\n }\n\n &:hover {\n background: var(--color-gray-alpha-100);\n }\n\n &:active {\n background: var(--color-gray-alpha-200);\n }\n }\n\n .feedback-button[aria-disabled='true'] {\n opacity: 0.7;\n cursor: not-allowed;\n }\n\n .feedback-button.voted {\n background: var(--color-gray-alpha-200);\n }\n\n .thumbs-up-icon,\n .thumbs-down-icon {\n color: var(--color-gray-900);\n width: var(--size-16);\n height: var(--size-16);\n }\n";
//# sourceMappingURL=error-feedback.js.map

View File

@@ -0,0 +1,22 @@
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
import { ErrorFeedback } from './error-feedback/error-feedback';
import { styles as feedbackStyles } from './error-feedback/error-feedback';
export function ErrorOverlayFooter(param) {
let { errorCode, footerMessage } = param;
return /*#__PURE__*/ _jsxs("footer", {
className: "error-overlay-footer",
children: [
footerMessage ? /*#__PURE__*/ _jsx("p", {
className: "error-overlay-footer-message",
children: footerMessage
}) : null,
errorCode ? /*#__PURE__*/ _jsx(ErrorFeedback, {
className: "error-feedback",
errorCode: errorCode
}) : null
]
});
}
export const styles = "\n .error-overlay-footer {\n display: flex;\n flex-direction: row;\n justify-content: space-between;\n\n gap: 8px;\n padding: 12px;\n background: var(--color-background-200);\n border-top: 1px solid var(--color-gray-400);\n }\n\n .error-feedback {\n margin-left: auto;\n\n p {\n font-size: var(--size-14);\n font-weight: 500;\n margin: 0;\n }\n }\n\n .error-overlay-footer-message {\n color: var(--color-gray-900);\n margin: 0;\n font-size: var(--size-14);\n font-weight: 400;\n line-height: var(--size-20);\n }\n\n " + feedbackStyles + "\n";
//# sourceMappingURL=error-overlay-footer.js.map

View File

@@ -0,0 +1 @@
{"version":3,"sources":["../../../../../../../../src/client/components/react-dev-overlay/ui/components/errors/error-overlay-footer/error-overlay-footer.tsx"],"sourcesContent":["import { ErrorFeedback } from './error-feedback/error-feedback'\nimport { styles as feedbackStyles } from './error-feedback/error-feedback'\n\nexport type ErrorOverlayFooterProps = {\n errorCode: string | undefined\n footerMessage: string | undefined\n}\n\nexport function ErrorOverlayFooter({\n errorCode,\n footerMessage,\n}: ErrorOverlayFooterProps) {\n return (\n <footer className=\"error-overlay-footer\">\n {footerMessage ? (\n <p className=\"error-overlay-footer-message\">{footerMessage}</p>\n ) : null}\n {errorCode ? (\n <ErrorFeedback className=\"error-feedback\" errorCode={errorCode} />\n ) : null}\n </footer>\n )\n}\n\nexport const styles = `\n .error-overlay-footer {\n display: flex;\n flex-direction: row;\n justify-content: space-between;\n\n gap: 8px;\n padding: 12px;\n background: var(--color-background-200);\n border-top: 1px solid var(--color-gray-400);\n }\n\n .error-feedback {\n margin-left: auto;\n\n p {\n font-size: var(--size-14);\n font-weight: 500;\n margin: 0;\n }\n }\n\n .error-overlay-footer-message {\n color: var(--color-gray-900);\n margin: 0;\n font-size: var(--size-14);\n font-weight: 400;\n line-height: var(--size-20);\n }\n\n ${feedbackStyles}\n`\n"],"names":["ErrorFeedback","styles","feedbackStyles","ErrorOverlayFooter","errorCode","footerMessage","footer","className","p"],"mappings":";AAAA,SAASA,aAAa,QAAQ,kCAAiC;AAC/D,SAASC,UAAUC,cAAc,QAAQ,kCAAiC;AAO1E,OAAO,SAASC,mBAAmB,KAGT;IAHS,IAAA,EACjCC,SAAS,EACTC,aAAa,EACW,GAHS;IAIjC,qBACE,MAACC;QAAOC,WAAU;;YACfF,8BACC,KAACG;gBAAED,WAAU;0BAAgCF;iBAC3C;YACHD,0BACC,KAACJ;gBAAcO,WAAU;gBAAiBH,WAAWA;iBACnD;;;AAGV;AAEA,OAAO,MAAMH,SAAS,AAAC,4kBA8BnBC,iBAAe,KAClB"}

View File

@@ -0,0 +1,106 @@
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
import * as React from 'react';
import { DialogContent, DialogFooter } from '../../dialog';
import { ErrorOverlayToolbar, styles as toolbarStyles } from '../error-overlay-toolbar/error-overlay-toolbar';
import { ErrorOverlayFooter } from '../error-overlay-footer/error-overlay-footer';
import { ErrorMessage, styles as errorMessageStyles } from '../error-message/error-message';
import { ErrorTypeLabel, styles as errorTypeLabelStyles } from '../error-type-label/error-type-label';
import { ErrorOverlayNav, styles as floatingHeaderStyles } from '../error-overlay-nav/error-overlay-nav';
import { ErrorOverlayDialog, DIALOG_STYLES } from '../dialog/dialog';
import { ErrorOverlayDialogHeader, DIALOG_HEADER_STYLES } from '../dialog/header';
import { ErrorOverlayDialogBody, DIALOG_BODY_STYLES } from '../dialog/body';
import { CALL_STACK_STYLES } from '../call-stack/call-stack';
import { OVERLAY_STYLES, ErrorOverlayOverlay } from '../overlay/overlay';
import { ErrorOverlayBottomStack } from '../error-overlay-bottom-stack';
import { EnvironmentNameLabel } from '../environment-name-label/environment-name-label';
import { useFocusTrap } from '../dev-tools-indicator/utils';
export function ErrorOverlayLayout(param) {
let { errorMessage, errorType, children, errorCode, error, debugInfo, isBuildError, onClose, versionInfo, runtimeErrors, activeIdx, setActiveIndex, footerMessage, isTurbopack, dialogResizerRef, // This prop is used to animate the dialog, it comes from a parent component (<ErrorOverlay>)
// If it's not being passed, we should just render the component as it is being
// used without the context of a parent component that controls its state (e.g. Storybook).
rendered = true, transitionDurationMs } = param;
const animationProps = {
'data-rendered': rendered,
style: {
'--transition-duration': "" + transitionDurationMs + "ms"
}
};
const hasFooter = Boolean(footerMessage || errorCode);
const dialogRef = React.useRef(null);
useFocusTrap(dialogRef, null, rendered);
var _runtimeErrors_length;
return /*#__PURE__*/ _jsx(ErrorOverlayOverlay, {
fixed: isBuildError,
...animationProps,
children: /*#__PURE__*/ _jsxs("div", {
"data-nextjs-dialog-root": true,
ref: dialogRef,
...animationProps,
children: [
/*#__PURE__*/ _jsxs(ErrorOverlayDialog, {
onClose: onClose,
dialogResizerRef: dialogResizerRef,
"data-has-footer": hasFooter,
children: [
/*#__PURE__*/ _jsxs(DialogContent, {
children: [
/*#__PURE__*/ _jsxs(ErrorOverlayDialogHeader, {
children: [
/*#__PURE__*/ _jsxs("div", {
className: "nextjs__container_errors__error_title",
// allow assertion in tests before error rating is implemented
"data-nextjs-error-code": errorCode,
children: [
/*#__PURE__*/ _jsxs("span", {
"data-nextjs-error-label-group": true,
children: [
/*#__PURE__*/ _jsx(ErrorTypeLabel, {
errorType: errorType
}),
error.environmentName && /*#__PURE__*/ _jsx(EnvironmentNameLabel, {
environmentName: error.environmentName
})
]
}),
/*#__PURE__*/ _jsx(ErrorOverlayToolbar, {
error: error,
debugInfo: debugInfo
})
]
}),
/*#__PURE__*/ _jsx(ErrorMessage, {
errorMessage: errorMessage
})
]
}),
/*#__PURE__*/ _jsx(ErrorOverlayDialogBody, {
children: children
})
]
}),
hasFooter && /*#__PURE__*/ _jsx(DialogFooter, {
children: /*#__PURE__*/ _jsx(ErrorOverlayFooter, {
footerMessage: footerMessage,
errorCode: errorCode
})
}),
/*#__PURE__*/ _jsx(ErrorOverlayBottomStack, {
errorCount: (_runtimeErrors_length = runtimeErrors == null ? void 0 : runtimeErrors.length) != null ? _runtimeErrors_length : 0,
activeIdx: activeIdx != null ? activeIdx : 0
})
]
}),
/*#__PURE__*/ _jsx(ErrorOverlayNav, {
runtimeErrors: runtimeErrors,
activeIdx: activeIdx,
setActiveIndex: setActiveIndex,
versionInfo: versionInfo,
isTurbopack: isTurbopack
})
]
})
});
}
export const styles = "\n " + OVERLAY_STYLES + "\n " + DIALOG_STYLES + "\n " + DIALOG_HEADER_STYLES + "\n " + DIALOG_BODY_STYLES + "\n\n " + floatingHeaderStyles + "\n " + errorTypeLabelStyles + "\n " + errorMessageStyles + "\n " + toolbarStyles + "\n " + CALL_STACK_STYLES + "\n\n [data-nextjs-error-label-group] {\n display: flex;\n align-items: center;\n gap: 8px;\n }\n";
//# sourceMappingURL=error-overlay-layout.js.map

File diff suppressed because one or more lines are too long

Some files were not shown because too many files have changed in this diff Show More