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
@@ -8,29 +8,27 @@ node Todo {
8
8
  done: bool = False;
9
9
  }
10
10
 
11
- walker : pub create_todo {
11
+ walker:pub create_todo {
12
12
  has text: str;
13
13
 
14
14
  can create with `root entry {
15
15
  new_todo = here ++> Todo(text=self.text);
16
- report new_todo ;
16
+ report new_todo;
17
17
  }
18
18
  }
19
19
 
20
- walker : pub ping_server {
20
+ walker:pub ping_server {
21
21
  can ping with `root entry {
22
- report "pong from backend!" ;
22
+ report "pong from backend!";
23
23
  }
24
24
  }
25
25
 
26
- walker : pub get_server_message {
26
+ walker:pub get_server_message {
27
27
  can info with `root entry {
28
- report "hello from a basic walker!" ;
28
+ report "hello from a basic walker!";
29
29
  }
30
30
  }
31
31
 
32
-
33
-
34
32
  # Features Test Page - Backend Logic
35
33
  # This file is intentionally kept empty to demonstrate the separation of concerns
36
34
  # where UI logic resides in .cl.jac files and backend walker logic in app.jac
@@ -40,12 +38,11 @@ walker : pub get_server_message {
40
38
  # Features Test - Backend Walkers
41
39
  # This file demonstrates walker functionality for testing various JAC features
42
40
 
43
-
44
41
  # Node definition for storing test data
45
42
  node TestData {
46
- has message: str;
47
- has count: int = 0;
48
- has created_at: str = "";
43
+ has message: str,
44
+ count: int = 0,
45
+ created_at: str = "";
49
46
  }
50
47
 
51
48
  # Walker: Create test data
@@ -138,12 +135,14 @@ walker process_complex_data {
138
135
  can process with `root entry {
139
136
  processed = [];
140
137
  for item in self.items {
141
- processed.append({
142
- "id": item.get("id", 0),
143
- "name": item.get("name", "").upper(),
144
- "value": item.get("value", 0) * 2,
145
- "processed_at": datetime.now().strftime("%H:%M:%S")
146
- });
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
+ );
147
146
  }
148
147
 
149
148
  result = {
@@ -157,12 +156,11 @@ walker process_complex_data {
157
156
  }
158
157
  }
159
158
 
160
-
161
159
  #
162
160
  # Combined example: auth + routing + CSS styling + asset serving + nested folder imports
163
161
  #
164
162
  cl import from react { useEffect, useRef }
165
- cl import from "@jac-client/utils" {
163
+ cl import from "@jac/runtime" {
166
164
  Router,
167
165
  Routes,
168
166
  Route,
@@ -170,13 +168,12 @@ cl import from "@jac-client/utils" {
170
168
  useNavigate,
171
169
  Navigate,
172
170
  jacIsLoggedIn
173
-
174
171
  }
175
172
 
176
173
  # Pure CSS + asset-in-CSS example
177
174
  cl import ".styles/styles.css";
178
175
 
179
- # Login Page
176
+ # Login Page
180
177
  cl import from .pages.loginPage { LoginPage }
181
178
 
182
179
  # Signup Page
@@ -186,10 +183,14 @@ cl import from .pages.signupPage { SignupPage }
186
183
  cl import from .pages.notFound { NotFound }
187
184
 
188
185
  # Navigation component with active link styling and auth
189
- cl import from .components.navigation { Navigation }
186
+ cl import from .components.navigation {
187
+ Navigation
188
+ }
190
189
 
191
190
  # Page showing nested imports from different folders
192
- cl import from .pages.nestedDemo { NestedImportsDemo }
191
+ cl import from .pages.nestedDemo {
192
+ NestedImportsDemo
193
+ }
193
194
 
194
195
  cl import from .pages.FeaturesTest { FeaturesTest }
195
196
 
@@ -200,374 +201,342 @@ cl import from .pages.BudgetPlanner { BudgetPlanner }
200
201
  # Context provider
201
202
  cl import from .context.BudgetContext { BudgetProvider }
202
203
 
203
-
204
-
205
204
  # TypeScript component import
206
205
  cl import from ".components/Card.tsx" { Card }
207
206
 
208
-
209
207
  # Main app wrapped in Router (same API as with-router/ example)
210
208
  cl {
211
209
  def:pub HomePage -> any {
212
- # Check if user is logged in, redirect if not
213
- if not jacIsLoggedIn() {
214
- return <Navigate to="/login" />;
215
- }
216
- has count: int = 0;
217
- has pingResult: str = "";
218
- has serverMessage: str = "";
219
- has lastTodoMessage: str = "";
220
-
221
- useEffect(
222
- lambda -> None{ console.log("Home count changed: ", count);} , [count]
223
- );
224
-
225
- # Call simple backend walkers
226
- async def handlePing -> None {
227
- result = root spawn ping_server();
228
- if result.reports and result.reports.length > 0 {
229
- pingResult = result.reports[0][0];
210
+ # Check if user is logged in, redirect if not
211
+ if not jacIsLoggedIn() {
212
+ return
213
+ <Navigate to="/login" />;
230
214
  }
231
- }
215
+ has count: int = 0,
216
+ pingResult: str = "",
217
+ serverMessage: str = "",
218
+ lastTodoMessage: str = "";
232
219
 
233
- async def loadServerMessage -> None {
234
- result = root spawn get_server_message();
235
- if result.reports and result.reports.length > 0 {
236
- serverMessage = result.reports[0][0];
220
+ can with count entry {
221
+ console.log("Home count changed: ", count);
237
222
  }
238
- }
239
223
 
240
- # Create a sample Todo node in the graph with a hardcoded payload
241
- async def handleCreateSampleTodo -> None {
242
- result = root spawn create_todo(text="Sample todo from all-in-one app");
243
- if result.reports and result.reports.length > 0 {
244
- todo = result.reports[0][0];
245
- lastTodoMessage = "Created Todo: " + todo.text;
246
- console.log("Created Todo node:", todo);
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
+ }
247
230
  }
248
- }
249
231
 
250
- useEffect(lambda -> None{ loadServerMessage();} , []);
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
+ }
251
238
 
252
- # Initialize a Web Worker and handle message-based communication
253
- workerRef = useRef(None);
254
- has message: str = "";
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
+ }
255
248
 
256
- useEffect(lambda -> None {
257
- workerRef.current = Reflect.construct(Worker, ["/workers/worker.js"]);
258
- workerRef.current.onmessage = lambda event: any -> None {
259
- console.log("Message received from worker:", event.data);
260
- message = event.data;
261
- };
262
- return (lambda -> None {
263
- workerRef.current.terminate();
264
- });
265
- }, []);
266
- handleClick = lambda -> None {
267
- workerRef.current.postMessage("");
268
- };
269
-
270
- return <div
271
- style={{
272
- "padding": "2rem",
273
- "fontFamily": "system-ui, -apple-system, sans-serif"
274
- }}
275
- >
276
- <h1>
277
- 🍔 Router + Styling + Assets Demo
278
- </h1>
279
- <p>
280
- This home page combines
281
- {" "}
282
- <strong>
283
- React Router,
284
- </strong>
285
- {" "}
286
- <strong>
287
- pure CSS styling,
288
- </strong>
289
- {" "}
290
- <strong>
291
- static assets
292
- </strong>
293
- {" "}
294
- and
295
- {" "}
296
- <strong>
297
- nested folder imports
298
- </strong>
299
- </p>
300
- <div className="container">
301
- <h2
302
- style={{
303
- "color": "white",
304
- "textShadow": "2px 2px 4px rgba(0,0,0,0.6)"
305
- }}
306
- >
307
- CSS Background Image
308
- </h2>
309
- <p
310
- style={{
311
- "color": "white",
312
- "maxWidth": "480px",
313
- "textShadow": "1px 1px 3px rgba(0,0,0,0.7)"
314
- }}
315
- >
316
- This section uses the burger image as a background via CSS, just like the
317
- {" "}
318
- <code>
319
- asset-serving/css-with-image
320
- </code>
321
- {" "}
322
- example.
323
- </p>
324
- </div>
325
- <Card
326
- title="TypeScript Card Component"
327
- description="This card is built with TypeScript and demonstrates type-safe component usage in Jac"
328
- variant="highlighted"
329
- >
330
- <p
331
- style={{"margin": "0.5rem 0", "color": "#374151"}}
332
- >
333
- This is a TypeScript component imported and used in Jac code!
334
- </p>
335
- </Card>
336
- <div className="card">
337
- <h3>
338
- Direct &lt;img&gt; asset
339
- </h3>
340
- <img
341
- src="/static/assets/burger.png"
342
- alt="Burger asset served by Jac"
343
- className="burgerImage"
344
- />
345
- <p
346
- style={{"marginTop": "0.75rem", "color": "#555"}}
347
- >
348
- This image is served from the project
349
- {" "}
350
- <code>
351
- assets/
352
- </code>
353
- {" "}
354
- folder using the
355
- {" "}
356
- <code>
357
- /static/assets/
358
- </code>
359
- {" "}
360
- path.
361
- </p>
362
- </div>
363
- <div
364
- style={{"marginTop": "2rem"}}
365
- >
366
- <h3>
367
- Counter with pure CSS classes
368
- </h3>
369
- <p>
370
- You've clicked the burger
371
- {" "}
372
- <strong>
373
- {count}
374
- </strong>
375
- {" "}
376
- times.
377
- </p>
378
- <button
379
- onClick={lambda e: any -> None{ count = count + 1;} }
380
- style={{
381
- "padding": "0.6rem 1.4rem",
382
- "fontSize": "1rem",
383
- "backgroundColor": "#ff6b35",
384
- "color": "white",
385
- "border": "none",
386
- "borderRadius": "6px",
387
- "cursor": "pointer",
388
- "boxShadow": "0 2px 4px rgba(0,0,0,0.2)"
389
- }}
390
- >
391
- Click the Burger! 🍔
392
- </button>
393
- </div>
394
- <div
395
- style={{"marginTop": "2rem"}}
396
- >
397
- <h3>
398
- Backend Walkers
399
- </h3>
400
- <p>
401
- Basic example walkers:
402
- {" "}
403
- <code>
404
- ping_server
405
- </code>
406
- {" "}
407
- and
408
- {" "}
409
- <code>
410
- get_server_message
411
- </code>
412
- </p>
413
- <button
414
- onClick={lambda e: any -> None{ handlePing();} }
415
- style={{
416
- "padding": "0.5rem 1.2rem",
417
- "marginRight": "0.75rem",
418
- "backgroundColor": "#3b82f6",
419
- "color": "white",
420
- "border": "none",
421
- "borderRadius": "6px",
422
- "cursor": "pointer"
423
- }}
424
- >
425
- Ping Backend
426
- </button>
427
- <button
428
- onClick={lambda e: any -> None{ handleCreateSampleTodo();} }
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
429
271
  style={{
430
- "padding": "0.5rem 1.2rem",
431
- "backgroundColor": "#10b981",
432
- "color": "white",
433
- "border": "none",
434
- "borderRadius": "6px",
435
- "cursor": "pointer"
272
+ "padding": "2rem",
273
+ "fontFamily": "system-ui, -apple-system, sans-serif"
436
274
  }}
437
275
  >
438
- Create Sample Todo
439
- </button>
440
- {pingResult
441
- and (
442
- <span
443
- style={{"marginLeft": "0.5rem", "color": "#374151"}}
444
- >
445
- Result:
276
+ <h1>
277
+ 🍔 Router + Styling + Assets Demo
278
+ </h1>
279
+ <p>
280
+ This home page combines
446
281
  {" "}
447
- <code>
448
- {pingResult}
449
- </code>
450
- </span>
451
- )}
452
- {serverMessage
453
- and (
454
- <p
455
- style={{"marginTop": "0.75rem", "color": "#374151"}}
456
- >
457
- Message:
282
+ <strong>
283
+ React Router,
284
+ </strong>
285
+ {" "}
286
+ <strong>
287
+ pure CSS styling,
288
+ </strong>
289
+ {" "}
290
+ <strong>
291
+ staticassets
292
+ </strong>
458
293
  {" "}
459
- <code>
460
- {serverMessage}
461
- </code>
294
+ and
295
+ {" "}
296
+ <strong>
297
+ nested folder imports
298
+ </strong>
462
299
  </p>
463
- )}
464
- {lastTodoMessage
465
- and (
466
- <p
467
- style={{"marginTop": "0.5rem", "color": "#111827"}}
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"
468
329
  >
469
- {lastTodoMessage}
470
- </p>
471
- )}
472
- </div>
473
- <div
474
- style={{"marginTop": "2rem"}}
475
- >
476
- <h3>
477
- Web Worker
478
- </h3>
479
- <p>
480
- This demonstrates how to communicate with a
481
- {" "}
482
- <strong>Python backend worker</strong>
483
- {" "}
484
- using Web Workers for asynchronous processing.
485
- </p>
486
- <p
487
- style={{"fontSize": "0.9rem", "color": "#666", "marginTop": "0.5rem"}}
488
- >
489
- File:
490
- {" "}
491
- <code>
492
- worker.py
493
- </code>
494
- {" "}
495
- — Runs in a separate thread to avoid blocking the UI.
496
- </p>
497
- <button
498
- onClick={lambda -> None { handleClick(); }}
499
- style={{
500
- "padding": "0.5rem 1.2rem",
501
- "marginRight": "0.75rem",
502
- "backgroundColor": "#d73bf6ff",
503
- "color": "white",
504
- "border": "none",
505
- "borderRadius": "6px",
506
- "cursor": "pointer"
507
- }}
508
- >
509
- Call Python Worker
510
- </button>
511
- {message && (
512
- <p style={{ marginTop: "1rem", fontWeight: "bold" }}>
513
- {message}
514
- </p>
515
- )}
516
- </div>
517
- </div>;
518
- }
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
+ }
519
510
 
520
511
  def:pub app -> any {
521
- return <Router>
522
- <div
523
- style={{"fontFamily": "system-ui, -apple-system, sans-serif"}}
524
- >
525
- <Navigation />
526
- <div
527
- style={{
528
- "maxWidth": "960px",
529
- "margin": "0 auto",
530
- "padding": "0 1rem 3rem 1rem"
531
- }}
532
- >
533
- <Routes>
534
- <Route
535
- path="/"
536
- element={<HomePage />}
537
- />
538
- <Route
539
- path="/login"
540
- element={<LoginPage />}
541
- />
542
- <Route
543
- path="/signup"
544
- element={<SignupPage />}
545
- />
546
- <Route
547
- path="/nested"
548
- element={<NestedImportsDemo />}
549
- />
550
- <Route
551
- path="/features-test"
552
- element={<FeaturesTest />}
553
- />
554
- <Route
555
- path="/landing"
556
- element={<LandingPage />}
557
- />
558
- <Route
559
- path="/budget-planner"
560
- element={<BudgetProvider>
561
- <BudgetPlanner />
562
- </BudgetProvider>}
563
- />
564
- <Route
565
- path="*"
566
- element={<NotFound />}
567
- />
568
- </Routes>
569
- </div>
570
- </div>
571
- </Router>;
572
- }
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
+ }
573
542
  }