@salas-ds/cli 0.2.0 → 0.2.2
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 +69 -34
- package/package.json +1 -1
- package/templates/angular/checkbox/checkbox.component.ts +2 -2
- package/templates/angular/dialog/dialog.component.ts +2 -31
- package/templates/angular/sidebar/sidebar-content.component.ts +7 -0
- package/templates/angular/sidebar/sidebar-header.component.ts +5 -0
- package/templates/angular/sidebar/sidebar-inset.component.ts +1 -1
- package/templates/angular/sidebar/sidebar-provider.component.ts +9 -0
- package/templates/angular/sidebar/sidebar.component.ts +33 -1
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
|
|
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
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 =
|
|
263
|
+
const componentsPath = path.join(projectRoot, options.path);
|
|
234
264
|
try {
|
|
235
|
-
const angularJsonPath =
|
|
236
|
-
const isAngular = await
|
|
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
|
|
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
|
|
251
|
-
const cssPath =
|
|
252
|
-
await
|
|
253
|
-
const utilsPath =
|
|
254
|
-
await
|
|
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
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
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
|
-
|
|
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 =
|
|
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 =
|
|
314
|
-
if (!await
|
|
348
|
+
const configPath = path.join(projectRoot, CONFIG_FILE2);
|
|
349
|
+
if (!await fs.pathExists(configPath)) {
|
|
315
350
|
return null;
|
|
316
351
|
}
|
|
317
|
-
return
|
|
352
|
+
return fs.readJSON(configPath);
|
|
318
353
|
}
|
|
319
354
|
async function addSingleComponent(componentName, componentsDir, options) {
|
|
320
355
|
const projectRoot = process.cwd();
|
|
321
|
-
const componentPath =
|
|
322
|
-
if (await
|
|
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
|
|
362
|
+
await fs.remove(componentPath);
|
|
328
363
|
}
|
|
329
|
-
await
|
|
330
|
-
const templatePath =
|
|
331
|
-
if (!await
|
|
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 =
|
|
342
|
-
const destPath =
|
|
343
|
-
await
|
|
344
|
-
await
|
|
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 = `./${
|
|
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
|
@@ -138,8 +138,8 @@ export class SalasCheckboxComponent implements CheckboxProps, ControlValueAccess
|
|
|
138
138
|
}
|
|
139
139
|
|
|
140
140
|
@HostListener('keydown.space', ['$event'])
|
|
141
|
-
handleSpace(event:
|
|
142
|
-
event.preventDefault();
|
|
141
|
+
handleSpace(event: Event): void {
|
|
142
|
+
(event as KeyboardEvent).preventDefault();
|
|
143
143
|
this.toggle();
|
|
144
144
|
}
|
|
145
145
|
|
|
@@ -1,35 +1,4 @@
|
|
|
1
1
|
import {
|
|
2
|
-
|
|
3
|
-
export type DialogSize = 'default' | 'sm';
|
|
4
|
-
|
|
5
|
-
export interface DialogProps {
|
|
6
|
-
/**
|
|
7
|
-
* Controlled open state. If provided, the dialog becomes controlled and
|
|
8
|
-
* will not manage its own internal state.
|
|
9
|
-
*/
|
|
10
|
-
open?: boolean;
|
|
11
|
-
/**
|
|
12
|
-
* Width of the dialog panel. Accepts any valid CSS width value (e.g. '480px', '32rem', '50%').
|
|
13
|
-
*/
|
|
14
|
-
width?: string;
|
|
15
|
-
/**
|
|
16
|
-
* Height of the dialog panel. Accepts any valid CSS height value.
|
|
17
|
-
*/
|
|
18
|
-
height?: string;
|
|
19
|
-
/**
|
|
20
|
-
* Named size preset. When provided, defines sensible defaults for width and padding.
|
|
21
|
-
*/
|
|
22
|
-
size?: DialogSize;
|
|
23
|
-
/**
|
|
24
|
-
* If true, closes the dialog when the user clicks on the overlay.
|
|
25
|
-
*/
|
|
26
|
-
closeOnOverlayClick?: boolean;
|
|
27
|
-
/**
|
|
28
|
-
* If true, hides the X close button in the top-right corner.
|
|
29
|
-
*/
|
|
30
|
-
hideCloseButton?: boolean;
|
|
31
|
-
}
|
|
32
|
-
|
|
33
2
|
Component,
|
|
34
3
|
Input,
|
|
35
4
|
Output,
|
|
@@ -38,6 +7,8 @@ export interface DialogProps {
|
|
|
38
7
|
HostListener,
|
|
39
8
|
} from '@angular/core';
|
|
40
9
|
|
|
10
|
+
export type DialogSize = 'default' | 'sm';
|
|
11
|
+
|
|
41
12
|
@Component({
|
|
42
13
|
selector: 'salas-dialog',
|
|
43
14
|
standalone: true,
|
|
@@ -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
|
})
|
|
@@ -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:
|
|
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
|
}
|