jac-client 0.1.0__py3-none-any.whl → 0.2.1__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 (141) hide show
  1. jac_client/docs/README.md +232 -172
  2. jac_client/docs/advanced-state.md +1012 -452
  3. jac_client/docs/asset-serving/intro.md +209 -0
  4. jac_client/docs/assets/pipe_line-v2.svg +32 -0
  5. jac_client/docs/assets/pipe_line.png +0 -0
  6. jac_client/docs/file-system/intro.md +90 -0
  7. jac_client/docs/guide-example/intro.md +117 -0
  8. jac_client/docs/guide-example/step-01-setup.md +260 -0
  9. jac_client/docs/guide-example/step-02-components.md +416 -0
  10. jac_client/docs/guide-example/step-03-styling.md +478 -0
  11. jac_client/docs/guide-example/step-04-todo-ui.md +477 -0
  12. jac_client/docs/guide-example/step-05-local-state.md +530 -0
  13. jac_client/docs/guide-example/step-06-events.md +750 -0
  14. jac_client/docs/guide-example/step-07-effects.md +469 -0
  15. jac_client/docs/guide-example/step-08-walkers.md +534 -0
  16. jac_client/docs/guide-example/step-09-authentication.md +586 -0
  17. jac_client/docs/guide-example/step-10-routing.md +540 -0
  18. jac_client/docs/guide-example/step-11-final.md +964 -0
  19. jac_client/docs/imports.md +538 -46
  20. jac_client/docs/lifecycle-hooks.md +517 -297
  21. jac_client/docs/routing.md +487 -357
  22. jac_client/docs/styling/intro.md +250 -0
  23. jac_client/docs/styling/js-styling.md +373 -0
  24. jac_client/docs/styling/material-ui.md +346 -0
  25. jac_client/docs/styling/pure-css.md +305 -0
  26. jac_client/docs/styling/sass.md +409 -0
  27. jac_client/docs/styling/styled-components.md +401 -0
  28. jac_client/docs/styling/tailwind.md +303 -0
  29. jac_client/examples/asset-serving/css-with-image/.babelrc +9 -0
  30. jac_client/examples/asset-serving/css-with-image/README.md +91 -0
  31. jac_client/examples/asset-serving/css-with-image/app.jac +67 -0
  32. jac_client/examples/asset-serving/css-with-image/assets/burger.png +0 -0
  33. jac_client/examples/asset-serving/css-with-image/package.json +28 -0
  34. jac_client/examples/asset-serving/css-with-image/styles.css +27 -0
  35. jac_client/examples/asset-serving/css-with-image/vite.config.js +29 -0
  36. jac_client/examples/asset-serving/image-asset/.babelrc +9 -0
  37. jac_client/examples/asset-serving/image-asset/README.md +119 -0
  38. jac_client/examples/asset-serving/image-asset/app.jac +43 -0
  39. jac_client/examples/asset-serving/image-asset/assets/burger.png +0 -0
  40. jac_client/examples/asset-serving/image-asset/package.json +28 -0
  41. jac_client/examples/asset-serving/image-asset/styles.css +27 -0
  42. jac_client/examples/asset-serving/image-asset/vite.config.js +29 -0
  43. jac_client/examples/asset-serving/import-alias/.babelrc +9 -0
  44. jac_client/examples/asset-serving/import-alias/README.md +83 -0
  45. jac_client/examples/asset-serving/import-alias/app.jac +57 -0
  46. jac_client/examples/asset-serving/import-alias/assets/burger.png +0 -0
  47. jac_client/examples/asset-serving/import-alias/package.json +28 -0
  48. jac_client/examples/asset-serving/import-alias/vite.config.js +29 -0
  49. jac_client/examples/basic/.babelrc +9 -0
  50. jac_client/examples/basic/README.md +16 -0
  51. jac_client/examples/basic/app.jac +16 -0
  52. jac_client/examples/basic/package.json +27 -0
  53. jac_client/examples/basic/vite.config.js +28 -0
  54. jac_client/examples/basic-auth/.babelrc +9 -0
  55. jac_client/examples/basic-auth/README.md +16 -0
  56. jac_client/examples/basic-auth/app.jac +308 -0
  57. jac_client/examples/basic-auth/package.json +27 -0
  58. jac_client/examples/basic-auth/vite.config.js +28 -0
  59. jac_client/examples/basic-auth-with-router/.babelrc +9 -0
  60. jac_client/examples/basic-auth-with-router/README.md +60 -0
  61. jac_client/examples/basic-auth-with-router/app.jac +464 -0
  62. jac_client/examples/basic-auth-with-router/package.json +28 -0
  63. jac_client/examples/basic-auth-with-router/vite.config.js +28 -0
  64. jac_client/examples/basic-full-stack/.babelrc +9 -0
  65. jac_client/examples/basic-full-stack/README.md +18 -0
  66. jac_client/examples/basic-full-stack/app.jac +320 -0
  67. jac_client/examples/basic-full-stack/package.json +28 -0
  68. jac_client/examples/basic-full-stack/vite.config.js +28 -0
  69. jac_client/examples/css-styling/js-styling/.babelrc +9 -0
  70. jac_client/examples/css-styling/js-styling/README.md +183 -0
  71. jac_client/examples/css-styling/js-styling/app.jac +63 -0
  72. jac_client/examples/css-styling/js-styling/package.json +28 -0
  73. jac_client/examples/css-styling/js-styling/styles.js +100 -0
  74. jac_client/examples/css-styling/js-styling/vite.config.js +28 -0
  75. jac_client/examples/css-styling/material-ui/.babelrc +9 -0
  76. jac_client/examples/css-styling/material-ui/README.md +16 -0
  77. jac_client/examples/css-styling/material-ui/app.jac +82 -0
  78. jac_client/examples/css-styling/material-ui/package.json +32 -0
  79. jac_client/examples/css-styling/material-ui/vite.config.js +28 -0
  80. jac_client/examples/css-styling/pure-css/.babelrc +9 -0
  81. jac_client/examples/css-styling/pure-css/README.md +16 -0
  82. jac_client/examples/css-styling/pure-css/app.jac +63 -0
  83. jac_client/examples/css-styling/pure-css/package.json +28 -0
  84. jac_client/examples/css-styling/pure-css/styles.css +112 -0
  85. jac_client/examples/css-styling/pure-css/vite.config.js +28 -0
  86. jac_client/examples/css-styling/sass-example/.babelrc +9 -0
  87. jac_client/examples/css-styling/sass-example/README.md +16 -0
  88. jac_client/examples/css-styling/sass-example/app.jac +63 -0
  89. jac_client/examples/css-styling/sass-example/package.json +29 -0
  90. jac_client/examples/css-styling/sass-example/styles.scss +158 -0
  91. jac_client/examples/css-styling/sass-example/vite.config.js +28 -0
  92. jac_client/examples/css-styling/styled-components/.babelrc +9 -0
  93. jac_client/examples/css-styling/styled-components/README.md +16 -0
  94. jac_client/examples/css-styling/styled-components/app.jac +66 -0
  95. jac_client/examples/css-styling/styled-components/package.json +29 -0
  96. jac_client/examples/css-styling/styled-components/styled.js +91 -0
  97. jac_client/examples/css-styling/styled-components/vite.config.js +28 -0
  98. jac_client/examples/css-styling/tailwind-example/.babelrc +9 -0
  99. jac_client/examples/css-styling/tailwind-example/README.md +16 -0
  100. jac_client/examples/css-styling/tailwind-example/app.jac +64 -0
  101. jac_client/examples/css-styling/tailwind-example/global.css +1 -0
  102. jac_client/examples/css-styling/tailwind-example/package.json +30 -0
  103. jac_client/examples/css-styling/tailwind-example/vite.config.js +30 -0
  104. jac_client/examples/full-stack-with-auth/.babelrc +9 -0
  105. jac_client/examples/full-stack-with-auth/README.md +16 -0
  106. jac_client/examples/full-stack-with-auth/app.jac +735 -0
  107. jac_client/examples/full-stack-with-auth/package.json +28 -0
  108. jac_client/examples/full-stack-with-auth/vite.config.js +30 -0
  109. jac_client/examples/with-router/.babelrc +9 -0
  110. jac_client/examples/with-router/README.md +17 -0
  111. jac_client/examples/with-router/app.jac +323 -0
  112. jac_client/examples/with-router/package.json +28 -0
  113. jac_client/examples/with-router/vite.config.js +28 -0
  114. jac_client/plugin/cli.py +95 -179
  115. jac_client/plugin/client.py +111 -2
  116. jac_client/plugin/client_runtime.jac +183 -890
  117. jac_client/plugin/vite_client_bundle.py +185 -205
  118. jac_client/tests/__init__.py +0 -1
  119. jac_client/tests/fixtures/{client_app.jac → basic-app/app.jac} +1 -1
  120. jac_client/tests/fixtures/cl_file/app.cl.jac +38 -0
  121. jac_client/tests/fixtures/cl_file/app.jac +15 -0
  122. jac_client/tests/fixtures/{client_app_with_antd.jac → client_app_with_antd/app.jac} +7 -0
  123. jac_client/tests/fixtures/{js_import.jac → js_import/app.jac} +2 -2
  124. jac_client/tests/fixtures/{relative_import.jac → relative_import/app.jac} +1 -1
  125. jac_client/tests/fixtures/{button.jac → relative_import/button.jac} +2 -2
  126. jac_client/tests/fixtures/spawn_test/app.jac +133 -0
  127. jac_client/tests/fixtures/{test_fragments_spread.jac → test_fragments_spread/app.jac} +11 -2
  128. jac_client/tests/test_asset_examples.py +339 -0
  129. jac_client/tests/test_cl.py +345 -151
  130. jac_client/tests/test_create_jac_app.py +41 -45
  131. {jac_client-0.1.0.dist-info → jac_client-0.2.1.dist-info}/METADATA +72 -16
  132. jac_client-0.2.1.dist-info/RECORD +140 -0
  133. jac_client/examples/little-x/package-lock.json +0 -2840
  134. jac_client/examples/todo-app/README.md +0 -82
  135. jac_client/examples/todo-app/app.jac +0 -683
  136. jac_client/examples/todo-app/package-lock.json +0 -999
  137. jac_client/examples/todo-app/package.json +0 -22
  138. jac_client-0.1.0.dist-info/RECORD +0 -33
  139. /jac_client/tests/fixtures/{utils.js → js_import/utils.js} +0 -0
  140. {jac_client-0.1.0.dist-info → jac_client-0.2.1.dist-info}/WHEEL +0 -0
  141. {jac_client-0.1.0.dist-info → jac_client-0.2.1.dist-info}/entry_points.txt +0 -0
