jac-client 0.2.10__py3-none-any.whl → 0.2.12__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 (85) hide show
  1. jac_client/examples/all-in-one/button.jac +4 -3
  2. jac_client/examples/all-in-one/components/CategoryFilter.jac +36 -24
  3. jac_client/examples/all-in-one/components/Header.jac +12 -8
  4. jac_client/examples/all-in-one/components/ProfitOverview.jac +49 -35
  5. jac_client/examples/all-in-one/components/Summary.jac +59 -36
  6. jac_client/examples/all-in-one/components/TransactionForm.jac +142 -112
  7. jac_client/examples/all-in-one/components/TransactionItem.jac +37 -30
  8. jac_client/examples/all-in-one/components/TransactionList.jac +33 -26
  9. jac_client/examples/all-in-one/components/button.jac +4 -3
  10. jac_client/examples/all-in-one/components/navigation.jac +111 -117
  11. jac_client/examples/all-in-one/constants/categories.jac +23 -24
  12. jac_client/examples/all-in-one/constants/clients.jac +7 -8
  13. jac_client/examples/all-in-one/context/BudgetContext.jac +9 -6
  14. jac_client/examples/all-in-one/hooks/useBudget.jac +18 -12
  15. jac_client/examples/all-in-one/hooks/useLocalStorage.jac +14 -13
  16. jac_client/examples/all-in-one/main.jac +340 -371
  17. jac_client/examples/all-in-one/pages/BudgetPlanner.jac +19 -12
  18. jac_client/examples/all-in-one/pages/FeaturesTest.jac +31 -15
  19. jac_client/examples/all-in-one/pages/LandingPage.jac +113 -90
  20. jac_client/examples/all-in-one/pages/budget_planner_ui.cl.jac +34 -39
  21. jac_client/examples/all-in-one/pages/features_test_ui.cl.jac +464 -352
  22. jac_client/examples/all-in-one/pages/loginPage.jac +114 -119
  23. jac_client/examples/all-in-one/pages/nestedDemo.jac +43 -50
  24. jac_client/examples/all-in-one/pages/notFound.jac +14 -15
  25. jac_client/examples/all-in-one/pages/signupPage.jac +113 -119
  26. jac_client/examples/all-in-one/utils/formatters.jac +5 -8
  27. jac_client/examples/asset-serving/css-with-image/main.jac +77 -73
  28. jac_client/examples/asset-serving/image-asset/main.jac +47 -46
  29. jac_client/examples/asset-serving/import-alias/main.jac +93 -95
  30. jac_client/examples/basic/main.jac +17 -15
  31. jac_client/examples/basic-auth/main.jac +246 -254
  32. jac_client/examples/basic-auth-with-router/main.jac +272 -285
  33. jac_client/examples/basic-full-stack/main.jac +245 -242
  34. jac_client/examples/css-styling/js-styling/main.jac +41 -62
  35. jac_client/examples/css-styling/material-ui/main.jac +90 -90
  36. jac_client/examples/css-styling/pure-css/main.jac +35 -44
  37. jac_client/examples/css-styling/sass-example/main.jac +35 -44
  38. jac_client/examples/css-styling/styled-components/main.jac +38 -47
  39. jac_client/examples/css-styling/tailwind-example/main.jac +54 -43
  40. jac_client/examples/full-stack-with-auth/main.jac +407 -433
  41. jac_client/examples/little-x/main.jac +306 -344
  42. jac_client/examples/little-x/src/submit-button.jac +15 -14
  43. jac_client/examples/nested-folders/nested-advance/main.jac +18 -27
  44. jac_client/examples/nested-folders/nested-advance/src/ButtonRoot.jac +4 -6
  45. jac_client/examples/nested-folders/nested-advance/src/level1/ButtonSecondL.jac +9 -13
  46. jac_client/examples/nested-folders/nested-advance/src/level1/Card.jac +29 -32
  47. jac_client/examples/nested-folders/nested-advance/src/level1/level2/ButtonThirdL.jac +12 -18
  48. jac_client/examples/nested-folders/nested-basic/main.jac +7 -5
  49. jac_client/examples/nested-folders/nested-basic/src/button.jac +4 -3
  50. jac_client/examples/nested-folders/nested-basic/src/components/button.jac +4 -3
  51. jac_client/examples/ts-support/main.jac +26 -26
  52. jac_client/examples/with-router/main.jac +186 -223
  53. jac_client/plugin/client_runtime.cl.jac +5 -3
  54. jac_client/plugin/impl/client_runtime.impl.jac +1 -1
  55. jac_client/plugin/plugin_config.jac +53 -99
  56. jac_client/plugin/src/__init__.jac +0 -2
  57. jac_client/plugin/src/compiler.jac +0 -1
  58. jac_client/plugin/src/impl/compiler.impl.jac +49 -17
  59. jac_client/plugin/src/impl/jac_to_js.impl.jac +5 -1
  60. jac_client/plugin/src/impl/package_installer.impl.jac +20 -20
  61. jac_client/plugin/src/impl/vite_bundler.impl.jac +146 -84
  62. jac_client/plugin/src/targets/impl/desktop_target.impl.jac +54 -41
  63. jac_client/plugin/utils/__init__.jac +3 -0
  64. jac_client/plugin/utils/bun_installer.jac +16 -0
  65. jac_client/plugin/utils/client_deps.jac +14 -0
  66. jac_client/plugin/utils/impl/bun_installer.impl.jac +99 -0
  67. jac_client/plugin/utils/impl/client_deps.impl.jac +73 -0
  68. jac_client/templates/client.jacpack +0 -4
  69. jac_client/templates/fullstack.jacpack +1 -5
  70. jac_client/tests/conftest.py +56 -41
  71. jac_client/tests/fixtures/spawn_test/app.jac +49 -52
  72. jac_client/tests/fixtures/with-ts/app.jac +27 -27
  73. jac_client/tests/test_cli.py +71 -6
  74. jac_client/tests/test_helpers.py +11 -18
  75. jac_client/tests/test_it.py +1 -1
  76. {jac_client-0.2.10.dist-info → jac_client-0.2.12.dist-info}/METADATA +5 -5
  77. jac_client-0.2.12.dist-info/RECORD +115 -0
  78. {jac_client-0.2.10.dist-info → jac_client-0.2.12.dist-info}/WHEEL +1 -1
  79. jac_client/plugin/src/babel_processor.jac +0 -18
  80. jac_client/plugin/src/impl/babel_processor.impl.jac +0 -89
  81. jac_client/plugin/utils/impl/node_installer.impl.jac +0 -249
  82. jac_client/plugin/utils/node_installer.jac +0 -41
  83. jac_client-0.2.10.dist-info/RECORD +0 -115
  84. {jac_client-0.2.10.dist-info → jac_client-0.2.12.dist-info}/entry_points.txt +0 -0
  85. {jac_client-0.2.10.dist-info → jac_client-0.2.12.dist-info}/top_level.txt +0 -0
