@akanjs/cli 3.0.0-beta.30 → 3.0.0-beta.32
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.
- package/.build-stamp +1 -1
- package/{CodeAgent-xnfyyz8h.js → CodeAgent-2vmp9qe0.js} +2 -2
- package/{CodeTui-h66xb1fh.js → CodeTui-5ed6bg2a.js} +1 -1
- package/{agent.command-c4v7kjff.js → agent.command-gn73rhe7.js} +5 -5
- package/akanCode.js +2 -2
- package/{application.command-yzsswrz6.js → application.command-e968t0hw.js} +14 -9
- package/{applicationBuildRunner-qkt6spd5.js → applicationBuildRunner-64taxseg.js} +3 -3
- package/buildBatch.proc.js +3 -3
- package/{cloud.command-v8h688jc.js → cloud.command-0jm301rr.js} +9 -9
- package/cloud.script-nemnzjpv.js +20 -0
- package/{code.command-jff3tw7y.js → code.command-18kcm7hq.js} +6 -6
- package/{context.command-y5sevk3c.js → context.command-trd9bn18.js} +13 -13
- package/context.runner-y5hwh673.js +21 -0
- package/{guideline.command-11cndccb.js → guideline.command-bdmdn2de.js} +2 -2
- package/guidelines/conventions/conventions.instruction.md +7 -4
- package/guidelines/runtimeRule/runtimeRule.instruction.md +29 -6
- package/incrementalBuilder.proc.js +2 -2
- package/{index-mk3b9rk1.js → index-0wpybxtr.js} +3 -3
- package/{index-n3jk2501.js → index-3w94e7n3.js} +27 -4
- package/{index-wfwgcnyc.js → index-4npz05nm.js} +4 -4
- package/{index-6x9p8dpb.js → index-6he6gvfg.js} +1 -1
- package/{index-0ncc0mbk.js → index-93j60em0.js} +3 -3
- package/{index-tzc1gtrg.js → index-9z771ptz.js} +2 -2
- package/{index-hqd0h1pb.js → index-abxpehf8.js} +7 -7
- package/{index-a4s954kq.js → index-by9pxkr0.js} +2 -2
- package/{index-5rp0h6na.js → index-drehwpdt.js} +2 -2
- package/{index-rtwhw4aq.js → index-f3c78nd6.js} +7 -7
- package/{index-kb16nzyt.js → index-gbggbqcp.js} +96 -35
- package/{index-tsb0f8ya.js → index-hsmtysz4.js} +2 -2
- package/{index-35mmm9ca.js → index-jmrn54tt.js} +1 -1
- package/{index-376gpdds.js → index-kcdj1z5v.js} +2 -2
- package/{index-hf6f4xnb.js → index-kqabytj7.js} +4 -4
- package/{index-se643zvp.js → index-mbxbhay5.js} +1 -1
- package/{index-gxamdf18.js → index-mgxpx3f2.js} +2 -2
- package/{index-3rh7thcx.js → index-p993efkq.js} +33 -18
- package/{index-qcejqgts.js → index-pmhqttv3.js} +5 -5
- package/{index-8tv7356t.js → index-tqm7jjcn.js} +1 -1
- package/{index-xb7qhxa8.js → index-vpj42xwt.js} +1 -1
- package/{index-bxmejydw.js → index-wprnsjms.js} +3 -3
- package/{index-hmdq5pqm.js → index-y3mphr1m.js} +1 -1
- package/{index-167c77aq.js → index-yg7jhz8x.js} +4 -4
- package/index.js +21 -21
- package/{library.command-n9kp7yms.js → library.command-9h749a1x.js} +3 -3
- package/{localRegistry.command-jx6kxt2x.js → localRegistry.command-2bqqhxyz.js} +8 -8
- package/{module.command-q2xjf6cx.js → module.command-nv8nzgft.js} +5 -5
- package/{package.command-q5a3nsw5.js → package.command-mq4bggp6.js} +3 -3
- package/package.json +2 -2
- package/{page.command-ppenrxjn.js → page.command-j639n707.js} +3 -3
- package/{primitive.command-dvgg8nem.js → primitive.command-kz6849th.js} +6 -6
- package/{quality.command-pz7kg3pc.js → quality.command-4hyabwkb.js} +2 -2
- package/{repair.command-a6py9xvz.js → repair.command-a9awpbqr.js} +5 -5
- package/{scalar.command-7f3xfpen.js → scalar.command-ma4fpm9m.js} +4 -4
- package/{subspace.command-z7nqs508.js → subspace.command-3k2pmrs4.js} +4 -4
- package/templates/app/page/_index.tsx +257 -258
- package/templates/app/page/_layout.tsx +5 -1
- package/templates/app/page/_overrides.tsx +12 -0
- package/templates/app/page/styles.css.template +316 -14
- package/templates/app/public/apple-touch-icon.png +0 -0
- package/templates/app/public/favicon.ico +0 -0
- package/templates/app/public/jelly/cloud.webp +0 -0
- package/templates/app/public/jelly/comet.webp +0 -0
- package/templates/app/public/jelly/moon.webp +0 -0
- package/templates/app/public/jelly/planet.webp +0 -0
- package/templates/app/public/jelly/rocket.webp +0 -0
- package/templates/app/public/jelly/star.webp +0 -0
- package/templates/app/public/jelly/sugar.webp +0 -0
- package/templates/app/public/logo.png +0 -0
- package/templates/app/ui/Recipe/index.ts +9 -0
- package/templates/app/ui/Recipe/jellyButton.ts +63 -0
- package/templates/appSample/lib/task/Task.Unit.tsx +1 -1
- package/templates/appSample/lib/task/Task.Util.tsx +10 -13
- package/templates/appSample/lib/task/Task.View.tsx +2 -2
- package/templates/appSample/lib/task/Task.Zone.tsx +5 -2
- package/templates/appSample/page/task/[taskId]/_index.tsx +6 -6
- package/templates/appSample/page/task/[taskId]/edit.tsx +5 -4
- package/templates/appSample/page/task/_index.tsx +4 -3
- package/templates/appSample/page/task/_layout.tsx +1 -1
- package/templates/appSample/page/task/new.tsx +5 -4
- package/templates/appSample/ui/GlobalLoading.tsx +2 -1
- package/templates/appSample/ui/QuantityControl.tsx +3 -3
- package/{tunnel.command-zy4wbcgt.js → tunnel.command-xwr46b66.js} +2 -2
- package/{workflow.command-f142t17s.js → workflow.command-t7wqe4h7.js} +10 -10
- package/{workspace.command-gpk1149x.js → workspace.command-4derhzrh.js} +24 -21
- package/cloud.script-yct1sk4k.js +0 -20
- package/context.runner-90hsmacr.js +0 -21
|
@@ -1,17 +1,319 @@
|
|
|
1
1
|
@import "tailwindcss";
|
|
2
2
|
@import "akanjs/ui/styles.css";
|
|
3
3
|
|
|
4
|
-
/* The
|
|
5
|
-
data-theme switching)
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
4
|
+
/* The jelly star palette. akanjs/ui/styles.css owns the theme system (token mapping, dark variant, runtime
|
|
5
|
+
data-theme switching), so a rebrand only overrides the token values below. The star red (--jelly) is a fill
|
|
6
|
+
color; --primary carries white text, so it is one step darker to keep 4.5:1 contrast. */
|
|
7
|
+
:root,
|
|
8
|
+
[data-theme="light"] {
|
|
9
|
+
--background: #f1f1ee;
|
|
10
|
+
--foreground: #0d0d0e;
|
|
11
|
+
--primary: #e02d27;
|
|
12
|
+
--primary-foreground: #ffffff;
|
|
13
|
+
--secondary: #0d0d0e;
|
|
14
|
+
--secondary-foreground: #f6f6f3;
|
|
15
|
+
--accent: #7650d8;
|
|
16
|
+
--accent-foreground: #ffffff;
|
|
17
|
+
--neutral: #26262a;
|
|
18
|
+
--neutral-foreground: #f6f6f3;
|
|
19
|
+
--info: #1f6fe0;
|
|
20
|
+
--info-foreground: #ffffff;
|
|
21
|
+
--success: #3f8f1f;
|
|
22
|
+
--success-foreground: #ffffff;
|
|
23
|
+
--warning: #f2b51c;
|
|
24
|
+
--warning-foreground: #0d0d0e;
|
|
25
|
+
--destructive: #c4161c;
|
|
26
|
+
--destructive-foreground: #ffffff;
|
|
27
|
+
--open: #5aa82a;
|
|
28
|
+
--open-foreground: #0d0d0e;
|
|
29
|
+
--muted: #e6e6e1;
|
|
30
|
+
--muted-foreground: #66666b;
|
|
31
|
+
--card: #fbfbf9;
|
|
32
|
+
--card-foreground: #0d0d0e;
|
|
33
|
+
--popover: #ffffff;
|
|
34
|
+
--popover-foreground: #0d0d0e;
|
|
35
|
+
--border: #dcdcd6;
|
|
36
|
+
--input: #d4d4ce;
|
|
37
|
+
--ring: #e02d27;
|
|
38
|
+
--jelly: #ef3a2d;
|
|
39
|
+
--studio-shadow: color-mix(in oklab, #3a2a20 16%, transparent);
|
|
40
|
+
--sky-top: #dfe5f7;
|
|
41
|
+
--sky-bottom: #f6eadf;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
[data-theme="dark"] {
|
|
45
|
+
--background: #0f1129;
|
|
46
|
+
--foreground: #f3f1fb;
|
|
47
|
+
--primary: #e02d27;
|
|
48
|
+
--primary-foreground: #ffffff;
|
|
49
|
+
--secondary: #f3f1fb;
|
|
50
|
+
--secondary-foreground: #0f1129;
|
|
51
|
+
--accent: #a585e0;
|
|
52
|
+
--accent-foreground: #0f1129;
|
|
53
|
+
--neutral: #262a4d;
|
|
54
|
+
--neutral-foreground: #f3f1fb;
|
|
55
|
+
--info: #4b8ef0;
|
|
56
|
+
--info-foreground: #0f1129;
|
|
57
|
+
--success: #7cc23a;
|
|
58
|
+
--success-foreground: #0f1129;
|
|
59
|
+
--warning: #f6c437;
|
|
60
|
+
--warning-foreground: #0f1129;
|
|
61
|
+
--destructive: #e5383b;
|
|
62
|
+
--destructive-foreground: #ffffff;
|
|
63
|
+
--open: #7cc23a;
|
|
64
|
+
--open-foreground: #0f1129;
|
|
65
|
+
--muted: #1a1d3b;
|
|
66
|
+
--muted-foreground: #a6a8c9;
|
|
67
|
+
--card: #161935;
|
|
68
|
+
--card-foreground: #f3f1fb;
|
|
69
|
+
--popover: #1b1e40;
|
|
70
|
+
--popover-foreground: #f3f1fb;
|
|
71
|
+
--border: #2b2f57;
|
|
72
|
+
--input: #33376a;
|
|
73
|
+
--ring: #f0392e;
|
|
74
|
+
--jelly: #f2402f;
|
|
75
|
+
--studio-shadow: color-mix(in oklab, #02030f 65%, transparent);
|
|
76
|
+
--sky-top: #25215f;
|
|
77
|
+
--sky-bottom: #2d1749;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
:root {
|
|
81
|
+
--planet: #1f6fe0;
|
|
82
|
+
--rocket: #82c43c;
|
|
83
|
+
--moon: #f6e27a;
|
|
84
|
+
--cloud: #a585e0;
|
|
85
|
+
--comet: #e3228e;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
@theme inline {
|
|
89
|
+
--color-jelly: var(--jelly);
|
|
90
|
+
--color-planet: var(--planet);
|
|
91
|
+
--color-rocket: var(--rocket);
|
|
92
|
+
--color-moon: var(--moon);
|
|
93
|
+
--color-cloud: var(--cloud);
|
|
94
|
+
--color-comet: var(--comet);
|
|
95
|
+
--radius-box: 1.5rem;
|
|
96
|
+
--radius-field: 0.875rem;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
/* A sampled damped spring: overshoots the target by 18%, wobbles twice and settles. */
|
|
100
|
+
@theme {
|
|
101
|
+
--ease-jelly: linear(0, 0.42 6%, 0.86 13%, 1.12 21%, 1.18 26%, 1.13 32%, 1 41%, 0.95 48%, 0.97 56%, 1.01 66%, 1.005 78%, 1);
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
/* html and body both paint a background color, so body's background is not propagated to the canvas: the sky
|
|
105
|
+
sits on body, and isolation keeps the grain layer above body's own background. */
|
|
106
|
+
@layer base {
|
|
107
|
+
body {
|
|
108
|
+
isolation: isolate;
|
|
109
|
+
background-image:
|
|
110
|
+
radial-gradient(120% 60% at 50% -14%, var(--sky-top), transparent 64%),
|
|
111
|
+
radial-gradient(110% 55% at 50% 114%, var(--sky-bottom), transparent 68%);
|
|
112
|
+
background-attachment: fixed;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
body::before {
|
|
116
|
+
content: "";
|
|
117
|
+
position: fixed;
|
|
118
|
+
inset: 0;
|
|
119
|
+
z-index: -1;
|
|
120
|
+
pointer-events: none;
|
|
121
|
+
opacity: 0.06;
|
|
122
|
+
mix-blend-mode: multiply;
|
|
123
|
+
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='180' height='180'%3E%3Cfilter id='g'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.85' numOctaves='2' stitchTiles='stitch'/%3E%3CfeColorMatrix type='saturate' values='0'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23g)'/%3E%3C/svg%3E");
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
[data-theme="dark"] body::before {
|
|
127
|
+
opacity: 0.1;
|
|
128
|
+
mix-blend-mode: overlay;
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
h1,
|
|
132
|
+
h2 {
|
|
133
|
+
letter-spacing: -0.035em;
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
::selection {
|
|
137
|
+
background-color: color-mix(in oklab, var(--jelly) 24%, transparent);
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
@keyframes jelly-intro {
|
|
142
|
+
from {
|
|
143
|
+
opacity: 0;
|
|
144
|
+
translate: 0 1.25rem;
|
|
145
|
+
filter: blur(6px);
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
@keyframes jelly-breathe {
|
|
150
|
+
0%,
|
|
151
|
+
100% {
|
|
152
|
+
scale: 1 1;
|
|
153
|
+
}
|
|
154
|
+
50% {
|
|
155
|
+
scale: 1.035 0.965;
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
@keyframes jelly-wobble {
|
|
160
|
+
0% {
|
|
161
|
+
scale: 1 1;
|
|
162
|
+
}
|
|
163
|
+
16% {
|
|
164
|
+
scale: 1.16 0.86;
|
|
165
|
+
}
|
|
166
|
+
32% {
|
|
167
|
+
scale: 0.9 1.1;
|
|
168
|
+
}
|
|
169
|
+
48% {
|
|
170
|
+
scale: 1.06 0.95;
|
|
171
|
+
}
|
|
172
|
+
64% {
|
|
173
|
+
scale: 0.97 1.03;
|
|
174
|
+
}
|
|
175
|
+
82% {
|
|
176
|
+
scale: 1.01 0.99;
|
|
177
|
+
}
|
|
178
|
+
100% {
|
|
179
|
+
scale: 1 1;
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
@keyframes jelly-float {
|
|
184
|
+
0%,
|
|
185
|
+
100% {
|
|
186
|
+
translate: 0 0;
|
|
187
|
+
rotate: calc(var(--float-tilt, 4deg) * -1);
|
|
188
|
+
}
|
|
189
|
+
50% {
|
|
190
|
+
translate: 0 calc(var(--float-rise, 0.9rem) * -1);
|
|
191
|
+
rotate: var(--float-tilt, 4deg);
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
@utility intro-rise {
|
|
196
|
+
@media (prefers-reduced-motion: no-preference) {
|
|
197
|
+
animation: jelly-intro 1.1s cubic-bezier(0.16, 1, 0.3, 1) both;
|
|
198
|
+
animation-delay: var(--intro-delay, 0ms);
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
@utility jelly-breathe {
|
|
203
|
+
transform-origin: 50% 100%;
|
|
204
|
+
@media (prefers-reduced-motion: no-preference) {
|
|
205
|
+
animation: jelly-breathe 3.2s ease-in-out infinite;
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
@utility jelly-wobble {
|
|
210
|
+
transform-origin: 50% 100%;
|
|
211
|
+
@media (prefers-reduced-motion: no-preference) {
|
|
212
|
+
animation: jelly-wobble 0.9s ease-out both;
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
@utility jelly-float {
|
|
217
|
+
@media (prefers-reduced-motion: no-preference) {
|
|
218
|
+
animation: jelly-float var(--float-duration, 6s) ease-in-out var(--float-delay, 0s) infinite;
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
@utility squish {
|
|
223
|
+
transition:
|
|
224
|
+
scale 700ms var(--ease-jelly),
|
|
225
|
+
translate 700ms var(--ease-jelly);
|
|
226
|
+
&:hover {
|
|
227
|
+
scale: 1.04 0.97;
|
|
228
|
+
}
|
|
229
|
+
&:active {
|
|
230
|
+
scale: 1.08 0.9;
|
|
231
|
+
transition-duration: 90ms;
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
@utility tint-* {
|
|
236
|
+
--tint: --value(--color-*);
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
/* A gummy surface. public/jelly/sugar.webp is a high-pass of the logo star's sugar coating (128 gray = no change),
|
|
240
|
+
laid on in hard-light so every tint gets the same sugar grain. */
|
|
241
|
+
@utility jelly {
|
|
242
|
+
--jelly-tint: var(--tint, var(--primary));
|
|
243
|
+
--jelly-deep: color-mix(in oklab, var(--jelly-tint) 70%, black);
|
|
244
|
+
--jelly-haze: color-mix(in oklab, var(--jelly-tint) 55%, white);
|
|
245
|
+
background-color: var(--jelly-tint);
|
|
246
|
+
background-image:
|
|
247
|
+
url("/jelly/sugar.webp"),
|
|
248
|
+
radial-gradient(120% 95% at 26% -8%, color-mix(in oklab, white 26%, transparent), transparent 58%),
|
|
249
|
+
radial-gradient(110% 90% at 60% 125%, color-mix(in oklab, var(--jelly-deep) 30%, transparent), transparent 60%);
|
|
250
|
+
background-size:
|
|
251
|
+
100px 100px,
|
|
252
|
+
100% 100%,
|
|
253
|
+
100% 100%;
|
|
254
|
+
background-repeat: repeat, no-repeat, no-repeat;
|
|
255
|
+
background-blend-mode: hard-light, normal, normal;
|
|
256
|
+
box-shadow:
|
|
257
|
+
inset 0 0 0 1px color-mix(in oklab, var(--jelly-haze) 40%, transparent),
|
|
258
|
+
inset 0 0 8px 1px color-mix(in oklab, white 20%, transparent),
|
|
259
|
+
inset 0 -3px 6px color-mix(in oklab, var(--jelly-deep) 28%, transparent),
|
|
260
|
+
0 6px 10px -6px color-mix(in oklab, var(--jelly-deep) 65%, transparent),
|
|
261
|
+
0 1px 2px color-mix(in oklab, black 12%, transparent);
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
@utility jelly-glass {
|
|
265
|
+
--jelly-tint: var(--tint, var(--card));
|
|
266
|
+
background-color: color-mix(in oklab, var(--card) 95%, var(--jelly-tint));
|
|
267
|
+
background-image:
|
|
268
|
+
radial-gradient(120% 70% at 20% -20%, color-mix(in oklab, white 55%, transparent), transparent 60%),
|
|
269
|
+
radial-gradient(90% 60% at 100% 120%, color-mix(in oklab, var(--jelly-tint) 9%, transparent), transparent 70%);
|
|
270
|
+
box-shadow:
|
|
271
|
+
inset 0 1px 0 color-mix(in oklab, white 70%, transparent),
|
|
272
|
+
inset 0 -1px 0 color-mix(in oklab, var(--jelly-tint) 14%, transparent),
|
|
273
|
+
0 22px 44px -28px var(--studio-shadow),
|
|
274
|
+
0 2px 6px -3px var(--studio-shadow);
|
|
275
|
+
@variant dark {
|
|
276
|
+
background-color: color-mix(in oklab, var(--card) 92%, var(--jelly-tint));
|
|
277
|
+
background-image:
|
|
278
|
+
radial-gradient(120% 70% at 20% -20%, color-mix(in oklab, white 7%, transparent), transparent 60%),
|
|
279
|
+
radial-gradient(90% 60% at 100% 120%, color-mix(in oklab, var(--jelly-tint) 14%, transparent), transparent 70%);
|
|
280
|
+
box-shadow:
|
|
281
|
+
inset 0 1px 0 color-mix(in oklab, white 11%, transparent),
|
|
282
|
+
inset 0 -1px 0 color-mix(in oklab, var(--jelly-tint) 18%, transparent),
|
|
283
|
+
0 22px 44px -28px var(--studio-shadow),
|
|
284
|
+
0 2px 6px -3px var(--studio-shadow);
|
|
285
|
+
}
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
/* The same sugar, clipped to the glyphs of plain text-primary text. Clipping replaces the element's background, so
|
|
289
|
+
elements with a surface of their own (bg-*, jelly, glass) and currentColor drawings are skipped, and icons inside
|
|
290
|
+
get their color back. */
|
|
291
|
+
.text-primary:not(svg, [class*="bg-"], [class*="jelly"], [class*="glass"], [class*="-current"]) {
|
|
292
|
+
background-color: var(--primary);
|
|
293
|
+
background-image:
|
|
294
|
+
url("/jelly/sugar.webp"),
|
|
295
|
+
linear-gradient(
|
|
296
|
+
to bottom,
|
|
297
|
+
color-mix(in oklab, black 8%, var(--primary)),
|
|
298
|
+
color-mix(in oklab, white 14%, var(--primary)) 22%,
|
|
299
|
+
var(--primary) 60%,
|
|
300
|
+
color-mix(in oklab, black 8%, var(--primary))
|
|
301
|
+
);
|
|
302
|
+
background-size:
|
|
303
|
+
100px 100px,
|
|
304
|
+
100% 1lh;
|
|
305
|
+
background-origin: content-box;
|
|
306
|
+
background-blend-mode: hard-light, normal;
|
|
307
|
+
-webkit-background-clip: text;
|
|
308
|
+
background-clip: text;
|
|
309
|
+
color: transparent;
|
|
310
|
+
text-decoration-color: var(--primary);
|
|
311
|
+
& :is(svg, [class*="-current"]) {
|
|
312
|
+
color: var(--primary);
|
|
313
|
+
}
|
|
314
|
+
/* A heading's tight leading pushes descenders out of the box, where a text-clipped background is never painted. */
|
|
315
|
+
:is(h1, h2, h3, h4, h5, h6) & {
|
|
316
|
+
padding-block: 0.15em;
|
|
317
|
+
margin-block: -0.15em;
|
|
318
|
+
}
|
|
319
|
+
}
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { AppInfo, LibInfo } from "akanjs";
|
|
2
|
+
|
|
3
|
+
export default function getContent(scanInfo: AppInfo | LibInfo | null, dict: { appName: string }) {
|
|
4
|
+
return {
|
|
5
|
+
filename: "index.ts",
|
|
6
|
+
content: `export { type JellyButtonVariants, jellyButtonRecipe } from "./jellyButton";
|
|
7
|
+
`,
|
|
8
|
+
};
|
|
9
|
+
}
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import type { AppInfo, LibInfo } from "akanjs";
|
|
2
|
+
|
|
3
|
+
export default function getContent(scanInfo: AppInfo | LibInfo | null, dict: { appName: string }) {
|
|
4
|
+
return {
|
|
5
|
+
filename: "jellyButton.ts",
|
|
6
|
+
content: `import { recipe, tv } from "akanjs/ui";
|
|
7
|
+
|
|
8
|
+
/** Sugared gummy button with the same variants as akanjs's \`buttonRecipe\`; \`page/_overrides.tsx\` binds it to every akanjs/ui Button. ghost/outline/link stay surfaceless. */
|
|
9
|
+
export const jellyButtonRecipe = recipe(
|
|
10
|
+
tv({
|
|
11
|
+
base: "squish inline-flex cursor-pointer items-center justify-center gap-2 whitespace-nowrap rounded-full font-bold focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring disabled:pointer-events-none disabled:opacity-50",
|
|
12
|
+
variants: {
|
|
13
|
+
variant: {
|
|
14
|
+
default: "text-foreground",
|
|
15
|
+
primary: "tint-primary text-primary-foreground",
|
|
16
|
+
secondary: "tint-secondary text-secondary-foreground",
|
|
17
|
+
accent: "tint-accent text-accent-foreground",
|
|
18
|
+
neutral: "tint-neutral text-neutral-foreground",
|
|
19
|
+
outline: "border border-foreground/12 bg-background/70 text-foreground hover:bg-foreground/5",
|
|
20
|
+
ghost: "text-foreground/75 hover:bg-foreground/6 hover:text-foreground",
|
|
21
|
+
destructive: "tint-destructive text-destructive-foreground",
|
|
22
|
+
success: "tint-success text-success-foreground",
|
|
23
|
+
warning: "tint-warning text-warning-foreground",
|
|
24
|
+
info: "tint-info text-info-foreground",
|
|
25
|
+
link: "text-primary underline-offset-4 hover:underline",
|
|
26
|
+
},
|
|
27
|
+
size: {
|
|
28
|
+
xs: "h-6 px-2.5 text-xs",
|
|
29
|
+
sm: "h-8 px-3.5 text-sm",
|
|
30
|
+
md: "h-10 px-5 text-sm",
|
|
31
|
+
lg: "h-12 px-7 text-base",
|
|
32
|
+
icon: "h-10 w-10 px-0",
|
|
33
|
+
},
|
|
34
|
+
shape: {
|
|
35
|
+
default: "",
|
|
36
|
+
square: "aspect-square px-0",
|
|
37
|
+
circle: "aspect-square px-0",
|
|
38
|
+
},
|
|
39
|
+
outline: { true: "border bg-transparent", false: "" },
|
|
40
|
+
},
|
|
41
|
+
compoundVariants: [
|
|
42
|
+
{ variant: "default", outline: false, class: "jelly-glass" },
|
|
43
|
+
{
|
|
44
|
+
variant: ["primary", "secondary", "accent", "neutral", "destructive", "success", "warning", "info"],
|
|
45
|
+
outline: false,
|
|
46
|
+
class: "jelly",
|
|
47
|
+
},
|
|
48
|
+
{ variant: "primary", outline: true, class: "border-primary text-primary hover:bg-primary/8" },
|
|
49
|
+
{ variant: "secondary", outline: true, class: "border-secondary text-secondary hover:bg-secondary/8" },
|
|
50
|
+
{ variant: "accent", outline: true, class: "border-accent text-accent hover:bg-accent/8" },
|
|
51
|
+
{ variant: "neutral", outline: true, class: "border-neutral text-neutral hover:bg-neutral/8" },
|
|
52
|
+
{ variant: "destructive", outline: true, class: "border-destructive text-destructive hover:bg-destructive/8" },
|
|
53
|
+
{ variant: "success", outline: true, class: "border-success text-success hover:bg-success/8" },
|
|
54
|
+
{ variant: "warning", outline: true, class: "border-warning text-warning hover:bg-warning/8" },
|
|
55
|
+
{ variant: "info", outline: true, class: "border-info text-info hover:bg-info/8" },
|
|
56
|
+
],
|
|
57
|
+
defaultVariants: { variant: "primary", size: "md", shape: "default" },
|
|
58
|
+
}),
|
|
59
|
+
);
|
|
60
|
+
export type JellyButtonVariants = NonNullable<Parameters<typeof jellyButtonRecipe>[0]>;
|
|
61
|
+
`,
|
|
62
|
+
};
|
|
63
|
+
}
|
|
@@ -30,7 +30,7 @@ export const Card = ({ task, className, href }: CardProps) => {
|
|
|
30
30
|
return (
|
|
31
31
|
<Layout.Unit
|
|
32
32
|
className={cn(
|
|
33
|
-
"
|
|
33
|
+
"jelly-glass block rounded-box p-5 transition-transform duration-300 ease-jelly hover:-translate-y-0.5",
|
|
34
34
|
className,
|
|
35
35
|
)}
|
|
36
36
|
href={href}
|
|
@@ -5,7 +5,8 @@ export default function getContent(scanInfo: AppInfo | LibInfo | null, dict: { a
|
|
|
5
5
|
filename: "Task.Util.tsx",
|
|
6
6
|
content: `"use client";
|
|
7
7
|
import { fetch, st, usePage } from "@apps/${dict.appName}/client";
|
|
8
|
-
import {
|
|
8
|
+
import { jellyButtonRecipe } from "@apps/${dict.appName}/ui";
|
|
9
|
+
import { Dropdown, Model } from "akanjs/ui";
|
|
9
10
|
|
|
10
11
|
// ===== Task.Util.tsx =====
|
|
11
12
|
// Convention: lib/<module>/ — PascalCase .tsx, Util suffix = action buttons/utility components.
|
|
@@ -19,10 +20,7 @@ interface StartProps {
|
|
|
19
20
|
}
|
|
20
21
|
|
|
21
22
|
export const Start = ({ taskId }: StartProps) => (
|
|
22
|
-
<button
|
|
23
|
-
className={buttonRecipe({ size: "xs" }, "border-primary/20 bg-primary/10 text-primary hover:bg-primary hover:text-primary-foreground")}
|
|
24
|
-
onClick={() => st.do.startTask(taskId)}
|
|
25
|
-
>
|
|
23
|
+
<button className={jellyButtonRecipe({ variant: "primary", size: "xs" })} onClick={() => st.do.startTask(taskId)}>
|
|
26
24
|
{usePage().l("task.taskStart")}
|
|
27
25
|
</button>
|
|
28
26
|
);
|
|
@@ -32,10 +30,7 @@ interface CompleteProps {
|
|
|
32
30
|
}
|
|
33
31
|
|
|
34
32
|
export const Complete = ({ taskId }: CompleteProps) => (
|
|
35
|
-
<button
|
|
36
|
-
className={buttonRecipe({ size: "xs" }, "border-success/20 bg-success/10 text-success hover:bg-success hover:text-success-foreground")}
|
|
37
|
-
onClick={() => st.do.completeTask(taskId)}
|
|
38
|
-
>
|
|
33
|
+
<button className={jellyButtonRecipe({ variant: "success", size: "xs" })} onClick={() => st.do.completeTask(taskId)}>
|
|
39
34
|
{usePage().l("task.taskComplete")}
|
|
40
35
|
</button>
|
|
41
36
|
);
|
|
@@ -46,7 +41,9 @@ interface RemoveProps {
|
|
|
46
41
|
|
|
47
42
|
export const Remove = ({ taskId }: RemoveProps) => (
|
|
48
43
|
<Model.Remove modelId={taskId} slice={fetch.slice.task}>
|
|
49
|
-
<button className={
|
|
44
|
+
<button className={jellyButtonRecipe({ variant: "ghost", size: "xs" }, "text-destructive")}>
|
|
45
|
+
{usePage().l("task.taskRemove")}
|
|
46
|
+
</button>
|
|
50
47
|
</Model.Remove>
|
|
51
48
|
);
|
|
52
49
|
|
|
@@ -59,9 +56,9 @@ export const Toolbox = ({ taskId, status }: ToolboxProps) => {
|
|
|
59
56
|
const { l } = usePage();
|
|
60
57
|
return (
|
|
61
58
|
<Dropdown
|
|
62
|
-
buttonClassName={
|
|
59
|
+
buttonClassName={jellyButtonRecipe({ variant: "ghost", size: "xs" })}
|
|
63
60
|
value={<span>···</span>}
|
|
64
|
-
dropdownClassName="w-40 rounded-box
|
|
61
|
+
dropdownClassName="jelly-glass w-40 rounded-box p-2"
|
|
65
62
|
content={
|
|
66
63
|
<>
|
|
67
64
|
{status === "todo" && (
|
|
@@ -96,7 +93,7 @@ export const Toolbox = ({ taskId, status }: ToolboxProps) => {
|
|
|
96
93
|
// New Task Button: Model.NewWrapper — triggers new Task creation form
|
|
97
94
|
// export const NewTask = () => (
|
|
98
95
|
// <Model.NewWrapper partial={{}}>
|
|
99
|
-
// <button className={
|
|
96
|
+
// <button className={jellyButtonRecipe({ variant: "primary", size: "sm" })}>+ New Task</button>
|
|
100
97
|
// </Model.NewWrapper>
|
|
101
98
|
// );
|
|
102
99
|
`,
|
|
@@ -29,12 +29,12 @@ export const General = ({ className, task }: GeneralProps) => {
|
|
|
29
29
|
return (
|
|
30
30
|
<div className={cn("flex w-full flex-col gap-4", className)}>
|
|
31
31
|
<div>
|
|
32
|
-
<h1 className="font-
|
|
32
|
+
<h1 className="font-black text-4xl text-foreground">{task.title}</h1>
|
|
33
33
|
<div className={cn("mt-1 font-medium text-sm", statusColor)}>{l(\`taskStatus.\${task.status}\`)}</div>
|
|
34
34
|
</div>
|
|
35
35
|
|
|
36
36
|
{task.content && (
|
|
37
|
-
<div className="
|
|
37
|
+
<div className="jelly-glass rounded-box p-5">
|
|
38
38
|
<p className="whitespace-pre-wrap text-foreground/80 text-sm">{task.content}</p>
|
|
39
39
|
</div>
|
|
40
40
|
)}
|
|
@@ -5,8 +5,9 @@ export default function getContent(scanInfo: AppInfo | LibInfo | null, dict: { a
|
|
|
5
5
|
filename: "Task.Zone.tsx",
|
|
6
6
|
content: `"use client";
|
|
7
7
|
import { type cnst, Task, usePage } from "@apps/${dict.appName}/client";
|
|
8
|
+
import { jellyButtonRecipe } from "@apps/${dict.appName}/ui";
|
|
8
9
|
import type { ClientInit, ClientView } from "akanjs/fetch";
|
|
9
|
-
import { Link, Load
|
|
10
|
+
import { Link, Load } from "akanjs/ui";
|
|
10
11
|
|
|
11
12
|
// ===== Task.Zone.tsx =====
|
|
12
13
|
// Convention: lib/<module>/ — PascalCase .tsx, Zone suffix = composition layer between pages and UI.
|
|
@@ -30,7 +31,9 @@ export const Card = ({ className, init }: CardProps) => {
|
|
|
30
31
|
<div className="flex flex-col items-center gap-4 py-16 text-center">
|
|
31
32
|
<div className="text-foreground/40 text-lg">{l("task.taskNoTasks")}</div>
|
|
32
33
|
<Link href="/task/new">
|
|
33
|
-
<button className={
|
|
34
|
+
<button className={jellyButtonRecipe({ variant: "primary", size: "sm" })}>
|
|
35
|
+
{l("task.taskCreateFirst")}
|
|
36
|
+
</button>
|
|
34
37
|
</Link>
|
|
35
38
|
</div>
|
|
36
39
|
)}
|
|
@@ -3,11 +3,11 @@ import type { AppInfo, LibInfo } from "akanjs";
|
|
|
3
3
|
export default function getContent(scanInfo: AppInfo | LibInfo | null, dict: { appName: string }) {
|
|
4
4
|
return {
|
|
5
5
|
filename: "_index.tsx",
|
|
6
|
-
content: `import { fetch, usePage } from "@apps/${dict.appName}/client";
|
|
7
|
-
import {
|
|
6
|
+
content: `import { fetch, Task, usePage } from "@apps/${dict.appName}/client";
|
|
7
|
+
import { jellyButtonRecipe } from "@apps/${dict.appName}/ui";
|
|
8
8
|
import { ID } from "akanjs/base";
|
|
9
9
|
import { page } from "akanjs/client";
|
|
10
|
-
import { Link
|
|
10
|
+
import { Link } from "akanjs/ui";
|
|
11
11
|
|
|
12
12
|
export default page()
|
|
13
13
|
.param("taskId", ID)
|
|
@@ -17,10 +17,10 @@ export default page()
|
|
|
17
17
|
return (
|
|
18
18
|
<main className="mx-auto max-w-4xl px-6 py-8">
|
|
19
19
|
<div className="mb-6 flex items-center justify-between">
|
|
20
|
-
<
|
|
20
|
+
<Link href="/task" className={jellyButtonRecipe({ variant: "ghost", size: "sm" })}>
|
|
21
21
|
{l("task.taskBackToTasks")}
|
|
22
|
-
</
|
|
23
|
-
<Link href={\`/task/\${taskId}/edit\`} className={
|
|
22
|
+
</Link>
|
|
23
|
+
<Link href={\`/task/\${taskId}/edit\`} className={jellyButtonRecipe({ variant: "primary", size: "sm" })}>
|
|
24
24
|
{l("task.taskEdit")}
|
|
25
25
|
</Link>
|
|
26
26
|
</div>
|
|
@@ -4,9 +4,10 @@ export default function getContent(scanInfo: AppInfo | LibInfo | null, dict: { a
|
|
|
4
4
|
return {
|
|
5
5
|
filename: "edit.tsx",
|
|
6
6
|
content: `import { fetch, Task } from "@apps/${dict.appName}/client";
|
|
7
|
+
import { jellyButtonRecipe } from "@apps/${dict.appName}/ui";
|
|
7
8
|
import { ID } from "akanjs/base";
|
|
8
9
|
import { page } from "akanjs/client";
|
|
9
|
-
import {
|
|
10
|
+
import { Link, Load } from "akanjs/ui";
|
|
10
11
|
|
|
11
12
|
export default page()
|
|
12
13
|
.param("taskId", ID)
|
|
@@ -16,15 +17,15 @@ export default page()
|
|
|
16
17
|
return (
|
|
17
18
|
<main className="mx-auto max-w-2xl px-6 py-8">
|
|
18
19
|
<div className="mb-6">
|
|
19
|
-
<Link href={\`/task/\${taskId}\`} className={
|
|
20
|
+
<Link href={\`/task/\${taskId}\`} className={jellyButtonRecipe({ variant: "ghost", size: "sm" })}>
|
|
20
21
|
← Back to Task
|
|
21
22
|
</Link>
|
|
22
23
|
</div>
|
|
23
24
|
<div className="mb-6">
|
|
24
|
-
<h1 className="font-
|
|
25
|
+
<h1 className="font-black text-4xl text-foreground">Edit Task</h1>
|
|
25
26
|
<p className="mt-1 text-foreground/60 text-sm">Update the task details</p>
|
|
26
27
|
</div>
|
|
27
|
-
<div className="
|
|
28
|
+
<div className="jelly-glass rounded-box p-6">
|
|
28
29
|
<Load.Edit slice={fetch.slice.taskInPublic} edit={taskEdit} type="form" onSubmit={\`/task/\${taskId}\`}>
|
|
29
30
|
<Task.Template.General />
|
|
30
31
|
</Load.Edit>
|
|
@@ -4,8 +4,9 @@ export default function getContent(scanInfo: AppInfo | LibInfo | null, dict: { a
|
|
|
4
4
|
return {
|
|
5
5
|
filename: "_index.tsx",
|
|
6
6
|
content: `import { fetch, Task, usePage } from "@apps/${dict.appName}/client";
|
|
7
|
+
import { jellyButtonRecipe } from "@apps/${dict.appName}/ui";
|
|
7
8
|
import { page } from "akanjs/client";
|
|
8
|
-
import { Link
|
|
9
|
+
import { Link } from "akanjs/ui";
|
|
9
10
|
|
|
10
11
|
export default page().render(async () => {
|
|
11
12
|
const { l } = usePage();
|
|
@@ -14,10 +15,10 @@ export default page().render(async () => {
|
|
|
14
15
|
<main className="mx-auto max-w-4xl px-6 py-8">
|
|
15
16
|
<div className="mb-6 flex items-center justify-between">
|
|
16
17
|
<div>
|
|
17
|
-
<h1 className="font-
|
|
18
|
+
<h1 className="font-black text-4xl text-foreground">{l("task.modelName")}</h1>
|
|
18
19
|
<p className="mt-1 text-foreground/60 text-sm">{l("task.modelDesc")}</p>
|
|
19
20
|
</div>
|
|
20
|
-
<Link href="/task/new" className={
|
|
21
|
+
<Link href="/task/new" className={jellyButtonRecipe({ variant: "primary", size: "sm" })}>
|
|
21
22
|
{l("task.taskNew")}
|
|
22
23
|
</Link>
|
|
23
24
|
</div>
|
|
@@ -6,7 +6,7 @@ export default function getContent(scanInfo: AppInfo | LibInfo | null, dict: { a
|
|
|
6
6
|
content: `import { layout } from "akanjs/client";
|
|
7
7
|
|
|
8
8
|
export default layout().render(({ children }) => {
|
|
9
|
-
return <div className="min-h-screen
|
|
9
|
+
return <div className="min-h-screen">{children}</div>;
|
|
10
10
|
});
|
|
11
11
|
`,
|
|
12
12
|
};
|