jac-client 0.2.0__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 (72) hide show
  1. jac_client/docs/README.md +659 -0
  2. jac_client/docs/advanced-state.md +1266 -0
  3. jac_client/docs/assets/pipe_line.png +0 -0
  4. jac_client/docs/guide-example/intro.md +117 -0
  5. jac_client/docs/guide-example/step-01-setup.md +260 -0
  6. jac_client/docs/guide-example/step-02-components.md +416 -0
  7. jac_client/docs/guide-example/step-03-styling.md +478 -0
  8. jac_client/docs/guide-example/step-04-todo-ui.md +477 -0
  9. jac_client/docs/guide-example/step-05-local-state.md +530 -0
  10. jac_client/docs/guide-example/step-06-events.md +750 -0
  11. jac_client/docs/guide-example/step-07-effects.md +469 -0
  12. jac_client/docs/guide-example/step-08-walkers.md +534 -0
  13. jac_client/docs/guide-example/step-09-authentication.md +586 -0
  14. jac_client/docs/guide-example/step-10-routing.md +540 -0
  15. jac_client/docs/guide-example/step-11-final.md +964 -0
  16. jac_client/docs/imports.md +1142 -0
  17. jac_client/docs/lifecycle-hooks.md +774 -0
  18. jac_client/docs/routing.md +660 -0
  19. jac_client/examples/basic/.babelrc +9 -0
  20. jac_client/examples/basic/README.md +16 -0
  21. jac_client/examples/basic/app.jac +16 -0
  22. jac_client/examples/basic/package.json +27 -0
  23. jac_client/examples/basic/vite.config.js +28 -0
  24. jac_client/examples/basic-auth/.babelrc +9 -0
  25. jac_client/examples/basic-auth/README.md +16 -0
  26. jac_client/examples/basic-auth/app.jac +308 -0
  27. jac_client/examples/basic-auth/package.json +27 -0
  28. jac_client/examples/basic-auth/vite.config.js +28 -0
  29. jac_client/examples/basic-auth-with-router/.babelrc +9 -0
  30. jac_client/examples/basic-auth-with-router/README.md +60 -0
  31. jac_client/examples/basic-auth-with-router/app.jac +464 -0
  32. jac_client/examples/basic-auth-with-router/package.json +28 -0
  33. jac_client/examples/basic-auth-with-router/vite.config.js +28 -0
  34. jac_client/examples/basic-full-stack/.babelrc +9 -0
  35. jac_client/examples/basic-full-stack/README.md +18 -0
  36. jac_client/examples/basic-full-stack/app.jac +320 -0
  37. jac_client/examples/basic-full-stack/package.json +28 -0
  38. jac_client/examples/basic-full-stack/vite.config.js +28 -0
  39. jac_client/examples/full-stack-with-auth/.babelrc +9 -0
  40. jac_client/examples/full-stack-with-auth/README.md +16 -0
  41. jac_client/examples/full-stack-with-auth/app.jac +735 -0
  42. jac_client/examples/full-stack-with-auth/package.json +28 -0
  43. jac_client/examples/full-stack-with-auth/vite.config.js +30 -0
  44. jac_client/examples/little-x/app.jac +615 -0
  45. jac_client/examples/little-x/package.json +23 -0
  46. jac_client/examples/little-x/submit-button.jac +8 -0
  47. jac_client/examples/with-router/.babelrc +9 -0
  48. jac_client/examples/with-router/README.md +17 -0
  49. jac_client/examples/with-router/app.jac +323 -0
  50. jac_client/examples/with-router/package.json +28 -0
  51. jac_client/examples/with-router/vite.config.js +28 -0
  52. jac_client/plugin/cli.py +239 -0
  53. jac_client/plugin/client.py +89 -0
  54. jac_client/plugin/client_runtime.jac +234 -0
  55. jac_client/plugin/vite_client_bundle.py +355 -0
  56. jac_client/tests/__init__.py +2 -0
  57. jac_client/tests/fixtures/basic-app/app.jac +18 -0
  58. jac_client/tests/fixtures/client_app_with_antd/app.jac +28 -0
  59. jac_client/tests/fixtures/js_import/app.jac +30 -0
  60. jac_client/tests/fixtures/js_import/utils.js +22 -0
  61. jac_client/tests/fixtures/package-lock.json +329 -0
  62. jac_client/tests/fixtures/package.json +11 -0
  63. jac_client/tests/fixtures/relative_import/app.jac +13 -0
  64. jac_client/tests/fixtures/relative_import/button.jac +6 -0
  65. jac_client/tests/fixtures/spawn_test/app.jac +133 -0
  66. jac_client/tests/fixtures/test_fragments_spread/app.jac +53 -0
  67. jac_client/tests/test_cl.py +476 -0
  68. jac_client/tests/test_create_jac_app.py +139 -0
  69. jac_client-0.2.0.dist-info/METADATA +182 -0
  70. jac_client-0.2.0.dist-info/RECORD +72 -0
  71. jac_client-0.2.0.dist-info/WHEEL +4 -0
  72. jac_client-0.2.0.dist-info/entry_points.txt +4 -0
