@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.
Files changed (92) hide show
  1. package/dist/index.js +296 -94
  2. package/package.json +4 -5
  3. package/templates/angular/accordion/accordion-content.component.ts +9 -0
  4. package/templates/angular/accordion/accordion-item.component.ts +138 -0
  5. package/templates/angular/accordion/accordion-trigger.component.ts +9 -0
  6. package/templates/angular/accordion/accordion.component.ts +120 -0
  7. package/templates/angular/accordion/accordion.module.ts +21 -0
  8. package/templates/angular/autocomplete/autocomplete.component.ts +707 -0
  9. package/templates/angular/autocomplete/autocomplete.module.ts +8 -0
  10. package/templates/angular/avatar/avatar-badge.component.ts +18 -0
  11. package/templates/angular/avatar/avatar-fallback.component.ts +39 -0
  12. package/templates/angular/avatar/avatar-group-count.component.ts +46 -0
  13. package/templates/angular/avatar/avatar-group.component.ts +33 -0
  14. package/templates/angular/avatar/avatar-image.component.ts +57 -0
  15. package/templates/angular/avatar/avatar.component.ts +73 -0
  16. package/templates/angular/avatar/avatar.module.ts +27 -0
  17. package/templates/angular/badge/badge.component.ts +84 -0
  18. package/templates/angular/badge/badge.module.ts +9 -0
  19. package/templates/angular/button/button.component.ts +24 -4
  20. package/templates/angular/card/card.component.ts +100 -0
  21. package/templates/angular/card/card.module.ts +8 -0
  22. package/templates/angular/checkbox/checkbox.component.ts +172 -0
  23. package/templates/angular/checkbox/checkbox.module.ts +8 -0
  24. package/templates/angular/datepicker/datepicker.component.ts +660 -0
  25. package/templates/angular/datepicker/datepicker.module.ts +8 -0
  26. package/templates/angular/dialog/dialog-content.component.ts +9 -0
  27. package/templates/angular/dialog/dialog-description.component.ts +17 -0
  28. package/templates/angular/dialog/dialog-footer.component.ts +17 -0
  29. package/templates/angular/dialog/dialog-header.component.ts +14 -0
  30. package/templates/angular/dialog/dialog-title.component.ts +18 -0
  31. package/templates/angular/dialog/dialog-trigger.component.ts +9 -0
  32. package/templates/angular/dialog/dialog.component.ts +212 -0
  33. package/templates/angular/dialog/dialog.module.ts +31 -0
  34. package/templates/angular/input/input.component.ts +229 -0
  35. package/templates/angular/input/input.module.ts +8 -0
  36. package/templates/angular/scroll-area/scroll-area.component.ts +72 -0
  37. package/templates/angular/scroll-area/scroll-area.module.ts +9 -0
  38. package/templates/angular/scroll-area/scroll-bar.component.ts +15 -0
  39. package/templates/angular/select/select.component.ts +292 -0
  40. package/templates/angular/select/select.module.ts +8 -0
  41. package/templates/angular/separator/separator.component.ts +63 -0
  42. package/templates/angular/separator/separator.module.ts +9 -0
  43. package/templates/angular/sheet/sheet-content.component.ts +13 -0
  44. package/templates/angular/sheet/sheet-description.component.ts +29 -0
  45. package/templates/angular/sheet/sheet-footer.component.ts +27 -0
  46. package/templates/angular/sheet/sheet-header.component.ts +26 -0
  47. package/templates/angular/sheet/sheet-title.component.ts +31 -0
  48. package/templates/angular/sheet/sheet-trigger.component.ts +11 -0
  49. package/templates/angular/sheet/sheet.component.ts +251 -0
  50. package/templates/angular/sheet/sheet.module.ts +30 -0
  51. package/templates/angular/sidebar/sidebar-content.component.ts +25 -0
  52. package/templates/angular/sidebar/sidebar-footer.component.ts +20 -0
  53. package/templates/angular/sidebar/sidebar-group-content.component.ts +16 -0
  54. package/templates/angular/sidebar/sidebar-group-label.component.ts +20 -0
  55. package/templates/angular/sidebar/sidebar-group.component.ts +14 -0
  56. package/templates/angular/sidebar/sidebar-header.component.ts +25 -0
  57. package/templates/angular/sidebar/sidebar-inset.component.ts +85 -0
  58. package/templates/angular/sidebar/sidebar-menu-button.component.ts +75 -0
  59. package/templates/angular/sidebar/sidebar-menu-item.component.ts +14 -0
  60. package/templates/angular/sidebar/sidebar-menu.component.ts +19 -0
  61. package/templates/angular/sidebar/sidebar-provider.component.ts +77 -0
  62. package/templates/angular/sidebar/sidebar-trigger.component.ts +58 -0
  63. package/templates/angular/sidebar/sidebar.component.ts +228 -0
  64. package/templates/angular/sidebar/sidebar.module.ts +48 -0
  65. package/templates/angular/sidebar/sidebar.service.ts +93 -0
  66. package/templates/angular/skeleton/skeleton.component.ts +44 -0
  67. package/templates/angular/skeleton/skeleton.module.ts +8 -0
  68. package/templates/angular/spinner/spinner.component.ts +75 -0
  69. package/templates/angular/spinner/spinner.module.ts +8 -0
  70. package/templates/angular/table/table-body.component.ts +23 -0
  71. package/templates/angular/table/table-caption.component.ts +29 -0
  72. package/templates/angular/table/table-cell.component.ts +49 -0
  73. package/templates/angular/table/table-footer.component.ts +32 -0
  74. package/templates/angular/table/table-head.component.ts +48 -0
  75. package/templates/angular/table/table-header.component.ts +28 -0
  76. package/templates/angular/table/table-row.component.ts +36 -0
  77. package/templates/angular/table/table.component.ts +35 -0
  78. package/templates/angular/table/table.module.ts +33 -0
  79. package/templates/angular/tabs/tabs-content.component.ts +71 -0
  80. package/templates/angular/tabs/tabs-list.component.ts +70 -0
  81. package/templates/angular/tabs/tabs-trigger.component.ts +149 -0
  82. package/templates/angular/tabs/tabs.component.ts +155 -0
  83. package/templates/angular/tabs/tabs.module.ts +21 -0
  84. package/templates/angular/textarea/textarea.component.ts +268 -0
  85. package/templates/angular/textarea/textarea.module.ts +8 -0
  86. package/templates/angular/toast/toast.module.ts +8 -0
  87. package/templates/angular/toast/toast.service.ts +104 -0
  88. package/templates/angular/toast/toaster.component.ts +329 -0
  89. package/templates/angular/tooltip/tooltip-content.component.ts +43 -0
  90. package/templates/angular/tooltip/tooltip-trigger.component.ts +13 -0
  91. package/templates/angular/tooltip/tooltip.component.ts +243 -0
  92. 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 fs2 from 'fs-extra';
