jac-client 0.2.0__py3-none-any.whl → 0.2.2__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 (154) hide show
  1. jac_client/docs/README.md +50 -20
  2. jac_client/docs/advanced-state.md +13 -14
  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/file-system/app.jac.md +121 -0
  6. jac_client/docs/file-system/backend-frontend.md +217 -0
  7. jac_client/docs/file-system/intro.md +72 -0
  8. jac_client/docs/file-system/nested-imports.md +348 -0
  9. jac_client/docs/guide-example/intro.md +11 -13
  10. jac_client/docs/guide-example/step-01-setup.md +30 -20
  11. jac_client/docs/guide-example/step-02-components.md +24 -24
  12. jac_client/docs/guide-example/step-03-styling.md +24 -24
  13. jac_client/docs/guide-example/step-04-todo-ui.md +17 -17
  14. jac_client/docs/guide-example/step-05-local-state.md +23 -23
  15. jac_client/docs/guide-example/step-06-events.md +23 -24
  16. jac_client/docs/guide-example/step-07-effects.md +27 -28
  17. jac_client/docs/guide-example/step-08-walkers.md +23 -23
  18. jac_client/docs/guide-example/step-09-authentication.md +18 -18
  19. jac_client/docs/guide-example/step-10-routing.md +20 -21
  20. jac_client/docs/guide-example/step-11-final.md +34 -35
  21. jac_client/docs/imports.md +4 -5
  22. jac_client/docs/lifecycle-hooks.md +12 -13
  23. jac_client/docs/routing.md +21 -22
  24. jac_client/docs/styling/intro.md +249 -0
  25. jac_client/docs/styling/js-styling.md +367 -0
  26. jac_client/docs/styling/material-ui.md +341 -0
  27. jac_client/docs/styling/pure-css.md +299 -0
  28. jac_client/docs/styling/sass.md +403 -0
  29. jac_client/docs/styling/styled-components.md +395 -0
  30. jac_client/docs/styling/tailwind.md +298 -0
  31. jac_client/examples/all-in-one/.babelrc +9 -0
  32. jac_client/examples/all-in-one/README.md +16 -0
  33. jac_client/examples/all-in-one/app.jac +426 -0
  34. jac_client/examples/all-in-one/assets/burger.png +0 -0
  35. jac_client/examples/all-in-one/button.jac +7 -0
  36. jac_client/examples/all-in-one/components/button.jac +7 -0
  37. jac_client/examples/all-in-one/package.json +29 -0
  38. jac_client/examples/all-in-one/styles.css +26 -0
  39. jac_client/examples/all-in-one/vite.config.js +28 -0
  40. jac_client/examples/asset-serving/css-with-image/.babelrc +9 -0
  41. jac_client/examples/asset-serving/css-with-image/README.md +91 -0
  42. jac_client/examples/asset-serving/css-with-image/app.jac +88 -0
  43. jac_client/examples/asset-serving/css-with-image/assets/burger.png +0 -0
  44. jac_client/examples/asset-serving/css-with-image/package.json +28 -0
  45. jac_client/examples/asset-serving/css-with-image/styles.css +26 -0
  46. jac_client/examples/asset-serving/css-with-image/vite.config.js +28 -0
  47. jac_client/examples/asset-serving/image-asset/.babelrc +9 -0
  48. jac_client/examples/asset-serving/image-asset/README.md +119 -0
  49. jac_client/examples/asset-serving/image-asset/app.jac +55 -0
  50. jac_client/examples/asset-serving/image-asset/assets/burger.png +0 -0
  51. jac_client/examples/asset-serving/image-asset/package.json +28 -0
  52. jac_client/examples/asset-serving/image-asset/styles.css +26 -0
  53. jac_client/examples/asset-serving/image-asset/vite.config.js +28 -0
  54. jac_client/examples/asset-serving/import-alias/.babelrc +9 -0
  55. jac_client/examples/asset-serving/import-alias/README.md +83 -0
  56. jac_client/examples/asset-serving/import-alias/app.jac +111 -0
  57. jac_client/examples/asset-serving/import-alias/assets/burger.png +0 -0
  58. jac_client/examples/asset-serving/import-alias/package.json +28 -0
  59. jac_client/examples/asset-serving/import-alias/vite.config.js +28 -0
  60. jac_client/examples/basic/app.jac +14 -9
  61. jac_client/examples/basic/package.json +1 -1
  62. jac_client/examples/basic/vite.config.js +0 -1
  63. jac_client/examples/basic-auth/package.json +1 -1
  64. jac_client/examples/basic-auth/vite.config.js +0 -1
  65. jac_client/examples/basic-auth-with-router/package.json +1 -1
  66. jac_client/examples/basic-auth-with-router/vite.config.js +0 -1
  67. jac_client/examples/basic-full-stack/package.json +1 -1
  68. jac_client/examples/basic-full-stack/vite.config.js +0 -1
  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 +84 -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 +27 -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 +122 -0
  78. jac_client/examples/css-styling/material-ui/package.json +32 -0
  79. jac_client/examples/css-styling/material-ui/vite.config.js +27 -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 +64 -0
  83. jac_client/examples/css-styling/pure-css/package.json +28 -0
  84. jac_client/examples/css-styling/pure-css/styles.css +111 -0
  85. jac_client/examples/css-styling/pure-css/vite.config.js +27 -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 +64 -0
  89. jac_client/examples/css-styling/sass-example/package.json +29 -0
  90. jac_client/examples/css-styling/sass-example/styles.scss +153 -0
  91. jac_client/examples/css-styling/sass-example/vite.config.js +27 -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 +71 -0
  95. jac_client/examples/css-styling/styled-components/package.json +29 -0
  96. jac_client/examples/css-styling/styled-components/styled.js +90 -0
  97. jac_client/examples/css-styling/styled-components/vite.config.js +27 -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 +63 -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 +29 -0
  104. jac_client/examples/full-stack-with-auth/app.jac +20 -33
  105. jac_client/examples/full-stack-with-auth/package.json +1 -1
  106. jac_client/examples/full-stack-with-auth/vite.config.js +0 -1
  107. jac_client/examples/little-x/app.jac +327 -218
  108. jac_client/examples/little-x/submit-button.jac +1 -1
  109. jac_client/examples/nested-folders/nested-advance/.babelrc +9 -0
  110. jac_client/examples/nested-folders/nested-advance/ButtonRoot.jac +11 -0
  111. jac_client/examples/nested-folders/nested-advance/README.md +77 -0
  112. jac_client/examples/nested-folders/nested-advance/app.jac +35 -0
  113. jac_client/examples/nested-folders/nested-advance/level1/ButtonSecondL.jac +19 -0
  114. jac_client/examples/nested-folders/nested-advance/level1/Card.jac +43 -0
  115. jac_client/examples/nested-folders/nested-advance/level1/level2/ButtonThirdL.jac +25 -0
  116. jac_client/examples/nested-folders/nested-advance/package.json +29 -0
  117. jac_client/examples/nested-folders/nested-advance/vite.config.js +28 -0
  118. jac_client/examples/nested-folders/nested-basic/.babelrc +9 -0
  119. jac_client/examples/nested-folders/nested-basic/README.md +183 -0
  120. jac_client/examples/nested-folders/nested-basic/app.jac +13 -0
  121. jac_client/examples/nested-folders/nested-basic/app.js +7 -0
  122. jac_client/examples/nested-folders/nested-basic/button.jac +7 -0
  123. jac_client/examples/nested-folders/nested-basic/components/button.jac +7 -0
  124. jac_client/examples/nested-folders/nested-basic/package.json +28 -0
  125. jac_client/examples/nested-folders/nested-basic/vite.config.js +27 -0
  126. jac_client/examples/with-router/app.jac +1 -1
  127. jac_client/examples/with-router/package.json +1 -1
  128. jac_client/examples/with-router/vite.config.js +0 -1
  129. jac_client/plugin/cli.py +7 -2
  130. jac_client/plugin/client.py +68 -5
  131. jac_client/plugin/client_runtime.jac +1 -1
  132. jac_client/plugin/vite_client_bundle.py +162 -14
  133. jac_client/tests/__init__.py +0 -1
  134. jac_client/tests/fixtures/basic-app/app.jac +7 -2
  135. jac_client/tests/fixtures/cl_file/app.cl.jac +48 -0
  136. jac_client/tests/fixtures/cl_file/app.jac +15 -0
  137. jac_client/tests/fixtures/client_app_with_antd/app.jac +14 -8
  138. jac_client/tests/fixtures/js_import/app.jac +19 -15
  139. jac_client/tests/fixtures/js_import/utils.js +0 -1
  140. jac_client/tests/fixtures/package.json +1 -1
  141. jac_client/tests/fixtures/relative_import/app.jac +4 -6
  142. jac_client/tests/fixtures/relative_import/button.jac +7 -6
  143. jac_client/tests/fixtures/spawn_test/app.jac +1 -5
  144. jac_client/tests/fixtures/test_fragments_spread/app.jac +24 -10
  145. jac_client/tests/test_asset_examples.py +322 -0
  146. jac_client/tests/test_cl.py +480 -426
  147. jac_client/tests/test_create_jac_app.py +125 -133
  148. jac_client/tests/test_it.py +329 -0
  149. jac_client/tests/test_nested_file.py +374 -0
  150. {jac_client-0.2.0.dist-info → jac_client-0.2.2.dist-info}/METADATA +2 -2
  151. jac_client-0.2.2.dist-info/RECORD +171 -0
  152. jac_client-0.2.0.dist-info/RECORD +0 -72
  153. {jac_client-0.2.0.dist-info → jac_client-0.2.2.dist-info}/WHEEL +0 -0
  154. {jac_client-0.2.0.dist-info → jac_client-0.2.2.dist-info}/entry_points.txt +0 -0
