@codraoss/ui 0.9.4 → 0.9.5
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/dist/{chunk-HCQJTSV3.js → chunk-GNGWMNUA.js} +1 -1
- package/dist/chunk-GNGWMNUA.js.map +1 -0
- package/dist/components/motion/index.d.ts +6 -9
- package/dist/components/motion/index.js +2 -3
- package/dist/components/motion/index.js.map +1 -1
- package/dist/index.d.ts +12 -2
- package/dist/index.js +51 -27
- package/dist/index.js.map +1 -1
- package/dist/lib/file-tree.js.map +1 -1
- package/dist/lib/prompt-diff.d.ts +0 -7
- package/dist/lib/prompt-diff.js.map +1 -1
- package/dist/lib/utils.js +1 -1
- package/dist/styles/tokens.css +345 -0
- package/package.json +10 -6
- package/dist/chunk-HCQJTSV3.js.map +0 -1
|
@@ -0,0 +1,345 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* @codraoss/ui design tokens: the tokens and classes this package's components reference, without which they render unstyled. A Tailwind v4 partial, not an entry, so import it from the app's stylesheet AFTER `@import "tailwindcss"` for the @theme/@utility directives to be processed.
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
/* dark: utilities follow .dark class, not OS prefers-color-scheme. */
|
|
7
|
+
@custom-variant dark (&:where(.dark, .dark *));
|
|
8
|
+
|
|
9
|
+
:root {
|
|
10
|
+
--ui-base: #ffffff;
|
|
11
|
+
--ui-canvas: oklch(98.75% 0 0);
|
|
12
|
+
--ui-line: oklch(14.5% 0 0 / 0.1);
|
|
13
|
+
--ui-fill: oklch(92.2% 0 0);
|
|
14
|
+
--ui-subtle: oklch(55.6% 0 0);
|
|
15
|
+
--ui-default: oklch(21% 0 0);
|
|
16
|
+
--ui-strong: oklch(14.5% 0 0);
|
|
17
|
+
}
|
|
18
|
+
.dark {
|
|
19
|
+
--ui-base: oklch(17% 0 0);
|
|
20
|
+
--ui-canvas: oklch(10% 0 0);
|
|
21
|
+
--ui-line: oklch(32% 0 0);
|
|
22
|
+
--ui-fill: oklch(26.9% 0 0);
|
|
23
|
+
--ui-subtle: oklch(70.8% 0 0);
|
|
24
|
+
--ui-default: oklch(97% 0 0);
|
|
25
|
+
--ui-strong: oklch(98.5% 0 0);
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
:root {
|
|
29
|
+
--ease-out-expo: cubic-bezier(0.16, 1, 0.3, 1);
|
|
30
|
+
--ease-out-quart: cubic-bezier(0.25, 1, 0.5, 1);
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
:root {
|
|
34
|
+
--background: oklch(100% 0 0);
|
|
35
|
+
--foreground: oklch(12% 0.02 115);
|
|
36
|
+
--card: oklch(100% 0 0);
|
|
37
|
+
--card-foreground: oklch(12% 0.02 115);
|
|
38
|
+
--popover: oklch(100% 0 0);
|
|
39
|
+
--popover-foreground: oklch(12% 0.02 115);
|
|
40
|
+
|
|
41
|
+
/* Lime darkened for AA contrast on white; .dark restores full brightness. */
|
|
42
|
+
--primary: oklch(64% 0.24 115);
|
|
43
|
+
--primary-foreground: oklch(100% 0 0);
|
|
44
|
+
--btn-primary-bg: oklch(64% 0.24 115);
|
|
45
|
+
--btn-primary-fg: oklch(20% 0.02 118);
|
|
46
|
+
--btn-primary-border: oklch(72% 0.17 118);
|
|
47
|
+
--btn-primary-surface: oklch(95% 0.09 118);
|
|
48
|
+
--btn-primary-hover: oklch(90% 0.13 118);
|
|
49
|
+
|
|
50
|
+
--secondary: oklch(96.3% 0.003 286.3);
|
|
51
|
+
--secondary-foreground:oklch(27.4% 0.006 286.3);
|
|
52
|
+
--muted: oklch(96.3% 0.003 286.3);
|
|
53
|
+
--muted-foreground: oklch(55.1% 0.011 286.3);
|
|
54
|
+
|
|
55
|
+
--accent: oklch(90.9% 0.004 286.3);
|
|
56
|
+
--accent-foreground: oklch(20.5% 0.005 286.3);
|
|
57
|
+
|
|
58
|
+
--destructive: oklch(55% 0.22 25);
|
|
59
|
+
--destructive-foreground: oklch(100% 0 0);
|
|
60
|
+
|
|
61
|
+
--border: oklch(90.9% 0.004 286.3);
|
|
62
|
+
--input: oklch(90.9% 0.004 286.3);
|
|
63
|
+
--ring: oklch(72% 0.22 115);
|
|
64
|
+
|
|
65
|
+
--radius: 0.75rem;
|
|
66
|
+
|
|
67
|
+
--success: oklch(64% 0.24 115);
|
|
68
|
+
--success-bg: oklch(98% 0.04 115);
|
|
69
|
+
--success-border: oklch(85% 0.15 115);
|
|
70
|
+
--warning: oklch(56% 0.18 65);
|
|
71
|
+
--warning-bg: oklch(98% 0.04 65);
|
|
72
|
+
--warning-border: oklch(90% 0.12 65);
|
|
73
|
+
--danger: oklch(62% 0.22 25);
|
|
74
|
+
--danger-bg: oklch(98% 0.04 25);
|
|
75
|
+
--danger-border: oklch(88% 0.14 25);
|
|
76
|
+
--info: oklch(68% 0.18 250);
|
|
77
|
+
--info-bg: oklch(98% 0.04 250);
|
|
78
|
+
--info-border: oklch(88% 0.12 250);
|
|
79
|
+
|
|
80
|
+
--shadow-sm: 0 1px 2px oklch(0% 0 0 / 0.02);
|
|
81
|
+
--shadow-md: 0 1px 4px oklch(0% 0 0 / 0.03), 0 1px 2px oklch(0% 0 0 / 0.02);
|
|
82
|
+
--shadow-lg: 0 4px 16px -4px oklch(0% 0 0 / 0.04), 0 1px 6px -2px oklch(0% 0 0 / 0.03);
|
|
83
|
+
|
|
84
|
+
--code-bg: oklch(96.3% 0.003 286.3);
|
|
85
|
+
--code-fg: oklch(27.4% 0.006 286.3);
|
|
86
|
+
--code-border: oklch(90.9% 0.004 286.3);
|
|
87
|
+
|
|
88
|
+
/* True green/red, not brand lime, so diff rows/counts stay distinguishable. */
|
|
89
|
+
--diff-add-bg: oklch(95% 0.06 150);
|
|
90
|
+
--diff-add-fg: oklch(48% 0.13 150);
|
|
91
|
+
--diff-del-bg: oklch(95% 0.05 27);
|
|
92
|
+
--diff-del-fg: oklch(52% 0.16 27);
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
.dark {
|
|
96
|
+
--background: #000000;
|
|
97
|
+
--foreground: oklch(98% 0.005 115);
|
|
98
|
+
--card: #09090b;
|
|
99
|
+
--card-foreground: oklch(98% 0.005 115);
|
|
100
|
+
--popover: #09090b;
|
|
101
|
+
--popover-foreground: oklch(98% 0.005 115);
|
|
102
|
+
|
|
103
|
+
--primary: oklch(94% 0.23 115);
|
|
104
|
+
--primary-foreground: oklch(12% 0.04 115);
|
|
105
|
+
|
|
106
|
+
--btn-primary-bg: #CCE800;
|
|
107
|
+
--btn-primary-fg: #CCE800;
|
|
108
|
+
--btn-primary-border: color-mix(in oklab, #CCE800 50%, transparent);
|
|
109
|
+
--btn-primary-surface: color-mix(in oklab, #CCE800 8%, transparent);
|
|
110
|
+
--btn-primary-hover: color-mix(in oklab, #CCE800 16%, transparent);
|
|
111
|
+
|
|
112
|
+
--secondary: oklch(18% 0.018 115);
|
|
113
|
+
--secondary-foreground:oklch(82% 0.012 115);
|
|
114
|
+
--muted: oklch(18% 0.018 115);
|
|
115
|
+
--muted-foreground: oklch(55% 0.015 115);
|
|
116
|
+
|
|
117
|
+
--accent: oklch(18% 0.018 115);
|
|
118
|
+
--accent-foreground: oklch(91% 0.010 115);
|
|
119
|
+
|
|
120
|
+
--destructive: oklch(60% 0.220 25);
|
|
121
|
+
--destructive-foreground: oklch(10% 0.015 115);
|
|
122
|
+
|
|
123
|
+
--border: oklch(22% 0.02 115);
|
|
124
|
+
--input: oklch(22% 0.02 115);
|
|
125
|
+
--ring: oklch(94% 0.23 115);
|
|
126
|
+
|
|
127
|
+
--success: oklch(94% 0.23 115);
|
|
128
|
+
--success-bg: oklch(18% 0.06 115);
|
|
129
|
+
--success-border: oklch(28% 0.10 115);
|
|
130
|
+
--warning: oklch(78% 0.165 65);
|
|
131
|
+
--warning-bg: oklch(18% 0.080 65);
|
|
132
|
+
--warning-border: oklch(35% 0.14 65);
|
|
133
|
+
--danger: oklch(70% 0.200 25);
|
|
134
|
+
--danger-bg: oklch(18% 0.080 25);
|
|
135
|
+
--danger-border: oklch(35% 0.14 25);
|
|
136
|
+
--info: oklch(72% 0.160 250);
|
|
137
|
+
--info-bg: oklch(18% 0.075 250);
|
|
138
|
+
--info-border: oklch(35% 0.12 250);
|
|
139
|
+
|
|
140
|
+
--shadow-sm: 0 1px 2px oklch(100% 0 0 / 0.05), 0 1px 2px oklch(0% 0 0 / 0.3);
|
|
141
|
+
--shadow-md: 0 4px 12px oklch(0% 0 0 / 0.45), 0 1px 4px oklch(0% 0 0 / 0.25);
|
|
142
|
+
--shadow-lg: 0 12px 24px -4px oklch(0% 0 0 / 0.5), 0 4px 12px -2px oklch(0% 0 0 / 0.3);
|
|
143
|
+
|
|
144
|
+
--code-bg: oklch(20.5% 0.005 286.3);
|
|
145
|
+
--code-fg: oklch(86.5% 0.005 286.3);
|
|
146
|
+
--code-border: oklch(27.4% 0.006 286.3);
|
|
147
|
+
|
|
148
|
+
--diff-add-bg: oklch(24% 0.055 150);
|
|
149
|
+
--diff-add-fg: oklch(82% 0.15 150);
|
|
150
|
+
--diff-del-bg: oklch(25% 0.075 27);
|
|
151
|
+
--diff-del-fg: oklch(80% 0.16 27);
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
@theme inline {
|
|
155
|
+
--font-sans: 'IBM Plex Sans', 'Segoe UI', system-ui, sans-serif;
|
|
156
|
+
--font-mono: 'JetBrains Mono', 'Fira Code', ui-monospace, monospace;
|
|
157
|
+
|
|
158
|
+
--color-ui-base: var(--ui-base);
|
|
159
|
+
--color-ui-canvas: var(--ui-canvas);
|
|
160
|
+
--color-ui-line: var(--ui-line);
|
|
161
|
+
--color-ui-fill: var(--ui-fill);
|
|
162
|
+
--color-ui-subtle: var(--ui-subtle);
|
|
163
|
+
--color-ui-default: var(--ui-default);
|
|
164
|
+
--color-ui-strong: var(--ui-strong);
|
|
165
|
+
--color-ui-brand: var(--primary);
|
|
166
|
+
|
|
167
|
+
--color-background: var(--background);
|
|
168
|
+
--color-foreground: var(--foreground);
|
|
169
|
+
--color-card: var(--card);
|
|
170
|
+
--color-card-foreground: var(--card-foreground);
|
|
171
|
+
--color-popover: var(--popover);
|
|
172
|
+
--color-popover-foreground: var(--popover-foreground);
|
|
173
|
+
--color-primary: var(--primary);
|
|
174
|
+
--color-primary-foreground: var(--primary-foreground);
|
|
175
|
+
--color-secondary: var(--secondary);
|
|
176
|
+
--color-secondary-foreground: var(--secondary-foreground);
|
|
177
|
+
--color-muted: var(--muted);
|
|
178
|
+
--color-muted-foreground: var(--muted-foreground);
|
|
179
|
+
--color-accent: var(--accent);
|
|
180
|
+
--color-accent-foreground: var(--accent-foreground);
|
|
181
|
+
--color-destructive: var(--destructive);
|
|
182
|
+
--color-destructive-foreground:var(--destructive-foreground);
|
|
183
|
+
--color-border: var(--border);
|
|
184
|
+
--color-input: var(--input);
|
|
185
|
+
--color-ring: var(--ring);
|
|
186
|
+
|
|
187
|
+
--color-success: var(--success);
|
|
188
|
+
--color-success-bg: var(--success-bg);
|
|
189
|
+
--color-success-border: var(--success-border);
|
|
190
|
+
|
|
191
|
+
--color-warning: var(--warning);
|
|
192
|
+
--color-warning-bg: var(--warning-bg);
|
|
193
|
+
--color-warning-border: var(--warning-border);
|
|
194
|
+
|
|
195
|
+
--color-danger: var(--danger);
|
|
196
|
+
--color-danger-bg: var(--danger-bg);
|
|
197
|
+
--color-danger-border: var(--danger-border);
|
|
198
|
+
|
|
199
|
+
--color-info: var(--info);
|
|
200
|
+
--color-info-bg: var(--info-bg);
|
|
201
|
+
--color-info-border: var(--info-border);
|
|
202
|
+
|
|
203
|
+
/* radius-lg == radius-xl intentionally: cards and .surface share one size. */
|
|
204
|
+
--radius-sm: 0.3125rem;
|
|
205
|
+
--radius-md: 0.4375rem;
|
|
206
|
+
--radius-lg: 0.6875rem;
|
|
207
|
+
--radius-xl: 0.6875rem;
|
|
208
|
+
--radius-2xl: 0.875rem;
|
|
209
|
+
|
|
210
|
+
--text-xs: 0.75rem;
|
|
211
|
+
--text-sm: 0.875rem;
|
|
212
|
+
--text-base: 1rem;
|
|
213
|
+
--text-lg: clamp(1.125rem, 2vw, 1.25rem);
|
|
214
|
+
--text-xl: clamp(1.25rem, 3vw, 1.5rem);
|
|
215
|
+
--text-2xl: clamp(1.5rem, 4vw, 2.25rem);
|
|
216
|
+
--text-3xl: clamp(2rem, 6vw, 3.5rem);
|
|
217
|
+
--text-4xl: clamp(2.5rem, 10vw, 6rem);
|
|
218
|
+
--text-display: clamp(3rem, 12vw, 9rem);
|
|
219
|
+
|
|
220
|
+
--space-xs: clamp(0.5rem, 1vw, 0.75rem);
|
|
221
|
+
--space-sm: clamp(1rem, 2vw, 1.5rem);
|
|
222
|
+
--space-md: clamp(1.5rem, 4vw, 3rem);
|
|
223
|
+
--space-lg: clamp(3rem, 8vw, 6rem);
|
|
224
|
+
--space-xl: clamp(6rem, 12vw, 10rem);
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
@keyframes shimmer {
|
|
228
|
+
0% { background-position: 200% 0; }
|
|
229
|
+
100% { background-position: -200% 0; }
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
@utility surface {
|
|
233
|
+
@apply bg-card border border-border rounded-xl;
|
|
234
|
+
box-shadow: var(--shadow-md);
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
.surface-static {
|
|
238
|
+
transition: none !important;
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
.surface-static:hover {
|
|
242
|
+
box-shadow: var(--shadow-md) !important;
|
|
243
|
+
transform: none !important;
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
.surface-static-shadow {
|
|
247
|
+
box-shadow: var(--shadow-md) !important;
|
|
248
|
+
transition: none !important;
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
.surface-static-shadow:hover {
|
|
252
|
+
box-shadow: var(--shadow-md) !important;
|
|
253
|
+
transform: none !important;
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
@utility glass {
|
|
257
|
+
@apply backdrop-blur-md bg-card/75 border border-border;
|
|
258
|
+
background-image: linear-gradient(to bottom right, oklch(100% 0 0 / 0.05), transparent);
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
@utility surface-hover {
|
|
262
|
+
@apply transition-all duration-300;
|
|
263
|
+
&:hover {
|
|
264
|
+
@apply border-primary/30 shadow-lg shadow-primary/5 -translate-y-[1px];
|
|
265
|
+
}
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
@utility skeleton {
|
|
269
|
+
background: linear-gradient(
|
|
270
|
+
90deg,
|
|
271
|
+
var(--muted) 25%,
|
|
272
|
+
color-mix(in oklch, var(--muted) 50%, var(--card)) 50%,
|
|
273
|
+
var(--muted) 75%
|
|
274
|
+
);
|
|
275
|
+
background-size: 200% 100%;
|
|
276
|
+
@apply animate-[shimmer_1.8s_linear_infinite] rounded-sm;
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
/* Unlayered, kept at this specificity so no later utility can beat it. */
|
|
280
|
+
.skeleton {
|
|
281
|
+
background:
|
|
282
|
+
linear-gradient(
|
|
283
|
+
90deg,
|
|
284
|
+
var(--muted) 25%,
|
|
285
|
+
color-mix(in oklch, var(--muted) 50%, var(--card)) 50%,
|
|
286
|
+
var(--muted) 75%
|
|
287
|
+
) !important;
|
|
288
|
+
background-size: 200% 100% !important;
|
|
289
|
+
animation: shimmer 1.8s linear infinite !important;
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
/* Geist, scoped locally since global @theme sets --font-sans/mono to app defaults. */
|
|
293
|
+
.ui-font-sans {
|
|
294
|
+
font-family: 'Geist', ui-sans-serif, system-ui, sans-serif;
|
|
295
|
+
}
|
|
296
|
+
.ui-font-mono {
|
|
297
|
+
font-family: 'Geist Mono', ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
|
|
298
|
+
font-feature-settings: 'tnum' 1;
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
/* Matches dashboard stat-card chrome; .ui-well is its recessed inner panel. */
|
|
302
|
+
.ui-panel {
|
|
303
|
+
font-family: 'Geist', ui-sans-serif, system-ui, sans-serif;
|
|
304
|
+
border-radius: var(--radius-lg);
|
|
305
|
+
border: 1px solid var(--ui-line);
|
|
306
|
+
background: #ffffff;
|
|
307
|
+
}
|
|
308
|
+
.dark .ui-panel {
|
|
309
|
+
background: #000000;
|
|
310
|
+
border-color: oklch(0.27 0 0);
|
|
311
|
+
}
|
|
312
|
+
.ui-well {
|
|
313
|
+
background: oklch(97.8% 0.002 286.3);
|
|
314
|
+
/* On the recessed face the neutral-500 subtle tone reads washed out in light mode,
|
|
315
|
+
so step it down to zinc-600. Dark mode already has enough separation. */
|
|
316
|
+
--ui-subtle: oklch(44.2% 0.017 285.8);
|
|
317
|
+
}
|
|
318
|
+
.dark .ui-well {
|
|
319
|
+
background: oklch(19% 0 0);
|
|
320
|
+
--ui-subtle: oklch(70.8% 0 0);
|
|
321
|
+
}
|
|
322
|
+
|
|
323
|
+
/* Syntax tokens for sugar-high (./lib/highlight.tsx); it emits
|
|
324
|
+
color: var(--sh-<token type>) per token. */
|
|
325
|
+
:root {
|
|
326
|
+
--sh-keyword: oklch(48% 0.19 305);
|
|
327
|
+
--sh-string: oklch(46% 0.12 150);
|
|
328
|
+
--sh-class: oklch(50% 0.13 65);
|
|
329
|
+
--sh-comment: oklch(58% 0.01 260);
|
|
330
|
+
--sh-entity: oklch(46% 0.14 260);
|
|
331
|
+
--sh-property: oklch(45% 0.11 200);
|
|
332
|
+
--sh-identifier: inherit;
|
|
333
|
+
--sh-sign: oklch(58% 0.01 260);
|
|
334
|
+
--sh-jsxliterals: inherit;
|
|
335
|
+
--sh-break: inherit;
|
|
336
|
+
--sh-space: inherit;
|
|
337
|
+
}
|
|
338
|
+
.dark {
|
|
339
|
+
--sh-keyword: oklch(75% 0.14 305);
|
|
340
|
+
--sh-string: oklch(76% 0.11 150);
|
|
341
|
+
--sh-class: oklch(78% 0.12 65);
|
|
342
|
+
--sh-comment: oklch(58% 0.01 260);
|
|
343
|
+
--sh-entity: oklch(76% 0.1 260);
|
|
344
|
+
--sh-property: oklch(78% 0.1 200);
|
|
345
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@codraoss/ui",
|
|
3
|
-
"version": "0.9.
|
|
3
|
+
"version": "0.9.5",
|
|
4
4
|
"description": "Codra's reusable React design-system primitives and hooks.",
|
|
5
5
|
"author": "Devarshi Shimpi",
|
|
6
6
|
"license": "AGPL-3.0-only",
|
|
@@ -14,7 +14,9 @@
|
|
|
14
14
|
"url": "https://github.com/devarshishimpi/codra/issues"
|
|
15
15
|
},
|
|
16
16
|
"type": "module",
|
|
17
|
-
"sideEffects":
|
|
17
|
+
"sideEffects": [
|
|
18
|
+
"**/*.css"
|
|
19
|
+
],
|
|
18
20
|
"exports": {
|
|
19
21
|
".": {
|
|
20
22
|
"types": "./dist/index.d.ts",
|
|
@@ -59,7 +61,8 @@
|
|
|
59
61
|
"./hooks": {
|
|
60
62
|
"types": "./dist/hooks/index.d.ts",
|
|
61
63
|
"import": "./dist/hooks/index.js"
|
|
62
|
-
}
|
|
64
|
+
},
|
|
65
|
+
"./styles": "./dist/styles/tokens.css"
|
|
63
66
|
},
|
|
64
67
|
"files": [
|
|
65
68
|
"dist",
|
|
@@ -115,11 +118,12 @@
|
|
|
115
118
|
"./hooks": {
|
|
116
119
|
"types": "./dist/hooks/index.d.ts",
|
|
117
120
|
"import": "./dist/hooks/index.js"
|
|
118
|
-
}
|
|
121
|
+
},
|
|
122
|
+
"./styles": "./dist/styles/tokens.css"
|
|
119
123
|
}
|
|
120
124
|
},
|
|
121
125
|
"scripts": {
|
|
122
|
-
"build": "tsup",
|
|
126
|
+
"build": "tsup && node ./scripts/copy-styles.mjs",
|
|
123
127
|
"typecheck": "tsc -p tsconfig.json",
|
|
124
128
|
"prepack": "node ../../scripts/swap-publish-exports.mjs promote",
|
|
125
129
|
"postpack": "node ../../scripts/swap-publish-exports.mjs restore"
|
|
@@ -134,7 +138,7 @@
|
|
|
134
138
|
"sonner": ">=2.0.0"
|
|
135
139
|
},
|
|
136
140
|
"dependencies": {
|
|
137
|
-
"@codraoss/schema": "^0.9.
|
|
141
|
+
"@codraoss/schema": "^0.9.5",
|
|
138
142
|
"@base-ui/react": "^1.6.0",
|
|
139
143
|
"class-variance-authority": "^0.7.1",
|
|
140
144
|
"clsx": "^2.1.1",
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/lib/utils.ts"],"sourcesContent":["import { clsx, type ClassValue } from 'clsx';\r\nimport { twMerge } from 'tailwind-merge';\r\n\r\nexport function cn(...inputs: ClassValue[]) {\r\n return twMerge(clsx(inputs));\r\n}\r\n\r\nexport function fmtNumber(n: number) {\r\n if (n >= 1_000_000) return `${(n / 1_000_000).toFixed(1)}M`;\r\n if (n >= 1_000) return `${(n / 1_000).toFixed(n >= 10_000 ? 0 : 1)}k`;\r\n return n.toLocaleString();\r\n}\r\n\r\n/**\r\n * Like {@link fmtNumber} but returns the numeric part and its unit suffix\r\n * separately, so a card can render \"1.4\" large and \"M\" as a smaller unit.\r\n */\r\nexport function fmtStat(n: number): { value: string; unit: string } {\r\n if (n >= 1_000_000) return { value: (n / 1_000_000).toFixed(1), unit: 'M' };\r\n if (n >= 1_000) return { value: (n / 1_000).toFixed(n >= 10_000 ? 0 : 1), unit: 'k' };\r\n return { value: n.toLocaleString(), unit: '' };\r\n}\r\n\r\nexport function formatPreciseDuration(ms: number | null | undefined): string {\r\n if (ms == null) return '';\r\n // Sub-minute: show one decimal so e.g. a 724ms review reads as \"0.7s\" rather than \"0s\".\r\n if (ms < 60_000) {\r\n return `${(ms / 1000).toFixed(1)}s`;\r\n }\r\n const totalSeconds = Math.round(ms / 1000);\r\n const minutes = Math.floor(totalSeconds / 60);\r\n const seconds = totalSeconds % 60;\r\n if (minutes < 60) {\r\n return `${minutes}m ${seconds}s`;\r\n }\r\n const hours = Math.floor(minutes / 60);\r\n const remainingMinutes = minutes % 60;\r\n return `${hours}h ${remainingMinutes}m`;\r\n}\r\n"],"mappings":";AAAA,SAAS,YAA6B;AACtC,SAAS,eAAe;AAEjB,SAAS,MAAM,QAAsB;AAC1C,SAAO,QAAQ,KAAK,MAAM,CAAC;AAC7B;AAEO,SAAS,UAAU,GAAW;AACnC,MAAI,KAAK,IAAW,QAAO,IAAI,IAAI,KAAW,QAAQ,CAAC,CAAC;AACxD,MAAI,KAAK,IAAW,QAAO,IAAI,IAAI,KAAO,QAAQ,KAAK,MAAS,IAAI,CAAC,CAAC;AACtE,SAAO,EAAE,eAAe;AAC1B;AAMO,SAAS,QAAQ,GAA4C;AAClE,MAAI,KAAK,IAAW,QAAO,EAAE,QAAQ,IAAI,KAAW,QAAQ,CAAC,GAAG,MAAM,IAAI;AAC1E,MAAI,KAAK,IAAW,QAAO,EAAE,QAAQ,IAAI,KAAO,QAAQ,KAAK,MAAS,IAAI,CAAC,GAAG,MAAM,IAAI;AACxF,SAAO,EAAE,OAAO,EAAE,eAAe,GAAG,MAAM,GAAG;AAC/C;AAEO,SAAS,sBAAsB,IAAuC;AAC3E,MAAI,MAAM,KAAM,QAAO;AAEvB,MAAI,KAAK,KAAQ;AACf,WAAO,IAAI,KAAK,KAAM,QAAQ,CAAC,CAAC;AAAA,EAClC;AACA,QAAM,eAAe,KAAK,MAAM,KAAK,GAAI;AACzC,QAAM,UAAU,KAAK,MAAM,eAAe,EAAE;AAC5C,QAAM,UAAU,eAAe;AAC/B,MAAI,UAAU,IAAI;AAChB,WAAO,GAAG,OAAO,KAAK,OAAO;AAAA,EAC/B;AACA,QAAM,QAAQ,KAAK,MAAM,UAAU,EAAE;AACrC,QAAM,mBAAmB,UAAU;AACnC,SAAO,GAAG,KAAK,KAAK,gBAAgB;AACtC;","names":[]}
|