5
- import path2 from 'path';
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 __filename$1 = fileURLToPath(import.meta.url);
180
- path2.dirname(__filename$1);
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 = path2.join(projectRoot, options.path);
263
+ const componentsPath = path.join(projectRoot, options.path);
185
264
  try {
186
- await fs2.ensureDir(componentsPath);
187
- const cssPath = path2.join(componentsPath, "styles.css");
188
- await fs2.writeFile(cssPath, THEME_CSS);
189
- console.log(chalk2.green("\u2705 Salas Design System inicializado com sucesso!"));
190
- console.log(chalk2.gray(` Componentes ser\xE3o adicionados em: ${options.path}`));
191
- console.log(chalk2.gray(` CSS variables criado em: ${options.path}/styles.css
192
- `));
193
- console.log(chalk2.blue("\u{1F4A1} Pr\xF3ximos passos:"));
194
- console.log(chalk2.gray(` npx @salas-ds/cli add button`));
195
- console.log(chalk2.gray(` npx @salas-ds/cli add input`));
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 __filename2 = fileURLToPath(import.meta.url);
202
- var __dirname2 = path2.dirname(__filename2);
203
- var COMPONENTS = ["button", "input", "select", "autocomplete", "datepicker"];
204
- var DEFAULT_PATH = "src/components";
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
- if (!COMPONENTS.includes(componentName)) {
207
- console.error(
208
- chalk2.red(`\u274C Componente "${componentName}" n\xE3o encontrado.`)
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
- console.log(chalk2.blue(`\u{1F4E6} Adicionando componente: ${componentName}
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
- const defaultPath = options.path ?? DEFAULT_PATH;
216
- const { path: chosenPath } = await inquirer.prompt([
217
- {
218
- type: "input",
219
- name: "path",
220
- message: `Pasta onde o componente ser\xE1 criado (ser\xE1 criado: ${defaultPath}/${componentName})`,
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
- await fs2.ensureDir(componentPath);
238
- const templatePath = path2.join(
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
- console.log(chalk2.blue("\u{1F4A1} Pr\xF3ximos passos:"));
269
- console.log(chalk2.gray(` 1. Importe o componente (ex.: no seu m\xF3dulo ou standalone):`));
270
- const importPath = `./${path2.join(basePath, componentName, componentName).replace(/\\/g, "/")}.module`;
271
- console.log(
272
- chalk2.gray(
273
- ` import { Salas${toPascalCase(componentName)}Module } from '${importPath}';`
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
- function toPascalCase(str) {
284
- return str.split("-").map((word) => word.charAt(0).toUpperCase() + word.slice(1)).join("");
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/app/ui").action(initCommand);
291
- program.command("add").description("Adiciona um componente ao projeto").argument("<component>", "Nome do componente").option("-p, --path <path>", "Pasta onde o componente ser\xE1 criado (ex: src/components)", "src/components").action(addCommand);
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.0",
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
- "build": "tsup",
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,9 @@
1
+ import { Component } from '@angular/core';
2
+
3
+ @Component({
4
+ selector: 'salas-accordion-content',
5
+ standalone: true,
6
+ template: '<ng-content></ng-content>',
7
+ styles: [`:host { display: contents; }`],
8
+ })
9
+ export class SalasAccordionContentComponent {}
@@ -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
+ }
@@ -0,0 +1,9 @@
1
+ import { Component } from '@angular/core';
2
+
3
+ @Component({
4
+ selector: 'salas-accordion-trigger',
5
+ standalone: true,
6
+ template: '<ng-content></ng-content>',
7
+ styles: [`:host { display: contents; }`],
8
+ })
9
+ export class SalasAccordionTriggerComponent {}