jac-client 0.2.8__py3-none-any.whl → 0.2.11__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (119) 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 +542 -0
  17. jac_client/examples/all-in-one/pages/BudgetPlanner.jac +26 -12
  18. jac_client/examples/all-in-one/pages/FeaturesTest.jac +43 -12
  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 +65 -0
  21. jac_client/examples/all-in-one/pages/features_test_ui.cl.jac +675 -0
  22. jac_client/examples/all-in-one/pages/loginPage.jac +114 -119
  23. jac_client/examples/all-in-one/pages/nestedDemo.jac +44 -51
  24. jac_client/examples/all-in-one/pages/notFound.jac +15 -21
  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 +92 -0
  28. jac_client/examples/asset-serving/image-asset/main.jac +56 -0
  29. jac_client/examples/asset-serving/import-alias/main.jac +109 -0
  30. jac_client/examples/basic/main.jac +23 -0
  31. jac_client/examples/basic-auth/main.jac +363 -0
  32. jac_client/examples/basic-auth-with-router/main.jac +451 -0
  33. jac_client/examples/basic-full-stack/main.jac +362 -0
  34. jac_client/examples/css-styling/js-styling/main.jac +63 -0
  35. jac_client/examples/css-styling/material-ui/main.jac +122 -0
  36. jac_client/examples/css-styling/pure-css/main.jac +55 -0
  37. jac_client/examples/css-styling/sass-example/main.jac +55 -0
  38. jac_client/examples/css-styling/styled-components/main.jac +62 -0
  39. jac_client/examples/css-styling/tailwind-example/main.jac +74 -0
  40. jac_client/examples/full-stack-with-auth/main.jac +696 -0
  41. jac_client/examples/little-x/main.jac +681 -0
  42. jac_client/examples/little-x/src/submit-button.jac +15 -14
  43. jac_client/examples/nested-folders/nested-advance/main.jac +26 -0
  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/{src/app.jac → 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 +35 -0
  52. jac_client/examples/with-router/main.jac +286 -0
  53. jac_client/plugin/cli.jac +491 -411
  54. jac_client/plugin/client.jac +25 -0
  55. jac_client/plugin/client_runtime.cl.jac +10 -4
  56. jac_client/plugin/impl/client.impl.jac +96 -55
  57. jac_client/plugin/impl/client_runtime.impl.jac +155 -1
  58. jac_client/plugin/plugin_config.jac +211 -29
  59. jac_client/plugin/src/__init__.jac +0 -2
  60. jac_client/plugin/src/compiler.jac +0 -1
  61. jac_client/plugin/src/config_loader.jac +1 -0
  62. jac_client/plugin/src/desktop_config.jac +31 -0
  63. jac_client/plugin/src/impl/compiler.impl.jac +49 -17
  64. jac_client/plugin/src/impl/config_loader.impl.jac +8 -0
  65. jac_client/plugin/src/impl/desktop_config.impl.jac +191 -0
  66. jac_client/plugin/src/impl/jac_to_js.impl.jac +5 -1
  67. jac_client/plugin/src/impl/package_installer.impl.jac +20 -20
  68. jac_client/plugin/src/impl/vite_bundler.impl.jac +191 -64
  69. jac_client/plugin/src/targets/desktop/sidecar/main.py +144 -0
  70. jac_client/plugin/src/targets/desktop_target.jac +37 -0
  71. jac_client/plugin/src/targets/impl/desktop_target.impl.jac +2347 -0
  72. jac_client/plugin/src/targets/impl/registry.impl.jac +64 -0
  73. jac_client/plugin/src/targets/impl/web_target.impl.jac +157 -0
  74. jac_client/plugin/src/targets/register.jac +21 -0
  75. jac_client/plugin/src/targets/registry.jac +87 -0
  76. jac_client/plugin/src/targets/web_target.jac +35 -0
  77. jac_client/plugin/src/vite_bundler.jac +6 -0
  78. jac_client/plugin/utils/__init__.jac +3 -0
  79. jac_client/plugin/utils/bun_installer.jac +16 -0
  80. jac_client/plugin/utils/impl/bun_installer.impl.jac +99 -0
  81. jac_client/templates/client.jacpack +72 -0
  82. jac_client/templates/fullstack.jacpack +61 -0
  83. jac_client/tests/conftest.py +103 -47
  84. jac_client/tests/fixtures/spawn_test/app.jac +49 -52
  85. jac_client/tests/fixtures/with-ts/app.jac +27 -27
  86. jac_client/tests/test_cli.py +182 -71
  87. jac_client/tests/test_e2e.py +232 -0
  88. jac_client/tests/test_helpers.py +58 -0
  89. jac_client/tests/test_it.py +91 -135
  90. jac_client/tests/test_it_desktop.py +891 -0
  91. {jac_client-0.2.8.dist-info → jac_client-0.2.11.dist-info}/METADATA +6 -6
  92. jac_client-0.2.11.dist-info/RECORD +113 -0
  93. {jac_client-0.2.8.dist-info → jac_client-0.2.11.dist-info}/WHEEL +1 -1
  94. jac_client/examples/all-in-one/app.jac +0 -573
  95. jac_client/examples/all-in-one/pages/BudgetPlanner.cl.jac +0 -70
  96. jac_client/examples/all-in-one/pages/FeaturesTest.cl.jac +0 -552
  97. jac_client/examples/asset-serving/css-with-image/src/app.jac +0 -88
  98. jac_client/examples/asset-serving/image-asset/src/app.jac +0 -55
  99. jac_client/examples/asset-serving/import-alias/src/app.jac +0 -111
  100. jac_client/examples/basic/src/app.jac +0 -21
  101. jac_client/examples/basic-auth/src/app.jac +0 -371
  102. jac_client/examples/basic-auth-with-router/src/app.jac +0 -464
  103. jac_client/examples/basic-full-stack/src/app.jac +0 -359
  104. jac_client/examples/css-styling/js-styling/src/app.jac +0 -84
  105. jac_client/examples/css-styling/material-ui/src/app.jac +0 -122
  106. jac_client/examples/css-styling/pure-css/src/app.jac +0 -64
  107. jac_client/examples/css-styling/sass-example/src/app.jac +0 -64
  108. jac_client/examples/css-styling/styled-components/src/app.jac +0 -71
  109. jac_client/examples/css-styling/tailwind-example/src/app.jac +0 -63
  110. jac_client/examples/full-stack-with-auth/src/app.jac +0 -722
  111. jac_client/examples/little-x/src/app.jac +0 -719
  112. jac_client/examples/nested-folders/nested-advance/src/app.jac +0 -35
  113. jac_client/examples/ts-support/src/app.jac +0 -35
  114. jac_client/examples/with-router/src/app.jac +0 -323
  115. jac_client/plugin/src/babel_processor.jac +0 -18
  116. jac_client/plugin/src/impl/babel_processor.impl.jac +0 -89
  117. jac_client-0.2.8.dist-info/RECORD +0 -97
  118. {jac_client-0.2.8.dist-info → jac_client-0.2.11.dist-info}/entry_points.txt +0 -0
  119. {jac_client-0.2.8.dist-info → jac_client-0.2.11.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,542 @@
1
+ import from datetime { datetime, timedelta }
2
+
3
+ #
4
+ # Basic backend walkers
5
+ #
6
+ node Todo {
7
+ has text: str,
8
+ done: bool = False;
9
+ }
10
+
11
+ walker:pub create_todo {
12
+ has text: str;
13
+
14
+ can create with `root entry {
15
+ new_todo = here ++> Todo(text=self.text);
16
+ report new_todo;
17
+ }
18
+ }
19
+
20
+ walker:pub ping_server {
21
+ can ping with `root entry {
22
+ report "pong from backend!";
23
+ }
24
+ }
25
+
26
+ walker:pub get_server_message {
27
+ can info with `root entry {
28
+ report "hello from a basic walker!";
29
+ }
30
+ }
31
+
32
+ # Features Test Page - Backend Logic
33
+ # This file is intentionally kept empty to demonstrate the separation of concerns
34
+ # where UI logic resides in .cl.jac files and backend walker logic in app.jac
35
+
36
+ # All walker implementations for this feature are in main.jac
37
+ # This demonstrates that you can have separate .jac files for different purposes
38
+ # Features Test - Backend Walkers
39
+ # This file demonstrates walker functionality for testing various JAC features
40
+
41
+ # Node definition for storing test data
42
+ node TestData {
43
+ has message: str,
44
+ count: int = 0,
45
+ created_at: str = "";
46
+ }
47
+
48
+ # Walker: Create test data
49
+ walker create_test_data {
50
+ has message: str;
51
+
52
+ can create with `root entry {
53
+ new_data = here ++> TestData(
54
+ message=self.message,
55
+ count=1,
56
+ created_at=datetime.now().strftime("%Y-%m-%d %H:%M:%S")
57
+ );
58
+ report new_data;
59
+ }
60
+ }
61
+
62
+ # Walker: Read all test data
63
+ walker read_test_data {
64
+ can read with `root entry {
65
+ visit [-->(`?TestData)];
66
+ }
67
+
68
+ can report_data with exit {
69
+ report here;
70
+ }
71
+ }
72
+
73
+ # Walker: Update test data
74
+ walker update_test_data {
75
+ has new_message: str;
76
+
77
+ can update with TestData entry {
78
+ here.message = self.new_message;
79
+ here.count = here.count + 1;
80
+ report here;
81
+ }
82
+ }
83
+
84
+ # Walker: Delete test data
85
+ walker delete_test_data {
86
+ can delete with TestData entry {
87
+ del here;
88
+ report {"status": "deleted"};
89
+ }
90
+ }
91
+
92
+ # Walker: String manipulation test
93
+ walker test_string_methods {
94
+ has input_text: str;
95
+
96
+ can process with `root entry {
97
+ result = {
98
+ "original": self.input_text,
99
+ "uppercase": self.input_text.upper(),
100
+ "lowercase": self.input_text.lower(),
101
+ "capitalized": self.input_text.capitalize(),
102
+ "reversed": self.input_text[::-1],
103
+ "length": len(self.input_text),
104
+ "words": self.input_text.split(),
105
+ "trimmed": self.input_text.strip(),
106
+ "replaced": self.input_text.replace("test", "demo")
107
+ };
108
+ report result;
109
+ }
110
+ }
111
+
112
+ # Walker: Array/List operations test
113
+ walker test_list_operations {
114
+ has numbers: list;
115
+
116
+ can process with `root entry {
117
+ result = {
118
+ "original": self.numbers,
119
+ "sorted": sorted(self.numbers),
120
+ "reversed": list(reversed(self.numbers)),
121
+ "sum": sum(self.numbers),
122
+ "max": max(self.numbers) if len(self.numbers) > 0 else 0,
123
+ "min": min(self.numbers) if len(self.numbers) > 0 else 0,
124
+ "length": len(self.numbers),
125
+ "doubled": [x * 2 for x in self.numbers]
126
+ };
127
+ report result;
128
+ }
129
+ }
130
+
131
+ # Walker: Complex data processing
132
+ walker process_complex_data {
133
+ has items: list;
134
+
135
+ can process with `root entry {
136
+ processed = [];
137
+ for item in self.items {
138
+ processed.append(
139
+ {
140
+ "id": item.get("id", 0),
141
+ "name": item.get("name", "").upper(),
142
+ "value": item.get("value", 0) * 2,
143
+ "processed_at": datetime.now().strftime("%H:%M:%S")
144
+ }
145
+ );
146
+ }
147
+
148
+ result = {
149
+ "original_count": len(self.items),
150
+ "processed_count": len(processed),
151
+ "items": processed,
152
+ "total_value": sum([p["value"] for p in processed])
153
+ };
154
+
155
+ report result;
156
+ }
157
+ }
158
+
159
+ #
160
+ # Combined example: auth + routing + CSS styling + asset serving + nested folder imports
161
+ #
162
+ cl import from react { useEffect, useRef }
163
+ cl import from "@jac/runtime" {
164
+ Router,
165
+ Routes,
166
+ Route,
167
+ Link,
168
+ useNavigate,
169
+ Navigate,
170
+ jacIsLoggedIn
171
+ }
172
+
173
+ # Pure CSS + asset-in-CSS example
174
+ cl import ".styles/styles.css";
175
+
176
+ # Login Page
177
+ cl import from .pages.loginPage { LoginPage }
178
+
179
+ # Signup Page
180
+ cl import from .pages.signupPage { SignupPage }
181
+
182
+ # Simple 404 page
183
+ cl import from .pages.notFound { NotFound }
184
+
185
+ # Navigation component with active link styling and auth
186
+ cl import from .components.navigation {
187
+ Navigation
188
+ }
189
+
190
+ # Page showing nested imports from different folders
191
+ cl import from .pages.nestedDemo {
192
+ NestedImportsDemo
193
+ }
194
+
195
+ cl import from .pages.FeaturesTest { FeaturesTest }
196
+
197
+ cl import from .pages.LandingPage { LandingPage }
198
+
199
+ cl import from .pages.BudgetPlanner { BudgetPlanner }
200
+
201
+ # Context provider
202
+ cl import from .context.BudgetContext { BudgetProvider }
203
+
204
+ # TypeScript component import
205
+ cl import from ".components/Card.tsx" { Card }
206
+
207
+ # Main app wrapped in Router (same API as with-router/ example)
208
+ cl {
209
+ def:pub HomePage -> any {
210
+ # Check if user is logged in, redirect if not
211
+ if not jacIsLoggedIn() {
212
+ return
213
+ <Navigate to="/login" />;
214
+ }
215
+ has count: int = 0,
216
+ pingResult: str = "",
217
+ serverMessage: str = "",
218
+ lastTodoMessage: str = "";
219
+
220
+ can with count entry {
221
+ console.log("Home count changed: ", count);
222
+ }
223
+
224
+ # Call simple backend walkers
225
+ async def handlePing -> None {
226
+ result = root spawn ping_server();
227
+ if result.reports and result.reports.length > 0 {
228
+ pingResult = result.reports[0][0];
229
+ }
230
+ }
231
+
232
+ async def loadServerMessage -> None {
233
+ result = root spawn get_server_message();
234
+ if result.reports and result.reports.length > 0 {
235
+ serverMessage = result.reports[0][0];
236
+ }
237
+ }
238
+
239
+ # Create a sample Todo node in the graph with a hardcoded payload
240
+ async def handleCreateSampleTodo -> None {
241
+ result = root spawn create_todo(text="Sample todo from all-in-one app");
242
+ if result.reports and result.reports.length > 0 {
243
+ todo = result.reports[0][0];
244
+ lastTodoMessage = "Created Todo: " + todo.text;
245
+ console.log("Created Todo node:", todo);
246
+ }
247
+ }
248
+
249
+ async can with entry {
250
+ await loadServerMessage();
251
+ }
252
+
253
+ # Initialize a Web Worker and handle message-based communication
254
+ workerRef = useRef(None);
255
+ has message: str = "";
256
+
257
+ useEffect(
258
+ lambda -> None { workerRef.current = Reflect.construct(
259
+ Worker, ["/workers/worker.js"]
260
+ );workerRef.current.onmessage = lambda event: any -> None { console.log(
261
+ "Message received from worker:", event.data
262
+ );message = event.data;};return (
263
+ lambda -> None { workerRef.current.terminate();}
264
+ ); },
265
+ []
266
+ );
267
+ handleClick = lambda -> None { workerRef.current.postMessage("");};
268
+
269
+ return
270
+ <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
+ staticassets
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"
329
+ >
330
+ <p style={{"margin": "0.5rem 0", "color": "#374151"}}>
331
+ This is a TypeScript component imported and used in Jac code!
332
+ </p>
333
+ </Card>
334
+ <div className="card">
335
+ <h3>
336
+ Direct &lt;img&gt; asset
337
+ </h3>
338
+ <img
339
+ src="/static/assets/burger.png"
340
+ alt="Burger asset served by Jac"
341
+ className="burgerImage"
342
+ />
343
+ <p style={{"marginTop": "0.75rem", "color": "#555"}}>
344
+ This image is served from the project
345
+ {" "}
346
+ <code>
347
+ assets/
348
+ </code>
349
+ {" "}
350
+ folder using the
351
+ {" "}
352
+ <code>
353
+ /static/assets/
354
+ </code>
355
+ {" "}
356
+ path.
357
+ </p>
358
+ </div>
359
+ <div style={{"marginTop": "2rem"}}>
360
+ <h3>
361
+ Counter with pure CSS classes
362
+ </h3>
363
+ <p>
364
+ You've clicked the burger
365
+ {" "}
366
+ <strong>
367
+ {count}
368
+ </strong>
369
+ {" "}
370
+ times.
371
+ </p>
372
+ <button
373
+ onClick={lambda e: any -> None { count = count + 1;}}
374
+ style={{
375
+ "padding": "0.6rem 1.4rem",
376
+ "fontSize": "1rem",
377
+ "backgroundColor": "#ff6b35",
378
+ "color": "white",
379
+ "border": "none",
380
+ "borderRadius": "6px",
381
+ "cursor": "pointer",
382
+ "boxShadow": "0 2px 4px rgba(0,0,0,0.2)"
383
+ }}
384
+ >
385
+ Click the Burger! 🍔
386
+ </button>
387
+ </div>
388
+ <div style={{"marginTop": "2rem"}}>
389
+ <h3>
390
+ Backend Walkers
391
+ </h3>
392
+ <p>
393
+ Basic example walkers:
394
+ {" "}
395
+ <code>
396
+ ping_server
397
+ </code>
398
+ {" "}
399
+ and
400
+ {" "}
401
+ <code>
402
+ get_server_message
403
+ </code>
404
+ </p>
405
+ <button
406
+ onClick={lambda e: any -> None { handlePing();}}
407
+ style={{
408
+ "padding": "0.5rem 1.2rem",
409
+ "marginRight": "0.75rem",
410
+ "backgroundColor": "#3b82f6",
411
+ "color": "white",
412
+ "border": "none",
413
+ "borderRadius": "6px",
414
+ "cursor": "pointer"
415
+ }}
416
+ >
417
+ Ping Backend
418
+ </button>
419
+ <button
420
+ onClick={lambda e: any -> None { handleCreateSampleTodo();}}
421
+ style={{
422
+ "padding": "0.5rem 1.2rem",
423
+ "backgroundColor": "#10b981",
424
+ "color": "white",
425
+ "border": "none",
426
+ "borderRadius": "6px",
427
+ "cursor": "pointer"
428
+ }}
429
+ >
430
+ Create Sample Todo
431
+ </button>
432
+ {pingResult
433
+ and (
434
+ <span style={{"marginLeft": "0.5rem", "color": "#374151"}}>
435
+ Result:
436
+ {" "}
437
+ <code>
438
+ {pingResult}
439
+ </code>
440
+ </span>
441
+ )}
442
+ {serverMessage
443
+ and (
444
+ <p style={{"marginTop": "0.75rem", "color": "#374151"}}>
445
+ Message:
446
+ {" "}
447
+ <code>
448
+ {serverMessage}
449
+ </code>
450
+ </p>
451
+ )}
452
+ {lastTodoMessage
453
+ and (
454
+ <p style={{"marginTop": "0.5rem", "color": "#111827"}}>
455
+ {lastTodoMessage}
456
+ </p>
457
+ )}
458
+ </div>
459
+ <div style={{"marginTop": "2rem"}}>
460
+ <h3>
461
+ Web Worker
462
+ </h3>
463
+ <p>
464
+ This demonstrates how to communicate with a
465
+ {" "}
466
+ <strong>
467
+ Python backend worker
468
+ </strong>
469
+ {" "}
470
+ using Web Workers for asynchronous processing.
471
+ </p>
472
+ <p
473
+ style={{
474
+ "fontSize": "0.9rem",
475
+ "color": "#666",
476
+ "marginTop": "0.5rem"
477
+ }}
478
+ >
479
+ File:
480
+ {" "}
481
+ <code>
482
+ worker.py
483
+ </code>
484
+ {" "}
485
+ — Runs in a separate thread to avoid blocking the UI.
486
+ </p>
487
+ <button
488
+ onClick={lambda -> None { handleClick();}}
489
+ style={{
490
+ "padding": "0.5rem 1.2rem",
491
+ "marginRight": "0.75rem",
492
+ "backgroundColor": "#d73bf6ff",
493
+ "color": "white",
494
+ "border": "none",
495
+ "borderRadius": "6px",
496
+ "cursor": "pointer"
497
+ }}
498
+ >
499
+ Call Python Worker
500
+ </button>
501
+ {message
502
+ && (
503
+ <p style={{marginTop: "1rem", fontWeight: "bold"}}>
504
+ {message}
505
+ </p>
506
+ )}
507
+ </div>
508
+ </div>;
509
+ }
510
+
511
+ def:pub app -> any {
512
+ return
513
+ <Router>
514
+ <div style={{"fontFamily": "system-ui, -apple-system, sans-serif"}}>
515
+ <Navigation />
516
+ <div
517
+ style={{
518
+ "maxWidth": "960px",
519
+ "margin": "0 auto",
520
+ "padding": "0 1rem 3rem 1rem"
521
+ }}
522
+ >
523
+ <Routes>
524
+ <Route path="/" element={<HomePage />} />
525
+ <Route path="/login" element={<LoginPage />} />
526
+ <Route path="/signup" element={<SignupPage />} />
527
+ <Route path="/nested" element={<NestedImportsDemo />} />
528
+ <Route path="/features-test" element={<FeaturesTest />} />
529
+ <Route path="/landing" element={<LandingPage />} />
530
+ <Route
531
+ path="/budget-planner"
532
+ element={<BudgetProvider>
533
+ <BudgetPlanner />
534
+ </BudgetProvider>}
535
+ />
536
+ <Route path="*" element={<NotFound />} />
537
+ </Routes>
538
+ </div>
539
+ </div>
540
+ </Router>;
541
+ }
542
+ }
@@ -2,18 +2,20 @@
2
2
  # This file is intentionally kept empty to demonstrate the separation of concerns
3
3
  # where UI logic resides in .cl.jac files and backend walker logic in app.jac
4
4
 
5
- # All walker implementations for this feature are in src/app.jac
5
+ # All walker implementations for this feature are in main.jac
6
6
  # This demonstrates that you can have separate .jac files for different purposes
7
7
  # Features Test - Backend Walkers
8
8
  # This file demonstrates walker functionality for testing various JAC features
9
-
10
- import from datetime { datetime, timedelta }
9
+ import from datetime {
10
+ datetime,
11
+ timedelta
12
+ }
11
13
 
12
14
  # Node definition for storing test data
13
15
  node TestData {
14
- has message: str;
15
- has count: int = 0;
16
- has created_at: str = "";
16
+ has message: str,
17
+ count: int = 0,
18
+ created_at: str = "";
17
19
  }
18
20
 
19
21
  # Walker: Create test data
@@ -106,12 +108,14 @@ walker process_complex_data {
106
108
  can process with `root entry {
107
109
  processed = [];
108
110
  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
- });
111
+ processed.append(
112
+ {
113
+ "id": item.get("id", 0),
114
+ "name": item.get("name", "").upper(),
115
+ "value": item.get("value", 0) * 2,
116
+ "processed_at": datetime.now().strftime("%H:%M:%S")
117
+ }
118
+ );
115
119
  }
