pejay-ui 1.0.3 → 1.1.0

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 CHANGED
@@ -28,153 +28,111 @@ npx pejay-ui remove <component-name>
28
28
 
29
29
  ## Available Components
30
30
 
31
- Here is the list of components. You can copy the command using the **Copy** button on the right:
32
-
33
- <table>
34
- <thead>
35
- <tr>
36
- <th>Component</th>
37
- <th>Description</th>
38
- <th>Install Command</th>
39
- <th>Action</th>
40
- </tr>
41
- </thead>
42
- <tbody>
43
- <!-- Buttons -->
44
- <tr>
45
- <td><strong>button</strong></td>
46
- <td>Premium interactive button with multiple variants, loaders, and tooltips.</td>
47
- <td><code>npx pejay-ui add button</code></td>
48
- <td><button onclick="navigator.clipboard.writeText('npx pejay-ui add button')">Copy</button></td>
49
- </tr>
50
- <!-- Form Inputs -->
51
- <tr>
52
- <td><strong>form/input</strong></td>
53
- <td>Standard text input field with labels and validation errors.</td>
54
- <td><code>npx pejay-ui add form/input</code></td>
55
- <td><button onclick="navigator.clipboard.writeText('npx pejay-ui add form/input')">Copy</button></td>
56
- </tr>
57
- <tr>
58
- <td><strong>form/amount-input</strong></td>
59
- <td>Numeric input configured for formatted currency entry.</td>
60
- <td><code>npx pejay-ui add form/amount-input</code></td>
61
- <td><button onclick="navigator.clipboard.writeText('npx pejay-ui add form/amount-input')">Copy</button></td>
62
- </tr>
63
- <tr>
64
- <td><strong>form/checkbox</strong></td>
65
- <td>Styled single checkbox input.</td>
66
- <td><code>npx pejay-ui add form/checkbox</code></td>
67
- <td><button onclick="navigator.clipboard.writeText('npx pejay-ui add form/checkbox')">Copy</button></td>
68
- </tr>
69
- <tr>
70
- <td><strong>form/checkbox-group</strong></td>
71
- <td>Group of checkboxes managing single/multiple selection states.</td>
72
- <td><code>npx pejay-ui add form/checkbox-group</code></td>
73
- <td><button onclick="navigator.clipboard.writeText('npx pejay-ui add form/checkbox-group')">Copy</button></td>
74
- </tr>
75
- <tr>
76
- <td><strong>form/email-input</strong></td>
77
- <td>Dedicated input for email addresses with prefix icon.</td>
78
- <td><code>npx pejay-ui add form/email-input</code></td>
79
- <td><button onclick="navigator.clipboard.writeText('npx pejay-ui add form/email-input')">Copy</button></td>
80
- </tr>
81
- <tr>
82
- <td><strong>form/file-input</strong></td>
83
- <td>Premium dropzone-style file upload component.</td>
84
- <td><code>npx pejay-ui add form/file-input</code></td>
85
- <td><button onclick="navigator.clipboard.writeText('npx pejay-ui add form/file-input')">Copy</button></td>
86
- </tr>
87
- <tr>
88
- <td><strong>form/number-input</strong></td>
89
- <td>Input field for numerical values with increment/decrement steppers.</td>
90
- <td><code>npx pejay-ui add form/number-input</code></td>
91
- <td><button onclick="navigator.clipboard.writeText('npx pejay-ui add form/number-input')">Copy</button></td>
92
- </tr>
93
- <tr>
94
- <td><strong>form/password-input</strong></td>
95
- <td>Secure text input with eye icon toggle to show/hide password.</td>
96
- <td><code>npx pejay-ui add form/password-input</code></td>
97
- <td><button onclick="navigator.clipboard.writeText('npx pejay-ui add form/password-input')">Copy</button></td>
98
- </tr>
99
- <tr>
100
- <td><strong>form/phone-input</strong></td>
101
- <td>Formatted input field for telephone numbers.</td>
102
- <td><code>npx pejay-ui add form/phone-input</code></td>
103
- <td><button onclick="navigator.clipboard.writeText('npx pejay-ui add form/phone-input')">Copy</button></td>
104
- </tr>
105
- <tr>
106
- <td><strong>form/radio</strong></td>
107
- <td>Styled radio selection dot.</td>
108
- <td><code>npx pejay-ui add form/radio</code></td>
109
- <td><button onclick="navigator.clipboard.writeText('npx pejay-ui add form/radio')">Copy</button></td>
110
- </tr>
111
- <tr>
112
- <td><strong>form/radio-group</strong></td>
113
- <td>Group of mutually exclusive radio options.</td>
114
- <td><code>npx pejay-ui add form/radio-group</code></td>
115
- <td><button onclick="navigator.clipboard.writeText('npx pejay-ui add form/radio-group')">Copy</button></td>
116
- </tr>
117
- <tr>
118
- <td><strong>form/range-slider</strong></td>
119
- <td>Slider controls for choosing values from a numeric range.</td>
120
- <td><code>npx pejay-ui add form/range-slider</code></td>
121
- <td><button onclick="navigator.clipboard.writeText('npx pejay-ui add form/range-slider')">Copy</button></td>
122
- </tr>
123
- <tr>
124
- <td><strong>form/switch</strong></td>
125
- <td>Styled toggle switch representing boolean options.</td>
126
- <td><code>npx pejay-ui add form/switch</code></td>
127
- <td><button onclick="navigator.clipboard.writeText('npx pejay-ui add form/switch')">Copy</button></td>
128
- </tr>
129
- <tr>
130
- <td><strong>form/textarea</strong></td>
131
- <td>Multiline text area input with character counter/limits.</td>
132
- <td><code>npx pejay-ui add form/textarea</code></td>
133
- <td><button onclick="navigator.clipboard.writeText('npx pejay-ui add form/textarea')">Copy</button></td>
134
- </tr>
135
- <tr>
136
- <td><strong>form/url-input</strong></td>
137
- <td>Styled input field specifically formatted for web addresses.</td>
138
- <td><code>npx pejay-ui add form/url-input</code></td>
139
- <td><button onclick="navigator.clipboard.writeText('npx pejay-ui add form/url-input')">Copy</button></td>
140
- </tr>
141
- <!-- Date & Time Pickers -->
142
- <tr>
143
- <td><strong>form/date-picker</strong></td>
144
- <td>Calendar-based date selector popover with inline selects.</td>
145
- <td><code>npx pejay-ui add form/date-picker</code></td>
146
- <td><button onclick="navigator.clipboard.writeText('npx pejay-ui add form/date-picker')">Copy</button></td>
147
- </tr>
148
- <tr>
149
- <td><strong>form/date-range-picker</strong></td>
150
- <td>Date range selector to pick start and end dates.</td>
151
- <td><code>npx pejay-ui add form/date-range-picker</code></td>
152
- <td><button onclick="navigator.clipboard.writeText('npx pejay-ui add form/date-range-picker')">Copy</button></td>
153
- </tr>
154
- <tr>
155
- <td><strong>form/time-picker</strong></td>
156
- <td>Dropdown component for picking hours, minutes, and AM/PM.</td>
157
- <td><code>npx pejay-ui add form/time-picker</code></td>
158
- <td><button onclick="navigator.clipboard.writeText('npx pejay-ui add form/time-picker')">Copy</button></td>
159
- </tr>
160
- <tr>
161
- <td><strong>form/time-range-picker</strong></td>
162
- <td>Popover time selector for configuring custom duration intervals.</td>
163
- <td><code>npx pejay-ui add form/time-range-picker</code></td>
164
- <td><button onclick="navigator.clipboard.writeText('npx pejay-ui add form/time-range-picker')">Copy</button></td>
165
- </tr>
166
- <!-- Dropdowns & Selects -->
167
- <tr>
168
- <td><strong>dropdown/select-input</strong></td>
169
- <td>Elegant single-select searchable dropdown input.</td>
170
- <td><code>npx pejay-ui add dropdown/select-input</code></td>
171
- <td><button onclick="navigator.clipboard.writeText('npx pejay-ui add dropdown/select-input')">Copy</button></td>
172
- </tr>
173
- <tr>
174
- <td><strong>dropdown/multiselect-input</strong></td>
175
- <td>Searchable multiselect dropdown with dismissible tag pills.</td>
176
- <td><code>npx pejay-ui add dropdown/multiselect-input</code></td>
177
- <td><button onclick="navigator.clipboard.writeText('npx pejay-ui add dropdown/multiselect-input')">Copy</button></td>
178
- </tr>
179
- </tbody>
180
- </table>
31
+ Below is the list of components you can add. Each has a copyable command block with a working native copy button on GitHub and NPM:
32
+
33
+ ### Buttons
34
+
35
+ * **`button`**: Premium interactive button supporting multiple variants (solid, soft, ghost), loaders, and custom hover tooltips.
36
+ ```bash
37
+ npx pejay-ui add button
38
+ ```
39
+
40
+ ### Form Inputs
41
+
42
+ * **`form/input`**: Standard text input field with validation, labels, and error messaging.
43
+ ```bash
44
+ npx pejay-ui add form/input
45
+ ```
46
+ * **`form/amount-input`**: Numeric input configured for currency entry with symbol prefixes and formatting.
47
+ ```bash
48
+ npx pejay-ui add form/amount-input
49
+ ```
50
+ * **`form/checkbox`**: Styled single checkbox input.
51
+ ```bash
52
+ npx pejay-ui add form/checkbox
53
+ ```
54
+ * **`form/checkbox-group`**: Group of checkboxes managing single or multiple selection states with item indices.
55
+ ```bash
56
+ npx pejay-ui add form/checkbox-group
57
+ ```
58
+ * **`form/email-input`**: Dedicated input for email addresses with prefix icon.
59
+ ```bash
60
+ npx pejay-ui add form/email-input
61
+ ```
62
+ * **`form/file-input`**: Premium dropzone-style file upload component supporting drag-and-drop and progress/preview states.
63
+ ```bash
64
+ npx pejay-ui add form/file-input
65
+ ```
66
+ * **`form/number-input`**: Input field for numerical values with increment/decrement steppers.
67
+ ```bash
68
+ npx pejay-ui add form/number-input
69
+ ```
70
+ * **`form/password-input`**: Secure text input with eye icon toggle to show/hide the password.
71
+ ```bash
72
+ npx pejay-ui add form/password-input
73
+ ```
74
+ * **`form/phone-input`**: Formatted input field for telephone numbers.
75
+ ```bash
76
+ npx pejay-ui add form/phone-input
77
+ ```
78
+ * **`form/radio`**: Styled radio selection dot.
79
+ ```bash
80
+ npx pejay-ui add form/radio
81
+ ```
82
+ * **`form/radio-group`**: Group of mutually exclusive radio options.
83
+ ```bash
84
+ npx pejay-ui add form/radio-group
85
+ ```
86
+ * **`form/range-slider`**: Slider controls for choosing values from a numeric range.
87
+ ```bash
88
+ npx pejay-ui add form/range-slider
89
+ ```
90
+ * **`form/switch`**: Styled toggle switch representing boolean options.
91
+ ```bash
92
+ npx pejay-ui add form/switch
93
+ ```
94
+ * **`form/textarea`**: Multiline text area input with character counter/limit indicators.
95
+ ```bash
96
+ npx pejay-ui add form/textarea
97
+ ```
98
+ * **`form/url-input`**: Styled input field specifically formatted for web addresses/links.
99
+ ```bash
100
+ npx pejay-ui add form/url-input
101
+ ```
102
+
103
+ ### Date & Time Pickers
104
+
105
+ * **`form/date-picker`**: Calendar-based date selector popover with inline month/year dropdowns.
106
+ ```bash
107
+ npx pejay-ui add form/date-picker
108
+ ```
109
+ * **`form/date-range-picker`**: Date range selector to pick start and end dates with highlight ranges.
110
+ ```bash
111
+ npx pejay-ui add form/date-range-picker
112
+ ```
113
+ * **`form/time-picker`**: Dropdown component for picking specific hours, minutes, and AM/PM.
114
+ ```bash
115
+ npx pejay-ui add form/time-picker
116
+ ```
117
+ * **`form/time-range-picker`**: Popover time selector for configuring custom duration intervals.
118
+ ```bash
119
+ npx pejay-ui add form/time-range-picker
120
+ ```
121
+
122
+ ### Dropdowns & Selects
123
+
124
+ * **`dropdown/select-input`**: Elegant single-select searchable dropdown input.
125
+ ```bash
126
+ npx pejay-ui add dropdown/select-input
127
+ ```
128
+ * **`dropdown/multiselect-input`**: Searchable multiselect dropdown which renders selected options as dismissible tag pills.
129
+ ```bash
130
+ npx pejay-ui add dropdown/multiselect-input
131
+ ```
132
+
133
+ ### Scaffolds & Templates
134
+
135
+ * **`tanstack-query-client`**: Bare-bone TanStack Query client and context provider setup, copied directly into your project's `src/tanstack-query/`.
136
+ ```bash
137
+ npx pejay-ui add tanstack-query-client
138
+ ```
package/bin/cli.js CHANGED
@@ -21,6 +21,23 @@ const prompt = async (questions) => {
21
21
  return inquirer.default.prompt(questions);
22
22
  };