@@ -0,0 +1,153 @@
1
+ // Sass Variables
2
+ $primary-gradient-start: #dbeafe;
3
+ $primary-gradient-end: #e0e7ff;
4
+ $white: #ffffff;
5
+ $gray-800: #1f2937;
6
+ $gray-600: #4b5563;
7
+ $gray-500: #6b7280;
8
+ $green-600: #16a34a;
9
+ $red-500: #ef4444;
10
+ $red-600: #dc2626;
11
+
12
+ // Mixins
13
+ @mixin flex-center {
14
+ display: flex;
15
+ align-items: center;
16
+ justify-content: center;
17
+ }
18
+
19
+ @mixin button-base {
20
+ color: $white;
21
+ font-weight: bold;
22
+ padding: 0.75rem 1.5rem;
23
+ border-radius: 0.5rem;
24
+ box-shadow: 0 10px 15px -3px rgba(0, 0, 0, 0.1);
25
+ transition: all 0.2s ease;
26
+ font-size: 1.25rem;
27
+ border: none;
28
+ cursor: pointer;
29
+
30
+ &:hover {
31
+ transform: scale(1.05);
32
+ }
33
+
34
+ &:active {
35
+ transform: scale(0.95);
36
+ }
37
+ }
38
+
39
+ @mixin gradient-divider {
40
+ height: 1px;
41
+ background: linear-gradient(to right, transparent, $gray-500, transparent);
42
+ margin-bottom: 1.5rem;
43
+ }
44
+
45
+ // Container
46
+ .container {
47
+ min-height: 100vh;
48
+ background: linear-gradient(to bottom right, $primary-gradient-start, $primary-gradient-end);
49
+ @include flex-center;
50
+ padding: 1rem;
51
+ }
52
+
53
+ // Card
54
+ .card {
55
+ background-color: $white;
56
+ border-radius: 1rem;
57
+ box-shadow: 0 25px 50px -12px rgba(0, 0, 0, 0.25);
58
+ padding: 2rem;
59
+ max-width: 28rem;
60
+ width: 100%;
61
+ }
62
+
63
+ // Title
64
+ .title {
65
+ font-size: 1.875rem;
66
+ font-weight: bold;
67
+ color: $gray-800;
68
+ text-align: center;
69
+ margin-bottom: 1.5rem;
70
+ }
71
+
72
+ // Divider
73
+ .divider {
74
+ @include gradient-divider;
75
+ }
76
+
77
+ // Counter Section
78
+ .counterSection {
79
+ text-align: center;
80
+ margin-bottom: 2rem;
81
+ }
82
+
83
+ .label {
84
+ font-size: 0.875rem;
85
+ font-weight: 600;
86
+ color: $gray-600;
87
+ margin-bottom: 0.5rem;
88
+ text-transform: uppercase;
89
+ letter-spacing: 0.05em;
90
+ }
91
+
92
+ // Count Display with dynamic colors
93
+ .countDisplay {
94
+ font-size: 3.75rem;
95
+ font-weight: bold;
96
+ transition: color 0.3s ease;
97
+
98
+ &.zero {
99
+ color: $gray-800;
100
+ }
101
+
102
+ &.positive {
103
+ color: $green-600;
104
+ }
105
+
106
+ &.negative {
107
+ color: $red-600;
108
+ }
109
+ }
110
+
111
+ // Button Group
112
+ .buttonGroup {
113
+ @include flex-center;
114
+ gap: 1rem;
115
+ margin-bottom: 1.5rem;
116
+ }
117
+
118
+ // Buttons
119
+ .btn {
120
+ @include button-base;
121
+
122
+ &Decrement {
123
+ background-color: $red-500;
124
+
125
+ &:hover {
126
+ background-color: darken($red-500, 10%);
127
+ }
128
+ }
129
+
130
+ &Reset {
131
+ background-color: $gray-500;
132
+
133
+ &:hover {
134
+ background-color: darken($gray-500, 10%);
135
+ }
136
+ }
137
+
138
+ &Increment {
139
+ background-color: $green-600;
140
+
141
+ &:hover {
142
+ background-color: darken($green-600, 10%);
143
+ }
144
+ }
145
+ }
146
+
147
+ // Hint
148
+ .hint {
149
+ text-align: center;
150
+ font-size: 0.875rem;
151
+ color: $gray-500;
152
+ font-style: italic;
153
+ }
@@ -0,0 +1,27 @@
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
+ });
@@ -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
+ # styled-components
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,71 @@
1
+ # Pages
2
+ cl import from react { useState, useEffect }
3
+ cl import from .styled {
4
+ Container,
5
+ Card,
6
+ Title,
7
+ Divider,
8
+ CounterSection,
9
+ Label,
10
+ CountDisplay,
11
+ ButtonGroup,
12
+ Button,
13
+ Hint
14
+ }
15
+
16
+ cl {
17
+ def app() -> any {
18
+ let [count, setCount] = useState(0);
19
+
20
+ useEffect(lambda -> None{ console.log("Count changed: ", count);} , [count]);
21
+
22
+ let handleIncrement = lambda e: any -> None{ setCount(count + 1);} ;
23
+
24
+ let handleDecrement = lambda e: any -> None{ setCount(count - 1);} ;
25
+
26
+ let handleReset = lambda e: any -> None{ setCount(0);} ;
27
+
28
+ return <Container>
29
+ <Card>
30
+ <Title>
31
+ Counter Application
32
+ </Title>
33
+ <Divider></Divider>
34
+ <CounterSection>
35
+ <Label>
36
+ Current Count
37
+ </Label>
38
+ <CountDisplay
39
+ count={count}
40
+ >
41
+ {count}
42
+ </CountDisplay>
43
+ </CounterSection>
44
+ <Divider></Divider>
45
+ <ButtonGroup>
46
+ <Button
47
+ bgColor="#ef4444"
48
+ onClick={handleDecrement}
49
+ >
50
+ -
51
+ </Button>
52
+ <Button
53
+ bgColor="#6b7280"
54
+ onClick={handleReset}
55
+ >
56
+
57
+ </Button>
58
+ <Button
59
+ bgColor="#22c55e"
60
+ onClick={handleIncrement}
61
+ >
62
+ +
63
+ </Button>
64
+ </ButtonGroup>
65
+ <Hint>
66
+ Click the buttons to increment, decrement, or reset the counter
67
+ </Hint>
68
+ </Card>
69
+ </Container>;
70
+ }
71
+ }
@@ -0,0 +1,29 @@
1
+ {
2
+ "name": "styled-components",
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: styled-components",
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
+ "styled-components": "^6.1.13"
28
+ }
29
+ }
@@ -0,0 +1,90 @@
1
+ import styled from "styled-components";
2
+
3
+ export const Container = styled.div`
4
+ min-height: 100vh;
5
+ background: linear-gradient(to bottom right, #dbeafe, #e0e7ff);
6
+ display: flex;
7
+ align-items: center;
8
+ justify-content: center;
9
+ padding: 1rem;
10
+ `;
11
+
12
+ export const Card = styled.div`
13
+ background-color: #ffffff;
14
+ border-radius: 1rem;
15
+ box-shadow: 0 25px 50px -12px rgba(0, 0, 0, 0.25);
16
+ padding: 2rem;
17
+ max-width: 28rem;
18
+ width: 100%;
19
+ `;
20
+
21
+ export const Title = styled.h1`
22
+ font-size: 1.875rem;
23
+ font-weight: bold;
24
+ color: #1f2937;
25
+ text-align: center;
26
+ margin-bottom: 1.5rem;
27
+ `;
28
+
29
+ export const Divider = styled.div`
30
+ height: 1px;
31
+ background: linear-gradient(to right, transparent, #d1d5db, transparent);
32
+ margin-bottom: 1.5rem;
33
+ `;
34
+
35
+ export const CounterSection = styled.div`
36
+ text-align: center;
37
+ margin-bottom: 2rem;
38
+ `;
39
+
40
+ export const Label = styled.div`
41
+ font-size: 0.875rem;
42
+ font-weight: 600;
43
+ color: #4b5563;
44
+ margin-bottom: 0.5rem;
45
+ text-transform: uppercase;
46
+ letter-spacing: 0.05em;
47
+ `;
48
+
49
+ export const CountDisplay = styled.div`
50
+ font-size: 3.75rem;
51
+ font-weight: bold;
52
+ transition: color 0.3s ease;
53
+ color: ${props => props.count === 0 ? "#1f2937" : (props.count > 0 ? "#16a34a" : "#dc2626")};
54
+ `;
55
+
56
+ export const ButtonGroup = styled.div`
57
+ display: flex;
58
+ justify-content: center;
59
+ align-items: center;
60
+ gap: 1rem;
61
+ margin-bottom: 1.5rem;
62
+ `;
63
+
64
+ export const Button = styled.button`
65
+ color: #ffffff;
66
+ font-weight: bold;
67
+ padding: 0.75rem 1.5rem;
68
+ border-radius: 0.5rem;
69
+ box-shadow: 0 10px 15px -3px rgba(0, 0, 0, 0.1);
70
+ transition: all 0.2s ease;
71
+ font-size: 1.25rem;
72
+ border: none;
73
+ cursor: pointer;
74
+ background-color: ${props => props.bgColor};
75
+
76
+ &:hover {
77
+ transform: scale(1.05);
78
+ }
79
+
80
+ &:active {
81
+ transform: scale(0.95);
82
+ }
83
+ `;
84
+
85
+ export const Hint = styled.div`
86
+ text-align: center;
87
+ font-size: 0.875rem;
88
+ color: #6b7280;
89
+ font-style: italic;
90
+ `;
@@ -0,0 +1,27 @@
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
+ });
@@ -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
+ # tailwind-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 ".global.css";
4
+ cl {
5
+ def app() -> any {
6
+ let [count, setCount] = useState(0);
7
+
8
+ useEffect(lambda -> None{ console.log("Count changed: ", count);} , [count]);
9
+
10
+ let handleIncrement = lambda e: any -> None{ setCount(count + 1);} ;
11
+
12
+ let handleDecrement = lambda e: any -> None{ setCount(count - 1);} ;
13
+
14
+ let handleReset = lambda e: any -> None{ setCount(0);} ;
15
+
16
+ let countColorClass = "text-gray-800"
17
+ if count == 0
18
+ else ("text-green-600" if count > 0 else "text-red-600");
19
+
20
+ return <div className="min-h-screen bg-gradient-to-br from-blue-50 to-indigo-100 flex items-center justify-center p-4">
21
+ <div className="bg-white rounded-2xl shadow-2xl p-8 max-w-md w-full">
22
+ <h1 className="text-3xl font-bold text-gray-800 text-center mb-6">
23
+ Counter Application
24
+ </h1>
25
+ <div className="h-px bg-gradient-to-r from-transparent via-gray-300 to-transparent mb-6"></div>
26
+ <div className="text-center mb-8">
27
+ <div className="text-sm font-semibold text-gray-600 mb-2 uppercase tracking-wide">
28
+ Current Count
29
+ </div>
30
+ <div
31
+ className={"text-6xl font-bold " + countColorClass + " transition-colors duration-300"}
32
+ >
33
+ {count}
34
+ </div>
35
+ </div>
36
+ <div className="h-px bg-gradient-to-r from-transparent via-gray-300 to-transparent mb-6"></div>
37
+ <div className="flex justify-center items-center gap-4 mb-6">
38
+ <button
39
+ className="bg-red-500 hover:bg-red-600 text-white font-bold py-3 px-6 rounded-lg shadow-lg transition-all duration-200 transform hover:scale-105 active:scale-95 text-xl"
40
+ onClick={handleDecrement}
41
+ >
42
+ -
43
+ </button>
44
+ <button
45
+ className="bg-gray-500 hover:bg-gray-600 text-white font-bold py-3 px-6 rounded-lg shadow-lg transition-all duration-200 transform hover:scale-105 active:scale-95 text-xl"
46
+ onClick={handleReset}
47
+ >
48
+
49
+ </button>
50
+ <button
51
+ className="bg-green-500 hover:bg-green-600 text-white font-bold py-3 px-6 rounded-lg shadow-lg transition-all duration-200 transform hover:scale-105 active:scale-95 text-xl"
52
+ onClick={handleIncrement}
53
+ >
54
+ +
55
+ </button>
56
+ </div>
57
+ <div className="text-center text-sm text-gray-500 italic">
58
+ Click the buttons to increment, decrement, or reset the counter
59
+ </div>
60
+ </div>
61
+ </div>;
62
+ }
63
+ }
@@ -0,0 +1 @@
1
+ @import "tailwindcss";
@@ -0,0 +1,30 @@
1
+ {
2
+ "name": "tailwind-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: tailwind-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
+ "@tailwindcss/vite": "^4.1.17",
25
+ "react": "^19.2.0",
26
+ "react-dom": "^19.2.0",
27
+ "react-router-dom": "^6.30.1",
28
+ "tailwindcss": "^4.1.17"
29
+ }
30
+ }
@@ -0,0 +1,29 @@
1
+
2
+ import { defineConfig } from "vite";
3
+ import tailwindcss from '@tailwindcss/vite'
4
+ import path from "path";
5
+ import { fileURLToPath } from "url";
6
+
7
+ const __dirname = path.dirname(fileURLToPath(import.meta.url));
8
+
9
+ export default defineConfig({
10
+ root: ".", // base folder
11
+ build: {
12
+ rollupOptions: {
13
+ input: "build/main.js", // your compiled entry file
14
+ output: {
15
+ entryFileNames: "client.[hash].js", // name of the final js file
16
+ assetFileNames: "[name].[ext]",
17
+ },
18
+ },
19
+ outDir: "dist", // final bundled output
20
+ emptyOutDir: true,
21
+ },
22
+ plugins: [ tailwindcss(), ],
23
+ publicDir: false,
24
+ resolve: {
25
+ alias: {
26
+ "@jac-client/utils": path.resolve(__dirname, "src/client_runtime.js"),
27
+ },
28
+ },
29
+ });