@webjsdev/ui 0.3.1 → 0.3.2

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 (39) hide show
  1. package/package.json +4 -3
  2. package/packages/registry/README.md +35 -0
  3. package/packages/registry/components/accordion.ts +74 -0
  4. package/packages/registry/components/alert-dialog.ts +359 -0
  5. package/packages/registry/components/alert.ts +51 -0
  6. package/packages/registry/components/aspect-ratio.ts +22 -0
  7. package/packages/registry/components/avatar.ts +52 -0
  8. package/packages/registry/components/badge.ts +40 -0
  9. package/packages/registry/components/breadcrumb.ts +43 -0
  10. package/packages/registry/components/button.ts +72 -0
  11. package/packages/registry/components/card.ts +86 -0
  12. package/packages/registry/components/checkbox.ts +97 -0
  13. package/packages/registry/components/collapsible.ts +60 -0
  14. package/packages/registry/components/dialog.ts +378 -0
  15. package/packages/registry/components/dropdown-menu.ts +591 -0
  16. package/packages/registry/components/hover-card.ts +175 -0
  17. package/packages/registry/components/input.ts +36 -0
  18. package/packages/registry/components/kbd.ts +25 -0
  19. package/packages/registry/components/label.ts +23 -0
  20. package/packages/registry/components/native-select.ts +110 -0
  21. package/packages/registry/components/pagination.ts +45 -0
  22. package/packages/registry/components/popover.ts +260 -0
  23. package/packages/registry/components/progress.ts +46 -0
  24. package/packages/registry/components/radio-group.ts +113 -0
  25. package/packages/registry/components/separator.ts +30 -0
  26. package/packages/registry/components/skeleton.ts +16 -0
  27. package/packages/registry/components/sonner.ts +240 -0
  28. package/packages/registry/components/switch.ts +52 -0
  29. package/packages/registry/components/table.ts +58 -0
  30. package/packages/registry/components/tabs.ts +271 -0
  31. package/packages/registry/components/textarea.ts +27 -0
  32. package/packages/registry/components/toggle-group.ts +236 -0
  33. package/packages/registry/components/toggle.ts +118 -0
  34. package/packages/registry/components/tooltip.ts +195 -0
  35. package/packages/registry/lib/utils.ts +241 -0
  36. package/packages/registry/package.json +7 -0
  37. package/packages/registry/registry.json +479 -0
  38. package/packages/registry/themes/base-colors.js +193 -0
  39. package/packages/registry/themes/index.css +141 -0
