@salas-ds/cli 0.2.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 CHANGED
@@ -1,8 +1,8 @@
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
8
 
@@ -227,19 +227,49 @@ export const throttle = <T extends (...args: any[]) => any>(
227
227
 
228
228
  // src/commands/init.ts
229
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
+ }
230
260
  async function initCommand(options) {
231
261
  console.log(chalk2.blue("\u{1F680} Inicializando Salas Design System...\n"));
232
262
  const projectRoot = process.cwd();
233
- const componentsPath = path2.join(projectRoot, options.path);
263
+ const componentsPath = path.join(projectRoot, options.path);
234
264
  try {
235
- const angularJsonPath = path2.join(projectRoot, "angular.json");
236
- const isAngular = await fs2.pathExists(angularJsonPath);
265
+ const angularJsonPath = path.join(projectRoot, "angular.json");
266
+ const isAngular = await fs.pathExists(angularJsonPath);
237
267
  if (!isAngular) {
238
268
  console.error(chalk2.red("\u274C Projeto Angular n\xE3o detectado (angular.json n\xE3o encontrado)."));
239
269
  console.log(chalk2.gray("Execute este comando na raiz de um projeto Angular."));
240
270
  process.exit(1);
241
271
  }
242
- await fs2.ensureDir(componentsPath);
272
+ await fs.ensureDir(componentsPath);
243
273
  const config = {
244
274
  $schema: "https://salas-ds.dev/schema.json",
245
275
  framework: options.framework,
@@ -247,27 +277,32 @@ async function initCommand(options) {
247
277
  utils: `${options.path}/utils.ts`,
248
278
  styles: `${options.path}/styles.css`
249
279
  };
250
- await fs2.writeJSON(path2.join(projectRoot, CONFIG_FILE), config, { spaces: 2 });
251
- const cssPath = path2.join(componentsPath, "styles.css");
252
- await fs2.writeFile(cssPath, THEME_CSS);
253
- const utilsPath = path2.join(componentsPath, "utils.ts");
254
- await fs2.writeFile(utilsPath, UTILS_TS);
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);
255
286
  console.log(chalk2.green("\u2705 Salas Design System inicializado com sucesso!\n"));
256
287
  console.log(chalk2.gray("Arquivos criados:"));
257
288
  console.log(chalk2.gray(` ${CONFIG_FILE}`));
258
289
  console.log(chalk2.gray(` ${options.path}/styles.css`));
259
- console.log(chalk2.gray(` ${options.path}/utils.ts
260
- `));
261
- console.log(chalk2.blue("\u{1F4A1} Pr\xF3ximos passos:"));
262
- console.log(chalk2.gray(` 1. Importe o CSS no seu styles.css ou angular.json:`));
263
- console.log(chalk2.white(` @import './${options.path}/styles.css';`));
264
- console.log(chalk2.gray(`
265
- 2. Adicione componentes:`));
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:`));
266
301
  console.log(chalk2.white(` npx @salas-ds/cli add button`));
267
302
  console.log(chalk2.white(` npx @salas-ds/cli add input`));
268
303
  console.log(chalk2.white(` npx @salas-ds/cli add --all`));
269
304
  console.log(chalk2.gray(`
270
- 3. Componentes dispon\xEDveis:`));
305
+ Componentes dispon\xEDveis:`));
271
306
  console.log(chalk2.gray(` accordion, autocomplete, avatar, badge, button, card,`));
272
307
  console.log(chalk2.gray(` checkbox, datepicker, dialog, input, scroll-area, select,`));
273
308
  console.log(chalk2.gray(` separator, sheet, sidebar, skeleton, spinner, table,`));
@@ -278,7 +313,7 @@ async function initCommand(options) {
278
313
  }
279
314
  }
280
315
  var __filename$1 = fileURLToPath(import.meta.url);
