jac-client 0.1.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.
- jac_client/docs/README.md +629 -0
- jac_client/docs/advanced-state.md +706 -0
- jac_client/docs/imports.md +650 -0
- jac_client/docs/lifecycle-hooks.md +554 -0
- jac_client/docs/routing.md +530 -0
- jac_client/examples/little-x/app.jac +615 -0
- jac_client/examples/little-x/package-lock.json +2840 -0
- jac_client/examples/little-x/package.json +23 -0
- jac_client/examples/little-x/submit-button.jac +8 -0
- jac_client/examples/todo-app/README.md +82 -0
- jac_client/examples/todo-app/app.jac +683 -0
- jac_client/examples/todo-app/package-lock.json +999 -0
- jac_client/examples/todo-app/package.json +22 -0
- jac_client/plugin/cli.py +328 -0
- jac_client/plugin/client.py +41 -0
- jac_client/plugin/client_runtime.jac +941 -0
- jac_client/plugin/vite_client_bundle.py +470 -0
- jac_client/tests/__init__.py +2 -0
- jac_client/tests/fixtures/button.jac +6 -0
- jac_client/tests/fixtures/client_app.jac +18 -0
- jac_client/tests/fixtures/client_app_with_antd.jac +21 -0
- jac_client/tests/fixtures/js_import.jac +30 -0
- jac_client/tests/fixtures/package-lock.json +329 -0
- jac_client/tests/fixtures/package.json +11 -0
- jac_client/tests/fixtures/relative_import.jac +13 -0
- jac_client/tests/fixtures/test_fragments_spread.jac +44 -0
- jac_client/tests/fixtures/utils.js +22 -0
- jac_client/tests/test_cl.py +360 -0
- jac_client/tests/test_create_jac_app.py +139 -0
- jac_client-0.1.0.dist-info/METADATA +126 -0
- jac_client-0.1.0.dist-info/RECORD +33 -0
- jac_client-0.1.0.dist-info/WHEEL +4 -0
- jac_client-0.1.0.dist-info/entry_points.txt +4 -0
|
@@ -0,0 +1,650 @@
|
|
|
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
|
+
- [Working with Third-Party Node Modules](#working-with-third-party-node-modules)
|
|
10
|
+
- [Installing Packages](#installing-packages)
|
|
11
|
+
- [Importing Third-Party Libraries](#importing-third-party-libraries)
|
|
12
|
+
- [Importing Other Jac Files](#importing-other-jac-files)
|
|
13
|
+
- [Importing JavaScript Files](#importing-javascript-files)
|
|
14
|
+
- [Best Practices](#best-practices)
|
|
15
|
+
|
|
16
|
+
---
|
|
17
|
+
|
|
18
|
+
## Working with Third-Party Node Modules
|
|
19
|
+
|
|
20
|
+
Jac supports importing any npm package that's compatible with ES modules. This includes popular libraries like React UI frameworks, utility libraries, and more.
|
|
21
|
+
|
|
22
|
+
### Prerequisites
|
|
23
|
+
|
|
24
|
+
Before importing third-party libraries, you need:
|
|
25
|
+
|
|
26
|
+
1. **Node.js** installed (for npm)
|
|
27
|
+
2. **package.json** in your project root
|
|
28
|
+
3. **Vite** configured in your project (automatically set up with `jac create_jac_app`)
|
|
29
|
+
|
|
30
|
+
### Why Third-Party Libraries?
|
|
31
|
+
|
|
32
|
+
Third-party libraries provide:
|
|
33
|
+
- **UI Components**: React component libraries (Ant Design, Material-UI, etc.)
|
|
34
|
+
- **Utilities**: Helper functions and utilities (lodash, date-fns, etc.)
|
|
35
|
+
- **Tools**: Development and production tools
|
|
36
|
+
- **Reusability**: Community-maintained, tested code
|
|
37
|
+
|
|
38
|
+
---
|
|
39
|
+
|
|
40
|
+
## Installing Packages
|
|
41
|
+
|
|
42
|
+
### Step 1: Install with npm
|
|
43
|
+
|
|
44
|
+
Use npm to install packages into your project:
|
|
45
|
+
|
|
46
|
+
```bash
|
|
47
|
+
# Install a package
|
|
48
|
+
npm install antd
|
|
49
|
+
|
|
50
|
+
# Install a specific version
|
|
51
|
+
npm install antd@5.12.8
|
|
52
|
+
|
|
53
|
+
# Install as dev dependency (development tools)
|
|
54
|
+
npm install --save-dev vite
|
|
55
|
+
|
|
56
|
+
# Install multiple packages
|
|
57
|
+
npm install antd react-icons date-fns
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
**What Happens:**
|
|
61
|
+
- Package is downloaded to `node_modules/`
|
|
62
|
+
- Package is added to `package.json` dependencies
|
|
63
|
+
- Package becomes available for import
|
|
64
|
+
|
|
65
|
+
### Step 2: Verify Installation
|
|
66
|
+
|
|
67
|
+
Check that the package is installed:
|
|
68
|
+
|
|
69
|
+
```bash
|
|
70
|
+
# Check package.json
|
|
71
|
+
cat package.json
|
|
72
|
+
|
|
73
|
+
# Verify node_modules exists
|
|
74
|
+
ls node_modules | grep antd
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
**package.json Example:**
|
|
78
|
+
```json
|
|
79
|
+
{
|
|
80
|
+
"name": "my-app",
|
|
81
|
+
"version": "1.0.0",
|
|
82
|
+
"dependencies": {
|
|
83
|
+
"antd": "^5.12.8",
|
|
84
|
+
"react-icons": "^4.12.0"
|
|
85
|
+
},
|
|
86
|
+
"devDependencies": {
|
|
87
|
+
"vite": "^5.0.0"
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
---
|
|
93
|
+
|
|
94
|
+
## Importing Third-Party Libraries
|
|
95
|
+
|
|
96
|
+
Once a package is installed, you can import it using Jac's `cl import` syntax.
|
|
97
|
+
|
|
98
|
+
### Basic Import Syntax
|
|
99
|
+
|
|
100
|
+
```jac
|
|
101
|
+
cl import from package_name {
|
|
102
|
+
Component1,
|
|
103
|
+
Component2,
|
|
104
|
+
Function1,
|
|
105
|
+
Constant1
|
|
106
|
+
}
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
**Key Points:**
|
|
110
|
+
- Use `cl import` for client-side imports
|
|
111
|
+
- `from package_name` - the npm package name (no quotes)
|
|
112
|
+
- `{ ... }` - list of exports to import (comma-separated)
|
|
113
|
+
|
|
114
|
+
### Example: Importing Ant Design
|
|
115
|
+
|
|
116
|
+
```bash
|
|
117
|
+
# First, install Ant Design
|
|
118
|
+
npm install antd
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
```jac
|
|
122
|
+
"""Importing Ant Design components."""
|
|
123
|
+
|
|
124
|
+
cl import from antd {
|
|
125
|
+
Button,
|
|
126
|
+
Card,
|
|
127
|
+
Input,
|
|
128
|
+
Space
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
cl def MyApp() -> any {
|
|
132
|
+
return <div>
|
|
133
|
+
<Space direction="vertical" size="large">
|
|
134
|
+
<Card title="Welcome">
|
|
135
|
+
<Input placeholder="Enter text..." />
|
|
136
|
+
<Button type="primary">Submit</Button>
|
|
137
|
+
</Card>
|
|
138
|
+
</Space>
|
|
139
|
+
</div>;
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
cl def jac_app() -> any {
|
|
143
|
+
return MyApp();
|
|
144
|
+
}
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
### Example: Importing React Icons
|
|
148
|
+
|
|
149
|
+
```bash
|
|
150
|
+
# Install React Icons
|
|
151
|
+
npm install react-icons
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
```jac
|
|
155
|
+
"""Importing React Icons."""
|
|
156
|
+
|
|
157
|
+
cl import from 'react-icons' {
|
|
158
|
+
FaHome,
|
|
159
|
+
FaUser,
|
|
160
|
+
FaSettings
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
cl def Navigation() -> any {
|
|
164
|
+
return <nav>
|
|
165
|
+
<FaHome />
|
|
166
|
+
<FaUser />
|
|
167
|
+
<FaSettings />
|
|
168
|
+
</nav>;
|
|
169
|
+
}
|
|
170
|
+
```
|
|
171
|
+
|
|
172
|
+
### Example: Importing Utility Libraries
|
|
173
|
+
|
|
174
|
+
```bash
|
|
175
|
+
# Install utility libraries
|
|
176
|
+
npm install date-fns lodash
|
|
177
|
+
```
|
|
178
|
+
|
|
179
|
+
```jac
|
|
180
|
+
"""Importing utility functions."""
|
|
181
|
+
|
|
182
|
+
cl import from 'date-fns' {
|
|
183
|
+
format,
|
|
184
|
+
parseISO,
|
|
185
|
+
differenceInDays
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
cl import from lodash {
|
|
189
|
+
debounce,
|
|
190
|
+
throttle
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
```
|
|
194
|
+
|
|
195
|
+
### Example: Importing Multiple Components
|
|
196
|
+
|
|
197
|
+
```jac
|
|
198
|
+
"""Importing multiple components from a library."""
|
|
199
|
+
|
|
200
|
+
cl import from antd {
|
|
201
|
+
Button,
|
|
202
|
+
Card,
|
|
203
|
+
Input,
|
|
204
|
+
Form,
|
|
205
|
+
Select,
|
|
206
|
+
DatePicker,
|
|
207
|
+
Table
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
cl def FormExample() -> any {
|
|
211
|
+
return <Card title="Form Example">
|
|
212
|
+
<Form>
|
|
213
|
+
<Input placeholder="Name" />
|
|
214
|
+
<Select placeholder="Select option">
|
|
215
|
+
<option value="1">Option 1</option>
|
|
216
|
+
<option value="2">Option 2</option>
|
|
217
|
+
</Select>
|
|
218
|
+
<DatePicker />
|
|
219
|
+
<Button type="primary">Submit</Button>
|
|
220
|
+
</Form>
|
|
221
|
+
</Card>;
|
|
222
|
+
}
|
|
223
|
+
```
|
|
224
|
+
|
|
225
|
+
### Importing Default Exports
|
|
226
|
+
|
|
227
|
+
Some libraries export a default export. Import it like this:
|
|
228
|
+
|
|
229
|
+
```jac
|
|
230
|
+
"""Importing default exports."""
|
|
231
|
+
|
|
232
|
+
# If the library has a default export, you can import it
|
|
233
|
+
# Note: Check the library's documentation for export patterns
|
|
234
|
+
|
|
235
|
+
cl import from mylibrary {
|
|
236
|
+
default as MyLibrary
|
|
237
|
+
}
|
|
238
|
+
```
|
|
239
|
+
|
|
240
|
+
### Using Imported Components
|
|
241
|
+
|
|
242
|
+
Once imported, use components just like Jac components:
|
|
243
|
+
|
|
244
|
+
```jac
|
|
245
|
+
cl import from antd {
|
|
246
|
+
Button,
|
|
247
|
+
Card,
|
|
248
|
+
Modal
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
cl def MyComponent() -> any {
|
|
252
|
+
return <div>
|
|
253
|
+
<Card title="My Card">
|
|
254
|
+
<Button
|
|
255
|
+
type="primary"
|
|
256
|
+
onClick={lambda -> None {
|
|
257
|
+
console.log("Button clicked!");
|
|
258
|
+
}}
|
|
259
|
+
>
|
|
260
|
+
Click Me
|
|
261
|
+
</Button>
|
|
262
|
+
</Card>
|
|
263
|
+
</div>;
|
|
264
|
+
}
|
|
265
|
+
```
|
|
266
|
+
|
|
267
|
+
---
|
|
268
|
+
|
|
269
|
+
## Importing Other Jac Files
|
|
270
|
+
|
|
271
|
+
You can import components, functions, and constants from other Jac files in your project.
|
|
272
|
+
|
|
273
|
+
### Relative Import Syntax
|
|
274
|
+
|
|
275
|
+
```jac
|
|
276
|
+
cl import from .module_name {
|
|
277
|
+
Component1,
|
|
278
|
+
Function1,
|
|
279
|
+
Constant1
|
|
280
|
+
}
|
|
281
|
+
```
|
|
282
|
+
|
|
283
|
+
**Key Points:**
|
|
284
|
+
- Use `.` for relative imports (same directory or subdirectory)
|
|
285
|
+
- `.module_name` - the Jac file name without `.jac` extension
|
|
286
|
+
- `{ ... }` - list of exports to import
|
|
287
|
+
|
|
288
|
+
### Example: Importing from Same Directory
|
|
289
|
+
|
|
290
|
+
**button.jac:**
|
|
291
|
+
```jac
|
|
292
|
+
"""Button component."""
|
|
293
|
+
|
|
294
|
+
cl def CustomButton(props: dict) -> any {
|
|
295
|
+
return <button
|
|
296
|
+
style={{
|
|
297
|
+
"padding": "10px 20px",
|
|
298
|
+
"background": "#7C3AED",
|
|
299
|
+
"color": "#FFFFFF",
|
|
300
|
+
"border": "none",
|
|
301
|
+
"borderRadius": "6px",
|
|
302
|
+
"cursor": "pointer"
|
|
303
|
+
}}
|
|
304
|
+
onClick={props.onClick}
|
|
305
|
+
>
|
|
306
|
+
{props.children}
|
|
307
|
+
</button>;
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
cl def PrimaryButton(props: dict) -> any {
|
|
311
|
+
return <button
|
|
312
|
+
style={{
|
|
313
|
+
"padding": "10px 20px",
|
|
314
|
+
"background": "#059669",
|
|
315
|
+
"color": "#FFFFFF",
|
|
316
|
+
"border": "none",
|
|
317
|
+
"borderRadius": "6px",
|
|
318
|
+
"cursor": "pointer"
|
|
319
|
+
}}
|
|
320
|
+
onClick={props.onClick}
|
|
321
|
+
>
|
|
322
|
+
{props.children}
|
|
323
|
+
</button>;
|
|
324
|
+
}
|
|
325
|
+
```
|
|
326
|
+
|
|
327
|
+
**app.jac:**
|
|
328
|
+
```jac
|
|
329
|
+
"""Main application."""
|
|
330
|
+
|
|
331
|
+
cl import from .button {
|
|
332
|
+
CustomButton,
|
|
333
|
+
PrimaryButton
|
|
334
|
+
}
|
|
335
|
+
|
|
336
|
+
cl def App() -> any {
|
|
337
|
+
return <div>
|
|
338
|
+
<CustomButton onClick={lambda -> None { console.log("Clicked!"); }}>
|
|
339
|
+
Custom Button
|
|
340
|
+
</CustomButton>
|
|
341
|
+
<PrimaryButton onClick={lambda -> None { console.log("Primary!"); }}>
|
|
342
|
+
Primary Button
|
|
343
|
+
</PrimaryButton>
|
|
344
|
+
</div>;
|
|
345
|
+
}
|
|
346
|
+
|
|
347
|
+
cl def jac_app() -> any {
|
|
348
|
+
return App();
|
|
349
|
+
}
|
|
350
|
+
```
|
|
351
|
+
|
|
352
|
+
### Example: Importing from Subdirectory
|
|
353
|
+
|
|
354
|
+
> currently not suported
|
|
355
|
+
|
|
356
|
+
## Importing JavaScript Files
|
|
357
|
+
|
|
358
|
+
You can import functions, classes, and constants from local JavaScript files.
|
|
359
|
+
|
|
360
|
+
### JavaScript File Structure
|
|
361
|
+
|
|
362
|
+
**utils.js:**
|
|
363
|
+
```javascript
|
|
364
|
+
// Export individual functions
|
|
365
|
+
export function formatMessage(name) {
|
|
366
|
+
return `Hello, ${name}!`;
|
|
367
|
+
}
|
|
368
|
+
|
|
369
|
+
export function calculateSum(a, b) {
|
|
370
|
+
return a + b;
|
|
371
|
+
}
|
|
372
|
+
|
|
373
|
+
// Export constants
|
|
374
|
+
export const JS_CONSTANT = "JavaScript Import Test";
|
|
375
|
+
|
|
376
|
+
// Export class
|
|
377
|
+
export class MessageFormatter {
|
|
378
|
+
constructor(prefix) {
|
|
379
|
+
this.prefix = prefix;
|
|
380
|
+
}
|
|
381
|
+
|
|
382
|
+
format(message) {
|
|
383
|
+
return `[${this.prefix}] ${message}`;
|
|
384
|
+
}
|
|
385
|
+
}
|
|
386
|
+
|
|
387
|
+
// Export default (if needed)
|
|
388
|
+
export default function defaultExport() {
|
|
389
|
+
return "Default export";
|
|
390
|
+
}
|
|
391
|
+
```
|
|
392
|
+
|
|
393
|
+
### Importing from JavaScript Files
|
|
394
|
+
|
|
395
|
+
```jac
|
|
396
|
+
"""Importing from JavaScript files."""
|
|
397
|
+
|
|
398
|
+
cl import from .utils {
|
|
399
|
+
formatMessage,
|
|
400
|
+
calculateSum,
|
|
401
|
+
JS_CONSTANT,
|
|
402
|
+
MessageFormatter
|
|
403
|
+
}
|
|
404
|
+
|
|
405
|
+
cl def JsImportTest() -> any {
|
|
406
|
+
greeting = formatMessage("Jac");
|
|
407
|
+
sum = calculateSum(5, 3);
|
|
408
|
+
formatter = MessageFormatter("JS");
|
|
409
|
+
formatted = formatter.format("Hello from JS class");
|
|
410
|
+
|
|
411
|
+
return <div>
|
|
412
|
+
<h1>{JS_CONSTANT}</h1>
|
|
413
|
+
<p>Greeting: {greeting}</p>
|
|
414
|
+
<p>Sum (5 + 3): {sum}</p>
|
|
415
|
+
<p>Constant: {JS_CONSTANT}</p>
|
|
416
|
+
<p>Formatted: {formatted}</p>
|
|
417
|
+
</div>;
|
|
418
|
+
}
|
|
419
|
+
|
|
420
|
+
cl def jac_app() -> any {
|
|
421
|
+
return JsImportTest();
|
|
422
|
+
}
|
|
423
|
+
```
|
|
424
|
+
|
|
425
|
+
### Using JavaScript Functions
|
|
426
|
+
|
|
427
|
+
```jac
|
|
428
|
+
"""Using imported JavaScript functions."""
|
|
429
|
+
|
|
430
|
+
cl import from .dateUtils {
|
|
431
|
+
formatDate,
|
|
432
|
+
parseDate,
|
|
433
|
+
getDaysDifference
|
|
434
|
+
}
|
|
435
|
+
|
|
436
|
+
cl import from .stringUtils {
|
|
437
|
+
capitalize,
|
|
438
|
+
slugify
|
|
439
|
+
}
|
|
440
|
+
|
|
441
|
+
cl def DateComponent() -> any {
|
|
442
|
+
today = new Date();
|
|
443
|
+
formatted = formatDate(today);
|
|
444
|
+
|
|
445
|
+
return <div>
|
|
446
|
+
<p>Today: {formatted}</p>
|
|
447
|
+
<p>Capitalized: {capitalize("hello world")}</p>
|
|
448
|
+
</div>;
|
|
449
|
+
}
|
|
450
|
+
```
|
|
451
|
+
|
|
452
|
+
### JavaScript Classes
|
|
453
|
+
|
|
454
|
+
```jac
|
|
455
|
+
"""Using imported JavaScript classes."""
|
|
456
|
+
|
|
457
|
+
cl import from .validators {
|
|
458
|
+
EmailValidator,
|
|
459
|
+
PasswordValidator
|
|
460
|
+
}
|
|
461
|
+
|
|
462
|
+
cl def ValidationForm() -> any {
|
|
463
|
+
emailValidator = EmailValidator();
|
|
464
|
+
passwordValidator = PasswordValidator();
|
|
465
|
+
|
|
466
|
+
return <form>
|
|
467
|
+
<input
|
|
468
|
+
type="email"
|
|
469
|
+
onBlur={lambda e: any -> None {
|
|
470
|
+
if not emailValidator.validate(e.target.value) {
|
|
471
|
+
alert("Invalid email");
|
|
472
|
+
}
|
|
473
|
+
}}
|
|
474
|
+
/>
|
|
475
|
+
<input
|
|
476
|
+
type="password"
|
|
477
|
+
onBlur={lambda e: any -> None {
|
|
478
|
+
if not passwordValidator.validate(e.target.value) {
|
|
479
|
+
alert("Invalid password");
|
|
480
|
+
}
|
|
481
|
+
}}
|
|
482
|
+
/>
|
|
483
|
+
</form>;
|
|
484
|
+
}
|
|
485
|
+
```
|
|
486
|
+
|
|
487
|
+
---
|
|
488
|
+
|
|
489
|
+
## Best Practices
|
|
490
|
+
|
|
491
|
+
### 1. Organize Imports
|
|
492
|
+
|
|
493
|
+
```jac
|
|
494
|
+
# ✅ Good: Group imports logically
|
|
495
|
+
# Third-party libraries
|
|
496
|
+
cl import from antd {
|
|
497
|
+
Button,
|
|
498
|
+
Card
|
|
499
|
+
}
|
|
500
|
+
|
|
501
|
+
cl import from 'react-icons' {
|
|
502
|
+
FaHome,
|
|
503
|
+
FaUser
|
|
504
|
+
}
|
|
505
|
+
|
|
506
|
+
# Local Jac files
|
|
507
|
+
cl import from .header {
|
|
508
|
+
Header
|
|
509
|
+
}
|
|
510
|
+
|
|
511
|
+
cl import from .utils {
|
|
512
|
+
formatDate
|
|
513
|
+
}
|
|
514
|
+
|
|
515
|
+
# Local JavaScript files
|
|
516
|
+
cl import from .helpers {
|
|
517
|
+
debounce
|
|
518
|
+
}
|
|
519
|
+
```
|
|
520
|
+
|
|
521
|
+
## Common Import Patterns
|
|
522
|
+
|
|
523
|
+
### Pattern 1: UI Component Library
|
|
524
|
+
|
|
525
|
+
```jac
|
|
526
|
+
"""Using a UI component library."""
|
|
527
|
+
|
|
528
|
+
cl import from antd {
|
|
529
|
+
Button,
|
|
530
|
+
Card,
|
|
531
|
+
Input,
|
|
532
|
+
Space,
|
|
533
|
+
Layout
|
|
534
|
+
}
|
|
535
|
+
|
|
536
|
+
cl def Dashboard() -> any {
|
|
537
|
+
return <Layout>
|
|
538
|
+
<Card title="Dashboard">
|
|
539
|
+
<Space direction="vertical">
|
|
540
|
+
<Input placeholder="Search..." />
|
|
541
|
+
<Button type="primary">Submit</Button>
|
|
542
|
+
</Space>
|
|
543
|
+
</Card>
|
|
544
|
+
</Layout>;
|
|
545
|
+
}
|
|
546
|
+
```
|
|
547
|
+
|
|
548
|
+
### Pattern 2: Utility Functions
|
|
549
|
+
|
|
550
|
+
```jac
|
|
551
|
+
"""Using utility functions."""
|
|
552
|
+
|
|
553
|
+
cl import from .dateUtils {
|
|
554
|
+
formatDate,
|
|
555
|
+
getRelativeTime
|
|
556
|
+
}
|
|
557
|
+
|
|
558
|
+
cl import from .stringUtils {
|
|
559
|
+
capitalize,
|
|
560
|
+
truncate
|
|
561
|
+
}
|
|
562
|
+
|
|
563
|
+
cl def PostCard(post: dict) -> any {
|
|
564
|
+
return <div>
|
|
565
|
+
<h3>{capitalize(post.title)}</h3>
|
|
566
|
+
<p>{truncate(post.content, 100)}</p>
|
|
567
|
+
<small>{getRelativeTime(post.created_at)}</small>
|
|
568
|
+
</div>;
|
|
569
|
+
}
|
|
570
|
+
```
|
|
571
|
+
|
|
572
|
+
### Pattern 3: Reusable Components
|
|
573
|
+
|
|
574
|
+
```jac
|
|
575
|
+
"""Using reusable components."""
|
|
576
|
+
|
|
577
|
+
cl import from .forms {
|
|
578
|
+
TextInput,
|
|
579
|
+
SelectInput,
|
|
580
|
+
SubmitButton
|
|
581
|
+
}
|
|
582
|
+
|
|
583
|
+
cl import from .layout {
|
|
584
|
+
Container,
|
|
585
|
+
Row,
|
|
586
|
+
Column
|
|
587
|
+
}
|
|
588
|
+
|
|
589
|
+
cl def ContactForm() -> any {
|
|
590
|
+
return <Container>
|
|
591
|
+
<Row>
|
|
592
|
+
<Column>
|
|
593
|
+
<TextInput placeholder="Name" />
|
|
594
|
+
<TextInput placeholder="Email" />
|
|
595
|
+
<SelectInput options={["Option 1", "Option 2"]} />
|
|
596
|
+
<SubmitButton>Send</SubmitButton>
|
|
597
|
+
</Column>
|
|
598
|
+
</Row>
|
|
599
|
+
</Container>;
|
|
600
|
+
}
|
|
601
|
+
```
|
|
602
|
+
|
|
603
|
+
---
|
|
604
|
+
|
|
605
|
+
## Troubleshooting
|
|
606
|
+
|
|
607
|
+
### Issue: Module Not Found
|
|
608
|
+
|
|
609
|
+
**Problem:**
|
|
610
|
+
```
|
|
611
|
+
Error: Cannot find module 'antd'
|
|
612
|
+
```
|
|
613
|
+
|
|
614
|
+
**Solution:**
|
|
615
|
+
```bash
|
|
616
|
+
# Install the missing package
|
|
617
|
+
npm install antd
|
|
618
|
+
```
|
|
619
|
+
|
|
620
|
+
### Issue: Import Not Working
|
|
621
|
+
|
|
622
|
+
**Problem:**
|
|
623
|
+
Imported component is `undefined`
|
|
624
|
+
|
|
625
|
+
**Solution:**
|
|
626
|
+
- Check the export name matches exactly
|
|
627
|
+
- Verify the file path is correct
|
|
628
|
+
- Ensure the file exports the component/function
|
|
629
|
+
|
|
630
|
+
### Issue: Type Errors
|
|
631
|
+
|
|
632
|
+
**Problem:**
|
|
633
|
+
Type errors with imported functions
|
|
634
|
+
|
|
635
|
+
**Solution:**
|
|
636
|
+
- Check function signatures match
|
|
637
|
+
- Verify parameter types
|
|
638
|
+
- Review library documentation
|
|
639
|
+
|
|
640
|
+
---
|
|
641
|
+
|
|
642
|
+
## Summary
|
|
643
|
+
|
|
644
|
+
- **Third-Party Libraries**: Install with `npm install`, import with `cl import from package_name`
|
|
645
|
+
- **Jac Files**: Import with `cl import from .module_name`
|
|
646
|
+
- **JavaScript Files**: Import with `cl import from .filename`
|
|
647
|
+
- **Best Practices**: Organize imports, import only what you need, document exports
|
|
648
|
+
|
|
649
|
+
Imports in Jac make it easy to use third-party libraries and organize your code! 🚀
|
|
650
|
+
|