jac-client 0.2.6__py3-none-any.whl → 0.2.11__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 (119) hide show
  1. jac_client/examples/all-in-one/{src/button.jac → button.jac} +4 -3
  2. jac_client/examples/all-in-one/components/CategoryFilter.jac +47 -0
  3. jac_client/examples/all-in-one/components/Header.jac +17 -0
  4. jac_client/examples/all-in-one/components/ProfitOverview.jac +64 -0
  5. jac_client/examples/all-in-one/components/Summary.jac +76 -0
  6. jac_client/examples/all-in-one/components/TransactionForm.jac +188 -0
  7. jac_client/examples/all-in-one/components/TransactionItem.jac +62 -0
  8. jac_client/examples/all-in-one/components/TransactionList.jac +44 -0
  9. jac_client/examples/all-in-one/components/button.jac +8 -0
  10. jac_client/examples/all-in-one/components/navigation.jac +126 -0
  11. jac_client/examples/all-in-one/constants/categories.jac +36 -0
  12. jac_client/examples/all-in-one/constants/clients.jac +12 -0
  13. jac_client/examples/all-in-one/context/BudgetContext.jac +31 -0
  14. jac_client/examples/all-in-one/hooks/useBudget.jac +122 -0
  15. jac_client/examples/all-in-one/hooks/useLocalStorage.jac +37 -0
  16. jac_client/examples/all-in-one/main.jac +542 -0
  17. jac_client/examples/all-in-one/pages/BudgetPlanner.jac +140 -0
  18. jac_client/examples/all-in-one/pages/FeaturesTest.jac +157 -0
  19. jac_client/examples/all-in-one/pages/LandingPage.jac +124 -0
  20. jac_client/examples/all-in-one/pages/budget_planner_ui.cl.jac +65 -0
  21. jac_client/examples/all-in-one/pages/features_test_ui.cl.jac +675 -0
  22. jac_client/examples/all-in-one/pages/loginPage.jac +127 -0
  23. jac_client/examples/all-in-one/pages/nestedDemo.jac +54 -0
  24. jac_client/examples/all-in-one/pages/notFound.jac +18 -0
  25. jac_client/examples/all-in-one/pages/signupPage.jac +127 -0
  26. jac_client/examples/all-in-one/utils/formatters.jac +49 -0
  27. jac_client/examples/asset-serving/css-with-image/main.jac +92 -0
  28. jac_client/examples/asset-serving/image-asset/main.jac +56 -0
  29. jac_client/examples/asset-serving/import-alias/main.jac +109 -0
  30. jac_client/examples/basic/main.jac +23 -0
  31. jac_client/examples/basic-auth/main.jac +363 -0
  32. jac_client/examples/basic-auth-with-router/main.jac +451 -0
  33. jac_client/examples/basic-full-stack/main.jac +362 -0
  34. jac_client/examples/css-styling/js-styling/main.jac +63 -0
  35. jac_client/examples/css-styling/material-ui/main.jac +122 -0
  36. jac_client/examples/css-styling/pure-css/main.jac +55 -0
  37. jac_client/examples/css-styling/sass-example/main.jac +55 -0
  38. jac_client/examples/css-styling/styled-components/main.jac +62 -0
  39. jac_client/examples/css-styling/tailwind-example/main.jac +74 -0
  40. jac_client/examples/full-stack-with-auth/main.jac +696 -0
  41. jac_client/examples/little-x/main.jac +681 -0
  42. jac_client/examples/little-x/src/submit-button.jac +15 -14
  43. jac_client/examples/nested-folders/nested-advance/main.jac +26 -0
  44. jac_client/examples/nested-folders/nested-advance/src/ButtonRoot.jac +4 -6
  45. jac_client/examples/nested-folders/nested-advance/src/level1/ButtonSecondL.jac +9 -13
  46. jac_client/examples/nested-folders/nested-advance/src/level1/Card.jac +29 -32
  47. jac_client/examples/nested-folders/nested-advance/src/level1/level2/ButtonThirdL.jac +12 -18
  48. jac_client/examples/nested-folders/nested-basic/{src/app.jac → main.jac} +7 -5
  49. jac_client/examples/nested-folders/nested-basic/src/button.jac +4 -3
  50. jac_client/examples/nested-folders/nested-basic/src/components/button.jac +4 -3
  51. jac_client/examples/ts-support/main.jac +35 -0
  52. jac_client/examples/with-router/main.jac +286 -0
  53. jac_client/plugin/cli.jac +507 -470
  54. jac_client/plugin/client.jac +30 -12
  55. jac_client/plugin/client_runtime.cl.jac +25 -15
  56. jac_client/plugin/impl/client.impl.jac +126 -26
  57. jac_client/plugin/impl/client_runtime.impl.jac +182 -10
  58. jac_client/plugin/plugin_config.jac +216 -34
  59. jac_client/plugin/src/__init__.jac +0 -2
  60. jac_client/plugin/src/compiler.jac +2 -2
  61. jac_client/plugin/src/config_loader.jac +1 -0
  62. jac_client/plugin/src/desktop_config.jac +31 -0
  63. jac_client/plugin/src/impl/compiler.impl.jac +99 -30
  64. jac_client/plugin/src/impl/config_loader.impl.jac +8 -0
  65. jac_client/plugin/src/impl/desktop_config.impl.jac +191 -0
  66. jac_client/plugin/src/impl/jac_to_js.impl.jac +5 -1
  67. jac_client/plugin/src/impl/package_installer.impl.jac +20 -20
  68. jac_client/plugin/src/impl/vite_bundler.impl.jac +384 -144
  69. jac_client/plugin/src/package_installer.jac +1 -1
  70. jac_client/plugin/src/targets/desktop/sidecar/main.py +144 -0
  71. jac_client/plugin/src/targets/desktop_target.jac +37 -0
  72. jac_client/plugin/src/targets/impl/desktop_target.impl.jac +2347 -0
  73. jac_client/plugin/src/targets/impl/registry.impl.jac +64 -0
  74. jac_client/plugin/src/targets/impl/web_target.impl.jac +157 -0
  75. jac_client/plugin/src/targets/register.jac +21 -0
  76. jac_client/plugin/src/targets/registry.jac +87 -0
  77. jac_client/plugin/src/targets/web_target.jac +35 -0
  78. jac_client/plugin/src/vite_bundler.jac +15 -1
  79. jac_client/plugin/utils/__init__.jac +3 -0
  80. jac_client/plugin/utils/bun_installer.jac +16 -0
  81. jac_client/plugin/utils/impl/bun_installer.impl.jac +99 -0
  82. jac_client/templates/client.jacpack +72 -0
  83. jac_client/templates/fullstack.jacpack +61 -0
  84. jac_client/tests/conftest.py +110 -52
  85. jac_client/tests/fixtures/spawn_test/app.jac +64 -70
  86. jac_client/tests/fixtures/with-ts/app.jac +28 -28
  87. jac_client/tests/test_cli.py +280 -113
  88. jac_client/tests/test_e2e.py +232 -0
  89. jac_client/tests/test_helpers.py +58 -0
  90. jac_client/tests/test_it.py +325 -154
  91. jac_client/tests/test_it_desktop.py +891 -0
  92. {jac_client-0.2.6.dist-info → jac_client-0.2.11.dist-info}/METADATA +20 -11
  93. jac_client-0.2.11.dist-info/RECORD +113 -0
  94. {jac_client-0.2.6.dist-info → jac_client-0.2.11.dist-info}/WHEEL +1 -1
  95. jac_client/examples/all-in-one/src/app.jac +0 -841
  96. jac_client/examples/all-in-one/src/components/button.jac +0 -7
  97. jac_client/examples/asset-serving/css-with-image/src/app.jac +0 -88
  98. jac_client/examples/asset-serving/image-asset/src/app.jac +0 -55
  99. jac_client/examples/asset-serving/import-alias/src/app.jac +0 -111
  100. jac_client/examples/basic/src/app.jac +0 -21
  101. jac_client/examples/basic-auth/src/app.jac +0 -377
  102. jac_client/examples/basic-auth-with-router/src/app.jac +0 -464
  103. jac_client/examples/basic-full-stack/src/app.jac +0 -365
  104. jac_client/examples/css-styling/js-styling/src/app.jac +0 -84
  105. jac_client/examples/css-styling/material-ui/src/app.jac +0 -122
  106. jac_client/examples/css-styling/pure-css/src/app.jac +0 -64
  107. jac_client/examples/css-styling/sass-example/src/app.jac +0 -64
  108. jac_client/examples/css-styling/styled-components/src/app.jac +0 -71
  109. jac_client/examples/css-styling/tailwind-example/src/app.jac +0 -63
  110. jac_client/examples/full-stack-with-auth/src/app.jac +0 -722
  111. jac_client/examples/little-x/src/app.jac +0 -719
  112. jac_client/examples/nested-folders/nested-advance/src/app.jac +0 -35
  113. jac_client/examples/ts-support/src/app.jac +0 -35
  114. jac_client/examples/with-router/src/app.jac +0 -323
  115. jac_client/plugin/src/babel_processor.jac +0 -18
  116. jac_client/plugin/src/impl/babel_processor.impl.jac +0 -84
  117. jac_client-0.2.6.dist-info/RECORD +0 -74
  118. {jac_client-0.2.6.dist-info → jac_client-0.2.11.dist-info}/entry_points.txt +0 -0
  119. {jac_client-0.2.6.dist-info → jac_client-0.2.11.dist-info}/top_level.txt +0 -0
