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
@@ -0,0 +1,552 @@
1
+ # # Features Test Page - Client-side UI
2
+ # # Demonstrates: props, exports, cl files, TypeScript imports, string methods,
3
+ # # imports from JAC/JS/TS, spawning walkers from cl file
4
+
5
+ import from "@jac-client/utils" { Link, useNavigate }
6
+ import from react { useState, useEffect }
7
+
8
+ # # Import TypeScript component
9
+ # import from ..components.PieChart { PieChart }
10
+
11
+ # # Import JavaScript helpers
12
+ import from ..utils.helpers { generateId, calculatePercentage, sumBy }
13
+
14
+ # # Import from other JAC files
15
+ import from ..utils.formatters { formatCurrency }
16
+
17
+ # ============================================================================
18
+ # REUSABLE COMPONENTS WITH PROPS
19
+ # ============================================================================
20
+
21
+ # Button component demonstrating props - NEW PATTERN: Direct parameters
22
+ def:pub TestButton(text: str, onClick: any, variant: str) -> any {
23
+ bg_color = "#3b82f6" if variant == "primary" else "#6b7280";
24
+ hover_color = "#2563eb" if variant == "primary" else "#4b5563";
25
+
26
+ return <button
27
+ onClick={onClick}
28
+ style={{
29
+ "padding": "10px 20px",
30
+ "backgroundColor": bg_color,
31
+ "color": "white",
32
+ "border": "none",
33
+ "borderRadius": "6px",
34
+ "cursor": "pointer",
35
+ "fontSize": "14px",
36
+ "fontWeight": "600",
37
+ "transition": "all 0.2s"
38
+ }}
39
+ onMouseOver={lambda e: any -> None {
40
+ e.target.style.backgroundColor = hover_color;
41
+ }}
42
+ onMouseOut={lambda e: any -> None {
43
+ e.target.style.backgroundColor = bg_color;
44
+ }}
45
+ >
46
+ {text}
47
+ </button>;
48
+ }
49
+
50
+ # # Card component with props - NEW PATTERN: Direct parameters
51
+ def:pub TestCard(title: str, children: any, color: str) -> any {
52
+ return <div style={{
53
+ "backgroundColor": "white",
54
+ "border": "1px solid #e5e7eb",
55
+ "borderRadius": "8px",
56
+ "padding": "20px",
57
+ "marginBottom": "20px",
58
+ "boxShadow": "0 1px 3px rgba(0,0,0,0.1)"
59
+ }}>
60
+ <div style={{
61
+ "backgroundColor": color,
62
+ "padding": "10px",
63
+ "borderRadius": "6px",
64
+ "marginBottom": "15px"
65
+ }}>
66
+ <h3 style={{
67
+ "margin": "0",
68
+ "fontSize": "18px",
69
+ "fontWeight": "600",
70
+ "color": "#1f2937"
71
+ }}>{title}</h3>
72
+ </div>
73
+ <div>{children}</div>
74
+ </div>;
75
+ }
76
+
77
+ # Result display component - NEW PATTERN: Direct parameters
78
+ def:pub ResultDisplay(data: any, label: str) -> any {
79
+ if not data {
80
+ return <div style={{"color": "#9ca3af", "fontStyle": "italic"}}>
81
+ No data to display
82
+ </div>;
83
+ }
84
+
85
+ return <div style={{
86
+ "backgroundColor": "#f9fafb",
87
+ "padding": "15px",
88
+ "borderRadius": "6px",
89
+ "border": "1px solid #e5e7eb"
90
+ }}>
91
+ <strong style={{"color": "#374151"}}>{label}:</strong>
92
+ <pre style={{
93
+ "marginTop": "10px",
94
+ "padding": "10px",
95
+ "backgroundColor": "#1f2937",
96
+ "color": "#10b981",
97
+ "borderRadius": "4px",
98
+ "overflow": "auto",
99
+ "fontSize": "12px",
100
+ "fontFamily": "monospace"
101
+ }}>
102
+ {JSON.stringify(data, None, 2)}
103
+ </pre>
104
+ </div>;
105
+ }
106
+
107
+ # ============================================================================
108
+ # MAIN PAGE COMPONENT
109
+ # ============================================================================
110
+
111
+ def:pub FeaturesTest() -> any {
112
+ navigate = useNavigate();
113
+
114
+ # State management
115
+ has testMessage: str = "";
116
+ has testData: list = [];
117
+ has stringInput: str = "Hello JAC World!";
118
+ has stringResult: any = None;
119
+ has numberList: str = "1,2,3,4,5";
120
+ has listResult: any = None;
121
+ has complexResult: any = None;
122
+ has loading: bool = false;
123
+
124
+ # Load test data on mount
125
+ useEffect(lambda -> None {
126
+ async def loadData() -> None {
127
+ try {
128
+ result = root spawn read_test_data();
129
+ testData = result.reports if result.reports[0] else [];
130
+ } except Exception as e {
131
+ console.log("Error loading data:", e);
132
+ }
133
+ }
134
+ loadData();
135
+ }, []);
136
+
137
+ # ========================================================================
138
+ # EVENT HANDLERS - Demonstrating Walker Spawning from CL
139
+ # ========================================================================
140
+
141
+ # Create test data
142
+ async def handleCreate() -> None {
143
+ if not testMessage.trim() {
144
+ alert("Please enter a message");
145
+ return;
146
+ }
147
+
148
+ loading = true;
149
+ try {
150
+ response = root spawn create_test_data(message=testMessage.trim());
151
+ new_item = response.reports[0][0];
152
+ testData = testData.concat([new_item]);
153
+ testMessage = "";
154
+ alert("Data created successfully!");
155
+ } except Exception as e {
156
+ console.error("Error creating data:", e);
157
+ alert("Error creating data: " + e.toString());
158
+ }
159
+ loading = false;
160
+ }
161
+
162
+ # Update test data
163
+ async def handleUpdate(item_id: any) -> None {
164
+ new_msg = prompt("Enter new message:");
165
+ if not new_msg {
166
+ return;
167
+ }
168
+
169
+ loading = true;
170
+ try {
171
+ item_id spawn update_test_data(new_message=new_msg);
172
+ # Reload data
173
+ result = root spawn read_test_data();
174
+ testData = result.reports if result.reports[0] else [];
175
+ alert("Data updated successfully!");
176
+ } except Exception as e {
177
+ console.error("Error updating data:", e);
178
+ alert("Error updating data: " + e.toString());
179
+ }
180
+ loading = false;
181
+ }
182
+
183
+ # Delete test data
184
+ async def handleDelete(item_id: any) -> None {
185
+ if not confirm("Are you sure you want to delete this item?") {
186
+ return;
187
+ }
188
+
189
+ loading = true;
190
+ try {
191
+ item_id spawn delete_test_data();
192
+ # Remove from local state
193
+ testData = testData.filter(lambda item: any -> bool {
194
+ return item._jac_id != item_id;
195
+ });
196
+ alert("Data deleted successfully!");
197
+ } except Exception as e {
198
+ console.error("Error deleting data:", e);
199
+ alert("Error deleting data: " + e.toString());
200
+ }
201
+ loading = false;
202
+ }
203
+
204
+ # Test string methods via walker
205
+ async def handleStringTest() -> None {
206
+ loading = true;
207
+ try {
208
+ response = root spawn test_string_methods(input_text=stringInput);
209
+ result = response.reports[0];
210
+ stringResult = result;
211
+ } except Exception as e {
212
+ console.error("Error testing strings:", e);
213
+ alert("Error testing strings: " + e.toString());
214
+ }
215
+ loading = false;
216
+ }
217
+
218
+ # Test list operations via walker
219
+ async def handleListTest() -> None {
220
+ loading = true;
221
+ try {
222
+ # Parse number list
223
+ numbers = numberList.split(",").map(lambda x: str -> int {
224
+ return parseInt(x.trim());
225
+ }).filter(lambda x: any -> bool {
226
+ return not isNaN(x);
227
+ });
228
+
229
+ response = root spawn test_list_operations(numbers=numbers);
230
+ result = response.reports[0];
231
+ listResult = result;
232
+ } except Exception as e {
233
+ console.error("Error testing lists:", e);
234
+ alert("Error testing lists: " + e.toString());
235
+ }
236
+ loading = false;
237
+ }
238
+
239
+ # Test complex data processing
240
+ async def handleComplexTest() -> None {
241
+ loading = true;
242
+ try {
243
+ # Generate sample data using JS helper
244
+ sample_items = [
245
+ {"id": generateId(), "name": "apple", "value": 10},
246
+ {"id": generateId(), "name": "banana", "value": 20},
247
+ {"id": generateId(), "name": "cherry", "value": 30}
248
+ ];
249
+
250
+ response = root spawn process_complex_data(items=sample_items);
251
+ result = response.reports[0];
252
+ complexResult = result;
253
+ } except Exception as e {
254
+ console.error("Error processing complex data:", e);
255
+ alert("Error processing complex data: " + e.toString());
256
+ }
257
+ loading = false;
258
+ }
259
+
260
+ # ========================================================================
261
+ # DEMONSTRATION OF STRING METHODS (CLIENT-SIDE)
262
+ # ========================================================================
263
+ demo_text = "JAC Language Features";
264
+ string_demos = {
265
+ "Original": demo_text,
266
+ "Uppercase": demo_text.toUpperCase(),
267
+ "Lowercase": demo_text.toLowerCase(),
268
+ "Length": demo_text.length.toString(),
269
+ "Split by space": demo_text.split(" ").join(", ")
270
+ };
271
+
272
+ # Demo chart data for TypeScript component
273
+ chart_data = [
274
+ {"name": "Walker Tests", "value": 5},
275
+ {"name": "String Methods", "value": 8},
276
+ {"name": "List Operations", "value": 7},
277
+ {"name": "Components", "value": 4}
278
+ ];
279
+
280
+ # Calculate total using JS helper
281
+ total_tests = sumBy(chart_data, "value");
282
+
283
+
284
+ # ========================================================================
285
+ # RENDER
286
+ # ========================================================================
287
+ return <div style={{
288
+ "maxWidth": "1200px",
289
+ "margin": "0 auto",
290
+ "padding": "20px",
291
+ "fontFamily": "system-ui, -apple-system, sans-serif"
292
+ }}>
293
+ # Header
294
+ <div style={{
295
+ "display": "flex",
296
+ "justifyContent": "space-between",
297
+ "alignItems": "center",
298
+ "marginBottom": "30px"
299
+ }}>
300
+ <h1 style={{"color": "#1f2937", "margin": "0"}}>
301
+ JAC Features Test Suite
302
+ </h1>
303
+ <Link to="/">
304
+ <TestButton text="← Back Home" onClick={lambda -> None {}} variant="secondary" />
305
+ </Link>
306
+ </div>
307
+
308
+ # Loading indicator
309
+ {loading and <div style={{
310
+ "position": "fixed",
311
+ "top": "20px",
312
+ "right": "20px",
313
+ "backgroundColor": "#3b82f6",
314
+ "color": "white",
315
+ "padding": "10px 20px",
316
+ "borderRadius": "6px",
317
+ "boxShadow": "0 4px 6px rgba(0,0,0,0.2)",
318
+ "zIndex": "1000"
319
+ }}>
320
+ Processing...
321
+ </div>}
322
+
323
+ # Section 1: Walker CRUD Operations
324
+ <TestCard title="1. Walker CRUD Operations (Spawn from CL)" color="#dbeafe">
325
+ <div style={{"marginBottom": "15px"}}>
326
+ <p style={{"color": "#4b5563", "marginBottom": "10px"}}>
327
+ Test creating, reading, updating, and deleting data using walkers spawned from client code.
328
+ </p>
329
+
330
+ <div style={{"display": "flex", "gap": "10px", "marginBottom": "15px"}}>
331
+ <input
332
+ type="text"
333
+ value={testMessage}
334
+ onChange={lambda e: any -> None { testMessage = e.target.value; }}
335
+ placeholder="Enter test message..."
336
+ style={{
337
+ "flex": "1",
338
+ "padding": "10px",
339
+ "border": "1px solid #d1d5db",
340
+ "borderRadius": "6px",
341
+ "fontSize": "14px"
342
+ }}
343
+ />
344
+ <TestButton
345
+ text="Create"
346
+ onClick={lambda -> None { handleCreate(); }}
347
+ variant="primary"
348
+ />
349
+ </div>
350
+
351
+ <div style={{"marginTop": "20px"}}>
352
+ <strong style={{"color": "#374151"}}>Stored Data ({testData.length} items):</strong>
353
+ {testData.length == 0 and <p style={{"color": "#9ca3af", "fontStyle": "italic"}}>
354
+ No data yet. Create some!
355
+ </p>}
356
+ {testData.map(lambda item: any -> any {
357
+ return <div
358
+ key={item._jac_id}
359
+ style={{
360
+ "backgroundColor": "#f9fafb",
361
+ "padding": "12px",
362
+ "borderRadius": "6px",
363
+ "marginTop": "8px",
364
+ "display": "flex",
365
+ "justifyContent": "space-between",
366
+ "alignItems": "center"
367
+ }}
368
+ >
369
+ <div>
370
+ <div style={{"fontWeight": "600", "color": "#1f2937"}}>
371
+ {item.message}
372
+ </div>
373
+ <div style={{"fontSize": "12px", "color": "#6b7280"}}>
374
+ Count: {item.count} | Created: {item.created_at}
375
+ </div>
376
+ </div>
377
+ <div style={{"display": "flex", "gap": "8px"}}>
378
+ <TestButton
379
+ text="Edit"
380
+ onClick={lambda -> None { handleUpdate(item._jac_id); }}
381
+ variant="secondary"
382
+ />
383
+ <TestButton
384
+ text="Delete"
385
+ onClick={lambda -> None { handleDelete(item._jac_id); }}
386
+ variant="secondary"
387
+ />
388
+ </div>
389
+ </div>;
390
+ })}
391
+ </div>
392
+ </div>
393
+ </TestCard>
394
+
395
+ # # Section 2: String Methods
396
+ <TestCard title="2. String Methods (Client & Walker)" color="#fce7f3">
397
+ <div>
398
+ <p style={{"color": "#4b5563", "marginBottom": "10px"}}>
399
+ Client-side string manipulation and walker-based string processing.
400
+ </p>
401
+
402
+ # Client-side demo
403
+ <div style={{"marginBottom": "20px"}}>
404
+ <strong style={{"color": "#374151"}}>Client-side String Demo:</strong>
405
+ <div style={{
406
+ "backgroundColor": "#fef3c7",
407
+ "padding": "10px",
408
+ "borderRadius": "6px",
409
+ "marginTop": "8px"
410
+ }}>
411
+ {Object.keys(string_demos).map(lambda key: str -> any {
412
+ return <div key={key} style={{"marginBottom": "5px"}}>
413
+ <span style={{"fontWeight": "600"}}>{key}:</span> {string_demos[key]}
414
+ </div>;
415
+ })}
416
+ </div>
417
+ </div>
418
+
419
+ # Walker-based test
420
+ <div>
421
+ <strong style={{"color": "#374151"}}>Walker String Processing:</strong>
422
+ <div style={{"display": "flex", "gap": "10px", "marginTop": "10px"}}>
423
+ <input
424
+ type="text"
425
+ value={stringInput}
426
+ onChange={lambda e: any -> None { stringInput = e.target.value; }}
427
+ style={{
428
+ "flex": "1",
429
+ "padding": "10px",
430
+ "border": "1px solid #d1d5db",
431
+ "borderRadius": "6px",
432
+ "fontSize": "14px"
433
+ }}
434
+ />
435
+ <TestButton
436
+ text="Process with Walker"
437
+ onClick={lambda -> None { handleStringTest(); }}
438
+ variant="primary"
439
+ />
440
+ </div>
441
+ {stringResult and <ResultDisplay data={stringResult} label="Walker Result" />}
442
+ </div>
443
+ </div>
444
+ </TestCard>
445
+
446
+ # # Section 3: List Operations
447
+ <TestCard title="3. List/Array Operations" color="#ddd6fe">
448
+ <div>
449
+ <p style={{"color": "#4b5563", "marginBottom": "10px"}}>
450
+ Process arrays/lists using walker operations.
451
+ </p>
452
+
453
+ <div style={{"display": "flex", "gap": "10px", "marginTop": "10px"}}>
454
+ <input
455
+ type="text"
456
+ value={numberList}
457
+ onChange={lambda e: any -> None { numberList = e.target.value; }}
458
+ placeholder="Enter numbers (comma-separated)"
459
+ style={{
460
+ "flex": "1",
461
+ "padding": "10px",
462
+ "border": "1px solid #d1d5db",
463
+ "borderRadius": "6px",
464
+ "fontSize": "14px"
465
+ }}
466
+ />
467
+ <TestButton
468
+ text="Process List"
469
+ onClick={lambda -> None { handleListTest(); }}
470
+ variant="primary"
471
+ />
472
+ </div>
473
+ {listResult and <ResultDisplay data={listResult} label="List Operations Result" />}
474
+ </div>
475
+ </TestCard>
476
+
477
+ # # Section 4: TypeScript Component Integration
478
+ # <TestCard title="4. TypeScript Component (PieChart.tsx)" color="#ccfbf1">
479
+ # <div>
480
+ # <p style={{"color": "#4b5563", "marginBottom": "10px"}}>
481
+ # Imported TypeScript React component with data from JAC.
482
+ # </p>
483
+ # # <PieChart data={chart_data} title="Feature Test Distribution" />
484
+ # <p style={{"marginTop": "10px", "color": "#6b7280", "fontSize": "14px"}}>
485
+ # Total tests: {total_tests} (calculated using JS helper: sumBy)
486
+ # </p>
487
+ # </div>
488
+ # </TestCard>
489
+
490
+ # # Section 5: Import Demonstrations
491
+ <TestCard title="5. Import Demonstrations" color="#fed7aa">
492
+ <div>
493
+ <p style={{"color": "#4b5563", "marginBottom": "15px"}}>
494
+ This page demonstrates various import types:
495
+ </p>
496
+
497
+ <ul style={{"color": "#374151", "lineHeight": "1.8"}}>
498
+ <li><strong>JAC-Client Utils:</strong> Router components (Link, useNavigate)</li>
499
+ <li><strong>React:</strong> Hooks (useState, useEffect)</li>
500
+ # <li><strong>TypeScript:</strong> PieChart component from .tsx file</li>
501
+ <li><strong>JavaScript:</strong> Helper functions from .js file (generateId, sumBy)</li>
502
+ <li><strong>JAC Files:</strong> formatCurrency from utils/formatters.jac</li>
503
+ </ul>
504
+
505
+ <div style={{
506
+ "backgroundColor": "#f0fdf4",
507
+ "padding": "15px",
508
+ "borderRadius": "6px",
509
+ "marginTop": "15px"
510
+ }}>
511
+ <strong style={{"color": "#065f46"}}>Examples:</strong>
512
+ <div style={{"marginTop": "8px", "fontSize": "14px", "color": "#047857"}}>
513
+ <div>Generated ID: {generateId()}</div>
514
+ <div>Formatted Currency: {formatCurrency(1234.56)}</div>
515
+ <div>Percentage Calc: {calculatePercentage(75, 100)}%</div>
516
+ </div>
517
+ </div>
518
+ </div>
519
+ </TestCard>
520
+
521
+ # # Section 6: Complex Data Processing
522
+ <TestCard title="6. Complex Data Processing" color="#e0e7ff">
523
+ <div>
524
+ <p style={{"color": "#4b5563", "marginBottom": "10px"}}>
525
+ Process complex nested data structures with walkers.
526
+ </p>
527
+
528
+ <TestButton
529
+ text="Process Sample Data"
530
+ onClick={lambda -> None { handleComplexTest(); }}
531
+ variant="primary"
532
+ />
533
+
534
+ {complexResult and <ResultDisplay data={complexResult} label="Complex Processing Result" />}
535
+ </div>
536
+ </TestCard>
537
+
538
+ # Footer
539
+ <div style={{
540
+ "marginTop": "30px",
541
+ "padding": "20px",
542
+ "backgroundColor": "#f9fafb",
543
+ "borderRadius": "8px",
544
+ "textAlign": "center",
545
+ "color": "#6b7280"
546
+ }}>
547
+ <p style={{"margin": "0"}}>
548
+ ✅ All features tested: Props, Exports, CL Files, TypeScript, JavaScript, JAC Imports, String Methods, Walker Spawning
549
+ </p>
550
+ </div>
551
+ </div>;
552
+ }
@@ -0,0 +1,126 @@
1
+ # Features Test Page - Backend Logic
2
+ # This file is intentionally kept empty to demonstrate the separation of concerns
3
+ # where UI logic resides in .cl.jac files and backend walker logic in app.jac
4
+
5
+ # All walker implementations for this feature are in src/app.jac
6
+ # This demonstrates that you can have separate .jac files for different purposes
7
+ # Features Test - Backend Walkers
8
+ # This file demonstrates walker functionality for testing various JAC features
9
+
10
+ import from datetime { datetime, timedelta }
11
+
12
+ # Node definition for storing test data
13
+ node TestData {
14
+ has message: str;
15
+ has count: int = 0;
16
+ has created_at: str = "";
17
+ }
18
+
19
+ # Walker: Create test data
20
+ walker create_test_data {
21
+ has message: str;
22
+
23
+ can create with `root entry {
24
+ new_data = here ++> TestData(
25
+ message=self.message,
26
+ count=1,
27
+ created_at=datetime.now().strftime("%Y-%m-%d %H:%M:%S")
28
+ );
29
+ report new_data;
30
+ }
31
+ }
32
+
33
+ # Walker: Read all test data
34
+ walker read_test_data {
35
+ can read with `root entry {
36
+ visit [-->(`?TestData)];
37
+ }
38
+
39
+ can report_data with exit {
40
+ report here;
41
+ }
42
+ }
43
+
44
+ # Walker: Update test data
45
+ walker update_test_data {
46
+ has new_message: str;
47
+
48
+ can update with TestData entry {
49
+ here.message = self.new_message;
50
+ here.count = here.count + 1;
51
+ report here;
52
+ }
53
+ }
54
+
55
+ # Walker: Delete test data
56
+ walker delete_test_data {
57
+ can delete with TestData entry {
58
+ del here;
59
+ report {"status": "deleted"};
60
+ }
61
+ }
62
+
63
+ # Walker: String manipulation test
64
+ walker test_string_methods {
65
+ has input_text: str;
66
+
67
+ can process with `root entry {
68
+ result = {
69
+ "original": self.input_text,
70
+ "uppercase": self.input_text.upper(),
71
+ "lowercase": self.input_text.lower(),
72
+ "capitalized": self.input_text.capitalize(),
73
+ "reversed": self.input_text[::-1],
74
+ "length": len(self.input_text),
75
+ "words": self.input_text.split(),
76
+ "trimmed": self.input_text.strip(),
77
+ "replaced": self.input_text.replace("test", "demo")
78
+ };
79
+ report result;
80
+ }
81
+ }
82
+
83
+ # Walker: Array/List operations test
84
+ walker test_list_operations {
85
+ has numbers: list;
86
+
87
+ can process with `root entry {
88
+ result = {
89
+ "original": self.numbers,
90
+ "sorted": sorted(self.numbers),
91
+ "reversed": list(reversed(self.numbers)),
92
+ "sum": sum(self.numbers),
93
+ "max": max(self.numbers) if len(self.numbers) > 0 else 0,
94
+ "min": min(self.numbers) if len(self.numbers) > 0 else 0,
95
+ "length": len(self.numbers),
96
+ "doubled": [x * 2 for x in self.numbers]
97
+ };
98
+ report result;
99
+ }
100
+ }
101
+
102
+ # Walker: Complex data processing
103
+ walker process_complex_data {
104
+ has items: list;
105
+
106
+ can process with `root entry {
107
+ processed = [];
108
+ for item in self.items {
109
+ processed.append({
110
+ "id": item.get("id", 0),
111
+ "name": item.get("name", "").upper(),
112
+ "value": item.get("value", 0) * 2,
113
+ "processed_at": datetime.now().strftime("%H:%M:%S")
114
+ });
115
+ }
116
+
117
+ result = {
118
+ "original_count": len(self.items),
119
+ "processed_count": len(processed),
120
+ "items": processed,
121
+ "total_value": sum([p["value"] for p in processed])
122
+ };
123
+
124
+ report result;
125
+ }
126
+ }