@@ -0,0 +1,1142 @@
1
+ # Imports in Jac: Working with Modules and Libraries
2
+
3
+ Learn how to import third-party libraries, other Jac files, and JavaScript modules in your Jac applications.
4
+
5
+ ---
6
+
7
+ ## 📚 Table of Contents
8
+
9
+ - [Importing Jac-Client Utilities](#importing-jac-client-utilities)
10
+ - [Working with Third-Party Node Modules](#working-with-third-party-node-modules)
11
+ - [Installing Packages](#installing-packages)
12
+ - [Importing Third-Party Libraries](#importing-third-party-libraries)
13
+ - [Importing Other Jac Files](#importing-other-jac-files)
14
+ - [Importing JavaScript Files](#importing-javascript-files)
15
+ - [Best Practices](#best-practices)
16
+
17
+ ---
18
+
19
+ ## Importing Jac-Client Utilities
20
+
21
+ Jac-Client provides built-in utilities for authentication, backend communication, and routing through the `@jac-client/utils` package.
22
+
23
+ ### Available Utilities
24
+
25
+ ```jac
26
+ cl import from '@jac-client/utils' {
27
+ jacSpawn, # Call backend walkers
28
+ jacLogin, # Login user
29
+ jacSignup, # Register new user
30
+ jacLogout, # Logout user
31
+ jacIsLoggedIn, # Check if user is logged in
32
+ navigate, # Navigate to routes
33
+ Link, # Link component for routing
34
+ }
35
+ ```
36
+
37
+ ### Backend Communication
38
+
39
+ #### `jacSpawn` - Call Backend Walkers
40
+
41
+ The `jacSpawn` function lets you call backend walkers from the frontend:
42
+
43
+ ```jac
44
+ cl import from react { useState, useEffect }
45
+ cl import from '@jac-client/utils' { jacSpawn }
46
+
47
+ cl {
48
+ def TodoApp() -> any {
49
+ let [todos, setTodos] = useState([]);
50
+
51
+ useEffect(lambda -> None {
52
+ async def loadTodos() -> None {
53
+ # Call backend walker
54
+ result = await jacSpawn("read_todos", "", {});
55
+ setTodos(result.reports);
56
+ }
57
+ loadTodos();
58
+ }, []);
59
+
60
+ async def addTodo(text: str) -> None {
61
+ # Call walker with parameters
62
+ new_todo = await jacSpawn("create_todo", "", {"text": text});
63
+ setTodos(todos.concat([new_todo]));
64
+ }
65
+
66
+ return <div>{/* UI */}</div>;
67
+ }
68
+ }
69
+ ```
70
+
71
+ **Signature:**
72
+ ```jac
73
+ jacSpawn(walker_name: str, node_id: str, params: dict) -> any
74
+ ```
75
+
76
+ - `walker_name`: Name of the backend walker to call
77
+ - `node_id`: Target node ID (use `""` for root)
78
+ - `params`: Dictionary of parameters to pass to the walker
79
+
80
+ ### Authentication Functions
81
+
82
+ #### `jacLogin` - User Login
83
+
84
+ ```jac
85
+ cl import from '@jac-client/utils' { jacLogin, navigate }
86
+
87
+ cl {
88
+ def LoginForm() -> any {
89
+ async def handleLogin(e: any) -> None {
90
+ e.preventDefault();
91
+ username = document.getElementById("username").value;
92
+ password = document.getElementById("password").value;
93
+
94
+ success = await jacLogin(username, password);
95
+
96
+ if success {
97
+ navigate("/dashboard");
98
+ } else {
99
+ alert("Login failed");
100
+ }
101
+ }
102
+
103
+ return <form onSubmit={handleLogin}>
104
+ <input id="username" type="text" placeholder="Username" />
105
+ <input id="password" type="password" placeholder="Password" />
106
+ <button type="submit">Login</button>
107
+ </form>;
108
+ }
109
+ }
110
+ ```
111
+
112
+ #### `jacSignup` - User Registration
113
+
114
+ ```jac
115
+ cl import from '@jac-client/utils' { jacSignup, navigate }
116
+
117
+ cl {
118
+ def SignupForm() -> any {
119
+ async def handleSignup(e: any) -> None {
120
+ e.preventDefault();
121
+ username = document.getElementById("username").value;
122
+ password = document.getElementById("password").value;
123
+
124
+ result = await jacSignup(username, password);
125
+
126
+ if result.success {
127
+ alert("Account created successfully!");
128
+ navigate("/login");
129
+ } else {
130
+ alert(result.error or "Signup failed");
131
+ }
132
+ }
133
+
134
+ return <form onSubmit={handleSignup}>
135
+ <input id="username" type="text" placeholder="Username" />
136
+ <input id="password" type="password" placeholder="Password" />
137
+ <button type="submit">Sign Up</button>
138
+ </form>;
139
+ }
140
+ }
141
+ ```
142
+
143
+ #### `jacLogout` - User Logout
144
+
145
+ ```jac
146
+ cl import from '@jac-client/utils' { jacLogout, navigate }
147
+
148
+ cl {
149
+ def Header() -> any {
150
+ def handleLogout() -> None {
151
+ jacLogout();
152
+ navigate("/login");
153
+ }
154
+
155
+ return <header>
156
+ <button onClick={handleLogout}>Logout</button>
157
+ </header>;
158
+ }
159
+ }
160
+ ```
161
+
162
+ #### `jacIsLoggedIn` - Check Authentication Status
163
+
164
+ ```jac
165
+ cl import from '@jac-client/utils' { jacIsLoggedIn, navigate }
166
+
167
+ cl {
168
+ def ProtectedPage() -> any {
169
+ if not jacIsLoggedIn() {
170
+ navigate("/login");
171
+ return <div>Redirecting...</div>;
172
+ }
173
+
174
+ return <div>
175
+ <h1>Protected Content</h1>
176
+ <p>Only logged-in users can see this!</p>
177
+ </div>;
178
+ }
179
+ }
180
+ ```
181
+
182
+ ### Routing Functions
183
+
184
+ #### `navigate` - Programmatic Navigation
185
+
186
+ ```jac
187
+ cl import from '@jac-client/utils' { navigate }
188
+
189
+ cl {
190
+ def MyComponent() -> any {
191
+ def goToHome() -> None {
192
+ navigate("/");
193
+ }
194
+
195
+ def goToProfile() -> None {
196
+ navigate("/profile");
197
+ }
198
+
199
+ return <div>
200
+ <button onClick={goToHome}>Go Home</button>
201
+ <button onClick={goToProfile}>Go to Profile</button>
202
+ </div>;
203
+ }
204
+ }
205
+ ```
206
+
207
+ #### `Link` - Declarative Navigation
208
+
209
+ ```jac
210
+ cl import from '@jac-client/utils' { Link }
211
+
212
+ cl {
213
+ def Navigation() -> any {
214
+ return <nav>
215
+ <Link href="/">Home</Link>
216
+ <Link href="/about">About</Link>
217
+ <Link href="/contact">Contact</Link>
218
+ </nav>;
219
+ }
220
+ }
221
+ ```
222
+
223
+ #### `initRouter` - Initialize Router
224
+
225
+ ```jac
226
+ cl import from '@jac-client/utils' { initRouter, jacIsLoggedIn }
227
+
228
+ cl {
229
+ def App() -> any {
230
+ # Define routes
231
+ routes = [
232
+ {
233
+ "path": "/",
234
+ "component": lambda -> any { return <HomePage />; },
235
+ "guard": None
236
+ },
237
+ {
238
+ "path": "/dashboard",
239
+ "component": lambda -> any { return <Dashboard />; },
240
+ "guard": jacIsLoggedIn # Require authentication
241
+ },
242
+ {
243
+ "path": "/login",
244
+ "component": lambda -> any { return <LoginPage />; },
245
+ "guard": None
246
+ }
247
+ ];
248
+
249
+ # Initialize router with default route
250
+ router = initRouter(routes, "/");
251
+
252
+ return <div>
253
+ <Navigation />
254
+ {router.render()}
255
+ </div>;
256
+ }
257
+ }
258
+ ```
259
+
260
+ ### Complete Authentication Example
261
+
262
+ ```jac
263
+ cl import from react { useState }
264
+ cl import from '@jac-client/utils' {
265
+ jacLogin,
266
+ jacSignup,
267
+ jacLogout,
268
+ jacIsLoggedIn,
269
+ navigate,
270
+ Link,
271
+ initRouter
272
+ }
273
+
274
+ cl {
275
+ def LoginPage() -> any {
276
+ let [error, setError] = useState("");
277
+
278
+ async def handleLogin(e: any) -> None {
279
+ e.preventDefault();
280
+ username = document.getElementById("username").value;
281
+ password = document.getElementById("password").value;
282
+
283
+ success = await jacLogin(username, password);
284
+
285
+ if success {
286
+ navigate("/dashboard");
287
+ } else {
288
+ setError("Invalid credentials");
289
+ }
290
+ }
291
+
292
+ return <div style={{"maxWidth": "400px", "margin": "50px auto"}}>
293
+ <h1>Login</h1>
294
+ {error and <p style={{"color": "red"}}>{error}</p>}
295
+ <form onSubmit={handleLogin}>
296
+ <input
297
+ id="username"
298
+ type="text"
299
+ placeholder="Username"
300
+ style={{"width": "100%", "padding": "10px", "marginBottom": "10px"}}
301
+ />
302
+ <input
303
+ id="password"
304
+ type="password"
305
+ placeholder="Password"
306
+ style={{"width": "100%", "padding": "10px", "marginBottom": "10px"}}
307
+ />
308
+ <button type="submit" style={{"width": "100%", "padding": "10px"}}>
309
+ Login
310
+ </button>
311
+ </form>
312
+ <p>
313
+ Don't have an account? <Link href="/signup">Sign up</Link>
314
+ </p>
315
+ </div>;
316
+ }
317
+
318
+ def Dashboard() -> any {
319
+ if not jacIsLoggedIn() {
320
+ navigate("/login");
321
+ return <div>Redirecting...</div>;
322
+ }
323
+
324
+ def handleLogout() -> None {
325
+ jacLogout();
326
+ navigate("/login");
327
+ }
328
+
329
+ return <div style={{"padding": "20px"}}>
330
+ <h1>Dashboard</h1>
331
+ <p>Welcome! You are logged in.</p>
332
+ <button onClick={handleLogout}>Logout</button>
333
+ </div>;
334
+ }
335
+
336
+ def App() -> any {
337
+ routes = [
338
+ {"path": "/login", "component": lambda -> any { return LoginPage(); }, "guard": None},
339
+ {"path": "/dashboard", "component": lambda -> any { return Dashboard(); }, "guard": jacIsLoggedIn}
340
+ ];
341
+
342
+ router = initRouter(routes, "/login");
343
+
344
+ return <div>
345
+ {router.render()}
346
+ </div>;
347
+ }
348
+ }
349
+ ```
350
+
351
+ ### Common Patterns
352
+
353
+ #### Pattern 1: Protected Route with Loading State
354
+
355
+ ```jac
356
+ cl import from react { useState, useEffect }
357
+ cl import from '@jac-client/utils' { jacIsLoggedIn, jacSpawn, navigate }
358
+
359
+ cl {
360
+ def ProtectedDashboard() -> any {
361
+ let [user, setUser] = useState(None);
362
+ let [loading, setLoading] = useState(True);
363
+
364
+ useEffect(lambda -> None {
365
+ if not jacIsLoggedIn() {
366
+ navigate("/login");
367
+ return;
368
+ }
369
+
370
+ async def loadUserData() -> None {
371
+ result = await jacSpawn("get_user_profile", "", {});
372
+ setUser(result);
373
+ setLoading(False);
374
+ }
375
+ loadUserData();
376
+ }, []);
377
+
378
+ if loading { return <div>Loading...</div>; }
379
+
380
+ return <div>
381
+ <h1>Welcome, {user.name}!</h1>
382
+ </div>;
383
+ }
384
+ }
385
+ ```
386
+
387
+ #### Pattern 2: Form with Backend Integration
388
+
389
+ ```jac
390
+ cl import from react { useState }
391
+ cl import from '@jac-client/utils' { jacSpawn }
392
+
393
+ cl {
394
+ def CreateTodoForm() -> any {
395
+ let [text, setText] = useState("");
396
+ let [loading, setLoading] = useState(False);
397
+
398
+ async def handleSubmit(e: any) -> None {
399
+ e.preventDefault();
400
+ if not text.trim() { return; }
401
+
402
+ setLoading(True);
403
+ try {
404
+ await jacSpawn("create_todo", "", {"text": text});
405
+ setText(""); # Clear form
406
+ alert("Todo created!");
407
+ } catch (err) {
408
+ alert("Failed to create todo");
409
+ } finally {
410
+ setLoading(False);
411
+ }
412
+ }
413
+
414
+ return <form onSubmit={handleSubmit}>
415
+ <input
416
+ value={text}
417
+ onChange={lambda e: any -> None { setText(e.target.value); }}
418
+ placeholder="Enter todo..."
419
+ disabled={loading}
420
+ />
421
+ <button type="submit" disabled={loading}>
422
+ {"Creating..." if loading else "Add Todo"}
423
+ </button>
424
+ </form>;
425
+ }
426
+ }
427
+ ```
428
+
429
+ #### Pattern 3: Navigation with Auth Check
430
+
431
+ ```jac
432
+ cl import from '@jac-client/utils' { Link, jacIsLoggedIn, jacLogout, navigate }
433
+
434
+ cl {
435
+ def Navigation() -> any {
436
+ isLoggedIn = jacIsLoggedIn();
437
+
438
+ def handleLogout() -> None {
439
+ jacLogout();
440
+ navigate("/");
441
+ }
442
+
443
+ return <nav style={{"padding": "10px", "background": "#f5f5f5"}}>
444
+ <Link href="/">Home</Link>
445
+ {isLoggedIn ? (
446
+ <>
447
+ <Link href="/dashboard">Dashboard</Link>
448
+ <button onClick={handleLogout}>Logout</button>
449
+ </>
450
+ ) : (
451
+ <>
452
+ <Link href="/login">Login</Link>
453
+ <Link href="/signup">Sign Up</Link>
454
+ </>
455
+ )}
456
+ </nav>;
457
+ }
458
+ }
459
+ ```
460
+
461
+ ---
462
+
463
+ ## Working with Third-Party Node Modules
464
+
465
+ Jac supports importing any npm package that's compatible with ES modules. This includes popular libraries like React UI frameworks, utility libraries, and more.
466
+
467
+ ### Prerequisites
468
+
469
+ Before importing third-party libraries, you need:
470
+
471
+ 1. **Node.js** installed (for npm)
472
+ 2. **package.json** in your project root
473
+ 3. **Vite** configured in your project (automatically set up with `jac create_jac_app`)
474
+
475
+ ### Why Third-Party Libraries?
476
+
477
+ Third-party libraries provide:
478
+ - **UI Components**: React component libraries (Ant Design, Material-UI, etc.)
479
+ - **Utilities**: Helper functions and utilities (lodash, date-fns, etc.)
480
+ - **Tools**: Development and production tools
481
+ - **Reusability**: Community-maintained, tested code
482
+
483
+ ---
484
+
485
+ ## Installing Packages
486
+
487
+ ### Step 1: Install with npm
488
+
489
+ Use npm to install packages into your project:
490
+
491
+ ```bash
492
+ # Install a package
493
+ npm install antd
494
+
495
+ # Install a specific version
496
+ npm install antd@5.12.8
497
+
498
+ # Install as dev dependency (development tools)
499
+ npm install --save-dev vite
500
+
501
+ # Install multiple packages
502
+ npm install antd react-icons date-fns
503
+ ```
504
+
505
+ **What Happens:**
506
+ - Package is downloaded to `node_modules/`
507
+ - Package is added to `package.json` dependencies
508
+ - Package becomes available for import
509
+
510
+ ### Step 2: Verify Installation
511
+
512
+ Check that the package is installed:
513
+
514
+ ```bash
515
+ # Check package.json
516
+ cat package.json
517
+
518
+ # Verify node_modules exists
519
+ ls node_modules | grep antd
520
+ ```
521
+
522
+ **package.json Example:**
523
+ ```json
524
+ {
525
+ "name": "my-app",
526
+ "version": "1.0.0",
527
+ "dependencies": {
528
+ "antd": "^5.12.8",
529
+ "react-icons": "^4.12.0"
530
+ },
531
+ "devDependencies": {
532
+ "vite": "^5.0.0"
533
+ }
534
+ }
535
+ ```
536
+
537
+ ---
538
+
539
+ ## Importing Third-Party Libraries
540
+
541
+ Once a package is installed, you can import it using Jac's `cl import` syntax.
542
+
543
+ ### Basic Import Syntax
544
+
545
+ ```jac
546
+ cl import from package_name {
547
+ Component1,
548
+ Component2,
549
+ Function1,
550
+ Constant1
551
+ }
552
+ ```
553
+
554
+ **Key Points:**
555
+ - Use `cl import` for client-side imports
556
+ - `from package_name` - the npm package name (no quotes)
557
+ - `{ ... }` - list of exports to import (comma-separated)
558
+
559
+ ### Example: Importing Ant Design
560
+
561
+ ```bash
562
+ # First, install Ant Design
563
+ npm install antd
564
+ ```
565
+
566
+ ```jac
567
+ """Importing Ant Design components."""
568
+
569
+ cl import from antd { Button, Input, Card, Typography, Space }
570
+
571
+ cl {
572
+ def MyApp() -> any {
573
+ return <div>
574
+ <Card title="Welcome" style={{"maxWidth": "400px", "margin": "50px auto"}}>
575
+ <Card.Meta title="Hello" description="Welcome to Jac!" />
576
+ <Space direction="vertical" style={{"width": "100%"}}>
577
+ <Input placeholder="Enter text..." />
578
+ <Button type="primary" style={{"width": "100%"}}>Submit</Button>
579
+ <Button color="default" variant="dashed">Dashed</Button>
580
+ <Button color="default" variant="filled">Filled</Button>
581
+ <Button color="default" variant="text">Text</Button>
582
+ <Button color="default" variant="link">Link</Button>
583
+ </Space>
584
+ </Card>
585
+ </div>;
586
+ }
587
+
588
+ def jac_app() -> any {
589
+ return MyApp();
590
+ }
591
+ }
592
+ ```
593
+
594
+ ### Example: Importing React Hooks
595
+
596
+ React hooks can be imported and used directly in Jac:
597
+
598
+ ```bash
599
+ # React is typically included by default, but if needed:
600
+ npm install react
601
+ ```
602
+
603
+ ```jac
604
+ """Using React hooks in Jac."""
605
+
606
+ cl import from react { useState, useEffect }
607
+
608
+ cl {
609
+ def Counter() -> any {
610
+ let [count, setCount] = useState(0);
611
+
612
+ useEffect(lambda -> None {
613
+ console.log("Count: ", count);
614
+ }, [count]);
615
+
616
+ return <div>
617
+ <h1>Count: {count}</h1>
618
+ <button onClick={lambda e: any -> None {
619
+ setCount(count + 1);
620
+ }}>
621
+ Increment
622
+ </button>
623
+ </div>;
624
+ }
625
+ }
626
+ ```
627
+
628
+ ### Example: Importing Utility Libraries
629
+
630
+ Lodash is a popular utility library with many helpful functions:
631
+
632
+ ```bash
633
+ # Install lodash
634
+ npm install lodash
635
+ ```
636
+
637
+ ```jac
638
+ """Importing lodash utilities."""
639
+
640
+ cl import from lodash { * as _ }
641
+
642
+ cl {
643
+ def RandomQuoteCard() -> any {
644
+ suggestions = ['good luck', 'have fun', 'enjoy the ride'];
645
+ randomSuggestion = _.sample(suggestions); # Pick random item
646
+
647
+ return <div>
648
+ <h2>{randomSuggestion}</h2>
649
+ <p>Powered by Lodash!</p>
650
+ </div>;
651
+ }
652
+ }
653
+ ```
654
+
655
+ ### Example: Importing Specialized Libraries
656
+
657
+ You can import specialized libraries like pluralize or animation libraries:
658
+
659
+ ```bash
660
+ # Install packages
661
+ npm install pluralize
662
+ npm install react-animated-components
663
+ ```
664
+
665
+ ```jac
666
+ """Importing specialized libraries."""
667
+
668
+ cl import from pluralize { default as pluralize }
669
+ cl import from 'react-animated-components' { Rotate }
670
+
671
+ cl {
672
+ def AnimatedDemo() -> any {
673
+ word = "tweet";
674
+ count = 5;
675
+ pluralWord = pluralize(word, count);
676
+
677
+ return <div>
678
+ <h1>{count} {pluralWord}</h1>
679
+ <Rotate>
680
+ <span style={{"fontSize": "48px"}}>😂</span>
681
+ </Rotate>
682
+ </div>;
683
+ }
684
+ }
685
+ ```
686
+
687
+ ### Example: Importing Multiple Components
688
+
689
+ ```jac
690
+ """Importing multiple components from a library."""
691
+
692
+ cl import from antd {
693
+ Button,
694
+ Card,
695
+ Input,
696
+ Form,
697
+ Select,
698
+ DatePicker,
699
+ Table
700
+ }
701
+
702
+ cl def FormExample() -> any {
703
+ return <Card title="Form Example">
704
+ <Form>
705
+ <Input placeholder="Name" />
706
+ <Select placeholder="Select option">
707
+ <option value="1">Option 1</option>
708
+ <option value="2">Option 2</option>
709
+ </Select>
710
+ <DatePicker />
711
+ <Button type="primary">Submit</Button>
712
+ </Form>
713
+ </Card>;
714
+ }
715
+ ```
716
+
717
+ ### Importing Default Exports
718
+
719
+ Some libraries export a default export. Import it like this:
720
+
721
+ ```jac
722
+ """Importing default exports."""
723
+
724
+ # If the library has a default export, you can import it
725
+ # Note: Check the library's documentation for export patterns
726
+
727
+ cl import from mylibrary {
728
+ default as MyLibrary
729
+ }
730
+ ```
731
+
732
+ ### Using Imported Components
733
+
734
+ Once imported, use components just like Jac components:
735
+
736
+ ```jac
737
+ cl import from antd {
738
+ Button,
739
+ Card,
740
+ Modal
741
+ }
742
+
743
+ cl def MyComponent() -> any {
744
+ return <div>
745
+ <Card title="My Card">
746
+ <Button
747
+ type="primary"
748
+ onClick={lambda -> None {
749
+ console.log("Button clicked!");
750
+ }}
751
+ >
752
+ Click Me
753
+ </Button>
754
+ </Card>
755
+ </div>;
756
+ }
757
+ ```
758
+
759
+ ---
760
+
761
+ ## Importing Other Jac Files
762
+
763
+ You can import components, functions, and constants from other Jac files in your project.
764
+
765
+ ### Relative Import Syntax
766
+
767
+ ```jac
768
+ cl import from .module_name {
769
+ Component1,
770
+ Function1,
771
+ Constant1
772
+ }
773
+ ```
774
+
775
+ **Key Points:**
776
+ - Use `.` for relative imports (same directory or subdirectory)
777
+ - `.module_name` - the Jac file name without `.jac` extension
778
+ - `{ ... }` - list of exports to import
779
+
780
+ ### Example: Importing from Same Directory
781
+
782
+ **button.jac:**
783
+ ```jac
784
+ """Button component."""
785
+
786
+ cl def CustomButton(props: dict) -> any {
787
+ return <button
788
+ style={{
789
+ "padding": "10px 20px",
790
+ "background": "#7C3AED",
791
+ "color": "#FFFFFF",
792
+ "border": "none",
793
+ "borderRadius": "6px",
794
+ "cursor": "pointer"
795
+ }}
796
+ onClick={props.onClick}
797
+ >
798
+ {props.children}
799
+ </button>;
800
+ }
801
+
802
+ cl def PrimaryButton(props: dict) -> any {
803
+ return <button
804
+ style={{
805
+ "padding": "10px 20px",
806
+ "background": "#059669",
807
+ "color": "#FFFFFF",
808
+ "border": "none",
809
+ "borderRadius": "6px",
810
+ "cursor": "pointer"
811
+ }}
812
+ onClick={props.onClick}
813
+ >
814
+ {props.children}
815
+ </button>;
816
+ }
817
+ ```
818
+
819
+ **app.jac:**
820
+ ```jac
821
+ """Main application."""
822
+
823
+ cl import from .button {
824
+ CustomButton,
825
+ PrimaryButton
826
+ }
827
+
828
+ cl def App() -> any {
829
+ return <div>
830
+ <CustomButton onClick={lambda -> None { console.log("Clicked!"); }}>
831
+ Custom Button
832
+ </CustomButton>
833
+ <PrimaryButton onClick={lambda -> None { console.log("Primary!"); }}>
834
+ Primary Button
835
+ </PrimaryButton>
836
+ </div>;
837
+ }
838
+
839
+ cl def jac_app() -> any {
840
+ return App();
841
+ }
842
+ ```
843
+
844
+ ### Example: Importing from Subdirectory
845
+
846
+ > currently not suported
847
+
848
+ ## Importing JavaScript Files
849
+
850
+ You can import functions, classes, and constants from local JavaScript files.
851
+
852
+ ### JavaScript File Structure
853
+
854
+ **utils.js:**
855
+ ```javascript
856
+ // Export individual functions
857
+ export function formatMessage(name) {
858
+ return `Hello, ${name}!`;
859
+ }
860
+
861
+ export function calculateSum(a, b) {
862
+ return a + b;
863
+ }
864
+
865
+ // Export constants
866
+ export const JS_CONSTANT = "JavaScript Import Test";
867
+
868
+ // Export class
869
+ export class MessageFormatter {
870
+ constructor(prefix) {
871
+ this.prefix = prefix;
872
+ }
873
+
874
+ format(message) {
875
+ return `[${this.prefix}] ${message}`;
876
+ }
877
+ }
878
+
879
+ // Export default (if needed)
880
+ export default function defaultExport() {
881
+ return "Default export";
882
+ }
883
+ ```
884
+
885
+ ### Importing from JavaScript Files
886
+
887
+ ```jac
888
+ """Importing from JavaScript files."""
889
+
890
+ cl import from .utils {
891
+ formatMessage,
892
+ calculateSum,
893
+ JS_CONSTANT,
894
+ MessageFormatter
895
+ }
896
+
897
+ cl def JsImportTest() -> any {
898
+ greeting = formatMessage("Jac");
899
+ sum = calculateSum(5, 3);
900
+ formatter = MessageFormatter("JS");
901
+ formatted = formatter.format("Hello from JS class");
902
+
903
+ return <div>
904
+ <h1>{JS_CONSTANT}</h1>
905
+ <p>Greeting: {greeting}</p>
906
+ <p>Sum (5 + 3): {sum}</p>
907
+ <p>Constant: {JS_CONSTANT}</p>
908
+ <p>Formatted: {formatted}</p>
909
+ </div>;
910
+ }
911
+
912
+ cl def jac_app() -> any {
913
+ return JsImportTest();
914
+ }
915
+ ```
916
+
917
+ ### Using JavaScript Functions
918
+
919
+ ```jac
920
+ """Using imported JavaScript functions."""
921
+
922
+ cl import from .dateUtils {
923
+ formatDate,
924
+ parseDate,
925
+ getDaysDifference
926
+ }
927
+
928
+ cl import from .stringUtils {
929
+ capitalize,
930
+ slugify
931
+ }
932
+
933
+ cl def DateComponent() -> any {
934
+ today = new Date();
935
+ formatted = formatDate(today);
936
+
937
+ return <div>
938
+ <p>Today: {formatted}</p>
939
+ <p>Capitalized: {capitalize("hello world")}</p>
940
+ </div>;
941
+ }
942
+ ```
943
+
944
+ ### JavaScript Classes
945
+
946
+ ```jac
947
+ """Using imported JavaScript classes."""
948
+
949
+ cl import from .validators {
950
+ EmailValidator,
951
+ PasswordValidator
952
+ }
953
+
954
+ cl def ValidationForm() -> any {
955
+ emailValidator = EmailValidator();
956
+ passwordValidator = PasswordValidator();
957
+
958
+ return <form>
959
+ <input
960
+ type="email"
961
+ onBlur={lambda e: any -> None {
962
+ if not emailValidator.validate(e.target.value) {
963
+ alert("Invalid email");
964
+ }
965
+ }}
966
+ />
967
+ <input
968
+ type="password"
969
+ onBlur={lambda e: any -> None {
970
+ if not passwordValidator.validate(e.target.value) {
971
+ alert("Invalid password");
972
+ }
973
+ }}
974
+ />
975
+ </form>;
976
+ }
977
+ ```
978
+
979
+ ---
980
+
981
+ ## Best Practices
982
+
983
+ ### 1. Organize Imports
984
+
985
+ ```jac
986
+ # ✅ Good: Group imports logically
987
+ # Third-party libraries
988
+ cl import from antd {
989
+ Button,
990
+ Card
991
+ }
992
+
993
+ cl import from 'react-icons' {
994
+ FaHome,
995
+ FaUser
996
+ }
997
+
998
+ # Local Jac files
999
+ cl import from .header {
1000
+ Header
1001
+ }
1002
+
1003
+ cl import from .utils {
1004
+ formatDate
1005
+ }
1006
+
1007
+ # Local JavaScript files
1008
+ cl import from .helpers {
1009
+ debounce
1010
+ }
1011
+ ```
1012
+
1013
+ ## Common Import Patterns
1014
+
1015
+ ### Pattern 1: UI Component Library
1016
+
1017
+ ```jac
1018
+ """Using a UI component library."""
1019
+
1020
+ cl import from antd {
1021
+ Button,
1022
+ Card,
1023
+ Input,
1024
+ Space,
1025
+ Layout
1026
+ }
1027
+
1028
+ cl def Dashboard() -> any {
1029
+ return <Layout>
1030
+ <Card title="Dashboard">
1031
+ <Space direction="vertical">
1032
+ <Input placeholder="Search..." />
1033
+ <Button type="primary">Submit</Button>
1034
+ </Space>
1035
+ </Card>
1036
+ </Layout>;
1037
+ }
1038
+ ```
1039
+
1040
+ ### Pattern 2: Utility Functions
1041
+
1042
+ ```jac
1043
+ """Using utility functions."""
1044
+
1045
+ cl import from .dateUtils {
1046
+ formatDate,
1047
+ getRelativeTime
1048
+ }
1049
+
1050
+ cl import from .stringUtils {
1051
+ capitalize,
1052
+ truncate
1053
+ }
1054
+
1055
+ cl def PostCard(post: dict) -> any {
1056
+ return <div>
1057
+ <h3>{capitalize(post.title)}</h3>
1058
+ <p>{truncate(post.content, 100)}</p>
1059
+ <small>{getRelativeTime(post.created_at)}</small>
1060
+ </div>;
1061
+ }
1062
+ ```
1063
+
1064
+ ### Pattern 3: Reusable Components
1065
+
1066
+ ```jac
1067
+ """Using reusable components."""
1068
+
1069
+ cl import from .forms {
1070
+ TextInput,
1071
+ SelectInput,
1072
+ SubmitButton
1073
+ }
1074
+
1075
+ cl import from .layout {
1076
+ Container,
1077
+ Row,
1078
+ Column
1079
+ }
1080
+
1081
+ cl def ContactForm() -> any {
1082
+ return <Container>
1083
+ <Row>
1084
+ <Column>
1085
+ <TextInput placeholder="Name" />
1086
+ <TextInput placeholder="Email" />
1087
+ <SelectInput options={["Option 1", "Option 2"]} />
1088
+ <SubmitButton>Send</SubmitButton>
1089
+ </Column>
1090
+ </Row>
1091
+ </Container>;
1092
+ }
1093
+ ```
1094
+
1095
+ ---
1096
+
1097
+ ## Troubleshooting
1098
+
1099
+ ### Issue: Module Not Found
1100
+
1101
+ **Problem:**
1102
+ ```
1103
+ Error: Cannot find module 'antd'
1104
+ ```
1105
+
1106
+ **Solution:**
1107
+ ```bash
1108
+ # Install the missing package
1109
+ npm install antd
1110
+ ```
1111
+
1112
+ ### Issue: Import Not Working
1113
+
1114
+ **Problem:**
1115
+ Imported component is `undefined`
1116
+
1117
+ **Solution:**
1118
+ - Check the export name matches exactly
1119
+ - Verify the file path is correct
1120
+ - Ensure the file exports the component/function
1121
+
1122
+ ### Issue: Type Errors
1123
+
1124
+ **Problem:**
1125
+ Type errors with imported functions
1126
+
1127
+ **Solution:**
1128
+ - Check function signatures match
1129
+ - Verify parameter types
1130
+ - Review library documentation
1131
+
1132
+ ---
1133
+
1134
+ ## Summary
1135
+
1136
+ - **Third-Party Libraries**: Install with `npm install`, import with `cl import from package_name`
1137
+ - **Jac Files**: Import with `cl import from .module_name`
1138
+ - **JavaScript Files**: Import with `cl import from .filename`
1139
+ - **Best Practices**: Organize imports, import only what you need, document exports
1140
+
1141
+ Imports in Jac make it easy to use third-party libraries and organize your code! 🚀
1142
+