116
120
 
117
121
  result = {
@@ -124,3 +128,13 @@ walker process_complex_data {
124
128
  report result;
125
129
  }
126
130
  }
131
+
132
+ # Re-export client components from the standalone client module
133
+ cl {
134
+ import from .budget_planner_ui { BudgetPlanner as BudgetPlannerUI }
135
+
136
+ def:pub BudgetPlanner -> any {
137
+ return
138
+ <BudgetPlannerUI />;
139
+ }
140
+ }
@@ -2,18 +2,20 @@
2
2
  # This file is intentionally kept empty to demonstrate the separation of concerns
3
3
  # where UI logic resides in .cl.jac files and backend walker logic in app.jac
4
4
 
5
- # All walker implementations for this feature are in src/app.jac
5
+ # All walker implementations for this feature are in main.jac
6
6
  # This demonstrates that you can have separate .jac files for different purposes
7
7
  # Features Test - Backend Walkers
8
8
  # This file demonstrates walker functionality for testing various JAC features
9
-
10
- import from datetime { datetime, timedelta }
9
+ import from datetime {
10
+ datetime,
11
+ timedelta
12
+ }
11
13
 
12
14
  # Node definition for storing test data
13
15
  node TestData {
14
- has message: str;
15
- has count: int = 0;
16
- has created_at: str = "";
16
+ has message: str,
17
+ count: int = 0,
18
+ created_at: str = "";
17
19
  }
