vista-core-js 0.0.2

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.
Files changed (53) hide show
  1. package/dist/ErrorOverlay.d.ts +7 -0
  2. package/dist/ErrorOverlay.js +68 -0
  3. package/dist/app.d.ts +21 -0
  4. package/dist/app.js +119 -0
  5. package/dist/client/link.d.ts +23 -0
  6. package/dist/client/link.js +42 -0
  7. package/dist/client.d.ts +2 -0
  8. package/dist/client.js +290 -0
  9. package/dist/components/PixelBlast.d.ts +28 -0
  10. package/dist/components/PixelBlast.js +584 -0
  11. package/dist/entry-client.d.ts +1 -0
  12. package/dist/entry-client.js +56 -0
  13. package/dist/entry-server.d.ts +9 -0
  14. package/dist/entry-server.js +33 -0
  15. package/dist/error-overlay.d.ts +1 -0
  16. package/dist/error-overlay.js +166 -0
  17. package/dist/font/google/index.d.ts +1923 -0
  18. package/dist/font/google/index.js +1948 -0
  19. package/dist/image/get-img-props.d.ts +20 -0
  20. package/dist/image/get-img-props.js +46 -0
  21. package/dist/image/image-config.d.ts +20 -0
  22. package/dist/image/image-config.js +17 -0
  23. package/dist/image/image-loader.d.ts +7 -0
  24. package/dist/image/image-loader.js +10 -0
  25. package/dist/image/index.d.ts +12 -0
  26. package/dist/image/index.js +12 -0
  27. package/dist/index.d.ts +6 -0
  28. package/dist/index.js +4 -0
  29. package/dist/plugin.d.ts +5 -0
  30. package/dist/plugin.js +88 -0
  31. package/dist/router.d.ts +18 -0
  32. package/dist/router.js +55 -0
  33. package/package.json +47 -0
  34. package/src/ErrorOverlay.tsx +194 -0
  35. package/src/app.tsx +138 -0
  36. package/src/assets/vista.gif +0 -0
  37. package/src/client/link.tsx +85 -0
  38. package/src/client.tsx +368 -0
  39. package/src/entry-client.tsx +70 -0
  40. package/src/entry-server.tsx +58 -0
  41. package/src/error-overlay.ts +187 -0
  42. package/src/font/google/index.d.ts +19011 -0
  43. package/src/font/google/index.ts +1968 -0
  44. package/src/font/types.d.ts +13 -0
  45. package/src/image/get-img-props.ts +100 -0
  46. package/src/image/image-config.ts +22 -0
  47. package/src/image/image-loader.ts +23 -0
  48. package/src/image/index.tsx +21 -0
  49. package/src/index.ts +7 -0
  50. package/src/plugin.ts +100 -0
  51. package/src/router-loader.ts +51 -0
  52. package/src/router.tsx +80 -0
  53. package/tsconfig.json +23 -0