@@ -1,365 +0,0 @@
1
- # Todo App
2
- cl import from react { useState, useEffect }
3
-
4
- node Todo {
5
- has text: str,
6
- done: bool = False;
7
- }
8
-
9
- walker create_todo {
10
- has text: str;
11
-
12
- can create with `root entry {
13
- new_todo = here ++> Todo(text=self.text);
14
- report new_todo ;
15
- }
16
- }
17
-
18
- walker toggle_todo {
19
- can toggle with Todo entry {
20
- here.done = not here.done;
21
- report here ;
22
- }
23
- }
24
-
25
- walker read_todos {
26
- can read with `root entry {
27
- visit [-->(`?Todo)];
28
- }
29
-
30
- can report_todos with exit {
31
- report here ;
32
- }
33
- }
34
-
35
- cl {
36
- def:pub app -> any {
37
- [todos, setTodos] = useState([]);
38
- [inputValue, setInputValue] = useState("");
39
- [filter, setFilter] = useState("all");
40
-
41
- useEffect(
42
- lambda -> None{ async def loadTodos -> None {
43
- todos = root spawn read_todos();
44
- setTodos(todos.reports);
45
- } loadTodos();} ,
46
- []
47
- );
48
-
49
- # Add a new todo
50
- async def addTodo -> None {
51
- if not inputValue.trim() {
52
- return;
53
- }
54
- newTodo = {"id": Date.now(), "text": inputValue.trim(), "done": False};
55
- response = root spawn create_todo(text=inputValue.trim());
56
- newTodos = todos.concat([response.reports[0][0]]);
57
- setTodos(newTodos);
58
- setInputValue("");
59
- }
60
-
61
- # Toggle todo completion status
62
- async def toggleTodo(id: any) -> None {
63
- console.log("toggleTodo", id);
64
- id spawn toggle_todo();
65
- setTodos(
66
- todos.map(
67
- lambda todo: any -> any{ if todo._jac_id == id {
68
- updatedTodo = {
69
- "_jac_id": todo._jac_id,
70
- "text": todo.text,
71
- "done": not todo.done,
72
- "id": todo.id
73
- };
74
- return updatedTodo;
75
- }return todo; }
76
- )
77
- );
78
- }
79
-
80
- # Delete a todo
81
- def deleteTodo(id: any) -> None {
82
- setTodos(
83
- todos.filter(lambda todo: any -> bool{ return todo.id != id; } )
84
- );
85
- }
86
-
87
- # Clear all completed todos
88
- def clearCompleted -> None {
89
- setTodos(
90
- todos.filter(lambda todo: any -> bool{ return not todo.done; } )
91
- );
92
- }
93
-
94
- # Filter todos based on current filter
95
- def getFilteredTodos -> list {
96
- if filter == "active" {
97
- return todos.filter(
98
- lambda todo: any -> bool{ return not todo.done; }
99
- );
100
- } elif filter == "completed" {
101
- return todos.filter(lambda todo: any -> bool{ return todo.done; } );
102
- }
103
- return todos;
104
- }
105
-
106
- # Count active todos
107
- activeCount = todos.filter(
108
- lambda todo: any -> bool{ return not todo.done; }
109
- ).length;
110
-
111
- filteredTodos = getFilteredTodos();
112
-
113
- return <div
114
- style={{
115
- "maxWidth": "600px",
116
- "margin": "40px auto",
117
- "padding": "24px",
118
- "fontFamily": "system-ui, -apple-system, sans-serif",
119
- "background": "#f9fafb",
120
- "minHeight": "100vh"
121
- }}
122
- >
123
- <h1
124
- style={{
125
- "textAlign": "center",
126
- "color": "#1f2937",
127
- "marginBottom": "32px",
128
- "fontSize": "2.5rem",
129
- "fontWeight": "700"
130
- }}
131
- >
132
- 📝 My Todo App
133
- </h1>
134
- # Add todo form
135
- <div
136
- style={{
137
- "display": "flex",
138
- "gap": "8px",
139
- "marginBottom": "24px",
140
- "background": "#ffffff",
141
- "padding": "16px",
142
- "borderRadius": "12px",
143
- "boxShadow": "0 1px 3px rgba(0,0,0,0.1)"
144
- }}
145
- >
146
- <input
147
- type="text"
148
- value={inputValue}
149
- onChange={lambda e: any -> None{ setInputValue(e.target.value);} }
150
- onKeyPress={lambda e: any -> None{ if e.key == "Enter" {
151
- addTodo();
152
- }} }
153
- placeholder="What needs to be done?"
154
- style={{
155
- "flex": "1",
156
- "padding": "12px 16px",
157
- "border": "1px solid #e5e7eb",
158
- "borderRadius": "8px",
159
- "fontSize": "16px",
160
- "outline": "none"
161
- }}
162
- />
163
- <button
164
- onClick={addTodo}
165
- style={{
166
- "padding": "12px 24px",
167
- "background": "#3b82f6",
168
- "color": "#ffffff",
169
- "border": "none",
170
- "borderRadius": "8px",
171
- "fontSize": "16px",
172
- "fontWeight": "600",
173
- "cursor": "pointer",
174
- "transition": "background 0.2s"
175
- }}
176
- >
177
- Add
178
- </button>
179
- </div>
180
- # Filter buttons
181
- <div
182
- style={{
183
- "display": "flex",
184
- "gap": "8px",
185
- "marginBottom": "24px",
186
- "justifyContent": "center"
187
- }}
188
- >
189
- <button
190
- onClick={lambda -> None{ setFilter("all");} }
191
- style={{
192
- "padding": "8px 16px",
193
- "background": ("#3b82f6" if filter == "all" else "#ffffff"),
194
- "color": ("#ffffff" if filter == "all" else "#3b82f6"),
195
- "border": "1px solid #3b82f6",
196
- "borderRadius": "6px",
197
- "fontSize": "14px",
198
- "fontWeight": "600",
199
- "cursor": "pointer"
200
- }}
201
- >
202
- All
203
- </button>
204
- <button
205
- onClick={lambda -> None{ setFilter("active");} }
206
- style={{
207
- "padding": "8px 16px",
208
- "background": ("#3b82f6" if filter == "active" else "#ffffff"),
209
- "color": ("#ffffff" if filter == "active" else "#3b82f6"),
210
- "border": "1px solid #3b82f6",
211
- "borderRadius": "6px",
212
- "fontSize": "14px",
213
- "fontWeight": "600",
214
- "cursor": "pointer"
215
- }}
216
- >
217
- Active
218
- </button>
219
- <button
220
- onClick={lambda -> None{ setFilter("completed");} }
221
- style={{
222
- "padding": "8px 16px",
223
- "background": (
224
- "#3b82f6" if filter == "completed" else "#ffffff"
225
- ),
226
- "color": ("#ffffff" if filter == "completed" else "#3b82f6"),
227
- "border": "1px solid #3b82f6",
228
- "borderRadius": "6px",
229
- "fontSize": "14px",
230
- "fontWeight": "600",
231
- "cursor": "pointer"
232
- }}
233
- >
234
- Completed
235
- </button>
236
- </div>
237
- # Todo list
238
- <div
239
- style={{
240
- "background": "#ffffff",
241
- "borderRadius": "12px",
242
- "boxShadow": "0 1px 3px rgba(0,0,0,0.1)",
243
- "overflow": "hidden"
244
- }}
245
- >
246
- {(
247
- <div
248
- style={{
249
- "padding": "40px",
250
- "textAlign": "center",
251
- "color": "#9ca3af"
252
- }}
253
- >
254
- {(
255
- "No todos yet. Add one above!"
256
- if filter == "all"
257
- else (
258
- "No active todos!"
259
- if filter == "active"
260
- else "No completed todos!"
261
- )
262
- )}
263
- </div>
264
- )
265
- if filteredTodos.length == 0
266
- else (
267
- filteredTodos.map(
268
- lambda todo: any -> any{ return <div
269
- key={todo._jac_id}
270
- style={{
271
- "display": "flex",
272
- "alignItems": "center",
273
- "gap": "12px",
274
- "padding": "16px",
275
- "borderBottom": "1px solid #e5e7eb",
276
- "transition": "background 0.2s"
277
- }}
278
- >
279
- <input
280
- type="checkbox"
281
- checked={todo.done}
282
- onChange={lambda -> None{ toggleTodo(todo._jac_id);} }
283
- style={{
284
- "width": "20px",
285
- "height": "20px",
286
- "cursor": "pointer"
287
- }}
288
- />
289
- <span
290
- style={{
291
- "flex": "1",
292
- "textDecoration": (
293
- "line-through" if todo.done else "none"
294
- ),
295
- "color": ("#9ca3af" if todo.done else "#1f2937"),
296
- "fontSize": "16px"
297
- }}
298
- >
299
- {todo.text}
300
- </span>
301
- <button
302
- onClick={lambda -> None{ deleteTodo(todo.__jac_id);} }
303
- style={{
304
- "padding": "6px 12px",
305
- "background": "#ef4444",
306
- "color": "#ffffff",
307
- "border": "none",
308
- "borderRadius": "6px",
309
- "fontSize": "14px",
310
- "fontWeight": "500",
311
- "cursor": "pointer",
312
- "transition": "background 0.2s"
313
- }}
314
- >
315
- Delete
316
- </button>
317
- </div>; }
318
- )
319
- )}
320
- </div>
321
- # Stats and clear completed button
322
- {(
323
- <div
324
- style={{
325
- "display": "flex",
326
- "justifyContent": "space-between",
327
- "alignItems": "center",
328
- "marginTop": "24px",
329
- "padding": "16px",
330
- "background": "#ffffff",
331
- "borderRadius": "12px",
332
- "boxShadow": "0 1px 3px rgba(0,0,0,0.1)"
333
- }}
334
- >
335
- <span
336
- style={{"color": "#6b7280", "fontSize": "14px"}}
337
- >
338
- {activeCount} {"item" if activeCount == 1 else "items"} left
339
- </span>
340
- {(
341
- <button
342
- onClick={clearCompleted}
343
- style={{
344
- "padding": "8px 16px",
345
- "background": "#ef4444",
346
- "color": "#ffffff",
347
- "border": "none",
348
- "borderRadius": "6px",
349
- "fontSize": "14px",
350
- "fontWeight": "600",
351
- "cursor": "pointer"
352
- }}
353
- >
354
- Clear Completed
355
- </button>
356
- )
357
- if todos.some(lambda todo: any -> bool{ return todo.done; } )
358
- else None}
359
- </div>
360
- )
361
- if todos.length > 0
362
- else None}
363
- </div>;
364
- }
365
- }
@@ -1,84 +0,0 @@
1
- # Pages
2
- cl import from react { useState, useEffect }
3
- cl import from .styles { default as styles }
4
-
5
- cl {
6
- def:pub app -> any {
7
- [count, setCount] = useState(0);
8
-
9
- useEffect(lambda -> None{ console.log("Count changed: ", count);} , [count]);
10
-
11
- handleIncrement = lambda e: any -> None{ setCount(count + 1);} ;
12
-
13
- handleDecrement = lambda e: any -> None{ setCount(count - 1);} ;
14
-
15
- handleReset = lambda e: any -> None{ setCount(0);} ;
16
-
17
- countStyle = styles.countDisplayZero
18
- if count == 0
19
- else (
20
- styles.countDisplayPositive if count > 0 else styles.countDisplayNegative
21
- );
22
-
23
- return <div
24
- style={styles.container}
25
- >
26
- <div
27
- style={styles.card}
28
- >
29
- <h1
30
- style={styles.title}
31
- >
32
- Counter Application
33
- </h1>
34
- <div
35
- style={styles.divider}
36
- ></div>
37
- <div
38
- style={styles.counterSection}
39
- >
40
- <div
41
- style={styles.label}
42
- >
43
- Current Count
44
- </div>
45
- <div
46
- style={countStyle}
47
- >
48
- {count}
49
- </div>
50
- </div>
51
- <div
52
- style={styles.divider}
53
- ></div>
54
- <div
55
- style={styles.buttonGroup}
56
- >
57
- <button
58
- style={styles.buttonDecrement}
59
- onClick={handleDecrement}
60
- >
61
- -
62
- </button>
63
- <button
64
- style={styles.buttonReset}
65
- onClick={handleReset}
66
- >
67
-
68
- </button>
69
- <button
70
- style={styles.buttonIncrement}
71
- onClick={handleIncrement}
72
- >
73
- +
74
- </button>
75
- </div>
76
- <div
77
- style={styles.hint}
78
- >
79
- Click the buttons to increment, decrement, or reset the counter
80
- </div>
81
- </div>
82
- </div>;
83
- }
84
- }
@@ -1,122 +0,0 @@
1
- cl import from react { useState, useEffect }
2
- cl import from '@mui/material/Button' { default as Button }
3
- cl import from '@mui/material/Card' { default as Card }
4
- cl import from '@mui/material/CardContent' { default as CardContent }
5
- cl import from '@mui/material/CardActions' { default as CardActions }
6
- cl import from '@mui/material/Typography' { default as Typography }
7
- cl import from '@mui/material/IconButton' { default as IconButton }
8
- cl import from '@mui/material/Box' { default as Box }
9
- cl import from '@mui/material/Divider' { default as Divider }
10
- cl import from '@mui/icons-material/Add' { default as AddIcon }
11
- cl import from '@mui/icons-material/Remove' { default as RemoveIcon }
12
- cl import from '@mui/icons-material/Refresh' { default as RefreshIcon }
13
-
14
- cl {
15
- def:pub app -> any {
16
- [count, setCount] = useState(0);
17
-
18
- useEffect(lambda -> None{ console.log("Count changed: ", count);} , [count]);
19
-
20
- handleIncrement = lambda e: any -> None{ setCount(count + 1);} ;
21
-
22
- handleDecrement = lambda e: any -> None{ setCount(count - 1);} ;
23
-
24
- handleReset = lambda e: any -> None{ setCount(0);} ;
25
-
26
- return <Box
27
- sx={{
28
- "display": "flex",
29
- "justifyContent": "center",
30
- "alignItems": "center",
31
- "minHeight": "100vh",
32
- "backgroundColor": "#f5f5f5"
33
- }}
34
- >
35
- <Card
36
- sx={{"minWidth": 400, "boxShadow": 3}}
37
- >
38
- <CardContent>
39
- <Typography
40
- variant="h4"
41
- component="div"
42
- gutterBottom
43
- sx={{"textAlign": "center", "color": "primary.main"}}
44
- >
45
- Counter Application
46
- </Typography>
47
- <Divider
48
- sx={{"my": 2}}
49
- />
50
- <Box
51
- sx={{
52
- "display": "flex",
53
- "flexDirection": "column",
54
- "alignItems": "center",
55
- "py": 3
56
- }}
57
- >
58
- <Typography
59
- variant="h6"
60
- color="text.secondary"
61
- gutterBottom
62
- >
63
- Current Count
64
- </Typography>
65
- <Typography
66
- variant="h1"
67
- component="div"
68
- sx={{
69
- "fontWeight": "bold",
70
- "color": "success.main"
71
- if count > 0
72
- else "error.main" if count < 0 else "text.primary"
73
- }}
74
- >
75
- {count}
76
- </Typography>
77
- </Box>
78
- </CardContent>
79
- <Divider />
80
- <CardActions
81
- sx={{"display": "flex", "justifyContent": "space-around", "p": 2}}
82
- >
83
- <IconButton
84
- color="error"
85
- size="large"
86
- onClick={handleDecrement}
87
- sx={{"border": "2px solid", "borderColor": "error.main"}}
88
- >
89
- <RemoveIcon />
90
- </IconButton>
91
- <IconButton
92
- color="primary"
93
- size="large"
94
- onClick={handleReset}
95
- sx={{"border": "2px solid", "borderColor": "primary.main"}}
96
- >
97
- <RefreshIcon />
98
- </IconButton>
99
- <IconButton
100
- color="success"
101
- size="large"
102
- onClick={handleIncrement}
103
- sx={{"border": "2px solid", "borderColor": "success.main"}}
104
- >
105
- <AddIcon />
106
- </IconButton>
107
- </CardActions>
108
- <Box
109
- sx={{"px": 3, "pb": 2}}
110
- >
111
- <Typography
112
- variant="caption"
113
- color="text.secondary"
114
- sx={{"display": "block", "textAlign": "center"}}
115
- >
116
- Click the buttons to increment, decrement, or reset the counter
117
- </Typography>
118
- </Box>
119
- </Card>
120
- </Box>;
121
- }
122
- }
@@ -1,64 +0,0 @@
1
- # Pages
2
- cl import from react { useState, useEffect }
3
- cl import ".styles.css";
4
-
5
- cl {
6
- def:pub app -> any {
7
- [count, setCount] = useState(0);
8
-
9
- useEffect(lambda -> None{ console.log("Count changed: ", count);} , [count]);
10
-
11
- handleIncrement = lambda e: any -> None{ setCount(count + 1);} ;
12
-
13
- handleDecrement = lambda e: any -> None{ setCount(count - 1);} ;
14
-
15
- handleReset = lambda e: any -> None{ setCount(0);} ;
16
-
17
- countClass = "countDisplay " + (
18
- "positive" if count > 0 else "negative" if count < 0 else "zero"
19
- );
20
-
21
- return <div className="container">
22
- <div className="card">
23
- <h1 className="title">
24
- Counter Application
25
- </h1>
26
- <div className="divider"></div>
27
- <div className="counterSection">
28
- <div className="label">
29
- Current Count
30
- </div>
31
- <div
32
- className={countClass}
33
- >
34
- {count}
35
- </div>
36
- </div>
37
- <div className="divider"></div>
38
- <div className="buttonGroup">
39
- <button
40
- className="btn btnDecrement"
41
- onClick={handleDecrement}
42
- >
43
- -
44
- </button>
45
- <button
46
- className="btn btnReset"
47
- onClick={handleReset}
48
- >
49
-
50
- </button>
51
- <button
52
- className="btn btnIncrement"
53
- onClick={handleIncrement}
54
- >
55
- +
56
- </button>
57
- </div>
58
- <div className="hint">
59
- Click the buttons to increment, decrement, or reset the counter
60
- </div>
61
- </div>
62
- </div>;
63
- }
64
- }