veloria-ui 0.1.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.
- package/CHANGELOG.md +206 -0
- package/LICENSE +21 -0
- package/README.md +253 -0
- package/dist/cli/index.js +511 -0
- package/dist/index.d.mts +1317 -0
- package/dist/index.d.ts +1317 -0
- package/dist/index.js +5373 -0
- package/dist/index.js.map +1 -0
- package/dist/index.mjs +5130 -0
- package/dist/index.mjs.map +1 -0
- package/dist/provider.d.mts +15 -0
- package/dist/provider.d.ts +15 -0
- package/dist/provider.js +1197 -0
- package/dist/provider.js.map +1 -0
- package/dist/provider.mjs +1161 -0
- package/dist/provider.mjs.map +1 -0
- package/dist/tailwind.d.ts +25 -0
- package/dist/tailwind.js +129 -0
- package/package.json +138 -0
- package/src/cli/index.ts +303 -0
- package/src/cli/registry.ts +139 -0
- package/src/components/advanced-forms/index.tsx +975 -0
- package/src/components/basic/Button.tsx +135 -0
- package/src/components/basic/IconButton.tsx +69 -0
- package/src/components/basic/index.tsx +446 -0
- package/src/components/data-display/index.tsx +1158 -0
- package/src/components/feedback/index.tsx +1051 -0
- package/src/components/forms/index.tsx +476 -0
- package/src/components/layout/index.tsx +296 -0
- package/src/components/media/index.tsx +437 -0
- package/src/components/navigation/index.tsx +484 -0
- package/src/components/overlay/index.tsx +473 -0
- package/src/components/utility/index.tsx +566 -0
- package/src/hooks/index.ts +602 -0
- package/src/hooks/use-toast.tsx +74 -0
- package/src/index.ts +396 -0
- package/src/provider.tsx +54 -0
- package/src/styles/atlas.css +252 -0
- package/src/tailwind.ts +124 -0
- package/src/types/index.ts +95 -0
- package/src/utils/cn.ts +66 -0
|
@@ -0,0 +1,511 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
#!/usr/bin/env node
|
|
3
|
+
"use strict";
|
|
4
|
+
var __create = Object.create;
|
|
5
|
+
var __defProp = Object.defineProperty;
|
|
6
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
7
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
8
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
9
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
10
|
+
var __commonJS = (cb, mod) => function __require() {
|
|
11
|
+
return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports;
|
|
12
|
+
};
|
|
13
|
+
var __copyProps = (to, from, except, desc) => {
|
|
14
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
15
|
+
for (let key of __getOwnPropNames(from))
|
|
16
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
17
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
18
|
+
}
|
|
19
|
+
return to;
|
|
20
|
+
};
|
|
21
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
22
|
+
// If the importer is in node compatibility mode or this is not an ESM
|
|
23
|
+
// file that has been converted to a CommonJS file using a Babel-
|
|
24
|
+
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
25
|
+
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
26
|
+
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
27
|
+
mod
|
|
28
|
+
));
|
|
29
|
+
|
|
30
|
+
// package.json
|
|
31
|
+
var require_package = __commonJS({
|
|
32
|
+
"package.json"(exports2, module2) {
|
|
33
|
+
module2.exports = {
|
|
34
|
+
name: "veloria-ui",
|
|
35
|
+
version: "0.1.2",
|
|
36
|
+
private: false,
|
|
37
|
+
description: "Veloria UI \u2014 Build anything. Ship faster. 102 accessible, composable React components with Tailwind CSS and dark mode.",
|
|
38
|
+
keywords: [
|
|
39
|
+
"react",
|
|
40
|
+
"ui",
|
|
41
|
+
"components",
|
|
42
|
+
"veloria-ui",
|
|
43
|
+
"veloria-ui",
|
|
44
|
+
"design-system",
|
|
45
|
+
"accessible",
|
|
46
|
+
"aria",
|
|
47
|
+
"tailwind",
|
|
48
|
+
"tailwindcss",
|
|
49
|
+
"nextjs",
|
|
50
|
+
"typescript",
|
|
51
|
+
"dark-mode",
|
|
52
|
+
"radix-ui",
|
|
53
|
+
"component-library"
|
|
54
|
+
],
|
|
55
|
+
homepage: "https://veloria-ui.vercel.app/",
|
|
56
|
+
repository: {
|
|
57
|
+
type: "git",
|
|
58
|
+
url: "https://github.com/JohnDev19/Veloria-UI.git"
|
|
59
|
+
},
|
|
60
|
+
bugs: {
|
|
61
|
+
url: "https://github.com/JohnDev19/Veloria-UI/issues"
|
|
62
|
+
},
|
|
63
|
+
license: "MIT",
|
|
64
|
+
author: {
|
|
65
|
+
name: "JohnDev19",
|
|
66
|
+
url: "https://github.com/JohnDev19"
|
|
67
|
+
},
|
|
68
|
+
sideEffects: [
|
|
69
|
+
"**/*.css"
|
|
70
|
+
],
|
|
71
|
+
exports: {
|
|
72
|
+
".": {
|
|
73
|
+
types: "./dist/index.d.ts",
|
|
74
|
+
import: "./dist/index.mjs",
|
|
75
|
+
require: "./dist/index.js"
|
|
76
|
+
},
|
|
77
|
+
"./styles": "./dist/styles/atlas.css",
|
|
78
|
+
"./tailwind": "./dist/tailwind.js",
|
|
79
|
+
"./provider": {
|
|
80
|
+
types: "./dist/provider.d.ts",
|
|
81
|
+
import: "./dist/provider.mjs",
|
|
82
|
+
require: "./dist/provider.js"
|
|
83
|
+
},
|
|
84
|
+
"./cli": "./dist/cli/index.js"
|
|
85
|
+
},
|
|
86
|
+
main: "./dist/index.js",
|
|
87
|
+
module: "./dist/index.mjs",
|
|
88
|
+
types: "./dist/index.d.ts",
|
|
89
|
+
bin: {
|
|
90
|
+
"veloria-ui": "./dist/cli/index.js",
|
|
91
|
+
atlas: "./dist/cli/index.js"
|
|
92
|
+
},
|
|
93
|
+
files: [
|
|
94
|
+
"dist",
|
|
95
|
+
"src",
|
|
96
|
+
"README.md",
|
|
97
|
+
"CHANGELOG.md",
|
|
98
|
+
"LICENSE"
|
|
99
|
+
],
|
|
100
|
+
scripts: {
|
|
101
|
+
build: "tsup",
|
|
102
|
+
dev: "tsup --watch",
|
|
103
|
+
lint: "eslint src --ext .ts,.tsx",
|
|
104
|
+
typecheck: "tsc --noEmit",
|
|
105
|
+
clean: "rm -rf dist",
|
|
106
|
+
prepublishOnly: "npm run build"
|
|
107
|
+
},
|
|
108
|
+
peerDependencies: {
|
|
109
|
+
react: "^18.0.0",
|
|
110
|
+
"react-dom": "^18.0.0",
|
|
111
|
+
tailwindcss: ">=3.0.0"
|
|
112
|
+
},
|
|
113
|
+
peerDependenciesMeta: {
|
|
114
|
+
tailwindcss: { optional: true }
|
|
115
|
+
},
|
|
116
|
+
dependencies: {
|
|
117
|
+
"@radix-ui/react-accessible-icon": "^1.0.3",
|
|
118
|
+
"@radix-ui/react-alert-dialog": "^1.0.5",
|
|
119
|
+
"@radix-ui/react-aspect-ratio": "^1.0.3",
|
|
120
|
+
"@radix-ui/react-avatar": "^1.0.4",
|
|
121
|
+
"@radix-ui/react-checkbox": "^1.0.4",
|
|
122
|
+
"@radix-ui/react-collapsible": "^1.0.3",
|
|
123
|
+
"@radix-ui/react-context-menu": "^2.1.5",
|
|
124
|
+
"@radix-ui/react-dialog": "^1.0.5",
|
|
125
|
+
"@radix-ui/react-dropdown-menu": "^2.0.6",
|
|
126
|
+
"@radix-ui/react-hover-card": "^1.0.7",
|
|
127
|
+
"@radix-ui/react-label": "^2.0.2",
|
|
128
|
+
"@radix-ui/react-navigation-menu": "^1.1.4",
|
|
129
|
+
"@radix-ui/react-popover": "^1.0.7",
|
|
130
|
+
"@radix-ui/react-portal": "^1.0.4",
|
|
131
|
+
"@radix-ui/react-progress": "^1.0.3",
|
|
132
|
+
"@radix-ui/react-radio-group": "^1.1.3",
|
|
133
|
+
"@radix-ui/react-scroll-area": "^1.0.5",
|
|
134
|
+
"@radix-ui/react-select": "^2.0.0",
|
|
135
|
+
"@radix-ui/react-separator": "^1.0.3",
|
|
136
|
+
"@radix-ui/react-slider": "^1.1.2",
|
|
137
|
+
"@radix-ui/react-slot": "^1.0.2",
|
|
138
|
+
"@radix-ui/react-switch": "^1.0.3",
|
|
139
|
+
"@radix-ui/react-tabs": "^1.0.4",
|
|
140
|
+
"@radix-ui/react-toast": "^1.1.5",
|
|
141
|
+
"@radix-ui/react-toggle": "^1.0.3",
|
|
142
|
+
"@radix-ui/react-tooltip": "^1.0.7",
|
|
143
|
+
chalk: "^5.3.0",
|
|
144
|
+
"class-variance-authority": "^0.7.0",
|
|
145
|
+
clsx: "^2.1.0",
|
|
146
|
+
cmdk: "^0.2.0",
|
|
147
|
+
commander: "^11.1.0",
|
|
148
|
+
execa: "^8.0.1",
|
|
149
|
+
"fs-extra": "^11.2.0",
|
|
150
|
+
"lucide-react": "^0.309.0",
|
|
151
|
+
ora: "^7.0.1",
|
|
152
|
+
prompts: "^2.4.2",
|
|
153
|
+
"tailwind-merge": "^2.2.0"
|
|
154
|
+
},
|
|
155
|
+
devDependencies: {
|
|
156
|
+
"@types/fs-extra": "^11.0.4",
|
|
157
|
+
"@types/node": "^20.11.5",
|
|
158
|
+
"@types/prompts": "^2.4.9",
|
|
159
|
+
"@types/react": "^18.2.48",
|
|
160
|
+
"@types/react-dom": "^18.2.18",
|
|
161
|
+
prettier: "^3.2.4",
|
|
162
|
+
tailwindcss: "^3.4.1",
|
|
163
|
+
tsup: "^8.0.1",
|
|
164
|
+
typescript: "^5.3.3"
|
|
165
|
+
},
|
|
166
|
+
engines: {
|
|
167
|
+
node: ">=18.0.0"
|
|
168
|
+
}
|
|
169
|
+
};
|
|
170
|
+
}
|
|
171
|
+
});
|
|
172
|
+
|
|
173
|
+
// src/cli/index.ts
|
|
174
|
+
var import_path = __toESM(require("path"));
|
|
175
|
+
var import_commander = require("commander");
|
|
176
|
+
var import_chalk = __toESM(require("chalk"));
|
|
177
|
+
var import_ora = __toESM(require("ora"));
|
|
178
|
+
var import_prompts = __toESM(require("prompts"));
|
|
179
|
+
var import_fs_extra = __toESM(require("fs-extra"));
|
|
180
|
+
var import_execa = require("execa");
|
|
181
|
+
|
|
182
|
+
// src/cli/registry.ts
|
|
183
|
+
var REGISTRY = [
|
|
184
|
+
// Basic
|
|
185
|
+
{ name: "button", category: "basic", description: "Solid, outline, ghost, soft, link, danger variants. Loading state, icon slots.", deps: ["@radix-ui/react-slot", "class-variance-authority", "clsx", "tailwind-merge"] },
|
|
186
|
+
{ name: "icon-button", category: "basic", description: "Square or circular icon-only button.", deps: ["@radix-ui/react-slot", "class-variance-authority", "clsx", "tailwind-merge"] },
|
|
187
|
+
{ name: "link", category: "basic", description: "Anchor with external link indicator and underline control.", deps: ["@radix-ui/react-slot"] },
|
|
188
|
+
{ name: "badge", category: "basic", description: "Compact label \u2014 5 color variants, optional dot.", deps: ["class-variance-authority", "clsx", "tailwind-merge"] },
|
|
189
|
+
{ name: "avatar", category: "basic", description: "Image with fallback initials, status ring, 6 sizes.", deps: ["@radix-ui/react-avatar"] },
|
|
190
|
+
{ name: "avatar-group", category: "basic", description: "Stacked avatars with overflow count.", deps: ["@radix-ui/react-avatar"], registryDeps: ["avatar"] },
|
|
191
|
+
{ name: "divider", category: "basic", description: "Horizontal/vertical separator with optional center label.", deps: ["@radix-ui/react-separator"] },
|
|
192
|
+
{ name: "tag", category: "basic", description: "Closable colored tag with icon slot.", deps: [] },
|
|
193
|
+
{ name: "chip", category: "basic", description: "Toggleable chip with avatar/icon and remove button.", deps: [] },
|
|
194
|
+
{ name: "tooltip", category: "basic", description: "Radix tooltip, all four sides, configurable delay.", deps: ["@radix-ui/react-tooltip"] },
|
|
195
|
+
// Layout
|
|
196
|
+
{ name: "container", category: "layout", description: "Responsive max-width wrapper with padding control.", deps: [] },
|
|
197
|
+
{ name: "stack", category: "layout", description: "Flex column/row with gap, align, justify, divider.", deps: [] },
|
|
198
|
+
{ name: "grid", category: "layout", description: "CSS Grid with column/row/gap config.", deps: [] },
|
|
199
|
+
{ name: "flex", category: "layout", description: "Flex with full directional control.", deps: [] },
|
|
200
|
+
{ name: "section", category: "layout", description: "Semantic section with vertical padding presets.", deps: [] },
|
|
201
|
+
{ name: "spacer", category: "layout", description: "Invisible spacing element.", deps: [] },
|
|
202
|
+
{ name: "aspect-ratio", category: "layout", description: "Radix aspect-ratio container.", deps: ["@radix-ui/react-aspect-ratio"] },
|
|
203
|
+
{ name: "center", category: "layout", description: "Flex centering helper.", deps: [] },
|
|
204
|
+
{ name: "scroll-area", category: "layout", description: "Custom scrollbar via Radix ScrollArea.", deps: ["@radix-ui/react-scroll-area"] },
|
|
205
|
+
{ name: "masonry", category: "layout", description: "CSS multi-column masonry grid.", deps: [] },
|
|
206
|
+
// Navigation
|
|
207
|
+
{ name: "navbar", category: "navigation", description: "Sticky, glass-blur top bar.", deps: [] },
|
|
208
|
+
{ name: "sidebar", category: "navigation", description: "Collapsible side nav with width transition.", deps: [] },
|
|
209
|
+
{ name: "menu", category: "navigation", description: "Vertical nav menu with active/disabled states.", deps: [] },
|
|
210
|
+
{ name: "dropdown-menu", category: "navigation", description: "Full Radix Dropdown with all sub-primitives.", deps: ["@radix-ui/react-dropdown-menu"] },
|
|
211
|
+
{ name: "breadcrumb", category: "navigation", description: "Accessible trail with custom separator.", deps: [] },
|
|
212
|
+
{ name: "pagination", category: "navigation", description: "Page numbers with ellipsis and prev/next.", deps: [] },
|
|
213
|
+
{ name: "tabs", category: "navigation", description: "Line, pills, enclosed variants. Radix powered.", deps: ["@radix-ui/react-tabs"] },
|
|
214
|
+
{ name: "command-palette", category: "navigation", description: "\u2318K command palette.", deps: ["cmdk", "@radix-ui/react-dialog"], registryDeps: ["command-dialog"] },
|
|
215
|
+
{ name: "navigation-menu", category: "navigation", description: "Radix Navigation Menu for complex navbars.", deps: ["@radix-ui/react-navigation-menu"] },
|
|
216
|
+
{ name: "stepper", category: "navigation", description: "Horizontal/vertical multi-step indicator.", deps: [] },
|
|
217
|
+
// Forms
|
|
218
|
+
{ name: "input", category: "forms", description: "Left/right icon slots, sizes, error state.", deps: ["class-variance-authority"] },
|
|
219
|
+
{ name: "textarea", category: "forms", description: "Multi-line input with resize control.", deps: [] },
|
|
220
|
+
{ name: "select", category: "forms", description: "Full Radix Select with all sub-primitives.", deps: ["@radix-ui/react-select"] },
|
|
221
|
+
{ name: "checkbox", category: "forms", description: "With label, description, error state.", deps: ["@radix-ui/react-checkbox"] },
|
|
222
|
+
{ name: "radio-group", category: "forms", description: "Per-option labels and descriptions.", deps: ["@radix-ui/react-radio-group"] },
|
|
223
|
+
{ name: "switch", category: "forms", description: "Three sizes, label, description.", deps: ["@radix-ui/react-switch"] },
|
|
224
|
+
{ name: "slider", category: "forms", description: "Single-thumb range slider.", deps: ["@radix-ui/react-slider"] },
|
|
225
|
+
{ name: "range-slider", category: "forms", description: "Dual-thumb slider.", deps: ["@radix-ui/react-slider"], registryDeps: ["slider"] },
|
|
226
|
+
{ name: "date-picker", category: "forms", description: "Native date input wrapper.", deps: [] },
|
|
227
|
+
{ name: "time-picker", category: "forms", description: "Native time input wrapper.", deps: [] },
|
|
228
|
+
// Advanced Forms
|
|
229
|
+
{ name: "file-upload", category: "advanced-forms", description: "Drag-and-drop zone with click-to-upload fallback.", deps: [] },
|
|
230
|
+
{ name: "otp-input", category: "advanced-forms", description: "PIN/OTP with auto-advance and paste support.", deps: [] },
|
|
231
|
+
{ name: "color-picker", category: "advanced-forms", description: "Swatches + hex input.", deps: [] },
|
|
232
|
+
{ name: "search-input", category: "advanced-forms", description: "Search with loading state and clear button.", deps: [] },
|
|
233
|
+
{ name: "password-input", category: "advanced-forms", description: "Password with show/hide toggle.", deps: [] },
|
|
234
|
+
{ name: "combobox", category: "advanced-forms", description: "Searchable single-value select.", deps: [] },
|
|
235
|
+
{ name: "multi-select", category: "advanced-forms", description: "Multi-value select with chips.", deps: [] },
|
|
236
|
+
{ name: "form-field", category: "advanced-forms", description: "Form field wrapper with spacing.", deps: [] },
|
|
237
|
+
{ name: "form-label", category: "advanced-forms", description: "Label with required/optional indicators.", deps: [] },
|
|
238
|
+
{ name: "form-error", category: "advanced-forms", description: "Accessible error message.", deps: [] },
|
|
239
|
+
// Data Display
|
|
240
|
+
{ name: "card", category: "data-display", description: "Surface with header/content/footer slots. 5 variants.", deps: [] },
|
|
241
|
+
{ name: "table", category: "data-display", description: "Full HTML table system.", deps: [] },
|
|
242
|
+
{ name: "data-table", category: "data-display", description: "Sortable data table with loading and empty states.", deps: [] },
|
|
243
|
+
{ name: "list", category: "data-display", description: "Simple, bordered, and divided lists.", deps: [] },
|
|
244
|
+
{ name: "list-item", category: "data-display", description: "List item with icon and extra slot.", deps: [] },
|
|
245
|
+
{ name: "statistic", category: "data-display", description: "Key metric with trend indicator.", deps: [] },
|
|
246
|
+
{ name: "timeline", category: "data-display", description: "Vertical events with color-coded icons.", deps: [] },
|
|
247
|
+
{ name: "calendar", category: "data-display", description: "Month picker with highlighted dates.", deps: [] },
|
|
248
|
+
{ name: "chart", category: "data-display", description: "Chart wrapper \u2014 bring your own chart library.", deps: [] },
|
|
249
|
+
{ name: "code-block", category: "data-display", description: "Code display with copy button and line numbers.", deps: [] },
|
|
250
|
+
// Feedback
|
|
251
|
+
{ name: "alert", category: "feedback", description: "Info/success/warning/danger with optional dismiss.", deps: ["class-variance-authority"] },
|
|
252
|
+
{ name: "toast", category: "feedback", description: "Radix Toast with all sub-primitives.", deps: ["@radix-ui/react-toast"] },
|
|
253
|
+
{ name: "snackbar", category: "feedback", description: "Positioned message with action.", deps: [] },
|
|
254
|
+
{ name: "progress", category: "feedback", description: "Linear bar with color variants.", deps: ["@radix-ui/react-progress"] },
|
|
255
|
+
{ name: "circular-progress", category: "feedback", description: "SVG ring with indeterminate mode.", deps: [] },
|
|
256
|
+
{ name: "skeleton", category: "feedback", description: "Pulse placeholder for text, rect, circle.", deps: [] },
|
|
257
|
+
{ name: "loading-spinner", category: "feedback", description: "Accessible SVG spinner.", deps: [] },
|
|
258
|
+
{ name: "empty-state", category: "feedback", description: "Icon + title + description + action.", deps: [] },
|
|
259
|
+
{ name: "status-indicator", category: "feedback", description: "Online/offline/busy/away dot with pulse.", deps: [] },
|
|
260
|
+
{ name: "notification", category: "feedback", description: "Notification item with avatar, timestamp, unread dot.", deps: [] },
|
|
261
|
+
// Overlay
|
|
262
|
+
{ name: "modal", category: "overlay", description: "Preset dialog \u2014 sm to full size variants.", deps: ["@radix-ui/react-dialog"] },
|
|
263
|
+
{ name: "dialog", category: "overlay", description: "Full Radix Dialog primitive suite.", deps: ["@radix-ui/react-dialog"] },
|
|
264
|
+
{ name: "drawer", category: "overlay", description: "Slides in from any edge.", deps: ["@radix-ui/react-dialog"] },
|
|
265
|
+
{ name: "popover", category: "overlay", description: "Floating panel.", deps: ["@radix-ui/react-popover"] },
|
|
266
|
+
{ name: "hover-card", category: "overlay", description: "Rich hover preview.", deps: ["@radix-ui/react-hover-card"] },
|
|
267
|
+
{ name: "context-menu", category: "overlay", description: "Right-click menu.", deps: ["@radix-ui/react-context-menu"] },
|
|
268
|
+
{ name: "command-dialog", category: "overlay", description: "\u2318K palette.", deps: ["cmdk", "@radix-ui/react-dialog"] },
|
|
269
|
+
{ name: "sheet", category: "overlay", description: "Drawer alias.", deps: ["@radix-ui/react-dialog"], registryDeps: ["drawer"] },
|
|
270
|
+
{ name: "lightbox", category: "overlay", description: "Full-screen image overlay.", deps: ["@radix-ui/react-dialog"] },
|
|
271
|
+
{ name: "image-viewer", category: "overlay", description: "Lightbox alias.", deps: ["@radix-ui/react-dialog"], registryDeps: ["lightbox"] },
|
|
272
|
+
// Media
|
|
273
|
+
{ name: "image", category: "media", description: "Image with fallback, aspect ratio, fit, caption.", deps: [] },
|
|
274
|
+
{ name: "video-player", category: "media", description: "HTML5 video with captions/subtitles support.", deps: [] },
|
|
275
|
+
{ name: "audio-player", category: "media", description: "Custom audio UI with seek bar, cover art.", deps: [] },
|
|
276
|
+
{ name: "carousel", category: "media", description: "Autoplay, dots, arrows, loop, slidesPerView.", deps: [] },
|
|
277
|
+
{ name: "gallery", category: "media", description: "Responsive image grid with click handler.", deps: [] },
|
|
278
|
+
// Utility
|
|
279
|
+
{ name: "theme-switcher", category: "utility", description: "Icon / toggle / select variants.", deps: [] },
|
|
280
|
+
{ name: "copy-button", category: "utility", description: "Icon or labelled copy button with success feedback.", deps: [] },
|
|
281
|
+
{ name: "keyboard-shortcut", category: "utility", description: "Styled <kbd> shortcut display.", deps: [] },
|
|
282
|
+
{ name: "resizable-panel", category: "utility", description: "Drag-to-resize panel with min/max constraints.", deps: [] },
|
|
283
|
+
{ name: "drag-drop-area", category: "utility", description: "Accessible file drop zone.", deps: [] }
|
|
284
|
+
];
|
|
285
|
+
var COMPONENTS_BY_NAME = new Map(REGISTRY.map((c) => [c.name, c]));
|
|
286
|
+
var CATEGORIES = [
|
|
287
|
+
"basic",
|
|
288
|
+
"layout",
|
|
289
|
+
"navigation",
|
|
290
|
+
"forms",
|
|
291
|
+
"advanced-forms",
|
|
292
|
+
"data-display",
|
|
293
|
+
"feedback",
|
|
294
|
+
"overlay",
|
|
295
|
+
"media",
|
|
296
|
+
"utility"
|
|
297
|
+
];
|
|
298
|
+
|
|
299
|
+
// src/cli/index.ts
|
|
300
|
+
var PKG_VERSION = require_package().version;
|
|
301
|
+
var banner = `
|
|
302
|
+
${import_chalk.default.bold.blue(" \u2566 \u2566\u2554\u2550\u2557\u2566 \u2554\u2550\u2557\u2566\u2550\u2557\u2566\u2554\u2550\u2557")}
|
|
303
|
+
${import_chalk.default.bold.blue(" \u255A\u2557\u2554\u255D\u2551\u2563 \u2551 \u2551 \u2551\u2560\u2566\u255D\u2551\u2560\u2550\u2563")}
|
|
304
|
+
${import_chalk.default.bold.blue(" \u255A\u255D \u255A\u2550\u255D\u2569\u2550\u255D\u255A\u2550\u255D\u2569\u255A\u2550\u2569\u2569 \u2569")}
|
|
305
|
+
${import_chalk.default.dim("Build anything. Ship faster.")}
|
|
306
|
+
${import_chalk.default.dim("by JohnDev19 \xB7 https://github.com/JohnDev19/Veloria-UI")}
|
|
307
|
+
`;
|
|
308
|
+
var program = new import_commander.Command();
|
|
309
|
+
program.name("veloria-ui").description("veloria-ui CLI \u2014 copy components into your project").version(PKG_VERSION, "-v, --version").addHelpText("before", banner);
|
|
310
|
+
program.command("init").description("Set up veloria-ui in your project").option("--typescript", "Use TypeScript", true).option("--tailwind", "Configure Tailwind", true).option("--no-install", "Skip dependency install").option("-y, --yes", "Skip all prompts, use defaults").action(async (opts) => {
|
|
311
|
+
console.log(import_chalk.default.bold.blue("\n Veloria UI Init\n") + import_chalk.default.dim(" Let's get you set up\u2026\n"));
|
|
312
|
+
const cwd = process.cwd();
|
|
313
|
+
const pkgPath = import_path.default.join(cwd, "package.json");
|
|
314
|
+
if (!import_fs_extra.default.existsSync(pkgPath)) {
|
|
315
|
+
console.error(import_chalk.default.red("\n No package.json found. Run from your project root.\n"));
|
|
316
|
+
process.exit(1);
|
|
317
|
+
}
|
|
318
|
+
const pkg = import_fs_extra.default.readJsonSync(pkgPath);
|
|
319
|
+
const isNext = !!(pkg.dependencies?.next || pkg.devDependencies?.next);
|
|
320
|
+
const answers = opts.yes ? { componentsDir: "components/ui", cssPath: isNext ? "app/globals.css" : "src/index.css", pm: detectPM(cwd) } : await (0, import_prompts.default)([
|
|
321
|
+
{ type: "text", name: "componentsDir", message: "Where should components go?", initial: "components/ui" },
|
|
322
|
+
{ type: "text", name: "cssPath", message: "Path to your global CSS file?", initial: isNext ? "app/globals.css" : "src/index.css" },
|
|
323
|
+
{
|
|
324
|
+
type: "select",
|
|
325
|
+
name: "pm",
|
|
326
|
+
message: "Package manager?",
|
|
327
|
+
choices: [
|
|
328
|
+
{ title: "npm", value: "npm" },
|
|
329
|
+
{ title: "pnpm", value: "pnpm" },
|
|
330
|
+
{ title: "yarn", value: "yarn" },
|
|
331
|
+
{ title: "bun", value: "bun" }
|
|
332
|
+
]
|
|
333
|
+
}
|
|
334
|
+
]);
|
|
335
|
+
if (!answers.componentsDir) return;
|
|
336
|
+
import_fs_extra.default.writeJsonSync(import_path.default.join(cwd, "atlas.config.json"), {
|
|
337
|
+
$schema: "https://veloria-ui.vercel.app/schema.json",
|
|
338
|
+
style: "default",
|
|
339
|
+
typescript: opts.typescript ?? true,
|
|
340
|
+
tailwind: { config: "tailwind.config.ts", css: answers.cssPath, baseColor: "slate", cssVariables: true },
|
|
341
|
+
aliases: { components: `@/${answers.componentsDir}`, utils: "@/lib/utils" }
|
|
342
|
+
}, { spaces: 2 });
|
|
343
|
+
console.log(import_chalk.default.green(" \u2713 Created atlas.config.json"));
|
|
344
|
+
const utilsPath = import_path.default.join(cwd, "lib", "utils.ts");
|
|
345
|
+
if (!import_fs_extra.default.existsSync(utilsPath)) {
|
|
346
|
+
await import_fs_extra.default.ensureDir(import_path.default.dirname(utilsPath));
|
|
347
|
+
await import_fs_extra.default.writeFile(
|
|
348
|
+
utilsPath,
|
|
349
|
+
`import { type ClassValue, clsx } from "clsx";
|
|
350
|
+
import { twMerge } from "tailwind-merge";
|
|
351
|
+
|
|
352
|
+
export function cn(...inputs: ClassValue[]) {
|
|
353
|
+
return twMerge(clsx(inputs));
|
|
354
|
+
}
|
|
355
|
+
`
|
|
356
|
+
);
|
|
357
|
+
console.log(import_chalk.default.green(" \u2713 Created lib/utils.ts"));
|
|
358
|
+
}
|
|
359
|
+
if (opts.install !== false) {
|
|
360
|
+
const pm = answers.pm;
|
|
361
|
+
const spinner = (0, import_ora.default)(`Installing core deps with ${pm}\u2026`).start();
|
|
362
|
+
try {
|
|
363
|
+
const deps = ["clsx", "tailwind-merge", "class-variance-authority", "@radix-ui/react-slot"];
|
|
364
|
+
const cmd = pm === "pnpm" ? ["pnpm", "add", ...deps] : pm === "bun" ? ["bun", "add", ...deps] : pm === "yarn" ? ["yarn", "add", ...deps] : ["npm", "install", ...deps];
|
|
365
|
+
await (0, import_execa.execa)(cmd[0], cmd.slice(1), { cwd });
|
|
366
|
+
spinner.succeed(import_chalk.default.green("Core deps installed"));
|
|
367
|
+
} catch {
|
|
368
|
+
spinner.warn(import_chalk.default.yellow("Auto-install failed \u2014 run manually:"));
|
|
369
|
+
console.log(import_chalk.default.dim(" npm install clsx tailwind-merge class-variance-authority @radix-ui/react-slot\n"));
|
|
370
|
+
}
|
|
371
|
+
}
|
|
372
|
+
console.log(`
|
|
373
|
+
${import_chalk.default.bold.green(" Veloria UI is ready!")}
|
|
374
|
+
|
|
375
|
+
${import_chalk.default.dim("Next steps:")}
|
|
376
|
+
${import_chalk.default.cyan("1.")} Add components: ${import_chalk.default.bold("npx veloria-ui add button card modal")}
|
|
377
|
+
${import_chalk.default.cyan("2.")} Browse all: ${import_chalk.default.bold("npx veloria-ui list")}
|
|
378
|
+
${import_chalk.default.cyan("3.")} Docs: ${import_chalk.default.bold("https://veloria-ui.vercel.app/")}
|
|
379
|
+
${import_chalk.default.cyan("4.")} Issues: ${import_chalk.default.bold("https://github.com/JohnDev19/Veloria-UI/issues")}
|
|
380
|
+
`);
|
|
381
|
+
});
|
|
382
|
+
program.command("add [components...]").alias("a").description("Copy one or more components into your project").option("-d, --dir <path>", "Output directory", "components/ui").option("--overwrite", "Replace existing files").option("--no-install", "Skip npm dep install").action(async (components, opts) => {
|
|
383
|
+
const cwd = process.cwd();
|
|
384
|
+
if (!components?.length) {
|
|
385
|
+
console.log(import_chalk.default.red("\n Specify at least one component.\n"));
|
|
386
|
+
console.log(` ${import_chalk.default.dim("Example:")} ${import_chalk.default.cyan("npx veloria-ui add button card modal\n")}`);
|
|
387
|
+
process.exit(1);
|
|
388
|
+
}
|
|
389
|
+
const toAdd = /* @__PURE__ */ new Set();
|
|
390
|
+
function resolve(name) {
|
|
391
|
+
const key = name.toLowerCase().replace(/([a-z])([A-Z])/g, "$1-$2").toLowerCase();
|
|
392
|
+
const meta = COMPONENTS_BY_NAME.get(key) || COMPONENTS_BY_NAME.get(name);
|
|
393
|
+
if (!meta) {
|
|
394
|
+
console.error(import_chalk.default.red(`
|
|
395
|
+
"${name}" not found in the registry.
|
|
396
|
+
`));
|
|
397
|
+
console.log(` Run ${import_chalk.default.cyan("npx veloria-ui list")} to see what's available.
|
|
398
|
+
`);
|
|
399
|
+
return;
|
|
400
|
+
}
|
|
401
|
+
toAdd.add(meta.name);
|
|
402
|
+
meta.registryDeps?.forEach(resolve);
|
|
403
|
+
}
|
|
404
|
+
components.forEach(resolve);
|
|
405
|
+
if (!toAdd.size) return;
|
|
406
|
+
const configPath = import_path.default.join(cwd, "atlas.config.json");
|
|
407
|
+
const config = import_fs_extra.default.existsSync(configPath) ? import_fs_extra.default.readJsonSync(configPath) : null;
|
|
408
|
+
const aliasDir = config?.aliases?.components?.replace(/^@\//, "");
|
|
409
|
+
const targetDir = import_path.default.join(cwd, opts.dir ?? aliasDir ?? "components/ui");
|
|
410
|
+
console.log(import_chalk.default.bold.blue("\n Veloria UI Add\n") + import_chalk.default.dim(` Adding: ${[...toAdd].join(", ")}
|
|
411
|
+
`));
|
|
412
|
+
const allDeps = /* @__PURE__ */ new Set();
|
|
413
|
+
for (const name of toAdd) COMPONENTS_BY_NAME.get(name).deps.forEach((d) => allDeps.add(d));
|
|
414
|
+
for (const name of toAdd) {
|
|
415
|
+
const spinner = (0, import_ora.default)(`Adding ${import_chalk.default.bold(name)}`).start();
|
|
416
|
+
const pascal = name.split("-").map((p) => p[0].toUpperCase() + p.slice(1)).join("");
|
|
417
|
+
const dir = import_path.default.join(targetDir, name);
|
|
418
|
+
await import_fs_extra.default.ensureDir(dir);
|
|
419
|
+
const file = import_path.default.join(dir, "index.tsx");
|
|
420
|
+
if (import_fs_extra.default.existsSync(file) && !opts.overwrite) {
|
|
421
|
+
spinner.warn(import_chalk.default.yellow(`${name} already exists (--overwrite to replace)`));
|
|
422
|
+
continue;
|
|
423
|
+
}
|
|
424
|
+
await import_fs_extra.default.writeFile(
|
|
425
|
+
file,
|
|
426
|
+
`/**
|
|
427
|
+
* Veloria UI \u2014 ${pascal}
|
|
428
|
+
*
|
|
429
|
+
* Added by the veloria-ui CLI. This file is yours \u2014 edit it however you want.
|
|
430
|
+
* Re-export from veloria-ui to stay in sync, or paste the full source here
|
|
431
|
+
* to customise the internals.
|
|
432
|
+
*
|
|
433
|
+
* Docs: https://veloria-ui.vercel.app/components/${name}
|
|
434
|
+
* Source: https://github.com/JohnDev19/Veloria-UI
|
|
435
|
+
*/
|
|
436
|
+
|
|
437
|
+
export { ${pascal} } from "veloria-ui";
|
|
438
|
+
export type { ${pascal}Props } from "veloria-ui";
|
|
439
|
+
`
|
|
440
|
+
);
|
|
441
|
+
spinner.succeed(import_chalk.default.green(`${name} \u2192 ${import_path.default.relative(cwd, file)}`));
|
|
442
|
+
}
|
|
443
|
+
if (opts.install !== false && allDeps.size > 0) {
|
|
444
|
+
const pm = detectPM(cwd);
|
|
445
|
+
const spinner = (0, import_ora.default)(`Installing ${allDeps.size} package(s)\u2026`).start();
|
|
446
|
+
try {
|
|
447
|
+
const deps = [...allDeps];
|
|
448
|
+
const cmd = pm === "pnpm" ? ["pnpm", "add", ...deps] : pm === "bun" ? ["bun", "add", ...deps] : pm === "yarn" ? ["yarn", "add", ...deps] : ["npm", "install", ...deps];
|
|
449
|
+
await (0, import_execa.execa)(cmd[0], cmd.slice(1), { cwd });
|
|
450
|
+
spinner.succeed(import_chalk.default.green(`Installed: ${deps.join(", ")}`));
|
|
451
|
+
} catch {
|
|
452
|
+
spinner.warn(import_chalk.default.yellow("Auto-install failed \u2014 run manually:"));
|
|
453
|
+
console.log(import_chalk.default.dim(` npm install ${[...allDeps].join(" ")}
|
|
454
|
+
`));
|
|
455
|
+
}
|
|
456
|
+
}
|
|
457
|
+
const exNames = [...toAdd].map((n) => n.split("-").map((p) => p[0].toUpperCase() + p.slice(1)).join("")).join(", ");
|
|
458
|
+
console.log(`
|
|
459
|
+
${import_chalk.default.bold.green(" Done!")} ${import_path.default.relative(cwd, targetDir)}
|
|
460
|
+
|
|
461
|
+
${import_chalk.default.cyan(`import { ${exNames} } from "@/components/ui/${[...toAdd][0]}"`)}
|
|
462
|
+
`);
|
|
463
|
+
});
|
|
464
|
+
program.command("list").alias("ls").description("List all available components").option("-c, --category <category>", "Filter by category").action((opts) => {
|
|
465
|
+
const filterCat = opts.category?.toLowerCase();
|
|
466
|
+
console.log(import_chalk.default.bold.blue("\n veloria-ui Components\n"));
|
|
467
|
+
const cats = filterCat ? [filterCat] : CATEGORIES;
|
|
468
|
+
for (const cat of cats) {
|
|
469
|
+
const items = REGISTRY.filter((c) => c.category === cat);
|
|
470
|
+
if (!items.length) continue;
|
|
471
|
+
const label = cat.replace("-", " ").replace(/^\w/, (c) => c.toUpperCase());
|
|
472
|
+
console.log(import_chalk.default.bold(` ${label} (${items.length})`));
|
|
473
|
+
for (const c of items) {
|
|
474
|
+
console.log(` ${import_chalk.default.cyan(c.name.padEnd(22))} ${import_chalk.default.dim(c.description)}`);
|
|
475
|
+
}
|
|
476
|
+
console.log();
|
|
477
|
+
}
|
|
478
|
+
console.log(import_chalk.default.dim(` ${REGISTRY.length} components total
|
|
479
|
+
`) + import_chalk.default.dim(" Add one: ") + import_chalk.default.cyan("npx veloria-ui add <name>\n"));
|
|
480
|
+
});
|
|
481
|
+
program.command("diff [component]").description("Compare your local copy to the latest version").action((component) => {
|
|
482
|
+
if (!component) {
|
|
483
|
+
console.log(import_chalk.default.dim("\n Usage: npx veloria-ui diff <component>\n"));
|
|
484
|
+
return;
|
|
485
|
+
}
|
|
486
|
+
console.log(import_chalk.default.bold.blue(`
|
|
487
|
+
diff: ${component}
|
|
488
|
+
`) + import_chalk.default.dim(" Comparing local copy to latest in the veloria-ui registry\u2026\n"));
|
|
489
|
+
console.log(import_chalk.default.yellow(" \u26A0 Registry diff isn't wired up yet."));
|
|
490
|
+
console.log(import_chalk.default.dim(` Check the latest source at:
|
|
491
|
+
`) + import_chalk.default.cyan(` https://github.com/JohnDev19/Veloria-UI/tree/main/src/components
|
|
492
|
+
`));
|
|
493
|
+
});
|
|
494
|
+
program.on("command:*", (operands) => {
|
|
495
|
+
console.error(import_chalk.default.red(`
|
|
496
|
+
Unknown command: "${operands[0]}"
|
|
497
|
+
`));
|
|
498
|
+
program.help();
|
|
499
|
+
process.exit(1);
|
|
500
|
+
});
|
|
501
|
+
program.parse(process.argv);
|
|
502
|
+
if (!process.argv.slice(2).length) {
|
|
503
|
+
console.log(banner);
|
|
504
|
+
program.help();
|
|
505
|
+
}
|
|
506
|
+
function detectPM(cwd) {
|
|
507
|
+
if (import_fs_extra.default.existsSync(import_path.default.join(cwd, "bun.lockb"))) return "bun";
|
|
508
|
+
if (import_fs_extra.default.existsSync(import_path.default.join(cwd, "pnpm-lock.yaml"))) return "pnpm";
|
|
509
|
+
if (import_fs_extra.default.existsSync(import_path.default.join(cwd, "yarn.lock"))) return "yarn";
|
|
510
|
+
return "npm";
|
|
511
|
+
}
|