23
23
 
24
+ // Helper to get all files recursively from a directory
25
+ const getFilesRecursively = async (dir) => {
26
+ let results = [];
27
+ const list = await fs.readdir(dir);
28
+ for (const file of list) {
29
+ const filePath = path.join(dir, file);
30
+ const stat = await fs.stat(filePath);
31
+ if (stat && stat.isDirectory()) {
32
+ const subFiles = await getFilesRecursively(filePath);
33
+ results = results.concat(subFiles);
34
+ } else {
35
+ results.push(filePath);
36
+ }
37
+ }
38
+ return results;
39
+ };
40
+
24
41
  program
25
42
  .name("pejay-ui")
26
43
  .description("CLI to initialize, add, and remove React UI components")
@@ -178,7 +195,12 @@ program
178
195
  }
179
196
 
180
197
  // 3. Process & Copy Component Files
181
- const targetDir = path.join(cwd, config.baseDir, "components", componentData.category);
198
+ let targetDir;
199
+ if (componentData.category === "tanstack-query") {
200
+ targetDir = path.join(cwd, "src", "tanstack-query");
201
+ } else {
202
+ targetDir = path.join(cwd, config.baseDir, "components", componentData.category);
203
+ }
182
204
  const outputExt = isTsProject ? "tsx" : "jsx";
