revine 1.2.0 → 1.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/client.d.ts CHANGED
@@ -1,10 +1,11 @@
1
- export { Outlet, RouterProvider, useLocation, useNavigate, useParams, useSearchParams, } from "react-router-dom";
1
+ export { Outlet, RouterProvider, useLocation, useNavigate, useParams, useSearchParams } from "react-router-dom";
2
2
  export { Image } from "./components/Image.js";
3
3
  export type { ImageProps } from "./components/Image.js";
4
4
  export { Link } from "./components/Link.js";
5
5
  export type { LinkProps } from "./components/Link.js";
6
6
  export { NavLink } from "./components/NavLink.js";
7
7
  export type { NavLinkProps } from "./components/NavLink.js";
8
+ export { useRouter } from "./hooks/useRouter.js";
8
9
  export { defineConfig } from "./runtime/defineConfig.js";
9
10
  export { env, envAll } from "./runtime/env.js";
10
11
  export type { LayoutProps } from "./runtime/types.js";
@@ -1 +1 @@
1
- {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,MAAM,EACN,cAAc,EACd,WAAW,EACX,WAAW,EACX,SAAS,EACT,eAAe,GAChB,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EAAE,KAAK,EAAE,MAAM,uBAAuB,CAAC;AAC9C,YAAY,EAAE,UAAU,EAAE,MAAM,uBAAuB,CAAC;AACxD,OAAO,EAAE,IAAI,EAAE,MAAM,sBAAsB,CAAC;AAC5C,YAAY,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAC;AACtD,OAAO,EAAE,OAAO,EAAE,MAAM,yBAAyB,CAAC;AAClD,YAAY,EAAE,YAAY,EAAE,MAAM,yBAAyB,CAAC;AAC5D,OAAO,EAAE,YAAY,EAAE,MAAM,2BAA2B,CAAC;AACzD,OAAO,EAAE,GAAG,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;AAC/C,YAAY,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC"}
1
+ {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,MAAM,EACN,cAAc,EACd,WAAW,EACX,WAAW,EACX,SAAS,EACT,eAAe,EAChB,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EAAE,KAAK,EAAE,MAAM,uBAAuB,CAAC;AAC9C,YAAY,EAAE,UAAU,EAAE,MAAM,uBAAuB,CAAC;AACxD,OAAO,EAAE,IAAI,EAAE,MAAM,sBAAsB,CAAC;AAC5C,YAAY,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAC;AACtD,OAAO,EAAE,OAAO,EAAE,MAAM,yBAAyB,CAAC;AAClD,YAAY,EAAE,YAAY,EAAE,MAAM,yBAAyB,CAAC;AAC5D,OAAO,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAC;AACjD,OAAO,EAAE,YAAY,EAAE,MAAM,2BAA2B,CAAC;AACzD,OAAO,EAAE,GAAG,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;AAC/C,YAAY,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC"}
package/dist/client.js CHANGED
@@ -1,6 +1,7 @@
1
- export { Outlet, RouterProvider, useLocation, useNavigate, useParams, useSearchParams, } from "react-router-dom";
1
+ export { Outlet, RouterProvider, useLocation, useNavigate, useParams, useSearchParams } from "react-router-dom";
2
2
  export { Image } from "./components/Image.js";
3
3
  export { Link } from "./components/Link.js";
4
4
  export { NavLink } from "./components/NavLink.js";
5
+ export { useRouter } from "./hooks/useRouter.js";
5
6
  export { defineConfig } from "./runtime/defineConfig.js";
6
7
  export { env, envAll } from "./runtime/env.js";
@@ -1,5 +1,10 @@
1
1
  import { type ImgHTMLAttributes } from "react";
2
2
  type ObjectFit = "contain" | "cover" | "fill" | "none" | "scale-down";
3
+ declare module "react" {
4
+ interface ImgHTMLAttributes<T> {
5
+ fetchpriority?: "high" | "low" | "auto";
6
+ }
7
+ }
3
8
  export interface ImageProps extends Omit<ImgHTMLAttributes<HTMLImageElement>, "src" | "width" | "height" | "placeholder"> {
4
9
  /** Image source URL or import (e.g. import logo from './logo.png') */
5
10
  src: string;
@@ -1 +1 @@
1
- {"version":3,"file":"Image.d.ts","sourceRoot":"","sources":["../../src/components/Image.tsx"],"names":[],"mappings":"AAAA,OAAO,EAA+B,KAAK,iBAAiB,EAAE,MAAM,OAAO,CAAC;AAE5E,KAAK,SAAS,GAAG,SAAS,GAAG,OAAO,GAAG,MAAM,GAAG,MAAM,GAAG,YAAY,CAAC;AAEtE,MAAM,WAAW,UAAW,SAAQ,IAAI,CACtC,iBAAiB,CAAC,gBAAgB,CAAC,EACnC,KAAK,GAAG,OAAO,GAAG,QAAQ,GAAG,aAAa,CAC3C;IACC,sEAAsE;IACtE,GAAG,EAAE,MAAM,CAAC;IACZ,4CAA4C;IAC5C,GAAG,EAAE,MAAM,CAAC;IACZ,yDAAyD;IACzD,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,0DAA0D;IAC1D,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB;;;OAGG;IACH,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,4DAA4D;IAC5D,SAAS,CAAC,EAAE,SAAS,CAAC;IACtB,kEAAkE;IAClE,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB;;;OAGG;IACH,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB;;;;OAIG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,0CAA0C;IAC1C,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;IACrB,6CAA6C;IAC7C,QAAQ,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IAC3B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE,KAAK,CAAC,aAAa,CAAC;IAC5B,OAAO,CAAC,EAAE,KAAK,CAAC;CACjB;AAeD,wBAAgB,KAAK,CAAC,EACpB,GAAG,EACH,GAAG,EACH,KAAK,EACL,MAAM,EACN,IAAY,EACZ,SAAmB,EACnB,cAAyB,EACzB,QAAgB,EAChB,WAAW,EACX,OAAO,EACP,QAAQ,EACR,SAAS,EACT,KAAK,EACL,GAAG,IAAI,EACR,EAAE,UAAU,2CAmJZ"}
1
+ {"version":3,"file":"Image.d.ts","sourceRoot":"","sources":["../../src/components/Image.tsx"],"names":[],"mappings":"AAAA,OAAO,EAA+B,KAAK,iBAAiB,EAAE,MAAM,OAAO,CAAC;AAE5E,KAAK,SAAS,GAAG,SAAS,GAAG,OAAO,GAAG,MAAM,GAAG,MAAM,GAAG,YAAY,CAAC;AAEtE,OAAO,QAAQ,OAAO,CAAC;IACrB,UAAU,iBAAiB,CAAC,CAAC;QAC3B,aAAa,CAAC,EAAE,MAAM,GAAG,KAAK,GAAG,MAAM,CAAC;KACzC;CACF;AAED,MAAM,WAAW,UAAW,SAAQ,IAAI,CACtC,iBAAiB,CAAC,gBAAgB,CAAC,EACnC,KAAK,GAAG,OAAO,GAAG,QAAQ,GAAG,aAAa,CAC3C;IACC,sEAAsE;IACtE,GAAG,EAAE,MAAM,CAAC;IACZ,4CAA4C;IAC5C,GAAG,EAAE,MAAM,CAAC;IACZ,yDAAyD;IACzD,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,0DAA0D;IAC1D,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB;;;OAGG;IACH,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,4DAA4D;IAC5D,SAAS,CAAC,EAAE,SAAS,CAAC;IACtB,kEAAkE;IAClE,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB;;;OAGG;IACH,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB;;;;OAIG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,0CAA0C;IAC1C,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;IACrB,6CAA6C;IAC7C,QAAQ,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IAC3B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE,KAAK,CAAC,aAAa,CAAC;IAC5B,OAAO,CAAC,EAAE,KAAK,CAAC;CACjB;AAeD,wBAAgB,KAAK,CAAC,EACpB,GAAG,EACH,GAAG,EACH,KAAK,EACL,MAAM,EACN,IAAY,EACZ,SAAmB,EACnB,cAAyB,EACzB,QAAgB,EAChB,WAAW,EACX,OAAO,EACP,QAAQ,EACR,SAAS,EACT,KAAK,EACL,GAAG,IAAI,EACR,EAAE,UAAU,2CAmJZ"}
@@ -44,7 +44,7 @@ export function Image({ src, alt, width, height, fill = false, objectFit = "cove
44
44
  backgroundPosition: "center",
45
45
  filter: placeholder ? "blur(8px)" : undefined,
46
46
  transform: "scale(1.05)",
47
- } })), !errored ? (_jsx("img", { ref: imgRef, src: src, alt: alt, loading: priority ? "eager" : "lazy", decoding: priority ? "sync" : "async", fetchPriority: priority ? "high" : "auto", onLoad: () => setLoaded(true), onError: handleError, className: className, style: {
47
+ } })), !errored ? (_jsx("img", { ref: imgRef, src: src, alt: alt, loading: priority ? "eager" : "lazy", decoding: priority ? "sync" : "async", fetchpriority: priority ? "high" : "auto", onLoad: () => setLoaded(true), onError: handleError, className: className, style: {
48
48
  position: "absolute",
49
49
  inset: 0,
50
50
  width: "100%",
@@ -77,7 +77,7 @@ export function Image({ src, alt, width, height, fill = false, objectFit = "cove
77
77
  backgroundPosition: "center",
78
78
  filter: placeholder ? "blur(8px)" : undefined,
79
79
  transform: "scale(1.05)",
80
- } })), !errored ? (_jsx("img", { ref: imgRef, src: src, alt: alt, width: width, height: height, loading: priority ? "eager" : "lazy", decoding: priority ? "sync" : "async", fetchPriority: priority ? "high" : "auto", onLoad: () => setLoaded(true), onError: handleError, className: className, style: {
80
+ } })), !errored ? (_jsx("img", { ref: imgRef, src: src, alt: alt, width: width, height: height, loading: priority ? "eager" : "lazy", decoding: priority ? "sync" : "async", fetchpriority: priority ? "high" : "auto", onLoad: () => setLoaded(true), onError: handleError, className: className, style: {
81
81
  display: "block",
82
82
  width: "100%",
83
83
  height: "100%",
@@ -0,0 +1,12 @@
1
+ export declare function useRouter(): {
2
+ pathname: string;
3
+ params: Readonly<import("react-router").Params<string>>;
4
+ searchParams: URLSearchParams;
5
+ setSearchParams: import("react-router-dom").SetURLSearchParams;
6
+ push: (path: string) => void;
7
+ replace: (path: string) => void;
8
+ back: () => void;
9
+ forward: () => void;
10
+ prefetch: (_path: string) => void;
11
+ };
12
+ //# sourceMappingURL=useRouter.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useRouter.d.ts","sourceRoot":"","sources":["../../src/hooks/useRouter.ts"],"names":[],"mappings":"AAEA,wBAAgB,SAAS;;;;;iBAcR,MAAM;oBACH,MAAM;;;sBAGJ,MAAM;EAI3B"}
@@ -0,0 +1,22 @@
1
+ import { useNavigate, useLocation, useParams, useSearchParams } from "react-router-dom";
2
+ export function useRouter() {
3
+ const navigate = useNavigate();
4
+ const location = useLocation();
5
+ const params = useParams();
6
+ const [searchParams, setSearchParams] = useSearchParams();
7
+ return {
8
+ // Current route info
9
+ pathname: location.pathname,
10
+ params,
11
+ searchParams,
12
+ setSearchParams,
13
+ // Navigation methods
14
+ push: (path) => navigate(path),
15
+ replace: (path) => navigate(path, { replace: true }),
16
+ back: () => navigate(-1),
17
+ forward: () => navigate(1),
18
+ prefetch: (_path) => {
19
+ // Reserved for future prefetch support
20
+ },
21
+ };
22
+ }
@@ -1 +1 @@
1
- {"version":3,"file":"revinePlugin.d.ts","sourceRoot":"","sources":["../../../src/runtime/bundler/revinePlugin.ts"],"names":[],"mappings":"AA2VA,wBAAgB,YAAY,IAAI,GAAG,CAwIlC"}
1
+ {"version":3,"file":"revinePlugin.d.ts","sourceRoot":"","sources":["../../../src/runtime/bundler/revinePlugin.ts"],"names":[],"mappings":"AA2VA,wBAAgB,YAAY,IAAI,GAAG,CA6IlC"}
@@ -461,7 +461,12 @@ routes.push({
461
461
  errorElement: createElement(RevineErrorDialog),
462
462
  });
463
463
 
464
- export const router = createBrowserRouter(routes);
464
+ export const router = createBrowserRouter(routes, {
465
+ future: {
466
+ v7_startTransition: true,
467
+ v7_relativeSplatPath: true,
468
+ },
469
+ });
465
470
  `;
466
471
  }
467
472
  },
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "revine",
3
- "version": "1.2.0",
3
+ "version": "1.3.0",
4
4
  "description": "A react framework, but better.",
5
5
  "license": "MIT",
6
6
  "author": "Rachit Bharadwaj",
package/src/client.ts CHANGED
@@ -4,7 +4,7 @@ export {
4
4
  useLocation,
5
5
  useNavigate,
6
6
  useParams,
7
- useSearchParams,
7
+ useSearchParams
8
8
  } from "react-router-dom";
9
9
  export { Image } from "./components/Image.js";
10
10
  export type { ImageProps } from "./components/Image.js";
@@ -12,6 +12,7 @@ export { Link } from "./components/Link.js";
12
12
  export type { LinkProps } from "./components/Link.js";
13
13
  export { NavLink } from "./components/NavLink.js";
14
14
  export type { NavLinkProps } from "./components/NavLink.js";
15
+ export { useRouter } from "./hooks/useRouter.js";
15
16
  export { defineConfig } from "./runtime/defineConfig.js";
16
17
  export { env, envAll } from "./runtime/env.js";
17
18
  export type { LayoutProps } from "./runtime/types.js";
@@ -2,6 +2,12 @@ import { useEffect, useRef, useState, type ImgHTMLAttributes } from "react";
2
2
 
3
3
  type ObjectFit = "contain" | "cover" | "fill" | "none" | "scale-down";
4
4
 
5
+ declare module "react" {
6
+ interface ImgHTMLAttributes<T> {
7
+ fetchpriority?: "high" | "low" | "auto";
8
+ }
9
+ }
10
+
5
11
  export interface ImageProps extends Omit<
6
12
  ImgHTMLAttributes<HTMLImageElement>,
7
13
  "src" | "width" | "height" | "placeholder"
@@ -126,7 +132,7 @@ export function Image({
126
132
  alt={alt}
127
133
  loading={priority ? "eager" : "lazy"}
128
134
  decoding={priority ? "sync" : "async"}
129
- fetchPriority={priority ? "high" : "auto"}
135
+ fetchpriority={priority ? "high" : "auto"}
130
136
  onLoad={() => setLoaded(true)}
131
137
  onError={handleError}
132
138
  className={className}
@@ -196,7 +202,7 @@ export function Image({
196
202
  height={height}
197
203
  loading={priority ? "eager" : "lazy"}
198
204
  decoding={priority ? "sync" : "async"}
199
- fetchPriority={priority ? "high" : "auto"}
205
+ fetchpriority={priority ? "high" : "auto"}
200
206
  onLoad={() => setLoaded(true)}
201
207
  onError={handleError}
202
208
  className={className}
@@ -0,0 +1,25 @@
1
+ import { useNavigate, useLocation, useParams, useSearchParams } from "react-router-dom";
2
+
3
+ export function useRouter() {
4
+ const navigate = useNavigate();
5
+ const location = useLocation();
6
+ const params = useParams();
7
+ const [searchParams, setSearchParams] = useSearchParams();
8
+
9
+ return {
10
+ // Current route info
11
+ pathname: location.pathname,
12
+ params,
13
+ searchParams,
14
+ setSearchParams,
15
+
16
+ // Navigation methods
17
+ push: (path: string) => navigate(path),
18
+ replace: (path: string) => navigate(path, { replace: true }),
19
+ back: () => navigate(-1),
20
+ forward: () => navigate(1),
21
+ prefetch: (_path: string) => {
22
+ // Reserved for future prefetch support
23
+ },
24
+ };
25
+ }
@@ -476,9 +476,14 @@ routes.push({
476
476
  errorElement: createElement(RevineErrorDialog),
477
477
  });
478
478
 
479
- export const router = createBrowserRouter(routes);
479
+ export const router = createBrowserRouter(routes, {
480
+ future: {
481
+ v7_startTransition: true,
482
+ v7_relativeSplatPath: true,
483
+ },
484
+ });
480
485
  `;
481
486
  }
482
487
  },
483
488
  };
484
- }
489
+ }
@@ -9,6 +9,11 @@ const root = createRoot(container);
9
9
 
10
10
  root.render(
11
11
  <React.StrictMode>
12
- <RouterProvider router={router} />
12
+ <RouterProvider
13
+ router={router}
14
+ future={{
15
+ v7_startTransition: true,
16
+ }}
17
+ />
13
18
  </React.StrictMode>,
14
- );
19
+ );
@@ -1,2 +0,0 @@
1
- export declare const errorBoundaryComponent = "\nfunction RevineErrorDialog() {\n const error = useRouteError();\n const [expanded, setExpanded] = React.useState(false);\n\n const message = error?.message || String(error) || \"An unexpected error occurred.\";\n const stack = error?.stack || \"\";\n // Pull only the first meaningful line from the stack (skip the error message repeat)\n const stackLines = stack\n .split(\"\\n\")\n .filter((l) => l.trim().startsWith(\"at \"))\n .slice(0, 8);\n\n return React.createElement(\n \"div\",\n { style: overlayStyle },\n React.createElement(\n \"div\",\n { style: dialogStyle },\n // Header\n React.createElement(\n \"div\",\n { style: headerStyle },\n React.createElement(\"span\", { style: iconStyle }, \"\u2715\"),\n React.createElement(\"span\", { style: titleStyle }, \"Application Error\")\n ),\n // Message\n React.createElement(\"p\", { style: messageStyle }, message),\n // Stack toggle\n stackLines.length > 0 &&\n React.createElement(\n \"div\",\n null,\n React.createElement(\n \"button\",\n { onClick: () => setExpanded((v) => !v), style: toggleBtnStyle },\n expanded ? \"\u25B2 Hide stack trace\" : \"\u25BC Show stack trace\"\n ),\n expanded &&\n React.createElement(\n \"pre\",\n { style: stackStyle },\n stackLines.join(\"\\n\")\n )\n ),\n // Actions\n React.createElement(\n \"div\",\n { style: actionsStyle },\n React.createElement(\n \"button\",\n { onClick: () => window.location.reload(), style: primaryBtnStyle },\n \"Reload page\"\n ),\n React.createElement(\n \"button\",\n { onClick: () => (window.location.href = \"/\"), style: secondaryBtnStyle },\n \"Go to home\"\n )\n )\n )\n );\n}\n\nconst overlayStyle = {\n position: \"fixed\", inset: 0, background: \"rgba(0,0,0,0.65)\",\n backdropFilter: \"blur(4px)\", display: \"flex\",\n alignItems: \"center\", justifyContent: \"center\",\n zIndex: 9999, fontFamily: \"ui-monospace, 'Cascadia Code', monospace\",\n};\nconst dialogStyle = {\n background: \"#1a1a1a\", border: \"1px solid #ff4d4f55\",\n borderRadius: \"10px\", padding: \"28px 32px\",\n maxWidth: \"560px\", width: \"90%\", boxShadow: \"0 24px 64px rgba(0,0,0,0.6)\",\n color: \"#e5e5e5\",\n};\nconst headerStyle = {\n display: \"flex\", alignItems: \"center\", gap: \"10px\",\n marginBottom: \"14px\",\n};\nconst iconStyle = {\n display: \"inline-flex\", alignItems: \"center\", justifyContent: \"center\",\n width: \"26px\", height: \"26px\", borderRadius: \"50%\",\n background: \"#ff4d4f22\", color: \"#ff4d4f\", fontSize: \"13px\", fontWeight: 700,\n};\nconst titleStyle = {\n fontFamily: \"system-ui, sans-serif\",\n fontSize: \"16px\", fontWeight: 600, color: \"#fff\",\n};\nconst messageStyle = {\n fontFamily: \"ui-monospace, monospace\",\n fontSize: \"13px\", color: \"#ff7875\",\n background: \"#ff4d4f0f\", border: \"1px solid #ff4d4f22\",\n borderRadius: \"6px\", padding: \"10px 14px\",\n marginBottom: \"16px\", wordBreak: \"break-word\", lineHeight: 1.6,\n};\nconst toggleBtnStyle = {\n background: \"none\", border: \"none\", cursor: \"pointer\",\n color: \"#888\", fontSize: \"12px\", padding: \"0 0 10px 0\",\n fontFamily: \"system-ui, sans-serif\",\n};\nconst stackStyle = {\n background: \"#111\", borderRadius: \"6px\", padding: \"12px 14px\",\n fontSize: \"11px\", color: \"#aaa\", overflowX: \"auto\",\n lineHeight: 1.7, marginBottom: \"16px\",\n border: \"1px solid #2a2a2a\",\n};\nconst actionsStyle = {\n display: \"flex\", gap: \"10px\", marginTop: \"6px\",\n};\nconst primaryBtnStyle = {\n flex: 1, padding: \"9px 0\", borderRadius: \"6px\", border: \"none\",\n background: \"#ff4d4f\", color: \"#fff\", fontWeight: 600,\n fontSize: \"13px\", cursor: \"pointer\", fontFamily: \"system-ui, sans-serif\",\n};\nconst secondaryBtnStyle = {\n flex: 1, padding: \"9px 0\", borderRadius: \"6px\",\n border: \"1px solid #333\", background: \"transparent\",\n color: \"#aaa\", fontSize: \"13px\", cursor: \"pointer\",\n fontFamily: \"system-ui, sans-serif\",\n};\n";
2
- //# sourceMappingURL=errorBoundary.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"errorBoundary.d.ts","sourceRoot":"","sources":["../../../src/runtime/bundler/errorBoundary.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,sBAAsB,suIAyHlC,CAAC"}
@@ -1,122 +0,0 @@
1
- export const errorBoundaryComponent = `
2
- function RevineErrorDialog() {
3
- const error = useRouteError();
4
- const [expanded, setExpanded] = React.useState(false);
5
-
6
- const message = error?.message || String(error) || "An unexpected error occurred.";
7
- const stack = error?.stack || "";
8
- // Pull only the first meaningful line from the stack (skip the error message repeat)
9
- const stackLines = stack
10
- .split("\\n")
11
- .filter((l) => l.trim().startsWith("at "))
12
- .slice(0, 8);
13
-
14
- return React.createElement(
15
- "div",
16
- { style: overlayStyle },
17
- React.createElement(
18
- "div",
19
- { style: dialogStyle },
20
- // Header
21
- React.createElement(
22
- "div",
23
- { style: headerStyle },
24
- React.createElement("span", { style: iconStyle }, "✕"),
25
- React.createElement("span", { style: titleStyle }, "Application Error")
26
- ),
27
- // Message
28
- React.createElement("p", { style: messageStyle }, message),
29
- // Stack toggle
30
- stackLines.length > 0 &&
31
- React.createElement(
32
- "div",
33
- null,
34
- React.createElement(
35
- "button",
36
- { onClick: () => setExpanded((v) => !v), style: toggleBtnStyle },
37
- expanded ? "▲ Hide stack trace" : "▼ Show stack trace"
38
- ),
39
- expanded &&
40
- React.createElement(
41
- "pre",
42
- { style: stackStyle },
43
- stackLines.join("\\n")
44
- )
45
- ),
46
- // Actions
47
- React.createElement(
48
- "div",
49
- { style: actionsStyle },
50
- React.createElement(
51
- "button",
52
- { onClick: () => window.location.reload(), style: primaryBtnStyle },
53
- "Reload page"
54
- ),
55
- React.createElement(
56
- "button",
57
- { onClick: () => (window.location.href = "/"), style: secondaryBtnStyle },
58
- "Go to home"
59
- )
60
- )
61
- )
62
- );
63
- }
64
-
65
- const overlayStyle = {
66
- position: "fixed", inset: 0, background: "rgba(0,0,0,0.65)",
67
- backdropFilter: "blur(4px)", display: "flex",
68
- alignItems: "center", justifyContent: "center",
69
- zIndex: 9999, fontFamily: "ui-monospace, 'Cascadia Code', monospace",
70
- };
71
- const dialogStyle = {
72
- background: "#1a1a1a", border: "1px solid #ff4d4f55",
73
- borderRadius: "10px", padding: "28px 32px",
74
- maxWidth: "560px", width: "90%", boxShadow: "0 24px 64px rgba(0,0,0,0.6)",
75
- color: "#e5e5e5",
76
- };
77
- const headerStyle = {
78
- display: "flex", alignItems: "center", gap: "10px",
79
- marginBottom: "14px",
80
- };
81
- const iconStyle = {
82
- display: "inline-flex", alignItems: "center", justifyContent: "center",
83
- width: "26px", height: "26px", borderRadius: "50%",
84
- background: "#ff4d4f22", color: "#ff4d4f", fontSize: "13px", fontWeight: 700,
85
- };
86
- const titleStyle = {
87
- fontFamily: "system-ui, sans-serif",
88
- fontSize: "16px", fontWeight: 600, color: "#fff",
89
- };
90
- const messageStyle = {
91
- fontFamily: "ui-monospace, monospace",
92
- fontSize: "13px", color: "#ff7875",
93
- background: "#ff4d4f0f", border: "1px solid #ff4d4f22",
94
- borderRadius: "6px", padding: "10px 14px",
95
- marginBottom: "16px", wordBreak: "break-word", lineHeight: 1.6,
96
- };
97
- const toggleBtnStyle = {
98
- background: "none", border: "none", cursor: "pointer",
99
- color: "#888", fontSize: "12px", padding: "0 0 10px 0",
100
- fontFamily: "system-ui, sans-serif",
101
- };
102
- const stackStyle = {
103
- background: "#111", borderRadius: "6px", padding: "12px 14px",
104
- fontSize: "11px", color: "#aaa", overflowX: "auto",
105
- lineHeight: 1.7, marginBottom: "16px",
106
- border: "1px solid #2a2a2a",
107
- };
108
- const actionsStyle = {
109
- display: "flex", gap: "10px", marginTop: "6px",
110
- };
111
- const primaryBtnStyle = {
112
- flex: 1, padding: "9px 0", borderRadius: "6px", border: "none",
113
- background: "#ff4d4f", color: "#fff", fontWeight: 600,
114
- fontSize: "13px", cursor: "pointer", fontFamily: "system-ui, sans-serif",
115
- };
116
- const secondaryBtnStyle = {
117
- flex: 1, padding: "9px 0", borderRadius: "6px",
118
- border: "1px solid #333", background: "transparent",
119
- color: "#aaa", fontSize: "13px", cursor: "pointer",
120
- fontFamily: "system-ui, sans-serif",
121
- };
122
- `;