jac-client 0.2.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (72) hide show
  1. jac_client/docs/README.md +659 -0
  2. jac_client/docs/advanced-state.md +1266 -0
  3. jac_client/docs/assets/pipe_line.png +0 -0
  4. jac_client/docs/guide-example/intro.md +117 -0
  5. jac_client/docs/guide-example/step-01-setup.md +260 -0
  6. jac_client/docs/guide-example/step-02-components.md +416 -0
  7. jac_client/docs/guide-example/step-03-styling.md +478 -0
  8. jac_client/docs/guide-example/step-04-todo-ui.md +477 -0
  9. jac_client/docs/guide-example/step-05-local-state.md +530 -0
  10. jac_client/docs/guide-example/step-06-events.md +750 -0
  11. jac_client/docs/guide-example/step-07-effects.md +469 -0
  12. jac_client/docs/guide-example/step-08-walkers.md +534 -0
  13. jac_client/docs/guide-example/step-09-authentication.md +586 -0
  14. jac_client/docs/guide-example/step-10-routing.md +540 -0
  15. jac_client/docs/guide-example/step-11-final.md +964 -0
  16. jac_client/docs/imports.md +1142 -0
  17. jac_client/docs/lifecycle-hooks.md +774 -0
  18. jac_client/docs/routing.md +660 -0
  19. jac_client/examples/basic/.babelrc +9 -0
  20. jac_client/examples/basic/README.md +16 -0
  21. jac_client/examples/basic/app.jac +16 -0
  22. jac_client/examples/basic/package.json +27 -0
  23. jac_client/examples/basic/vite.config.js +28 -0
  24. jac_client/examples/basic-auth/.babelrc +9 -0
  25. jac_client/examples/basic-auth/README.md +16 -0
  26. jac_client/examples/basic-auth/app.jac +308 -0
  27. jac_client/examples/basic-auth/package.json +27 -0
  28. jac_client/examples/basic-auth/vite.config.js +28 -0
  29. jac_client/examples/basic-auth-with-router/.babelrc +9 -0
  30. jac_client/examples/basic-auth-with-router/README.md +60 -0
  31. jac_client/examples/basic-auth-with-router/app.jac +464 -0
  32. jac_client/examples/basic-auth-with-router/package.json +28 -0
  33. jac_client/examples/basic-auth-with-router/vite.config.js +28 -0
  34. jac_client/examples/basic-full-stack/.babelrc +9 -0
  35. jac_client/examples/basic-full-stack/README.md +18 -0
  36. jac_client/examples/basic-full-stack/app.jac +320 -0
  37. jac_client/examples/basic-full-stack/package.json +28 -0
  38. jac_client/examples/basic-full-stack/vite.config.js +28 -0
  39. jac_client/examples/full-stack-with-auth/.babelrc +9 -0
  40. jac_client/examples/full-stack-with-auth/README.md +16 -0
  41. jac_client/examples/full-stack-with-auth/app.jac +735 -0
  42. jac_client/examples/full-stack-with-auth/package.json +28 -0
  43. jac_client/examples/full-stack-with-auth/vite.config.js +30 -0
  44. jac_client/examples/little-x/app.jac +615 -0
  45. jac_client/examples/little-x/package.json +23 -0
  46. jac_client/examples/little-x/submit-button.jac +8 -0
  47. jac_client/examples/with-router/.babelrc +9 -0
  48. jac_client/examples/with-router/README.md +17 -0
  49. jac_client/examples/with-router/app.jac +323 -0
  50. jac_client/examples/with-router/package.json +28 -0
  51. jac_client/examples/with-router/vite.config.js +28 -0
  52. jac_client/plugin/cli.py +239 -0
  53. jac_client/plugin/client.py +89 -0
  54. jac_client/plugin/client_runtime.jac +234 -0
  55. jac_client/plugin/vite_client_bundle.py +355 -0
  56. jac_client/tests/__init__.py +2 -0
  57. jac_client/tests/fixtures/basic-app/app.jac +18 -0
  58. jac_client/tests/fixtures/client_app_with_antd/app.jac +28 -0
  59. jac_client/tests/fixtures/js_import/app.jac +30 -0
  60. jac_client/tests/fixtures/js_import/utils.js +22 -0
  61. jac_client/tests/fixtures/package-lock.json +329 -0
  62. jac_client/tests/fixtures/package.json +11 -0
  63. jac_client/tests/fixtures/relative_import/app.jac +13 -0
  64. jac_client/tests/fixtures/relative_import/button.jac +6 -0
  65. jac_client/tests/fixtures/spawn_test/app.jac +133 -0
  66. jac_client/tests/fixtures/test_fragments_spread/app.jac +53 -0
  67. jac_client/tests/test_cl.py +476 -0
  68. jac_client/tests/test_create_jac_app.py +139 -0
  69. jac_client-0.2.0.dist-info/METADATA +182 -0
  70. jac_client-0.2.0.dist-info/RECORD +72 -0
  71. jac_client-0.2.0.dist-info/WHEEL +4 -0
  72. jac_client-0.2.0.dist-info/entry_points.txt +4 -0
@@ -0,0 +1,416 @@
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)**