183
205
 
184
206
  // Determine list of files to copy
@@ -192,29 +214,70 @@ program
192
214
  process.exit(1);
193
215
  }
194
216
 
195
- const filename = path.basename(srcFilePath).replace(/\.(tsx|ts)$/, (match) => {
196
- return match === ".tsx" ? `.${outputExt}` : `.${isTsProject ? "ts" : "js"}`;
197
- });
198
- const targetFile = path.join(targetDir, filename);
199
-
200
- let componentCode = await fs.readFile(templateSrc, "utf-8");
217
+ const isDir = (await fs.stat(templateSrc)).isDirectory();
218
+ if (isDir) {
219
+ const allFiles = await getFilesRecursively(templateSrc);
220
+ for (const file of allFiles) {
221
+ const relativePath = path.relative(templateSrc, file);
222
+ const filename = relativePath.replace(/\.(tsx|ts)$/, (match) => {
223
+ return match === ".tsx" ? `.${outputExt}` : `.${isTsProject ? "ts" : "js"}`;
224
+ });
225
+ const targetFile = path.join(targetDir, filename);
226
+
227
+ let componentCode = await fs.readFile(file, "utf-8");
228
+
229
+ const fileDir = path.dirname(targetFile);
230
+ const relativeToUtils = path.relative(fileDir, targetUtilsDir).replace(/\\/g, "/");
231
+ const cnImportPath = isTsProject
232
+ ? `${relativeToUtils}/cn`
233
+ : `${relativeToUtils}/cn.js`;
234
+ componentCode = componentCode.replace(/@\/utils\/cn/g, cnImportPath);
201
235
 
202
- // Replace `@/utils/cn` with relative path to the local utils/cn folder
203
- const cnImportPath = isTsProject ? "../../utils/cn" : "../../utils/cn.js";
204
- componentCode = componentCode.replace(/@\/utils\/cn/g, cnImportPath);
236
+ if (!isTsProject) {
237
+ const transformed = babel.transformSync(componentCode, {
238
+ presets: ["@babel/preset-typescript"],
239
+ filename: path.basename(file),
240
+ });
241
+ componentCode = transformed?.code || componentCode;
242
+ }
205
243
 
206
- if (!isTsProject) {
207
- const transformed = babel.transformSync(componentCode, {
208
- presets: ["@babel/preset-typescript"],
209
- filename: path.basename(srcFilePath),
244
+ await fs.ensureDir(path.dirname(targetFile));
245
+ await fs.writeFile(targetFile, componentCode, "utf-8");
246
+
247
+ const relativeTargetFile = path.relative(cwd, targetFile).replace(/\\/g, "/");
248
+ console.log(`✅ Created ${relativeTargetFile}`);
249
+ installedFiles.push(path.relative(path.join(cwd, config.baseDir), targetFile).replace(/\\/g, "/"));
250
+ }
251
+ } else {
252
+ const filename = path.basename(srcFilePath).replace(/\.(tsx|ts)$/, (match) => {
253
+ return match === ".tsx" ? `.${outputExt}` : `.${isTsProject ? "ts" : "js"}`;
210
254
  });
211
- componentCode = transformed?.code || componentCode;
212
- }
255
+ const targetFile = path.join(targetDir, filename);
256
+
257
+ let componentCode = await fs.readFile(templateSrc, "utf-8");
258
+
259
+ const fileDir = path.dirname(targetFile);
260
+ const relativeToUtils = path.relative(fileDir, targetUtilsDir).replace(/\\/g, "/");
261
+ const cnImportPath = isTsProject
262
+ ? `${relativeToUtils}/cn`
263
+ : `${relativeToUtils}/cn.js`;
264
+ componentCode = componentCode.replace(/@\/utils\/cn/g, cnImportPath);
265
+
266
+ if (!isTsProject) {
267
+ const transformed = babel.transformSync(componentCode, {
268
+ presets: ["@babel/preset-typescript"],
269
+ filename: path.basename(srcFilePath),
270
+ });
271
+ componentCode = transformed?.code || componentCode;
272
+ }
213
273
 
214
- await fs.ensureDir(targetDir);
215
- await fs.writeFile(targetFile, componentCode, "utf-8");
216
- console.log(`✅ Created components/${componentData.category}/${filename}`);
217
- installedFiles.push(path.join("components", componentData.category, filename));
274
+ await fs.ensureDir(targetDir);
275
+ await fs.writeFile(targetFile, componentCode, "utf-8");
276
+
277
+ const relativeTargetFile = path.relative(cwd, targetFile).replace(/\\/g, "/");
278
+ console.log(`✅ Created ${relativeTargetFile}`);
279
+ installedFiles.push(path.relative(path.join(cwd, config.baseDir), targetFile).replace(/\\/g, "/"));
280
+ }
218
281
  }
219
282
 
220
283
  // 4. Update State tracking in config
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pejay-ui",
3
- "version": "1.0.3",
3
+ "version": "1.1.0",
4
4
  "type": "module",
5
5
  "description": "react ui components",
6
6
  "bin": {
@@ -22,6 +22,7 @@
22
22
  "dependencies": {
23
23
  "@babel/core": "^7.24.0",
24
24
  "@babel/preset-typescript": "^7.24.0",
25
+ "@tanstack/react-query": "^5.100.14",
25
26
  "commander": "^12.0.0",
26
27
  "fs-extra": "^11.0.0",
27
28
  "inquirer": "^9.0.0"