jac-client 0.2.2__py3-none-any.whl → 0.2.4__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 (176) hide show
  1. jac_client/examples/all-in-one/assets/workers/worker.py +5 -0
  2. jac_client/tests/conftest.py +281 -0
  3. jac_client/tests/test_cli.py +755 -0
  4. jac_client/tests/test_it.py +347 -67
  5. {jac_client-0.2.2.dist-info → jac_client-0.2.4.dist-info}/METADATA +30 -24
  6. jac_client-0.2.4.dist-info/RECORD +10 -0
  7. {jac_client-0.2.2.dist-info → jac_client-0.2.4.dist-info}/WHEEL +2 -1
  8. jac_client-0.2.4.dist-info/entry_points.txt +4 -0
  9. jac_client-0.2.4.dist-info/top_level.txt +1 -0
  10. jac_client/docs/README.md +0 -689
  11. jac_client/docs/advanced-state.md +0 -1265
  12. jac_client/docs/asset-serving/intro.md +0 -209
  13. jac_client/docs/assets/pipe_line-v2.svg +0 -32
  14. jac_client/docs/assets/pipe_line.png +0 -0
  15. jac_client/docs/file-system/app.jac.md +0 -121
  16. jac_client/docs/file-system/backend-frontend.md +0 -217
  17. jac_client/docs/file-system/intro.md +0 -72
  18. jac_client/docs/file-system/nested-imports.md +0 -348
  19. jac_client/docs/guide-example/intro.md +0 -115
  20. jac_client/docs/guide-example/step-01-setup.md +0 -270
  21. jac_client/docs/guide-example/step-02-components.md +0 -416
  22. jac_client/docs/guide-example/step-03-styling.md +0 -478
  23. jac_client/docs/guide-example/step-04-todo-ui.md +0 -477
  24. jac_client/docs/guide-example/step-05-local-state.md +0 -530
  25. jac_client/docs/guide-example/step-06-events.md +0 -749
  26. jac_client/docs/guide-example/step-07-effects.md +0 -468
  27. jac_client/docs/guide-example/step-08-walkers.md +0 -534
  28. jac_client/docs/guide-example/step-09-authentication.md +0 -586
  29. jac_client/docs/guide-example/step-10-routing.md +0 -539
  30. jac_client/docs/guide-example/step-11-final.md +0 -963
  31. jac_client/docs/imports.md +0 -1141
  32. jac_client/docs/lifecycle-hooks.md +0 -773
  33. jac_client/docs/routing.md +0 -659
  34. jac_client/docs/styling/intro.md +0 -249
  35. jac_client/docs/styling/js-styling.md +0 -367
  36. jac_client/docs/styling/material-ui.md +0 -341
  37. jac_client/docs/styling/pure-css.md +0 -299
  38. jac_client/docs/styling/sass.md +0 -403
  39. jac_client/docs/styling/styled-components.md +0 -395
  40. jac_client/docs/styling/tailwind.md +0 -298
  41. jac_client/examples/all-in-one/.babelrc +0 -9
  42. jac_client/examples/all-in-one/README.md +0 -16
  43. jac_client/examples/all-in-one/app.jac +0 -426
  44. jac_client/examples/all-in-one/assets/burger.png +0 -0
  45. jac_client/examples/all-in-one/button.jac +0 -7
  46. jac_client/examples/all-in-one/components/button.jac +0 -7
  47. jac_client/examples/all-in-one/package.json +0 -29
  48. jac_client/examples/all-in-one/styles.css +0 -26
  49. jac_client/examples/all-in-one/vite.config.js +0 -28
  50. jac_client/examples/asset-serving/css-with-image/.babelrc +0 -9
  51. jac_client/examples/asset-serving/css-with-image/README.md +0 -91
  52. jac_client/examples/asset-serving/css-with-image/app.jac +0 -88
  53. jac_client/examples/asset-serving/css-with-image/assets/burger.png +0 -0
  54. jac_client/examples/asset-serving/css-with-image/package.json +0 -28
  55. jac_client/examples/asset-serving/css-with-image/styles.css +0 -26
  56. jac_client/examples/asset-serving/css-with-image/vite.config.js +0 -28
  57. jac_client/examples/asset-serving/image-asset/.babelrc +0 -9
  58. jac_client/examples/asset-serving/image-asset/README.md +0 -119
  59. jac_client/examples/asset-serving/image-asset/app.jac +0 -55
  60. jac_client/examples/asset-serving/image-asset/assets/burger.png +0 -0
  61. jac_client/examples/asset-serving/image-asset/package.json +0 -28
  62. jac_client/examples/asset-serving/image-asset/styles.css +0 -26
  63. jac_client/examples/asset-serving/image-asset/vite.config.js +0 -28
  64. jac_client/examples/asset-serving/import-alias/.babelrc +0 -9
  65. jac_client/examples/asset-serving/import-alias/README.md +0 -83
  66. jac_client/examples/asset-serving/import-alias/app.jac +0 -111
  67. jac_client/examples/asset-serving/import-alias/assets/burger.png +0 -0
  68. jac_client/examples/asset-serving/import-alias/package.json +0 -28
  69. jac_client/examples/asset-serving/import-alias/vite.config.js +0 -28
  70. jac_client/examples/basic/.babelrc +0 -9
  71. jac_client/examples/basic/README.md +0 -16
  72. jac_client/examples/basic/app.jac +0 -21
  73. jac_client/examples/basic/package.json +0 -27
  74. jac_client/examples/basic/vite.config.js +0 -27
  75. jac_client/examples/basic-auth/.babelrc +0 -9
  76. jac_client/examples/basic-auth/README.md +0 -16
  77. jac_client/examples/basic-auth/app.jac +0 -308
  78. jac_client/examples/basic-auth/package.json +0 -27
  79. jac_client/examples/basic-auth/vite.config.js +0 -27
  80. jac_client/examples/basic-auth-with-router/.babelrc +0 -9
  81. jac_client/examples/basic-auth-with-router/README.md +0 -60
  82. jac_client/examples/basic-auth-with-router/app.jac +0 -464
  83. jac_client/examples/basic-auth-with-router/package.json +0 -28
  84. jac_client/examples/basic-auth-with-router/vite.config.js +0 -27
  85. jac_client/examples/basic-full-stack/.babelrc +0 -9
  86. jac_client/examples/basic-full-stack/README.md +0 -18
  87. jac_client/examples/basic-full-stack/app.jac +0 -320
  88. jac_client/examples/basic-full-stack/package.json +0 -28
  89. jac_client/examples/basic-full-stack/vite.config.js +0 -27
  90. jac_client/examples/css-styling/js-styling/.babelrc +0 -9
  91. jac_client/examples/css-styling/js-styling/README.md +0 -183
  92. jac_client/examples/css-styling/js-styling/app.jac +0 -84
  93. jac_client/examples/css-styling/js-styling/package.json +0 -28
  94. jac_client/examples/css-styling/js-styling/styles.js +0 -100
  95. jac_client/examples/css-styling/js-styling/vite.config.js +0 -27
  96. jac_client/examples/css-styling/material-ui/.babelrc +0 -9
  97. jac_client/examples/css-styling/material-ui/README.md +0 -16
  98. jac_client/examples/css-styling/material-ui/app.jac +0 -122
  99. jac_client/examples/css-styling/material-ui/package.json +0 -32
  100. jac_client/examples/css-styling/material-ui/vite.config.js +0 -27
  101. jac_client/examples/css-styling/pure-css/.babelrc +0 -9
  102. jac_client/examples/css-styling/pure-css/README.md +0 -16
  103. jac_client/examples/css-styling/pure-css/app.jac +0 -64
  104. jac_client/examples/css-styling/pure-css/package.json +0 -28
  105. jac_client/examples/css-styling/pure-css/styles.css +0 -111
  106. jac_client/examples/css-styling/pure-css/vite.config.js +0 -27
  107. jac_client/examples/css-styling/sass-example/.babelrc +0 -9
  108. jac_client/examples/css-styling/sass-example/README.md +0 -16
  109. jac_client/examples/css-styling/sass-example/app.jac +0 -64
  110. jac_client/examples/css-styling/sass-example/package.json +0 -29
  111. jac_client/examples/css-styling/sass-example/styles.scss +0 -153
  112. jac_client/examples/css-styling/sass-example/vite.config.js +0 -27
  113. jac_client/examples/css-styling/styled-components/.babelrc +0 -9
  114. jac_client/examples/css-styling/styled-components/README.md +0 -16
  115. jac_client/examples/css-styling/styled-components/app.jac +0 -71
  116. jac_client/examples/css-styling/styled-components/package.json +0 -29
  117. jac_client/examples/css-styling/styled-components/styled.js +0 -90
  118. jac_client/examples/css-styling/styled-components/vite.config.js +0 -27
  119. jac_client/examples/css-styling/tailwind-example/.babelrc +0 -9
  120. jac_client/examples/css-styling/tailwind-example/README.md +0 -16
  121. jac_client/examples/css-styling/tailwind-example/app.jac +0 -63
  122. jac_client/examples/css-styling/tailwind-example/global.css +0 -1
  123. jac_client/examples/css-styling/tailwind-example/package.json +0 -30
  124. jac_client/examples/css-styling/tailwind-example/vite.config.js +0 -29
  125. jac_client/examples/full-stack-with-auth/.babelrc +0 -9
  126. jac_client/examples/full-stack-with-auth/README.md +0 -16
  127. jac_client/examples/full-stack-with-auth/app.jac +0 -722
  128. jac_client/examples/full-stack-with-auth/package.json +0 -28
  129. jac_client/examples/full-stack-with-auth/vite.config.js +0 -29
  130. jac_client/examples/little-x/app.jac +0 -724
  131. jac_client/examples/little-x/package.json +0 -23
  132. jac_client/examples/little-x/submit-button.jac +0 -8
  133. jac_client/examples/nested-folders/nested-advance/.babelrc +0 -9
  134. jac_client/examples/nested-folders/nested-advance/ButtonRoot.jac +0 -11
  135. jac_client/examples/nested-folders/nested-advance/README.md +0 -77
  136. jac_client/examples/nested-folders/nested-advance/app.jac +0 -35
  137. jac_client/examples/nested-folders/nested-advance/level1/ButtonSecondL.jac +0 -19
  138. jac_client/examples/nested-folders/nested-advance/level1/Card.jac +0 -43
  139. jac_client/examples/nested-folders/nested-advance/level1/level2/ButtonThirdL.jac +0 -25
  140. jac_client/examples/nested-folders/nested-advance/package.json +0 -29
  141. jac_client/examples/nested-folders/nested-advance/vite.config.js +0 -28
  142. jac_client/examples/nested-folders/nested-basic/.babelrc +0 -9
  143. jac_client/examples/nested-folders/nested-basic/README.md +0 -183
  144. jac_client/examples/nested-folders/nested-basic/app.jac +0 -13
  145. jac_client/examples/nested-folders/nested-basic/app.js +0 -7
  146. jac_client/examples/nested-folders/nested-basic/button.jac +0 -7
  147. jac_client/examples/nested-folders/nested-basic/components/button.jac +0 -7
  148. jac_client/examples/nested-folders/nested-basic/package.json +0 -28
  149. jac_client/examples/nested-folders/nested-basic/vite.config.js +0 -27
  150. jac_client/examples/with-router/.babelrc +0 -9
  151. jac_client/examples/with-router/README.md +0 -17
  152. jac_client/examples/with-router/app.jac +0 -323
  153. jac_client/examples/with-router/package.json +0 -28
  154. jac_client/examples/with-router/vite.config.js +0 -27
  155. jac_client/plugin/cli.py +0 -244
  156. jac_client/plugin/client.py +0 -152
  157. jac_client/plugin/client_runtime.jac +0 -234
  158. jac_client/plugin/vite_client_bundle.py +0 -503
  159. jac_client/tests/fixtures/basic-app/app.jac +0 -23
  160. jac_client/tests/fixtures/cl_file/app.cl.jac +0 -48
  161. jac_client/tests/fixtures/cl_file/app.jac +0 -15
  162. jac_client/tests/fixtures/client_app_with_antd/app.jac +0 -34
  163. jac_client/tests/fixtures/js_import/app.jac +0 -34
  164. jac_client/tests/fixtures/js_import/utils.js +0 -21
  165. jac_client/tests/fixtures/package-lock.json +0 -329
  166. jac_client/tests/fixtures/package.json +0 -11
  167. jac_client/tests/fixtures/relative_import/app.jac +0 -11
  168. jac_client/tests/fixtures/relative_import/button.jac +0 -7
  169. jac_client/tests/fixtures/spawn_test/app.jac +0 -129
  170. jac_client/tests/fixtures/test_fragments_spread/app.jac +0 -67
  171. jac_client/tests/test_asset_examples.py +0 -322
  172. jac_client/tests/test_cl.py +0 -530
  173. jac_client/tests/test_create_jac_app.py +0 -131
  174. jac_client/tests/test_nested_file.py +0 -374
  175. jac_client-0.2.2.dist-info/RECORD +0 -171
  176. jac_client-0.2.2.dist-info/entry_points.txt +0 -4
