jac-client 0.2.3__py3-none-any.whl → 0.2.8__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.
Files changed (224) hide show
  1. jac_client/examples/all-in-one/app.jac +494 -347
  2. jac_client/examples/all-in-one/assets/workers/worker.py +5 -0
  3. jac_client/examples/all-in-one/button.jac +1 -1
  4. jac_client/examples/all-in-one/components/CategoryFilter.jac +35 -0
  5. jac_client/examples/all-in-one/components/Header.jac +13 -0
  6. jac_client/examples/all-in-one/components/ProfitOverview.jac +50 -0
  7. jac_client/examples/all-in-one/components/Summary.jac +53 -0
  8. jac_client/examples/all-in-one/components/TransactionForm.jac +158 -0
  9. jac_client/examples/all-in-one/components/TransactionItem.jac +55 -0
  10. jac_client/examples/all-in-one/components/TransactionList.jac +37 -0
  11. jac_client/examples/all-in-one/components/button.jac +1 -1
  12. jac_client/examples/all-in-one/components/navigation.jac +132 -0
  13. jac_client/examples/all-in-one/constants/categories.jac +37 -0
  14. jac_client/examples/all-in-one/constants/clients.jac +13 -0
  15. jac_client/examples/all-in-one/context/BudgetContext.jac +28 -0
  16. jac_client/examples/all-in-one/hooks/useBudget.jac +116 -0
  17. jac_client/examples/all-in-one/hooks/useLocalStorage.jac +36 -0
  18. jac_client/examples/all-in-one/pages/BudgetPlanner.cl.jac +70 -0
  19. jac_client/examples/all-in-one/pages/BudgetPlanner.jac +126 -0
  20. jac_client/examples/all-in-one/pages/FeaturesTest.cl.jac +552 -0
  21. jac_client/examples/all-in-one/pages/FeaturesTest.jac +126 -0
  22. jac_client/examples/all-in-one/pages/LandingPage.jac +101 -0
  23. jac_client/examples/all-in-one/pages/loginPage.jac +132 -0
  24. jac_client/examples/all-in-one/pages/nestedDemo.jac +61 -0
  25. jac_client/examples/all-in-one/pages/notFound.jac +24 -0
  26. jac_client/examples/all-in-one/pages/signupPage.jac +133 -0
  27. jac_client/examples/all-in-one/utils/formatters.jac +52 -0
  28. jac_client/examples/asset-serving/css-with-image/{app.jac → src/app.jac} +4 -4
  29. jac_client/examples/asset-serving/image-asset/{app.jac → src/app.jac} +4 -4
  30. jac_client/examples/asset-serving/import-alias/{app.jac → src/app.jac} +5 -5
  31. jac_client/examples/basic/{app.jac → src/app.jac} +4 -4
  32. jac_client/examples/basic-auth/src/app.jac +371 -0
  33. jac_client/examples/basic-auth-with-router/{app.jac → src/app.jac} +28 -28
  34. jac_client/examples/basic-full-stack/{app.jac → src/app.jac} +166 -127
  35. jac_client/examples/css-styling/js-styling/{app.jac → src/app.jac} +7 -7
  36. jac_client/examples/css-styling/material-ui/{app.jac → src/app.jac} +6 -6
  37. jac_client/examples/css-styling/pure-css/{app.jac → src/app.jac} +7 -7
  38. jac_client/examples/css-styling/sass-example/{app.jac → src/app.jac} +7 -7
  39. jac_client/examples/css-styling/styled-components/{app.jac → src/app.jac} +6 -6
  40. jac_client/examples/css-styling/tailwind-example/{app.jac → src/app.jac} +7 -7
  41. jac_client/examples/full-stack-with-auth/{app.jac → src/app.jac} +47 -47
  42. jac_client/examples/little-x/{app.jac → src/app.jac} +27 -32
  43. jac_client/examples/little-x/src/submit-button.jac +16 -0
  44. jac_client/examples/nested-folders/nested-advance/{ButtonRoot.jac → src/ButtonRoot.jac} +1 -1
  45. jac_client/examples/nested-folders/nested-advance/{app.jac → src/app.jac} +1 -1
  46. jac_client/examples/nested-folders/nested-advance/{level1 → src/level1}/ButtonSecondL.jac +1 -1
  47. jac_client/examples/nested-folders/nested-advance/{level1 → src/level1}/Card.jac +1 -1
  48. jac_client/examples/nested-folders/nested-advance/{level1 → src/level1}/level2/ButtonThirdL.jac +1 -1
  49. jac_client/examples/nested-folders/nested-basic/{app.jac → src/app.jac} +2 -2
  50. jac_client/examples/nested-folders/nested-basic/{button.jac → src/button.jac} +1 -1
  51. jac_client/examples/nested-folders/nested-basic/{components → src/components}/button.jac +1 -1
  52. jac_client/examples/ts-support/src/app.jac +35 -0
  53. jac_client/examples/with-router/{app.jac → src/app.jac} +15 -15
  54. jac_client/plugin/cli.jac +504 -0
  55. jac_client/plugin/client.jac +45 -0
  56. jac_client/plugin/client_runtime.cl.jac +42 -0
  57. jac_client/plugin/impl/client.impl.jac +193 -0
  58. jac_client/plugin/impl/client_runtime.impl.jac +195 -0
  59. jac_client/plugin/impl/vite_client_bundle.impl.jac +72 -0
  60. jac_client/plugin/plugin_config.jac +195 -0
  61. jac_client/plugin/src/__init__.jac +20 -0
  62. jac_client/plugin/src/asset_processor.jac +33 -0
  63. jac_client/plugin/src/babel_processor.jac +18 -0
  64. jac_client/plugin/src/compiler.jac +67 -0
  65. jac_client/plugin/src/config_loader.jac +32 -0
  66. jac_client/plugin/src/impl/asset_processor.impl.jac +127 -0
  67. jac_client/plugin/src/impl/babel_processor.impl.jac +89 -0
  68. jac_client/plugin/src/impl/compiler.impl.jac +288 -0
  69. jac_client/plugin/src/impl/config_loader.impl.jac +119 -0
  70. jac_client/plugin/src/impl/import_processor.impl.jac +33 -0
  71. jac_client/plugin/src/impl/jac_to_js.impl.jac +41 -0
  72. jac_client/plugin/src/impl/package_installer.impl.jac +105 -0
  73. jac_client/plugin/src/impl/vite_bundler.impl.jac +626 -0
  74. jac_client/plugin/src/import_processor.jac +19 -0
  75. jac_client/plugin/src/jac_to_js.jac +35 -0
  76. jac_client/plugin/src/package_installer.jac +26 -0
  77. jac_client/plugin/src/vite_bundler.jac +44 -0
  78. jac_client/plugin/vite_client_bundle.jac +31 -0
  79. jac_client/tests/conftest.py +283 -0
  80. jac_client/tests/fixtures/basic-app/app.jac +2 -2
  81. jac_client/tests/fixtures/cl_file/app.cl.jac +2 -2
  82. jac_client/tests/fixtures/client_app_with_antd/app.jac +1 -1
  83. jac_client/tests/fixtures/js_import/app.jac +5 -5
  84. jac_client/tests/fixtures/spawn_test/app.jac +15 -18
  85. jac_client/tests/fixtures/with-ts/app.jac +35 -0
  86. jac_client/tests/test_cli.py +811 -0
  87. jac_client/tests/test_it.py +592 -97
  88. {jac_client-0.2.3.dist-info → jac_client-0.2.8.dist-info}/METADATA +41 -34
  89. jac_client-0.2.8.dist-info/RECORD +97 -0
  90. {jac_client-0.2.3.dist-info → jac_client-0.2.8.dist-info}/WHEEL +2 -1
  91. jac_client-0.2.8.dist-info/entry_points.txt +4 -0
  92. jac_client-0.2.8.dist-info/top_level.txt +1 -0
  93. jac_client/docs/README.md +0 -689
  94. jac_client/docs/advanced-state.md +0 -1265
  95. jac_client/docs/asset-serving/intro.md +0 -209
  96. jac_client/docs/assets/pipe_line-v2.svg +0 -32
  97. jac_client/docs/assets/pipe_line.png +0 -0
  98. jac_client/docs/file-system/app.jac.md +0 -121
  99. jac_client/docs/file-system/backend-frontend.md +0 -217
  100. jac_client/docs/file-system/intro.md +0 -72
  101. jac_client/docs/file-system/nested-imports.md +0 -348
  102. jac_client/docs/guide-example/intro.md +0 -115
  103. jac_client/docs/guide-example/step-01-setup.md +0 -270
  104. jac_client/docs/guide-example/step-02-components.md +0 -416
  105. jac_client/docs/guide-example/step-03-styling.md +0 -478
  106. jac_client/docs/guide-example/step-04-todo-ui.md +0 -477
  107. jac_client/docs/guide-example/step-05-local-state.md +0 -530
  108. jac_client/docs/guide-example/step-06-events.md +0 -749
  109. jac_client/docs/guide-example/step-07-effects.md +0 -468
  110. jac_client/docs/guide-example/step-08-walkers.md +0 -534
  111. jac_client/docs/guide-example/step-09-authentication.md +0 -586
  112. jac_client/docs/guide-example/step-10-routing.md +0 -539
  113. jac_client/docs/guide-example/step-11-final.md +0 -963
  114. jac_client/docs/imports.md +0 -1141
  115. jac_client/docs/lifecycle-hooks.md +0 -773
  116. jac_client/docs/routing.md +0 -659
  117. jac_client/docs/styling/intro.md +0 -249
  118. jac_client/docs/styling/js-styling.md +0 -367
  119. jac_client/docs/styling/material-ui.md +0 -341
  120. jac_client/docs/styling/pure-css.md +0 -299
  121. jac_client/docs/styling/sass.md +0 -403
  122. jac_client/docs/styling/styled-components.md +0 -395
  123. jac_client/docs/styling/tailwind.md +0 -298
  124. jac_client/examples/all-in-one/.babelrc +0 -9
  125. jac_client/examples/all-in-one/README.md +0 -16
  126. jac_client/examples/all-in-one/assets/burger.png +0 -0
  127. jac_client/examples/all-in-one/package.json +0 -29
  128. jac_client/examples/all-in-one/styles.css +0 -26
  129. jac_client/examples/all-in-one/vite.config.js +0 -28
  130. jac_client/examples/asset-serving/css-with-image/.babelrc +0 -9
  131. jac_client/examples/asset-serving/css-with-image/README.md +0 -91
  132. jac_client/examples/asset-serving/css-with-image/assets/burger.png +0 -0
  133. jac_client/examples/asset-serving/css-with-image/package.json +0 -28
  134. jac_client/examples/asset-serving/css-with-image/styles.css +0 -26
  135. jac_client/examples/asset-serving/css-with-image/vite.config.js +0 -28
  136. jac_client/examples/asset-serving/image-asset/.babelrc +0 -9
  137. jac_client/examples/asset-serving/image-asset/README.md +0 -119
  138. jac_client/examples/asset-serving/image-asset/assets/burger.png +0 -0
  139. jac_client/examples/asset-serving/image-asset/package.json +0 -28
  140. jac_client/examples/asset-serving/image-asset/styles.css +0 -26
  141. jac_client/examples/asset-serving/image-asset/vite.config.js +0 -28
  142. jac_client/examples/asset-serving/import-alias/.babelrc +0 -9
  143. jac_client/examples/asset-serving/import-alias/README.md +0 -83
  144. jac_client/examples/asset-serving/import-alias/assets/burger.png +0 -0
  145. jac_client/examples/asset-serving/import-alias/package.json +0 -28
  146. jac_client/examples/asset-serving/import-alias/vite.config.js +0 -28
  147. jac_client/examples/basic/.babelrc +0 -9
  148. jac_client/examples/basic/README.md +0 -16
  149. jac_client/examples/basic/package.json +0 -27
  150. jac_client/examples/basic/vite.config.js +0 -27
  151. jac_client/examples/basic-auth/.babelrc +0 -9
  152. jac_client/examples/basic-auth/README.md +0 -16
  153. jac_client/examples/basic-auth/app.jac +0 -308
  154. jac_client/examples/basic-auth/package.json +0 -27
  155. jac_client/examples/basic-auth/vite.config.js +0 -27
  156. jac_client/examples/basic-auth-with-router/.babelrc +0 -9
  157. jac_client/examples/basic-auth-with-router/README.md +0 -60
  158. jac_client/examples/basic-auth-with-router/package.json +0 -28
  159. jac_client/examples/basic-auth-with-router/vite.config.js +0 -27
  160. jac_client/examples/basic-full-stack/.babelrc +0 -9
  161. jac_client/examples/basic-full-stack/README.md +0 -18
  162. jac_client/examples/basic-full-stack/package.json +0 -28
  163. jac_client/examples/basic-full-stack/vite.config.js +0 -27
  164. jac_client/examples/css-styling/js-styling/.babelrc +0 -9
  165. jac_client/examples/css-styling/js-styling/README.md +0 -183
  166. jac_client/examples/css-styling/js-styling/package.json +0 -28
  167. jac_client/examples/css-styling/js-styling/styles.js +0 -100
  168. jac_client/examples/css-styling/js-styling/vite.config.js +0 -27
  169. jac_client/examples/css-styling/material-ui/.babelrc +0 -9
  170. jac_client/examples/css-styling/material-ui/README.md +0 -16
  171. jac_client/examples/css-styling/material-ui/package.json +0 -32
  172. jac_client/examples/css-styling/material-ui/vite.config.js +0 -27
  173. jac_client/examples/css-styling/pure-css/.babelrc +0 -9
  174. jac_client/examples/css-styling/pure-css/README.md +0 -16
  175. jac_client/examples/css-styling/pure-css/package.json +0 -28
  176. jac_client/examples/css-styling/pure-css/styles.css +0 -111
  177. jac_client/examples/css-styling/pure-css/vite.config.js +0 -27
  178. jac_client/examples/css-styling/sass-example/.babelrc +0 -9
  179. jac_client/examples/css-styling/sass-example/README.md +0 -16
  180. jac_client/examples/css-styling/sass-example/package.json +0 -29
  181. jac_client/examples/css-styling/sass-example/styles.scss +0 -153
  182. jac_client/examples/css-styling/sass-example/vite.config.js +0 -27
  183. jac_client/examples/css-styling/styled-components/.babelrc +0 -9
  184. jac_client/examples/css-styling/styled-components/README.md +0 -16
  185. jac_client/examples/css-styling/styled-components/package.json +0 -29
  186. jac_client/examples/css-styling/styled-components/styled.js +0 -90
  187. jac_client/examples/css-styling/styled-components/vite.config.js +0 -27
  188. jac_client/examples/css-styling/tailwind-example/.babelrc +0 -9
  189. jac_client/examples/css-styling/tailwind-example/README.md +0 -16
  190. jac_client/examples/css-styling/tailwind-example/global.css +0 -1
  191. jac_client/examples/css-styling/tailwind-example/package.json +0 -30
  192. jac_client/examples/css-styling/tailwind-example/vite.config.js +0 -29
  193. jac_client/examples/full-stack-with-auth/.babelrc +0 -9
  194. jac_client/examples/full-stack-with-auth/README.md +0 -16
  195. jac_client/examples/full-stack-with-auth/package.json +0 -28
  196. jac_client/examples/full-stack-with-auth/vite.config.js +0 -29
  197. jac_client/examples/little-x/package.json +0 -23
  198. jac_client/examples/little-x/submit-button.jac +0 -8
  199. jac_client/examples/nested-folders/nested-advance/.babelrc +0 -9
  200. jac_client/examples/nested-folders/nested-advance/README.md +0 -77
  201. jac_client/examples/nested-folders/nested-advance/package.json +0 -29
  202. jac_client/examples/nested-folders/nested-advance/vite.config.js +0 -28
  203. jac_client/examples/nested-folders/nested-basic/.babelrc +0 -9
  204. jac_client/examples/nested-folders/nested-basic/README.md +0 -183
  205. jac_client/examples/nested-folders/nested-basic/app.js +0 -7
  206. jac_client/examples/nested-folders/nested-basic/package.json +0 -28
  207. jac_client/examples/nested-folders/nested-basic/vite.config.js +0 -27
  208. jac_client/examples/with-router/.babelrc +0 -9
  209. jac_client/examples/with-router/README.md +0 -17
  210. jac_client/examples/with-router/package.json +0 -28
  211. jac_client/examples/with-router/vite.config.js +0 -27
  212. jac_client/plugin/cli.py +0 -244
  213. jac_client/plugin/client.py +0 -152
  214. jac_client/plugin/client_runtime.jac +0 -234
  215. jac_client/plugin/vite_client_bundle.py +0 -503
  216. jac_client/tests/fixtures/js_import/utils.js +0 -21
  217. jac_client/tests/fixtures/package-lock.json +0 -329
  218. jac_client/tests/fixtures/package.json +0 -11
  219. jac_client/tests/test_asset_examples.py +0 -322
  220. jac_client/tests/test_cl.py +0 -530
  221. jac_client/tests/test_create_jac_app.py +0 -131
  222. jac_client/tests/test_nested_file.py +0 -374
  223. jac_client-0.2.3.dist-info/RECORD +0 -171
  224. jac_client-0.2.3.dist-info/entry_points.txt +0 -4
