fractostate 1.0.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/LICENSE +13 -0
- package/README.md +83 -0
- package/docs/api-reference.md +46 -0
- package/docs/architecture.md +27 -0
- package/docs/getting-started.md +94 -0
- package/package.json +37 -0
- package/src/index.ts +82 -0
- package/src/proxy.ts +313 -0
- package/src/store.ts +324 -0
- package/src/types.ts +126 -0
- package/test/README.md +73 -0
- package/test/eslint.config.js +23 -0
- package/test/index.html +13 -0
- package/test/package.json +47 -0
- package/test/postcss.config.mjs +7 -0
- package/test/public/vite.svg +1 -0
- package/test/src/App.css +42 -0
- package/test/src/App.tsx +44 -0
- package/test/src/assets/react.svg +1 -0
- package/test/src/components/CartDrawer.tsx +79 -0
- package/test/src/components/Navbar.tsx +48 -0
- package/test/src/components/Notifications.tsx +27 -0
- package/test/src/components/ProductList.tsx +56 -0
- package/test/src/flows.ts +7 -0
- package/test/src/index.css +33 -0
- package/test/src/layout/Layout.tsx +68 -0
- package/test/src/layout/ProtectedRoute.tsx +19 -0
- package/test/src/main.tsx +10 -0
- package/test/src/pages/LoginPage.tsx +86 -0
- package/test/src/pages/ProfilePage.tsx +48 -0
- package/test/src/pages/ShopPage.tsx +54 -0
- package/test/src/store/auth.ts +39 -0
- package/test/src/store/flows.ts +74 -0
- package/test/tsconfig.app.json +31 -0
- package/test/tsconfig.json +7 -0
- package/test/tsconfig.node.json +29 -0
- package/test/vite.config.ts +16 -0
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import { useFlow } from "fractostate";
|
|
2
|
+
import { AuthFlow } from "../store/auth";
|
|
3
|
+
import { CartFlow, UIFlow } from "../store/flows";
|
|
4
|
+
import { Link } from "react-router-dom";
|
|
5
|
+
|
|
6
|
+
export default function Layout({ children }: { children: React.ReactNode }) {
|
|
7
|
+
const [auth, { ops: authOps }] = useFlow(AuthFlow);
|
|
8
|
+
const [cart] = useFlow(CartFlow);
|
|
9
|
+
const [, { ops: uiOps }] = useFlow(UIFlow);
|
|
10
|
+
|
|
11
|
+
const cartCount = cart.items.reduce((acc, item) => acc + item.quantity, 0);
|
|
12
|
+
|
|
13
|
+
return (
|
|
14
|
+
<div className="min-h-screen bg-[#050505] selection:bg-brand selection:text-white pb-20">
|
|
15
|
+
{/* Header Global */}
|
|
16
|
+
<nav className="fixed top-0 left-0 right-0 h-16 glass z-50 flex items-center justify-between px-6">
|
|
17
|
+
<Link to="/" className="flex items-center gap-2">
|
|
18
|
+
<div className="w-8 h-8 bg-brand rounded flex items-center justify-center font-bold text-lg select-none">
|
|
19
|
+
F
|
|
20
|
+
</div>
|
|
21
|
+
<span className="font-bold text-xl tracking-tight hidden sm:inline">
|
|
22
|
+
FractoShop
|
|
23
|
+
</span>
|
|
24
|
+
</Link>
|
|
25
|
+
|
|
26
|
+
{auth.isAuthenticated && (
|
|
27
|
+
<div className="flex items-center gap-4">
|
|
28
|
+
{/* Cart Button */}
|
|
29
|
+
<button
|
|
30
|
+
onClick={() => uiOps.self.cartOpen.set(true)}
|
|
31
|
+
className="relative p-2 hover:bg-white/5 rounded-full transition-colors cursor-pointer mr-2"
|
|
32
|
+
>
|
|
33
|
+
<span className="text-2xl">🛒</span>
|
|
34
|
+
{cartCount > 0 && (
|
|
35
|
+
<span className="absolute -top-1 -right-1 bg-brand text-white text-[10px] font-bold px-1.5 py-0.5 rounded-full ring-2 ring-black">
|
|
36
|
+
{cartCount}
|
|
37
|
+
</span>
|
|
38
|
+
)}
|
|
39
|
+
</button>
|
|
40
|
+
|
|
41
|
+
<Link
|
|
42
|
+
to="/profile"
|
|
43
|
+
className="flex items-center gap-3 hover:bg-white/5 p-1.5 pr-4 rounded-full transition-colors"
|
|
44
|
+
>
|
|
45
|
+
<img
|
|
46
|
+
src={auth.user?.avatar}
|
|
47
|
+
className="w-8 h-8 rounded-full border border-white/10"
|
|
48
|
+
alt="Avatar"
|
|
49
|
+
/>
|
|
50
|
+
<span className="text-sm font-medium text-white/80 hidden md:inline">
|
|
51
|
+
{auth.user?.username}
|
|
52
|
+
</span>
|
|
53
|
+
</Link>
|
|
54
|
+
<button
|
|
55
|
+
onClick={() => authOps.self.isAuthenticated.set(false)}
|
|
56
|
+
className="text-xs text-red-400 hover:text-red-300 font-bold tracking-wider px-3 py-1.5 border border-red-500/20 rounded-lg hover:bg-red-500/10 transition-all"
|
|
57
|
+
>
|
|
58
|
+
LOGOUT
|
|
59
|
+
</button>
|
|
60
|
+
</div>
|
|
61
|
+
)}
|
|
62
|
+
</nav>
|
|
63
|
+
|
|
64
|
+
{/* Main Content Injection */}
|
|
65
|
+
{children}
|
|
66
|
+
</div>
|
|
67
|
+
);
|
|
68
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { useFlow } from "fractostate";
|
|
2
|
+
import { AuthFlow } from "../store/auth";
|
|
3
|
+
import { Navigate, useLocation } from "react-router-dom";
|
|
4
|
+
|
|
5
|
+
export default function ProtectedRoute({
|
|
6
|
+
children,
|
|
7
|
+
}: {
|
|
8
|
+
children: React.ReactNode;
|
|
9
|
+
}) {
|
|
10
|
+
const [auth] = useFlow(AuthFlow);
|
|
11
|
+
const location = useLocation();
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
if (!auth.isAuthenticated) {
|
|
15
|
+
return <Navigate to="/login" state={{ from: location }} replace />;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
return <>{children}</>;
|
|
19
|
+
}
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
import { useFlow } from "fractostate";
|
|
2
|
+
import { AuthFlow } from "../store/auth";
|
|
3
|
+
import { useNavigate } from "react-router-dom";
|
|
4
|
+
|
|
5
|
+
export default function LoginPage() {
|
|
6
|
+
const [auth, { ops: authOps }] = useFlow(AuthFlow);
|
|
7
|
+
const navigate = useNavigate();
|
|
8
|
+
|
|
9
|
+
const handleLogin = async (e: React.FormEvent) => {
|
|
10
|
+
e.preventDefault();
|
|
11
|
+
|
|
12
|
+
// Simulation API
|
|
13
|
+
authOps.self.isLoading.set(true);
|
|
14
|
+
|
|
15
|
+
// Fake Server Delay
|
|
16
|
+
await new Promise((r) => setTimeout(r, 1000));
|
|
17
|
+
|
|
18
|
+
// Update State (Native-like mutation via Proxy)
|
|
19
|
+
authOps.self.merge({
|
|
20
|
+
isAuthenticated: true,
|
|
21
|
+
user: {
|
|
22
|
+
username: "FractoDev",
|
|
23
|
+
avatar: "https://api.dicebear.com/7.x/bottts/svg?seed=Fracto",
|
|
24
|
+
role: "admin",
|
|
25
|
+
},
|
|
26
|
+
token: "fra_abc123_secure_token",
|
|
27
|
+
isLoading: false,
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
navigate("/");
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
return (
|
|
34
|
+
<div className="min-h-screen flex items-center justify-center bg-[#050505] p-4">
|
|
35
|
+
<div className="glass p-8 rounded-2xl w-full max-w-md border border-white/5 space-y-6">
|
|
36
|
+
<div className="text-center">
|
|
37
|
+
<div className="w-12 h-12 bg-brand rounded-lg mx-auto mb-4 flex items-center justify-center font-bold text-xl">
|
|
38
|
+
F
|
|
39
|
+
</div>
|
|
40
|
+
<h1 className="text-2xl font-bold">Welcome Back</h1>
|
|
41
|
+
<p className="text-white/40 text-sm">
|
|
42
|
+
Sign in to access the FractoState Demo
|
|
43
|
+
</p>
|
|
44
|
+
</div>
|
|
45
|
+
|
|
46
|
+
<form onSubmit={handleLogin} className="space-y-4">
|
|
47
|
+
<div className="space-y-2">
|
|
48
|
+
<label className="text-xs font-bold text-white/60 ml-1">
|
|
49
|
+
USERNAME
|
|
50
|
+
</label>
|
|
51
|
+
<input
|
|
52
|
+
type="text"
|
|
53
|
+
defaultValue="demo_user"
|
|
54
|
+
className="w-full bg-white/5 border border-white/10 rounded-lg px-4 py-3 outline-none focus:border-brand/50 transition-colors text-sm font-medium"
|
|
55
|
+
/>
|
|
56
|
+
</div>
|
|
57
|
+
<div className="space-y-2">
|
|
58
|
+
<label className="text-xs font-bold text-white/60 ml-1">
|
|
59
|
+
PASSWORD
|
|
60
|
+
</label>
|
|
61
|
+
<input
|
|
62
|
+
type="password"
|
|
63
|
+
defaultValue="password"
|
|
64
|
+
className="w-full bg-white/5 border border-white/10 rounded-lg px-4 py-3 outline-none focus:border-brand/50 transition-colors text-sm font-medium"
|
|
65
|
+
/>
|
|
66
|
+
</div>
|
|
67
|
+
|
|
68
|
+
<button
|
|
69
|
+
disabled={auth.isLoading}
|
|
70
|
+
className="w-full btn-primary py-3 font-bold mt-4 flex items-center justify-center gap-2"
|
|
71
|
+
>
|
|
72
|
+
{auth.isLoading ? (
|
|
73
|
+
<span className="animate-spin text-lg">⏳</span>
|
|
74
|
+
) : (
|
|
75
|
+
"Sign In"
|
|
76
|
+
)}
|
|
77
|
+
</button>
|
|
78
|
+
</form>
|
|
79
|
+
|
|
80
|
+
<p className="text-center text-xs text-white/20">
|
|
81
|
+
Powered by FractoState Secure Vault
|
|
82
|
+
</p>
|
|
83
|
+
</div>
|
|
84
|
+
</div>
|
|
85
|
+
);
|
|
86
|
+
}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import { useFlow } from "fractostate";
|
|
2
|
+
import { AuthFlow } from "../store/auth";
|
|
3
|
+
|
|
4
|
+
export default function ProfilePage() {
|
|
5
|
+
const [auth] = useFlow(AuthFlow);
|
|
6
|
+
|
|
7
|
+
return (
|
|
8
|
+
<div className="pt-32 px-6 max-w-4xl mx-auto">
|
|
9
|
+
<div className="glass p-8 rounded-2xl border border-white/5 flex items-start gap-8">
|
|
10
|
+
<img
|
|
11
|
+
src={auth.user?.avatar}
|
|
12
|
+
className="w-32 h-32 rounded-2xl border-2 border-brand shadow-lg shadow-brand/20"
|
|
13
|
+
alt="Profile"
|
|
14
|
+
/>
|
|
15
|
+
<div className="space-y-4 flex-1">
|
|
16
|
+
<div>
|
|
17
|
+
<h1 className="text-3xl font-bold">{auth.user?.username}</h1>
|
|
18
|
+
<span className="bg-brand/20 text-brand text-[10px] font-bold px-2 py-1 rounded uppercase tracking-widest border border-brand/20">
|
|
19
|
+
{auth.user?.role}
|
|
20
|
+
</span>
|
|
21
|
+
</div>
|
|
22
|
+
|
|
23
|
+
<div className="grid grid-cols-2 gap-4 pt-4">
|
|
24
|
+
<div className="bg-white/5 p-4 rounded-xl">
|
|
25
|
+
<span className="text-xs text-white/40 font-bold block mb-1">
|
|
26
|
+
SESSION TOKEN
|
|
27
|
+
</span>
|
|
28
|
+
<code className="text-xs font-mono text-brand truncate block">
|
|
29
|
+
{auth.token}
|
|
30
|
+
</code>
|
|
31
|
+
</div>
|
|
32
|
+
<div className="bg-white/5 p-4 rounded-xl">
|
|
33
|
+
<span className="text-xs text-white/40 font-bold block mb-1">
|
|
34
|
+
AUTH STATUS
|
|
35
|
+
</span>
|
|
36
|
+
<div className="flex items-center gap-2">
|
|
37
|
+
<span className="w-2 h-2 bg-green-500 rounded-full animate-pulse" />
|
|
38
|
+
<span className="text-xs font-bold text-white/80">
|
|
39
|
+
Active & Secure
|
|
40
|
+
</span>
|
|
41
|
+
</div>
|
|
42
|
+
</div>
|
|
43
|
+
</div>
|
|
44
|
+
</div>
|
|
45
|
+
</div>
|
|
46
|
+
</div>
|
|
47
|
+
);
|
|
48
|
+
}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import { useFlow } from "fractostate";
|
|
2
|
+
import { ShopFlow } from "../store/flows";
|
|
3
|
+
import ProductList from "../components/ProductList";
|
|
4
|
+
import CartDrawer from "../components/CartDrawer";
|
|
5
|
+
import Notifications from "../components/Notifications";
|
|
6
|
+
|
|
7
|
+
export default function ShopPage() {
|
|
8
|
+
const [shop, { ops: shopOps }] = useFlow(ShopFlow);
|
|
9
|
+
|
|
10
|
+
return (
|
|
11
|
+
<>
|
|
12
|
+
<CartDrawer />
|
|
13
|
+
<Notifications />
|
|
14
|
+
|
|
15
|
+
<main className="max-w-7xl mx-auto">
|
|
16
|
+
<header className="px-6 pt-32 pb-4 text-center">
|
|
17
|
+
<h1 className="text-4xl md:text-6xl font-black mb-4 bg-gradient-to-r from-white to-white/40 bg-clip-text text-transparent italic tracking-tighter">
|
|
18
|
+
THE FUTURE OF STATE.
|
|
19
|
+
</h1>
|
|
20
|
+
<p className="text-white/40 font-medium max-w-xl mx-auto">
|
|
21
|
+
This entire application runs on{" "}
|
|
22
|
+
<span className="text-brand font-bold uppercase tracking-widest text-xs px-1">
|
|
23
|
+
FractoState
|
|
24
|
+
</span>
|
|
25
|
+
. Zero Prop-Drilling. Zero Context Providers. Ultra-fast surgical
|
|
26
|
+
updates.
|
|
27
|
+
</p>
|
|
28
|
+
</header>
|
|
29
|
+
|
|
30
|
+
<section className="mt-8">
|
|
31
|
+
<div className="px-6 flex items-center justify-between mb-8">
|
|
32
|
+
<h2 className="text-2xl font-bold flex items-center gap-2">
|
|
33
|
+
<span className="w-8 h-[2px] bg-brand inline-block" /> Latest
|
|
34
|
+
Drops
|
|
35
|
+
</h2>
|
|
36
|
+
<div className="flex gap-2">
|
|
37
|
+
{["All", "Electronics", "Apparel", "Accessories"].map((cat) => (
|
|
38
|
+
<button
|
|
39
|
+
key={cat}
|
|
40
|
+
onClick={() => shopOps.self.category.set(cat)}
|
|
41
|
+
className={`text-xs font-bold px-4 py-1.5 rounded-full transition-all cursor-pointer ${shop.category === cat ? "bg-brand text-white shadow-lg shadow-brand/20" : "bg-white/5 hover:bg-white/10 text-white/60"}`}
|
|
42
|
+
>
|
|
43
|
+
{cat}
|
|
44
|
+
</button>
|
|
45
|
+
))}
|
|
46
|
+
</div>
|
|
47
|
+
</div>
|
|
48
|
+
|
|
49
|
+
<ProductList />
|
|
50
|
+
</section>
|
|
51
|
+
</main>
|
|
52
|
+
</>
|
|
53
|
+
);
|
|
54
|
+
}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { defineFlow } from "fractostate";
|
|
2
|
+
|
|
3
|
+
export interface User {
|
|
4
|
+
username: string;
|
|
5
|
+
avatar: string;
|
|
6
|
+
role: "admin" | "user";
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
export interface AuthState {
|
|
10
|
+
isAuthenticated: boolean;
|
|
11
|
+
user: User | null;
|
|
12
|
+
token: string | null;
|
|
13
|
+
isLoading: boolean;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
// Simulons une persistance basique en lisant le localStorage au démarrage (si on le voulait vraiment)
|
|
17
|
+
// Pour l'instant, on part de zéro pour la démo.
|
|
18
|
+
|
|
19
|
+
export const AuthFlow = defineFlow<AuthState>(
|
|
20
|
+
"auth",
|
|
21
|
+
{
|
|
22
|
+
isAuthenticated: false,
|
|
23
|
+
user: null,
|
|
24
|
+
token: null,
|
|
25
|
+
isLoading: false,
|
|
26
|
+
},
|
|
27
|
+
{
|
|
28
|
+
// Middleware pour logger les actions d'auth (ex: sécu)
|
|
29
|
+
middleware: [
|
|
30
|
+
(state) => {
|
|
31
|
+
console.log(
|
|
32
|
+
"[Auth Audit]:",
|
|
33
|
+
state.isAuthenticated ? "User Logged In" : "User Guest",
|
|
34
|
+
);
|
|
35
|
+
return state;
|
|
36
|
+
},
|
|
37
|
+
],
|
|
38
|
+
},
|
|
39
|
+
);
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
import { defineFlow } from "fractostate";
|
|
2
|
+
|
|
3
|
+
export interface Product {
|
|
4
|
+
id: number;
|
|
5
|
+
name: string;
|
|
6
|
+
price: number;
|
|
7
|
+
image: string;
|
|
8
|
+
category: string;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export interface CartItem extends Product {
|
|
12
|
+
quantity: number;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
// --- Cart Flow ---
|
|
16
|
+
export const CartFlow = defineFlow<{ items: CartItem[] }>("cart", {
|
|
17
|
+
items: [],
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
// --- User Flow ---
|
|
21
|
+
export const UserFlow = defineFlow<{
|
|
22
|
+
name: string;
|
|
23
|
+
isPremium: boolean;
|
|
24
|
+
avatar: string;
|
|
25
|
+
}>("user", {
|
|
26
|
+
name: "Marc Ansene",
|
|
27
|
+
isPremium: true,
|
|
28
|
+
avatar: "https://api.dicebear.com/7.x/avataaars/svg?seed=Marc",
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
// --- Shop Flow ---
|
|
32
|
+
export const ShopProducts = [
|
|
33
|
+
{
|
|
34
|
+
id: 1,
|
|
35
|
+
name: "Fractal Watch",
|
|
36
|
+
price: 299,
|
|
37
|
+
category: "Accessories",
|
|
38
|
+
image: "⌚",
|
|
39
|
+
},
|
|
40
|
+
{ id: 2, name: "Neon Hoodie", price: 89, category: "Apparel", image: "🧥" },
|
|
41
|
+
{
|
|
42
|
+
id: 3,
|
|
43
|
+
name: "Quantum Buds",
|
|
44
|
+
price: 159,
|
|
45
|
+
category: "Electronics",
|
|
46
|
+
image: "🎧",
|
|
47
|
+
},
|
|
48
|
+
{
|
|
49
|
+
id: 4,
|
|
50
|
+
name: "Void Keyboard",
|
|
51
|
+
price: 199,
|
|
52
|
+
category: "Electronics",
|
|
53
|
+
image: "⌨️",
|
|
54
|
+
},
|
|
55
|
+
];
|
|
56
|
+
|
|
57
|
+
export const ShopFlow = defineFlow<{
|
|
58
|
+
loading: boolean;
|
|
59
|
+
category: string;
|
|
60
|
+
search: string;
|
|
61
|
+
}>("shop", {
|
|
62
|
+
loading: false,
|
|
63
|
+
category: "All",
|
|
64
|
+
search: "",
|
|
65
|
+
});
|
|
66
|
+
|
|
67
|
+
// --- UI / Notification Flow ---
|
|
68
|
+
export const UIFlow = defineFlow<{
|
|
69
|
+
cartOpen: boolean;
|
|
70
|
+
notifications: { id: number; text: string; type: "success" | "error" }[];
|
|
71
|
+
}>("ui", {
|
|
72
|
+
cartOpen: false,
|
|
73
|
+
notifications: [],
|
|
74
|
+
});
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
{
|
|
2
|
+
"compilerOptions": {
|
|
3
|
+
"tsBuildInfoFile": "./node_modules/.tmp/tsconfig.app.tsbuildinfo",
|
|
4
|
+
"target": "ES2022",
|
|
5
|
+
"useDefineForClassFields": true,
|
|
6
|
+
"lib": ["ES2022", "DOM", "DOM.Iterable"],
|
|
7
|
+
"module": "ESNext",
|
|
8
|
+
"types": ["vite/client"],
|
|
9
|
+
"skipLibCheck": true,
|
|
10
|
+
"paths": {
|
|
11
|
+
"fractostate": ["../src"]
|
|
12
|
+
},
|
|
13
|
+
|
|
14
|
+
/* Bundler mode */
|
|
15
|
+
"moduleResolution": "bundler",
|
|
16
|
+
"allowImportingTsExtensions": true,
|
|
17
|
+
"verbatimModuleSyntax": true,
|
|
18
|
+
"moduleDetection": "force",
|
|
19
|
+
"noEmit": true,
|
|
20
|
+
"jsx": "react-jsx",
|
|
21
|
+
|
|
22
|
+
/* Linting */
|
|
23
|
+
"strict": true,
|
|
24
|
+
"noUnusedLocals": true,
|
|
25
|
+
"noUnusedParameters": true,
|
|
26
|
+
"erasableSyntaxOnly": true,
|
|
27
|
+
"noFallthroughCasesInSwitch": true,
|
|
28
|
+
"noUncheckedSideEffectImports": true
|
|
29
|
+
},
|
|
30
|
+
"include": ["src", "postcss.config.mjs"]
|
|
31
|
+
}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
{
|
|
2
|
+
"compilerOptions": {
|
|
3
|
+
"tsBuildInfoFile": "./node_modules/.tmp/tsconfig.node.tsbuildinfo",
|
|
4
|
+
"target": "ES2023",
|
|
5
|
+
"lib": ["ES2023"],
|
|
6
|
+
"module": "ESNext",
|
|
7
|
+
"types": ["node"],
|
|
8
|
+
"skipLibCheck": true,
|
|
9
|
+
|
|
10
|
+
/* Bundler mode */
|
|
11
|
+
"moduleResolution": "bundler",
|
|
12
|
+
"allowImportingTsExtensions": true,
|
|
13
|
+
"verbatimModuleSyntax": true,
|
|
14
|
+
"moduleDetection": "force",
|
|
15
|
+
"noEmit": true,
|
|
16
|
+
|
|
17
|
+
/* Linting */
|
|
18
|
+
"strict": true,
|
|
19
|
+
"noUnusedLocals": true,
|
|
20
|
+
"noUnusedParameters": true,
|
|
21
|
+
"erasableSyntaxOnly": true,
|
|
22
|
+
"noFallthroughCasesInSwitch": true,
|
|
23
|
+
"noUncheckedSideEffectImports": true,
|
|
24
|
+
"paths": {
|
|
25
|
+
"fractostate": ["../src"]
|
|
26
|
+
}
|
|
27
|
+
},
|
|
28
|
+
"include": ["vite.config.ts"]
|
|
29
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { defineConfig } from "vite";
|
|
2
|
+
import react from "@vitejs/plugin-react";
|
|
3
|
+
|
|
4
|
+
import path from "path";
|
|
5
|
+
|
|
6
|
+
// https://vite.dev/config/
|
|
7
|
+
export default defineConfig({
|
|
8
|
+
plugins: [react()],
|
|
9
|
+
resolve: {
|
|
10
|
+
alias: {
|
|
11
|
+
fractostate: path.resolve(__dirname, "../src"),
|
|
12
|
+
react: path.resolve(__dirname, "./node_modules/react"),
|
|
13
|
+
"react-dom": path.resolve(__dirname, "./node_modules/react-dom"),
|
|
14
|
+
},
|
|
15
|
+
},
|
|
16
|
+
});
|