@@ -0,0 +1,7 @@
1
+ import React from 'react';
2
+ interface ErrorOverlayProps {
3
+ error: any;
4
+ onClose?: () => void;
5
+ }
6
+ export declare const ErrorOverlay: React.FC<ErrorOverlayProps>;
7
+ export {};
@@ -0,0 +1,68 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ const VSCodeColors = {
3
+ bg: '#1e1e1e',
4
+ sidebar: '#252526',
5
+ activityBar: '#333333',
6
+ statusBar: '#007acc',
7
+ titleBar: '#3c3c3c',
8
+ text: '#d4d4d4',
9
+ red: '#f14c4c',
10
+ yellow: '#cca700',
11
+ green: '#238636',
12
+ terminalBg: '#1e1e1e',
13
+ editorBg: '#1e1e1e',
14
+ lineNo: '#858585',
15
+ };
16
+ export const ErrorOverlay = ({ error, onClose }) => {
17
+ if (!error)
18
+ return null;
19
+ const isBuildError = error.type === 'error' || error.plugin; // Vite error shape
20
+ const message = error.message || 'Unknown Error';
21
+ const file = error.id || error.file || error.filename || 'Unknown File';
22
+ const frame = error.frame || '';
23
+ const stack = error.stack || '';
24
+ // Parse location if available
25
+ const loc = error.loc ? `${error.loc.line}:${error.loc.column}` : '';
26
+ return (_jsxs("div", { style: {
27
+ position: 'fixed',
28
+ top: 0,
29
+ left: 0,
30
+ width: '100vw',
31
+ height: '100vh',
32
+ zIndex: 99999,
33
+ backgroundColor: 'rgba(0, 0, 0, 0.6)',
34
+ backdropFilter: 'blur(8px)',
35
+ display: 'flex',
36
+ alignItems: 'center',
37
+ justifyContent: 'center',
38
+ fontFamily: "'Segoe UI', Tahoma, Geneva, Verdana, sans-serif",
39
+ }, children: [_jsxs("div", { style: {
40
+ width: '85vw',
41
+ maxWidth: '1000px',
42
+ height: '80vh',
43
+ backgroundColor: VSCodeColors.bg,
44
+ borderRadius: '10px',
45
+ boxShadow: '0 20px 50px rgba(0,0,0,0.5)',
46
+ overflow: 'hidden',
47
+ display: 'flex',
48
+ flexDirection: 'column',
49
+ border: '1px solid #454545',
50
+ animation: 'vista-slide-up 0.3s ease-out',
51
+ }, children: [_jsxs("div", { style: {
52
+ height: '35px',
53
+ backgroundColor: VSCodeColors.titleBar,
54
+ display: 'flex',
55
+ alignItems: 'center',
56
+ padding: '0 15px',
57
+ borderBottom: '1px solid #333',
58
+ }, children: [_jsxs("div", { style: { display: 'flex', gap: '8px', marginRight: '20px' }, children: [_jsx("div", { onClick: onClose, style: { width: '12px', height: '12px', borderRadius: '50%', backgroundColor: '#ff5f56', cursor: 'pointer' } }), _jsx("div", { style: { width: '12px', height: '12px', borderRadius: '50%', backgroundColor: '#ffbd2e' } }), _jsx("div", { style: { width: '12px', height: '12px', borderRadius: '50%', backgroundColor: '#27c93f' } })] }), _jsxs("div", { style: { color: '#ccc', fontSize: '13px', flex: 1, textAlign: 'center', opacity: 0.8 }, children: [file.split('/').pop(), " ", loc ? `— ${loc}` : ''] })] }), _jsxs("div", { style: { display: 'flex', flex: 1, overflow: 'hidden' }, children: [_jsxs("div", { style: { width: '50px', backgroundColor: VSCodeColors.activityBar, display: 'flex', flexDirection: 'column', alignItems: 'center', paddingTop: '15px' }, children: [_jsx("div", { style: { marginBottom: '20px', opacity: 0.6, cursor: 'pointer' }, title: "Explorer", children: _jsxs("svg", { width: "24", height: "24", viewBox: "0 0 24 24", fill: "none", stroke: "#d4d4d4", strokeWidth: "1.5", children: [_jsx("path", { d: "M13 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V9z" }), _jsx("polyline", { points: "13 2 13 9 20 9" })] }) }), _jsx("div", { style: { marginBottom: '20px', opacity: 0.6, cursor: 'pointer' }, title: "Search", children: _jsxs("svg", { width: "24", height: "24", viewBox: "0 0 24 24", fill: "none", stroke: "#d4d4d4", strokeWidth: "1.5", children: [_jsx("circle", { cx: "11", cy: "11", r: "8" }), _jsx("line", { x1: "21", y1: "21", x2: "16.65", y2: "16.65" })] }) }), _jsx("div", { style: { marginBottom: '20px', opacity: 1, borderLeft: '2px solid white', paddingLeft: '11px', cursor: 'pointer' }, title: "Run and Debug", children: _jsxs("svg", { width: "24", height: "24", viewBox: "0 0 24 24", fill: "none", stroke: "#d4d4d4", strokeWidth: "1.5", children: [_jsx("path", { d: "M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71" }), _jsx("path", { d: "M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71" })] }) })] }), _jsxs("div", { className: "vista-sidebar", style: { width: '200px', backgroundColor: VSCodeColors.sidebar, fontSize: '13px', color: VSCodeColors.text, padding: '10px', borderRight: '1px solid #333' }, children: [_jsx("div", { style: { fontSize: '11px', fontWeight: 'bold', marginBottom: '10px', opacity: 0.7, textTransform: 'uppercase' }, children: "Open Editors" }), _jsxs("div", { style: { padding: '5px 10px', backgroundColor: '#37373d', borderRadius: '3px', cursor: 'pointer', display: 'flex', alignItems: 'center' }, children: [_jsx("span", { style: { marginRight: '8px', display: 'flex', alignItems: 'center' }, children: _jsxs("svg", { width: "14", height: "14", viewBox: "0 0 24 24", fill: "none", stroke: "#61dafb", strokeWidth: "2", children: [_jsx("circle", { cx: "12", cy: "12", r: "10" }), _jsx("line", { x1: "12", y1: "8", x2: "12", y2: "12" }), _jsx("line", { x1: "12", y1: "16", x2: "12.01", y2: "16" })] }) }), file.split('/').pop()] })] }), _jsxs("div", { style: { flex: 1, display: 'flex', flexDirection: 'column', backgroundColor: VSCodeColors.editorBg }, children: [_jsx("div", { style: { height: '35px', backgroundColor: VSCodeColors.bg, display: 'flex', alignItems: 'center', borderBottom: '1px solid #333' }, children: _jsxs("div", { style: { padding: '0 15px', height: '100%', backgroundColor: '#1e1e1e', borderTop: '2px solid #e11c1c', color: '#fff', fontSize: '13px', display: 'flex', alignItems: 'center', gap: '8px' }, children: [_jsxs("svg", { width: "14", height: "14", viewBox: "0 0 24 24", fill: "none", stroke: "#61dafb", strokeWidth: "2", children: [_jsx("circle", { cx: "12", cy: "12", r: "10" }), _jsx("line", { x1: "12", y1: "8", x2: "12", y2: "12" }), _jsx("line", { x1: "12", y1: "16", x2: "12.01", y2: "16" })] }), file.split('/').pop(), _jsx("span", { style: { marginLeft: '10px', cursor: 'pointer', opacity: 0.7 }, children: _jsxs("svg", { width: "12", height: "12", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", children: [_jsx("line", { x1: "18", y1: "6", x2: "6", y2: "18" }), _jsx("line", { x1: "6", y1: "6", x2: "18", y2: "18" })] }) })] }) }), _jsxs("div", { style: { flex: 2, padding: '20px', overflow: 'auto', fontFamily: "'Fira Code', 'Consolas', monospace", fontSize: '14px', lineHeight: '1.5', color: '#d4d4d4' }, children: [isBuildError && (_jsx("div", { style: { color: '#f14c4c', marginBottom: '15px', fontWeight: 'bold' }, children: message })), frame ? (_jsx("pre", { style: { margin: 0, whiteSpace: 'pre-wrap', fontFamily: 'inherit' }, children: frame })) : (_jsxs("div", { style: { color: '#d4d4d4' }, children: [_jsx("div", { style: { color: '#666', marginBottom: '20px' }, children: "// Source code not available for runtime execution error." }), _jsx("pre", { style: { margin: 0, color: '#9cdcfe', whiteSpace: 'pre-wrap' }, children: stack })] }))] }), _jsxs("div", { style: { flex: 1, backgroundColor: '#1e1e1e', borderTop: '1px solid #444', display: 'flex', flexDirection: 'column' }, children: [_jsxs("div", { style: { display: 'flex', padding: '5px 15px', borderBottom: '1px solid #333', fontSize: '11px', color: '#ccc', gap: '15px' }, children: [_jsx("span", { style: { textDecoration: 'underline', cursor: 'pointer' }, children: "PROBLEMS" }), _jsx("span", { style: { opacity: 0.5, cursor: 'pointer' }, children: "OUTPUT" }), _jsx("span", { style: { opacity: 0.5, cursor: 'pointer' }, children: "DEBUG CONSOLE" }), _jsx("span", { style: { opacity: 0.5, cursor: 'pointer' }, children: "TERMINAL" })] }), _jsxs("div", { style: { padding: '15px', overflow: 'auto', fontFamily: 'monospace', fontSize: '13px', color: '#f14c4c' }, children: [_jsx("div", { style: { color: '#d4d4d4', marginBottom: '5px' }, children: "$ npm run dev" }), _jsxs("div", { children: ["> Error: ", message] })] })] })] })] }), _jsxs("div", { style: { height: '22px', backgroundColor: '#e11c1c', display: 'flex', alignItems: 'center', padding: '0 10px', fontSize: '12px', color: 'white', justifyContent: 'space-between' }, children: [_jsxs("div", { style: { display: 'flex', gap: '15px', alignItems: 'center' }, children: [_jsxs("span", { style: { display: 'flex', alignItems: 'center', gap: '5px' }, children: [_jsxs("svg", { width: "12", height: "12", viewBox: "0 0 24 24", fill: "currentColor", children: [_jsx("circle", { cx: "12", cy: "12", r: "10" }), _jsx("line", { x1: "15", y1: "9", x2: "9", y2: "15" }), _jsx("line", { x1: "9", y1: "9", x2: "15", y2: "15" })] }), "1 Error"] }), _jsxs("span", { style: { display: 'flex', alignItems: 'center', gap: '5px' }, children: [_jsxs("svg", { width: "12", height: "12", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", children: [_jsx("path", { d: "M10.29 3.86L1.82 18a2 2 0 0 0 1.71 3h16.94a2 2 0 0 0 1.71-3L13.71 3.86a2 2 0 0 0-3.42 0z" }), _jsx("line", { x1: "12", y1: "9", x2: "12", y2: "13" }), _jsx("line", { x1: "12", y1: "17", x2: "12.01", y2: "17" })] }), "0 Warnings"] })] }), _jsxs("div", { children: ["Ln ", error.loc?.line || 0, ", Col ", error.loc?.column || 0] })] })] }), _jsx("style", { children: `
59
+ .vista-sidebar { display: none; }
60
+ @media (min-width: 768px) {
61
+ .vista-sidebar { display: block; }
62
+ }
63
+ @keyframes vista-slide-up {
64
+ from { opacity: 0; transform: translateY(20px) scale(0.95); }
65
+ to { opacity: 1; transform: translateY(0) scale(1); }
66
+ }
67
+ ` })] }));
68
+ };
package/dist/app.d.ts ADDED
@@ -0,0 +1,21 @@
1
+ import React from 'react';
2
+ export declare function loadRoute(path: string): Promise<React.ComponentType<any> | null>;
3
+ export declare function loadRootLayout(): Promise<{
4
+ Component: React.ComponentType<any>;
5
+ metadata: any;
6
+ } | {
7
+ Component: null;
8
+ metadata: {};
9
+ }>;
10
+ export type VistaAsset = {
11
+ type: 'style' | 'script' | 'preamble';
12
+ src?: string;
13
+ content?: string;
14
+ key?: string;
15
+ };
16
+ export default function App({ initialComponent, initialRootLayout, metadata, assets }: {
17
+ initialComponent?: React.ComponentType<any>;
18
+ initialRootLayout?: React.ComponentType<any>;
19
+ metadata?: any;
20
+ assets?: VistaAsset[];
21
+ }): import("react/jsx-runtime").JSX.Element;
package/dist/app.js ADDED
@@ -0,0 +1,119 @@
1
+ import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import React, { Suspense } from 'react';
3
+ import { useRouter } from './router.js';
4
+ // Lazy load all pages and layouts at module level so they can be accessed by loadRoute
5
+ // Note: Vite treats absolute paths in glob as relative to the project root
6
+ // Lazy load all pages and layouts at module level so they can be accessed by loadRoute
7
+ // Note: Vite treats absolute paths in glob as relative to the project root
8
+ // FIX: Use eager: true to solve HMR instability with lazy boundaries
9
+ // FIX: Use eager: true to solve HMR instability with lazy boundaries
10
+ const pages = import.meta.glob('/app/**/index.tsx', { eager: true });
11
+ const layouts = import.meta.glob('/app/**/layout.tsx', { eager: true });
12
+ const rootLayout = import.meta.glob('/app/layout.tsx', { eager: true });
13
+ // Helper to resolve route path to file key
14
+ function getPageKey(path) {
15
+ const cleanPath = path === '/' ? '/' : path.replace(/\/$/, '');
16
+ return `/app${cleanPath === '/' ? '' : cleanPath}/index.tsx`;
17
+ }
18
+ // Exported loader for entry-client to preload the initial route
19
+ export async function loadRoute(path) {
20
+ const pageKey = getPageKey(path);
21
+ if (pages[pageKey]) {
22
+ try {
23
+ // Eager: pages[pageKey] is the module itself
24
+ const mod = pages[pageKey];
25
+ return mod.default;
26
+ }
27
+ catch (e) {
28
+ console.error(`Failed to load route: ${path}`, e);
29
+ }
30
+ }
31
+ return null;
32
+ }
33
+ // Exported loader for entry-client/server to preload the root layout and metadata
34
+ export async function loadRootLayout() {
35
+ const rootLayoutKey = '/app/layout.tsx';
36
+ if (rootLayout[rootLayoutKey]) {
37
+ try {
38
+ // Eager: rootLayout[rootLayoutKey] is the module itself
39
+ const mod = rootLayout[rootLayoutKey];
40
+ return {
41
+ Component: mod.default,
42
+ metadata: mod.metadata || {}
43
+ };
44
+ }
45
+ catch (e) {
46
+ console.error('Failed to load root layout', e);
47
+ }
48
+ }
49
+ return { Component: null, metadata: {} };
50
+ }
51
+ function VistaHead({ assets, metadata }) {
52
+ // Serialize assets for client hydration
53
+ const serializedAssets = JSON.stringify(assets || []);
54
+ // With hydrateRoot(document) and React 19, we can just render the tags.
55
+ // React handles the hoisting for stylesheets if we hint them, or just standard placement.
56
+ // Since we are hydrating the full document, and RootLayout contains <head>,
57
+ // these tags will be rendered where they are (in body/root children).
58
+ // React 19 "Hoistable" Resources: <title>, <meta>, <link rel=stylesheet>.
59
+ // They will be hoisted to <head> automatically.
60
+ return (_jsxs(_Fragment, { children: [metadata?.title && _jsx("title", { children: metadata.title }), metadata?.description && _jsx("meta", { name: "description", content: metadata.description }), assets?.map((asset, index) => {
61
+ if (asset.type === 'style' && asset.src) {
62
+ // Precedence="default" opts into React 19 Resource Loading/Hoisting
63
+ /* @ts-ignore: React 19 prop */
64
+ return _jsx("link", { rel: "stylesheet", href: asset.src, precedence: "default" }, asset.key || asset.src);
65
+ }
66
+ if (asset.type === 'script' && asset.src) {
67
+ return _jsx("script", { type: "module", src: asset.src }, asset.key || asset.src);
68
+ }
69
+ if (asset.type === 'preamble' && asset.content) {
70
+ return (_jsx("script", { type: "module", dangerouslySetInnerHTML: { __html: asset.content } }, "preamble"));
71
+ }
72
+ return null;
73
+ }), _jsx("script", { id: "vista-assets", dangerouslySetInnerHTML: {
74
+ __html: `window.__VISTA_ASSETS__ = ${serializedAssets};`
75
+ } })] }));
76
+ }
77
+ export default function App({ initialComponent, initialRootLayout, metadata, assets }) {
78
+ const { path } = useRouter();
79
+ const pageKey = getPageKey(path);
80
+ if (!pages[pageKey]) {
81
+ return _jsxs("div", { children: ["404 Not Found: ", pageKey] });
82
+ }
83
+ // --- Page Logic ---
84
+ // --- Page Logic ---
85
+ const isInitialRender = React.useRef(!!initialComponent);
86
+ const [useInitial, setUseInitial] = React.useState(!!initialComponent);
87
+ const [initialPath] = React.useState(path); // FIX: Hook must be at top level
88
+ React.useEffect(() => {
89
+ // Switch to dynamic component (HMR-capable) after hydration
90
+ if (useInitial) {
91
+ setUseInitial(false);
92
+ isInitialRender.current = false;
93
+ }
94
+ }, []);
95
+ let PageComponent;
96
+ // Use initial component only if we are on the same path and fresh from hydration
97
+ if (useInitial && initialComponent && path === initialPath) {
98
+ PageComponent = initialComponent;
99
+ }
100
+ else {
101
+ // Eager: Direct access
102
+ PageComponent = pages[pageKey].default;
103
+ }
104
+ // --- Layout Logic ---
105
+ let RootLayoutComponent = initialRootLayout;
106
+ if (!RootLayoutComponent) {
107
+ const rootLayoutKey = '/app/layout.tsx';
108
+ if (rootLayout[rootLayoutKey]) {
109
+ // Eager
110
+ RootLayoutComponent = rootLayout[rootLayoutKey].default;
111
+ }
112
+ else {
113
+ RootLayoutComponent = React.Fragment;
114
+ }
115
+ }
116
+ return (
117
+ /* @ts-ignore */
118
+ _jsxs(RootLayoutComponent, { children: [_jsx(VistaHead, { metadata: metadata, assets: assets }), _jsx(Suspense, { fallback: null, children: _jsx(PageComponent, {}, path) })] }));
119
+ }
@@ -0,0 +1,23 @@
1
+ import React, { AnchorHTMLAttributes } from 'react';
2
+ type Url = string | {
3
+ href: string;
4
+ query?: any;
5
+ hash?: string;
6
+ };
7
+ export interface LinkProps extends Omit<AnchorHTMLAttributes<HTMLAnchorElement>, 'href'> {
8
+ href: Url;
9
+ as?: Url;
10
+ replace?: boolean;
11
+ scroll?: boolean;
12
+ shallow?: boolean;
13
+ passHref?: boolean;
14
+ prefetch?: boolean | 'auto' | null;
15
+ locale?: string | false;
16
+ legacyBehavior?: boolean;
17
+ onNavigate?: () => void;
18
+ }
19
+ export declare const Link: React.ForwardRefExoticComponent<LinkProps & React.RefAttributes<HTMLAnchorElement>>;
20
+ export declare const useLinkStatus: () => {
21
+ pending: boolean;
22
+ };
23
+ export default Link;
@@ -0,0 +1,42 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import React from 'react';
3
+ import { useRouter } from '../router';
4
+ // Simple normalization for href (string or object)
5
+ const formatUrl = (url) => {
6
+ if (typeof url === 'string')
7
+ return url;
8
+ if (typeof url === 'object' && url !== null) {
9
+ // Very basic support just for demo
10
+ return (url.href || '') + (url.hash || '');
11
+ }
12
+ return '';
13
+ };
14
+ export const Link = React.forwardRef(({ href, as, replace, scroll, shallow, passHref, prefetch, legacyBehavior, children, onClick, ...props }, ref) => {
15
+ const { push, replace: replaceRoute } = useRouter();
16
+ const targetPath = formatUrl(as || href);
17
+ const handleClick = (e) => {
18
+ if (onClick)
19
+ onClick(e);
20
+ // Standard link behavior checks
21
+ if (e.defaultPrevented)
22
+ return;
23
+ if (e.button !== 0)
24
+ return; // ignore right clicks
25
+ if (e.metaKey || e.ctrlKey || e.shiftKey || e.altKey)
26
+ return; // ignore open in new tab
27
+ if (!href)
28
+ return;
29
+ e.preventDefault();
30
+ if (replace) {
31
+ replaceRoute(targetPath);
32
+ }
33
+ else {
34
+ push(targetPath);
35
+ }
36
+ };
37
+ return (_jsx("a", { href: targetPath, onClick: handleClick, ref: ref, ...props, children: children }));
38
+ });
39
+ export const useLinkStatus = () => {
40
+ return { pending: false }; // Mock implementation
41
+ };
42
+ export default Link;
@@ -0,0 +1,2 @@
1
+ export declare function mount(modules: Record<string, any>): void;
2
+ export declare function mountError(error: any): void;
package/dist/client.js ADDED
@@ -0,0 +1,290 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import React, { useState, useEffect } from 'react';
3
+ import ReactDOM from 'react-dom/client';
4
+ import { RouterProvider, useRouter } from './router.js';
5
+ import { ErrorOverlay } from './ErrorOverlay';
6
+ // --- Error Management ---
7
+ function VistaErrorManager({ children, initialError }) {
8
+ const [error, setError] = useState(initialError || null);
9
+ useEffect(() => {
10
+ // 1. Listen for Vite HMR/Build Errors
11
+ if (import.meta.hot) {
12
+ import.meta.hot.on('vite:error', (payloade) => {
13
+ // Vite sends an object like { err: { message, stack, plugin, id, frame, loc } }
14
+ // OR sometimes just the error object directly depending on version/context.
15
+ console.log('[Vista] Received vite:error payload:', payloade);
16
+ const err = payloade.err || payloade;
17
+ setError({
18
+ message: err.message,
19
+ stack: err.stack,
20
+ id: err.id, // Vite uses 'id' for filename often
21
+ frame: err.frame,
22
+ plugin: err.plugin,
23
+ loc: err.loc,
24
+ type: 'build',
25
+ // Fallbacks for Overlay keys
26
+ filename: err.id || err.file || 'Build Error',
27
+ });
28
+ });
29
+ import.meta.hot.on('vite:beforeUpdate', () => {
30
+ setError(null); // Clear error on new update
31
+ });
32
+ }
33
+ // 2. Listen for Unhandled Promise Rejections
34
+ const handleRejection = (event) => {
35
+ // Ignore dynamic import errors if we likely have a build error
36
+ if (event.reason?.message?.includes('Failed to fetch dynamically imported module')) {
37
+ console.log('[Vista] Ignoring dynamic import error (likely causing a build error)');
38
+ return;
39
+ }
40
+ setError((prev) => {
41
+ // specific check: don't overwrite build errors with runtime noise
42
+ if (prev && prev.type === 'build')
43
+ return prev;
44
+ return {
45
+ message: event.reason?.message || 'Unhandled Promise Rejection',
46
+ stack: event.reason?.stack || '',
47
+ filename: 'Runtime Error',
48
+ loc: { line: 0, column: 0 },
49
+ type: 'runtime'
50
+ };
51
+ });
52
+ };
53
+ // 3. Listen for Global Errors
54
+ const handleError = (event) => {
55
+ setError((prev) => {
56
+ if (prev && prev.type === 'build')
57
+ return prev;
58
+ return {
59
+ message: event.error?.message || event.message || 'Unknown Error',
60
+ stack: event.error?.stack || '',
61
+ filename: 'Runtime Error',
62
+ loc: { line: event.lineno || 0, column: event.colno || 0 },
63
+ type: 'runtime'
64
+ };
65
+ });
66
+ };
67
+ window.addEventListener('unhandledrejection', handleRejection);
68
+ window.addEventListener('error', handleError);
69
+ return () => {
70
+ window.removeEventListener('unhandledrejection', handleRejection);
71
+ window.removeEventListener('error', handleError);
72
+ };
73
+ }, []);
74
+ const handleBoundaryError = (err) => {
75
+ // Logic to ignore cascade errors
76
+ if (error && error.type === 'build')
77
+ return;
78
+ if (err.message && err.message.includes('Failed to fetch dynamically imported module'))
79
+ return;
80
+ setError({
81
+ message: err.message,
82
+ stack: err.stack,
83
+ loc: { line: 0, column: 0 },
84
+ filename: 'Runtime Error',
85
+ type: 'runtime'
86
+ });
87
+ };
88
+ if (error) {
89
+ return _jsx(ErrorOverlay, { error: error, onClose: () => setError(null) });
90
+ }
91
+ return (_jsx(ErrorBoundary, { onError: handleBoundaryError, children: children }));
92
+ }
93
+ // ... existing ErrorBoundary ...
94
+ // ... existing AppContent ...
95
+ // ... existing App ...
96
+ // Export a mount function that accepts the glob results
97
+ export function mount(modules) {
98
+ console.log('[Vista] Mount called with modules:', Object.keys(modules));
99
+ const root = document.getElementById('root');
100
+ if (root) {
101
+ console.log('[Vista] Root element found, rendering...');
102
+ ReactDOM.createRoot(root).render(_jsx(VistaErrorManager, { children: _jsx(App, { modules: modules }) }));
103
+ }
104
+ else {
105
+ console.error('[Vista] FATAL: Root element #root not found in DOM');
106
+ }
107
+ }
108
+ // Export a mountError function for when module loading fails
109
+ export function mountError(error) {
110
+ const root = document.getElementById('root');
111
+ if (root) {
112
+ // Mount just the ErrorManager to catch and display the Vite error
113
+ ReactDOM.createRoot(root).render(_jsx(VistaErrorManager, { initialError: error, children: _jsx("div", { style: { padding: '20px', fontFamily: 'sans-serif', color: '#666' }, children: "Initializing error overlay..." }) }));
114
+ }
115
+ }
116
+ class ErrorBoundary extends React.Component {
117
+ constructor(props) {
118
+ super(props);
119
+ this.state = { hasError: false };
120
+ }
121
+ static getDerivedStateFromError(error) {
122
+ return { hasError: true };
123
+ }
124
+ componentDidCatch(error, errorInfo) {
125
+ this.props.onError({
126
+ message: error.message,
127
+ stack: error.stack,
128
+ loc: { line: 0, column: 0 },
129
+ filename: 'Runtime Error'
130
+ });
131
+ }
132
+ render() {
133
+ if (this.state.hasError) {
134
+ return null;
135
+ }
136
+ return this.props.children;
137
+ }
138
+ }
139
+ // --- App Logic ---
140
+ function AppContent({ modules }) {
141
+ const { path: currentPath } = useRouter();
142
+ // 1. Find the matching page component
143
+ let PageComponent = () => _jsx("div", { className: "p-10 text-xl", children: "404 Not Found" });
144
+ // 2. Build the Layout Tree
145
+ // ... (Logic to build layoutPaths is same) ...
146
+ // Refactored Async Logic
147
+ const [componentTree, setComponentTree] = React.useState(null);
148
+ const [pageError, setPageError] = React.useState(null);
149
+ React.useEffect(() => {
150
+ let isMounted = true;
151
+ setPageError(null);
152
+ const loadRoute = async () => {
153
+ try {
154
+ // --- 1. Route Matching Engine ---
155
+ let pageLoader = null;
156
+ let matchedRoutePath = '';
157
+ let routeParams = {};
158
+ // Normalize current path: remove trailing slash (unless root)
159
+ let normalizedPath = currentPath;
160
+ if (normalizedPath.length > 1 && normalizedPath.endsWith('/')) {
161
+ normalizedPath = normalizedPath.slice(0, -1);
162
+ }
163
+ // Helper: Convert file path to route regex
164
+ // e.g. "/app/users/[id]/index.tsx" -> "^/users/([^/]+)$"
165
+ // e.g. "/app/index.tsx" -> "^/$"
166
+ const createRouteMatcher = (filePath) => {
167
+ // Remove prefix: handle "/", "./", or no slash before "app"
168
+ let cleanPath = filePath
169
+ .replace(/^(\.?\/)?app\//, '') // Remove app/ prefix (robust)
170
+ .replace(/\/index\.tsx$/, '') // Remove /index.tsx (nested)
171
+ .replace(/^index\.tsx$/, '') // Remove index.tsx (root)
172
+ .replace(/\.tsx$/, ''); // Remove .tsx (if any)
173
+ if (cleanPath === '')
174
+ cleanPath = '/';
175
+ // Split into segments
176
+ const segments = cleanPath.split('/').filter(Boolean);
177
+ const paramNames = [];
178
+ // Console log for debug
179
+ // console.log(`[Router Debug] File: ${filePath} -> Clean: ${cleanPath}`);
180
+ const pathPattern = segments.map(seg => {
181
+ if (seg.startsWith('[') && seg.endsWith(']')) {
182
+ const paramName = seg.slice(1, -1);
183
+ paramNames.push(paramName);
184
+ return '([^/]+)'; // Match any non-slash char
185
+ }
186
+ return seg; // Static segment
187
+ }).join('/');
188
+ // Generate Regex: Ensure it starts with ^/ and ends with $
189
+ // cleanPath modules like 'about' become '^/about$'
190
+ // root '' becomes '^/$'
191
+ const regexString = pathPattern ? `^/${pathPattern}$` : '^/$';
192
+ return {
193
+ regex: new RegExp(regexString),
194
+ paramNames,
195
+ originalPath: cleanPath
196
+ };
197
+ };
198
+ // Iterate all modules to find a match
199
+ // Note: In a real framework, you'd cache the route table.
200
+ // console.log('[Vista Router] Current Path (Normalized):', normalizedPath);
201
+ // console.log('[Vista Router] Modules Found:', Object.keys(modules));
202
+ for (const path in modules) {
203
+ // Only care about pages (index.tsx)
204
+ if (!path.endsWith('/index.tsx'))
205
+ continue;
206
+ const { regex, paramNames } = createRouteMatcher(path);
207
+ const match = normalizedPath.match(regex);
208
+ // console.log(`[Vista Router] Checking ${path} -> Regex: ${regex} -> Match: ${match ? 'YES' : 'NO'}`);
209
+ if (match) {
210
+ pageLoader = modules[path];
211
+ matchedRoutePath = path;
212
+ // Extract params
213
+ match.slice(1).forEach((val, index) => {
214
+ routeParams[paramNames[index]] = decodeURIComponent(val);
215
+ });
216
+ break; // Found first match (TODO: strict sorting Order)
217
+ }
218
+ }
219
+ if (!pageLoader) {
220
+ if (isMounted)
221
+ setComponentTree(_jsx("div", { className: "p-10 text-xl", children: "404 Not Found" }));
222
+ return;
223
+ }
224
+ // --- 2. Load Page & Layouts ---
225
+ const pageModule = await pageLoader();
226
+ let PageComponent = pageModule.default;
227
+ // Load Layouts: Climb up the directory tree from the page path
228
+ // e.g. /app/users/[id]/index.tsx
229
+ // Check: /app/users/[id]/layout.tsx
230
+ // Check: /app/users/layout.tsx
231
+ // Check: /app/layout.tsx
232
+ const layoutLoaders = [];
233
+ const dirSegments = matchedRoutePath.split('/').slice(0, -1); // remove index.tsx
234
+ // Construct potential layout paths from root down to leaf
235
+ // But we want to load them all.
236
+ // Actually, let's just create the list of all parent directories and check for layout.tsx
237
+ let currentDir = ''; // starts empty
238
+ const possibleLayouts = [];
239
+ // We know everything starts with /app
240
+ // dirSegments looks like ['', 'app', 'users', '[id]']
241
+ for (const segment of dirSegments) {
242
+ if (!segment)
243
+ continue;
244
+ currentDir += `/${segment}`;
245
+ const layoutPath = `${currentDir}/layout.tsx`;
246
+ if (modules[layoutPath]) {
247
+ possibleLayouts.push(layoutPath);
248
+ }
249
+ }
250
+ // Execute layout loaders
251
+ const layoutModules = await Promise.all(possibleLayouts.map(path => modules[path]()));
252
+ if (!isMounted)
253
+ return;
254
+ // Handle Metadata
255
+ let meta = pageModule.metadata || {};
256
+ layoutModules.forEach(mod => {
257
+ if (mod.metadata)
258
+ meta = { ...meta, ...mod.metadata };
259
+ });
260
+ if (meta.title)
261
+ document.title = meta.title;
262
+ // Build Tree: Wrap Page with Layouts (Inner -> Outer? NO. Outer wraps Inner.)
263
+ // layoutModules is [AppLayout, UsersLayout, UserIdLayout]
264
+ // We want <AppLayout><UsersLayout><UserIdLayout><Page /></...></...></...>
265
+ let Content = _jsx(PageComponent, { params: routeParams }); // Pass params to page!
266
+ // Reverse iterate to wrap from inside out
267
+ for (let i = layoutModules.length - 1; i >= 0; i--) {
268
+ const LayoutComponent = layoutModules[i].default;
269
+ Content = _jsx(LayoutComponent, { params: routeParams, children: Content });
270
+ }
271
+ setComponentTree(Content);
272
+ }
273
+ catch (err) {
274
+ console.error('[Vista] Failed to load route:', err);
275
+ if (isMounted)
276
+ setPageError(err);
277
+ }
278
+ };
279
+ loadRoute();
280
+ return () => { isMounted = false; };
281
+ }, [currentPath, modules]);
282
+ if (pageError) {
283
+ // Propagate to ErrorManager
284
+ throw pageError;
285
+ }
286
+ return componentTree;
287
+ }
288
+ function App({ modules }) {
289
+ return (_jsx(React.StrictMode, { children: _jsx(RouterProvider, { children: _jsx(AppContent, { modules: modules }) }) }));
290
+ }
@@ -0,0 +1,28 @@
1
+ import React from 'react';
2
+ type PixelBlastVariant = 'square' | 'circle' | 'triangle' | 'diamond';
3
+ export type PixelBlastProps = {
4
+ variant?: PixelBlastVariant;
5
+ pixelSize?: number;
6
+ color?: string;
7
+ className?: string;
8
+ style?: React.CSSProperties;
9
+ antialias?: boolean;
10
+ patternScale?: number;
11
+ patternDensity?: number;
12
+ liquid?: boolean;
13
+ liquidStrength?: number;
14
+ liquidRadius?: number;
15
+ pixelSizeJitter?: number;
16
+ enableRipples?: boolean;
17
+ rippleIntensityScale?: number;
18
+ rippleThickness?: number;
19
+ rippleSpeed?: number;
20
+ liquidWobbleSpeed?: number;
21
+ autoPauseOffscreen?: boolean;
22
+ speed?: number;
23
+ transparent?: boolean;
24
+ edgeFade?: number;
25
+ noiseAmount?: number;
26
+ };
27
+ declare const PixelBlast: React.FC<PixelBlastProps>;
28
+ export default PixelBlast;