jac-client 0.2.3__py3-none-any.whl → 0.2.8__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/app.jac +494 -347
- jac_client/examples/all-in-one/assets/workers/worker.py +5 -0
- jac_client/examples/all-in-one/button.jac +1 -1
- jac_client/examples/all-in-one/components/CategoryFilter.jac +35 -0
- jac_client/examples/all-in-one/components/Header.jac +13 -0
- jac_client/examples/all-in-one/components/ProfitOverview.jac +50 -0
- jac_client/examples/all-in-one/components/Summary.jac +53 -0
- jac_client/examples/all-in-one/components/TransactionForm.jac +158 -0
- jac_client/examples/all-in-one/components/TransactionItem.jac +55 -0
- jac_client/examples/all-in-one/components/TransactionList.jac +37 -0
- jac_client/examples/all-in-one/components/button.jac +1 -1
- jac_client/examples/all-in-one/components/navigation.jac +132 -0
- jac_client/examples/all-in-one/constants/categories.jac +37 -0
- jac_client/examples/all-in-one/constants/clients.jac +13 -0
- jac_client/examples/all-in-one/context/BudgetContext.jac +28 -0
- jac_client/examples/all-in-one/hooks/useBudget.jac +116 -0
- jac_client/examples/all-in-one/hooks/useLocalStorage.jac +36 -0
- jac_client/examples/all-in-one/pages/BudgetPlanner.cl.jac +70 -0
- jac_client/examples/all-in-one/pages/BudgetPlanner.jac +126 -0
- jac_client/examples/all-in-one/pages/FeaturesTest.cl.jac +552 -0
- jac_client/examples/all-in-one/pages/FeaturesTest.jac +126 -0
- jac_client/examples/all-in-one/pages/LandingPage.jac +101 -0
- jac_client/examples/all-in-one/pages/loginPage.jac +132 -0
- jac_client/examples/all-in-one/pages/nestedDemo.jac +61 -0
- jac_client/examples/all-in-one/pages/notFound.jac +24 -0
- jac_client/examples/all-in-one/pages/signupPage.jac +133 -0
- jac_client/examples/all-in-one/utils/formatters.jac +52 -0
- jac_client/examples/asset-serving/css-with-image/{app.jac → src/app.jac} +4 -4
- jac_client/examples/asset-serving/image-asset/{app.jac → src/app.jac} +4 -4
- jac_client/examples/asset-serving/import-alias/{app.jac → src/app.jac} +5 -5
- jac_client/examples/basic/{app.jac → src/app.jac} +4 -4
- jac_client/examples/basic-auth/src/app.jac +371 -0
- jac_client/examples/basic-auth-with-router/{app.jac → src/app.jac} +28 -28
- jac_client/examples/basic-full-stack/{app.jac → src/app.jac} +166 -127
- jac_client/examples/css-styling/js-styling/{app.jac → src/app.jac} +7 -7
- jac_client/examples/css-styling/material-ui/{app.jac → src/app.jac} +6 -6
- jac_client/examples/css-styling/pure-css/{app.jac → src/app.jac} +7 -7
- jac_client/examples/css-styling/sass-example/{app.jac → src/app.jac} +7 -7
- jac_client/examples/css-styling/styled-components/{app.jac → src/app.jac} +6 -6
- jac_client/examples/css-styling/tailwind-example/{app.jac → src/app.jac} +7 -7
- jac_client/examples/full-stack-with-auth/{app.jac → src/app.jac} +47 -47
- jac_client/examples/little-x/{app.jac → src/app.jac} +27 -32
- jac_client/examples/little-x/src/submit-button.jac +16 -0
- jac_client/examples/nested-folders/nested-advance/{ButtonRoot.jac → src/ButtonRoot.jac} +1 -1
- jac_client/examples/nested-folders/nested-advance/{app.jac → src/app.jac} +1 -1
- jac_client/examples/nested-folders/nested-advance/{level1 → src/level1}/ButtonSecondL.jac +1 -1
- jac_client/examples/nested-folders/nested-advance/{level1 → src/level1}/Card.jac +1 -1
- jac_client/examples/nested-folders/nested-advance/{level1 → src/level1}/level2/ButtonThirdL.jac +1 -1
- jac_client/examples/nested-folders/nested-basic/{app.jac → src/app.jac} +2 -2
- jac_client/examples/nested-folders/nested-basic/{button.jac → src/button.jac} +1 -1
- jac_client/examples/nested-folders/nested-basic/{components → src/components}/button.jac +1 -1
- jac_client/examples/ts-support/src/app.jac +35 -0
- jac_client/examples/with-router/{app.jac → src/app.jac} +15 -15
- jac_client/plugin/cli.jac +504 -0
- jac_client/plugin/client.jac +45 -0
- jac_client/plugin/client_runtime.cl.jac +42 -0
- jac_client/plugin/impl/client.impl.jac +193 -0
- jac_client/plugin/impl/client_runtime.impl.jac +195 -0
- jac_client/plugin/impl/vite_client_bundle.impl.jac +72 -0
- jac_client/plugin/plugin_config.jac +195 -0
- jac_client/plugin/src/__init__.jac +20 -0
- jac_client/plugin/src/asset_processor.jac +33 -0
- jac_client/plugin/src/babel_processor.jac +18 -0
- jac_client/plugin/src/compiler.jac +67 -0
- jac_client/plugin/src/config_loader.jac +32 -0
- jac_client/plugin/src/impl/asset_processor.impl.jac +127 -0
- jac_client/plugin/src/impl/babel_processor.impl.jac +89 -0
- jac_client/plugin/src/impl/compiler.impl.jac +288 -0
- jac_client/plugin/src/impl/config_loader.impl.jac +119 -0
- jac_client/plugin/src/impl/import_processor.impl.jac +33 -0
- jac_client/plugin/src/impl/jac_to_js.impl.jac +41 -0
- jac_client/plugin/src/impl/package_installer.impl.jac +105 -0
- jac_client/plugin/src/impl/vite_bundler.impl.jac +626 -0
- jac_client/plugin/src/import_processor.jac +19 -0
- jac_client/plugin/src/jac_to_js.jac +35 -0
- jac_client/plugin/src/package_installer.jac +26 -0
- jac_client/plugin/src/vite_bundler.jac +44 -0
- jac_client/plugin/vite_client_bundle.jac +31 -0
- jac_client/tests/conftest.py +283 -0
- jac_client/tests/fixtures/basic-app/app.jac +2 -2
- jac_client/tests/fixtures/cl_file/app.cl.jac +2 -2
- jac_client/tests/fixtures/client_app_with_antd/app.jac +1 -1
- jac_client/tests/fixtures/js_import/app.jac +5 -5
- jac_client/tests/fixtures/spawn_test/app.jac +15 -18
- jac_client/tests/fixtures/with-ts/app.jac +35 -0
- jac_client/tests/test_cli.py +811 -0
- jac_client/tests/test_it.py +592 -97
- {jac_client-0.2.3.dist-info → jac_client-0.2.8.dist-info}/METADATA +41 -34
- jac_client-0.2.8.dist-info/RECORD +97 -0
- {jac_client-0.2.3.dist-info → jac_client-0.2.8.dist-info}/WHEEL +2 -1
- jac_client-0.2.8.dist-info/entry_points.txt +4 -0
- jac_client-0.2.8.dist-info/top_level.txt +1 -0
- jac_client/docs/README.md +0 -689
- jac_client/docs/advanced-state.md +0 -1265
- jac_client/docs/asset-serving/intro.md +0 -209
- jac_client/docs/assets/pipe_line-v2.svg +0 -32
- jac_client/docs/assets/pipe_line.png +0 -0
- jac_client/docs/file-system/app.jac.md +0 -121
- jac_client/docs/file-system/backend-frontend.md +0 -217
- jac_client/docs/file-system/intro.md +0 -72
- jac_client/docs/file-system/nested-imports.md +0 -348
- jac_client/docs/guide-example/intro.md +0 -115
- jac_client/docs/guide-example/step-01-setup.md +0 -270
- jac_client/docs/guide-example/step-02-components.md +0 -416
- jac_client/docs/guide-example/step-03-styling.md +0 -478
- jac_client/docs/guide-example/step-04-todo-ui.md +0 -477
- jac_client/docs/guide-example/step-05-local-state.md +0 -530
- jac_client/docs/guide-example/step-06-events.md +0 -749
- jac_client/docs/guide-example/step-07-effects.md +0 -468
- jac_client/docs/guide-example/step-08-walkers.md +0 -534
- jac_client/docs/guide-example/step-09-authentication.md +0 -586
- jac_client/docs/guide-example/step-10-routing.md +0 -539
- jac_client/docs/guide-example/step-11-final.md +0 -963
- jac_client/docs/imports.md +0 -1141
- jac_client/docs/lifecycle-hooks.md +0 -773
- jac_client/docs/routing.md +0 -659
- jac_client/docs/styling/intro.md +0 -249
- jac_client/docs/styling/js-styling.md +0 -367
- jac_client/docs/styling/material-ui.md +0 -341
- jac_client/docs/styling/pure-css.md +0 -299
- jac_client/docs/styling/sass.md +0 -403
- jac_client/docs/styling/styled-components.md +0 -395
- jac_client/docs/styling/tailwind.md +0 -298
- jac_client/examples/all-in-one/.babelrc +0 -9
- jac_client/examples/all-in-one/README.md +0 -16
- jac_client/examples/all-in-one/assets/burger.png +0 -0
- jac_client/examples/all-in-one/package.json +0 -29
- jac_client/examples/all-in-one/styles.css +0 -26
- jac_client/examples/all-in-one/vite.config.js +0 -28
- jac_client/examples/asset-serving/css-with-image/.babelrc +0 -9
- jac_client/examples/asset-serving/css-with-image/README.md +0 -91
- jac_client/examples/asset-serving/css-with-image/assets/burger.png +0 -0
- jac_client/examples/asset-serving/css-with-image/package.json +0 -28
- jac_client/examples/asset-serving/css-with-image/styles.css +0 -26
- jac_client/examples/asset-serving/css-with-image/vite.config.js +0 -28
- jac_client/examples/asset-serving/image-asset/.babelrc +0 -9
- jac_client/examples/asset-serving/image-asset/README.md +0 -119
- jac_client/examples/asset-serving/image-asset/assets/burger.png +0 -0
- jac_client/examples/asset-serving/image-asset/package.json +0 -28
- jac_client/examples/asset-serving/image-asset/styles.css +0 -26
- jac_client/examples/asset-serving/image-asset/vite.config.js +0 -28
- jac_client/examples/asset-serving/import-alias/.babelrc +0 -9
- jac_client/examples/asset-serving/import-alias/README.md +0 -83
- jac_client/examples/asset-serving/import-alias/assets/burger.png +0 -0
- jac_client/examples/asset-serving/import-alias/package.json +0 -28
- jac_client/examples/asset-serving/import-alias/vite.config.js +0 -28
- jac_client/examples/basic/.babelrc +0 -9
- jac_client/examples/basic/README.md +0 -16
- jac_client/examples/basic/package.json +0 -27
- jac_client/examples/basic/vite.config.js +0 -27
- jac_client/examples/basic-auth/.babelrc +0 -9
- jac_client/examples/basic-auth/README.md +0 -16
- jac_client/examples/basic-auth/app.jac +0 -308
- jac_client/examples/basic-auth/package.json +0 -27
- jac_client/examples/basic-auth/vite.config.js +0 -27
- jac_client/examples/basic-auth-with-router/.babelrc +0 -9
- jac_client/examples/basic-auth-with-router/README.md +0 -60
- jac_client/examples/basic-auth-with-router/package.json +0 -28
- jac_client/examples/basic-auth-with-router/vite.config.js +0 -27
- jac_client/examples/basic-full-stack/.babelrc +0 -9
- jac_client/examples/basic-full-stack/README.md +0 -18
- jac_client/examples/basic-full-stack/package.json +0 -28
- jac_client/examples/basic-full-stack/vite.config.js +0 -27
- jac_client/examples/css-styling/js-styling/.babelrc +0 -9
- jac_client/examples/css-styling/js-styling/README.md +0 -183
- jac_client/examples/css-styling/js-styling/package.json +0 -28
- jac_client/examples/css-styling/js-styling/styles.js +0 -100
- jac_client/examples/css-styling/js-styling/vite.config.js +0 -27
- jac_client/examples/css-styling/material-ui/.babelrc +0 -9
- jac_client/examples/css-styling/material-ui/README.md +0 -16
- jac_client/examples/css-styling/material-ui/package.json +0 -32
- jac_client/examples/css-styling/material-ui/vite.config.js +0 -27
- jac_client/examples/css-styling/pure-css/.babelrc +0 -9
- jac_client/examples/css-styling/pure-css/README.md +0 -16
- jac_client/examples/css-styling/pure-css/package.json +0 -28
- jac_client/examples/css-styling/pure-css/styles.css +0 -111
- jac_client/examples/css-styling/pure-css/vite.config.js +0 -27
- jac_client/examples/css-styling/sass-example/.babelrc +0 -9
- jac_client/examples/css-styling/sass-example/README.md +0 -16
- jac_client/examples/css-styling/sass-example/package.json +0 -29
- jac_client/examples/css-styling/sass-example/styles.scss +0 -153
- jac_client/examples/css-styling/sass-example/vite.config.js +0 -27
- jac_client/examples/css-styling/styled-components/.babelrc +0 -9
- jac_client/examples/css-styling/styled-components/README.md +0 -16
- jac_client/examples/css-styling/styled-components/package.json +0 -29
- jac_client/examples/css-styling/styled-components/styled.js +0 -90
- jac_client/examples/css-styling/styled-components/vite.config.js +0 -27
- jac_client/examples/css-styling/tailwind-example/.babelrc +0 -9
- jac_client/examples/css-styling/tailwind-example/README.md +0 -16
- jac_client/examples/css-styling/tailwind-example/global.css +0 -1
- jac_client/examples/css-styling/tailwind-example/package.json +0 -30
- jac_client/examples/css-styling/tailwind-example/vite.config.js +0 -29
- jac_client/examples/full-stack-with-auth/.babelrc +0 -9
- jac_client/examples/full-stack-with-auth/README.md +0 -16
- jac_client/examples/full-stack-with-auth/package.json +0 -28
- jac_client/examples/full-stack-with-auth/vite.config.js +0 -29
- jac_client/examples/little-x/package.json +0 -23
- jac_client/examples/little-x/submit-button.jac +0 -8
- jac_client/examples/nested-folders/nested-advance/.babelrc +0 -9
- jac_client/examples/nested-folders/nested-advance/README.md +0 -77
- jac_client/examples/nested-folders/nested-advance/package.json +0 -29
- jac_client/examples/nested-folders/nested-advance/vite.config.js +0 -28
- jac_client/examples/nested-folders/nested-basic/.babelrc +0 -9
- jac_client/examples/nested-folders/nested-basic/README.md +0 -183
- jac_client/examples/nested-folders/nested-basic/app.js +0 -7
- jac_client/examples/nested-folders/nested-basic/package.json +0 -28
- jac_client/examples/nested-folders/nested-basic/vite.config.js +0 -27
- jac_client/examples/with-router/.babelrc +0 -9
- jac_client/examples/with-router/README.md +0 -17
- jac_client/examples/with-router/package.json +0 -28
- jac_client/examples/with-router/vite.config.js +0 -27
- jac_client/plugin/cli.py +0 -244
- jac_client/plugin/client.py +0 -152
- jac_client/plugin/client_runtime.jac +0 -234
- jac_client/plugin/vite_client_bundle.py +0 -503
- jac_client/tests/fixtures/js_import/utils.js +0 -21
- jac_client/tests/fixtures/package-lock.json +0 -329
- jac_client/tests/fixtures/package.json +0 -11
- jac_client/tests/test_asset_examples.py +0 -322
- jac_client/tests/test_cl.py +0 -530
- jac_client/tests/test_create_jac_app.py +0 -131
- jac_client/tests/test_nested_file.py +0 -374
- jac_client-0.2.3.dist-info/RECORD +0 -171
- jac_client-0.2.3.dist-info/entry_points.txt +0 -4
jac_client/docs/imports.md
DELETED
|
@@ -1,1141 +0,0 @@
|
|
|
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!
|