jac-client 0.2.3__py3-none-any.whl → 0.2.4__py3-none-any.whl
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.
- jac_client/examples/all-in-one/assets/workers/worker.py +5 -0
- jac_client/tests/conftest.py +281 -0
- jac_client/tests/test_cli.py +755 -0
- jac_client/tests/test_it.py +347 -67
- {jac_client-0.2.3.dist-info → jac_client-0.2.4.dist-info}/METADATA +28 -30
- jac_client-0.2.4.dist-info/RECORD +10 -0
- {jac_client-0.2.3.dist-info → jac_client-0.2.4.dist-info}/WHEEL +2 -1
- jac_client-0.2.4.dist-info/entry_points.txt +4 -0
- jac_client-0.2.4.dist-info/top_level.txt +1 -0
- jac_client/docs/README.md +0 -689
- jac_client/docs/advanced-state.md +0 -1265
- jac_client/docs/asset-serving/intro.md +0 -209
- jac_client/docs/assets/pipe_line-v2.svg +0 -32
- jac_client/docs/assets/pipe_line.png +0 -0
- jac_client/docs/file-system/app.jac.md +0 -121
- jac_client/docs/file-system/backend-frontend.md +0 -217
- jac_client/docs/file-system/intro.md +0 -72
- jac_client/docs/file-system/nested-imports.md +0 -348
- jac_client/docs/guide-example/intro.md +0 -115
- jac_client/docs/guide-example/step-01-setup.md +0 -270
- jac_client/docs/guide-example/step-02-components.md +0 -416
- jac_client/docs/guide-example/step-03-styling.md +0 -478
- jac_client/docs/guide-example/step-04-todo-ui.md +0 -477
- jac_client/docs/guide-example/step-05-local-state.md +0 -530
- jac_client/docs/guide-example/step-06-events.md +0 -749
- jac_client/docs/guide-example/step-07-effects.md +0 -468
- jac_client/docs/guide-example/step-08-walkers.md +0 -534
- jac_client/docs/guide-example/step-09-authentication.md +0 -586
- jac_client/docs/guide-example/step-10-routing.md +0 -539
- jac_client/docs/guide-example/step-11-final.md +0 -963
- jac_client/docs/imports.md +0 -1141
- jac_client/docs/lifecycle-hooks.md +0 -773
- jac_client/docs/routing.md +0 -659
- jac_client/docs/styling/intro.md +0 -249
- jac_client/docs/styling/js-styling.md +0 -367
- jac_client/docs/styling/material-ui.md +0 -341
- jac_client/docs/styling/pure-css.md +0 -299
- jac_client/docs/styling/sass.md +0 -403
- jac_client/docs/styling/styled-components.md +0 -395
- jac_client/docs/styling/tailwind.md +0 -298
- jac_client/examples/all-in-one/.babelrc +0 -9
- jac_client/examples/all-in-one/README.md +0 -16
- jac_client/examples/all-in-one/app.jac +0 -426
- jac_client/examples/all-in-one/assets/burger.png +0 -0
- jac_client/examples/all-in-one/button.jac +0 -7
- jac_client/examples/all-in-one/components/button.jac +0 -7
- jac_client/examples/all-in-one/package.json +0 -29
- jac_client/examples/all-in-one/styles.css +0 -26
- jac_client/examples/all-in-one/vite.config.js +0 -28
- jac_client/examples/asset-serving/css-with-image/.babelrc +0 -9
- jac_client/examples/asset-serving/css-with-image/README.md +0 -91
- jac_client/examples/asset-serving/css-with-image/app.jac +0 -88
- jac_client/examples/asset-serving/css-with-image/assets/burger.png +0 -0
- jac_client/examples/asset-serving/css-with-image/package.json +0 -28
- jac_client/examples/asset-serving/css-with-image/styles.css +0 -26
- jac_client/examples/asset-serving/css-with-image/vite.config.js +0 -28
- jac_client/examples/asset-serving/image-asset/.babelrc +0 -9
- jac_client/examples/asset-serving/image-asset/README.md +0 -119
- jac_client/examples/asset-serving/image-asset/app.jac +0 -55
- jac_client/examples/asset-serving/image-asset/assets/burger.png +0 -0
- jac_client/examples/asset-serving/image-asset/package.json +0 -28
- jac_client/examples/asset-serving/image-asset/styles.css +0 -26
- jac_client/examples/asset-serving/image-asset/vite.config.js +0 -28
- jac_client/examples/asset-serving/import-alias/.babelrc +0 -9
- jac_client/examples/asset-serving/import-alias/README.md +0 -83
- jac_client/examples/asset-serving/import-alias/app.jac +0 -111
- jac_client/examples/asset-serving/import-alias/assets/burger.png +0 -0
- jac_client/examples/asset-serving/import-alias/package.json +0 -28
- jac_client/examples/asset-serving/import-alias/vite.config.js +0 -28
- jac_client/examples/basic/.babelrc +0 -9
- jac_client/examples/basic/README.md +0 -16
- jac_client/examples/basic/app.jac +0 -21
- jac_client/examples/basic/package.json +0 -27
- jac_client/examples/basic/vite.config.js +0 -27
- jac_client/examples/basic-auth/.babelrc +0 -9
- jac_client/examples/basic-auth/README.md +0 -16
- jac_client/examples/basic-auth/app.jac +0 -308
- jac_client/examples/basic-auth/package.json +0 -27
- jac_client/examples/basic-auth/vite.config.js +0 -27
- jac_client/examples/basic-auth-with-router/.babelrc +0 -9
- jac_client/examples/basic-auth-with-router/README.md +0 -60
- jac_client/examples/basic-auth-with-router/app.jac +0 -464
- jac_client/examples/basic-auth-with-router/package.json +0 -28
- jac_client/examples/basic-auth-with-router/vite.config.js +0 -27
- jac_client/examples/basic-full-stack/.babelrc +0 -9
- jac_client/examples/basic-full-stack/README.md +0 -18
- jac_client/examples/basic-full-stack/app.jac +0 -320
- jac_client/examples/basic-full-stack/package.json +0 -28
- jac_client/examples/basic-full-stack/vite.config.js +0 -27
- jac_client/examples/css-styling/js-styling/.babelrc +0 -9
- jac_client/examples/css-styling/js-styling/README.md +0 -183
- jac_client/examples/css-styling/js-styling/app.jac +0 -84
- jac_client/examples/css-styling/js-styling/package.json +0 -28
- jac_client/examples/css-styling/js-styling/styles.js +0 -100
- jac_client/examples/css-styling/js-styling/vite.config.js +0 -27
- jac_client/examples/css-styling/material-ui/.babelrc +0 -9
- jac_client/examples/css-styling/material-ui/README.md +0 -16
- jac_client/examples/css-styling/material-ui/app.jac +0 -122
- jac_client/examples/css-styling/material-ui/package.json +0 -32
- jac_client/examples/css-styling/material-ui/vite.config.js +0 -27
- jac_client/examples/css-styling/pure-css/.babelrc +0 -9
- jac_client/examples/css-styling/pure-css/README.md +0 -16
- jac_client/examples/css-styling/pure-css/app.jac +0 -64
- jac_client/examples/css-styling/pure-css/package.json +0 -28
- jac_client/examples/css-styling/pure-css/styles.css +0 -111
- jac_client/examples/css-styling/pure-css/vite.config.js +0 -27
- jac_client/examples/css-styling/sass-example/.babelrc +0 -9
- jac_client/examples/css-styling/sass-example/README.md +0 -16
- jac_client/examples/css-styling/sass-example/app.jac +0 -64
- jac_client/examples/css-styling/sass-example/package.json +0 -29
- jac_client/examples/css-styling/sass-example/styles.scss +0 -153
- jac_client/examples/css-styling/sass-example/vite.config.js +0 -27
- jac_client/examples/css-styling/styled-components/.babelrc +0 -9
- jac_client/examples/css-styling/styled-components/README.md +0 -16
- jac_client/examples/css-styling/styled-components/app.jac +0 -71
- jac_client/examples/css-styling/styled-components/package.json +0 -29
- jac_client/examples/css-styling/styled-components/styled.js +0 -90
- jac_client/examples/css-styling/styled-components/vite.config.js +0 -27
- jac_client/examples/css-styling/tailwind-example/.babelrc +0 -9
- jac_client/examples/css-styling/tailwind-example/README.md +0 -16
- jac_client/examples/css-styling/tailwind-example/app.jac +0 -63
- jac_client/examples/css-styling/tailwind-example/global.css +0 -1
- jac_client/examples/css-styling/tailwind-example/package.json +0 -30
- jac_client/examples/css-styling/tailwind-example/vite.config.js +0 -29
- jac_client/examples/full-stack-with-auth/.babelrc +0 -9
- jac_client/examples/full-stack-with-auth/README.md +0 -16
- jac_client/examples/full-stack-with-auth/app.jac +0 -722
- jac_client/examples/full-stack-with-auth/package.json +0 -28
- jac_client/examples/full-stack-with-auth/vite.config.js +0 -29
- jac_client/examples/little-x/app.jac +0 -724
- jac_client/examples/little-x/package.json +0 -23
- jac_client/examples/little-x/submit-button.jac +0 -8
- jac_client/examples/nested-folders/nested-advance/.babelrc +0 -9
- jac_client/examples/nested-folders/nested-advance/ButtonRoot.jac +0 -11
- jac_client/examples/nested-folders/nested-advance/README.md +0 -77
- jac_client/examples/nested-folders/nested-advance/app.jac +0 -35
- jac_client/examples/nested-folders/nested-advance/level1/ButtonSecondL.jac +0 -19
- jac_client/examples/nested-folders/nested-advance/level1/Card.jac +0 -43
- jac_client/examples/nested-folders/nested-advance/level1/level2/ButtonThirdL.jac +0 -25
- jac_client/examples/nested-folders/nested-advance/package.json +0 -29
- jac_client/examples/nested-folders/nested-advance/vite.config.js +0 -28
- jac_client/examples/nested-folders/nested-basic/.babelrc +0 -9
- jac_client/examples/nested-folders/nested-basic/README.md +0 -183
- jac_client/examples/nested-folders/nested-basic/app.jac +0 -13
- jac_client/examples/nested-folders/nested-basic/app.js +0 -7
- jac_client/examples/nested-folders/nested-basic/button.jac +0 -7
- jac_client/examples/nested-folders/nested-basic/components/button.jac +0 -7
- jac_client/examples/nested-folders/nested-basic/package.json +0 -28
- jac_client/examples/nested-folders/nested-basic/vite.config.js +0 -27
- jac_client/examples/with-router/.babelrc +0 -9
- jac_client/examples/with-router/README.md +0 -17
- jac_client/examples/with-router/app.jac +0 -323
- jac_client/examples/with-router/package.json +0 -28
- jac_client/examples/with-router/vite.config.js +0 -27
- jac_client/plugin/cli.py +0 -244
- jac_client/plugin/client.py +0 -152
- jac_client/plugin/client_runtime.jac +0 -234
- jac_client/plugin/vite_client_bundle.py +0 -503
- jac_client/tests/fixtures/basic-app/app.jac +0 -23
- jac_client/tests/fixtures/cl_file/app.cl.jac +0 -48
- jac_client/tests/fixtures/cl_file/app.jac +0 -15
- jac_client/tests/fixtures/client_app_with_antd/app.jac +0 -34
- jac_client/tests/fixtures/js_import/app.jac +0 -34
- jac_client/tests/fixtures/js_import/utils.js +0 -21
- jac_client/tests/fixtures/package-lock.json +0 -329
- jac_client/tests/fixtures/package.json +0 -11
- jac_client/tests/fixtures/relative_import/app.jac +0 -11
- jac_client/tests/fixtures/relative_import/button.jac +0 -7
- jac_client/tests/fixtures/spawn_test/app.jac +0 -129
- jac_client/tests/fixtures/test_fragments_spread/app.jac +0 -67
- jac_client/tests/test_asset_examples.py +0 -322
- jac_client/tests/test_cl.py +0 -530
- jac_client/tests/test_create_jac_app.py +0 -131
- jac_client/tests/test_nested_file.py +0 -374
- jac_client-0.2.3.dist-info/RECORD +0 -171
- jac_client-0.2.3.dist-info/entry_points.txt +0 -4
|
@@ -1,28 +0,0 @@
|
|
|
1
|
-
|
|
2
|
-
import { defineConfig } from "vite";
|
|
3
|
-
import path from "path";
|
|
4
|
-
import { fileURLToPath } from "url";
|
|
5
|
-
|
|
6
|
-
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
|
7
|
-
|
|
8
|
-
export default defineConfig({
|
|
9
|
-
root: ".", // base folder
|
|
10
|
-
build: {
|
|
11
|
-
rollupOptions: {
|
|
12
|
-
input: "build/main.js", // your compiled entry file
|
|
13
|
-
output: {
|
|
14
|
-
entryFileNames: "client.[hash].js", // name of the final js file
|
|
15
|
-
assetFileNames: "[name].[ext]",
|
|
16
|
-
},
|
|
17
|
-
},
|
|
18
|
-
outDir: "dist", // final bundled output
|
|
19
|
-
emptyOutDir: true,
|
|
20
|
-
},
|
|
21
|
-
publicDir: false,
|
|
22
|
-
resolve: {
|
|
23
|
-
alias: {
|
|
24
|
-
"@jac-client/utils": path.resolve(__dirname, "src/client_runtime.js"),
|
|
25
|
-
"@jac-client/assets": path.resolve(__dirname, "src/assets"),
|
|
26
|
-
},
|
|
27
|
-
},
|
|
28
|
-
});
|
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
# Pages
|
|
2
|
-
cl import from react { useState, useEffect }
|
|
3
|
-
cl {
|
|
4
|
-
def app() -> any {
|
|
5
|
-
let [count, setCount] = useState(0);
|
|
6
|
-
useEffect(lambda -> None{ console.log("Count: ", count);} , [count]);
|
|
7
|
-
return <div>
|
|
8
|
-
<h1>
|
|
9
|
-
Hello, World!
|
|
10
|
-
</h1>
|
|
11
|
-
<p>
|
|
12
|
-
Count: {count}
|
|
13
|
-
</p>
|
|
14
|
-
<button
|
|
15
|
-
onClick={lambda e: any -> None{ setCount(count + 1);} }
|
|
16
|
-
>
|
|
17
|
-
Increment
|
|
18
|
-
</button>
|
|
19
|
-
</div>;
|
|
20
|
-
}
|
|
21
|
-
}
|
|
@@ -1,27 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "my-app",
|
|
3
|
-
"version": "1.0.0",
|
|
4
|
-
"main": "index.js",
|
|
5
|
-
"scripts": {
|
|
6
|
-
"build": "npm run compile && vite build",
|
|
7
|
-
"dev": "vite dev",
|
|
8
|
-
"preview": "vite preview",
|
|
9
|
-
"compile": "babel src --out-dir build --extensions \".jsx,.js\" --out-file-extension .js"
|
|
10
|
-
},
|
|
11
|
-
"keywords": [],
|
|
12
|
-
"author": "",
|
|
13
|
-
"license": "ISC",
|
|
14
|
-
"description": "Jac application: my-app",
|
|
15
|
-
"type": "module",
|
|
16
|
-
"devDependencies": {
|
|
17
|
-
"vite": "^6.4.1",
|
|
18
|
-
"@babel/cli": "^7.28.3",
|
|
19
|
-
"@babel/core": "^7.28.5",
|
|
20
|
-
"@babel/preset-env": "^7.28.5",
|
|
21
|
-
"@babel/preset-react": "^7.28.5"
|
|
22
|
-
},
|
|
23
|
-
"dependencies": {
|
|
24
|
-
"react": "^19.2.0",
|
|
25
|
-
"react-dom": "^19.2.0"
|
|
26
|
-
}
|
|
27
|
-
}
|
|
@@ -1,27 +0,0 @@
|
|
|
1
|
-
|
|
2
|
-
import { defineConfig } from "vite";
|
|
3
|
-
import path from "path";
|
|
4
|
-
import { fileURLToPath } from "url";
|
|
5
|
-
|
|
6
|
-
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
|
7
|
-
|
|
8
|
-
export default defineConfig({
|
|
9
|
-
root: ".", // base folder
|
|
10
|
-
build: {
|
|
11
|
-
rollupOptions: {
|
|
12
|
-
input: "build/main.js", // your compiled entry file
|
|
13
|
-
output: {
|
|
14
|
-
entryFileNames: "client.[hash].js", // name of the final js file
|
|
15
|
-
assetFileNames: "[name].[ext]",
|
|
16
|
-
},
|
|
17
|
-
},
|
|
18
|
-
outDir: "dist", // final bundled output
|
|
19
|
-
emptyOutDir: true,
|
|
20
|
-
},
|
|
21
|
-
publicDir: false,
|
|
22
|
-
resolve: {
|
|
23
|
-
alias: {
|
|
24
|
-
"@jac-client/utils": path.resolve(__dirname, "src/client_runtime.js"),
|
|
25
|
-
},
|
|
26
|
-
},
|
|
27
|
-
});
|
|
@@ -1,308 +0,0 @@
|
|
|
1
|
-
# Simple Authentication App with Jac Client Utils
|
|
2
|
-
cl import from react {useState, useEffect}
|
|
3
|
-
cl import from '@jac-client/utils' {jacSignup, jacLogin, jacLogout, jacIsLoggedIn}
|
|
4
|
-
|
|
5
|
-
cl {
|
|
6
|
-
def app() -> any {
|
|
7
|
-
let [isLoggedIn, setIsLoggedIn] = useState(False);
|
|
8
|
-
let [isSignup, setIsSignup] = useState(False);
|
|
9
|
-
let [username, setUsername] = useState("");
|
|
10
|
-
let [password, setPassword] = useState("");
|
|
11
|
-
let [error, setError] = useState("");
|
|
12
|
-
let [loading, setLoading] = useState(False);
|
|
13
|
-
|
|
14
|
-
# Check login status on mount
|
|
15
|
-
useEffect(lambda -> None {
|
|
16
|
-
setIsLoggedIn(jacIsLoggedIn());
|
|
17
|
-
}, []);
|
|
18
|
-
|
|
19
|
-
# Handle login
|
|
20
|
-
async def handleLogin() -> None {
|
|
21
|
-
setError("");
|
|
22
|
-
if not username.trim() or not password {
|
|
23
|
-
setError("Please fill in all fields");
|
|
24
|
-
return;
|
|
25
|
-
}
|
|
26
|
-
setLoading(True);
|
|
27
|
-
success = await jacLogin(username, password);
|
|
28
|
-
setLoading(False);
|
|
29
|
-
if success {
|
|
30
|
-
setIsLoggedIn(True);
|
|
31
|
-
setUsername("");
|
|
32
|
-
setPassword("");
|
|
33
|
-
} else {
|
|
34
|
-
setError("Invalid username or password");
|
|
35
|
-
}
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
# Handle signup
|
|
39
|
-
async def handleSignup() -> None {
|
|
40
|
-
setError("");
|
|
41
|
-
if not username.trim() or not password {
|
|
42
|
-
setError("Please fill in all fields");
|
|
43
|
-
return;
|
|
44
|
-
}
|
|
45
|
-
if password.length < 6 {
|
|
46
|
-
setError("Password must be at least 6 characters");
|
|
47
|
-
return;
|
|
48
|
-
}
|
|
49
|
-
setLoading(True);
|
|
50
|
-
result = await jacSignup(username, password);
|
|
51
|
-
setLoading(False);
|
|
52
|
-
if result["success"] {
|
|
53
|
-
setIsLoggedIn(True);
|
|
54
|
-
setUsername("");
|
|
55
|
-
setPassword("");
|
|
56
|
-
} else {
|
|
57
|
-
setError(result["error"] if result["error"] else "Signup failed");
|
|
58
|
-
}
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
# Handle logout
|
|
62
|
-
def handleLogout() -> None {
|
|
63
|
-
jacLogout();
|
|
64
|
-
setIsLoggedIn(False);
|
|
65
|
-
setUsername("");
|
|
66
|
-
setPassword("");
|
|
67
|
-
setError("");
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
# Handle form submit
|
|
71
|
-
async def handleSubmit(e: any) -> None {
|
|
72
|
-
e.preventDefault();
|
|
73
|
-
if isSignup {
|
|
74
|
-
await handleSignup();
|
|
75
|
-
} else {
|
|
76
|
-
await handleLogin();
|
|
77
|
-
}
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
# Logged in view - Dashboard
|
|
81
|
-
if isLoggedIn {
|
|
82
|
-
return <div style={{
|
|
83
|
-
"minHeight": "100vh",
|
|
84
|
-
"background": "linear-gradient(135deg, #667eea 0%, #764ba2 100%)",
|
|
85
|
-
"display": "flex",
|
|
86
|
-
"alignItems": "center",
|
|
87
|
-
"justifyContent": "center",
|
|
88
|
-
"fontFamily": "system-ui, -apple-system, sans-serif"
|
|
89
|
-
}}>
|
|
90
|
-
<div style={{
|
|
91
|
-
"background": "#ffffff",
|
|
92
|
-
"borderRadius": "16px",
|
|
93
|
-
"padding": "48px",
|
|
94
|
-
"boxShadow": "0 20px 60px rgba(0,0,0,0.3)",
|
|
95
|
-
"maxWidth": "500px",
|
|
96
|
-
"width": "90%",
|
|
97
|
-
"textAlign": "center"
|
|
98
|
-
}}>
|
|
99
|
-
<h1 style={{
|
|
100
|
-
"fontSize": "2.5rem",
|
|
101
|
-
"marginBottom": "16px",
|
|
102
|
-
"color": "#1f2937",
|
|
103
|
-
"fontWeight": "700"
|
|
104
|
-
}}>✅ Welcome!</h1>
|
|
105
|
-
<p style={{
|
|
106
|
-
"fontSize": "1.1rem",
|
|
107
|
-
"color": "#6b7280",
|
|
108
|
-
"marginBottom": "32px"
|
|
109
|
-
}}>You are successfully logged in</p>
|
|
110
|
-
|
|
111
|
-
<div style={{
|
|
112
|
-
"background": "#f3f4f6",
|
|
113
|
-
"padding": "24px",
|
|
114
|
-
"borderRadius": "12px",
|
|
115
|
-
"marginBottom": "32px"
|
|
116
|
-
}}>
|
|
117
|
-
<p style={{
|
|
118
|
-
"fontSize": "0.9rem",
|
|
119
|
-
"color": "#6b7280",
|
|
120
|
-
"marginBottom": "8px"
|
|
121
|
-
}}>Logged in as:</p>
|
|
122
|
-
<p style={{
|
|
123
|
-
"fontSize": "1.2rem",
|
|
124
|
-
"fontWeight": "600",
|
|
125
|
-
"color": "#667eea"
|
|
126
|
-
}}>User</p>
|
|
127
|
-
</div>
|
|
128
|
-
|
|
129
|
-
<button
|
|
130
|
-
onClick={handleLogout}
|
|
131
|
-
style={{
|
|
132
|
-
"width": "100%",
|
|
133
|
-
"padding": "14px 24px",
|
|
134
|
-
"background": "#ef4444",
|
|
135
|
-
"color": "#ffffff",
|
|
136
|
-
"border": "none",
|
|
137
|
-
"borderRadius": "10px",
|
|
138
|
-
"fontSize": "16px",
|
|
139
|
-
"fontWeight": "600",
|
|
140
|
-
"cursor": "pointer",
|
|
141
|
-
"transition": "all 0.3s",
|
|
142
|
-
"boxShadow": "0 4px 12px rgba(239,68,68,0.3)"
|
|
143
|
-
}}
|
|
144
|
-
>
|
|
145
|
-
Logout
|
|
146
|
-
</button>
|
|
147
|
-
</div>
|
|
148
|
-
</div>;
|
|
149
|
-
}
|
|
150
|
-
|
|
151
|
-
# Login/Signup view
|
|
152
|
-
return <div style={{
|
|
153
|
-
"minHeight": "100vh",
|
|
154
|
-
"background": "linear-gradient(135deg, #667eea 0%, #764ba2 100%)",
|
|
155
|
-
"display": "flex",
|
|
156
|
-
"alignItems": "center",
|
|
157
|
-
"justifyContent": "center",
|
|
158
|
-
"fontFamily": "system-ui, -apple-system, sans-serif",
|
|
159
|
-
"padding": "20px"
|
|
160
|
-
}}>
|
|
161
|
-
<div style={{
|
|
162
|
-
"background": "#ffffff",
|
|
163
|
-
"borderRadius": "16px",
|
|
164
|
-
"padding": "48px",
|
|
165
|
-
"boxShadow": "0 20px 60px rgba(0,0,0,0.3)",
|
|
166
|
-
"maxWidth": "400px",
|
|
167
|
-
"width": "100%"
|
|
168
|
-
}}>
|
|
169
|
-
# Header
|
|
170
|
-
<div style={{"textAlign": "center", "marginBottom": "32px"}}>
|
|
171
|
-
<h1 style={{
|
|
172
|
-
"fontSize": "2rem",
|
|
173
|
-
"fontWeight": "700",
|
|
174
|
-
"color": "#1f2937",
|
|
175
|
-
"marginBottom": "8px"
|
|
176
|
-
}}>
|
|
177
|
-
{("Create Account" if isSignup else "Welcome Back")}
|
|
178
|
-
</h1>
|
|
179
|
-
<p style={{
|
|
180
|
-
"color": "#6b7280",
|
|
181
|
-
"fontSize": "0.95rem"
|
|
182
|
-
}}>
|
|
183
|
-
{("Sign up to get started" if isSignup else "Sign in to continue")}
|
|
184
|
-
</p>
|
|
185
|
-
</div>
|
|
186
|
-
|
|
187
|
-
# Form
|
|
188
|
-
<form onSubmit={handleSubmit} style={{"marginBottom": "24px"}}>
|
|
189
|
-
<div style={{"marginBottom": "20px"}}>
|
|
190
|
-
<label style={{
|
|
191
|
-
"display": "block",
|
|
192
|
-
"marginBottom": "8px",
|
|
193
|
-
"color": "#374151",
|
|
194
|
-
"fontSize": "14px",
|
|
195
|
-
"fontWeight": "600"
|
|
196
|
-
}}>Username</label>
|
|
197
|
-
<input
|
|
198
|
-
type="text"
|
|
199
|
-
value={username}
|
|
200
|
-
onChange={lambda e: any -> None { setUsername(e.target.value); }}
|
|
201
|
-
placeholder="Enter your username"
|
|
202
|
-
style={{
|
|
203
|
-
"width": "100%",
|
|
204
|
-
"padding": "12px 16px",
|
|
205
|
-
"border": "2px solid #e5e7eb",
|
|
206
|
-
"borderRadius": "10px",
|
|
207
|
-
"fontSize": "16px",
|
|
208
|
-
"outline": "none",
|
|
209
|
-
"transition": "border 0.2s",
|
|
210
|
-
"boxSizing": "border-box"
|
|
211
|
-
}}
|
|
212
|
-
/>
|
|
213
|
-
</div>
|
|
214
|
-
|
|
215
|
-
<div style={{"marginBottom": "24px"}}>
|
|
216
|
-
<label style={{
|
|
217
|
-
"display": "block",
|
|
218
|
-
"marginBottom": "8px",
|
|
219
|
-
"color": "#374151",
|
|
220
|
-
"fontSize": "14px",
|
|
221
|
-
"fontWeight": "600"
|
|
222
|
-
}}>Password</label>
|
|
223
|
-
<input
|
|
224
|
-
type="password"
|
|
225
|
-
value={password}
|
|
226
|
-
onChange={lambda e: any -> None { setPassword(e.target.value); }}
|
|
227
|
-
placeholder="Enter your password"
|
|
228
|
-
style={{
|
|
229
|
-
"width": "100%",
|
|
230
|
-
"padding": "12px 16px",
|
|
231
|
-
"border": "2px solid #e5e7eb",
|
|
232
|
-
"borderRadius": "10px",
|
|
233
|
-
"fontSize": "16px",
|
|
234
|
-
"outline": "none",
|
|
235
|
-
"transition": "border 0.2s",
|
|
236
|
-
"boxSizing": "border-box"
|
|
237
|
-
}}
|
|
238
|
-
/>
|
|
239
|
-
</div>
|
|
240
|
-
|
|
241
|
-
{(<div style={{
|
|
242
|
-
"padding": "12px",
|
|
243
|
-
"background": "#fee2e2",
|
|
244
|
-
"border": "1px solid #fecaca",
|
|
245
|
-
"borderRadius": "8px",
|
|
246
|
-
"marginBottom": "20px"
|
|
247
|
-
}}>
|
|
248
|
-
<p style={{
|
|
249
|
-
"color": "#dc2626",
|
|
250
|
-
"fontSize": "14px",
|
|
251
|
-
"margin": "0"
|
|
252
|
-
}}>{error}</p>
|
|
253
|
-
</div>) if error else None}
|
|
254
|
-
|
|
255
|
-
<button
|
|
256
|
-
type="submit"
|
|
257
|
-
disabled={loading}
|
|
258
|
-
style={{
|
|
259
|
-
"width": "100%",
|
|
260
|
-
"padding": "14px 24px",
|
|
261
|
-
"background": (("#9ca3af" if loading else "#667eea")),
|
|
262
|
-
"color": "#ffffff",
|
|
263
|
-
"border": "none",
|
|
264
|
-
"borderRadius": "10px",
|
|
265
|
-
"fontSize": "16px",
|
|
266
|
-
"fontWeight": "600",
|
|
267
|
-
"cursor": (("not-allowed" if loading else "pointer")),
|
|
268
|
-
"transition": "all 0.3s",
|
|
269
|
-
"boxShadow": "0 4px 12px rgba(102,126,234,0.4)"
|
|
270
|
-
}}
|
|
271
|
-
>
|
|
272
|
-
{(("Processing..." if loading else ("Sign Up" if isSignup else "Sign In")))}
|
|
273
|
-
</button>
|
|
274
|
-
</form>
|
|
275
|
-
|
|
276
|
-
# Toggle between login/signup
|
|
277
|
-
<div style={{"textAlign": "center"}}>
|
|
278
|
-
<p style={{
|
|
279
|
-
"color": "#6b7280",
|
|
280
|
-
"fontSize": "14px",
|
|
281
|
-
"marginBottom": "8px"
|
|
282
|
-
}}>
|
|
283
|
-
{(("Already have an account?" if isSignup else "Don't have an account?"))}
|
|
284
|
-
</p>
|
|
285
|
-
<button
|
|
286
|
-
onClick={lambda -> None {
|
|
287
|
-
setIsSignup(not isSignup);
|
|
288
|
-
setError("");
|
|
289
|
-
setUsername("");
|
|
290
|
-
setPassword("");
|
|
291
|
-
}}
|
|
292
|
-
style={{
|
|
293
|
-
"background": "none",
|
|
294
|
-
"border": "none",
|
|
295
|
-
"color": "#667eea",
|
|
296
|
-
"fontSize": "14px",
|
|
297
|
-
"fontWeight": "600",
|
|
298
|
-
"cursor": "pointer",
|
|
299
|
-
"textDecoration": "underline"
|
|
300
|
-
}}
|
|
301
|
-
>
|
|
302
|
-
{(("Sign In" if isSignup else "Create Account"))}
|
|
303
|
-
</button>
|
|
304
|
-
</div>
|
|
305
|
-
</div>
|
|
306
|
-
</div>;
|
|
307
|
-
}
|
|
308
|
-
}
|
|
@@ -1,27 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "basic-auth",
|
|
3
|
-
"version": "1.0.0",
|
|
4
|
-
"main": "index.js",
|
|
5
|
-
"scripts": {
|
|
6
|
-
"build": "npm run compile && vite build",
|
|
7
|
-
"dev": "vite dev",
|
|
8
|
-
"preview": "vite preview",
|
|
9
|
-
"compile": "babel src --out-dir build --extensions \".jsx,.js\" --out-file-extension .js"
|
|
10
|
-
},
|
|
11
|
-
"keywords": [],
|
|
12
|
-
"author": "",
|
|
13
|
-
"license": "ISC",
|
|
14
|
-
"description": "Jac application: basic-auth",
|
|
15
|
-
"type": "module",
|
|
16
|
-
"devDependencies": {
|
|
17
|
-
"vite": "^6.4.1",
|
|
18
|
-
"@babel/cli": "^7.28.3",
|
|
19
|
-
"@babel/core": "^7.28.5",
|
|
20
|
-
"@babel/preset-env": "^7.28.5",
|
|
21
|
-
"@babel/preset-react": "^7.28.5"
|
|
22
|
-
},
|
|
23
|
-
"dependencies": {
|
|
24
|
-
"react": "^19.2.0",
|
|
25
|
-
"react-dom": "^19.2.0"
|
|
26
|
-
}
|
|
27
|
-
}
|
|
@@ -1,27 +0,0 @@
|
|
|
1
|
-
|
|
2
|
-
import { defineConfig } from "vite";
|
|
3
|
-
import path from "path";
|
|
4
|
-
import { fileURLToPath } from "url";
|
|
5
|
-
|
|
6
|
-
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
|
7
|
-
|
|
8
|
-
export default defineConfig({
|
|
9
|
-
root: ".", // base folder
|
|
10
|
-
build: {
|
|
11
|
-
rollupOptions: {
|
|
12
|
-
input: "build/main.js", // your compiled entry file
|
|
13
|
-
output: {
|
|
14
|
-
entryFileNames: "client.[hash].js", // name of the final js file
|
|
15
|
-
assetFileNames: "[name].[ext]",
|
|
16
|
-
},
|
|
17
|
-
},
|
|
18
|
-
outDir: "dist", // final bundled output
|
|
19
|
-
emptyOutDir: true,
|
|
20
|
-
},
|
|
21
|
-
publicDir: false,
|
|
22
|
-
resolve: {
|
|
23
|
-
alias: {
|
|
24
|
-
"@jac-client/utils": path.resolve(__dirname, "src/client_runtime.js"),
|
|
25
|
-
},
|
|
26
|
-
},
|
|
27
|
-
});
|
|
@@ -1,60 +0,0 @@
|
|
|
1
|
-
# Basic Authentication with React Router
|
|
2
|
-
|
|
3
|
-
A complete authentication example using Jac with React Router for client-side routing.
|
|
4
|
-
|
|
5
|
-
## Features
|
|
6
|
-
|
|
7
|
-
- ✨ **React Router Integration** - Hash-based routing using `react-router-dom` v6
|
|
8
|
-
- 🔐 **User Authentication** - Login and signup functionality
|
|
9
|
-
- 🛡️ **Protected Routes** - Dashboard page accessible only to authenticated users
|
|
10
|
-
- 🎨 **Modern UI** - Clean, responsive design
|
|
11
|
-
- 🔄 **Navigation Guards** - Automatic redirects for unauthenticated users
|
|
12
|
-
- 💾 **LocalStorage Session** - Persistent authentication state
|
|
13
|
-
|
|
14
|
-
## React Router Features Demonstrated
|
|
15
|
-
|
|
16
|
-
- `HashRouter` for hash-based routing (`#/login`, `#/dashboard`)
|
|
17
|
-
- `useNavigate()` hook for programmatic navigation
|
|
18
|
-
- `useLocation()` hook for accessing current location
|
|
19
|
-
- `<Navigate />` component for conditional redirects
|
|
20
|
-
- `<Link />` component for declarative navigation
|
|
21
|
-
- `<Routes />` and `<Route />` for route definitions
|
|
22
|
-
|
|
23
|
-
## Setup
|
|
24
|
-
|
|
25
|
-
Install dependencies:
|
|
26
|
-
```bash
|
|
27
|
-
npm install
|
|
28
|
-
```
|
|
29
|
-
|
|
30
|
-
## Running the App
|
|
31
|
-
|
|
32
|
-
Start the development server:
|
|
33
|
-
```bash
|
|
34
|
-
jac serve app.jac
|
|
35
|
-
```
|
|
36
|
-
|
|
37
|
-
Then open your browser to `http://localhost:8000`
|
|
38
|
-
|
|
39
|
-
## Usage
|
|
40
|
-
|
|
41
|
-
1. **Sign Up**: Create a new account at `#/signup`
|
|
42
|
-
2. **Login**: Access your account at `#/login`
|
|
43
|
-
3. **Dashboard**: View protected content at `#/dashboard` (requires login)
|
|
44
|
-
4. **Logout**: Click the logout button in the navigation
|
|
45
|
-
|
|
46
|
-
## Project Structure
|
|
47
|
-
|
|
48
|
-
- `app.jac` - Main application with routing and authentication logic
|
|
49
|
-
- `package.json` - Dependencies including `react-router-dom` v6.30.1
|
|
50
|
-
- Session files - User data and tokens stored locally
|
|
51
|
-
|
|
52
|
-
## Authentication Flow
|
|
53
|
-
|
|
54
|
-
1. User signs up or logs in
|
|
55
|
-
2. Token stored in localStorage
|
|
56
|
-
3. Navigation redirects to dashboard
|
|
57
|
-
4. Protected routes check authentication status
|
|
58
|
-
5. Unauthenticated access redirects to login
|
|
59
|
-
|
|
60
|
-
Happy coding with Jac! 🚀
|