@@ -0,0 +1,100 @@
1
+ // Style objects for the counter app
2
+ const countDisplay = {
3
+ fontSize: "3.75rem",
4
+ fontWeight: "bold",
5
+ transition: "color 0.3s ease"
6
+ };
7
+
8
+ const button = {
9
+ color: "#ffffff",
10
+ fontWeight: "bold",
11
+ padding: "0.75rem 1.5rem",
12
+ borderRadius: "0.5rem",
13
+ boxShadow: "0 10px 15px -3px rgba(0, 0, 0, 0.1)",
14
+ transition: "all 0.2s ease",
15
+ fontSize: "1.25rem",
16
+ border: "none",
17
+ cursor: "pointer"
18
+ };
19
+
20
+ export default {
21
+ container: {
22
+ minHeight: "100vh",
23
+ background: "linear-gradient(to bottom right, #dbeafe, #e0e7ff)",
24
+ display: "flex",
25
+ alignItems: "center",
26
+ justifyContent: "center",
27
+ padding: "1rem"
28
+ },
29
+ card: {
30
+ backgroundColor: "#ffffff",
31
+ borderRadius: "1rem",
32
+ boxShadow: "0 25px 50px -12px rgba(0, 0, 0, 0.25)",
33
+ padding: "2rem",
34
+ maxWidth: "28rem",
35
+ width: "100%"
36
+ },
37
+ title: {
38
+ fontSize: "1.875rem",
39
+ fontWeight: "bold",
40
+ color: "#1f2937",
41
+ textAlign: "center",
42
+ marginBottom: "1.5rem"
43
+ },
44
+ divider: {
45
+ height: "1px",
46
+ background: "linear-gradient(to right, transparent, #d1d5db, transparent)",
47
+ marginBottom: "1.5rem"
48
+ },
49
+ counterSection: {
50
+ textAlign: "center",
51
+ marginBottom: "2rem"
52
+ },
53
+ label: {
54
+ fontSize: "0.875rem",
55
+ fontWeight: "600",
56
+ color: "#4b5563",
57
+ marginBottom: "0.5rem",
58
+ textTransform: "uppercase",
59
+ letterSpacing: "0.05em"
60
+ },
61
+ countDisplay: countDisplay,
62
+ countDisplayZero: {
63
+ ...countDisplay,
64
+ color: "#1f2937"
65
+ },
66
+ countDisplayPositive: {
67
+ ...countDisplay,
68
+ color: "#16a34a"
69
+ },
70
+ countDisplayNegative: {
71
+ ...countDisplay,
72
+ color: "#dc2626"
73
+ },
74
+ buttonGroup: {
75
+ display: "flex",
76
+ justifyContent: "center",
77
+ alignItems: "center",
78
+ gap: "1rem",
79
+ marginBottom: "1.5rem"
80
+ },
81
+ button: button,
82
+ buttonDecrement: {
83
+ ...button,
84
+ backgroundColor: "#ef4444"
85
+ },
86
+ buttonReset: {
87
+ ...button,
88
+ backgroundColor: "#6b7280"
89
+ },
90
+ buttonIncrement: {
91
+ ...button,
92
+ backgroundColor: "#22c55e"
93
+ },
94
+ hint: {
95
+ textAlign: "center",
96
+ fontSize: "0.875rem",
97
+ color: "#6b7280",
98
+ fontStyle: "italic"
99
+ }
100
+ };
@@ -0,0 +1,28 @@
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
+ });
28
+
@@ -0,0 +1,9 @@
1
+
2
+ {
3
+ "presets": [[
4
+ "@babel/preset-env",
5
+ {
6
+ "modules": false
7
+ }
8
+ ], "@babel/preset-react"]
9
+ }
@@ -0,0 +1,16 @@
1
+ # my-test-app
2
+
3
+ ## Running Jac Code
4
+
5
+ make sure node modules are installed:
6
+ ```bash
7
+ npm install
8
+ ```
9
+
10
+ To run your Jac code, use the Jac CLI:
11
+
12
+ ```bash
13
+ jac serve app.jac
14
+ ```
15
+
16
+ Happy coding with Jac!
@@ -0,0 +1,82 @@
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 app() -> any {
16
+ let [count, setCount] = useState(0);
17
+
18
+ useEffect(lambda -> None {
19
+ console.log("Count changed: ", count);
20
+ }, [count]);
21
+
22
+ let handleIncrement = lambda e: any -> None {
23
+ setCount(count + 1);
24
+ };
25
+
26
+ let handleDecrement = lambda e: any -> None {
27
+ setCount(count - 1);
28
+ };
29
+
30
+ let handleReset = lambda e: any -> None {
31
+ setCount(0);
32
+ };
33
+
34
+ return <Box sx={{"display": "flex", "justifyContent": "center", "alignItems": "center", "minHeight": "100vh", "backgroundColor": "#f5f5f5"}}>
35
+ <Card sx={{"minWidth": 400, "boxShadow": 3}}>
36
+ <CardContent>
37
+ <Typography variant="h4" component="div" gutterBottom sx={{"textAlign": "center", "color": "primary.main"}}>
38
+ Counter Application
39
+ </Typography>
40
+ <Divider sx={{"my": 2}} />
41
+ <Box sx={{"display": "flex", "flexDirection": "column", "alignItems": "center", "py": 3}}>
42
+ <Typography variant="h6" color="text.secondary" gutterBottom>
43
+ Current Count
44
+ </Typography>
45
+ <Typography variant="h1" component="div" sx={{"fontWeight": "bold", "color": "success.main" if count > 0 else "error.main" if count < 0 else "text.primary"}}>
46
+ {count}
47
+ </Typography>
48
+ </Box>
49
+ </CardContent>
50
+ <Divider />
51
+ <CardActions sx={{"display": "flex", "justifyContent": "space-around", "p": 2}}>
52
+ <IconButton
53
+ color="error"
54
+ size="large"
55
+ onClick={handleDecrement}
56
+ sx={{"border": "2px solid", "borderColor": "error.main"}}>
57
+ <RemoveIcon />
58
+ </IconButton>
59
+ <IconButton
60
+ color="primary"
61
+ size="large"
62
+ onClick={handleReset}
63
+ sx={{"border": "2px solid", "borderColor": "primary.main"}}>
64
+ <RefreshIcon />
65
+ </IconButton>
66
+ <IconButton
67
+ color="success"
68
+ size="large"
69
+ onClick={handleIncrement}
70
+ sx={{"border": "2px solid", "borderColor": "success.main"}}>
71
+ <AddIcon />
72
+ </IconButton>
73
+ </CardActions>
74
+ <Box sx={{"px": 3, "pb": 2}}>
75
+ <Typography variant="caption" color="text.secondary" sx={{"display": "block", "textAlign": "center"}}>
76
+ Click the buttons to increment, decrement, or reset the counter
77
+ </Typography>
78
+ </Box>
79
+ </Card>
80
+ </Box>;
81
+ }
82
+ }
@@ -0,0 +1,32 @@
1
+ {
2
+ "name": "my-test-app",
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: my-test-app",
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
+ "@emotion/react": "^11.14.0",
25
+ "@emotion/styled": "^11.14.1",
26
+ "@mui/icons-material": "^7.3.5",
27
+ "@mui/material": "^7.3.5",
28
+ "react": "^19.2.0",
29
+ "react-dom": "^19.2.0",
30
+ "react-router-dom": "^6.30.1"
31
+ }
32
+ }
@@ -0,0 +1,28 @@
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
+ });
28
+
@@ -0,0 +1,9 @@
1
+
2
+ {
3
+ "presets": [[
4
+ "@babel/preset-env",
5
+ {
6
+ "modules": false
7
+ }
8
+ ], "@babel/preset-react"]
9
+ }
@@ -0,0 +1,16 @@
1
+ # my-test-app
2
+
3
+ ## Running Jac Code
4
+
5
+ make sure node modules are installed:
6
+ ```bash
7
+ npm install
8
+ ```
9
+
10
+ To run your Jac code, use the Jac CLI:
11
+
12
+ ```bash
13
+ jac serve app.jac
14
+ ```
15
+
16
+ Happy coding with Jac!
@@ -0,0 +1,63 @@
1
+ # Pages
2
+ cl import from react {useState, useEffect}
3
+ cl import ".styles.css";
4
+
5
+ cl {
6
+ def app() -> any {
7
+ let [count, setCount] = useState(0);
8
+
9
+ useEffect(lambda -> None {
10
+ console.log("Count changed: ", count);
11
+ }, [count]);
12
+
13
+ let handleIncrement = lambda e: any -> None {
14
+ setCount(count + 1);
15
+ };
16
+
17
+ let handleDecrement = lambda e: any -> None {
18
+ setCount(count - 1);
19
+ };
20
+
21
+ let handleReset = lambda e: any -> None {
22
+ setCount(0);
23
+ };
24
+
25
+ let countClass = "countDisplay " + ("positive" if count > 0 else "negative" if count < 0 else "zero");
26
+
27
+ return <div className="container">
28
+ <div className="card">
29
+ <h1 className="title">Counter Application</h1>
30
+ <div className="divider"></div>
31
+
32
+ <div className="counterSection">
33
+ <div className="label">Current Count</div>
34
+ <div className={countClass}>{count}</div>
35
+ </div>
36
+
37
+ <div className="divider"></div>
38
+
39
+ <div className="buttonGroup">
40
+ <button
41
+ className="btn btnDecrement"
42
+ onClick={handleDecrement}>
43
+ -
44
+ </button>
45
+ <button
46
+ className="btn btnReset"
47
+ onClick={handleReset}>
48
+
49
+ </button>
50
+ <button
51
+ className="btn btnIncrement"
52
+ onClick={handleIncrement}>
53
+ +
54
+ </button>
55
+ </div>
56
+
57
+ <div className="hint">
58
+ Click the buttons to increment, decrement, or reset the counter
59
+ </div>
60
+ </div>
61
+ </div>;
62
+ }
63
+ }
@@ -0,0 +1,28 @@
1
+ {
2
+ "name": "my-test-app",
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: my-test-app",
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": "^6.30.1"
27
+ }
28
+ }
@@ -0,0 +1,112 @@
1
+ .container {
2
+ display: flex;
3
+ justify-content: center;
4
+ align-items: center;
5
+ min-height: 100vh;
6
+ background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
7
+ font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
8
+ }
9
+
10
+ .card {
11
+ background: white;
12
+ border-radius: 20px;
13
+ box-shadow: 0 20px 60px rgba(0, 0, 0, 0.3);
14
+ padding: 40px;
15
+ min-width: 400px;
16
+ text-align: center;
17
+ }
18
+
19
+ .title {
20
+ font-size: 2rem;
21
+ color: #667eea;
22
+ margin: 0 0 10px 0;
23
+ font-weight: 600;
24
+ }
25
+
26
+ .divider {
27
+ height: 2px;
28
+ background: linear-gradient(90deg, transparent, #667eea, transparent);
29
+ margin: 20px 0;
30
+ }
31
+
32
+ .counterSection {
33
+ padding: 30px 0;
34
+ }
35
+
36
+ .label {
37
+ font-size: 1.2rem;
38
+ color: #666;
39
+ margin-bottom: 10px;
40
+ }
41
+
42
+ .countDisplay {
43
+ font-size: 5rem;
44
+ font-weight: bold;
45
+ margin: 20px 0;
46
+ transition: color 0.3s ease;
47
+ }
48
+
49
+ .positive {
50
+ color: #4caf50;
51
+ }
52
+
53
+ .negative {
54
+ color: #f44336;
55
+ }
56
+
57
+ .zero {
58
+ color: #333;
59
+ }
60
+
61
+ .buttonGroup {
62
+ display: flex;
63
+ justify-content: space-around;
64
+ gap: 15px;
65
+ margin-top: 30px;
66
+ }
67
+
68
+ .btn {
69
+ border: none;
70
+ border-radius: 50%;
71
+ width: 70px;
72
+ height: 70px;
73
+ font-size: 1.5rem;
74
+ cursor: pointer;
75
+ transition: all 0.3s ease;
76
+ display: flex;
77
+ align-items: center;
78
+ justify-content: center;
79
+ font-weight: bold;
80
+ box-shadow: 0 4px 15px rgba(0, 0, 0, 0.2);
81
+ }
82
+
83
+ .btn:hover {
84
+ transform: translateY(-3px);
85
+ box-shadow: 0 6px 20px rgba(0, 0, 0, 0.3);
86
+ }
87
+
88
+ .btn:active {
89
+ transform: translateY(0);
90
+ }
91
+
92
+ .btnDecrement {
93
+ background: linear-gradient(135deg, #f44336, #e91e63);
94
+ color: white;
95
+ }
96
+
97
+ .btnReset {
98
+ background: linear-gradient(135deg, #2196f3, #00bcd4);
99
+ color: white;
100
+ }
101
+
102
+ .btnIncrement {
103
+ background: linear-gradient(135deg, #4caf50, #8bc34a);
104
+ color: white;
105
+ }
106
+
107
+ .hint {
108
+ margin-top: 20px;
109
+ font-size: 0.9rem;
110
+ color: #999;
111
+ }
112
+
@@ -0,0 +1,28 @@
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
+ });
28
+
@@ -0,0 +1,9 @@
1
+
2
+ {
3
+ "presets": [[
4
+ "@babel/preset-env",
5
+ {
6
+ "modules": false
7
+ }
8
+ ], "@babel/preset-react"]
9
+ }
@@ -0,0 +1,16 @@
1
+ # sass-example
2
+
3
+ ## Running Jac Code
4
+
5
+ make sure node modules are installed:
6
+ ```bash
7
+ npm install
8
+ ```
9
+
10
+ To run your Jac code, use the Jac CLI:
11
+
12
+ ```bash
13
+ jac serve app.jac
14
+ ```
15
+
16
+ Happy coding with Jac!
@@ -0,0 +1,63 @@
1
+ # Pages
2
+ cl import from react {useState, useEffect}
3
+ cl import ".styles.scss";
4
+
5
+ cl {
6
+ def app() -> any {
7
+ let [count, setCount] = useState(0);
8
+
9
+ useEffect(lambda -> None {
10
+ console.log("Count changed: ", count);
11
+ }, [count]);
12
+
13
+ let handleIncrement = lambda e: any -> None {
14
+ setCount(count + 1);
15
+ };
16
+
17
+ let handleDecrement = lambda e: any -> None {
18
+ setCount(count - 1);
19
+ };
20
+
21
+ let handleReset = lambda e: any -> None {
22
+ setCount(0);
23
+ };
24
+
25
+ let countClass = "countDisplay " + ("positive" if count > 0 else "negative" if count < 0 else "zero");
26
+
27
+ return <div className="container">
28
+ <div className="card">
29
+ <h1 className="title">Counter Application</h1>
30
+ <div className="divider"></div>
31
+
32
+ <div className="counterSection">
33
+ <div className="label">Current Count</div>
34
+ <div className={countClass}>{count}</div>
35
+ </div>
36
+
37
+ <div className="divider"></div>
38
+
39
+ <div className="buttonGroup">
40
+ <button
41
+ className="btn btnDecrement"
42
+ onClick={handleDecrement}>
43
+ -
44
+ </button>
45
+ <button
46
+ className="btn btnReset"
47
+ onClick={handleReset}>
48
+
49
+ </button>
50
+ <button
51
+ className="btn btnIncrement"
52
+ onClick={handleIncrement}>
53
+ +
54
+ </button>
55
+ </div>
56
+
57
+ <div className="hint">
58
+ Click the buttons to increment, decrement, or reset the counter
59
+ </div>
60
+ </div>
61
+ </div>;
62
+ }
63
+ }
@@ -0,0 +1,29 @@
1
+ {
2
+ "name": "sass-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: sass-example",
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
+ "sass": "^1.77.8"
23
+ },
24
+ "dependencies": {
25
+ "react": "^19.2.0",
26
+ "react-dom": "^19.2.0",
27
+ "react-router-dom": "^6.30.1"
28
+ }
29
+ }