18
20
 
19
21
  # Walker: Create test data
@@ -106,12 +108,14 @@ walker process_complex_data {
106
108
  can process with `root entry {
107
109
  processed = [];
108
110
  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
- });
111
+ processed.append(
112
+ {
113
+ "id": item.get("id", 0),
114
+ "name": item.get("name", "").upper(),
115
+ "value": item.get("value", 0) * 2,
116
+ "processed_at": datetime.now().strftime("%H:%M:%S")
117
+ }
118
+ );
115
119
  }
116
120
 
117
121
  result = {
@@ -124,3 +128,30 @@ walker process_complex_data {
124
128
  report result;
125
129
  }
126
130
  }
131
+
132
+ # Re-export client components from the standalone client module
133
+ cl {
134
+ import from .features_test_ui {
135
+ FeaturesTest as FeaturesTestUI,
136
+ TestButton as TestButtonUI,
137
+ TestCard as TestCardUI,
138
+ ResultDisplay as ResultDisplayUI
139
+ }
140
+
141
+ def:pub FeaturesTest -> any {
142
+ return
143
+ <FeaturesTestUI />;
144
+ }
145
+ def:pub TestButton(text: str, onClick: any, variant: str) -> any {
146
+ return
147
+ <TestButtonUI text={text} onClick={onClick} variant={variant} />;
148
+ }
149
+ def:pub TestCard(title: str, children: any, color: str) -> any {
150
+ return
151
+ <TestCardUI title={title} children={children} color={color} />;
152
+ }
153
+ def:pub ResultDisplay(data: any, label: str) -> any {
154
+ return
155
+ <ResultDisplayUI data={data} label={label} />;
156
+ }
157
+ }