jac-client 0.2.8__py3-none-any.whl → 0.2.11__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/button.jac +4 -3
- jac_client/examples/all-in-one/components/CategoryFilter.jac +36 -24
- jac_client/examples/all-in-one/components/Header.jac +12 -8
- jac_client/examples/all-in-one/components/ProfitOverview.jac +49 -35
- jac_client/examples/all-in-one/components/Summary.jac +59 -36
- jac_client/examples/all-in-one/components/TransactionForm.jac +142 -112
- jac_client/examples/all-in-one/components/TransactionItem.jac +37 -30
- jac_client/examples/all-in-one/components/TransactionList.jac +33 -26
- jac_client/examples/all-in-one/components/button.jac +4 -3
- jac_client/examples/all-in-one/components/navigation.jac +111 -117
- jac_client/examples/all-in-one/constants/categories.jac +23 -24
- jac_client/examples/all-in-one/constants/clients.jac +7 -8
- jac_client/examples/all-in-one/context/BudgetContext.jac +9 -6
- jac_client/examples/all-in-one/hooks/useBudget.jac +18 -12
- jac_client/examples/all-in-one/hooks/useLocalStorage.jac +14 -13
- jac_client/examples/all-in-one/main.jac +542 -0
- jac_client/examples/all-in-one/pages/BudgetPlanner.jac +26 -12
- jac_client/examples/all-in-one/pages/FeaturesTest.jac +43 -12
- jac_client/examples/all-in-one/pages/LandingPage.jac +113 -90
- jac_client/examples/all-in-one/pages/budget_planner_ui.cl.jac +65 -0
- jac_client/examples/all-in-one/pages/features_test_ui.cl.jac +675 -0
- jac_client/examples/all-in-one/pages/loginPage.jac +114 -119
- jac_client/examples/all-in-one/pages/nestedDemo.jac +44 -51
- jac_client/examples/all-in-one/pages/notFound.jac +15 -21
- jac_client/examples/all-in-one/pages/signupPage.jac +113 -119
- jac_client/examples/all-in-one/utils/formatters.jac +5 -8
- jac_client/examples/asset-serving/css-with-image/main.jac +92 -0
- jac_client/examples/asset-serving/image-asset/main.jac +56 -0
- jac_client/examples/asset-serving/import-alias/main.jac +109 -0
- jac_client/examples/basic/main.jac +23 -0
- jac_client/examples/basic-auth/main.jac +363 -0
- jac_client/examples/basic-auth-with-router/main.jac +451 -0
- jac_client/examples/basic-full-stack/main.jac +362 -0
- jac_client/examples/css-styling/js-styling/main.jac +63 -0
- jac_client/examples/css-styling/material-ui/main.jac +122 -0
- jac_client/examples/css-styling/pure-css/main.jac +55 -0
- jac_client/examples/css-styling/sass-example/main.jac +55 -0
- jac_client/examples/css-styling/styled-components/main.jac +62 -0
- jac_client/examples/css-styling/tailwind-example/main.jac +74 -0
- jac_client/examples/full-stack-with-auth/main.jac +696 -0
- jac_client/examples/little-x/main.jac +681 -0
- jac_client/examples/little-x/src/submit-button.jac +15 -14
- jac_client/examples/nested-folders/nested-advance/main.jac +26 -0
- jac_client/examples/nested-folders/nested-advance/src/ButtonRoot.jac +4 -6
- jac_client/examples/nested-folders/nested-advance/src/level1/ButtonSecondL.jac +9 -13
- jac_client/examples/nested-folders/nested-advance/src/level1/Card.jac +29 -32
- jac_client/examples/nested-folders/nested-advance/src/level1/level2/ButtonThirdL.jac +12 -18
- jac_client/examples/nested-folders/nested-basic/{src/app.jac → main.jac} +7 -5
- jac_client/examples/nested-folders/nested-basic/src/button.jac +4 -3
- jac_client/examples/nested-folders/nested-basic/src/components/button.jac +4 -3
- jac_client/examples/ts-support/main.jac +35 -0
- jac_client/examples/with-router/main.jac +286 -0
- jac_client/plugin/cli.jac +491 -411
- jac_client/plugin/client.jac +25 -0
- jac_client/plugin/client_runtime.cl.jac +10 -4
- jac_client/plugin/impl/client.impl.jac +96 -55
- jac_client/plugin/impl/client_runtime.impl.jac +155 -1
- jac_client/plugin/plugin_config.jac +211 -29
- jac_client/plugin/src/__init__.jac +0 -2
- jac_client/plugin/src/compiler.jac +0 -1
- jac_client/plugin/src/config_loader.jac +1 -0
- jac_client/plugin/src/desktop_config.jac +31 -0
- jac_client/plugin/src/impl/compiler.impl.jac +49 -17
- jac_client/plugin/src/impl/config_loader.impl.jac +8 -0
- jac_client/plugin/src/impl/desktop_config.impl.jac +191 -0
- jac_client/plugin/src/impl/jac_to_js.impl.jac +5 -1
- jac_client/plugin/src/impl/package_installer.impl.jac +20 -20
- jac_client/plugin/src/impl/vite_bundler.impl.jac +191 -64
- jac_client/plugin/src/targets/desktop/sidecar/main.py +144 -0
- jac_client/plugin/src/targets/desktop_target.jac +37 -0
- jac_client/plugin/src/targets/impl/desktop_target.impl.jac +2347 -0
- jac_client/plugin/src/targets/impl/registry.impl.jac +64 -0
- jac_client/plugin/src/targets/impl/web_target.impl.jac +157 -0
- jac_client/plugin/src/targets/register.jac +21 -0
- jac_client/plugin/src/targets/registry.jac +87 -0
- jac_client/plugin/src/targets/web_target.jac +35 -0
- jac_client/plugin/src/vite_bundler.jac +6 -0
- jac_client/plugin/utils/__init__.jac +3 -0
- jac_client/plugin/utils/bun_installer.jac +16 -0
- jac_client/plugin/utils/impl/bun_installer.impl.jac +99 -0
- jac_client/templates/client.jacpack +72 -0
- jac_client/templates/fullstack.jacpack +61 -0
- jac_client/tests/conftest.py +103 -47
- jac_client/tests/fixtures/spawn_test/app.jac +49 -52
- jac_client/tests/fixtures/with-ts/app.jac +27 -27
- jac_client/tests/test_cli.py +182 -71
- jac_client/tests/test_e2e.py +232 -0
- jac_client/tests/test_helpers.py +58 -0
- jac_client/tests/test_it.py +91 -135
- jac_client/tests/test_it_desktop.py +891 -0
- {jac_client-0.2.8.dist-info → jac_client-0.2.11.dist-info}/METADATA +6 -6
- jac_client-0.2.11.dist-info/RECORD +113 -0
- {jac_client-0.2.8.dist-info → jac_client-0.2.11.dist-info}/WHEEL +1 -1
- jac_client/examples/all-in-one/app.jac +0 -573
- jac_client/examples/all-in-one/pages/BudgetPlanner.cl.jac +0 -70
- jac_client/examples/all-in-one/pages/FeaturesTest.cl.jac +0 -552
- jac_client/examples/asset-serving/css-with-image/src/app.jac +0 -88
- jac_client/examples/asset-serving/image-asset/src/app.jac +0 -55
- jac_client/examples/asset-serving/import-alias/src/app.jac +0 -111
- jac_client/examples/basic/src/app.jac +0 -21
- jac_client/examples/basic-auth/src/app.jac +0 -371
- jac_client/examples/basic-auth-with-router/src/app.jac +0 -464
- jac_client/examples/basic-full-stack/src/app.jac +0 -359
- jac_client/examples/css-styling/js-styling/src/app.jac +0 -84
- jac_client/examples/css-styling/material-ui/src/app.jac +0 -122
- jac_client/examples/css-styling/pure-css/src/app.jac +0 -64
- jac_client/examples/css-styling/sass-example/src/app.jac +0 -64
- jac_client/examples/css-styling/styled-components/src/app.jac +0 -71
- jac_client/examples/css-styling/tailwind-example/src/app.jac +0 -63
- jac_client/examples/full-stack-with-auth/src/app.jac +0 -722
- jac_client/examples/little-x/src/app.jac +0 -719
- jac_client/examples/nested-folders/nested-advance/src/app.jac +0 -35
- jac_client/examples/ts-support/src/app.jac +0 -35
- jac_client/examples/with-router/src/app.jac +0 -323
- jac_client/plugin/src/babel_processor.jac +0 -18
- jac_client/plugin/src/impl/babel_processor.impl.jac +0 -89
- jac_client-0.2.8.dist-info/RECORD +0 -97
- {jac_client-0.2.8.dist-info → jac_client-0.2.11.dist-info}/entry_points.txt +0 -0
- {jac_client-0.2.8.dist-info → jac_client-0.2.11.dist-info}/top_level.txt +0 -0
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
# Nested Folder Levels Example
|
|
2
|
+
cl import from .ButtonRoot { ButtonRoot }
|
|
3
|
+
cl import from .level1.ButtonSecondL { ButtonSecondL }
|
|
4
|
+
cl import from .level1.level2.ButtonThirdL { ButtonThirdL }
|
|
5
|
+
cl import from .level1.Card { Card }
|
|
6
|
+
|
|
7
|
+
cl def:pub app -> any {
|
|
8
|
+
return
|
|
9
|
+
<div style={{padding: "20px"}}>
|
|
10
|
+
<h1>
|
|
11
|
+
Nested Folder Levels Demo
|
|
12
|
+
</h1>
|
|
13
|
+
<div style={{margin: "10px 0"}}>
|
|
14
|
+
<ButtonRoot />
|
|
15
|
+
</div>
|
|
16
|
+
<div style={{margin: "10px 0"}}>
|
|
17
|
+
<ButtonSecondL />
|
|
18
|
+
</div>
|
|
19
|
+
<div style={{margin: "10px 0"}}>
|
|
20
|
+
<ButtonThirdL />
|
|
21
|
+
</div>
|
|
22
|
+
<div style={{margin: "10px 0"}}>
|
|
23
|
+
<Card />
|
|
24
|
+
</div>
|
|
25
|
+
</div>;
|
|
26
|
+
}
|
|
@@ -3,17 +3,13 @@ cl import from antd { Button }
|
|
|
3
3
|
cl import from ..ButtonRoot { ButtonRoot }
|
|
4
4
|
|
|
5
5
|
cl def:pub ButtonSecondL -> any {
|
|
6
|
-
return
|
|
7
|
-
<
|
|
8
|
-
type="default"
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
>
|
|
16
|
-
<ButtonRoot />
|
|
17
|
-
</div>
|
|
18
|
-
</div>;
|
|
6
|
+
return
|
|
7
|
+
<div>
|
|
8
|
+
<Button type="default" size="large">
|
|
9
|
+
Second Level Button (imports from root)
|
|
10
|
+
</Button>
|
|
11
|
+
<div style={{marginTop: "10px"}}>
|
|
12
|
+
<ButtonRoot />
|
|
13
|
+
</div>
|
|
14
|
+
</div>;
|
|
19
15
|
}
|
|
@@ -6,38 +6,35 @@ cl import from ..ButtonRoot {
|
|
|
6
6
|
cl import from .level2.ButtonThirdL { ButtonThirdL }
|
|
7
7
|
|
|
8
8
|
cl def:pub Card -> any {
|
|
9
|
-
return
|
|
10
|
-
style={{
|
|
11
|
-
border: "2px solid #007bff",
|
|
12
|
-
borderRadius: "8px",
|
|
13
|
-
padding: "20px",
|
|
14
|
-
margin: "10px 0",
|
|
15
|
-
backgroundColor: "#f8f9fa"
|
|
16
|
-
}}
|
|
17
|
-
>
|
|
18
|
-
<h3>
|
|
19
|
-
Card Component (Second Level)
|
|
20
|
-
</h3>
|
|
21
|
-
<p>
|
|
22
|
-
This card imports from:
|
|
23
|
-
</p>
|
|
24
|
-
<ul>
|
|
25
|
-
<li>
|
|
26
|
-
Root level: ButtonRoot (using ..)
|
|
27
|
-
</li>
|
|
28
|
-
<li>
|
|
29
|
-
Third level: ButtonThirdL (using .level2)
|
|
30
|
-
</li>
|
|
31
|
-
</ul>
|
|
9
|
+
return
|
|
32
10
|
<div
|
|
33
|
-
style={{
|
|
11
|
+
style={{
|
|
12
|
+
border: "2px solid #007bff",
|
|
13
|
+
borderRadius: "8px",
|
|
14
|
+
padding: "20px",
|
|
15
|
+
margin: "10px 0",
|
|
16
|
+
backgroundColor: "#f8f9fa"
|
|
17
|
+
}}
|
|
34
18
|
>
|
|
35
|
-
<
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
19
|
+
<h3>
|
|
20
|
+
Card Component (Second Level)
|
|
21
|
+
</h3>
|
|
22
|
+
<p>
|
|
23
|
+
This card imports from:
|
|
24
|
+
</p>
|
|
25
|
+
<ul>
|
|
26
|
+
<li>
|
|
27
|
+
Root level: ButtonRoot (using ..)
|
|
28
|
+
</li>
|
|
29
|
+
<li>
|
|
30
|
+
Third level: ButtonThirdL (using .level2)
|
|
31
|
+
</li>
|
|
32
|
+
</ul>
|
|
33
|
+
<div style={{marginTop: "15px"}}>
|
|
34
|
+
<ButtonRoot />
|
|
35
|
+
</div>
|
|
36
|
+
<div style={{marginTop: "10px"}}>
|
|
37
|
+
<ButtonThirdL />
|
|
38
|
+
</div>
|
|
39
|
+
</div>;
|
|
43
40
|
}
|
|
@@ -4,22 +4,16 @@ cl import from ...ButtonRoot { ButtonRoot }
|
|
|
4
4
|
cl import from ..ButtonSecondL { ButtonSecondL }
|
|
5
5
|
|
|
6
6
|
cl def:pub ButtonThirdL -> any {
|
|
7
|
-
return
|
|
8
|
-
<
|
|
9
|
-
type="dashed"
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
style={{marginTop: "10px"}}
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
</div
|
|
19
|
-
<div
|
|
20
|
-
style={{marginTop: "10px"}}
|
|
21
|
-
>
|
|
22
|
-
<ButtonSecondL />
|
|
23
|
-
</div>
|
|
24
|
-
</div>;
|
|
7
|
+
return
|
|
8
|
+
<div>
|
|
9
|
+
<Button type="dashed" size="large">
|
|
10
|
+
Third Level Button (imports from root and second level)
|
|
11
|
+
</Button>
|
|
12
|
+
<div style={{marginTop: "10px"}}>
|
|
13
|
+
<ButtonRoot />
|
|
14
|
+
</div>
|
|
15
|
+
<div style={{marginTop: "10px"}}>
|
|
16
|
+
<ButtonSecondL />
|
|
17
|
+
</div>
|
|
18
|
+
</div>;
|
|
25
19
|
}
|
|
@@ -2,12 +2,14 @@ cl import from .components.button { CustomButton }
|
|
|
2
2
|
cl import from .button { CustomButtonRoot }
|
|
3
3
|
|
|
4
4
|
cl def RelativeImport -> any {
|
|
5
|
-
return
|
|
6
|
-
<
|
|
7
|
-
|
|
8
|
-
|
|
5
|
+
return
|
|
6
|
+
<div>
|
|
7
|
+
<CustomButton />
|
|
8
|
+
<CustomButtonRoot />
|
|
9
|
+
</div>;
|
|
9
10
|
}
|
|
10
11
|
|
|
11
12
|
cl def:pub app -> any {
|
|
12
|
-
return
|
|
13
|
+
return
|
|
14
|
+
<RelativeImport />;
|
|
13
15
|
}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
|
|
2
|
+
# Pages
|
|
3
|
+
cl import from ".components/Button.tsx" { Button }
|
|
4
|
+
|
|
5
|
+
cl {
|
|
6
|
+
def:pub app -> any {
|
|
7
|
+
has count: int = 0;
|
|
8
|
+
|
|
9
|
+
can with count entry {
|
|
10
|
+
console.log("Count: ", count);
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
return
|
|
14
|
+
<div style={{padding: "2rem", fontFamily: "Arial, sans-serif"}}>
|
|
15
|
+
<h1>
|
|
16
|
+
Hello, World!
|
|
17
|
+
</h1>
|
|
18
|
+
<p>
|
|
19
|
+
Count: {count}
|
|
20
|
+
</p>
|
|
21
|
+
<div style={{display: "flex", gap: "1rem", marginTop: "1rem"}}>
|
|
22
|
+
<Button
|
|
23
|
+
label="Increment"
|
|
24
|
+
onClick={lambda -> None { count = count + 1;}}
|
|
25
|
+
variant="primary"
|
|
26
|
+
/>
|
|
27
|
+
<Button
|
|
28
|
+
label="Reset"
|
|
29
|
+
onClick={lambda -> None { count = 0;}}
|
|
30
|
+
variant="secondary"
|
|
31
|
+
/>
|
|
32
|
+
</div>
|
|
33
|
+
</div>;
|
|
34
|
+
}
|
|
35
|
+
}
|
|
@@ -0,0 +1,286 @@
|
|
|
1
|
+
# React Router HashRouter Example
|
|
2
|
+
cl import from react { useEffect }
|
|
3
|
+
cl import from "@jac/runtime" {
|
|
4
|
+
Router,
|
|
5
|
+
Routes,
|
|
6
|
+
Route,
|
|
7
|
+
Link,
|
|
8
|
+
useNavigate,
|
|
9
|
+
useLocation,
|
|
10
|
+
useParams
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
cl {
|
|
14
|
+
# Home Page Component
|
|
15
|
+
def Home -> any {
|
|
16
|
+
location = useLocation();
|
|
17
|
+
navigate = useNavigate();
|
|
18
|
+
|
|
19
|
+
def goToAbout(e: any) -> None {
|
|
20
|
+
navigate("/about");
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
return
|
|
24
|
+
<div>
|
|
25
|
+
<h1>
|
|
26
|
+
🏠 Home Page
|
|
27
|
+
</h1>
|
|
28
|
+
<p>
|
|
29
|
+
Welcome to the home page!
|
|
30
|
+
</p>
|
|
31
|
+
<p>
|
|
32
|
+
This example uses React Router's
|
|
33
|
+
<strong>
|
|
34
|
+
HashRouter
|
|
35
|
+
</strong>
|
|
36
|
+
# for client-side routing.
|
|
37
|
+
</p>
|
|
38
|
+
<p>
|
|
39
|
+
Current path:
|
|
40
|
+
<code>
|
|
41
|
+
{location.pathname}
|
|
42
|
+
</code>
|
|
43
|
+
</p>
|
|
44
|
+
<button onClick={goToAbout}>
|
|
45
|
+
Go to About →
|
|
46
|
+
</button>
|
|
47
|
+
</div>;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
# About Page Component
|
|
51
|
+
def About -> any {
|
|
52
|
+
location = useLocation();
|
|
53
|
+
|
|
54
|
+
return
|
|
55
|
+
<div>
|
|
56
|
+
<h1>
|
|
57
|
+
ℹ️ About Page
|
|
58
|
+
</h1>
|
|
59
|
+
<p>
|
|
60
|
+
This is the about page.
|
|
61
|
+
</p>
|
|
62
|
+
<p>
|
|
63
|
+
Learn more about our application here.
|
|
64
|
+
</p>
|
|
65
|
+
<p>
|
|
66
|
+
Current path:
|
|
67
|
+
<code>
|
|
68
|
+
{location.pathname}
|
|
69
|
+
</code>
|
|
70
|
+
</p>
|
|
71
|
+
<div style={{"marginTop": "1rem"}}>
|
|
72
|
+
<Link to="/about/team">
|
|
73
|
+
View Team →
|
|
74
|
+
</Link>
|
|
75
|
+
</div>
|
|
76
|
+
</div>;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
# Team Page Component (nested route example)
|
|
80
|
+
def Team -> any {
|
|
81
|
+
return
|
|
82
|
+
<div>
|
|
83
|
+
<h1>
|
|
84
|
+
👥 Our Team
|
|
85
|
+
</h1>
|
|
86
|
+
<p>
|
|
87
|
+
Meet the amazing team behind this project!
|
|
88
|
+
</p>
|
|
89
|
+
<Link to="/about">
|
|
90
|
+
← Back to About
|
|
91
|
+
</Link>
|
|
92
|
+
</div>;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
# User Profile Component (with URL parameters)
|
|
96
|
+
def UserProfile -> any {
|
|
97
|
+
params = useParams();
|
|
98
|
+
userId = params.id or "Unknown";
|
|
99
|
+
|
|
100
|
+
return
|
|
101
|
+
<div>
|
|
102
|
+
<h1>
|
|
103
|
+
👤 User Profile
|
|
104
|
+
</h1>
|
|
105
|
+
<p>
|
|
106
|
+
Viewing profile for user:
|
|
107
|
+
<strong>
|
|
108
|
+
{userId}
|
|
109
|
+
</strong>
|
|
110
|
+
</p>
|
|
111
|
+
<p>
|
|
112
|
+
This demonstrates URL parameters using
|
|
113
|
+
<code>
|
|
114
|
+
/user/:id
|
|
115
|
+
</code>
|
|
116
|
+
</p>
|
|
117
|
+
<Link to="/">
|
|
118
|
+
← Back to Home
|
|
119
|
+
</Link>
|
|
120
|
+
</div>;
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
# Contact Page Component
|
|
124
|
+
def Contact -> any {
|
|
125
|
+
has submitted: bool = False;
|
|
126
|
+
|
|
127
|
+
def handleSubmit(e: any) -> None {
|
|
128
|
+
e.preventDefault();
|
|
129
|
+
submitted = True;
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
def resetForm(e: any) -> None {
|
|
133
|
+
submitted = False;
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
if submitted {
|
|
137
|
+
return
|
|
138
|
+
<div>
|
|
139
|
+
<h1>
|
|
140
|
+
📧 Contact Page
|
|
141
|
+
</h1>
|
|
142
|
+
<div style={{"color": "green"}}>
|
|
143
|
+
<p>
|
|
144
|
+
✓ Thank you! Your message has been sent.
|
|
145
|
+
</p>
|
|
146
|
+
<button onClick={resetForm}>
|
|
147
|
+
Send another
|
|
148
|
+
</button>
|
|
149
|
+
</div>
|
|
150
|
+
</div>;
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
return
|
|
154
|
+
<div>
|
|
155
|
+
<h1>
|
|
156
|
+
📧 Contact Page
|
|
157
|
+
</h1>
|
|
158
|
+
<p>
|
|
159
|
+
Get in touch with us!
|
|
160
|
+
</p>
|
|
161
|
+
<form onSubmit={handleSubmit}>
|
|
162
|
+
<input
|
|
163
|
+
type="text"
|
|
164
|
+
placeholder="Your name"
|
|
165
|
+
style={{"margin": "0.5rem 0", "display": "block"}}
|
|
166
|
+
/>
|
|
167
|
+
<input
|
|
168
|
+
type="text"
|
|
169
|
+
placeholder="Your username"
|
|
170
|
+
style={{"margin": "0.5rem 0", "display": "block"}}
|
|
171
|
+
/>
|
|
172
|
+
<textarea
|
|
173
|
+
placeholder="Your message"
|
|
174
|
+
style={{"margin": "0.5rem 0", "display": "block"}}
|
|
175
|
+
></textarea>
|
|
176
|
+
<button type="submit">
|
|
177
|
+
Send Message
|
|
178
|
+
</button>
|
|
179
|
+
</form>
|
|
180
|
+
</div>;
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
# 404 Not Found Component
|
|
184
|
+
def NotFound -> any {
|
|
185
|
+
location = useLocation();
|
|
186
|
+
navigate = useNavigate();
|
|
187
|
+
|
|
188
|
+
def goHome(e: any) -> None {
|
|
189
|
+
navigate("/");
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
return
|
|
193
|
+
<div style={{"textAlign": "center", "padding": "2rem"}}>
|
|
194
|
+
<h1>
|
|
195
|
+
🔍 404 - Page Not Found
|
|
196
|
+
</h1>
|
|
197
|
+
<p>
|
|
198
|
+
The page
|
|
199
|
+
<code>
|
|
200
|
+
{location.pathname}
|
|
201
|
+
</code>
|
|
202
|
+
does not exist.
|
|
203
|
+
</p>
|
|
204
|
+
<button onClick={goHome}>
|
|
205
|
+
Go Home
|
|
206
|
+
</button>
|
|
207
|
+
</div>;
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
# Navigation Component with active link styling
|
|
211
|
+
def Navigation -> any {
|
|
212
|
+
location = useLocation();
|
|
213
|
+
|
|
214
|
+
def linkStyle(path: str) -> dict {
|
|
215
|
+
isActive = location.pathname == path;
|
|
216
|
+
return {
|
|
217
|
+
"padding": "0.5rem 1rem",
|
|
218
|
+
"textDecoration": "none",
|
|
219
|
+
"color": "#0066cc" if isActive else "#333",
|
|
220
|
+
"fontWeight": "bold" if isActive else "normal",
|
|
221
|
+
"backgroundColor": "#e3f2fd" if isActive else "transparent",
|
|
222
|
+
"borderRadius": "4px",
|
|
223
|
+
"display": "inline-block"
|
|
224
|
+
};
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
return
|
|
228
|
+
<nav
|
|
229
|
+
style={{
|
|
230
|
+
"padding": "1rem",
|
|
231
|
+
"backgroundColor": "#f5f5f5",
|
|
232
|
+
"marginBottom": "2rem",
|
|
233
|
+
"boxShadow": "0 2px 4px rgba(0,0,0,0.1)"
|
|
234
|
+
}}
|
|
235
|
+
>
|
|
236
|
+
<div
|
|
237
|
+
style={{
|
|
238
|
+
"maxWidth": "1200px",
|
|
239
|
+
"margin": "0 auto",
|
|
240
|
+
"display": "flex",
|
|
241
|
+
"gap": "1rem",
|
|
242
|
+
"alignItems": "center"
|
|
243
|
+
}}
|
|
244
|
+
>
|
|
245
|
+
<Link to="/" style={linkStyle("/")}>
|
|
246
|
+
Home
|
|
247
|
+
</Link>
|
|
248
|
+
<Link to="/about" style={linkStyle("/about")}>
|
|
249
|
+
About
|
|
250
|
+
</Link>
|
|
251
|
+
<Link to="/contact" style={linkStyle("/contact")}>
|
|
252
|
+
Contact
|
|
253
|
+
</Link>
|
|
254
|
+
<Link to="/user/123" style={linkStyle("/user/123")}>
|
|
255
|
+
Profile Demo
|
|
256
|
+
</Link>
|
|
257
|
+
</div>
|
|
258
|
+
</nav>;
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
# Main App Component with React Router HashRouter
|
|
262
|
+
def:pub app -> any {
|
|
263
|
+
return
|
|
264
|
+
<Router>
|
|
265
|
+
<div style={{"fontFamily": "system-ui, -apple-system, sans-serif"}}>
|
|
266
|
+
<Navigation />
|
|
267
|
+
<div
|
|
268
|
+
style={{
|
|
269
|
+
"maxWidth": "1200px",
|
|
270
|
+
"margin": "0 auto",
|
|
271
|
+
"padding": "0 1rem"
|
|
272
|
+
}}
|
|
273
|
+
>
|
|
274
|
+
<Routes>
|
|
275
|
+
<Route path="/" element={<Home />} />
|
|
276
|
+
<Route path="/about" element={<About />} />
|
|
277
|
+
<Route path="/about/team" element={<Team />} />
|
|
278
|
+
<Route path="/contact" element={<Contact />} />
|
|
279
|
+
<Route path="/user/:id" element={<UserProfile />} />
|
|
280
|
+
<Route path="*" element={<NotFound />} />
|
|
281
|
+
</Routes>
|
|
282
|
+
</div>
|
|
283
|
+
</div>
|
|
284
|
+
</Router>;
|
|
285
|
+
}
|
|
286
|
+
}
|