281
- var __dirname$1 = path2.dirname(__filename$1);
316
+ var __dirname$1 = path.dirname(__filename$1);
282
317
  var COMPONENTS = [
283
318
  "accordion",
284
319
  "autocomplete",
@@ -310,25 +345,25 @@ function toPascalCase(str) {
310
345
  }
311
346
  async function readConfig() {
312
347
  const projectRoot = process.cwd();
313
- const configPath = path2.join(projectRoot, CONFIG_FILE2);
314
- if (!await fs2.pathExists(configPath)) {
348
+ const configPath = path.join(projectRoot, CONFIG_FILE2);
349
+ if (!await fs.pathExists(configPath)) {
315
350
  return null;
316
351
  }
317
- return fs2.readJSON(configPath);
352
+ return fs.readJSON(configPath);
318
353
  }
319
354
  async function addSingleComponent(componentName, componentsDir, options) {
320
355
  const projectRoot = process.cwd();
321
- const componentPath = path2.join(projectRoot, componentsDir, componentName);
322
- if (await fs2.pathExists(componentPath)) {
356
+ const componentPath = path.join(projectRoot, componentsDir, componentName);
357
+ if (await fs.pathExists(componentPath)) {
323
358
  if (!options.overwrite) {
324
359
  console.log(chalk2.yellow(` \u26A0 ${componentName} j\xE1 existe. Use --overwrite para substituir.`));
325
360
  return false;
326
361
  }
327
- await fs2.remove(componentPath);
362
+ await fs.remove(componentPath);
328
363
  }
329
- await fs2.ensureDir(componentPath);
330
- const templatePath = path2.join(__dirname$1, "..", "templates", "angular", componentName);
331
- if (!await fs2.pathExists(templatePath)) {
364
+ await fs.ensureDir(componentPath);
365
+ const templatePath = path.join(__dirname$1, "..", "templates", "angular", componentName);
366
+ if (!await fs.pathExists(templatePath)) {
332
367
  console.error(chalk2.red(` \u274C Template n\xE3o encontrado para: ${componentName}`));
333
368
  return false;
334
369
  }
@@ -338,10 +373,10 @@ async function addSingleComponent(componentName, componentsDir, options) {
338
373
  nodir: true
339
374
  });
340
375
  for (const file of templateFiles) {
341
- const srcPath = path2.join(templatePath, file);
342
- const destPath = path2.join(componentPath, file);
343
- await fs2.ensureDir(path2.dirname(destPath));
344
- await fs2.copyFile(srcPath, destPath);
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);
345
380
  }
346
381
  return true;
347
382
  }
@@ -407,7 +442,7 @@ Exemplos:`));
407
442
  console.log(chalk2.blue("\u{1F4A1} Como usar:"));
408
443
  const example = added[0];
409
444
  const exampleClass = `Salas${toPascalCase(example)}Component`;
410
- const relPath = `./${path2.join(componentsDir, example, example).replace(/\\/g, "/")}`;
445
+ const relPath = `./${path.join(componentsDir, example, example).replace(/\\/g, "/")}`;
411
446
  console.log(chalk2.gray(` // Standalone component:`));
412
447
  console.log(chalk2.white(` import { ${exampleClass} } from '${relPath}.component';`));
413
448
  console.log(chalk2.gray(`
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@salas-ds/cli",
3
- "version": "0.2.0",
3
+ "version": "0.2.1",
4
4
  "description": "CLI para adicionar componentes do Salas Design System ao projeto (estilo shadcn)",
5
5
  "type": "module",
6
6
  "bin": {
@@ -6,8 +6,15 @@ import { Component } from '@angular/core';
6
6
  imports: [],
7
7
  template: `<div class="salas-sidebar-content"><ng-content></ng-content></div>`,
8
8
  styles: [`
9
+ :host {
10
+ display: flex;
11
+ flex: 1;
12
+ min-height: 0;
13
+ overflow: hidden;
14
+ }
9
15
  .salas-sidebar-content {
10
16
  flex: 1;
17
+ min-height: 0;
11
18
  overflow-y: auto;
12
19
  overflow-x: hidden;
13
20
  padding: 0.5rem;
@@ -6,6 +6,9 @@ import { Component } from '@angular/core';
6
6
  imports: [],
7
7
  template: `<header class="salas-sidebar-header"><ng-content></ng-content></header>`,
8
8
  styles: [`
9
+ :host {
10
+ display: block;
11
+ }
9
12
  .salas-sidebar-header {
10
13
  flex-shrink: 0;
11
14
  padding: 1rem 1.25rem;
@@ -14,6 +17,8 @@ import { Component } from '@angular/core';
14
17
  overflow: hidden;
15
18
  white-space: nowrap;
16
19
  transition: padding 0.2s ease, height 0.2s ease, opacity 0.2s ease;
20
+ font-weight: 600;
21
+ font-size: 1rem;
17
22
  }
18
23
  `],
19
24
  })
@@ -33,7 +33,7 @@ const SIDEBAR_WIDTH_ICON = '3rem';
33
33
  .salas-sidebar-inset {
34
34
  flex: 1;
35
35
  min-width: 0;
36
- min-height: 100%;
36
+ min-height: 100vh;
37
37
  padding: 1rem;
38
38
  background-color: var(--salas-bg);
39
39
  color: var(--salas-text);
@@ -22,11 +22,20 @@ const MOBILE_BREAKPOINT = 768;
22
22
  providers: [SidebarService],
23
23
  template: `<div class="salas-sidebar-provider"><ng-content></ng-content></div>`,
24
24
  styles: [`
25
+ :host {
26
+ display: block;
27
+ height: 100%;
28
+ min-height: 100vh;
29
+ overflow: visible;
30
+ }
25
31
  .salas-sidebar-provider {
26
32
  display: flex;
33
+ flex-direction: row;
27
34
  min-height: 100vh;
28
35
  height: 100%;
29
36
  width: 100%;
37
+ position: relative;
38
+ overflow: visible;
30
39
  }
31
40
  `],
32
41
  })
@@ -42,17 +42,21 @@ export interface SidebarProviderProps {
42
42
  styles: [`
43
43
  :host {
44
44
  display: block;
45
+ flex-shrink: 0;
46
+ width: 0;
47
+ min-width: 0;
45
48
  }
46
49
 
47
50
  .salas-sidebar {
48
51
  --salas-sidebar-width: 16rem;
49
52
  --salas-sidebar-width-icon: 3rem;
53
+ box-sizing: border-box;
50
54
  background-color: var(--salas-bg-elevated);
51
55
  color: var(--salas-text);
52
56
  border-right: 1px solid var(--salas-gray-200);
53
57
  display: flex;
54
58
  flex-direction: column;
55
- height: 100%;
59
+ height: 100vh;
56
60
  min-height: 100vh;
57
61
  position: fixed;
58
62
  top: 0;
@@ -61,6 +65,34 @@ export interface SidebarProviderProps {
61
65
  width: var(--salas-sidebar-width);
62
66
  }
63
67
 
68
+ .salas-sidebar > salas-sidebar-header {
69
+ flex-shrink: 0;
70
+ display: block;
71
+ }
72
+ .salas-sidebar > salas-sidebar-content {
73
+ flex: 1 1 0;
74
+ min-height: 0;
75
+ display: flex;
76
+ overflow: hidden;
77
+ }
78
+ .salas-sidebar > salas-sidebar-content > .salas-sidebar-content {
79
+ flex: 1;
80
+ min-height: 0;
81
+ display: block;
82
+ overflow-y: auto;
83
+ overflow-x: hidden;
84
+ width: 100%;
85
+ padding: 0.5rem;
86
+ }
87
+ .salas-sidebar salas-sidebar-menu {
88
+ display: flex;
89
+ flex-direction: column;
90
+ gap: 0.125rem;
91
+ }
92
+ .salas-sidebar salas-sidebar-menu-item {
93
+ display: block;
94
+ }
95
+
64
96
  .salas-sidebar[data-side="left"] {
65
97
  left: 0;
66
98
  }