@salas-ds/cli 0.1.0 → 0.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +296 -94
- package/package.json +4 -5
- package/templates/angular/accordion/accordion-content.component.ts +9 -0
- package/templates/angular/accordion/accordion-item.component.ts +138 -0
- package/templates/angular/accordion/accordion-trigger.component.ts +9 -0
- package/templates/angular/accordion/accordion.component.ts +120 -0
- package/templates/angular/accordion/accordion.module.ts +21 -0
- package/templates/angular/autocomplete/autocomplete.component.ts +707 -0
- package/templates/angular/autocomplete/autocomplete.module.ts +8 -0
- package/templates/angular/avatar/avatar-badge.component.ts +18 -0
- package/templates/angular/avatar/avatar-fallback.component.ts +39 -0
- package/templates/angular/avatar/avatar-group-count.component.ts +46 -0
- package/templates/angular/avatar/avatar-group.component.ts +33 -0
- package/templates/angular/avatar/avatar-image.component.ts +57 -0
- package/templates/angular/avatar/avatar.component.ts +73 -0
- package/templates/angular/avatar/avatar.module.ts +27 -0
- package/templates/angular/badge/badge.component.ts +84 -0
- package/templates/angular/badge/badge.module.ts +9 -0
- package/templates/angular/button/button.component.ts +24 -4
- package/templates/angular/card/card.component.ts +100 -0
- package/templates/angular/card/card.module.ts +8 -0
- package/templates/angular/checkbox/checkbox.component.ts +172 -0
- package/templates/angular/checkbox/checkbox.module.ts +8 -0
- package/templates/angular/datepicker/datepicker.component.ts +660 -0
- package/templates/angular/datepicker/datepicker.module.ts +8 -0
- package/templates/angular/dialog/dialog-content.component.ts +9 -0
- package/templates/angular/dialog/dialog-description.component.ts +17 -0
- package/templates/angular/dialog/dialog-footer.component.ts +17 -0
- package/templates/angular/dialog/dialog-header.component.ts +14 -0
- package/templates/angular/dialog/dialog-title.component.ts +18 -0
- package/templates/angular/dialog/dialog-trigger.component.ts +9 -0
- package/templates/angular/dialog/dialog.component.ts +212 -0
- package/templates/angular/dialog/dialog.module.ts +31 -0
- package/templates/angular/input/input.component.ts +229 -0
- package/templates/angular/input/input.module.ts +8 -0
- package/templates/angular/scroll-area/scroll-area.component.ts +72 -0
- package/templates/angular/scroll-area/scroll-area.module.ts +9 -0
- package/templates/angular/scroll-area/scroll-bar.component.ts +15 -0
- package/templates/angular/select/select.component.ts +292 -0
- package/templates/angular/select/select.module.ts +8 -0
- package/templates/angular/separator/separator.component.ts +63 -0
- package/templates/angular/separator/separator.module.ts +9 -0
- package/templates/angular/sheet/sheet-content.component.ts +13 -0
- package/templates/angular/sheet/sheet-description.component.ts +29 -0
- package/templates/angular/sheet/sheet-footer.component.ts +27 -0
- package/templates/angular/sheet/sheet-header.component.ts +26 -0
- package/templates/angular/sheet/sheet-title.component.ts +31 -0
- package/templates/angular/sheet/sheet-trigger.component.ts +11 -0
- package/templates/angular/sheet/sheet.component.ts +251 -0
- package/templates/angular/sheet/sheet.module.ts +30 -0
- package/templates/angular/sidebar/sidebar-content.component.ts +25 -0
- package/templates/angular/sidebar/sidebar-footer.component.ts +20 -0
- package/templates/angular/sidebar/sidebar-group-content.component.ts +16 -0
- package/templates/angular/sidebar/sidebar-group-label.component.ts +20 -0
- package/templates/angular/sidebar/sidebar-group.component.ts +14 -0
- package/templates/angular/sidebar/sidebar-header.component.ts +25 -0
- package/templates/angular/sidebar/sidebar-inset.component.ts +85 -0
- package/templates/angular/sidebar/sidebar-menu-button.component.ts +75 -0
- package/templates/angular/sidebar/sidebar-menu-item.component.ts +14 -0
- package/templates/angular/sidebar/sidebar-menu.component.ts +19 -0
- package/templates/angular/sidebar/sidebar-provider.component.ts +77 -0
- package/templates/angular/sidebar/sidebar-trigger.component.ts +58 -0
- package/templates/angular/sidebar/sidebar.component.ts +228 -0
- package/templates/angular/sidebar/sidebar.module.ts +48 -0
- package/templates/angular/sidebar/sidebar.service.ts +93 -0
- package/templates/angular/skeleton/skeleton.component.ts +44 -0
- package/templates/angular/skeleton/skeleton.module.ts +8 -0
- package/templates/angular/spinner/spinner.component.ts +75 -0
- package/templates/angular/spinner/spinner.module.ts +8 -0
- package/templates/angular/table/table-body.component.ts +23 -0
- package/templates/angular/table/table-caption.component.ts +29 -0
- package/templates/angular/table/table-cell.component.ts +49 -0
- package/templates/angular/table/table-footer.component.ts +32 -0
- package/templates/angular/table/table-head.component.ts +48 -0
- package/templates/angular/table/table-header.component.ts +28 -0
- package/templates/angular/table/table-row.component.ts +36 -0
- package/templates/angular/table/table.component.ts +35 -0
- package/templates/angular/table/table.module.ts +33 -0
- package/templates/angular/tabs/tabs-content.component.ts +71 -0
- package/templates/angular/tabs/tabs-list.component.ts +70 -0
- package/templates/angular/tabs/tabs-trigger.component.ts +149 -0
- package/templates/angular/tabs/tabs.component.ts +155 -0
- package/templates/angular/tabs/tabs.module.ts +21 -0
- package/templates/angular/textarea/textarea.component.ts +268 -0
- package/templates/angular/textarea/textarea.module.ts +8 -0
- package/templates/angular/toast/toast.module.ts +8 -0
- package/templates/angular/toast/toast.service.ts +104 -0
- package/templates/angular/toast/toaster.component.ts +329 -0
- package/templates/angular/tooltip/tooltip-content.component.ts +43 -0
- package/templates/angular/tooltip/tooltip-trigger.component.ts +13 -0
- package/templates/angular/tooltip/tooltip.component.ts +243 -0
- package/templates/angular/tooltip/tooltip.module.ts +10 -0
package/dist/index.js
CHANGED
|
@@ -1,11 +1,10 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import { Command } from 'commander';
|
|
3
3
|
import chalk2 from 'chalk';
|
|
4
|
-
import
|
|
5
|
-
import
|
|
4
|
+
import fs from 'fs-extra';
|
|
5
|
+
import path from 'path';
|
|
6
6
|
import { fileURLToPath } from 'url';
|
|
7
7
|
import { glob } from 'glob';
|
|
8
|
-
import inquirer from 'inquirer';
|
|
9
8
|
|
|
10
9
|
// src/index.ts
|
|
11
10
|
|
|
@@ -175,118 +174,321 @@ var THEME_CSS = `/* Salas Design System - Light & Dark theme */
|
|
|
175
174
|
[data-theme="dark"] .salas-autocomplete-loading { color: var(--salas-text-muted); }
|
|
176
175
|
`;
|
|
177
176
|
|
|
177
|
+
// src/utils-template.ts
|
|
178
|
+
var UTILS_TS = `/**
|
|
179
|
+
* Salas Design System - Utility functions
|
|
180
|
+
* Generated by @salas-ds/cli
|
|
181
|
+
*/
|
|
182
|
+
|
|
183
|
+
export const cn = (...classes: (string | undefined | null | false)[]): string => {
|
|
184
|
+
return classes.filter(Boolean).join(' ');
|
|
185
|
+
};
|
|
186
|
+
|
|
187
|
+
export const isEqual = <T>(a: T, b: T): boolean => {
|
|
188
|
+
if (Object.is(a, b)) return true;
|
|
189
|
+
if (typeof a !== 'object' || typeof b !== 'object' || a === null || b === null) {
|
|
190
|
+
return false;
|
|
191
|
+
}
|
|
192
|
+
const keysA = Object.keys(a);
|
|
193
|
+
const keysB = Object.keys(b);
|
|
194
|
+
if (keysA.length !== keysB.length) return false;
|
|
195
|
+
for (const key of keysA) {
|
|
196
|
+
if (!keysB.includes(key)) return false;
|
|
197
|
+
if (!isEqual((a as any)[key], (b as any)[key])) return false;
|
|
198
|
+
}
|
|
199
|
+
return true;
|
|
200
|
+
};
|
|
201
|
+
|
|
202
|
+
export const debounce = <T extends (...args: any[]) => any>(
|
|
203
|
+
func: T,
|
|
204
|
+
wait: number
|
|
205
|
+
): ((...args: Parameters<T>) => void) => {
|
|
206
|
+
let timeout: ReturnType<typeof setTimeout> | null = null;
|
|
207
|
+
return (...args: Parameters<T>) => {
|
|
208
|
+
if (timeout) clearTimeout(timeout);
|
|
209
|
+
timeout = setTimeout(() => func(...args), wait);
|
|
210
|
+
};
|
|
211
|
+
};
|
|
212
|
+
|
|
213
|
+
export const throttle = <T extends (...args: any[]) => any>(
|
|
214
|
+
func: T,
|
|
215
|
+
limit: number
|
|
216
|
+
): ((...args: Parameters<T>) => void) => {
|
|
217
|
+
let inThrottle: boolean;
|
|
218
|
+
return (...args: Parameters<T>) => {
|
|
219
|
+
if (!inThrottle) {
|
|
220
|
+
func(...args);
|
|
221
|
+
inThrottle = true;
|
|
222
|
+
setTimeout(() => (inThrottle = false), limit);
|
|
223
|
+
}
|
|
224
|
+
};
|
|
225
|
+
};
|
|
226
|
+
`;
|
|
227
|
+
|
|
178
228
|
// src/commands/init.ts
|
|
179
|
-
var
|
|
180
|
-
|
|
229
|
+
var CONFIG_FILE = "salas-ds.json";
|
|
230
|
+
async function injectStyleImport(projectRoot, componentsPath) {
|
|
231
|
+
const angularJsonPath = path.join(projectRoot, "angular.json");
|
|
232
|
+
const angularJson = await fs.readJSON(angularJsonPath);
|
|
233
|
+
const projectName = Object.keys(angularJson.projects)[0];
|
|
234
|
+
if (!projectName) return null;
|
|
235
|
+
const project = angularJson.projects[projectName];
|
|
236
|
+
const stylesArray = project?.architect?.build?.options?.styles ?? [];
|
|
237
|
+
const globalStyleEntry = stylesArray.find((s) => {
|
|
238
|
+
const file = typeof s === "string" ? s : s.input;
|
|
239
|
+
return /\.(css|scss|sass|less)$/.test(file);
|
|
240
|
+
});
|
|
241
|
+
if (!globalStyleEntry) return null;
|
|
242
|
+
const globalStyleRelative = typeof globalStyleEntry === "string" ? globalStyleEntry : globalStyleEntry.input;
|
|
243
|
+
const globalStyleAbsolute = path.join(projectRoot, globalStyleRelative);
|
|
244
|
+
if (!await fs.pathExists(globalStyleAbsolute)) return null;
|
|
245
|
+
const styleDir = path.dirname(globalStyleAbsolute);
|
|
246
|
+
const salasStylesAbsolute = path.join(componentsPath, "styles.css");
|
|
247
|
+
let importPath = path.relative(styleDir, salasStylesAbsolute).replace(/\\/g, "/");
|
|
248
|
+
if (!importPath.startsWith(".")) {
|
|
249
|
+
importPath = "./" + importPath;
|
|
250
|
+
}
|
|
251
|
+
const content = await fs.readFile(globalStyleAbsolute, "utf-8");
|
|
252
|
+
const importLine = `@import '${importPath}';`;
|
|
253
|
+
if (content.includes(importPath)) {
|
|
254
|
+
return null;
|
|
255
|
+
}
|
|
256
|
+
const newContent = importLine + "\n" + content;
|
|
257
|
+
await fs.writeFile(globalStyleAbsolute, newContent);
|
|
258
|
+
return globalStyleRelative;
|
|
259
|
+
}
|
|
181
260
|
async function initCommand(options) {
|
|
182
261
|
console.log(chalk2.blue("\u{1F680} Inicializando Salas Design System...\n"));
|
|
183
262
|
const projectRoot = process.cwd();
|
|
184
|
-
const componentsPath =
|
|
263
|
+
const componentsPath = path.join(projectRoot, options.path);
|
|
185
264
|
try {
|
|
186
|
-
|
|
187
|
-
const
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
265
|
+
const angularJsonPath = path.join(projectRoot, "angular.json");
|
|
266
|
+
const isAngular = await fs.pathExists(angularJsonPath);
|
|
267
|
+
if (!isAngular) {
|
|
268
|
+
console.error(chalk2.red("\u274C Projeto Angular n\xE3o detectado (angular.json n\xE3o encontrado)."));
|
|
269
|
+
console.log(chalk2.gray("Execute este comando na raiz de um projeto Angular."));
|
|
270
|
+
process.exit(1);
|
|
271
|
+
}
|
|
272
|
+
await fs.ensureDir(componentsPath);
|
|
273
|
+
const config = {
|
|
274
|
+
$schema: "https://salas-ds.dev/schema.json",
|
|
275
|
+
framework: options.framework,
|
|
276
|
+
componentsDir: options.path,
|
|
277
|
+
utils: `${options.path}/utils.ts`,
|
|
278
|
+
styles: `${options.path}/styles.css`
|
|
279
|
+
};
|
|
280
|
+
await fs.writeJSON(path.join(projectRoot, CONFIG_FILE), config, { spaces: 2 });
|
|
281
|
+
const cssPath = path.join(componentsPath, "styles.css");
|
|
282
|
+
await fs.writeFile(cssPath, THEME_CSS);
|
|
283
|
+
const utilsPath = path.join(componentsPath, "utils.ts");
|
|
284
|
+
await fs.writeFile(utilsPath, UTILS_TS);
|
|
285
|
+
const injectedFile = await injectStyleImport(projectRoot, componentsPath);
|
|
286
|
+
console.log(chalk2.green("\u2705 Salas Design System inicializado com sucesso!\n"));
|
|
287
|
+
console.log(chalk2.gray("Arquivos criados:"));
|
|
288
|
+
console.log(chalk2.gray(` ${CONFIG_FILE}`));
|
|
289
|
+
console.log(chalk2.gray(` ${options.path}/styles.css`));
|
|
290
|
+
console.log(chalk2.gray(` ${options.path}/utils.ts`));
|
|
291
|
+
if (injectedFile) {
|
|
292
|
+
console.log(chalk2.green(`
|
|
293
|
+
\u2705 Import adicionado automaticamente em ${injectedFile}`));
|
|
294
|
+
} else {
|
|
295
|
+
console.log(chalk2.yellow(`
|
|
296
|
+
\u26A0 Adicione manualmente no seu arquivo de estilos global:`));
|
|
297
|
+
console.log(chalk2.white(` @import './components/ui/styles.css';`));
|
|
298
|
+
}
|
|
299
|
+
console.log(chalk2.blue("\n\u{1F4A1} Pr\xF3ximos passos:"));
|
|
300
|
+
console.log(chalk2.gray(` Adicione componentes:`));
|
|
301
|
+
console.log(chalk2.white(` npx @salas-ds/cli add button`));
|
|
302
|
+
console.log(chalk2.white(` npx @salas-ds/cli add input`));
|
|
303
|
+
console.log(chalk2.white(` npx @salas-ds/cli add --all`));
|
|
304
|
+
console.log(chalk2.gray(`
|
|
305
|
+
Componentes dispon\xEDveis:`));
|
|
306
|
+
console.log(chalk2.gray(` accordion, autocomplete, avatar, badge, button, card,`));
|
|
307
|
+
console.log(chalk2.gray(` checkbox, datepicker, dialog, input, scroll-area, select,`));
|
|
308
|
+
console.log(chalk2.gray(` separator, sheet, sidebar, skeleton, spinner, table,`));
|
|
309
|
+
console.log(chalk2.gray(` tabs, textarea, toast, tooltip`));
|
|
196
310
|
} catch (error) {
|
|
197
311
|
console.error(chalk2.red("\u274C Erro ao inicializar:"), error);
|
|
198
312
|
process.exit(1);
|
|
199
313
|
}
|
|
200
314
|
}
|
|
201
|
-
var
|
|
202
|
-
var
|
|
203
|
-
var COMPONENTS = [
|
|
204
|
-
|
|
315
|
+
var __filename$1 = fileURLToPath(import.meta.url);
|
|
316
|
+
var __dirname$1 = path.dirname(__filename$1);
|
|
317
|
+
var COMPONENTS = [
|
|
318
|
+
"accordion",
|
|
319
|
+
"autocomplete",
|
|
320
|
+
"avatar",
|
|
321
|
+
"badge",
|
|
322
|
+
"button",
|
|
323
|
+
"card",
|
|
324
|
+
"checkbox",
|
|
325
|
+
"datepicker",
|
|
326
|
+
"dialog",
|
|
327
|
+
"input",
|
|
328
|
+
"scroll-area",
|
|
329
|
+
"select",
|
|
330
|
+
"separator",
|
|
331
|
+
"sheet",
|
|
332
|
+
"sidebar",
|
|
333
|
+
"skeleton",
|
|
334
|
+
"spinner",
|
|
335
|
+
"table",
|
|
336
|
+
"tabs",
|
|
337
|
+
"textarea",
|
|
338
|
+
"toast",
|
|
339
|
+
"tooltip"
|
|
340
|
+
];
|
|
341
|
+
var LUCIDE_COMPONENTS = ["autocomplete", "datepicker", "input", "select", "textarea"];
|
|
342
|
+
var CONFIG_FILE2 = "salas-ds.json";
|
|
343
|
+
function toPascalCase(str) {
|
|
344
|
+
return str.split("-").map((word) => word.charAt(0).toUpperCase() + word.slice(1)).join("");
|
|
345
|
+
}
|
|
346
|
+
async function readConfig() {
|
|
347
|
+
const projectRoot = process.cwd();
|
|
348
|
+
const configPath = path.join(projectRoot, CONFIG_FILE2);
|
|
349
|
+
if (!await fs.pathExists(configPath)) {
|
|
350
|
+
return null;
|
|
351
|
+
}
|
|
352
|
+
return fs.readJSON(configPath);
|
|
353
|
+
}
|
|
354
|
+
async function addSingleComponent(componentName, componentsDir, options) {
|
|
355
|
+
const projectRoot = process.cwd();
|
|
356
|
+
const componentPath = path.join(projectRoot, componentsDir, componentName);
|
|
357
|
+
if (await fs.pathExists(componentPath)) {
|
|
358
|
+
if (!options.overwrite) {
|
|
359
|
+
console.log(chalk2.yellow(` \u26A0 ${componentName} j\xE1 existe. Use --overwrite para substituir.`));
|
|
360
|
+
return false;
|
|
361
|
+
}
|
|
362
|
+
await fs.remove(componentPath);
|
|
363
|
+
}
|
|
364
|
+
await fs.ensureDir(componentPath);
|
|
365
|
+
const templatePath = path.join(__dirname$1, "..", "templates", "angular", componentName);
|
|
366
|
+
if (!await fs.pathExists(templatePath)) {
|
|
367
|
+
console.error(chalk2.red(` \u274C Template n\xE3o encontrado para: ${componentName}`));
|
|
368
|
+
return false;
|
|
369
|
+
}
|
|
370
|
+
const templateFiles = await glob("**/*", {
|
|
371
|
+
cwd: templatePath,
|
|
372
|
+
dot: false,
|
|
373
|
+
nodir: true
|
|
374
|
+
});
|
|
375
|
+
for (const file of templateFiles) {
|
|
376
|
+
const srcPath = path.join(templatePath, file);
|
|
377
|
+
const destPath = path.join(componentPath, file);
|
|
378
|
+
await fs.ensureDir(path.dirname(destPath));
|
|
379
|
+
await fs.copyFile(srcPath, destPath);
|
|
380
|
+
}
|
|
381
|
+
return true;
|
|
382
|
+
}
|
|
205
383
|
async function addCommand(componentName, options) {
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
);
|
|
210
|
-
console.log(chalk2.gray(`Componentes dispon\xEDveis: ${COMPONENTS.join(", ")}`));
|
|
384
|
+
const config = await readConfig();
|
|
385
|
+
if (!config) {
|
|
386
|
+
console.error(chalk2.red("\u274C Projeto n\xE3o inicializado."));
|
|
387
|
+
console.log(chalk2.gray("Execute primeiro: npx @salas-ds/cli init"));
|
|
211
388
|
process.exit(1);
|
|
212
389
|
}
|
|
213
|
-
|
|
390
|
+
const componentsDir = options.path ?? config.componentsDir;
|
|
391
|
+
const componentsToAdd = [];
|
|
392
|
+
if (options.all) {
|
|
393
|
+
componentsToAdd.push(...COMPONENTS);
|
|
394
|
+
console.log(chalk2.blue(`\u{1F4E6} Adicionando todos os ${COMPONENTS.length} componentes...
|
|
214
395
|
`));
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
default: defaultPath,
|
|
222
|
-
transformer: (input) => input.trim() || defaultPath
|
|
223
|
-
}
|
|
224
|
-
]);
|
|
225
|
-
const basePath = (chosenPath || defaultPath).trim();
|
|
226
|
-
const projectRoot = process.cwd();
|
|
227
|
-
const componentsPath = path2.join(projectRoot, basePath);
|
|
228
|
-
const componentPath = path2.join(componentsPath, componentName);
|
|
229
|
-
try {
|
|
230
|
-
const angularJsonPath = path2.join(projectRoot, "angular.json");
|
|
231
|
-
const isAngular = await fs2.pathExists(angularJsonPath);
|
|
232
|
-
if (!isAngular) {
|
|
233
|
-
console.error(chalk2.red("\u274C Projeto Angular n\xE3o detectado."));
|
|
234
|
-
console.log(chalk2.gray("Execute este comando em um projeto Angular."));
|
|
396
|
+
} else if (componentName) {
|
|
397
|
+
if (!COMPONENTS.includes(componentName)) {
|
|
398
|
+
console.error(chalk2.red(`\u274C Componente "${componentName}" n\xE3o encontrado.`));
|
|
399
|
+
console.log(chalk2.gray(`
|
|
400
|
+
Componentes dispon\xEDveis:`));
|
|
401
|
+
console.log(chalk2.gray(` ${COMPONENTS.join(", ")}`));
|
|
235
402
|
process.exit(1);
|
|
236
403
|
}
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
__dirname2,
|
|
240
|
-
"..",
|
|
241
|
-
"..",
|
|
242
|
-
"templates",
|
|
243
|
-
"angular",
|
|
244
|
-
componentName
|
|
245
|
-
);
|
|
246
|
-
if (!await fs2.pathExists(templatePath)) {
|
|
247
|
-
console.error(chalk2.red(`\u274C Template n\xE3o encontrado para: ${componentName}`));
|
|
248
|
-
process.exit(1);
|
|
249
|
-
}
|
|
250
|
-
const templateFiles = await glob("**/*", {
|
|
251
|
-
cwd: templatePath,
|
|
252
|
-
dot: false,
|
|
253
|
-
ignore: ["node_modules/**"]
|
|
254
|
-
});
|
|
255
|
-
for (const file of templateFiles) {
|
|
256
|
-
const srcPath = path2.join(templatePath, file);
|
|
257
|
-
const destPath = path2.join(componentPath, file);
|
|
258
|
-
await fs2.ensureDir(path2.dirname(destPath));
|
|
259
|
-
let content = await fs2.readFile(srcPath, "utf-8");
|
|
260
|
-
content = content.replace(/{{COMPONENT_NAME}}/g, componentName);
|
|
261
|
-
content = content.replace(/{{COMPONENT_CLASS}}/g, toPascalCase(componentName));
|
|
262
|
-
await fs2.writeFile(destPath, content);
|
|
263
|
-
}
|
|
264
|
-
const relativePath = path2.relative(projectRoot, componentPath);
|
|
265
|
-
console.log(chalk2.green(`\u2705 Componente ${componentName} adicionado com sucesso!`));
|
|
266
|
-
console.log(chalk2.gray(` Localiza\xE7\xE3o: ${relativePath}
|
|
404
|
+
componentsToAdd.push(componentName);
|
|
405
|
+
console.log(chalk2.blue(`\u{1F4E6} Adicionando componente: ${componentName}
|
|
267
406
|
`));
|
|
268
|
-
|
|
269
|
-
console.
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
)
|
|
275
|
-
);
|
|
276
|
-
console.log(chalk2.gray(` 2. Use no template:`));
|
|
277
|
-
console.log(chalk2.gray(` <salas-${componentName}></salas-${componentName}>`));
|
|
278
|
-
} catch (error) {
|
|
279
|
-
console.error(chalk2.red("\u274C Erro ao adicionar componente:"), error);
|
|
407
|
+
} else {
|
|
408
|
+
console.error(chalk2.red("\u274C Especifique um componente ou use --all."));
|
|
409
|
+
console.log(chalk2.gray(`
|
|
410
|
+
Exemplos:`));
|
|
411
|
+
console.log(chalk2.gray(` npx @salas-ds/cli add button`));
|
|
412
|
+
console.log(chalk2.gray(` npx @salas-ds/cli add --all`));
|
|
280
413
|
process.exit(1);
|
|
281
414
|
}
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
415
|
+
const added = [];
|
|
416
|
+
const needsLucide = /* @__PURE__ */ new Set();
|
|
417
|
+
for (const name of componentsToAdd) {
|
|
418
|
+
const success = await addSingleComponent(name, componentsDir, options);
|
|
419
|
+
if (success) {
|
|
420
|
+
added.push(name);
|
|
421
|
+
if (LUCIDE_COMPONENTS.includes(name)) {
|
|
422
|
+
needsLucide.add(name);
|
|
423
|
+
}
|
|
424
|
+
console.log(chalk2.green(` \u2713 ${name}`));
|
|
425
|
+
}
|
|
426
|
+
}
|
|
427
|
+
if (added.length === 0) {
|
|
428
|
+
console.log(chalk2.yellow("\nNenhum componente adicionado."));
|
|
429
|
+
return;
|
|
430
|
+
}
|
|
431
|
+
process.cwd();
|
|
432
|
+
console.log(chalk2.green(`
|
|
433
|
+
\u2705 ${added.length} componente(s) adicionado(s) com sucesso!`));
|
|
434
|
+
console.log(chalk2.gray(` Localiza\xE7\xE3o: ${componentsDir}/
|
|
435
|
+
`));
|
|
436
|
+
if (needsLucide.size > 0) {
|
|
437
|
+
console.log(chalk2.yellow("\u26A0 Os seguintes componentes precisam do lucide-angular:"));
|
|
438
|
+
console.log(chalk2.gray(` ${[...needsLucide].join(", ")}`));
|
|
439
|
+
console.log(chalk2.gray(` Instale com: npm install lucide-angular
|
|
440
|
+
`));
|
|
441
|
+
}
|
|
442
|
+
console.log(chalk2.blue("\u{1F4A1} Como usar:"));
|
|
443
|
+
const example = added[0];
|
|
444
|
+
const exampleClass = `Salas${toPascalCase(example)}Component`;
|
|
445
|
+
const relPath = `./${path.join(componentsDir, example, example).replace(/\\/g, "/")}`;
|
|
446
|
+
console.log(chalk2.gray(` // Standalone component:`));
|
|
447
|
+
console.log(chalk2.white(` import { ${exampleClass} } from '${relPath}.component';`));
|
|
448
|
+
console.log(chalk2.gray(`
|
|
449
|
+
// Ou via module:`));
|
|
450
|
+
console.log(chalk2.white(` import { Salas${toPascalCase(example)}Module } from '${relPath}.module';`));
|
|
285
451
|
}
|
|
286
452
|
|
|
287
453
|
// src/index.ts
|
|
288
454
|
var program = new Command();
|
|
289
|
-
program.name("salas-ds").description("CLI para adicionar componentes do Salas Design System").version("0.1.0");
|
|
290
|
-
program.command("init").description("Inicializa o Salas Design System no projeto").option("-f, --framework <framework>", "Framework (angular)", "angular").option("-p, --path <path>", "Caminho para componentes", "src/
|
|
291
|
-
program.command("add").description("Adiciona um componente ao projeto").
|
|
455
|
+
program.name("salas-ds").description("CLI para adicionar componentes do Salas Design System ao seu projeto Angular (estilo shadcn)").version("0.1.0");
|
|
456
|
+
program.command("init").description("Inicializa o Salas Design System no projeto").option("-f, --framework <framework>", "Framework (angular)", "angular").option("-p, --path <path>", "Caminho para componentes", "src/components/ui").action(initCommand);
|
|
457
|
+
program.command("add [component]").description("Adiciona um componente ao projeto").option("-p, --path <path>", "Pasta onde os componentes ser\xE3o criados").option("-a, --all", "Adiciona todos os componentes").option("--overwrite", "Sobrescreve componentes existentes").action(addCommand);
|
|
458
|
+
program.command("list").description("Lista todos os componentes dispon\xEDveis").action(() => {
|
|
459
|
+
const components = [
|
|
460
|
+
"accordion",
|
|
461
|
+
"autocomplete",
|
|
462
|
+
"avatar",
|
|
463
|
+
"badge",
|
|
464
|
+
"button",
|
|
465
|
+
"card",
|
|
466
|
+
"checkbox",
|
|
467
|
+
"datepicker",
|
|
468
|
+
"dialog",
|
|
469
|
+
"input",
|
|
470
|
+
"scroll-area",
|
|
471
|
+
"select",
|
|
472
|
+
"separator",
|
|
473
|
+
"sheet",
|
|
474
|
+
"sidebar",
|
|
475
|
+
"skeleton",
|
|
476
|
+
"spinner",
|
|
477
|
+
"table",
|
|
478
|
+
"tabs",
|
|
479
|
+
"textarea",
|
|
480
|
+
"toast",
|
|
481
|
+
"tooltip"
|
|
482
|
+
];
|
|
483
|
+
console.log(chalk2.blue("\n\u{1F4E6} Componentes dispon\xEDveis:\n"));
|
|
484
|
+
for (const c of components) {
|
|
485
|
+
console.log(chalk2.gray(` \u2022 ${c}`));
|
|
486
|
+
}
|
|
487
|
+
console.log(chalk2.gray(`
|
|
488
|
+
Total: ${components.length} componentes`));
|
|
489
|
+
console.log(chalk2.gray(`
|
|
490
|
+
Uso: npx @salas-ds/cli add <componente>`));
|
|
491
|
+
console.log(chalk2.gray(` npx @salas-ds/cli add --all
|
|
492
|
+
`));
|
|
493
|
+
});
|
|
292
494
|
program.parse();
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@salas-ds/cli",
|
|
3
|
-
"version": "0.1
|
|
4
|
-
"description": "CLI para adicionar componentes do Salas Design System ao projeto",
|
|
3
|
+
"version": "0.2.1",
|
|
4
|
+
"description": "CLI para adicionar componentes do Salas Design System ao projeto (estilo shadcn)",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
7
7
|
"salas-ds": "./dist/index.js"
|
|
@@ -16,12 +16,10 @@
|
|
|
16
16
|
"chalk": "^5.3.0",
|
|
17
17
|
"fs-extra": "^11.2.0",
|
|
18
18
|
"glob": "^10.3.10",
|
|
19
|
-
"inquirer": "^9.2.12",
|
|
20
19
|
"prettier": "^3.2.0"
|
|
21
20
|
},
|
|
22
21
|
"devDependencies": {
|
|
23
22
|
"@types/fs-extra": "^11.0.4",
|
|
24
|
-
"@types/inquirer": "^9.0.7",
|
|
25
23
|
"@types/node": "^20.11.0",
|
|
26
24
|
"tsup": "^8.0.0",
|
|
27
25
|
"typescript": "~5.5.0"
|
|
@@ -35,7 +33,8 @@
|
|
|
35
33
|
"author": "",
|
|
36
34
|
"license": "MIT",
|
|
37
35
|
"scripts": {
|
|
38
|
-
"
|
|
36
|
+
"generate-templates": "node scripts/generate-templates.mjs",
|
|
37
|
+
"build": "node scripts/generate-templates.mjs && tsup",
|
|
39
38
|
"dev": "tsup --watch",
|
|
40
39
|
"clean": "rm -rf dist"
|
|
41
40
|
}
|
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
import { Component, Input, Output, EventEmitter, ViewEncapsulation } from '@angular/core';
|
|
2
|
+
|
|
3
|
+
@Component({
|
|
4
|
+
selector: 'salas-accordion-item',
|
|
5
|
+
standalone: true,
|
|
6
|
+
imports: [],
|
|
7
|
+
encapsulation: ViewEncapsulation.None,
|
|
8
|
+
template: `
|
|
9
|
+
<div
|
|
10
|
+
class="salas-accordion-item"
|
|
11
|
+
[class.salas-accordion-item--disabled]="disabled"
|
|
12
|
+
>
|
|
13
|
+
<button
|
|
14
|
+
type="button"
|
|
15
|
+
class="salas-accordion-trigger"
|
|
16
|
+
[class.salas-accordion-trigger--open]="open"
|
|
17
|
+
[disabled]="disabled"
|
|
18
|
+
(click)="onTriggerClick()"
|
|
19
|
+
[attr.aria-expanded]="open"
|
|
20
|
+
>
|
|
21
|
+
<ng-content select="salas-accordion-trigger"></ng-content>
|
|
22
|
+
<svg
|
|
23
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
24
|
+
width="16"
|
|
25
|
+
height="16"
|
|
26
|
+
viewBox="0 0 24 24"
|
|
27
|
+
fill="none"
|
|
28
|
+
stroke="currentColor"
|
|
29
|
+
stroke-width="2"
|
|
30
|
+
stroke-linecap="round"
|
|
31
|
+
stroke-linejoin="round"
|
|
32
|
+
class="salas-accordion-trigger-icon"
|
|
33
|
+
[class.salas-accordion-trigger-icon--open]="open"
|
|
34
|
+
>
|
|
35
|
+
<path d="m6 9 6 6 6-6"/>
|
|
36
|
+
</svg>
|
|
37
|
+
</button>
|
|
38
|
+
<div
|
|
39
|
+
class="salas-accordion-content"
|
|
40
|
+
[class.salas-accordion-content--open]="open"
|
|
41
|
+
[attr.aria-hidden]="!open"
|
|
42
|
+
>
|
|
43
|
+
<div class="salas-accordion-content-inner">
|
|
44
|
+
<ng-content select="salas-accordion-content"></ng-content>
|
|
45
|
+
</div>
|
|
46
|
+
</div>
|
|
47
|
+
</div>
|
|
48
|
+
`,
|
|
49
|
+
styles: [`
|
|
50
|
+
.salas-accordion-item {
|
|
51
|
+
border-bottom: 1px solid var(--salas-gray-200);
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
.salas-accordion-item:last-child {
|
|
55
|
+
border-bottom: none;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
.salas-accordion-item--disabled {
|
|
59
|
+
opacity: 0.5;
|
|
60
|
+
pointer-events: none;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
:host-context([data-theme="dark"]) .salas-accordion-item {
|
|
64
|
+
border-bottom-color: var(--salas-gray-800);
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
.salas-accordion-trigger {
|
|
68
|
+
display: flex;
|
|
69
|
+
align-items: center;
|
|
70
|
+
justify-content: space-between;
|
|
71
|
+
width: 100%;
|
|
72
|
+
padding: 1rem 0;
|
|
73
|
+
font-size: 0.875rem;
|
|
74
|
+
font-weight: 500;
|
|
75
|
+
color: var(--salas-text);
|
|
76
|
+
background: none;
|
|
77
|
+
border: none;
|
|
78
|
+
cursor: pointer;
|
|
79
|
+
transition: color 0.2s;
|
|
80
|
+
text-align: left;
|
|
81
|
+
font-family: inherit;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
.salas-accordion-trigger:hover:not(:disabled) {
|
|
85
|
+
text-decoration: underline;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
.salas-accordion-trigger:disabled {
|
|
89
|
+
cursor: not-allowed;
|
|
90
|
+
opacity: 0.5;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
.salas-accordion-trigger-icon {
|
|
94
|
+
flex-shrink: 0;
|
|
95
|
+
width: 1rem;
|
|
96
|
+
height: 1rem;
|
|
97
|
+
transition: transform 0.2s ease;
|
|
98
|
+
color: var(--salas-text-muted);
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
.salas-accordion-trigger-icon--open {
|
|
102
|
+
transform: rotate(180deg);
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
.salas-accordion-content {
|
|
106
|
+
overflow: hidden;
|
|
107
|
+
max-height: 0;
|
|
108
|
+
opacity: 0;
|
|
109
|
+
transition: max-height 0.3s ease, opacity 0.2s ease;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
.salas-accordion-content--open {
|
|
113
|
+
max-height: 500px;
|
|
114
|
+
opacity: 1;
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
.salas-accordion-content-inner {
|
|
118
|
+
padding-bottom: 1rem;
|
|
119
|
+
color: var(--salas-text-muted);
|
|
120
|
+
font-size: 0.875rem;
|
|
121
|
+
line-height: 1.5;
|
|
122
|
+
}
|
|
123
|
+
`],
|
|
124
|
+
})
|
|
125
|
+
export class SalasAccordionItemComponent {
|
|
126
|
+
@Input() value!: string;
|
|
127
|
+
@Input() disabled = false;
|
|
128
|
+
|
|
129
|
+
open = false;
|
|
130
|
+
|
|
131
|
+
@Output() toggled = new EventEmitter<string>();
|
|
132
|
+
|
|
133
|
+
onTriggerClick(): void {
|
|
134
|
+
if (!this.disabled) {
|
|
135
|
+
this.toggled.emit(this.value);
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
}
|