@@ -1,270 +0,0 @@
1
- # Step 1: Project Setup
2
-
3
- > ** Quick Tip:** Each step has two parts. **Part 1** shows you what to build. **Part 2** explains why it works. Want to just build? Skip all Part 2 sections!
4
-
5
- In this first step, you'll create your Jac project and understand the basic file structure.
6
-
7
- ---
8
-
9
- ## Part 1: Building the App
10
-
11
- ### Step 1.1: Create Your Project
12
-
13
- Open your terminal and run:
14
-
15
- ```bash
16
- jac create_jac_app todo-app
17
- ```
18
-
19
- This creates a new directory called `todo-app` with everything you need.
20
-
21
- ### Step 1.2: Navigate to Your Project
22
-
23
- ```bash
24
- cd todo-app
25
- ```
26
-
27
- ### Step 1.3: Understand the Structure
28
-
29
- Your project now has these files:
30
-
31
- ```
32
- todo-app/
33
- ├── app.jac # Your main application file (we'll work here!)
34
- ├── package.json # Node.js dependencies (auto-managed)
35
- ├── vite.config.js # Build configuration (you can ignore this)
36
- └── README.md # Basic instructions
37
- ```
38
-
39
- **Important**: We'll write ALL our code in `app.jac` - that's it!
40
-
41
- ### Step 1.4: Create Your First App
42
-
43
- Open `app.jac` in your code editor and replace everything with this:
44
-
45
- ```jac
46
- cl {
47
- def app() -> any {
48
- return <div>
49
- <h1>Hello, Jac!</h1>
50
- <p>My first full-stack app</p>
51
- </div>;
52
- }
53
- }
54
- ```
55
-
56
- ### Step 1.5: Run Your App
57
-
58
- In your terminal, run:
59
-
60
- ```bash
61
- jac serve app.jac
62
- ```
63
-
64
- You'll see output like:
65
-
66
- ```
67
- INFO: Started server process [12345]
68
- INFO: Waiting for application startup.
69
- INFO: Application startup complete.
70
- INFO: Uvicorn running on http://127.0.0.1:8000
71
- ```
72
-
73
- ### Step 1.6: View in Browser
74
-
75
- Open your browser and go to:
76
-
77
- ```
78
- http://localhost:8000/page/app
79
- ```
80
-
81
- You should see "Hello, Jac!" and "My first full-stack app"
82
-
83
- ---
84
-
85
- **⏭ Want to skip the theory?** Jump to [Step 2: First Component](./step-02-components.md)
86
-
87
- ---
88
-
89
- ## Part 2: Understanding the Concepts
90
-
91
- ### What is `cl { ... }`?
92
-
93
- `cl` stands for "client" - it means this code runs in the **browser** (frontend).
94
-
95
- ```jac
96
- cl {
97
- # Everything here runs on the client-side (browser)
98
- }
99
- ```
100
-
101
- Think of it like this:
102
-
103
- - Code **inside** `cl { }` → Runs in the browser (frontend)
104
- - Code **outside** `cl { }` → Runs on the server (backend)
105
-
106
- ### What is `def app() -> any`?
107
-
108
- This is your **main entry point** - the function that Jac calls first.
109
-
110
- ```jac
111
- def app() -> any {
112
- return <div>...</div>;
113
- }
114
- ```
115
-
116
- **Requirements:**
117
-
118
- - Must be named `app` (by convention)
119
- - Must return JSX (HTML-like syntax)
120
- - Located inside `cl { }` block
121
-
122
- **Python analogy:**
123
-
124
- ```python
125
- # Python
126
- if __name__ == "__main__":
127
- run_app()
128
-
129
- # Jac
130
- def app() -> any {
131
- # Start here
132
- }
133
- ```
134
-
135
- ### What is JSX?
136
-
137
- JSX lets you write HTML directly in your Jac code:
138
-
139
- ```jac
140
- return <div>
141
- <h1>This is HTML!</h1>
142
- <p>But written in Jac code</p>
143
- </div>;
144
- ```
145
-
146
- **Key rules:**
147
-
148
- 1. Must have **one root element**
149
-
150
- ```jac
151
- # Correct
152
- return <div><h1>Title</h1><p>Text</p></div>;
153
-
154
- # Wrong (two root elements)
155
- return <h1>Title</h1><p>Text</p>;
156
- ```
157
-
158
- 2. Self-closing tags need `/`
159
-
160
- ```jac
161
- <img src="photo.jpg" /> # Correct
162
- <img src="photo.jpg"> # Wrong
163
- ```
164
-
165
- 3. Use `{}` to insert Jac code
166
- ```jac
167
- let name = "Alice";
168
- return <h1>Hello, {name}!</h1>; # Shows: Hello, Alice!
169
- ```
170
-
171
- ### How `jac serve` Works
172
-
173
- When you run `jac serve app.jac`:
174
-
175
- 1. **Jac compiler** reads your `.jac` file
176
- 2. **Frontend code** (inside `cl`) → Compiled to JavaScript
177
- 3. **Backend code** (outside `cl`) → Stays as Python-like backend code
178
- 4. **Single server** serves both on port 8000
179
- 5. **Auto-reload** watches for file changes (coming soon...)
180
-
181
- It's like running a Flask/FastAPI server, but it ALSO compiles and serves your React frontend - all in one command!
182
-
183
- ### File Organization
184
-
185
- For now, everything goes in `app.jac`. As your app grows, you can split into multiple files:
186
-
187
- ```
188
- todo-app/
189
- ├── app.jac # Main app
190
- ├── components.jac # Reusable components
191
- └── walkers.jac # Backend logic
192
- ```
193
-
194
- But for this tutorial, we'll keep everything in one file for simplicity.
195
-
196
- ---
197
-
198
- ## What You've Learned
199
-
200
- - How to create a Jac project
201
- - Project structure basics
202
- - What `cl { }` means (client-side code)
203
- - The `def app()` entry point
204
- - JSX basics (HTML in code)
205
- - Running your app with `jac serve`
206
-
207
- ---
208
-
209
- ## Common Issues
210
-
211
- ### Issue: `jac: command not found`
212
-
213
- **Solution**: Install jac-client:
214
-
215
- ```bash
216
- pip install jac-client
217
- ```
218
-
219
- ### Issue: Port 8000 already in use
220
-
221
- **Solution**: Use a different port:
222
-
223
- ```bash
224
- jac serve app.jac --port 8080
225
- ```
226
-
227
- Then visit `http://localhost:8080/page/app`
228
-
229
- ### Issue: Blank page in browser
230
-
231
- **Check:**
232
-
233
- - Did you visit `/page/app` (not just `/`)?
234
- - Check terminal for errors
235
- - Make sure `app()` has a `return` statement
236
-
237
- ### Issue: Changes not showing
238
-
239
- **Solution**:
240
-
241
- - Stop the server (Ctrl+C)
242
- - Restart: `jac serve app.jac`
243
- - Refresh browser
244
-
245
- ---
246
-
247
- ## Quick Exercise
248
-
249
- Before moving on, try changing the text:
250
-
251
- ```jac
252
- cl {
253
- def app() -> any {
254
- return <div>
255
- <h1>My Todo App</h1>
256
- <p>Built with Jac</p>
257
- </div>;
258
- }
259
- }
260
- ```
261
-
262
- Save, refresh your browser, and see the changes!
263
-
264
- ---
265
-
266
- ## Next Step
267
-
268
- Great! You have a running Jac app. Now let's learn about **components** - the building blocks of any UI.
269
-
270
- **[Continue to Step 2: First Component](./step-02-components.md)**
@@ -1,416 +0,0 @@
1
- # Step 2: First Component
2
-
3
- > ** Quick Tip:** Each step has two parts. **Part 1** shows you what to build. **Part 2** explains why it works. Want to just build? Skip all Part 2 sections!
4
-
5
- In this step, you'll create your first reusable component - a **TodoItem** that displays a single todo.
6
-
7
- ---
8
-
9
- ## Part 1: Building the App
10
-
11
- ### Step 2.1: Create a TodoItem Component
12
-
13
- Update your `app.jac`:
14
-
15
- ```jac
16
- cl {
17
- # A component to display a single todo
18
- def TodoItem(props: any) -> any {
19
- return <div>
20
- <input type="checkbox" />
21
- <span>Learn Jac basics</span>
22
- <button>Delete</button>
23
- </div>;
24
- }
25
-
26
- def app() -> any {
27
- return <div>
28
- <h1>My Todos</h1>
29
- <TodoItem />
30
- </div>;
31
- }
32
- }
33
- ```
34
-
35
- **Try it!** Save and refresh your browser. You should see a todo item with a checkbox, text, and delete button.
36
-
37
- ### Step 2.2: Make It Reusable with Props
38
-
39
- Now let's make the TodoItem display different text:
40
-
41
- ```jac
42
- cl {
43
- # Component that accepts data via props
44
- def TodoItem(props: any) -> any {
45
- return <div>
46
- <input type="checkbox" checked={props.done} />
47
- <span>{props.text}</span>
48
- <button>Delete</button>
49
- </div>;
50
- }
51
-
52
- def app() -> any {
53
- return <div>
54
- <h1>My Todos</h1>
55
- <TodoItem text="Learn Jac basics" done={false} />
56
- <TodoItem text="Build a todo app" done={false} />
57
- <TodoItem text="Deploy to production" done={true} />
58
- </div>;
59
- }
60
- }
61
- ```
62
-
63
- **Try it!** You should now see three different todos. Notice how the third one has the checkbox checked!
64
-
65
- ### Step 2.3: Create Multiple Components
66
-
67
- Let's add more components to organize our app:
68
-
69
- ```jac
70
- cl {
71
- # Component 1: TodoInput (input field + Add button)
72
- def TodoInput(props: any) -> any {
73
- return <div>
74
- <input type="text" placeholder="What needs to be done?" />
75
- <button>Add</button>
76
- </div>;
77
- }
78
-
79
- # Component 2: TodoFilters (filter buttons)
80
- def TodoFilters(props: any) -> any {
81
- return <div>
82
- <button>All</button>
83
- <button>Active</button>
84
- <button>Completed</button>
85
- </div>;
86
- }
87
-
88
- # Component 3: TodoItem (single todo)
89
- def TodoItem(props: any) -> any {
90
- return <div>
91
- <input type="checkbox" checked={props.done} />
92
- <span>{props.text}</span>
93
- <button>Delete</button>
94
- </div>;
95
- }
96
-
97
- # Component 4: TodoList (list of todos)
98
- def TodoList(props: any) -> any {
99
- return <div>
100
- <TodoItem text="Learn Jac basics" done={true} />
101
- <TodoItem text="Build a todo app" done={false} />
102
- <TodoItem text="Deploy to production" done={false} />
103
- </div>;
104
- }
105
-
106
- # Main app - combines all components
107
- def app() -> any {
108
- return <div>
109
- <h1>My Todos</h1>
110
- <TodoInput />
111
- <TodoFilters />
112
- <TodoList />
113
- </div>;
114
- }
115
- }
116
- ```
117
-
118
- **Try it!** Your app now has a clear structure with separate components.
119
-
120
- ---
121
-
122
- **⏭ Want to skip the theory?** Jump to [Step 3: Styling](./step-03-styling.md)
123
-
124
- ---
125
-
126
- ## Part 2: Understanding the Concepts
127
-
128
- ### What is a Component?
129
-
130
- A component is a **function that returns UI (JSX)**.
131
-
132
- Think of components like Python functions:
133
-
134
- ```python
135
- # Python - returns text
136
- def greet_user(name):
137
- return f"Hello, {name}!"
138
-
139
- print(greet_user("Alice")) # Hello, Alice!
140
- print(greet_user("Bob")) # Hello, Bob!
141
- ```
142
-
143
- ```jac
144
- # Jac - returns UI
145
- def TodoItem(props: any) -> any {
146
- return <div>{props.text}</div>;
147
- }
148
-
149
- # Usage
150
- <TodoItem text="Learn Jac" />
151
- <TodoItem text="Build app" />
152
- ```
153
-
154
- ### Why Use Components?
155
-
156
- **1. Reusability** - Write once, use many times
157
-
158
- ```jac
159
- <TodoItem text="Task 1" done={false} />
160
- <TodoItem text="Task 2" done={true} />
161
- <TodoItem text="Task 3" done={false} />
162
- ```
163
-
164
- **2. Organization** - Break complex UI into manageable pieces
165
-
166
- ```jac
167
- app
168
- ├── TodoInput
169
- ├── TodoFilters
170
- └── TodoList
171
- ├── TodoItem
172
- ├── TodoItem
173
- └── TodoItem
174
- ```
175
-
176
- **3. Maintainability** - Easy to find and fix bugs
177
-
178
- If there's a bug in how todos display, you know to check `TodoItem`.
179
-
180
- ### Component Naming Rules
181
-
182
- **1. Use PascalCase** (first letter capitalized)
183
-
184
- ```jac
185
- # Correct
186
- def TodoItem() -> any { ... }
187
- def UserProfile() -> any { ... }
188
- def NavigationBar() -> any { ... }
189
-
190
- # Wrong
191
- def todoItem() -> any { ... } # camelCase
192
- def user_profile() -> any { ... } # snake_case
193
- def navigation-bar() -> any { ... } # kebab-case
194
- ```
195
-
196
- **2. Name describes what it does**
197
-
198
- ```jac
199
- # Good names
200
- def TodoItem() -> any { ... }
201
- def LoginForm() -> any { ... }
202
- def ProductCard() -> any { ... }
203
-
204
- # Bad names
205
- def Component1() -> any { ... }
206
- def Thing() -> any { ... }
207
- def X() -> any { ... }
208
- ```
209
-
210
- ### Understanding Props
211
-
212
- **Props** = "Properties" = Data passed to a component
213
-
214
- ```jac
215
- # Passing props (like function arguments)
216
- <TodoItem text="Learn Jac" done={false} />
217
-
218
- # Receiving props (in the component)
219
- def TodoItem(props: any) -> any {
220
- let text = props.text; # "Learn Jac"
221
- let done = props.done; # false
222
- return <div>{text}</div>;
223
- }
224
- ```
225
-
226
- **Important**: In React (which Jac uses), components receive props as a **single object**, not individual parameters.
227
-
228
- ```jac
229
- # Correct way
230
- def TodoItem(props: any) -> any {
231
- let text = props.text;
232
- let done = props.done;
233
- # ...
234
- }
235
-
236
- # Wrong way (won't work)
237
- def TodoItem(text: str, done: bool) -> any {
238
- # This doesn't work in React!
239
- }
240
- ```
241
-
242
- ### Accessing Props
243
-
244
- Three ways to access props:
245
-
246
- **Method 1: Direct access**
247
-
248
- ```jac
249
- def TodoItem(props: any) -> any {
250
- return <span>{props.text}</span>;
251
- }
252
- ```
253
-
254
- **Method 2: Extract to variables**
255
-
256
- ```jac
257
- def TodoItem(props: any) -> any {
258
- let text = props.text;
259
- let done = props.done;
260
- return <span>{text}</span>;
261
- }
262
- ```
263
-
264
- **Method 3: Dictionary access (explicit)**
265
-
266
- ```jac
267
- def TodoItem(props: any) -> any {
268
- let text = props["text"];
269
- let done = props["done"];
270
- return <span>{text}</span>;
271
- }
272
- ```
273
-
274
- All three ways work! Use whichever feels clearest to you.
275
-
276
- ### Composing Components
277
-
278
- You can nest components inside other components:
279
-
280
- ```jac
281
- # TodoList uses TodoItem
282
- def TodoList() -> any {
283
- return <div>
284
- <TodoItem text="Task 1" done={false} />
285
- <TodoItem text="Task 2" done={true} />
286
- </div>;
287
- }
288
-
289
- # App uses TodoList
290
- def app() -> any {
291
- return <div>
292
- <h1>My Todos</h1>
293
- <TodoList />
294
- </div>;
295
- }
296
- ```
297
-
298
- This creates a hierarchy:
299
-
300
- ```
301
- app
302
- └── TodoList
303
- ├── TodoItem
304
- └── TodoItem
305
- ```
306
-
307
- ### Using JSX in Props
308
-
309
- You can pass any value as props:
310
-
311
- ```jac
312
- # String
313
- <TodoItem text="Hello" />
314
-
315
- # Number
316
- <TodoItem count={42} />
317
-
318
- # Boolean
319
- <TodoItem done={true} />
320
-
321
- # Variable
322
- let myText = "Learn Jac";
323
- <TodoItem text={myText} />
324
-
325
- # Expression
326
- <TodoItem priority={5 + 3} />
327
- ```
328
-
329
- ---
330
-
331
- ## What You've Learned
332
-
333
- - Components are functions that return UI
334
- - How to create a component
335
- - PascalCase naming convention
336
- - Passing data to components with props
337
- - Receiving props as a single object
338
- - Composing components (nesting)
339
- - Organizing app into multiple components
340
-
341
- ---
342
-
343
- ## Common Issues
344
-
345
- ### Issue: Component not showing up
346
-
347
- **Check:**
348
- - Is the name in PascalCase? `TodoItem` not `todoItem`
349
- - Did you use `<TodoItem />` (with angle brackets)?
350
- - Does it have a `return` statement?
351
-
352
- ### Issue: "object with keys {text, done}"
353
-
354
- **Cause**: Using individual parameters instead of props object
355
-
356
- ```jac
357
- # Wrong
358
- def TodoItem(text: str, done: bool) -> any {
359
- # ...
360
- }
361
-
362
- # Correct
363
- def TodoItem(props: any) -> any {
364
- let text = props.text;
365
- # ...
366
- }
367
- ```
368
-
369
- ### Issue: Props are undefined
370
-
371
- **Check:**
372
- - Did you pass the props when using the component?
373
- - Are the prop names spelled the same in both places?
374
-
375
- ```jac
376
- # Passing props
377
- <TodoItem text="Learn" done={false} />
378
-
379
- # Receiving props (names must match!)
380
- def TodoItem(props: any) -> any {
381
- props.text # "Learn"
382
- props.done # false
383
- }
384
- ```
385
-
386
- ---
387
-
388
- ## Quick Exercise
389
-
390
- Try adding a new component:
391
-
392
- ```jac
393
- def TodoStats(props: any) -> any {
394
- return <div>
395
- <p>Total: {props.total}</p>
396
- <p>Completed: {props.completed}</p>
397
- </div>;
398
- }
399
-
400
- # Use it in app
401
- def app() -> any {
402
- return <div>
403
- <h1>My Todos</h1>
404
- <TodoStats total={3} completed={1} />
405
- # ... rest of your components
406
- </div>;
407
- }
408
- ```
409
-
410
- ---
411
-
412
- ## Next Step
413
-
414
- Great! You can now create and organize components. But they look plain. Let's make them beautiful with **styling**!
415
-
416
- **[Continue to Step 3: Styling](./step-03-styling.md)**