@@ -1,15 +1,21 @@
1
1
  # # Features Test Page - Client-side UI
2
2
  # # Demonstrates: props, exports, cl files, TypeScript imports, string methods,
3
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 }
4
+ import from "@jac/runtime" {
5
+ Link,
6
+ useNavigate
7
+ }
8
+ import from react { useState }
7
9
 
8
10
  # # Import TypeScript component
9
11
  # import from ..components.PieChart { PieChart }
10
12
 
11
13
  # # Import JavaScript helpers
12
- import from ..utils.helpers { generateId, calculatePercentage, sumBy }
14
+ import from ..utils.helpers {
15
+ generateId,
16
+ calculatePercentage,
17
+ sumBy
18
+ }
13
19
 
14
20
  # # Import from other JAC files
15
21
  import from ..utils.formatters { formatCurrency }
@@ -29,12 +35,15 @@ sv import from .FeaturesTest {
29
35
  # REUSABLE COMPONENTS WITH PROPS
30
36
  # ============================================================================
31
37
 
32
- # Button component demonstrating props - NEW PATTERN: Direct parameters
33
- def:pub TestButton(text: str, onClick: any, variant: str) -> any {
34
- bg_color = "#3b82f6" if variant == "primary" else "#6b7280";
35
- hover_color = "#2563eb" if variant == "primary" else "#4b5563";
38
+ # Button component demonstrating props - NEW PATTERN: Direct parameters
39
+ def:pub TestButton(
40
+ text: str, onClick: any, variant: str
41
+ ) -> any {
42
+ bg_color = "#3b82f6" if variant == "primary" else "#6b7280";
43
+ hover_color = "#2563eb" if variant == "primary" else "#4b5563";
36
44
 
37
- return <button
45
+ return
46
+ <button
38
47
  onClick={onClick}
39
48
  style={{
40
49
  "padding": "10px 20px",
@@ -47,302 +56,334 @@ sv import from .FeaturesTest {
47
56
  "fontWeight": "600",
48
57
  "transition": "all 0.2s"
49
58
  }}
50
- onMouseOver={lambda e: any -> None {
51
- e.target.style.backgroundColor = hover_color;
52
- }}
53
- onMouseOut={lambda e: any -> None {
54
- e.target.style.backgroundColor = bg_color;
55
- }}
59
+ onMouseOver={lambda e: any -> None { e.target.style.backgroundColor = hover_color;}}
60
+ onMouseOut={lambda e: any -> None { e.target.style.backgroundColor = bg_color;}}
56
61
  >
57
62
  {text}
58
63
  </button>;
59
- }
64
+ }
60
65
 
61
- # # Card component with props - NEW PATTERN: Direct parameters
62
- def:pub TestCard(title: str, children: any, color: str) -> any {
63
- return <div style={{
64
- "backgroundColor": "white",
65
- "border": "1px solid #e5e7eb",
66
- "borderRadius": "8px",
67
- "padding": "20px",
68
- "marginBottom": "20px",
69
- "boxShadow": "0 1px 3px rgba(0,0,0,0.1)"
70
- }}>
71
- <div style={{
72
- "backgroundColor": color,
73
- "padding": "10px",
74
- "borderRadius": "6px",
75
- "marginBottom": "15px"
76
- }}>
77
- <h3 style={{
78
- "margin": "0",
79
- "fontSize": "18px",
80
- "fontWeight": "600",
81
- "color": "#1f2937"
82
- }}>{title}</h3>
66
+ # # Card component with props - NEW PATTERN: Direct parameters
67
+ def:pub TestCard(
68
+ title: str, children: any, color: str
69
+ ) -> any {
70
+ return
71
+ <div
72
+ style={{
73
+ "backgroundColor": "white",
74
+ "border": "1px solid #e5e7eb",
75
+ "borderRadius": "8px",
76
+ "padding": "20px",
77
+ "marginBottom": "20px",
78
+ "boxShadow": "0 1px 3px rgba(0,0,0,0.1)"
79
+ }}
80
+ >
81
+ <div
82
+ style={{
83
+ "backgroundColor": color,
84
+ "padding": "10px",
85
+ "borderRadius": "6px",
86
+ "marginBottom": "15px"
87
+ }}
88
+ >
89
+ <h3
90
+ style={{
91
+ "margin": "0",
92
+ "fontSize": "18px",
93
+ "fontWeight": "600",
94
+ "color": "#1f2937"
95
+ }}
96
+ >
97
+ {title}
98
+ </h3>
99
+ </div>
100
+ <div>
101
+ {children}
83
102
  </div>
84
- <div>{children}</div>
85
103
  </div>;
86
- }
104
+ }
87
105
 
88
- # Result display component - NEW PATTERN: Direct parameters
89
- def:pub ResultDisplay(data: any, label: str) -> any {
90
- if not data {
91
- return <div style={{"color": "#9ca3af", "fontStyle": "italic"}}>
106
+ # Result display component - NEW PATTERN: Direct parameters
107
+ def:pub ResultDisplay(
108
+ data: any, label: str
109
+ ) -> any {
110
+ if not data {
111
+ return
112
+ <div style={{"color": "#9ca3af", "fontStyle": "italic"}}>
92
113
  No data to display
93
114
  </div>;
94
- }
115
+ }
95
116
 
96
- return <div style={{
97
- "backgroundColor": "#f9fafb",
98
- "padding": "15px",
99
- "borderRadius": "6px",
100
- "border": "1px solid #e5e7eb"
101
- }}>
102
- <strong style={{"color": "#374151"}}>{label}:</strong>
103
- <pre style={{
104
- "marginTop": "10px",
105
- "padding": "10px",
106
- "backgroundColor": "#1f2937",
107
- "color": "#10b981",
108
- "borderRadius": "4px",
109
- "overflow": "auto",
110
- "fontSize": "12px",
111
- "fontFamily": "monospace"
112
- }}>
117
+ return
118
+ <div
119
+ style={{
120
+ "backgroundColor": "#f9fafb",
121
+ "padding": "15px",
122
+ "borderRadius": "6px",
123
+ "border": "1px solid #e5e7eb"
124
+ }}
125
+ >
126
+ <strong style={{"color": "#374151"}}>
127
+ {label}:
128
+ </strong>
129
+ <pre
130
+ style={{
131
+ "marginTop": "10px",
132
+ "padding": "10px",
133
+ "backgroundColor": "#1f2937",
134
+ "color": "#10b981",
135
+ "borderRadius": "4px",
136
+ "overflow": "auto",
137
+ "fontSize": "12px",
138
+ "fontFamily": "monospace"
139
+ }}
140
+ >
113
141
  {JSON.stringify(data, None, 2)}
114
142
  </pre>
115
143
  </div>;
116
- }
117
-
118
- # ============================================================================
119
- # MAIN PAGE COMPONENT
120
- # ============================================================================
121
-
122
- def:pub FeaturesTest() -> any {
123
- navigate = useNavigate();
124
-
125
- # State management
126
- has testMessage: str = "";
127
- has testData: list = [];
128
- has stringInput: str = "Hello JAC World!";
129
- has stringResult: any = None;
130
- has numberList: str = "1,2,3,4,5";
131
- has listResult: any = None;
132
- has complexResult: any = None;
133
- has loading: bool = false;
134
-
135
- # Load test data on mount
136
- useEffect(lambda -> None {
137
- async def loadData() -> None {
138
- try {
139
- result = root spawn read_test_data();
140
- testData = result.reports if result.reports[0] else [];
141
- } except Exception as e {
142
- console.log("Error loading data:", e);
143
- }
144
- }
145
- loadData();
146
- }, []);
147
-
148
- # ========================================================================
149
- # EVENT HANDLERS - Demonstrating Walker Spawning from CL
150
- # ========================================================================
151
-
152
- # Create test data
153
- async def handleCreate() -> None {
154
- if not testMessage.trim() {
155
- alert("Please enter a message");
156
- return;
157
- }
144
+ }
158
145
 
159
- loading = true;
160
- try {
161
- response = root spawn create_test_data(message=testMessage.trim());
162
- new_item = response.reports[0][0];
163
- testData = testData.concat([new_item]);
164
- testMessage = "";
165
- alert("Data created successfully!");
166
- } except Exception as e {
167
- console.error("Error creating data:", e);
168
- alert("Error creating data: " + e.toString());
169
- }
170
- loading = false;
146
+ # ============================================================================
147
+ # MAIN PAGE COMPONENT
148
+ # ============================================================================
149
+ def:pub FeaturesTest -> any {
150
+ navigate = useNavigate();
151
+
152
+ # State management
153
+ has testMessage: str = "",
154
+ testData: list = [],
155
+ stringInput: str = "Hello JAC World!",
156
+ stringResult: any = None,
157
+ numberList: str = "1,2,3,4,5",
158
+ listResult: any = None,
159
+ complexResult: any = None,
160
+ loading: bool = false;
161
+
162
+ # Load test data on mount
163
+ async can with entry {
164
+ try {
165
+ result = root spawn read_test_data();
166
+ testData = result.reports if result.reports[0] else [];
167
+ } except Exception as e {
168
+ console.log("Error loading data:", e);
171
169
  }
170
+ }
172
171
 
173
- # Update test data
174
- async def handleUpdate(item_id: any) -> None {
175
- new_msg = prompt("Enter new message:");
176
- if not new_msg {
177
- return;
178
- }
172
+ # ========================================================================
173
+ # EVENT HANDLERS - Demonstrating Walker Spawning from CL
174
+ # ========================================================================
179
175
 
180
- loading = true;
181
- try {
182
- item_id spawn update_test_data(new_message=new_msg);
183
- # Reload data
184
- result = root spawn read_test_data();
185
- testData = result.reports if result.reports[0] else [];
186
- alert("Data updated successfully!");
187
- } except Exception as e {
188
- console.error("Error updating data:", e);
189
- alert("Error updating data: " + e.toString());
190
- }
191
- loading = false;
176
+ # Create test data
177
+ async def handleCreate -> None {
178
+ if not testMessage.trim() {
179
+ alert("Please enter a message");
180
+ return;
192
181
  }
193
182
 
194
- # Delete test data
195
- async def handleDelete(item_id: any) -> None {
196
- if not confirm("Are you sure you want to delete this item?") {
197
- return;
198
- }
199
-
200
- loading = true;
201
- try {
202
- item_id spawn delete_test_data();
203
- # Remove from local state
204
- testData = testData.filter(lambda item: any -> bool {
205
- return item._jac_id != item_id;
206
- });
207
- alert("Data deleted successfully!");
208
- } except Exception as e {
209
- console.error("Error deleting data:", e);
210
- alert("Error deleting data: " + e.toString());
211
- }
212
- loading = false;
183
+ loading = true;
184
+ try {
185
+ response = root spawn create_test_data(message=testMessage.trim());
186
+ new_item = response.reports[0][0];
187
+ testData = testData.concat([new_item]);
188
+ testMessage = "";
189
+ alert("Data created successfully!");
190
+ } except Exception as e {
191
+ console.error("Error creating data:", e);
192
+ alert("Error creating data: " + e.toString());
213
193
  }
194
+ loading = false;
195
+ }
214
196
 
215
- # Test string methods via walker
216
- async def handleStringTest() -> None {
217
- loading = true;
218
- try {
219
- response = root spawn test_string_methods(input_text=stringInput);
220
- result = response.reports[0];
221
- stringResult = result;
222
- } except Exception as e {
223
- console.error("Error testing strings:", e);
224
- alert("Error testing strings: " + e.toString());
225
- }
226
- loading = false;
197
+ # Update test data
198
+ async def handleUpdate(item_id: any) -> None {
199
+ new_msg = prompt("Enter new message:");
200
+ if not new_msg {
201
+ return;
227
202
  }
228
203
 
229
- # Test list operations via walker
230
- async def handleListTest() -> None {
231
- loading = true;
232
- try {
233
- # Parse number list
234
- numbers = numberList.split(",").map(lambda x: str -> int {
235
- return parseInt(x.trim());
236
- }).filter(lambda x: any -> bool {
237
- return not isNaN(x);
238
- });
239
-
240
- response = root spawn test_list_operations(numbers=numbers);
241
- result = response.reports[0];
242
- listResult = result;
243
- } except Exception as e {
244
- console.error("Error testing lists:", e);
245
- alert("Error testing lists: " + e.toString());
246
- }
247
- loading = false;
204
+ loading = true;
205
+ try {
206
+ item_id spawn update_test_data(new_message=new_msg);
207
+ # Reload data
208
+ result = root spawn read_test_data();
209
+ testData = result.reports if result.reports[0] else [];
210
+ alert("Data updated successfully!");
211
+ } except Exception as e {
212
+ console.error("Error updating data:", e);
213
+ alert("Error updating data: " + e.toString());
248
214
  }
215
+ loading = false;
216
+ }
249
217
 
250
- # Test complex data processing
251
- async def handleComplexTest() -> None {
252
- loading = true;
253
- try {
254
- # Generate sample data using JS helper
255
- sample_items = [
256
- {"id": generateId(), "name": "apple", "value": 10},
257
- {"id": generateId(), "name": "banana", "value": 20},
258
- {"id": generateId(), "name": "cherry", "value": 30}
259
- ];
260
-
261
- response = root spawn process_complex_data(items=sample_items);
262
- result = response.reports[0];
263
- complexResult = result;
264
- } except Exception as e {
265
- console.error("Error processing complex data:", e);
266
- alert("Error processing complex data: " + e.toString());
267
- }
268
- loading = false;
218
+ # Delete test data
219
+ async def handleDelete(item_id: any) -> None {
220
+ if not confirm("Are you sure you want to delete this item?") {
221
+ return;
269
222
  }
270
223
 
271
- # ========================================================================
272
- # DEMONSTRATION OF STRING METHODS (CLIENT-SIDE)
273
- # ========================================================================
274
- demo_text = "JAC Language Features";
275
- string_demos = {
276
- "Original": demo_text,
277
- "Uppercase": demo_text.toUpperCase(),
278
- "Lowercase": demo_text.toLowerCase(),
279
- "Length": demo_text.length.toString(),
280
- "Split by space": demo_text.split(" ").join(", ")
281
- };
224
+ loading = true;
225
+ try {
226
+ item_id spawn delete_test_data();
227
+ # Remove from local state
228
+ testData = testData.filter(
229
+ lambda item: any -> bool { return item._jac_id != item_id; }
230
+ );
231
+ alert("Data deleted successfully!");
232
+ } except Exception as e {
233
+ console.error("Error deleting data:", e);
234
+ alert("Error deleting data: " + e.toString());
235
+ }
236
+ loading = false;
237
+ }
282
238
 
283
- # Demo chart data for TypeScript component
284
- chart_data = [
285
- {"name": "Walker Tests", "value": 5},
286
- {"name": "String Methods", "value": 8},
287
- {"name": "List Operations", "value": 7},
288
- {"name": "Components", "value": 4}
289
- ];
239
+ # Test string methods via walker
240
+ async def handleStringTest -> None {
241
+ loading = true;
242
+ try {
243
+ response = root spawn test_string_methods(input_text=stringInput);
244
+ result = response.reports[0];
245
+ stringResult = result;
246
+ } except Exception as e {
247
+ console.error("Error testing strings:", e);
248
+ alert("Error testing strings: " + e.toString());
249
+ }
250
+ loading = false;
251
+ }
290
252
 
291
- # Calculate total using JS helper
292
- total_tests = sumBy(chart_data, "value");
253
+ # Test list operations via walker
254
+ async def handleListTest -> None {
255
+ loading = true;
256
+ try {
257
+ # Parse number list
258
+ numbers = numberList.split(",").map(
259
+ lambda x: str -> int { return parseInt(x.trim()); }
260
+ ).filter(
261
+ lambda x: any -> bool { return not isNaN(x); }
262
+ );
263
+
264
+ response = root spawn test_list_operations(numbers=numbers);
265
+ result = response.reports[0];
266
+ listResult = result;
267
+ } except Exception as e {
268
+ console.error("Error testing lists:", e);
269
+ alert("Error testing lists: " + e.toString());
270
+ }
271
+ loading = false;
272
+ }
293
273
 
274
+ # Test complex data processing
275
+ async def handleComplexTest -> None {
276
+ loading = true;
277
+ try {
278
+ # Generate sample data using JS helper
279
+ sample_items = [
280
+ {"id": generateId(), "name": "apple", "value": 10},
281
+ {"id": generateId(), "name": "banana", "value": 20},
282
+ {"id": generateId(), "name": "cherry", "value": 30}
283
+ ];
284
+
285
+ response = root spawn process_complex_data(items=sample_items);
286
+ result = response.reports[0];
287
+ complexResult = result;
288
+ } except Exception as e {
289
+ console.error("Error processing complex data:", e);
290
+ alert("Error processing complex data: " + e.toString());
291
+ }
292
+ loading = false;
293
+ }
294
294
 
295
- # ========================================================================
296
- # RENDER
297
- # ========================================================================
298
- return <div style={{
299
- "maxWidth": "1200px",
300
- "margin": "0 auto",
301
- "padding": "20px",
302
- "fontFamily": "system-ui, -apple-system, sans-serif"
303
- }}>
295
+ # ========================================================================
296
+ # DEMONSTRATION OF STRING METHODS (CLIENT-SIDE)
297
+ # ========================================================================
298
+ demo_text = "JAC Language Features";
299
+ string_demos = {
300
+ "Original": demo_text,
301
+ "Uppercase": demo_text.toUpperCase(),
302
+ "Lowercase": demo_text.toLowerCase(),
303
+ "Length": demo_text.length.toString(),
304
+ "Split by space": demo_text.split(" ").join(", ")
305
+ };
306
+
307
+ # Demo chart data for TypeScript component
308
+ chart_data = [
309
+ {"name": "Walker Tests", "value": 5},
310
+ {"name": "String Methods", "value": 8},
311
+ {"name": "List Operations", "value": 7},
312
+ {"name": "Components", "value": 4}
313
+ ];
314
+
315
+ # Calculate total using JS helper
316
+ total_tests = sumBy(chart_data, "value");
317
+
318
+ # ========================================================================
319
+ # RENDER
320
+ # ========================================================================
321
+ return
322
+ <div
323
+ style={{
324
+ "maxWidth": "1200px",
325
+ "margin": "0 auto",
326
+ "padding": "20px",
327
+ "fontFamily": "system-ui, -apple-system, sans-serif"
328
+ }}
329
+ >
304
330
  # Header
305
- <div style={{
306
- "display": "flex",
307
- "justifyContent": "space-between",
308
- "alignItems": "center",
309
- "marginBottom": "30px"
310
- }}>
331
+ <div
332
+ style={{
333
+ "display": "flex",
334
+ "justifyContent": "space-between",
335
+ "alignItems": "center",
336
+ "marginBottom": "30px"
337
+ }}
338
+ >
311
339
  <h1 style={{"color": "#1f2937", "margin": "0"}}>
312
340
  JAC Features Test Suite
313
341
  </h1>
314
342
  <Link to="/">
315
- <TestButton text="← Back Home" onClick={lambda -> None {}} variant="secondary" />
343
+ <TestButton
344
+ text="← Back Home"
345
+ onClick={lambda -> None { }}
346
+ variant="secondary"
347
+ />
316
348
  </Link>
317
349
  </div>
318
-
319
350
  # Loading indicator
320
- {loading and <div style={{
321
- "position": "fixed",
322
- "top": "20px",
323
- "right": "20px",
324
- "backgroundColor": "#3b82f6",
325
- "color": "white",
326
- "padding": "10px 20px",
327
- "borderRadius": "6px",
328
- "boxShadow": "0 4px 6px rgba(0,0,0,0.2)",
329
- "zIndex": "1000"
330
- }}>
351
+ {loading
352
+ and <div
353
+ style={{
354
+ "position": "fixed",
355
+ "top": "20px",
356
+ "right": "20px",
357
+ "backgroundColor": "#3b82f6",
358
+ "color": "white",
359
+ "padding": "10px 20px",
360
+ "borderRadius": "6px",
361
+ "boxShadow": "0 4px 6px rgba(0,0,0,0.2)",
362
+ "zIndex": "1000"
363
+ }}
364
+ >
331
365
  Processing...
332
366
  </div>}
333
-
334
367
  # Section 1: Walker CRUD Operations
335
- <TestCard title="1. Walker CRUD Operations (Spawn from CL)" color="#dbeafe">
368
+ <TestCard
369
+ title="1. Walker CRUD Operations (Spawn from CL)"
370
+ color="#dbeafe"
371
+ >
336
372
  <div style={{"marginBottom": "15px"}}>
337
373
  <p style={{"color": "#4b5563", "marginBottom": "10px"}}>
338
374
  Test creating, reading, updating, and deleting data using walkers spawned from client code.
339
375
  </p>
340
-
341
- <div style={{"display": "flex", "gap": "10px", "marginBottom": "15px"}}>
376
+ <div
377
+ style={{
378
+ "display": "flex",
379
+ "gap": "10px",
380
+ "marginBottom": "15px"
381
+ }}
382
+ >
342
383
  <input
343
384
  type="text"
344
385
  value={testMessage}
345
- onChange={lambda e: any -> None { testMessage = e.target.value; }}
386
+ onChange={lambda e: any -> None { testMessage = e.target.value;}}
346
387
  placeholder="Enter test message..."
347
388
  style={{
348
389
  "flex": "1",
@@ -354,87 +395,117 @@ sv import from .FeaturesTest {
354
395
  />
355
396
  <TestButton
356
397
  text="Create"
357
- onClick={lambda -> None { handleCreate(); }}
398
+ onClick={lambda -> None { handleCreate();}}
358
399
  variant="primary"
359
400
  />
360
401
  </div>
361
-
362
402
  <div style={{"marginTop": "20px"}}>
363
- <strong style={{"color": "#374151"}}>Stored Data ({testData.length} items):</strong>
364
- {testData.length == 0 and <p style={{"color": "#9ca3af", "fontStyle": "italic"}}>
403
+ <strong style={{"color": "#374151"}}>
404
+ Stored Data ({testData.length}items):
405
+ </strong>
406
+ {testData.length == 0
407
+ and <p style={{"color": "#9ca3af", "fontStyle": "italic"}}>
365
408
  No data yet. Create some!
366
409
  </p>}
367
- {testData.map(lambda item: any -> any {
368
- return <div
369
- key={item._jac_id}
370
- style={{
371
- "backgroundColor": "#f9fafb",
372
- "padding": "12px",
373
- "borderRadius": "6px",
374
- "marginTop": "8px",
375
- "display": "flex",
376
- "justifyContent": "space-between",
377
- "alignItems": "center"
378
- }}
379
- >
380
- <div>
381
- <div style={{"fontWeight": "600", "color": "#1f2937"}}>
382
- {item.message}
410
+ {testData.map(
411
+ lambda item: any -> any { return
412
+ <div
413
+ key={item._jac_id}
414
+ style={{
415
+ "backgroundColor": "#f9fafb",
416
+ "padding": "12px",
417
+ "borderRadius": "6px",
418
+ "marginTop": "8px",
419
+ "display": "flex",
420
+ "justifyContent": "space-between",
421
+ "alignItems": "center"
422
+ }}
423
+ >
424
+ <div>
425
+ <div
426
+ style={{
427
+ "fontWeight": "600",
428
+ "color": "#1f2937"
429
+ }}
430
+ >
431
+ {item.message}
432
+ </div>
433
+ <div
434
+ style={{
435
+ "fontSize": "12px",
436
+ "color": "#6b7280"
437
+ }}
438
+ >
439
+ Count: {item.count}| Created: {item.created_at}
440
+ </div>
383
441
  </div>
384
- <div style={{"fontSize": "12px", "color": "#6b7280"}}>
385
- Count: {item.count} | Created: {item.created_at}
442
+ <div style={{"display": "flex", "gap": "8px"}}>
443
+ <TestButton
444
+ text="Edit"
445
+ onClick={lambda -> None { handleUpdate(
446
+ item._jac_id
447
+ );}}
448
+ variant="secondary"
449
+ />
450
+ <TestButton
451
+ text="Delete"
452
+ onClick={lambda -> None { handleDelete(
453
+ item._jac_id
454
+ );}}
455
+ variant="secondary"
456
+ />
386
457
  </div>
387
- </div>
388
- <div style={{"display": "flex", "gap": "8px"}}>
389
- <TestButton
390
- text="Edit"
391
- onClick={lambda -> None { handleUpdate(item._jac_id); }}
392
- variant="secondary"
393
- />
394
- <TestButton
395
- text="Delete"
396
- onClick={lambda -> None { handleDelete(item._jac_id); }}
397
- variant="secondary"
398
- />
399
- </div>
400
- </div>;
401
- })}
458
+ </div>; }
459
+ )}
402
460
  </div>
403
461
  </div>
404
462
  </TestCard>
405
-
406
463
  # # Section 2: String Methods
407
464
  <TestCard title="2. String Methods (Client & Walker)" color="#fce7f3">
408
465
  <div>
409
466
  <p style={{"color": "#4b5563", "marginBottom": "10px"}}>
410
467
  Client-side string manipulation and walker-based string processing.
411
468
  </p>
412
-
413
469
  # Client-side demo
414
470
  <div style={{"marginBottom": "20px"}}>
415
- <strong style={{"color": "#374151"}}>Client-side String Demo:</strong>
416
- <div style={{
417
- "backgroundColor": "#fef3c7",
418
- "padding": "10px",
419
- "borderRadius": "6px",
420
- "marginTop": "8px"
421
- }}>
422
- {Object.keys(string_demos).map(lambda key: str -> any {
423
- return <div key={key} style={{"marginBottom": "5px"}}>
424
- <span style={{"fontWeight": "600"}}>{key}:</span> {string_demos[key]}
425
- </div>;
426
- })}
471
+ <strong style={{"color": "#374151"}}>
472
+ Client-side String Demo:
473
+ </strong>
474
+ <div
475
+ style={{
476
+ "backgroundColor": "#fef3c7",
477
+ "padding": "10px",
478
+ "borderRadius": "6px",
479
+ "marginTop": "8px"
480
+ }}
481
+ >
482
+ {Object.keys(string_demos).map(
483
+ lambda key: str -> any { return
484
+ <div key={key} style={{"marginBottom": "5px"}}>
485
+ <span style={{"fontWeight": "600"}}>
486
+ {key}:
487
+ </span>
488
+ {string_demos[key]}
489
+ </div>; }
490
+ )}
427
491
  </div>
428
492
  </div>
429
-
430
493
  # Walker-based test
431
494
  <div>
432
- <strong style={{"color": "#374151"}}>Walker String Processing:</strong>
433
- <div style={{"display": "flex", "gap": "10px", "marginTop": "10px"}}>
495
+ <strong style={{"color": "#374151"}}>
496
+ Walker String Processing:
497
+ </strong>
498
+ <div
499
+ style={{
500
+ "display": "flex",
501
+ "gap": "10px",
502
+ "marginTop": "10px"
503
+ }}
504
+ >
434
505
  <input
435
506
  type="text"
436
507
  value={stringInput}
437
- onChange={lambda e: any -> None { stringInput = e.target.value; }}
508
+ onChange={lambda e: any -> None { stringInput = e.target.value;}}
438
509
  style={{
439
510
  "flex": "1",
440
511
  "padding": "10px",
@@ -445,27 +516,28 @@ sv import from .FeaturesTest {
445
516
  />
446
517
  <TestButton
447
518
  text="Process with Walker"
448
- onClick={lambda -> None { handleStringTest(); }}
519
+ onClick={lambda -> None { handleStringTest();}}
449
520
  variant="primary"
450
521
  />
451
522
  </div>
452
- {stringResult and <ResultDisplay data={stringResult} label="Walker Result" />}
523
+ {stringResult
524
+ and <ResultDisplay data={stringResult} label="Walker Result" />}
453
525
  </div>
454
526
  </div>
455
527
  </TestCard>
456
-
457
528
  # # Section 3: List Operations
458
529
  <TestCard title="3. List/Array Operations" color="#ddd6fe">
459
530
  <div>
460
531
  <p style={{"color": "#4b5563", "marginBottom": "10px"}}>
461
532
  Process arrays/lists using walker operations.
462
533
  </p>
463
-
464
- <div style={{"display": "flex", "gap": "10px", "marginTop": "10px"}}>
534
+ <div
535
+ style={{"display": "flex", "gap": "10px", "marginTop": "10px"}}
536
+ >
465
537
  <input
466
538
  type="text"
467
539
  value={numberList}
468
- onChange={lambda e: any -> None { numberList = e.target.value; }}
540
+ onChange={lambda e: any -> None { numberList = e.target.value;}}
469
541
  placeholder="Enter numbers (comma-separated)"
470
542
  style={{
471
543
  "flex": "1",
@@ -477,14 +549,17 @@ sv import from .FeaturesTest {
477
549
  />
478
550
  <TestButton
479
551
  text="Process List"
480
- onClick={lambda -> None { handleListTest(); }}
552
+ onClick={lambda -> None { handleListTest();}}
481
553
  variant="primary"
482
554
  />
483
555
  </div>
484
- {listResult and <ResultDisplay data={listResult} label="List Operations Result" />}
556
+ {listResult
557
+ and <ResultDisplay
558
+ data={listResult}
559
+ label="List Operations Result"
560
+ />}
485
561
  </div>
486
562
  </TestCard>
487
-
488
563
  # # Section 4: TypeScript Component Integration
489
564
  # <TestCard title="4. TypeScript Component (PieChart.tsx)" color="#ccfbf1">
490
565
  # <div>
@@ -504,60 +579,97 @@ sv import from .FeaturesTest {
504
579
  <p style={{"color": "#4b5563", "marginBottom": "15px"}}>
505
580
  This page demonstrates various import types:
506
581
  </p>
507
-
508
582
  <ul style={{"color": "#374151", "lineHeight": "1.8"}}>
509
- <li><strong>JAC-Client Utils:</strong> Router components (Link, useNavigate)</li>
510
- <li><strong>React:</strong> Hooks (useState, useEffect)</li>
583
+ <li>
584
+ <strong>
585
+ JAC-Client Utils:
586
+ </strong>
587
+ Router components (Link, useNavigate)
588
+ </li>
589
+ <li>
590
+ <strong>
591
+ React:
592
+ </strong>
593
+ Hooks (useState, useEffect)
594
+ </li>
511
595
  # <li><strong>TypeScript:</strong> PieChart component from .tsx file</li>
512
- <li><strong>JavaScript:</strong> Helper functions from .js file (generateId, sumBy)</li>
513
- <li><strong>JAC Files:</strong> formatCurrency from utils/formatters.jac</li>
596
+ <li>
597
+ <strong>
598
+ JavaScript:
599
+ </strong>
600
+ Helper functions from .js file (generateId, sumBy)
601
+ </li>
602
+ <li>
603
+ <strong>
604
+ JAC Files:
605
+ </strong>
606
+ for
607
+ matCurrency from utils/formatters.jac
608
+ </li>
514
609
  </ul>
515
-
516
- <div style={{
517
- "backgroundColor": "#f0fdf4",
518
- "padding": "15px",
519
- "borderRadius": "6px",
520
- "marginTop": "15px"
521
- }}>
522
- <strong style={{"color": "#065f46"}}>Examples:</strong>
523
- <div style={{"marginTop": "8px", "fontSize": "14px", "color": "#047857"}}>
524
- <div>Generated ID: {generateId()}</div>
525
- <div>Formatted Currency: {formatCurrency(1234.56)}</div>
526
- <div>Percentage Calc: {calculatePercentage(75, 100)}%</div>
610
+ <div
611
+ style={{
612
+ "backgroundColor": "#f0fdf4",
613
+ "padding": "15px",
614
+ "borderRadius": "6px",
615
+ "marginTop": "15px"
616
+ }}
617
+ >
618
+ <strong style={{"color": "#065f46"}}>
619
+ Examples:
620
+ </strong>
621
+ <div
622
+ style={{
623
+ "marginTop": "8px",
624
+ "fontSize": "14px",
625
+ "color": "#047857"
626
+ }}
627
+ >
628
+ <div>
629
+ Generated ID: {generateId()}
630
+ </div>
631
+ <div>
632
+ Formatted Currency: {formatCurrency(1234.56)}
633
+ </div>
634
+ <div>
635
+ Percentage Calc: {calculatePercentage(75, 100)}%
636
+ </div>
527
637
  </div>
528
638
  </div>
529
639
  </div>
530
640
  </TestCard>
531
-
532
641
  # # Section 6: Complex Data Processing
533
642
  <TestCard title="6. Complex Data Processing" color="#e0e7ff">
534
643
  <div>
535
644
  <p style={{"color": "#4b5563", "marginBottom": "10px"}}>
536
645
  Process complex nested data structures with walkers.
537
646
  </p>
538
-
539
647
  <TestButton
540
648
  text="Process Sample Data"
541
- onClick={lambda -> None { handleComplexTest(); }}
649
+ onClick={lambda -> None { handleComplexTest();}}
542
650
  variant="primary"
543
651
  />
544
-
545
- {complexResult and <ResultDisplay data={complexResult} label="Complex Processing Result" />}
652
+ {complexResult
653
+ and <ResultDisplay
654
+ data={complexResult}
655
+ label="Complex Processing Result"
656
+ />}
546
657
  </div>
547
658
  </TestCard>
548
-
549
659
  # Footer
550
- <div style={{
551
- "marginTop": "30px",
552
- "padding": "20px",
553
- "backgroundColor": "#f9fafb",
554
- "borderRadius": "8px",
555
- "textAlign": "center",
556
- "color": "#6b7280"
557
- }}>
660
+ <div
661
+ style={{
662
+ "marginTop": "30px",
663
+ "padding": "20px",
664
+ "backgroundColor": "#f9fafb",
665
+ "borderRadius": "8px",
666
+ "textAlign": "center",
667
+ "color": "#6b7280"
668
+ }}
669
+ >
558
670
  <p style={{"margin": "0"}}>
559
671
  ✅ All features tested: Props, Exports, CL Files, TypeScript, JavaScript, JAC Imports, String Methods, Walker Spawning
560
672
  </p>
561
673
  </div>
562
674
  </div>;
563
- }
675
+ }