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.
- jac_client/examples/all-in-one/assets/workers/worker.py +5 -0
- jac_client/tests/conftest.py +281 -0
- jac_client/tests/test_cli.py +755 -0
- jac_client/tests/test_it.py +347 -67
- {jac_client-0.2.2.dist-info → jac_client-0.2.4.dist-info}/METADATA +30 -24
- jac_client-0.2.4.dist-info/RECORD +10 -0
- {jac_client-0.2.2.dist-info → jac_client-0.2.4.dist-info}/WHEEL +2 -1
- jac_client-0.2.4.dist-info/entry_points.txt +4 -0
- jac_client-0.2.4.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/app.jac +0 -426
- jac_client/examples/all-in-one/assets/burger.png +0 -0
- jac_client/examples/all-in-one/button.jac +0 -7
- jac_client/examples/all-in-one/components/button.jac +0 -7
- 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/app.jac +0 -88
- 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/app.jac +0 -55
- 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/app.jac +0 -111
- 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/app.jac +0 -21
- 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/app.jac +0 -464
- 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/app.jac +0 -320
- 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/app.jac +0 -84
- 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/app.jac +0 -122
- 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/app.jac +0 -64
- 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/app.jac +0 -64
- 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/app.jac +0 -71
- 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/app.jac +0 -63
- 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/app.jac +0 -722
- 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/app.jac +0 -724
- 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/ButtonRoot.jac +0 -11
- jac_client/examples/nested-folders/nested-advance/README.md +0 -77
- jac_client/examples/nested-folders/nested-advance/app.jac +0 -35
- jac_client/examples/nested-folders/nested-advance/level1/ButtonSecondL.jac +0 -19
- jac_client/examples/nested-folders/nested-advance/level1/Card.jac +0 -43
- jac_client/examples/nested-folders/nested-advance/level1/level2/ButtonThirdL.jac +0 -25
- 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.jac +0 -13
- jac_client/examples/nested-folders/nested-basic/app.js +0 -7
- jac_client/examples/nested-folders/nested-basic/button.jac +0 -7
- jac_client/examples/nested-folders/nested-basic/components/button.jac +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/app.jac +0 -323
- 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/basic-app/app.jac +0 -23
- jac_client/tests/fixtures/cl_file/app.cl.jac +0 -48
- jac_client/tests/fixtures/cl_file/app.jac +0 -15
- jac_client/tests/fixtures/client_app_with_antd/app.jac +0 -34
- jac_client/tests/fixtures/js_import/app.jac +0 -34
- 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/fixtures/relative_import/app.jac +0 -11
- jac_client/tests/fixtures/relative_import/button.jac +0 -7
- jac_client/tests/fixtures/spawn_test/app.jac +0 -129
- jac_client/tests/fixtures/test_fragments_spread/app.jac +0 -67
- 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.2.dist-info/RECORD +0 -171
- jac_client-0.2.2.dist-info/entry_points.txt +0 -4
|
@@ -1,320 +0,0 @@
|
|
|
1
|
-
# Todo App
|
|
2
|
-
cl import from react {useState, useEffect}
|
|
3
|
-
|
|
4
|
-
node Todo {
|
|
5
|
-
has text: str;
|
|
6
|
-
has done: bool = False;
|
|
7
|
-
}
|
|
8
|
-
|
|
9
|
-
walker create_todo {
|
|
10
|
-
has text:str;
|
|
11
|
-
can create with `root entry {
|
|
12
|
-
new_todo = here ++> Todo(text= self.text);
|
|
13
|
-
report new_todo;
|
|
14
|
-
}
|
|
15
|
-
}
|
|
16
|
-
walker toggle_todo {
|
|
17
|
-
can toggle with Todo entry {
|
|
18
|
-
here.done = not here.done;
|
|
19
|
-
report here;
|
|
20
|
-
}
|
|
21
|
-
}
|
|
22
|
-
walker read_todos {
|
|
23
|
-
can read with `root entry {
|
|
24
|
-
visit [-->(`?Todo)];
|
|
25
|
-
}
|
|
26
|
-
can report_todos with exit {
|
|
27
|
-
report here;
|
|
28
|
-
}
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
cl {
|
|
32
|
-
def app() -> any {
|
|
33
|
-
let [todos, setTodos] = useState([]);
|
|
34
|
-
let [inputValue, setInputValue] = useState("");
|
|
35
|
-
let [filter, setFilter] = useState("all");
|
|
36
|
-
|
|
37
|
-
useEffect(lambda -> None {
|
|
38
|
-
async def loadTodos() -> None {
|
|
39
|
-
todos = root spawn read_todos();
|
|
40
|
-
setTodos(todos.reports);
|
|
41
|
-
}
|
|
42
|
-
loadTodos();
|
|
43
|
-
}, []);
|
|
44
|
-
|
|
45
|
-
# Add a new todo
|
|
46
|
-
async def addTodo() -> None {
|
|
47
|
-
if not inputValue.trim() { return; }
|
|
48
|
-
newTodo = {
|
|
49
|
-
"id": Date.now(),
|
|
50
|
-
"text": inputValue.trim(),
|
|
51
|
-
"done": False
|
|
52
|
-
};
|
|
53
|
-
response = root spawn create_todo(text=inputValue.trim());
|
|
54
|
-
newTodos = todos.concat([response.reports[0][0]]);
|
|
55
|
-
setTodos(newTodos);
|
|
56
|
-
setInputValue("");
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
# Toggle todo completion status
|
|
60
|
-
async def toggleTodo(id: any) -> None {
|
|
61
|
-
console.log("toggleTodo", id);
|
|
62
|
-
id spawn toggle_todo();
|
|
63
|
-
setTodos(todos.map(lambda todo: any -> any {
|
|
64
|
-
if todo._jac_id == id {
|
|
65
|
-
updatedTodo = {
|
|
66
|
-
"_jac_id": todo._jac_id,
|
|
67
|
-
"text": todo.text,
|
|
68
|
-
"done": not todo.done,
|
|
69
|
-
"id": todo.id
|
|
70
|
-
};
|
|
71
|
-
return updatedTodo;
|
|
72
|
-
}
|
|
73
|
-
return todo;
|
|
74
|
-
}));
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
# Delete a todo
|
|
78
|
-
def deleteTodo(id: any) -> None {
|
|
79
|
-
setTodos(todos.filter(lambda todo: any -> bool { return todo.id != id; }));
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
# Clear all completed todos
|
|
83
|
-
def clearCompleted() -> None {
|
|
84
|
-
setTodos(todos.filter(lambda todo: any -> bool { return not todo.done; }));
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
# Filter todos based on current filter
|
|
88
|
-
def getFilteredTodos() -> list {
|
|
89
|
-
if filter == "active" {
|
|
90
|
-
return todos.filter(lambda todo: any -> bool { return not todo.done; });
|
|
91
|
-
} elif filter == "completed" {
|
|
92
|
-
return todos.filter(lambda todo: any -> bool { return todo.done; });
|
|
93
|
-
}
|
|
94
|
-
return todos;
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
# Count active todos
|
|
98
|
-
activeCount = todos.filter(lambda todo: any -> bool { return not todo.done; }).length;
|
|
99
|
-
|
|
100
|
-
filteredTodos = getFilteredTodos();
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
return <div style={{
|
|
104
|
-
"maxWidth": "600px",
|
|
105
|
-
"margin": "40px auto",
|
|
106
|
-
"padding": "24px",
|
|
107
|
-
"fontFamily": "system-ui, -apple-system, sans-serif",
|
|
108
|
-
"background": "#f9fafb",
|
|
109
|
-
"minHeight": "100vh"
|
|
110
|
-
}}>
|
|
111
|
-
<h1 style={{
|
|
112
|
-
"textAlign": "center",
|
|
113
|
-
"color": "#1f2937",
|
|
114
|
-
"marginBottom": "32px",
|
|
115
|
-
"fontSize": "2.5rem",
|
|
116
|
-
"fontWeight": "700"
|
|
117
|
-
}}>📝 My Todo App</h1>
|
|
118
|
-
|
|
119
|
-
# Add todo form
|
|
120
|
-
<div style={{
|
|
121
|
-
"display": "flex",
|
|
122
|
-
"gap": "8px",
|
|
123
|
-
"marginBottom": "24px",
|
|
124
|
-
"background": "#ffffff",
|
|
125
|
-
"padding": "16px",
|
|
126
|
-
"borderRadius": "12px",
|
|
127
|
-
"boxShadow": "0 1px 3px rgba(0,0,0,0.1)"
|
|
128
|
-
}}>
|
|
129
|
-
<input
|
|
130
|
-
type="text"
|
|
131
|
-
value={inputValue}
|
|
132
|
-
onChange={lambda e: any -> None { setInputValue(e.target.value); }}
|
|
133
|
-
onKeyPress={lambda e: any -> None {
|
|
134
|
-
if e.key == "Enter" { addTodo(); }
|
|
135
|
-
}}
|
|
136
|
-
placeholder="What needs to be done?"
|
|
137
|
-
style={{
|
|
138
|
-
"flex": "1",
|
|
139
|
-
"padding": "12px 16px",
|
|
140
|
-
"border": "1px solid #e5e7eb",
|
|
141
|
-
"borderRadius": "8px",
|
|
142
|
-
"fontSize": "16px",
|
|
143
|
-
"outline": "none"
|
|
144
|
-
}}
|
|
145
|
-
/>
|
|
146
|
-
<button
|
|
147
|
-
onClick={addTodo}
|
|
148
|
-
style={{
|
|
149
|
-
"padding": "12px 24px",
|
|
150
|
-
"background": "#3b82f6",
|
|
151
|
-
"color": "#ffffff",
|
|
152
|
-
"border": "none",
|
|
153
|
-
"borderRadius": "8px",
|
|
154
|
-
"fontSize": "16px",
|
|
155
|
-
"fontWeight": "600",
|
|
156
|
-
"cursor": "pointer",
|
|
157
|
-
"transition": "background 0.2s"
|
|
158
|
-
}}
|
|
159
|
-
>
|
|
160
|
-
Add
|
|
161
|
-
</button>
|
|
162
|
-
</div>
|
|
163
|
-
|
|
164
|
-
# Filter buttons
|
|
165
|
-
<div style={{
|
|
166
|
-
"display": "flex",
|
|
167
|
-
"gap": "8px",
|
|
168
|
-
"marginBottom": "24px",
|
|
169
|
-
"justifyContent": "center"
|
|
170
|
-
}}>
|
|
171
|
-
<button
|
|
172
|
-
onClick={lambda -> None { setFilter("all"); }}
|
|
173
|
-
style={{
|
|
174
|
-
"padding": "8px 16px",
|
|
175
|
-
"background": ("#3b82f6" if filter == "all" else "#ffffff"),
|
|
176
|
-
"color": ("#ffffff" if filter == "all" else "#3b82f6"),
|
|
177
|
-
"border": "1px solid #3b82f6",
|
|
178
|
-
"borderRadius": "6px",
|
|
179
|
-
"fontSize": "14px",
|
|
180
|
-
"fontWeight": "600",
|
|
181
|
-
"cursor": "pointer"
|
|
182
|
-
}}
|
|
183
|
-
>
|
|
184
|
-
All
|
|
185
|
-
</button>
|
|
186
|
-
<button
|
|
187
|
-
onClick={lambda -> None { setFilter("active"); }}
|
|
188
|
-
style={{
|
|
189
|
-
"padding": "8px 16px",
|
|
190
|
-
"background": ("#3b82f6" if filter == "active" else "#ffffff"),
|
|
191
|
-
"color": ("#ffffff" if filter == "active" else "#3b82f6"),
|
|
192
|
-
"border": "1px solid #3b82f6",
|
|
193
|
-
"borderRadius": "6px",
|
|
194
|
-
"fontSize": "14px",
|
|
195
|
-
"fontWeight": "600",
|
|
196
|
-
"cursor": "pointer"
|
|
197
|
-
}}
|
|
198
|
-
>
|
|
199
|
-
Active
|
|
200
|
-
</button>
|
|
201
|
-
<button
|
|
202
|
-
onClick={lambda -> None { setFilter("completed"); }}
|
|
203
|
-
style={{
|
|
204
|
-
"padding": "8px 16px",
|
|
205
|
-
"background": ("#3b82f6" if filter == "completed" else "#ffffff"),
|
|
206
|
-
"color": ("#ffffff" if filter == "completed" else "#3b82f6"),
|
|
207
|
-
"border": "1px solid #3b82f6",
|
|
208
|
-
"borderRadius": "6px",
|
|
209
|
-
"fontSize": "14px",
|
|
210
|
-
"fontWeight": "600",
|
|
211
|
-
"cursor": "pointer"
|
|
212
|
-
}}
|
|
213
|
-
>
|
|
214
|
-
Completed
|
|
215
|
-
</button>
|
|
216
|
-
</div>
|
|
217
|
-
|
|
218
|
-
# Todo list
|
|
219
|
-
<div style={{
|
|
220
|
-
"background": "#ffffff",
|
|
221
|
-
"borderRadius": "12px",
|
|
222
|
-
"boxShadow": "0 1px 3px rgba(0,0,0,0.1)",
|
|
223
|
-
"overflow": "hidden"
|
|
224
|
-
}}>
|
|
225
|
-
{(<div style={{
|
|
226
|
-
"padding": "40px",
|
|
227
|
-
"textAlign": "center",
|
|
228
|
-
"color": "#9ca3af"
|
|
229
|
-
}}>
|
|
230
|
-
{("No todos yet. Add one above!" if filter == "all" else
|
|
231
|
-
("No active todos!" if filter == "active" else
|
|
232
|
-
"No completed todos!"))}
|
|
233
|
-
</div>) if filteredTodos.length == 0 else (
|
|
234
|
-
filteredTodos.map(lambda todo: any -> any {
|
|
235
|
-
return <div
|
|
236
|
-
key={todo._jac_id}
|
|
237
|
-
style={{
|
|
238
|
-
"display": "flex",
|
|
239
|
-
"alignItems": "center",
|
|
240
|
-
"gap": "12px",
|
|
241
|
-
"padding": "16px",
|
|
242
|
-
"borderBottom": "1px solid #e5e7eb",
|
|
243
|
-
"transition": "background 0.2s"
|
|
244
|
-
}}
|
|
245
|
-
>
|
|
246
|
-
<input
|
|
247
|
-
type="checkbox"
|
|
248
|
-
checked={todo.done}
|
|
249
|
-
onChange={lambda -> None { toggleTodo(todo._jac_id); }}
|
|
250
|
-
style={{
|
|
251
|
-
"width": "20px",
|
|
252
|
-
"height": "20px",
|
|
253
|
-
"cursor": "pointer"
|
|
254
|
-
}}
|
|
255
|
-
/>
|
|
256
|
-
<span style={{
|
|
257
|
-
"flex": "1",
|
|
258
|
-
"textDecoration": ("line-through" if todo.done else "none"),
|
|
259
|
-
"color": ("#9ca3af" if todo.done else "#1f2937"),
|
|
260
|
-
"fontSize": "16px"
|
|
261
|
-
}}>
|
|
262
|
-
{todo.text}
|
|
263
|
-
</span>
|
|
264
|
-
<button
|
|
265
|
-
onClick={lambda -> None { deleteTodo(todo.__jac_id); }}
|
|
266
|
-
style={{
|
|
267
|
-
"padding": "6px 12px",
|
|
268
|
-
"background": "#ef4444",
|
|
269
|
-
"color": "#ffffff",
|
|
270
|
-
"border": "none",
|
|
271
|
-
"borderRadius": "6px",
|
|
272
|
-
"fontSize": "14px",
|
|
273
|
-
"fontWeight": "500",
|
|
274
|
-
"cursor": "pointer",
|
|
275
|
-
"transition": "background 0.2s"
|
|
276
|
-
}}
|
|
277
|
-
>
|
|
278
|
-
Delete
|
|
279
|
-
</button>
|
|
280
|
-
</div>;
|
|
281
|
-
})
|
|
282
|
-
)}
|
|
283
|
-
</div>
|
|
284
|
-
|
|
285
|
-
# Stats and clear completed button
|
|
286
|
-
{(<div style={{
|
|
287
|
-
"display": "flex",
|
|
288
|
-
"justifyContent": "space-between",
|
|
289
|
-
"alignItems": "center",
|
|
290
|
-
"marginTop": "24px",
|
|
291
|
-
"padding": "16px",
|
|
292
|
-
"background": "#ffffff",
|
|
293
|
-
"borderRadius": "12px",
|
|
294
|
-
"boxShadow": "0 1px 3px rgba(0,0,0,0.1)"
|
|
295
|
-
}}>
|
|
296
|
-
<span style={{
|
|
297
|
-
"color": "#6b7280",
|
|
298
|
-
"fontSize": "14px"
|
|
299
|
-
}}>
|
|
300
|
-
{activeCount} {"item" if activeCount == 1 else "items"} left
|
|
301
|
-
</span>
|
|
302
|
-
{(<button
|
|
303
|
-
onClick={clearCompleted}
|
|
304
|
-
style={{
|
|
305
|
-
"padding": "8px 16px",
|
|
306
|
-
"background": "#ef4444",
|
|
307
|
-
"color": "#ffffff",
|
|
308
|
-
"border": "none",
|
|
309
|
-
"borderRadius": "6px",
|
|
310
|
-
"fontSize": "14px",
|
|
311
|
-
"fontWeight": "600",
|
|
312
|
-
"cursor": "pointer"
|
|
313
|
-
}}
|
|
314
|
-
>
|
|
315
|
-
Clear Completed
|
|
316
|
-
</button>) if todos.some(lambda todo: any -> bool { return todo.done; }) else None}
|
|
317
|
-
</div>) if todos.length > 0 else None}
|
|
318
|
-
</div>;
|
|
319
|
-
}
|
|
320
|
-
}
|
|
@@ -1,28 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "basic-full-stack",
|
|
3
|
-
"version": "1.0.0",
|
|
4
|
-
"main": "index.js",
|
|
5
|
-
"scripts": {
|
|
6
|
-
"build": "npm run compile && vite build",
|
|
7
|
-
"dev": "vite dev",
|
|
8
|
-
"preview": "vite preview",
|
|
9
|
-
"compile": "babel src --out-dir build --extensions \".jsx,.js\" --out-file-extension .js"
|
|
10
|
-
},
|
|
11
|
-
"keywords": [],
|
|
12
|
-
"author": "",
|
|
13
|
-
"license": "ISC",
|
|
14
|
-
"description": "Jac application: basic-full-stack",
|
|
15
|
-
"type": "module",
|
|
16
|
-
"devDependencies": {
|
|
17
|
-
"vite": "^6.4.1",
|
|
18
|
-
"@babel/cli": "^7.28.3",
|
|
19
|
-
"@babel/core": "^7.28.5",
|
|
20
|
-
"@babel/preset-env": "^7.28.5",
|
|
21
|
-
"@babel/preset-react": "^7.28.5"
|
|
22
|
-
},
|
|
23
|
-
"dependencies": {
|
|
24
|
-
"react": "^19.2.0",
|
|
25
|
-
"react-dom": "^19.2.0",
|
|
26
|
-
"react-router-dom": "^7.3.0"
|
|
27
|
-
}
|
|
28
|
-
}
|
|
@@ -1,27 +0,0 @@
|
|
|
1
|
-
|
|
2
|
-
import { defineConfig } from "vite";
|
|
3
|
-
import path from "path";
|
|
4
|
-
import { fileURLToPath } from "url";
|
|
5
|
-
|
|
6
|
-
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
|
7
|
-
|
|
8
|
-
export default defineConfig({
|
|
9
|
-
root: ".", // base folder
|
|
10
|
-
build: {
|
|
11
|
-
rollupOptions: {
|
|
12
|
-
input: "build/main.js", // your compiled entry file
|
|
13
|
-
output: {
|
|
14
|
-
entryFileNames: "client.[hash].js", // name of the final js file
|
|
15
|
-
assetFileNames: "[name].[ext]",
|
|
16
|
-
},
|
|
17
|
-
},
|
|
18
|
-
outDir: "dist", // final bundled output
|
|
19
|
-
emptyOutDir: true,
|
|
20
|
-
},
|
|
21
|
-
publicDir: false,
|
|
22
|
-
resolve: {
|
|
23
|
-
alias: {
|
|
24
|
-
"@jac-client/utils": path.resolve(__dirname, "src/client_runtime.js"),
|
|
25
|
-
},
|
|
26
|
-
},
|
|
27
|
-
});
|
|
@@ -1,183 +0,0 @@
|
|
|
1
|
-
# JavaScript Styling Example
|
|
2
|
-
|
|
3
|
-
This example demonstrates styling a Jac application using JavaScript objects for inline styles.
|
|
4
|
-
|
|
5
|
-
## Overview
|
|
6
|
-
|
|
7
|
-
JavaScript styling uses JavaScript objects to define styles, which are then applied via the `style` prop. This approach is perfect for:
|
|
8
|
-
- Dynamic styling based on state
|
|
9
|
-
- Programmatic style generation
|
|
10
|
-
- Component-scoped styles without CSS files
|
|
11
|
-
- React-style inline styling
|
|
12
|
-
|
|
13
|
-
## Project Structure
|
|
14
|
-
|
|
15
|
-
```
|
|
16
|
-
js-styling/
|
|
17
|
-
├── app.jac # Main application component
|
|
18
|
-
├── styles.js # Style objects exported as default
|
|
19
|
-
├── package.json # Dependencies
|
|
20
|
-
└── vite.config.js # Vite configuration
|
|
21
|
-
```
|
|
22
|
-
|
|
23
|
-
## Setup
|
|
24
|
-
|
|
25
|
-
1. Install dependencies:
|
|
26
|
-
```bash
|
|
27
|
-
npm install
|
|
28
|
-
```
|
|
29
|
-
|
|
30
|
-
2. Run the application:
|
|
31
|
-
```bash
|
|
32
|
-
jac serve app.jac
|
|
33
|
-
```
|
|
34
|
-
|
|
35
|
-
## How It Works
|
|
36
|
-
|
|
37
|
-
### 1. Define Style Objects
|
|
38
|
-
|
|
39
|
-
In `styles.js`, export a default object with all styles:
|
|
40
|
-
|
|
41
|
-
```javascript
|
|
42
|
-
const countDisplay = {
|
|
43
|
-
fontSize: "3.75rem",
|
|
44
|
-
fontWeight: "bold",
|
|
45
|
-
transition: "color 0.3s ease"
|
|
46
|
-
};
|
|
47
|
-
|
|
48
|
-
export default {
|
|
49
|
-
container: {
|
|
50
|
-
minHeight: "100vh",
|
|
51
|
-
background: "linear-gradient(to bottom right, #dbeafe, #e0e7ff)",
|
|
52
|
-
display: "flex",
|
|
53
|
-
alignItems: "center",
|
|
54
|
-
justifyContent: "center",
|
|
55
|
-
padding: "1rem"
|
|
56
|
-
},
|
|
57
|
-
card: {
|
|
58
|
-
backgroundColor: "#ffffff",
|
|
59
|
-
borderRadius: "1rem",
|
|
60
|
-
boxShadow: "0 25px 50px -12px rgba(0, 0, 0, 0.25)",
|
|
61
|
-
padding: "2rem",
|
|
62
|
-
maxWidth: "28rem",
|
|
63
|
-
width: "100%"
|
|
64
|
-
},
|
|
65
|
-
countDisplayZero: {
|
|
66
|
-
...countDisplay,
|
|
67
|
-
color: "#1f2937"
|
|
68
|
-
},
|
|
69
|
-
countDisplayPositive: {
|
|
70
|
-
...countDisplay,
|
|
71
|
-
color: "#16a34a"
|
|
72
|
-
},
|
|
73
|
-
// ... more styles
|
|
74
|
-
};
|
|
75
|
-
```
|
|
76
|
-
|
|
77
|
-
### 2. Import Styles
|
|
78
|
-
|
|
79
|
-
In your Jac file:
|
|
80
|
-
|
|
81
|
-
```jac
|
|
82
|
-
cl import from .styles { default as styles }
|
|
83
|
-
```
|
|
84
|
-
|
|
85
|
-
### 3. Apply Styles
|
|
86
|
-
|
|
87
|
-
Use the `style` prop with style objects:
|
|
88
|
-
|
|
89
|
-
```jac
|
|
90
|
-
return <div style={styles.container}>
|
|
91
|
-
<div style={styles.card}>
|
|
92
|
-
<h1 style={styles.title}>Counter Application</h1>
|
|
93
|
-
</div>
|
|
94
|
-
</div>;
|
|
95
|
-
```
|
|
96
|
-
|
|
97
|
-
### 4. Dynamic Styles
|
|
98
|
-
|
|
99
|
-
Select styles based on state:
|
|
100
|
-
|
|
101
|
-
```jac
|
|
102
|
-
let countStyle = styles.countDisplayZero if count == 0 else (styles.countDisplayPositive if count > 0 else styles.countDisplayNegative);
|
|
103
|
-
|
|
104
|
-
return <div style={countStyle}>{count}</div>;
|
|
105
|
-
```
|
|
106
|
-
|
|
107
|
-
## Style Object Format
|
|
108
|
-
|
|
109
|
-
JavaScript style objects use camelCase property names (React convention):
|
|
110
|
-
|
|
111
|
-
```javascript
|
|
112
|
-
{
|
|
113
|
-
backgroundColor: "#ffffff", // not background-color
|
|
114
|
-
fontSize: "1.5rem", // not font-size
|
|
115
|
-
marginTop: "10px", // not margin-top
|
|
116
|
-
zIndex: 1 // not z-index
|
|
117
|
-
}
|
|
118
|
-
```
|
|
119
|
-
|
|
120
|
-
## Best Practices
|
|
121
|
-
|
|
122
|
-
1. **Use object spread**: Share common styles with spread operator
|
|
123
|
-
2. **Organize by component**: Group related styles together
|
|
124
|
-
3. **Use constants**: Define reusable values at the top
|
|
125
|
-
4. **CamelCase properties**: Follow React naming convention
|
|
126
|
-
5. **Extract complex logic**: Move style calculations to functions
|
|
127
|
-
|
|
128
|
-
## Advantages
|
|
129
|
-
|
|
130
|
-
- ✅ Dynamic styling based on props/state
|
|
131
|
-
- ✅ No CSS file needed
|
|
132
|
-
- ✅ Type-safe (with TypeScript)
|
|
133
|
-
- ✅ Component-scoped by default
|
|
134
|
-
- ✅ Programmatic style generation
|
|
135
|
-
|
|
136
|
-
## Limitations
|
|
137
|
-
|
|
138
|
-
- ❌ No pseudo-classes (hover, focus, etc.)
|
|
139
|
-
- ❌ No media queries
|
|
140
|
-
- ❌ No CSS animations (use JavaScript)
|
|
141
|
-
- ❌ Verbose for complex styles
|
|
142
|
-
- ❌ No CSS preprocessor features
|
|
143
|
-
|
|
144
|
-
## When to Use
|
|
145
|
-
|
|
146
|
-
Choose JavaScript Styling when:
|
|
147
|
-
- You need dynamic styles based on state
|
|
148
|
-
- You want programmatic style generation
|
|
149
|
-
- You prefer keeping styles in JavaScript
|
|
150
|
-
- You're building component libraries
|
|
151
|
-
- You need runtime style calculations
|
|
152
|
-
|
|
153
|
-
## Advanced Patterns
|
|
154
|
-
|
|
155
|
-
### Style Functions
|
|
156
|
-
|
|
157
|
-
Create functions that return styles:
|
|
158
|
-
|
|
159
|
-
```javascript
|
|
160
|
-
export const getButtonStyle = (variant) => ({
|
|
161
|
-
...buttonBase,
|
|
162
|
-
backgroundColor: variant === 'primary' ? '#007bff' : '#6c757d'
|
|
163
|
-
});
|
|
164
|
-
```
|
|
165
|
-
|
|
166
|
-
### Conditional Styles
|
|
167
|
-
|
|
168
|
-
Use ternary operators for conditional styles:
|
|
169
|
-
|
|
170
|
-
```javascript
|
|
171
|
-
export default {
|
|
172
|
-
button: {
|
|
173
|
-
backgroundColor: isActive ? '#007bff' : '#6c757d',
|
|
174
|
-
opacity: isDisabled ? 0.5 : 1,
|
|
175
|
-
}
|
|
176
|
-
};
|
|
177
|
-
```
|
|
178
|
-
|
|
179
|
-
## Next Steps
|
|
180
|
-
|
|
181
|
-
- Explore [Styled Components](../styled-components/) for CSS-in-JS with more features
|
|
182
|
-
- Check out [Emotion](../emotion-example/) for similar CSS-in-JS approach (coming soon)
|
|
183
|
-
- Learn about [CSS Modules](../css-modules/) for scoped CSS (coming soon)
|
|
@@ -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 app() -> any {
|
|
7
|
-
let [count, setCount] = useState(0);
|
|
8
|
-
|
|
9
|
-
useEffect(lambda -> None{ console.log("Count changed: ", count);} , [count]);
|
|
10
|
-
|
|
11
|
-
let handleIncrement = lambda e: any -> None{ setCount(count + 1);} ;
|
|
12
|
-
|
|
13
|
-
let handleDecrement = lambda e: any -> None{ setCount(count - 1);} ;
|
|
14
|
-
|
|
15
|
-
let handleReset = lambda e: any -> None{ setCount(0);} ;
|
|
16
|
-
|
|
17
|
-
let 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,28 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "bootstrap-example",
|
|
3
|
-
"version": "1.0.0",
|
|
4
|
-
"main": "index.js",
|
|
5
|
-
"scripts": {
|
|
6
|
-
"build": "npm run compile && vite build",
|
|
7
|
-
"dev": "vite dev",
|
|
8
|
-
"preview": "vite preview",
|
|
9
|
-
"compile": "babel src --out-dir build --extensions \".jsx,.js\" --out-file-extension .js"
|
|
10
|
-
},
|
|
11
|
-
"keywords": [],
|
|
12
|
-
"author": "",
|
|
13
|
-
"license": "ISC",
|
|
14
|
-
"description": "Jac application: bootstrap-example",
|
|
15
|
-
"type": "module",
|
|
16
|
-
"devDependencies": {
|
|
17
|
-
"@babel/cli": "^7.28.3",
|
|
18
|
-
"@babel/core": "^7.28.5",
|
|
19
|
-
"@babel/preset-env": "^7.28.5",
|
|
20
|
-
"@babel/preset-react": "^7.28.5",
|
|
21
|
-
"vite": "^6.4.1"
|
|
22
|
-
},
|
|
23
|
-
"dependencies": {
|
|
24
|
-
"react": "^19.2.0",
|
|
25
|
-
"react-dom": "^19.2.0",
|
|
26
|
-
"react-router-dom": "^6.30.1"
|
|
27
|
-
}
|
|
28
|
-
}
|