@@ -0,0 +1,479 @@
1
+ {
2
+ "$schema": "https://ui.webjs.dev/schema/registry.json",
3
+ "name": "@webjsdev/ui",
4
+ "homepage": "https://ui.webjs.dev",
5
+ "items": [
6
+ {
7
+ "name": "lib-utils",
8
+ "type": "registry:lib",
9
+ "description": "cn() class-merge helper",
10
+ "files": [
11
+ {
12
+ "path": "lib/utils.ts",
13
+ "type": "registry:lib",
14
+ "target": "lib/utils.ts"
15
+ }
16
+ ]
17
+ },
18
+ {
19
+ "name": "theme-neutral",
20
+ "type": "registry:theme",
21
+ "title": "Neutral",
22
+ "description": "Pure grayscale (default)",
23
+ "files": [
24
+ {
25
+ "path": "themes/index.css",
26
+ "type": "registry:file",
27
+ "target": "app/globals.css"
28
+ }
29
+ ]
30
+ },
31
+ {
32
+ "name": "accordion",
33
+ "type": "registry:ui",
34
+ "dependencies": [
35
+ "@webjsdev/core"
36
+ ],
37
+ "files": [
38
+ {
39
+ "path": "components/accordion.ts",
40
+ "type": "registry:ui"
41
+ }
42
+ ]
43
+ },
44
+ {
45
+ "name": "alert",
46
+ "type": "registry:ui",
47
+ "dependencies": [
48
+ "@webjsdev/core"
49
+ ],
50
+ "files": [
51
+ {
52
+ "path": "components/alert.ts",
53
+ "type": "registry:ui"
54
+ }
55
+ ]
56
+ },
57
+ {
58
+ "name": "alert-dialog",
59
+ "type": "registry:ui",
60
+ "registryDependencies": [
61
+ "button",
62
+ "dialog"
63
+ ],
64
+ "dependencies": [
65
+ "@webjsdev/core"
66
+ ],
67
+ "files": [
68
+ {
69
+ "path": "components/alert-dialog.ts",
70
+ "type": "registry:ui"
71
+ }
72
+ ]
73
+ },
74
+ {
75
+ "name": "aspect-ratio",
76
+ "type": "registry:ui",
77
+ "dependencies": [
78
+ "@webjsdev/core"
79
+ ],
80
+ "files": [
81
+ {
82
+ "path": "components/aspect-ratio.ts",
83
+ "type": "registry:ui"
84
+ }
85
+ ]
86
+ },
87
+ {
88
+ "name": "avatar",
89
+ "type": "registry:ui",
90
+ "dependencies": [
91
+ "@webjsdev/core"
92
+ ],
93
+ "files": [
94
+ {
95
+ "path": "components/avatar.ts",
96
+ "type": "registry:ui"
97
+ }
98
+ ]
99
+ },
100
+ {
101
+ "name": "badge",
102
+ "type": "registry:ui",
103
+ "registryDependencies": [
104
+ "lib-utils"
105
+ ],
106
+ "dependencies": [
107
+ "@webjsdev/core"
108
+ ],
109
+ "files": [
110
+ {
111
+ "path": "components/badge.ts",
112
+ "type": "registry:ui"
113
+ }
114
+ ]
115
+ },
116
+ {
117
+ "name": "breadcrumb",
118
+ "type": "registry:ui",
119
+ "dependencies": [
120
+ "@webjsdev/core"
121
+ ],
122
+ "files": [
123
+ {
124
+ "path": "components/breadcrumb.ts",
125
+ "type": "registry:ui"
126
+ }
127
+ ]
128
+ },
129
+ {
130
+ "name": "button",
131
+ "type": "registry:ui",
132
+ "registryDependencies": [
133
+ "lib-utils"
134
+ ],
135
+ "dependencies": [
136
+ "@webjsdev/core"
137
+ ],
138
+ "files": [
139
+ {
140
+ "path": "components/button.ts",
141
+ "type": "registry:ui"
142
+ }
143
+ ]
144
+ },
145
+ {
146
+ "name": "card",
147
+ "type": "registry:ui",
148
+ "registryDependencies": [
149
+ "lib-utils"
150
+ ],
151
+ "dependencies": [
152
+ "@webjsdev/core"
153
+ ],
154
+ "files": [
155
+ {
156
+ "path": "components/card.ts",
157
+ "type": "registry:ui"
158
+ }
159
+ ]
160
+ },
161
+ {
162
+ "name": "checkbox",
163
+ "type": "registry:ui",
164
+ "dependencies": [
165
+ "@webjsdev/core"
166
+ ],
167
+ "files": [
168
+ {
169
+ "path": "components/checkbox.ts",
170
+ "type": "registry:ui"
171
+ }
172
+ ]
173
+ },
174
+ {
175
+ "name": "collapsible",
176
+ "type": "registry:ui",
177
+ "dependencies": [
178
+ "@webjsdev/core"
179
+ ],
180
+ "files": [
181
+ {
182
+ "path": "components/collapsible.ts",
183
+ "type": "registry:ui"
184
+ }
185
+ ]
186
+ },
187
+ {
188
+ "name": "dialog",
189
+ "type": "registry:ui",
190
+ "registryDependencies": [
191
+ "lib-utils"
192
+ ],
193
+ "dependencies": [
194
+ "@webjsdev/core"
195
+ ],
196
+ "files": [
197
+ {
198
+ "path": "components/dialog.ts",
199
+ "type": "registry:ui"
200
+ }
201
+ ]
202
+ },
203
+ {
204
+ "name": "dropdown-menu",
205
+ "type": "registry:ui",
206
+ "dependencies": [
207
+ "@webjsdev/core"
208
+ ],
209
+ "files": [
210
+ {
211
+ "path": "components/dropdown-menu.ts",
212
+ "type": "registry:ui"
213
+ }
214
+ ]
215
+ },
216
+ {
217
+ "name": "hover-card",
218
+ "type": "registry:ui",
219
+ "dependencies": [
220
+ "@webjsdev/core"
221
+ ],
222
+ "files": [
223
+ {
224
+ "path": "components/hover-card.ts",
225
+ "type": "registry:ui"
226
+ }
227
+ ]
228
+ },
229
+ {
230
+ "name": "input",
231
+ "type": "registry:ui",
232
+ "registryDependencies": [
233
+ "lib-utils"
234
+ ],
235
+ "dependencies": [
236
+ "@webjsdev/core"
237
+ ],
238
+ "files": [
239
+ {
240
+ "path": "components/input.ts",
241
+ "type": "registry:ui"
242
+ }
243
+ ]
244
+ },
245
+ {
246
+ "name": "kbd",
247
+ "type": "registry:ui",
248
+ "dependencies": [
249
+ "@webjsdev/core"
250
+ ],
251
+ "files": [
252
+ {
253
+ "path": "components/kbd.ts",
254
+ "type": "registry:ui"
255
+ }
256
+ ]
257
+ },
258
+ {
259
+ "name": "label",
260
+ "type": "registry:ui",
261
+ "registryDependencies": [
262
+ "lib-utils"
263
+ ],
264
+ "dependencies": [
265
+ "@webjsdev/core"
266
+ ],
267
+ "files": [
268
+ {
269
+ "path": "components/label.ts",
270
+ "type": "registry:ui"
271
+ }
272
+ ]
273
+ },
274
+ {
275
+ "name": "native-select",
276
+ "type": "registry:ui",
277
+ "dependencies": [
278
+ "@webjsdev/core"
279
+ ],
280
+ "files": [
281
+ {
282
+ "path": "components/native-select.ts",
283
+ "type": "registry:ui"
284
+ }
285
+ ]
286
+ },
287
+ {
288
+ "name": "pagination",
289
+ "type": "registry:ui",
290
+ "registryDependencies": [
291
+ "button"
292
+ ],
293
+ "dependencies": [
294
+ "@webjsdev/core"
295
+ ],
296
+ "files": [
297
+ {
298
+ "path": "components/pagination.ts",
299
+ "type": "registry:ui"
300
+ }
301
+ ]
302
+ },
303
+ {
304
+ "name": "popover",
305
+ "type": "registry:ui",
306
+ "dependencies": [
307
+ "@webjsdev/core"
308
+ ],
309
+ "files": [
310
+ {
311
+ "path": "components/popover.ts",
312
+ "type": "registry:ui"
313
+ }
314
+ ]
315
+ },
316
+ {
317
+ "name": "progress",
318
+ "type": "registry:ui",
319
+ "dependencies": [
320
+ "@webjsdev/core"
321
+ ],
322
+ "files": [
323
+ {
324
+ "path": "components/progress.ts",
325
+ "type": "registry:ui"
326
+ }
327
+ ]
328
+ },
329
+ {
330
+ "name": "radio-group",
331
+ "type": "registry:ui",
332
+ "dependencies": [
333
+ "@webjsdev/core"
334
+ ],
335
+ "files": [
336
+ {
337
+ "path": "components/radio-group.ts",
338
+ "type": "registry:ui"
339
+ }
340
+ ]
341
+ },
342
+ {
343
+ "name": "separator",
344
+ "type": "registry:ui",
345
+ "registryDependencies": [
346
+ "lib-utils"
347
+ ],
348
+ "dependencies": [
349
+ "@webjsdev/core"
350
+ ],
351
+ "files": [
352
+ {
353
+ "path": "components/separator.ts",
354
+ "type": "registry:ui"
355
+ }
356
+ ]
357
+ },
358
+ {
359
+ "name": "skeleton",
360
+ "type": "registry:ui",
361
+ "registryDependencies": [
362
+ "lib-utils"
363
+ ],
364
+ "dependencies": [
365
+ "@webjsdev/core"
366
+ ],
367
+ "files": [
368
+ {
369
+ "path": "components/skeleton.ts",
370
+ "type": "registry:ui"
371
+ }
372
+ ]
373
+ },
374
+ {
375
+ "name": "sonner",
376
+ "type": "registry:ui",
377
+ "dependencies": [
378
+ "@webjsdev/core"
379
+ ],
380
+ "files": [
381
+ {
382
+ "path": "components/sonner.ts",
383
+ "type": "registry:ui"
384
+ }
385
+ ]
386
+ },
387
+ {
388
+ "name": "switch",
389
+ "type": "registry:ui",
390
+ "dependencies": [
391
+ "@webjsdev/core"
392
+ ],
393
+ "files": [
394
+ {
395
+ "path": "components/switch.ts",
396
+ "type": "registry:ui"
397
+ }
398
+ ]
399
+ },
400
+ {
401
+ "name": "table",
402
+ "type": "registry:ui",
403
+ "dependencies": [
404
+ "@webjsdev/core"
405
+ ],
406
+ "files": [
407
+ {
408
+ "path": "components/table.ts",
409
+ "type": "registry:ui"
410
+ }
411
+ ]
412
+ },
413
+ {
414
+ "name": "tabs",
415
+ "type": "registry:ui",
416
+ "dependencies": [
417
+ "@webjsdev/core"
418
+ ],
419
+ "files": [
420
+ {
421
+ "path": "components/tabs.ts",
422
+ "type": "registry:ui"
423
+ }
424
+ ]
425
+ },
426
+ {
427
+ "name": "textarea",
428
+ "type": "registry:ui",
429
+ "dependencies": [
430
+ "@webjsdev/core"
431
+ ],
432
+ "files": [
433
+ {
434
+ "path": "components/textarea.ts",
435
+ "type": "registry:ui"
436
+ }
437
+ ]
438
+ },
439
+ {
440
+ "name": "toggle",
441
+ "type": "registry:ui",
442
+ "dependencies": [
443
+ "@webjsdev/core"
444
+ ],
445
+ "files": [
446
+ {
447
+ "path": "components/toggle.ts",
448
+ "type": "registry:ui"
449
+ }
450
+ ]
451
+ },
452
+ {
453
+ "name": "toggle-group",
454
+ "type": "registry:ui",
455
+ "dependencies": [
456
+ "@webjsdev/core"
457
+ ],
458
+ "files": [
459
+ {
460
+ "path": "components/toggle-group.ts",
461
+ "type": "registry:ui"
462
+ }
463
+ ]
464
+ },
465
+ {
466
+ "name": "tooltip",
467
+ "type": "registry:ui",
468
+ "dependencies": [
469
+ "@webjsdev/core"
470
+ ],
471
+ "files": [
472
+ {
473
+ "path": "components/tooltip.ts",
474
+ "type": "registry:ui"
475
+ }
476
+ ]
477
+ }
478
+ ]
479
+ }
@@ -0,0 +1,193 @@
1
+ /**
2
+ * The 7 base colours `@webjsdev/ui` ships, mirroring shadcn's palette set.
3
+ * Each entry is a partial override on the canonical neutral palette defined
4
+ * in `themes/index.css`. Lightness stays identical so contrast ratios are
5
+ * preserved; only hue / chroma shift.
6
+ *
7
+ * Pure ESM data module: imported at request time by the website's registry
8
+ * composer (`app/_lib/registry.server.ts`) to synthesize `theme-<color>` items
9
+ * on demand. No build step, no committed output. Numbers match the values
10
+ * shadcn emits in `apps/v4/public/r/themes/*.json`.
11
+ */
12
+
13
+ export const BASE_COLORS = ['neutral', 'stone', 'zinc', 'mauve', 'olive', 'mist', 'taupe'];
14
+
15
+ export const BASE_TITLES = {
16
+ neutral: 'Neutral',
17
+ stone: 'Stone',
18
+ zinc: 'Zinc',
19
+ mauve: 'Mauve',
20
+ olive: 'Olive',
21
+ mist: 'Mist',
22
+ taupe: 'Taupe',
23
+ };
24
+
25
+ export const BASE_DESCRIPTIONS = {
26
+ neutral: 'Pure grayscale (default)',
27
+ stone: 'Warm grey with a hint of brown',
28
+ zinc: 'Cool grey with a hint of blue',
29
+ mauve: 'Soft purple',
30
+ olive: 'Muted green',
31
+ mist: 'Cool teal',
32
+ taupe: 'Warm beige',
33
+ };
34
+
35
+ /**
36
+ * Per-base overrides. Anything not listed here is inherited from
37
+ * `themes/index.css` (the neutral default).
38
+ */
39
+ export const BASE_OVERRIDES = {
40
+ neutral: { light: {}, dark: {} },
41
+ stone: {
42
+ light: {
43
+ foreground: 'oklch(0.147 0.004 49.25)',
44
+ 'card-foreground': 'oklch(0.147 0.004 49.25)',
45
+ 'popover-foreground': 'oklch(0.147 0.004 49.25)',
46
+ primary: 'oklch(0.216 0.006 56.043)',
47
+ 'primary-foreground': 'oklch(0.985 0.001 106.423)',
48
+ secondary: 'oklch(0.97 0.001 106.424)',
49
+ 'secondary-foreground': 'oklch(0.216 0.006 56.043)',
50
+ muted: 'oklch(0.97 0.001 106.424)',
51
+ 'muted-foreground': 'oklch(0.553 0.013 58.071)',
52
+ accent: 'oklch(0.97 0.001 106.424)',
53
+ 'accent-foreground': 'oklch(0.216 0.006 56.043)',
54
+ border: 'oklch(0.923 0.003 48.717)',
55
+ input: 'oklch(0.923 0.003 48.717)',
56
+ ring: 'oklch(0.709 0.01 56.259)',
57
+ },
58
+ dark: {
59
+ background: 'oklch(0.147 0.004 49.25)',
60
+ card: 'oklch(0.216 0.006 56.043)',
61
+ popover: 'oklch(0.216 0.006 56.043)',
62
+ primary: 'oklch(0.923 0.003 48.717)',
63
+ 'primary-foreground': 'oklch(0.216 0.006 56.043)',
64
+ secondary: 'oklch(0.268 0.007 34.298)',
65
+ muted: 'oklch(0.268 0.007 34.298)',
66
+ 'muted-foreground': 'oklch(0.709 0.01 56.259)',
67
+ accent: 'oklch(0.371 0.011 67.558)',
68
+ border: 'oklch(1 0 0 / 10%)',
69
+ input: 'oklch(1 0 0 / 15%)',
70
+ ring: 'oklch(0.553 0.013 58.071)',
71
+ },
72
+ },
73
+ zinc: {
74
+ light: {
75
+ foreground: 'oklch(0.141 0.005 285.823)',
76
+ primary: 'oklch(0.21 0.006 285.885)',
77
+ 'primary-foreground': 'oklch(0.985 0 0)',
78
+ secondary: 'oklch(0.967 0.001 286.375)',
79
+ 'secondary-foreground': 'oklch(0.21 0.006 285.885)',
80
+ muted: 'oklch(0.967 0.001 286.375)',
81
+ 'muted-foreground': 'oklch(0.552 0.016 285.938)',
82
+ accent: 'oklch(0.967 0.001 286.375)',
83
+ 'accent-foreground': 'oklch(0.21 0.006 285.885)',
84
+ border: 'oklch(0.92 0.004 286.32)',
85
+ input: 'oklch(0.92 0.004 286.32)',
86
+ ring: 'oklch(0.705 0.015 286.067)',
87
+ },
88
+ dark: {
89
+ background: 'oklch(0.141 0.005 285.823)',
90
+ card: 'oklch(0.21 0.006 285.885)',
91
+ popover: 'oklch(0.21 0.006 285.885)',
92
+ primary: 'oklch(0.92 0.004 286.32)',
93
+ 'primary-foreground': 'oklch(0.21 0.006 285.885)',
94
+ secondary: 'oklch(0.274 0.006 286.033)',
95
+ muted: 'oklch(0.274 0.006 286.033)',
96
+ 'muted-foreground': 'oklch(0.705 0.015 286.067)',
97
+ accent: 'oklch(0.274 0.006 286.033)',
98
+ ring: 'oklch(0.552 0.016 285.938)',
99
+ },
100
+ },
101
+ mauve: {
102
+ light: {
103
+ primary: 'oklch(0.42 0.05 296)',
104
+ 'primary-foreground': 'oklch(0.985 0 0)',
105
+ accent: 'oklch(0.96 0.01 296)',
106
+ 'accent-foreground': 'oklch(0.42 0.05 296)',
107
+ ring: 'oklch(0.55 0.05 296)',
108
+ },
109
+ dark: {
110
+ primary: 'oklch(0.75 0.06 296)',
111
+ accent: 'oklch(0.35 0.04 296)',
112
+ ring: 'oklch(0.55 0.05 296)',
113
+ },
114
+ },
115
+ olive: {
116
+ light: {
117
+ primary: 'oklch(0.40 0.06 130)',
118
+ 'primary-foreground': 'oklch(0.985 0 0)',
119
+ accent: 'oklch(0.95 0.02 130)',
120
+ 'accent-foreground': 'oklch(0.40 0.06 130)',
121
+ ring: 'oklch(0.55 0.05 130)',
122
+ },
123
+ dark: {
124
+ primary: 'oklch(0.70 0.07 130)',
125
+ accent: 'oklch(0.35 0.05 130)',
126
+ ring: 'oklch(0.55 0.05 130)',
127
+ },
128
+ },
129
+ mist: {
130
+ light: {
131
+ primary: 'oklch(0.42 0.05 196)',
132
+ 'primary-foreground': 'oklch(0.985 0 0)',
133
+ accent: 'oklch(0.95 0.02 196)',
134
+ 'accent-foreground': 'oklch(0.42 0.05 196)',
135
+ ring: 'oklch(0.55 0.05 196)',
136
+ },
137
+ dark: {
138
+ primary: 'oklch(0.72 0.06 196)',
139
+ accent: 'oklch(0.35 0.04 196)',
140
+ ring: 'oklch(0.55 0.05 196)',
141
+ },
142
+ },
143
+ taupe: {
144
+ light: {
145
+ primary: 'oklch(0.40 0.04 30)',
146
+ 'primary-foreground': 'oklch(0.985 0 0)',
147
+ accent: 'oklch(0.95 0.02 30)',
148
+ 'accent-foreground': 'oklch(0.40 0.04 30)',
149
+ ring: 'oklch(0.55 0.05 30)',
150
+ },
151
+ dark: {
152
+ primary: 'oklch(0.72 0.05 30)',
153
+ accent: 'oklch(0.35 0.04 30)',
154
+ ring: 'oklch(0.55 0.05 30)',
155
+ },
156
+ },
157
+ };
158
+
159
+ /**
160
+ * Merge per-base-colour overrides into the canonical neutral CSS.
161
+ *
162
+ * Strategy: locate the `:root { ... }` and `.dark { ... }` blocks, then
163
+ * substitute each overridden `--<key>: <value>` line in place. Keys not
164
+ * present in `overrides` keep their neutral defaults. The output preserves
165
+ * the original file's formatting + comments verbatim: only the values
166
+ * change.
167
+ *
168
+ * @param {string} neutralCss - verbatim contents of `themes/index.css`
169
+ * @param {{ light: Record<string,string>, dark: Record<string,string> }} overrides
170
+ */
171
+ export function mergeThemeCss(neutralCss, overrides) {
172
+ let css = neutralCss;
173
+ css = replaceBlockVars(css, ':root', overrides.light || {});
174
+ css = replaceBlockVars(css, '.dark', overrides.dark || {});
175
+ return css;
176
+ }
177
+
178
+ function replaceBlockVars(css, selector, vars) {
179
+ if (!Object.keys(vars).length) return css;
180
+ const blockRe = new RegExp(`(${escapeRe(selector)}\\s*\\{)([\\s\\S]*?)(\\n\\})`);
181
+ return css.replace(blockRe, (_m, open, body, close) => {
182
+ let next = body;
183
+ for (const [key, value] of Object.entries(vars)) {
184
+ const varRe = new RegExp(`(--${escapeRe(key)}\\s*:\\s*)[^;\\n]+`);
185
+ next = next.replace(varRe, `$1${value}`);
186
+ }
187
+ return open + next + close;
188
+ });
189
+ }
190
+
191
+ function escapeRe(s) {
192
+ return s.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
193
+ }