@srcroot/ui 0.0.55 → 0.0.58
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/README.md +151 -151
- package/dist/index.d.ts +0 -0
- package/dist/index.js +120 -93
- package/package.json +7 -2
- package/src/registry/analytics/google-analytics.tsx +36 -39
- package/src/registry/analytics/google-tag-manager.tsx +62 -65
- package/src/registry/analytics/meta-pixel.tsx +44 -47
- package/src/registry/analytics/microsoft-clarity.tsx +31 -34
- package/src/registry/analytics/tiktok-pixel.tsx +34 -37
- package/src/registry/lib/utils.ts +0 -0
- package/src/registry/themes/v3/blue.css +157 -157
- package/src/registry/themes/v3/glass.css +153 -153
- package/src/registry/themes/v3/gray.css +157 -157
- package/src/registry/themes/v3/green.css +157 -157
- package/src/registry/themes/v3/neutral.css +157 -157
- package/src/registry/themes/v3/orange.css +157 -157
- package/src/registry/themes/v3/rose.css +157 -157
- package/src/registry/themes/v3/slate.css +157 -157
- package/src/registry/themes/v3/stone.css +157 -157
- package/src/registry/themes/v3/violet.css +186 -186
- package/src/registry/themes/v3/zinc.css +157 -157
- package/src/registry/themes/v4/blue.css +184 -184
- package/src/registry/themes/v4/glass.css +180 -180
- package/src/registry/themes/v4/gray.css +184 -184
- package/src/registry/themes/v4/green.css +184 -184
- package/src/registry/themes/v4/neutral.css +184 -184
- package/src/registry/themes/v4/orange.css +184 -184
- package/src/registry/themes/v4/rose.css +184 -184
- package/src/registry/themes/v4/slate.css +184 -184
- package/src/registry/themes/v4/stone.css +184 -184
- package/src/registry/themes/v4/violet.css +184 -184
- package/src/registry/themes/v4/zinc.css +184 -184
- package/src/registry/ui/accordion.tsx +164 -165
- package/src/registry/ui/alert-dialog.tsx +213 -214
- package/src/registry/ui/alert.tsx +73 -76
- package/src/registry/ui/aspect-ratio.tsx +44 -47
- package/src/registry/ui/avatar.tsx +96 -97
- package/src/registry/ui/badge.tsx +52 -55
- package/src/registry/ui/breadcrumb.tsx +147 -150
- package/src/registry/ui/button-group.tsx +64 -67
- package/src/registry/ui/button.tsx +71 -72
- package/src/registry/ui/calendar.tsx +514 -515
- package/src/registry/ui/card.tsx +88 -91
- package/src/registry/ui/carousel.tsx +214 -214
- package/src/registry/ui/chart.tsx +373 -373
- package/src/registry/ui/chatbot.tsx +86 -13
- package/src/registry/ui/checkbox.tsx +93 -94
- package/src/registry/ui/collapsible.tsx +107 -108
- package/src/registry/ui/combobox.tsx +171 -171
- package/src/registry/ui/command.tsx +300 -300
- package/src/registry/ui/container.tsx +44 -47
- package/src/registry/ui/context-menu.tsx +221 -221
- package/src/registry/ui/date-picker.tsx +228 -228
- package/src/registry/ui/dialog.tsx +269 -270
- package/src/registry/ui/drawer.tsx +10 -4
- package/src/registry/ui/dropdown-menu.tsx +529 -530
- package/src/registry/ui/empty-state.tsx +0 -2
- package/src/registry/ui/file-upload.tsx +0 -0
- package/src/registry/ui/floating-dock.tsx +0 -0
- package/src/registry/ui/form-field.tsx +91 -94
- package/src/registry/ui/google-analytics.tsx +38 -0
- package/src/registry/ui/google-tag-manager.tsx +64 -0
- package/src/registry/ui/hover-card.tsx +223 -223
- package/src/registry/ui/image.tsx +144 -147
- package/src/registry/ui/input-group.tsx +82 -85
- package/src/registry/ui/input.tsx +125 -125
- package/src/registry/ui/kbd.tsx +60 -63
- package/src/registry/ui/label.tsx +36 -37
- package/src/registry/ui/loading-spinner.tsx +108 -111
- package/src/registry/ui/map.tsx +0 -0
- package/src/registry/ui/marquee.tsx +2 -0
- package/src/registry/ui/menubar.tsx +246 -246
- package/src/registry/ui/meta-pixel.tsx +46 -0
- package/src/registry/ui/microsoft-clarity.tsx +33 -0
- package/src/registry/ui/native-select.tsx +49 -52
- package/src/registry/ui/otp-input.tsx +163 -155
- package/src/registry/ui/pagination.tsx +149 -152
- package/src/registry/ui/patterns.tsx +28 -0
- package/src/registry/ui/popover.tsx +226 -227
- package/src/registry/ui/progress.tsx +51 -52
- package/src/registry/ui/radio.tsx +99 -102
- package/src/registry/ui/resizable.tsx +314 -314
- package/src/registry/ui/scroll-animation.tsx +45 -0
- package/src/registry/ui/scroll-area.tsx +121 -122
- package/src/registry/ui/scroll-to-top.tsx +0 -0
- package/src/registry/ui/search.tsx +162 -150
- package/src/registry/ui/select.tsx +292 -293
- package/src/registry/ui/separator.tsx +46 -47
- package/src/registry/ui/sheet.tsx +6 -3
- package/src/registry/ui/sidebar.tsx +628 -628
- package/src/registry/ui/skeleton.tsx +26 -29
- package/src/registry/ui/slider.tsx +196 -197
- package/src/registry/ui/slot.tsx +69 -72
- package/src/registry/ui/star-rating.tsx +146 -134
- package/src/registry/ui/switch.tsx +72 -73
- package/src/registry/ui/table-of-contents.tsx +96 -96
- package/src/registry/ui/table.tsx +138 -139
- package/src/registry/ui/tabs.tsx +124 -125
- package/src/registry/ui/text.tsx +61 -64
- package/src/registry/ui/textarea.tsx +41 -42
- package/src/registry/ui/theme-switcher.tsx +66 -66
- package/src/registry/ui/tiktok-pixel.tsx +36 -0
- package/src/registry/ui/toast.tsx +97 -98
- package/src/registry/ui/toggle-group.tsx +129 -129
- package/src/registry/ui/toggle.tsx +72 -72
- package/src/registry/ui/tooltip.tsx +143 -144
- package/src/registry/ui/whatsapp.tsx +0 -0
package/README.md
CHANGED
|
@@ -1,151 +1,151 @@
|
|
|
1
|
-
# @srcroot/ui
|
|
2
|
-
|
|
3
|
-
A UI library with polymorphic, accessible React components.
|
|
4
|
-
This library provides a collection of re-usable components that you can copy and paste into your apps.
|
|
5
|
-
|
|
6
|
-
## Features
|
|
7
|
-
|
|
8
|
-
- **Polymorphic**: Most components support an `as` prop (e.g., render a `Button` as an `a` tag).
|
|
9
|
-
- **Accessible**: Built on standard HTML elements and WAI-ARIA patterns.
|
|
10
|
-
- **Copy/Paste**: Not a dependency you install, but code you own.
|
|
11
|
-
- **Styled**: Beautiful defaults using Tailwind CSS and `class-variance-authority`.
|
|
12
|
-
|
|
13
|
-
## Installation
|
|
14
|
-
|
|
15
|
-
This library is distributed via a CLI that initializes your project and adds components directly to your source code.
|
|
16
|
-
|
|
17
|
-
### 1. Initialize
|
|
18
|
-
|
|
19
|
-
Run the `init` command to set up the necessary dependencies and structural files (like `cn` utility) in your project.
|
|
20
|
-
|
|
21
|
-
```bash
|
|
22
|
-
npx @srcroot/ui init
|
|
23
|
-
```
|
|
24
|
-
|
|
25
|
-
This will ask a few questions to configure your project structure (e.g., where to put components).
|
|
26
|
-
|
|
27
|
-
### 2. Add Components
|
|
28
|
-
|
|
29
|
-
Use the `add` command to install components. You can do this in three ways:
|
|
30
|
-
|
|
31
|
-
**Interactive Mode:**
|
|
32
|
-
Run without arguments to select components from a list.
|
|
33
|
-
```bash
|
|
34
|
-
npx @srcroot/ui add
|
|
35
|
-
```
|
|
36
|
-
|
|
37
|
-
**Specific Components:**
|
|
38
|
-
Add one or more components by name.
|
|
39
|
-
```bash
|
|
40
|
-
npx @srcroot/ui add button card input
|
|
41
|
-
```
|
|
42
|
-
|
|
43
|
-
**Add All:**
|
|
44
|
-
Install every available component at once.
|
|
45
|
-
```bash
|
|
46
|
-
npx @srcroot/ui add --all
|
|
47
|
-
```
|
|
48
|
-
|
|
49
|
-
This will copy the component files to your `components/ui` directory and install any necessary peer dependencies (like `react-icons` or `clsx`).
|
|
50
|
-
|
|
51
|
-
### 3. Usage
|
|
52
|
-
|
|
53
|
-
Import components directly from your project folder:
|
|
54
|
-
|
|
55
|
-
```tsx
|
|
56
|
-
import { Button } from "@/components/ui/button"
|
|
57
|
-
|
|
58
|
-
export default function Home() {
|
|
59
|
-
return (
|
|
60
|
-
<Button variant="destructive" onClick={() => alert("Clicked!")}>
|
|
61
|
-
Click Me
|
|
62
|
-
</Button>
|
|
63
|
-
)
|
|
64
|
-
}
|
|
65
|
-
```
|
|
66
|
-
|
|
67
|
-
## Available Components
|
|
68
|
-
|
|
69
|
-
run `npx @srcroot/ui list` to see all available components.
|
|
70
|
-
|
|
71
|
-
### Core
|
|
72
|
-
- `button` - Polymorphic button with variants.
|
|
73
|
-
- `badge` - Status indicators.
|
|
74
|
-
- `avatar` - User profile images with fallbacks.
|
|
75
|
-
- `separator` - Visual divider.
|
|
76
|
-
- `button-group` - Attached or spaced button sets.
|
|
77
|
-
|
|
78
|
-
### Forms
|
|
79
|
-
- `input` - Basic text input.
|
|
80
|
-
- `textarea` - Multi-line text input.
|
|
81
|
-
- `checkbox` - Toggle selection.
|
|
82
|
-
- `radio` - Single selection from list.
|
|
83
|
-
- `switch` - Toggle switch.
|
|
84
|
-
- `select` - Dropdown selection.
|
|
85
|
-
- `slider` - Range input.
|
|
86
|
-
- `otp-input` - One-time password verification.
|
|
87
|
-
- `search` - Search input with debounce support.
|
|
88
|
-
- `calendar` - Date and range picker.
|
|
89
|
-
|
|
90
|
-
### Layout
|
|
91
|
-
- `card` - Content container with header/content/footer.
|
|
92
|
-
- `container` - Centered layout wrapper.
|
|
93
|
-
- `aspect-ratio` - Maintain element proportions.
|
|
94
|
-
|
|
95
|
-
### Data Display
|
|
96
|
-
- `text` - Polymorphic typography component.
|
|
97
|
-
- `label` - Accessible form label.
|
|
98
|
-
- `table` - Responsive data table.
|
|
99
|
-
- `accordion` - Collapsible content sections.
|
|
100
|
-
- `collapsible` - Expandable panel.
|
|
101
|
-
- `tabs` - Tabbed content switcher.
|
|
102
|
-
- `progress` - Progress bar.
|
|
103
|
-
- `skeleton` - Loading placeholder state.
|
|
104
|
-
- `image` - Enhanced img with fallback and loading state.
|
|
105
|
-
- `carousel` - Content slider with autoplay.
|
|
106
|
-
|
|
107
|
-
### Feedback
|
|
108
|
-
- `loading-spinner` - SVG spinner with variants.
|
|
109
|
-
- `star-rating` - Interactive rating component.
|
|
110
|
-
- `toast` - Transient notifications.
|
|
111
|
-
- `alert` - Critical information banner.
|
|
112
|
-
|
|
113
|
-
### Overlays
|
|
114
|
-
- `dialog` - Modal dialog.
|
|
115
|
-
- `alert-dialog` - Modal for confirming actions.
|
|
116
|
-
- `sheet` - Side-panel overlay.
|
|
117
|
-
- `popover` - Content appearing over trigger.
|
|
118
|
-
- `tooltip` - Hover information.
|
|
119
|
-
- `dropdown-menu` - Menu for actions/navigation.
|
|
120
|
-
|
|
121
|
-
### Navigation
|
|
122
|
-
- `breadcrumb` - Navigation trail.
|
|
123
|
-
- `pagination` - Page navigation controls.
|
|
124
|
-
|
|
125
|
-
## Polymorphism
|
|
126
|
-
|
|
127
|
-
Our components accept an `as` prop to change the underlying HTML element while maintaining styles and behavior.
|
|
128
|
-
|
|
129
|
-
```tsx
|
|
130
|
-
// Renders as an <a> tag but looks like a button
|
|
131
|
-
<Button as="a" href="/login">
|
|
132
|
-
Login
|
|
133
|
-
</Button>
|
|
134
|
-
|
|
135
|
-
// Renders as a specialized text variant
|
|
136
|
-
<Text as="h1" variant="h1">
|
|
137
|
-
Page Title
|
|
138
|
-
</Text>
|
|
139
|
-
```
|
|
140
|
-
|
|
141
|
-
## Local Development
|
|
142
|
-
|
|
143
|
-
To run the documentation/playground locally:
|
|
144
|
-
|
|
145
|
-
```bash
|
|
146
|
-
cd examples/playground
|
|
147
|
-
npm install
|
|
148
|
-
npm run dev
|
|
149
|
-
```
|
|
150
|
-
|
|
151
|
-
Visit `http://localhost:3001` to view the component showcase.
|
|
1
|
+
# @srcroot/ui
|
|
2
|
+
|
|
3
|
+
A UI library with polymorphic, accessible React components.
|
|
4
|
+
This library provides a collection of re-usable components that you can copy and paste into your apps.
|
|
5
|
+
|
|
6
|
+
## Features
|
|
7
|
+
|
|
8
|
+
- **Polymorphic**: Most components support an `as` prop (e.g., render a `Button` as an `a` tag).
|
|
9
|
+
- **Accessible**: Built on standard HTML elements and WAI-ARIA patterns.
|
|
10
|
+
- **Copy/Paste**: Not a dependency you install, but code you own.
|
|
11
|
+
- **Styled**: Beautiful defaults using Tailwind CSS and `class-variance-authority`.
|
|
12
|
+
|
|
13
|
+
## Installation
|
|
14
|
+
|
|
15
|
+
This library is distributed via a CLI that initializes your project and adds components directly to your source code.
|
|
16
|
+
|
|
17
|
+
### 1. Initialize
|
|
18
|
+
|
|
19
|
+
Run the `init` command to set up the necessary dependencies and structural files (like `cn` utility) in your project.
|
|
20
|
+
|
|
21
|
+
```bash
|
|
22
|
+
npx @srcroot/ui init
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
This will ask a few questions to configure your project structure (e.g., where to put components).
|
|
26
|
+
|
|
27
|
+
### 2. Add Components
|
|
28
|
+
|
|
29
|
+
Use the `add` command to install components. You can do this in three ways:
|
|
30
|
+
|
|
31
|
+
**Interactive Mode:**
|
|
32
|
+
Run without arguments to select components from a list.
|
|
33
|
+
```bash
|
|
34
|
+
npx @srcroot/ui add
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
**Specific Components:**
|
|
38
|
+
Add one or more components by name.
|
|
39
|
+
```bash
|
|
40
|
+
npx @srcroot/ui add button card input
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
**Add All:**
|
|
44
|
+
Install every available component at once.
|
|
45
|
+
```bash
|
|
46
|
+
npx @srcroot/ui add --all
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
This will copy the component files to your `components/ui` directory and install any necessary peer dependencies (like `react-icons` or `clsx`).
|
|
50
|
+
|
|
51
|
+
### 3. Usage
|
|
52
|
+
|
|
53
|
+
Import components directly from your project folder:
|
|
54
|
+
|
|
55
|
+
```tsx
|
|
56
|
+
import { Button } from "@/components/ui/button"
|
|
57
|
+
|
|
58
|
+
export default function Home() {
|
|
59
|
+
return (
|
|
60
|
+
<Button variant="destructive" onClick={() => alert("Clicked!")}>
|
|
61
|
+
Click Me
|
|
62
|
+
</Button>
|
|
63
|
+
)
|
|
64
|
+
}
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
## Available Components
|
|
68
|
+
|
|
69
|
+
run `npx @srcroot/ui list` to see all available components.
|
|
70
|
+
|
|
71
|
+
### Core
|
|
72
|
+
- `button` - Polymorphic button with variants.
|
|
73
|
+
- `badge` - Status indicators.
|
|
74
|
+
- `avatar` - User profile images with fallbacks.
|
|
75
|
+
- `separator` - Visual divider.
|
|
76
|
+
- `button-group` - Attached or spaced button sets.
|
|
77
|
+
|
|
78
|
+
### Forms
|
|
79
|
+
- `input` - Basic text input.
|
|
80
|
+
- `textarea` - Multi-line text input.
|
|
81
|
+
- `checkbox` - Toggle selection.
|
|
82
|
+
- `radio` - Single selection from list.
|
|
83
|
+
- `switch` - Toggle switch.
|
|
84
|
+
- `select` - Dropdown selection.
|
|
85
|
+
- `slider` - Range input.
|
|
86
|
+
- `otp-input` - One-time password verification.
|
|
87
|
+
- `search` - Search input with debounce support.
|
|
88
|
+
- `calendar` - Date and range picker.
|
|
89
|
+
|
|
90
|
+
### Layout
|
|
91
|
+
- `card` - Content container with header/content/footer.
|
|
92
|
+
- `container` - Centered layout wrapper.
|
|
93
|
+
- `aspect-ratio` - Maintain element proportions.
|
|
94
|
+
|
|
95
|
+
### Data Display
|
|
96
|
+
- `text` - Polymorphic typography component.
|
|
97
|
+
- `label` - Accessible form label.
|
|
98
|
+
- `table` - Responsive data table.
|
|
99
|
+
- `accordion` - Collapsible content sections.
|
|
100
|
+
- `collapsible` - Expandable panel.
|
|
101
|
+
- `tabs` - Tabbed content switcher.
|
|
102
|
+
- `progress` - Progress bar.
|
|
103
|
+
- `skeleton` - Loading placeholder state.
|
|
104
|
+
- `image` - Enhanced img with fallback and loading state.
|
|
105
|
+
- `carousel` - Content slider with autoplay.
|
|
106
|
+
|
|
107
|
+
### Feedback
|
|
108
|
+
- `loading-spinner` - SVG spinner with variants.
|
|
109
|
+
- `star-rating` - Interactive rating component.
|
|
110
|
+
- `toast` - Transient notifications.
|
|
111
|
+
- `alert` - Critical information banner.
|
|
112
|
+
|
|
113
|
+
### Overlays
|
|
114
|
+
- `dialog` - Modal dialog.
|
|
115
|
+
- `alert-dialog` - Modal for confirming actions.
|
|
116
|
+
- `sheet` - Side-panel overlay.
|
|
117
|
+
- `popover` - Content appearing over trigger.
|
|
118
|
+
- `tooltip` - Hover information.
|
|
119
|
+
- `dropdown-menu` - Menu for actions/navigation.
|
|
120
|
+
|
|
121
|
+
### Navigation
|
|
122
|
+
- `breadcrumb` - Navigation trail.
|
|
123
|
+
- `pagination` - Page navigation controls.
|
|
124
|
+
|
|
125
|
+
## Polymorphism
|
|
126
|
+
|
|
127
|
+
Our components accept an `as` prop to change the underlying HTML element while maintaining styles and behavior.
|
|
128
|
+
|
|
129
|
+
```tsx
|
|
130
|
+
// Renders as an <a> tag but looks like a button
|
|
131
|
+
<Button as="a" href="/login">
|
|
132
|
+
Login
|
|
133
|
+
</Button>
|
|
134
|
+
|
|
135
|
+
// Renders as a specialized text variant
|
|
136
|
+
<Text as="h1" variant="h1">
|
|
137
|
+
Page Title
|
|
138
|
+
</Text>
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
## Local Development
|
|
142
|
+
|
|
143
|
+
To run the documentation/playground locally:
|
|
144
|
+
|
|
145
|
+
```bash
|
|
146
|
+
cd examples/playground
|
|
147
|
+
npm install
|
|
148
|
+
npm run dev
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
Visit `http://localhost:3001` to view the component showcase.
|
package/dist/index.d.ts
CHANGED
|
File without changes
|
package/dist/index.js
CHANGED
|
@@ -5,11 +5,11 @@ import { Command } from "commander";
|
|
|
5
5
|
import chalk3 from "chalk";
|
|
6
6
|
|
|
7
7
|
// src/cli/services/project-initializer.ts
|
|
8
|
-
import
|
|
9
|
-
import
|
|
8
|
+
import fs4 from "fs-extra";
|
|
9
|
+
import path4 from "path";
|
|
10
10
|
import ora from "ora";
|
|
11
11
|
import prompts from "prompts";
|
|
12
|
-
import { fileURLToPath as
|
|
12
|
+
import { fileURLToPath as fileURLToPath3 } from "url";
|
|
13
13
|
import { execa } from "execa";
|
|
14
14
|
|
|
15
15
|
// src/cli/services/theme-service.ts
|
|
@@ -167,6 +167,25 @@ function getPackageManager(cwd) {
|
|
|
167
167
|
return "npm";
|
|
168
168
|
}
|
|
169
169
|
|
|
170
|
+
// src/cli/utils/get-package-info.ts
|
|
171
|
+
import path3 from "path";
|
|
172
|
+
import fs3 from "fs-extra";
|
|
173
|
+
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
174
|
+
function getPackageInfo() {
|
|
175
|
+
const __filename2 = fileURLToPath2(import.meta.url);
|
|
176
|
+
const __dirname5 = path3.dirname(__filename2);
|
|
177
|
+
const pathsToCheck = [
|
|
178
|
+
path3.resolve(__dirname5, "..", "package.json"),
|
|
179
|
+
path3.resolve(__dirname5, "..", "..", "..", "package.json")
|
|
180
|
+
];
|
|
181
|
+
for (const pkgPath of pathsToCheck) {
|
|
182
|
+
if (fs3.existsSync(pkgPath)) {
|
|
183
|
+
return fs3.readJSONSync(pkgPath);
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
return { version: "0.0.0" };
|
|
187
|
+
}
|
|
188
|
+
|
|
170
189
|
// src/cli/utils/logger.ts
|
|
171
190
|
import chalk from "chalk";
|
|
172
191
|
var logger = {
|
|
@@ -185,7 +204,7 @@ var logger = {
|
|
|
185
204
|
};
|
|
186
205
|
|
|
187
206
|
// src/cli/services/project-initializer.ts
|
|
188
|
-
var __dirname3 =
|
|
207
|
+
var __dirname3 = path4.dirname(fileURLToPath3(import.meta.url));
|
|
189
208
|
var ProjectInitializer = class {
|
|
190
209
|
options;
|
|
191
210
|
config = {};
|
|
@@ -204,13 +223,13 @@ var ProjectInitializer = class {
|
|
|
204
223
|
this.printSuccess();
|
|
205
224
|
}
|
|
206
225
|
async validateEnvironment() {
|
|
207
|
-
const cwd =
|
|
208
|
-
const packageJsonPath =
|
|
209
|
-
if (!
|
|
226
|
+
const cwd = path4.resolve(this.options.cwd);
|
|
227
|
+
const packageJsonPath = path4.join(cwd, "package.json");
|
|
228
|
+
if (!fs4.existsSync(packageJsonPath)) {
|
|
210
229
|
logger.error("Error: No package.json found. Please run this in a project directory.");
|
|
211
230
|
process.exit(1);
|
|
212
231
|
}
|
|
213
|
-
const pkg = await
|
|
232
|
+
const pkg = await fs4.readJson(packageJsonPath);
|
|
214
233
|
const allDeps = { ...pkg.dependencies, ...pkg.devDependencies };
|
|
215
234
|
if (!allDeps["react"]) {
|
|
216
235
|
logger.error("Error: React not found in dependencies. Please initialize this in a React project.");
|
|
@@ -218,33 +237,33 @@ var ProjectInitializer = class {
|
|
|
218
237
|
}
|
|
219
238
|
}
|
|
220
239
|
async detectConfiguration() {
|
|
221
|
-
const cwd =
|
|
240
|
+
const cwd = path4.resolve(this.options.cwd);
|
|
222
241
|
const packageManager = getPackageManager(cwd);
|
|
223
242
|
const installCmd = packageManager === "npm" ? "install" : "add";
|
|
224
|
-
const pkg = await
|
|
243
|
+
const pkg = await fs4.readJson(path4.join(cwd, "package.json"));
|
|
225
244
|
const allDeps = { ...pkg.dependencies, ...pkg.devDependencies };
|
|
226
245
|
const tailwindVersion = allDeps["tailwindcss"] || "";
|
|
227
246
|
const isTailwind4 = tailwindVersion.includes("^4") || tailwindVersion.startsWith("4") || allDeps["@tailwindcss/postcss"];
|
|
228
|
-
const hasSrc =
|
|
229
|
-
const srcPath = hasSrc ?
|
|
230
|
-
const appPath =
|
|
231
|
-
const pagesPath =
|
|
232
|
-
const hasAppDir =
|
|
233
|
-
const hasPagesDir =
|
|
234
|
-
const libDir =
|
|
235
|
-
const componentsDir =
|
|
247
|
+
const hasSrc = fs4.existsSync(path4.join(cwd, "src"));
|
|
248
|
+
const srcPath = hasSrc ? path4.join(cwd, "src") : cwd;
|
|
249
|
+
const appPath = path4.join(srcPath, "app");
|
|
250
|
+
const pagesPath = path4.join(srcPath, "pages");
|
|
251
|
+
const hasAppDir = fs4.existsSync(appPath);
|
|
252
|
+
const hasPagesDir = fs4.existsSync(pagesPath);
|
|
253
|
+
const libDir = path4.join(srcPath, "lib");
|
|
254
|
+
const componentsDir = path4.join(srcPath, "components", "ui");
|
|
236
255
|
let globalsPath = "";
|
|
237
256
|
if (hasAppDir) {
|
|
238
|
-
if (
|
|
239
|
-
else if (
|
|
240
|
-
else globalsPath =
|
|
257
|
+
if (fs4.existsSync(path4.join(appPath, "globals.css"))) globalsPath = path4.join(appPath, "globals.css");
|
|
258
|
+
else if (fs4.existsSync(path4.join(appPath, "global.css"))) globalsPath = path4.join(appPath, "global.css");
|
|
259
|
+
else globalsPath = path4.join(appPath, "globals.css");
|
|
241
260
|
} else if (hasPagesDir) {
|
|
242
|
-
const stylesPath =
|
|
243
|
-
if (
|
|
244
|
-
else if (
|
|
245
|
-
else globalsPath =
|
|
261
|
+
const stylesPath = path4.join(srcPath, "styles");
|
|
262
|
+
if (fs4.existsSync(path4.join(stylesPath, "globals.css"))) globalsPath = path4.join(stylesPath, "globals.css");
|
|
263
|
+
else if (fs4.existsSync(path4.join(stylesPath, "global.css"))) globalsPath = path4.join(stylesPath, "global.css");
|
|
264
|
+
else globalsPath = path4.join(stylesPath, "globals.css");
|
|
246
265
|
} else {
|
|
247
|
-
globalsPath =
|
|
266
|
+
globalsPath = path4.join(srcPath, "globals.css");
|
|
248
267
|
}
|
|
249
268
|
this.config = {
|
|
250
269
|
cwd,
|
|
@@ -292,13 +311,13 @@ var ProjectInitializer = class {
|
|
|
292
311
|
const spinner = ora("Creating project structure...").start();
|
|
293
312
|
const cfg = this.config;
|
|
294
313
|
try {
|
|
295
|
-
await
|
|
296
|
-
await
|
|
297
|
-
const utilsPath =
|
|
298
|
-
const registryUtilsPath =
|
|
314
|
+
await fs4.ensureDir(cfg.libDir);
|
|
315
|
+
await fs4.ensureDir(cfg.componentsDir);
|
|
316
|
+
const utilsPath = path4.join(cfg.libDir, "utils.ts");
|
|
317
|
+
const registryUtilsPath = path4.resolve(__dirname3, "..", "src", "registry", "lib", "utils.ts");
|
|
299
318
|
let utilsContent = "";
|
|
300
|
-
if (
|
|
301
|
-
utilsContent = await
|
|
319
|
+
if (fs4.existsSync(registryUtilsPath)) {
|
|
320
|
+
utilsContent = await fs4.readFile(registryUtilsPath, "utf-8");
|
|
302
321
|
} else {
|
|
303
322
|
utilsContent = `import { type ClassValue, clsx } from "clsx"
|
|
304
323
|
import { twMerge } from "tailwind-merge"
|
|
@@ -309,15 +328,15 @@ export function cn(...inputs: ClassValue[]) {
|
|
|
309
328
|
`;
|
|
310
329
|
spinner.warn(`Could not find registry/utils.ts, using fallback content.`);
|
|
311
330
|
}
|
|
312
|
-
await
|
|
313
|
-
spinner.succeed(`Created ${
|
|
331
|
+
await fs4.writeFile(utilsPath, utilsContent);
|
|
332
|
+
spinner.succeed(`Created ${path4.relative(cfg.cwd, utilsPath)}`);
|
|
314
333
|
spinner.start(`Setting up ${cfg.selectedTheme} theme...`);
|
|
315
|
-
const stylesDir =
|
|
316
|
-
await
|
|
334
|
+
const stylesDir = path4.dirname(cfg.globalsPath);
|
|
335
|
+
await fs4.ensureDir(stylesDir);
|
|
317
336
|
try {
|
|
318
337
|
const cssContent = await this.themeService.getThemeCss(cfg.selectedTheme, cfg.isTailwind4);
|
|
319
|
-
await
|
|
320
|
-
spinner.succeed(`Updated ${
|
|
338
|
+
await fs4.writeFile(cfg.globalsPath, cssContent);
|
|
339
|
+
spinner.succeed(`Updated ${path4.relative(cfg.cwd, cfg.globalsPath)} with ${cfg.selectedTheme} theme (${cfg.isTailwind4 ? "Tailwind 4" : "Tailwind 3"})`);
|
|
321
340
|
} catch (error) {
|
|
322
341
|
spinner.fail(`Failed to load theme: ${cfg.selectedTheme}`);
|
|
323
342
|
console.error(error);
|
|
@@ -325,10 +344,21 @@ export function cn(...inputs: ClassValue[]) {
|
|
|
325
344
|
}
|
|
326
345
|
if (!cfg.isTailwind4) {
|
|
327
346
|
spinner.start("Setting up Tailwind config...");
|
|
328
|
-
const tailwindConfigPath =
|
|
329
|
-
await
|
|
347
|
+
const tailwindConfigPath = path4.join(cfg.cwd, "tailwind.config.ts");
|
|
348
|
+
await fs4.writeFile(tailwindConfigPath, TAILWIND_CONFIG);
|
|
330
349
|
spinner.succeed(`Created tailwind.config.ts`);
|
|
331
350
|
}
|
|
351
|
+
const packageInfo = getPackageInfo();
|
|
352
|
+
const configObj = {
|
|
353
|
+
version: packageInfo.version || "0.0.0",
|
|
354
|
+
theme: cfg.selectedTheme,
|
|
355
|
+
paths: {
|
|
356
|
+
components: path4.relative(cfg.cwd, cfg.componentsDir),
|
|
357
|
+
utils: path4.relative(cfg.cwd, utilsPath)
|
|
358
|
+
}
|
|
359
|
+
};
|
|
360
|
+
await fs4.writeJSON(path4.join(cfg.cwd, "srcroot.config.json"), configObj, { spaces: 2 });
|
|
361
|
+
spinner.succeed("Created srcroot.config.json");
|
|
332
362
|
} catch (error) {
|
|
333
363
|
spinner.fail("Failed to initialize project");
|
|
334
364
|
console.error(error);
|
|
@@ -348,8 +378,8 @@ export function cn(...inputs: ClassValue[]) {
|
|
|
348
378
|
deps.push("tailwindcss-animate");
|
|
349
379
|
}
|
|
350
380
|
try {
|
|
351
|
-
const packageJsonPath =
|
|
352
|
-
const pkg = await
|
|
381
|
+
const packageJsonPath = path4.join(cfg.cwd, "package.json");
|
|
382
|
+
const pkg = await fs4.readJson(packageJsonPath);
|
|
353
383
|
const allDeps = { ...pkg.dependencies, ...pkg.devDependencies };
|
|
354
384
|
const missingDeps = deps.filter((dep) => !allDeps[dep]);
|
|
355
385
|
if (missingDeps.length === 0) {
|
|
@@ -384,12 +414,12 @@ async function init(options) {
|
|
|
384
414
|
}
|
|
385
415
|
|
|
386
416
|
// src/cli/services/component-adder.ts
|
|
387
|
-
import
|
|
388
|
-
import
|
|
417
|
+
import fs5 from "fs-extra";
|
|
418
|
+
import path5 from "path";
|
|
389
419
|
import ora2 from "ora";
|
|
390
420
|
import prompts2 from "prompts";
|
|
391
421
|
import { execa as execa2 } from "execa";
|
|
392
|
-
import { fileURLToPath as
|
|
422
|
+
import { fileURLToPath as fileURLToPath4 } from "url";
|
|
393
423
|
|
|
394
424
|
// src/cli/registry.ts
|
|
395
425
|
var REGISTRY = {
|
|
@@ -696,7 +726,8 @@ var REGISTRY = {
|
|
|
696
726
|
file: "ui/file-upload.tsx",
|
|
697
727
|
description: "Drag-and-drop file upload",
|
|
698
728
|
category: "Forms",
|
|
699
|
-
dependencies: ["button"]
|
|
729
|
+
dependencies: ["button"],
|
|
730
|
+
registryDependencies: ["react-dropzone", "react-icons"]
|
|
700
731
|
},
|
|
701
732
|
"hover-card": {
|
|
702
733
|
file: "ui/hover-card.tsx",
|
|
@@ -801,48 +832,63 @@ var REGISTRY = {
|
|
|
801
832
|
category: "Navigation",
|
|
802
833
|
dependencies: []
|
|
803
834
|
},
|
|
835
|
+
map: {
|
|
836
|
+
file: "ui/map.tsx",
|
|
837
|
+
description: "Interactive map with Leaflet/Google",
|
|
838
|
+
category: "Data Display",
|
|
839
|
+
dependencies: [],
|
|
840
|
+
registryDependencies: ["leaflet", "react-leaflet"]
|
|
841
|
+
},
|
|
804
842
|
"empty-state": {
|
|
805
843
|
file: "ui/empty-state.tsx",
|
|
806
|
-
description: "Placeholder for empty
|
|
807
|
-
category: "
|
|
844
|
+
description: "Placeholder for empty data",
|
|
845
|
+
category: "Data Display",
|
|
808
846
|
dependencies: []
|
|
809
847
|
},
|
|
810
848
|
"floating-dock": {
|
|
811
849
|
file: "ui/floating-dock.tsx",
|
|
812
|
-
description: "
|
|
813
|
-
category: "
|
|
814
|
-
dependencies: []
|
|
815
|
-
},
|
|
816
|
-
"map": {
|
|
817
|
-
file: "ui/map.tsx",
|
|
818
|
-
description: "Leaflet/Google map integration",
|
|
819
|
-
category: "Data Display",
|
|
850
|
+
description: "Mac-style floating dock",
|
|
851
|
+
category: "Navigation",
|
|
820
852
|
dependencies: [],
|
|
821
|
-
registryDependencies: ["
|
|
853
|
+
registryDependencies: ["framer-motion"]
|
|
822
854
|
},
|
|
823
855
|
marquee: {
|
|
824
856
|
file: "ui/marquee.tsx",
|
|
825
|
-
description: "
|
|
857
|
+
description: "Infinite scrolling marquee",
|
|
826
858
|
category: "Data Display",
|
|
827
859
|
dependencies: []
|
|
828
860
|
},
|
|
829
861
|
"scroll-to-top": {
|
|
830
862
|
file: "ui/scroll-to-top.tsx",
|
|
831
|
-
description: "
|
|
863
|
+
description: "Button to scroll to top",
|
|
832
864
|
category: "Navigation",
|
|
833
|
-
dependencies: ["button"]
|
|
865
|
+
dependencies: ["button"],
|
|
866
|
+
registryDependencies: ["framer-motion"]
|
|
867
|
+
},
|
|
868
|
+
"scroll-animation": {
|
|
869
|
+
file: "ui/scroll-animation.tsx",
|
|
870
|
+
description: "Scroll-triggered animations",
|
|
871
|
+
category: "Layout",
|
|
872
|
+
dependencies: [],
|
|
873
|
+
registryDependencies: ["framer-motion"]
|
|
834
874
|
},
|
|
835
875
|
whatsapp: {
|
|
836
876
|
file: "ui/whatsapp.tsx",
|
|
837
|
-
description: "WhatsApp
|
|
838
|
-
category: "
|
|
877
|
+
description: "WhatsApp chat button",
|
|
878
|
+
category: "Data Display",
|
|
839
879
|
dependencies: ["button"],
|
|
840
880
|
registryDependencies: ["react-icons"]
|
|
881
|
+
},
|
|
882
|
+
patterns: {
|
|
883
|
+
file: "ui/patterns.tsx",
|
|
884
|
+
description: "Background patterns",
|
|
885
|
+
category: "Layout",
|
|
886
|
+
dependencies: []
|
|
841
887
|
}
|
|
842
888
|
};
|
|
843
889
|
|
|
844
890
|
// src/cli/services/component-adder.ts
|
|
845
|
-
var __dirname4 =
|
|
891
|
+
var __dirname4 = path5.dirname(fileURLToPath4(import.meta.url));
|
|
846
892
|
var ComponentAdder = class {
|
|
847
893
|
cwd;
|
|
848
894
|
options;
|
|
@@ -964,16 +1010,16 @@ Please manually install: ${packages.join(" ")}`);
|
|
|
964
1010
|
}
|
|
965
1011
|
async copyComponents(components) {
|
|
966
1012
|
const spinner = ora2("Adding components...").start();
|
|
967
|
-
const hasSrc =
|
|
968
|
-
const srcPath = hasSrc ?
|
|
969
|
-
const componentsDir =
|
|
1013
|
+
const hasSrc = fs5.existsSync(path5.join(this.cwd, "src"));
|
|
1014
|
+
const srcPath = hasSrc ? path5.join(this.cwd, "src") : this.cwd;
|
|
1015
|
+
const componentsDir = path5.join(srcPath, "components", "ui");
|
|
970
1016
|
try {
|
|
971
|
-
await
|
|
1017
|
+
await fs5.ensureDir(componentsDir);
|
|
972
1018
|
for (const name of components) {
|
|
973
1019
|
const comp = REGISTRY[name];
|
|
974
|
-
const fileName =
|
|
975
|
-
const targetPath =
|
|
976
|
-
if (
|
|
1020
|
+
const fileName = path5.basename(comp.file);
|
|
1021
|
+
const targetPath = path5.join(componentsDir, fileName);
|
|
1022
|
+
if (fs5.existsSync(targetPath) && !this.options.overwrite) {
|
|
977
1023
|
spinner.stop();
|
|
978
1024
|
const { overwrite } = await prompts2({
|
|
979
1025
|
type: "confirm",
|
|
@@ -988,13 +1034,13 @@ Please manually install: ${packages.join(" ")}`);
|
|
|
988
1034
|
}
|
|
989
1035
|
spinner.start("Adding components...");
|
|
990
1036
|
}
|
|
991
|
-
const registryPath =
|
|
992
|
-
if (!
|
|
1037
|
+
const registryPath = path5.resolve(__dirname4, "..", "src", "registry", comp.file);
|
|
1038
|
+
if (!fs5.existsSync(registryPath)) {
|
|
993
1039
|
spinner.warn(`Registry file not found for ${name}: ${registryPath}`);
|
|
994
1040
|
continue;
|
|
995
1041
|
}
|
|
996
|
-
const content = await
|
|
997
|
-
await
|
|
1042
|
+
const content = await fs5.readFile(registryPath, "utf-8");
|
|
1043
|
+
await fs5.writeFile(targetPath, content);
|
|
998
1044
|
if (components.length > 10) {
|
|
999
1045
|
spinner.text = `Adding ${fileName}...`;
|
|
1000
1046
|
} else {
|
|
@@ -1050,25 +1096,6 @@ async function list() {
|
|
|
1050
1096
|
console.log(chalk2.dim("Usage: npx @srcroot/ui add <component>\n"));
|
|
1051
1097
|
}
|
|
1052
1098
|
|
|
1053
|
-
// src/cli/utils/get-package-info.ts
|
|
1054
|
-
import path5 from "path";
|
|
1055
|
-
import fs5 from "fs-extra";
|
|
1056
|
-
import { fileURLToPath as fileURLToPath4 } from "url";
|
|
1057
|
-
function getPackageInfo() {
|
|
1058
|
-
const __filename2 = fileURLToPath4(import.meta.url);
|
|
1059
|
-
const __dirname5 = path5.dirname(__filename2);
|
|
1060
|
-
const pathsToCheck = [
|
|
1061
|
-
path5.resolve(__dirname5, "..", "package.json"),
|
|
1062
|
-
path5.resolve(__dirname5, "..", "..", "..", "package.json")
|
|
1063
|
-
];
|
|
1064
|
-
for (const pkgPath of pathsToCheck) {
|
|
1065
|
-
if (fs5.existsSync(pkgPath)) {
|
|
1066
|
-
return fs5.readJSONSync(pkgPath);
|
|
1067
|
-
}
|
|
1068
|
-
}
|
|
1069
|
-
return { version: "0.0.0" };
|
|
1070
|
-
}
|
|
1071
|
-
|
|
1072
1099
|
// src/cli/index.ts
|
|
1073
1100
|
process.on("SIGINT", () => process.exit(0));
|
|
1074
1101
|
process.on("SIGTERM", () => process.exit(0));
|