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.
- jac_client/examples/all-in-one/button.jac +4 -3
- jac_client/examples/all-in-one/components/CategoryFilter.jac +36 -24
- jac_client/examples/all-in-one/components/Header.jac +12 -8
- jac_client/examples/all-in-one/components/ProfitOverview.jac +49 -35
- jac_client/examples/all-in-one/components/Summary.jac +59 -36
- jac_client/examples/all-in-one/components/TransactionForm.jac +142 -112
- jac_client/examples/all-in-one/components/TransactionItem.jac +37 -30
- jac_client/examples/all-in-one/components/TransactionList.jac +33 -26
- jac_client/examples/all-in-one/components/button.jac +4 -3
- jac_client/examples/all-in-one/components/navigation.jac +111 -117
- jac_client/examples/all-in-one/constants/categories.jac +23 -24
- jac_client/examples/all-in-one/constants/clients.jac +7 -8
- jac_client/examples/all-in-one/context/BudgetContext.jac +9 -6
- jac_client/examples/all-in-one/hooks/useBudget.jac +18 -12
- jac_client/examples/all-in-one/hooks/useLocalStorage.jac +14 -13
- jac_client/examples/all-in-one/main.jac +340 -371
- jac_client/examples/all-in-one/pages/BudgetPlanner.jac +19 -12
- jac_client/examples/all-in-one/pages/FeaturesTest.jac +31 -15
- jac_client/examples/all-in-one/pages/LandingPage.jac +113 -90
- jac_client/examples/all-in-one/pages/budget_planner_ui.cl.jac +34 -39
- jac_client/examples/all-in-one/pages/features_test_ui.cl.jac +464 -352
- jac_client/examples/all-in-one/pages/loginPage.jac +114 -119
- jac_client/examples/all-in-one/pages/nestedDemo.jac +43 -50
- jac_client/examples/all-in-one/pages/notFound.jac +14 -15
- jac_client/examples/all-in-one/pages/signupPage.jac +113 -119
- jac_client/examples/all-in-one/utils/formatters.jac +5 -8
- jac_client/examples/asset-serving/css-with-image/main.jac +77 -73
- jac_client/examples/asset-serving/image-asset/main.jac +47 -46
- jac_client/examples/asset-serving/import-alias/main.jac +93 -95
- jac_client/examples/basic/main.jac +17 -15
- jac_client/examples/basic-auth/main.jac +246 -254
- jac_client/examples/basic-auth-with-router/main.jac +272 -285
- jac_client/examples/basic-full-stack/main.jac +245 -242
- jac_client/examples/css-styling/js-styling/main.jac +41 -62
- jac_client/examples/css-styling/material-ui/main.jac +90 -90
- jac_client/examples/css-styling/pure-css/main.jac +35 -44
- jac_client/examples/css-styling/sass-example/main.jac +35 -44
- jac_client/examples/css-styling/styled-components/main.jac +38 -47
- jac_client/examples/css-styling/tailwind-example/main.jac +54 -43
- jac_client/examples/full-stack-with-auth/main.jac +407 -433
- jac_client/examples/little-x/main.jac +306 -344
- jac_client/examples/little-x/src/submit-button.jac +15 -14
- jac_client/examples/nested-folders/nested-advance/main.jac +18 -27
- jac_client/examples/nested-folders/nested-advance/src/ButtonRoot.jac +4 -6
- jac_client/examples/nested-folders/nested-advance/src/level1/ButtonSecondL.jac +9 -13
- jac_client/examples/nested-folders/nested-advance/src/level1/Card.jac +29 -32
- jac_client/examples/nested-folders/nested-advance/src/level1/level2/ButtonThirdL.jac +12 -18
- jac_client/examples/nested-folders/nested-basic/main.jac +7 -5
- jac_client/examples/nested-folders/nested-basic/src/button.jac +4 -3
- jac_client/examples/nested-folders/nested-basic/src/components/button.jac +4 -3
- jac_client/examples/ts-support/main.jac +26 -26
- jac_client/examples/with-router/main.jac +186 -223
- jac_client/plugin/client_runtime.cl.jac +5 -3
- jac_client/plugin/impl/client_runtime.impl.jac +1 -1
- jac_client/plugin/plugin_config.jac +53 -99
- jac_client/plugin/src/__init__.jac +0 -2
- jac_client/plugin/src/compiler.jac +0 -1
- jac_client/plugin/src/impl/compiler.impl.jac +49 -17
- jac_client/plugin/src/impl/jac_to_js.impl.jac +5 -1
- jac_client/plugin/src/impl/package_installer.impl.jac +20 -20
- jac_client/plugin/src/impl/vite_bundler.impl.jac +146 -84
- jac_client/plugin/src/targets/impl/desktop_target.impl.jac +54 -41
- jac_client/plugin/utils/__init__.jac +3 -0
- jac_client/plugin/utils/bun_installer.jac +16 -0
- jac_client/plugin/utils/client_deps.jac +14 -0
- jac_client/plugin/utils/impl/bun_installer.impl.jac +99 -0
- jac_client/plugin/utils/impl/client_deps.impl.jac +73 -0
- jac_client/templates/client.jacpack +0 -4
- jac_client/templates/fullstack.jacpack +1 -5
- jac_client/tests/conftest.py +56 -41
- jac_client/tests/fixtures/spawn_test/app.jac +49 -52
- jac_client/tests/fixtures/with-ts/app.jac +27 -27
- jac_client/tests/test_cli.py +71 -6
- jac_client/tests/test_helpers.py +11 -18
- jac_client/tests/test_it.py +1 -1
- {jac_client-0.2.10.dist-info → jac_client-0.2.12.dist-info}/METADATA +5 -5
- jac_client-0.2.12.dist-info/RECORD +115 -0
- {jac_client-0.2.10.dist-info → jac_client-0.2.12.dist-info}/WHEEL +1 -1
- jac_client/plugin/src/babel_processor.jac +0 -18
- jac_client/plugin/src/impl/babel_processor.impl.jac +0 -89
- jac_client/plugin/utils/impl/node_installer.impl.jac +0 -249
- jac_client/plugin/utils/node_installer.jac +0 -41
- jac_client-0.2.10.dist-info/RECORD +0 -115
- {jac_client-0.2.10.dist-info → jac_client-0.2.12.dist-info}/entry_points.txt +0 -0
- {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
|
|
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
|
|
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
|
|
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
|
-
|
|
48
|
-
|
|
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
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
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
|
|
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
|
-
|
|
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 {
|
|
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 {
|
|
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
|
-
|
|
213
|
-
|
|
214
|
-
|
|
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
|
-
|
|
234
|
-
|
|
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
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
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
|
-
|
|
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
|
-
|
|
253
|
-
|
|
254
|
-
|
|
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
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
}
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
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 <img> 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": "
|
|
431
|
-
"
|
|
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
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
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
|
-
<
|
|
448
|
-
|
|
449
|
-
</
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
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
|
-
|
|
460
|
-
|
|
461
|
-
|
|
294
|
+
and
|
|
295
|
+
{" "}
|
|
296
|
+
<strong>
|
|
297
|
+
nested folder imports
|
|
298
|
+
</strong>
|
|
462
299
|
</p>
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
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
|
-
{
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
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 <img> 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
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
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
|
}
|