@@ -1,24 +1,11 @@
1
- #
2
- # Combined example: routing + CSS styling + asset serving + nested folder imports
3
- #
4
- cl import from react { useState, useEffect }
5
- cl import from "@jac-client/utils" { Router, Routes, Route, Link, useLocation }
6
-
7
- # Pure CSS + asset-in-CSS example
8
- cl import ".styles.css";
9
-
10
- # Nested folder imports (same pattern as nested-basic/)
11
- cl import from .components.button {
12
- CustomButton
13
- }
14
- cl import from .button { CustomButtonRoot }
1
+ import from datetime { datetime, timedelta }
15
2
 
16
3
  #
17
4
  # Basic backend walkers
18
5
  #
19
6
  node Todo {
20
- has text: str;
21
- has done: bool = False;
7
+ has text: str,
8
+ done: bool = False;
22
9
  }
23
10
 
24
11
  walker create_todo {
@@ -42,385 +29,545 @@ walker get_server_message {
42
29
  }
43
30
  }
44
31
 
45
- cl {
46
- # Home page demonstrating CSS styling + direct asset usage + basic walkers
47
- def Home() -> any {
48
- let [count, setCount] = useState(0);
49
- let [pingResult, setPingResult] = useState("");
50
- let [serverMessage, setServerMessage] = useState("");
51
- let [lastTodoMessage, setLastTodoMessage] = useState("");
52
-
53
- useEffect(
54
- lambda -> None{ console.log("Home count changed: ", count);} , [count]
32
+
33
+
34
+ # Features Test Page - Backend Logic
35
+ # This file is intentionally kept empty to demonstrate the separation of concerns
36
+ # where UI logic resides in .cl.jac files and backend walker logic in app.jac
37
+
38
+ # All walker implementations for this feature are in src/app.jac
39
+ # This demonstrates that you can have separate .jac files for different purposes
40
+ # Features Test - Backend Walkers
41
+ # This file demonstrates walker functionality for testing various JAC features
42
+
43
+
44
+ # Node definition for storing test data
45
+ node TestData {
46
+ has message: str;
47
+ has count: int = 0;
48
+ has created_at: str = "";
49
+ }
50
+
51
+ # Walker: Create test data
52
+ walker create_test_data {
53
+ has message: str;
54
+
55
+ can create with `root entry {
56
+ new_data = here ++> TestData(
57
+ message=self.message,
58
+ count=1,
59
+ created_at=datetime.now().strftime("%Y-%m-%d %H:%M:%S")
55
60
  );
61
+ report new_data;
62
+ }
63
+ }
64
+
65
+ # Walker: Read all test data
66
+ walker read_test_data {
67
+ can read with `root entry {
68
+ visit [-->(`?TestData)];
69
+ }
70
+
71
+ can report_data with exit {
72
+ report here;
73
+ }
74
+ }
75
+
76
+ # Walker: Update test data
77
+ walker update_test_data {
78
+ has new_message: str;
79
+
80
+ can update with TestData entry {
81
+ here.message = self.new_message;
82
+ here.count = here.count + 1;
83
+ report here;
84
+ }
85
+ }
86
+
87
+ # Walker: Delete test data
88
+ walker delete_test_data {
89
+ can delete with TestData entry {
90
+ del here;
91
+ report {"status": "deleted"};
92
+ }
93
+ }
94
+
95
+ # Walker: String manipulation test
96
+ walker test_string_methods {
97
+ has input_text: str;
98
+
99
+ can process with `root entry {
100
+ result = {
101
+ "original": self.input_text,
102
+ "uppercase": self.input_text.upper(),
103
+ "lowercase": self.input_text.lower(),
104
+ "capitalized": self.input_text.capitalize(),
105
+ "reversed": self.input_text[::-1],
106
+ "length": len(self.input_text),
107
+ "words": self.input_text.split(),
108
+ "trimmed": self.input_text.strip(),
109
+ "replaced": self.input_text.replace("test", "demo")
110
+ };
111
+ report result;
112
+ }
113
+ }
114
+
115
+ # Walker: Array/List operations test
116
+ walker test_list_operations {
117
+ has numbers: list;
118
+
119
+ can process with `root entry {
120
+ result = {
121
+ "original": self.numbers,
122
+ "sorted": sorted(self.numbers),
123
+ "reversed": list(reversed(self.numbers)),
124
+ "sum": sum(self.numbers),
125
+ "max": max(self.numbers) if len(self.numbers) > 0 else 0,
126
+ "min": min(self.numbers) if len(self.numbers) > 0 else 0,
127
+ "length": len(self.numbers),
128
+ "doubled": [x * 2 for x in self.numbers]
129
+ };
130
+ report result;
131
+ }
132
+ }
133
+
134
+ # Walker: Complex data processing
135
+ walker process_complex_data {
136
+ has items: list;
137
+
138
+ can process with `root entry {
139
+ processed = [];
140
+ for item in self.items {
141
+ processed.append({
142
+ "id": item.get("id", 0),
143
+ "name": item.get("name", "").upper(),
144
+ "value": item.get("value", 0) * 2,
145
+ "processed_at": datetime.now().strftime("%H:%M:%S")
146
+ });
147
+ }
148
+
149
+ result = {
150
+ "original_count": len(self.items),
151
+ "processed_count": len(processed),
152
+ "items": processed,
153
+ "total_value": sum([p["value"] for p in processed])
154
+ };
155
+
156
+ report result;
157
+ }
158
+ }
159
+
160
+
161
+ #
162
+ # Combined example: auth + routing + CSS styling + asset serving + nested folder imports
163
+ #
164
+ cl import from react { useEffect, useRef }
165
+ cl import from "@jac-client/utils" {
166
+ Router,
167
+ Routes,
168
+ Route,
169
+ Link,
170
+ useNavigate,
171
+ Navigate,
172
+ jacIsLoggedIn
173
+
174
+ }
175
+
176
+ # Pure CSS + asset-in-CSS example
177
+ cl import ".styles.css";
178
+
179
+ # Login Page
180
+ cl import from .pages.loginPage { LoginPage }
181
+
182
+ # Signup Page
183
+ cl import from .pages.signupPage { SignupPage }
184
+
185
+ # Simple 404 page
186
+ cl import from .pages.notFound { NotFound }
187
+
188
+ # Navigation component with active link styling and auth
189
+ cl import from .components.navigation { Navigation }
190
+
191
+ # Page showing nested imports from different folders
192
+ cl import from .pages.nestedDemo { NestedImportsDemo }
193
+
194
+ cl import from .pages.FeaturesTest { FeaturesTest }
56
195
 
57
- # Call simple backend walkers
58
- async def handlePing() -> None {
59
- result = root spawn ping_server();
60
- if result.reports and result.reports.length > 0 {
61
- setPingResult(result.reports[0][0]);
62
- }
196
+ cl import from .pages.LandingPage { LandingPage }
197
+
198
+ cl import from .pages.BudgetPlanner { BudgetPlanner }
199
+
200
+ # Context provider
201
+ cl import from .context.BudgetContext { BudgetProvider }
202
+
203
+
204
+
205
+ # TypeScript component import
206
+ cl import from ".components/Card.tsx" { Card }
207
+
208
+
209
+ # Main app wrapped in Router (same API as with-router/ example)
210
+ cl {
211
+ def:pub HomePage -> any {
212
+ # Check if user is logged in, redirect if not
213
+ if not jacIsLoggedIn() {
214
+ return <Navigate to="/login" />;
215
+ }
216
+ has count: int = 0;
217
+ has pingResult: str = "";
218
+ has serverMessage: str = "";
219
+ has lastTodoMessage: str = "";
220
+
221
+ useEffect(
222
+ lambda -> None{ console.log("Home count changed: ", count);} , [count]
223
+ );
224
+
225
+ # Call simple backend walkers
226
+ async def handlePing -> None {
227
+ result = root spawn ping_server();
228
+ if result.reports and result.reports.length > 0 {
229
+ pingResult = result.reports[0][0];
63
230
  }
231
+ }
64
232
 
65
- async def loadServerMessage() -> None {
66
- result = root spawn get_server_message();
67
- if result.reports and result.reports.length > 0 {
68
- setServerMessage(result.reports[0][0]);
69
- }
233
+ async def loadServerMessage -> None {
234
+ result = root spawn get_server_message();
235
+ if result.reports and result.reports.length > 0 {
236
+ serverMessage = result.reports[0][0];
70
237
  }
238
+ }
71
239
 
72
- # Create a sample Todo node in the graph with a hardcoded payload
73
- async def handleCreateSampleTodo() -> None {
74
- result = root spawn create_todo(text="Sample todo from all-in-one app");
75
- if result.reports and result.reports.length > 0 {
76
- todo = result.reports[0][0];
77
- setLastTodoMessage("Created Todo: " + todo.text);
78
- console.log("Created Todo node:", todo);
79
- }
240
+ # Create a sample Todo node in the graph with a hardcoded payload
241
+ async def handleCreateSampleTodo -> None {
242
+ result = root spawn create_todo(text="Sample todo from all-in-one app");
243
+ if result.reports and result.reports.length > 0 {
244
+ todo = result.reports[0][0];
245
+ lastTodoMessage = "Created Todo: " + todo.text;
246
+ console.log("Created Todo node:", todo);
80
247
  }
248
+ }
249
+
250
+ useEffect(lambda -> None{ loadServerMessage();} , []);
81
251
 
82
- useEffect(lambda -> None{ loadServerMessage();} , []);
252
+ # Initialize a Web Worker and handle message-based communication
253
+ workerRef = useRef(None);
254
+ has message: str = "";
83
255
 
84
- return <div
85
- style={{
86
- "padding": "2rem",
87
- "fontFamily": "system-ui, -apple-system, sans-serif"
88
- }}
256
+ useEffect(lambda -> None {
257
+ workerRef.current = Reflect.construct(Worker, ["/workers/worker.js"]);
258
+ workerRef.current.onmessage = lambda event: any -> None {
259
+ console.log("Message received from worker:", event.data);
260
+ message = event.data;
261
+ };
262
+ return (lambda -> None {
263
+ workerRef.current.terminate();
264
+ });
265
+ }, []);
266
+ handleClick = lambda -> None {
267
+ workerRef.current.postMessage("");
268
+ };
269
+
270
+ return <div
271
+ style={{
272
+ "padding": "2rem",
273
+ "fontFamily": "system-ui, -apple-system, sans-serif"
274
+ }}
275
+ >
276
+ <h1>
277
+ 🍔 Router + Styling + Assets Demo
278
+ </h1>
279
+ <p>
280
+ This home page combines
281
+ {" "}
282
+ <strong>
283
+ React Router,
284
+ </strong>
285
+ {" "}
286
+ <strong>
287
+ pure CSS styling,
288
+ </strong>
289
+ {" "}
290
+ <strong>
291
+ static assets
292
+ </strong>
293
+ {" "}
294
+ and
295
+ {" "}
296
+ <strong>
297
+ nested folder imports
298
+ </strong>
299
+ </p>
300
+ <div className="container">
301
+ <h2
302
+ style={{
303
+ "color": "white",
304
+ "textShadow": "2px 2px 4px rgba(0,0,0,0.6)"
305
+ }}
306
+ >
307
+ CSS Background Image
308
+ </h2>
309
+ <p
310
+ style={{
311
+ "color": "white",
312
+ "maxWidth": "480px",
313
+ "textShadow": "1px 1px 3px rgba(0,0,0,0.7)"
314
+ }}
315
+ >
316
+ This section uses the burger image as a background via CSS, just like the
317
+ {" "}
318
+ <code>
319
+ asset-serving/css-with-image
320
+ </code>
321
+ {" "}
322
+ example.
323
+ </p>
324
+ </div>
325
+ <Card
326
+ title="TypeScript Card Component"
327
+ description="This card is built with TypeScript and demonstrates type-safe component usage in Jac"
328
+ variant="highlighted"
89
329
  >
90
- <h1>
91
- 🍔 Router + Styling + Assets Demo
92
- </h1>
330
+ <p
331
+ style={{"margin": "0.5rem 0", "color": "#374151"}}
332
+ >
333
+ This is a TypeScript component imported and used in Jac code!
334
+ </p>
335
+ </Card>
336
+ <div className="card">
337
+ <h3>
338
+ Direct &lt;img&gt; asset
339
+ </h3>
340
+ <img
341
+ src="/static/assets/burger.png"
342
+ alt="Burger asset served by Jac"
343
+ className="burgerImage"
344
+ />
345
+ <p
346
+ style={{"marginTop": "0.75rem", "color": "#555"}}
347
+ >
348
+ This image is served from the project
349
+ {" "}
350
+ <code>
351
+ assets/
352
+ </code>
353
+ {" "}
354
+ folder using the
355
+ {" "}
356
+ <code>
357
+ /static/assets/
358
+ </code>
359
+ {" "}
360
+ path.
361
+ </p>
362
+ </div>
363
+ <div
364
+ style={{"marginTop": "2rem"}}
365
+ >
366
+ <h3>
367
+ Counter with pure CSS classes
368
+ </h3>
93
369
  <p>
94
- This home page combines
370
+ You've clicked the burger
95
371
  {" "}
96
372
  <strong>
97
- React Router,
373
+ {count}
98
374
  </strong>
99
375
  {" "}
100
- <strong>
101
- pure CSS styling,
102
- </strong>
376
+ times.
377
+ </p>
378
+ <button
379
+ onClick={lambda e: any -> None{ count = count + 1;} }
380
+ style={{
381
+ "padding": "0.6rem 1.4rem",
382
+ "fontSize": "1rem",
383
+ "backgroundColor": "#ff6b35",
384
+ "color": "white",
385
+ "border": "none",
386
+ "borderRadius": "6px",
387
+ "cursor": "pointer",
388
+ "boxShadow": "0 2px 4px rgba(0,0,0,0.2)"
389
+ }}
390
+ >
391
+ Click the Burger! 🍔
392
+ </button>
393
+ </div>
394
+ <div
395
+ style={{"marginTop": "2rem"}}
396
+ >
397
+ <h3>
398
+ Backend Walkers
399
+ </h3>
400
+ <p>
401
+ Basic example walkers:
103
402
  {" "}
104
- <strong>
105
- static assets
106
- </strong>
403
+ <code>
404
+ ping_server
405
+ </code>
107
406
  {" "}
108
407
  and
109
408
  {" "}
110
- <strong>
111
- nested folder imports
112
- </strong>
409
+ <code>
410
+ get_server_message
411
+ </code>
113
412
  </p>
114
- <div className="container">
115
- <h2
116
- style={{
117
- "color": "white",
118
- "textShadow": "2px 2px 4px rgba(0,0,0,0.6)"
119
- }}
120
- >
121
- CSS Background Image
122
- </h2>
123
- <p
124
- style={{
125
- "color": "white",
126
- "maxWidth": "480px",
127
- "textShadow": "1px 1px 3px rgba(0,0,0,0.7)"
128
- }}
413
+ <button
414
+ onClick={lambda e: any -> None{ handlePing();} }
415
+ style={{
416
+ "padding": "0.5rem 1.2rem",
417
+ "marginRight": "0.75rem",
418
+ "backgroundColor": "#3b82f6",
419
+ "color": "white",
420
+ "border": "none",
421
+ "borderRadius": "6px",
422
+ "cursor": "pointer"
423
+ }}
424
+ >
425
+ Ping Backend
426
+ </button>
427
+ <button
428
+ onClick={lambda e: any -> None{ handleCreateSampleTodo();} }
429
+ style={{
430
+ "padding": "0.5rem 1.2rem",
431
+ "backgroundColor": "#10b981",
432
+ "color": "white",
433
+ "border": "none",
434
+ "borderRadius": "6px",
435
+ "cursor": "pointer"
436
+ }}
437
+ >
438
+ Create Sample Todo
439
+ </button>
440
+ {pingResult
441
+ and (
442
+ <span
443
+ style={{"marginLeft": "0.5rem", "color": "#374151"}}
129
444
  >
130
- This section uses the burger image as a background via CSS, just like the
445
+ Result:
131
446
  {" "}
132
447
  <code>
133
- asset-serving/css-with-image
448
+ {pingResult}
134
449
  </code>
135
- {" "}
136
- example.
137
- </p>
138
- </div>
139
- <div className="card">
140
- <h3>
141
- Direct &lt;img&gt; asset
142
- </h3>
143
- <img
144
- src="/static/assets/burger.png"
145
- alt="Burger asset served by Jac"
146
- className="burgerImage"
147
- />
450
+ </span>
451
+ )}
452
+ {serverMessage
453
+ and (
148
454
  <p
149
- style={{"marginTop": "0.75rem", "color": "#555"}}
455
+ style={{"marginTop": "0.75rem", "color": "#374151"}}
150
456
  >
151
- This image is served from the project
152
- {" "}
153
- <code>
154
- assets/
155
- </code>
156
- {" "}
157
- folder using the
457
+ Message:
158
458
  {" "}
159
459
  <code>
160
- /static/assets/
460
+ {serverMessage}
161
461
  </code>
162
- {" "}
163
- path.
164
- </p>
165
- </div>
166
- <div
167
- style={{"marginTop": "2rem"}}
168
- >
169
- <h3>
170
- Counter with pure CSS classes
171
- </h3>
172
- <p>
173
- You've clicked the burger
174
- {" "}
175
- <strong>
176
- {count}
177
- </strong>
178
- {" "}
179
- times.
180
462
  </p>
181
- <button
182
- onClick={lambda e: any -> None{ setCount(count + 1);} }
183
- style={{
184
- "padding": "0.6rem 1.4rem",
185
- "fontSize": "1rem",
186
- "backgroundColor": "#ff6b35",
187
- "color": "white",
188
- "border": "none",
189
- "borderRadius": "6px",
190
- "cursor": "pointer",
191
- "boxShadow": "0 2px 4px rgba(0,0,0,0.2)"
192
- }}
463
+ )}
464
+ {lastTodoMessage
465
+ and (
466
+ <p
467
+ style={{"marginTop": "0.5rem", "color": "#111827"}}
193
468
  >
194
- Click the Burger! 🍔
195
- </button>
196
- </div>
197
- <div
198
- style={{"marginTop": "2rem"}}
199
- >
200
- <h3>
201
- Backend Walkers
202
- </h3>
203
- <p>
204
- Basic example walkers:
205
- {" "}
206
- <code>
207
- ping_server
208
- </code>
209
- {" "}
210
- and
211
- {" "}
212
- <code>
213
- get_server_message
214
- </code>
469
+ {lastTodoMessage}
215
470
  </p>
216
- <button
217
- onClick={lambda e: any -> None{ handlePing();} }
218
- style={{
219
- "padding": "0.5rem 1.2rem",
220
- "marginRight": "0.75rem",
221
- "backgroundColor": "#3b82f6",
222
- "color": "white",
223
- "border": "none",
224
- "borderRadius": "6px",
225
- "cursor": "pointer"
226
- }}
227
- >
228
- Ping Backend
229
- </button>
230
- <button
231
- onClick={lambda e: any -> None{ handleCreateSampleTodo();} }
232
- style={{
233
- "padding": "0.5rem 1.2rem",
234
- "backgroundColor": "#10b981",
235
- "color": "white",
236
- "border": "none",
237
- "borderRadius": "6px",
238
- "cursor": "pointer"
239
- }}
240
- >
241
- Create Sample Todo
242
- </button>
243
- {pingResult
244
- and (
245
- <span
246
- style={{"marginLeft": "0.5rem", "color": "#374151"}}
247
- >
248
- Result:
249
- {" "}
250
- <code>
251
- {pingResult}
252
- </code>
253
- </span>
254
- )}
255
- {serverMessage
256
- and (
257
- <p
258
- style={{"marginTop": "0.75rem", "color": "#374151"}}
259
- >
260
- Message:
261
- {" "}
262
- <code>
263
- {serverMessage}
264
- </code>
265
- </p>
266
- )}
267
- {lastTodoMessage
268
- and (
269
- <p
270
- style={{"marginTop": "0.5rem", "color": "#111827"}}
271
- >
272
- {lastTodoMessage}
273
- </p>
274
- )}
275
- </div>
276
- </div>;
277
- }
278
-
279
- # Page showing nested imports from different folders
280
- def NestedImportsDemo() -> any {
281
- return <div
282
- style={{
283
- "padding": "2rem",
284
- "fontFamily": "system-ui, -apple-system, sans-serif"
285
- }}
471
+ )}
472
+ </div>
473
+ <div
474
+ style={{"marginTop": "2rem"}}
286
475
  >
287
- <h1>
288
- 📁 Nested Folder Imports
289
- </h1>
476
+ <h3>
477
+ Web Worker
478
+ </h3>
290
479
  <p>
291
- This page mirrors the
480
+ This demonstrates how to communicate with a
292
481
  {" "}
293
- <code>
294
- nested-folders/nested-basic
295
- </code>
482
+ <strong>Python backend worker</strong>
296
483
  {" "}
297
- example by importing components from both
484
+ using Web Workers for asynchronous processing.
485
+ </p>
486
+ <p
487
+ style={{"fontSize": "0.9rem", "color": "#666", "marginTop": "0.5rem"}}
488
+ >
489
+ File:
298
490
  {" "}
299
491
  <code>
300
- components.button
492
+ worker.py
301
493
  </code>
302
494
  {" "}
303
- and
304
- {" "}
305
- <code>
306
- button
307
- </code>
308
- </p>
309
- <p
310
- style={{"marginTop": "0.75rem"}}
311
- >
312
- Both buttons below are rendered via relative imports:
495
+ — Runs in a separate thread to avoid blocking the UI.
313
496
  </p>
314
- <div
315
- style={{"display": "flex", "gap": "1rem", "marginTop": "1.5rem"}}
497
+ <button
498
+ onClick={lambda -> None { handleClick(); }}
499
+ style={{
500
+ "padding": "0.5rem 1.2rem",
501
+ "marginRight": "0.75rem",
502
+ "backgroundColor": "#d73bf6ff",
503
+ "color": "white",
504
+ "border": "none",
505
+ "borderRadius": "6px",
506
+ "cursor": "pointer"
507
+ }}
316
508
  >
317
- <CustomButton />
318
- <CustomButtonRoot />
319
- </div>
320
- </div>;
321
- }
322
-
323
- # Simple 404 page
324
- def NotFound() -> any {
325
- return <div
326
- style={{
327
- "padding": "2rem",
328
- "textAlign": "center",
329
- "fontFamily": "system-ui, -apple-system, sans-serif"
330
- }}
331
- >
332
- <h1>
333
- 🔍 404 - Page Not Found
334
- </h1>
335
- <p>
336
- The page you are looking for does not exist.
337
- </p>
338
- <Link to="/">
339
- ← Back to Home
340
- </Link>
341
- </div>;
342
- }
343
-
344
- # Navigation component with active link styling (same pattern as routing docs)
345
- def Navigation() -> any {
346
- let location = useLocation();
347
-
348
- def linkStyle(path: str) -> dict {
349
- isActive = location.pathname == path;
350
- return {
351
- "padding": "0.5rem 1rem",
352
- "textDecoration": "none",
353
- "color": "#0066cc" if isActive else "#333",
354
- "fontWeight": "bold" if isActive else "normal",
355
- "backgroundColor": "#e3f2fd" if isActive else "transparent",
356
- "borderRadius": "4px",
357
- "display": "inline-block"
358
- };
359
- }
509
+ Call Python Worker
510
+ </button>
511
+ {message && (
512
+ <p style={{ marginTop: "1rem", fontWeight: "bold" }}>
513
+ {message}
514
+ </p>
515
+ )}
516
+ </div>
517
+ </div>;
518
+ }
360
519
 
361
- return <nav
362
- style={{
363
- "padding": "1rem",
364
- "backgroundColor": "#f5f5f5",
365
- "marginBottom": "2rem",
366
- "boxShadow": "0 2px 4px rgba(0,0,0,0.1)"
367
- }}
520
+ def:pub app -> any {
521
+ return <Router>
522
+ <div
523
+ style={{"fontFamily": "system-ui, -apple-system, sans-serif"}}
368
524
  >
525
+ <Navigation />
369
526
  <div
370
527
  style={{
371
- "maxWidth": "1200px",
528
+ "maxWidth": "960px",
372
529
  "margin": "0 auto",
373
- "display": "flex",
374
- "gap": "1rem",
375
- "alignItems": "center"
530
+ "padding": "0 1rem 3rem 1rem"
376
531
  }}
377
532
  >
378
- <Link
379
- to="/"
380
- style={linkStyle("/")}
381
- >
382
- Home
383
- </Link>
384
- <Link
385
- to="/nested"
386
- style={linkStyle("/nested")}
387
- >
388
- Nested Imports
389
- </Link>
390
- </div>
391
- </nav>;
392
- }
393
-
394
- # Main app wrapped in Router (same API as with-router/ example)
395
- def app() -> any {
396
- return <Router>
397
- <div
398
- style={{"fontFamily": "system-ui, -apple-system, sans-serif"}}
399
- >
400
- <Navigation />
401
- <div
402
- style={{
403
- "maxWidth": "960px",
404
- "margin": "0 auto",
405
- "padding": "0 1rem 3rem 1rem"
406
- }}
407
- >
408
- <Routes>
409
- <Route
410
- path="/"
411
- element={<Home />}
412
- />
413
- <Route
414
- path="/nested"
415
- element={<NestedImportsDemo />}
416
- />
417
- <Route
418
- path="*"
419
- element={<NotFound />}
420
- />
421
- </Routes>
422
- </div>
533
+ <Routes>
534
+ <Route
535
+ path="/"
536
+ element={<HomePage />}
537
+ />
538
+ <Route
539
+ path="/login"
540
+ element={<LoginPage />}
541
+ />
542
+ <Route
543
+ path="/signup"
544
+ element={<SignupPage />}
545
+ />
546
+ <Route
547
+ path="/nested"
548
+ element={<NestedImportsDemo />}
549
+ />
550
+ <Route
551
+ path="/features-test"
552
+ element={<FeaturesTest />}
553
+ />
554
+ <Route
555
+ path="/landing"
556
+ element={<LandingPage />}
557
+ />
558
+ <Route
559
+ path="/budget-planner"
560
+ element={<BudgetProvider>
561
+ <BudgetPlanner />
562
+ </BudgetProvider>}
563
+ />
564
+ <Route
565
+ path="*"
566
+ element={<NotFound />}
567
+ />
568
+ </Routes>
423
569
  </div>
424
- </Router>;
425
- }
570
+ </div>
571
+ </Router>;
572
+ }
426
573
  }