ngx-opalbytes-components 1.19.0 → 1.21.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 +103 -0
- package/cli/cao-comp.cjs +456 -0
- package/fesm2022/ngx-opalbytes-components.mjs +23 -7
- package/fesm2022/ngx-opalbytes-components.mjs.map +1 -1
- package/package.json +4 -1
- package/src/lib/shared/components/autocomplete/autocomplete.component.html +126 -0
- package/src/lib/shared/components/autocomplete/autocomplete.component.scss +150 -0
- package/src/lib/shared/components/autocomplete/autocomplete.component.ts +552 -0
- package/src/lib/shared/components/autocomplete/autocomplete.stories.ts +133 -0
- package/src/lib/shared/components/base-button/base-button.component.html +33 -0
- package/src/lib/shared/components/base-button/base-button.component.scss +14 -0
- package/src/lib/shared/components/base-button/base-button.component.spec.ts +64 -0
- package/src/lib/shared/components/base-button/base-button.component.ts +48 -0
- package/src/lib/shared/components/base-button/base-button.stories.ts +102 -0
- package/src/lib/shared/components/base-icon/base-icon.css +0 -0
- package/src/lib/shared/components/base-icon/base-icon.html +11 -0
- package/src/lib/shared/components/base-icon/base-icon.spec.ts +23 -0
- package/src/lib/shared/components/base-icon/base-icon.stories.ts +56 -0
- package/src/lib/shared/components/base-icon/base-icon.ts +18 -0
- package/src/lib/shared/components/base-input/base-input.css +193 -0
- package/src/lib/shared/components/base-input/base-input.html +43 -0
- package/src/lib/shared/components/base-input/base-input.spec.ts +146 -0
- package/src/lib/shared/components/base-input/base-input.stories.ts +137 -0
- package/src/lib/shared/components/base-input/base-input.ts +133 -0
- package/src/lib/shared/components/base-time-range/base-time-range.css +27 -0
- package/src/lib/shared/components/base-time-range/base-time-range.html +23 -0
- package/src/lib/shared/components/base-time-range/base-time-range.spec.ts +27 -0
- package/src/lib/shared/components/base-time-range/base-time-range.stories.ts +54 -0
- package/src/lib/shared/components/base-time-range/base-time-range.ts +61 -0
- package/src/lib/shared/components/base-toggle/base-toggle.component.html +28 -0
- package/src/lib/shared/components/base-toggle/base-toggle.component.scss +45 -0
- package/src/lib/shared/components/base-toggle/base-toggle.component.spec.ts +22 -0
- package/src/lib/shared/components/base-toggle/base-toggle.component.ts +138 -0
- package/src/lib/shared/components/base-toggle/base-toggle.stories.ts +63 -0
- package/src/lib/shared/components/card/card.component.css +264 -0
- package/src/lib/shared/components/card/card.component.html +103 -0
- package/src/lib/shared/components/card/card.component.ts +63 -0
- package/src/lib/shared/components/card/card.stories.ts +114 -0
- package/src/lib/shared/components/date-picker/date-picker.html +82 -0
- package/src/lib/shared/components/date-picker/date-picker.scss +8 -0
- package/src/lib/shared/components/date-picker/date-picker.spec.ts +23 -0
- package/src/lib/shared/components/date-picker/date-picker.stories.ts +91 -0
- package/src/lib/shared/components/date-picker/date-picker.ts +165 -0
- package/src/lib/shared/components/drop-down/drop-down.css +61 -0
- package/src/lib/shared/components/drop-down/drop-down.html +96 -0
- package/src/lib/shared/components/drop-down/drop-down.spec.ts +335 -0
- package/src/lib/shared/components/drop-down/drop-down.stories.ts +90 -0
- package/src/lib/shared/components/drop-down/drop-down.ts +335 -0
- package/src/lib/shared/components/footer/footer.css +29 -0
- package/src/lib/shared/components/footer/footer.html +10 -0
- package/src/lib/shared/components/footer/footer.spec.ts +22 -0
- package/src/lib/shared/components/footer/footer.stories.ts +51 -0
- package/src/lib/shared/components/footer/footer.ts +15 -0
- package/src/lib/shared/components/index.ts +19 -0
- package/src/lib/shared/components/kpi/kpi.css +0 -0
- package/src/lib/shared/components/kpi/kpi.html +11 -0
- package/src/lib/shared/components/kpi/kpi.spec.ts +38 -0
- package/src/lib/shared/components/kpi/kpi.stories.ts +65 -0
- package/src/lib/shared/components/kpi/kpi.ts +25 -0
- package/src/lib/shared/components/links-button/links-button.css +70 -0
- package/src/lib/shared/components/links-button/links-button.html +23 -0
- package/src/lib/shared/components/links-button/links-button.spec.ts +139 -0
- package/src/lib/shared/components/links-button/links-button.stories.ts +75 -0
- package/src/lib/shared/components/links-button/links-button.ts +45 -0
- package/src/lib/shared/components/paginator/paginator.css +0 -0
- package/src/lib/shared/components/paginator/paginator.html +10 -0
- package/src/lib/shared/components/paginator/paginator.spec.ts +23 -0
- package/src/lib/shared/components/paginator/paginator.stories.ts +56 -0
- package/src/lib/shared/components/paginator/paginator.ts +25 -0
- package/src/lib/shared/components/stepper/step/step.css +8 -0
- package/src/lib/shared/components/stepper/step/step.html +1 -0
- package/src/lib/shared/components/stepper/step/step.spec.ts +131 -0
- package/src/lib/shared/components/stepper/step/step.ts +14 -0
- package/src/lib/shared/components/stepper/stepper.css +17 -0
- package/src/lib/shared/components/stepper/stepper.html +11 -0
- package/src/lib/shared/components/stepper/stepper.spec.ts +238 -0
- package/src/lib/shared/components/stepper/stepper.stories.ts +77 -0
- package/src/lib/shared/components/stepper/stepper.ts +57 -0
- package/src/lib/shared/components/tab-group/tab-group.component.html +84 -0
- package/src/lib/shared/components/tab-group/tab-group.component.scss +151 -0
- package/src/lib/shared/components/tab-group/tab-group.spec.ts +22 -0
- package/src/lib/shared/components/tab-group/tab-group.stories.ts +102 -0
- package/src/lib/shared/components/tab-group/tab-group.ts +218 -0
- package/src/lib/shared/components/tab-panel/tab-content.directive.ts +7 -0
- package/src/lib/shared/components/tab-panel/tab-label.directive.ts +7 -0
- package/src/lib/shared/components/tab-panel/tab-panel.css +0 -0
- package/src/lib/shared/components/tab-panel/tab-panel.spec.ts +22 -0
- package/src/lib/shared/components/tab-panel/tab-panel.stories.ts +54 -0
- package/src/lib/shared/components/tab-panel/tab-panel.ts +31 -0
- package/src/lib/shared/components/time-picker/time-picker.css +84 -0
- package/src/lib/shared/components/time-picker/time-picker.html +21 -0
- package/src/lib/shared/components/time-picker/time-picker.spec.ts +23 -0
- package/src/lib/shared/components/time-picker/time-picker.stories.ts +66 -0
- package/src/lib/shared/components/time-picker/time-picker.ts +90 -0
- package/types/ngx-opalbytes-components.d.ts +23 -4
package/README.md
CHANGED
|
@@ -72,6 +72,59 @@ export class ExemploComponent {
|
|
|
72
72
|
|
|
73
73
|
---
|
|
74
74
|
|
|
75
|
+
## Comandos CLI
|
|
76
|
+
|
|
77
|
+
A biblioteca disponibiliza uma CLI (`cao-comp`) para copiar o código-fonte de um componente da `ngx-opalbytes-components` para qualquer projeto. Isso é útil quando você precisa customizar o código-fonte de um componente internamente, sem depender apenas da API pública.
|
|
78
|
+
|
|
79
|
+
### Instalação global
|
|
80
|
+
|
|
81
|
+
Para utilizar o comando `cao-comp` de qualquer lugar, instale a biblioteca globalmente:
|
|
82
|
+
|
|
83
|
+
```bash
|
|
84
|
+
npm install -g ngx-opalbytes-components
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
Para desenvolvimento local, a partir da pasta `projects/ngx-opalbytes-components`:
|
|
88
|
+
|
|
89
|
+
```bash
|
|
90
|
+
npm link
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
> Caso não queira instalar, também é possível executar o script diretamente:
|
|
94
|
+
> `node ./node_modules/ngx-opalbytes-components/cli/cao-comp.cjs ...`
|
|
95
|
+
|
|
96
|
+
### Uso
|
|
97
|
+
|
|
98
|
+
```bash
|
|
99
|
+
cao-comp <componente> <destino> [opcoes]
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
**Argumentos:**
|
|
103
|
+
|
|
104
|
+
| Argumento | Descrição |
|
|
105
|
+
| --- | --- |
|
|
106
|
+
| `<componente>` | Nome da pasta do componente em `shared/components` (ex: `base-button`). |
|
|
107
|
+
| `<destino>` | Pasta de destino onde os arquivos serão gerados (criada se não existir). |
|
|
108
|
+
|
|
109
|
+
**Opções:**
|
|
110
|
+
|
|
111
|
+
| Opção | Descrição |
|
|
112
|
+
| --- | --- |
|
|
113
|
+
| `-h, --help` | Exibe a ajuda. |
|
|
114
|
+
| `-l, --list` | Lista os componentes disponíveis para cópia. |
|
|
115
|
+
| `-f, --force` | Sobrescreve arquivos existentes no destino. |
|
|
116
|
+
| `-v, --version` | Exibe a versão. |
|
|
117
|
+
|
|
118
|
+
**Exemplos:**
|
|
119
|
+
|
|
120
|
+
```bash
|
|
121
|
+
cao-comp base-button ./src/app/components
|
|
122
|
+
cao-comp stepper ./src/app/components --force
|
|
123
|
+
cao-comp --list
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
---
|
|
127
|
+
|
|
75
128
|
## Organização de Pastas
|
|
76
129
|
|
|
77
130
|
Dentro da pasta `src/lib/`, os componentes são organizados em `shared/components/` e cada componente reside em sua própria pasta, contendo seus arquivos (`.ts`, `.html`, `.css`, `.spec.ts`).
|
|
@@ -89,6 +142,7 @@ src/
|
|
|
89
142
|
| ├── base-toggle/
|
|
90
143
|
| ├── drop-down/
|
|
91
144
|
| ├── footer/
|
|
145
|
+
| ├── kpi/
|
|
92
146
|
| ├── links-button/
|
|
93
147
|
| ├── paginator/
|
|
94
148
|
| ├── stepper/
|
|
@@ -816,6 +870,55 @@ Um rodapé simples para a aplicação.
|
|
|
816
870
|
|
|
817
871
|
---
|
|
818
872
|
|
|
873
|
+
### `CaoKpi`
|
|
874
|
+
|
|
875
|
+
Um componente de KPI (Key Performance Indicator) que exibe um cartão com ícone, valor, título, cor de texto e cor de borda configuráveis.
|
|
876
|
+
|
|
877
|
+
**Seletor:** `<cao-kpi>`
|
|
878
|
+
|
|
879
|
+
**Interface `ICaoKPI`**
|
|
880
|
+
|
|
881
|
+
| Propriedade | Tipo | Descrição |
|
|
882
|
+
| --- | --- | --- |
|
|
883
|
+
| `title` | `string` | O título do KPI. |
|
|
884
|
+
| `value` | `string` | O valor exibido (ex: `"R$ 12.345"`). |
|
|
885
|
+
| `textColor` | `string` | Cor do texto (valor e título). |
|
|
886
|
+
| `borderColor` | `string` | Cor da borda do cartão. |
|
|
887
|
+
| `icon` | `ICaoImage` | O ícone exibido no canto superior direito. |
|
|
888
|
+
|
|
889
|
+
**Interface `ICaoImage`**
|
|
890
|
+
|
|
891
|
+
| Propriedade | Tipo | Descrição |
|
|
892
|
+
| --- | --- | --- |
|
|
893
|
+
| `src` | `string` | Caminho ou URL da imagem do ícone. |
|
|
894
|
+
| `alt` | `string` | Texto alternativo (acessibilidade) da imagem. |
|
|
895
|
+
|
|
896
|
+
**Atributos (Inputs)**
|
|
897
|
+
|
|
898
|
+
| Atributo | Tipo | Padrão | Descrição |
|
|
899
|
+
| --- | --- | --- | --- |
|
|
900
|
+
| `kpiData` | `ICaoKPI` | — (obrigatório) | Dados do KPI, recebidos via `input.required`. |
|
|
901
|
+
|
|
902
|
+
**Exemplo de uso:**
|
|
903
|
+
|
|
904
|
+
```html
|
|
905
|
+
<cao-kpi [kpiData]="meuKpi"></cao-kpi>
|
|
906
|
+
```
|
|
907
|
+
|
|
908
|
+
```typescript
|
|
909
|
+
import { CaoKpi, ICaoKPI } from 'ngx-opalbytes-components';
|
|
910
|
+
|
|
911
|
+
meuKpi: ICaoKPI = {
|
|
912
|
+
title: 'Total de Vendas',
|
|
913
|
+
value: 'R$ 12.345',
|
|
914
|
+
textColor: '#16a34a',
|
|
915
|
+
borderColor: '#16a34a',
|
|
916
|
+
icon: { src: 'assets/icon-vendas.svg', alt: 'Vendas' }
|
|
917
|
+
};
|
|
918
|
+
```
|
|
919
|
+
|
|
920
|
+
---
|
|
921
|
+
|
|
819
922
|
### `LinksButton`
|
|
820
923
|
Exibe uma lista de links de navegação como botões.
|
|
821
924
|
|
package/cli/cao-comp.cjs
ADDED
|
@@ -0,0 +1,456 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
'use strict';
|
|
3
|
+
|
|
4
|
+
const fs = require('fs');
|
|
5
|
+
const path = require('path');
|
|
6
|
+
|
|
7
|
+
const USAGE = `cao-comp — Copia um componente da lib ngx-opalbytes-components para qualquer projeto
|
|
8
|
+
e gera o setup de Storybook para visualizar os componentes
|
|
9
|
+
|
|
10
|
+
Uso:
|
|
11
|
+
cao-comp <componente> <destino> [opcoes]
|
|
12
|
+
cao-comp storybook <destino> [opcoes]
|
|
13
|
+
|
|
14
|
+
Argumentos:
|
|
15
|
+
<componente> Nome da pasta do componente em shared/components (ex: base-button)
|
|
16
|
+
<destino> Pasta de destino onde os arquivos serao gerados (criada se nao existir)
|
|
17
|
+
|
|
18
|
+
Opcoes:
|
|
19
|
+
-h, --help Exibe esta ajuda
|
|
20
|
+
-l, --list Lista os componentes disponiveis para copia
|
|
21
|
+
-f, --force Sobrescreve arquivos existentes no destino
|
|
22
|
+
-v, --version Exibe a versao
|
|
23
|
+
|
|
24
|
+
Subcomando storybook:
|
|
25
|
+
Gera o setup minimo do Storybook (.storybook/, exemplo de story e STORYBOOK-SETUP.md)
|
|
26
|
+
em <destino>, pronto para visualizar os componentes copiados.
|
|
27
|
+
|
|
28
|
+
Exemplos:
|
|
29
|
+
cao-comp base-button ./src/app/components
|
|
30
|
+
cao-comp stepper ./src/app/components --force
|
|
31
|
+
cao-comp --list
|
|
32
|
+
cao-comp storybook ./meu-projeto
|
|
33
|
+
cao-comp base-button ./meu-projeto/src/app/components && cao-comp storybook ./meu-projeto
|
|
34
|
+
`;
|
|
35
|
+
|
|
36
|
+
const STORYBOOK_FILES = {
|
|
37
|
+
'.storybook/main.ts': `import type { StorybookConfig } from '@storybook/angular-vite';
|
|
38
|
+
|
|
39
|
+
const config: StorybookConfig = {
|
|
40
|
+
"stories": [
|
|
41
|
+
"../src/**/*.mdx",
|
|
42
|
+
"../src/**/*.stories.@(js|jsx|mjs|ts|tsx)"
|
|
43
|
+
],
|
|
44
|
+
"addons": [
|
|
45
|
+
"@storybook/addon-essentials",
|
|
46
|
+
"@storybook/addon-a11y",
|
|
47
|
+
"@storybook/addon-docs",
|
|
48
|
+
"@storybook/addon-onboarding"
|
|
49
|
+
],
|
|
50
|
+
"framework": {
|
|
51
|
+
"name": "@storybook/angular-vite",
|
|
52
|
+
"options": {
|
|
53
|
+
"compodoc": false,
|
|
54
|
+
"compodocArgs": [
|
|
55
|
+
"-e",
|
|
56
|
+
"json",
|
|
57
|
+
"-d",
|
|
58
|
+
"."
|
|
59
|
+
]
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
};
|
|
63
|
+
export default config;
|
|
64
|
+
`,
|
|
65
|
+
'.storybook/preview.ts': `import type { Preview } from '@storybook/angular-vite';
|
|
66
|
+
|
|
67
|
+
// Para habilitar as docs automaticas (argTypes) com Compodoc:
|
|
68
|
+
// 1. Gere o documentation.json: npx @compodoc/compodoc -p tsconfig.json -e json -d .
|
|
69
|
+
// 2. Coloque "compodoc": true no framework options do .storybook/main.ts
|
|
70
|
+
// 3. Descomente as linhas abaixo:
|
|
71
|
+
// import { setCompodocJson } from '@storybook/addon-docs/angular';
|
|
72
|
+
// import docJson from '../documentation.json';
|
|
73
|
+
// setCompodocJson(docJson);
|
|
74
|
+
|
|
75
|
+
const preview: Preview = {
|
|
76
|
+
parameters: {
|
|
77
|
+
controls: {
|
|
78
|
+
matchers: {
|
|
79
|
+
color: /(background|color)$/i,
|
|
80
|
+
date: /Date$/i,
|
|
81
|
+
},
|
|
82
|
+
},
|
|
83
|
+
},
|
|
84
|
+
};
|
|
85
|
+
|
|
86
|
+
export default preview;
|
|
87
|
+
`,
|
|
88
|
+
'.storybook/tsconfig.json': `{
|
|
89
|
+
"extends": "../tsconfig.json",
|
|
90
|
+
"compilerOptions": {
|
|
91
|
+
"allowSyntheticDefaultImports": true,
|
|
92
|
+
"esModuleInterop": true,
|
|
93
|
+
"resolveJsonModule": true,
|
|
94
|
+
"skipLibCheck": true,
|
|
95
|
+
"types": ["node"]
|
|
96
|
+
},
|
|
97
|
+
"include": ["../src/**/*.stories.*", "./preview.ts", "./main.ts", "./typings.d.ts"]
|
|
98
|
+
}
|
|
99
|
+
`,
|
|
100
|
+
'.storybook/typings.d.ts': `declare module '*.md';
|
|
101
|
+
`,
|
|
102
|
+
};
|
|
103
|
+
|
|
104
|
+
const EXAMPLE_STORY_LINES = [
|
|
105
|
+
`import { Component, EventEmitter, Input, Output } from '@angular/core';`,
|
|
106
|
+
`import type { Meta, StoryObj } from '@storybook/angular-vite';`,
|
|
107
|
+
`import { fn } from 'storybook/test';`,
|
|
108
|
+
``,
|
|
109
|
+
`@Component({`,
|
|
110
|
+
` standalone: true,`,
|
|
111
|
+
` selector: 'storybook-example-button',`,
|
|
112
|
+
` template: \``,
|
|
113
|
+
` <button`,
|
|
114
|
+
` type="button"`,
|
|
115
|
+
` (click)="onClick.emit()"`,
|
|
116
|
+
` [disabled]="isDisabled"`,
|
|
117
|
+
` style="padding:10px 18px;font-size:14px;cursor:pointer;border-radius:6px;border:1px solid #4f46e5;background:#4f46e5;color:#fff;">`,
|
|
118
|
+
` {{ label }}`,
|
|
119
|
+
` </button>`,
|
|
120
|
+
` \`,`,
|
|
121
|
+
`})`,
|
|
122
|
+
`export class StorybookExampleButtonComponent {`,
|
|
123
|
+
` @Input() label = 'Clique!';`,
|
|
124
|
+
` @Input() isDisabled = false;`,
|
|
125
|
+
` @Output() readonly onClick = new EventEmitter<void>();`,
|
|
126
|
+
`}`,
|
|
127
|
+
``,
|
|
128
|
+
`const meta: Meta<StorybookExampleButtonComponent> = {`,
|
|
129
|
+
` title: 'Exemplo/Cao Button',`,
|
|
130
|
+
` component: StorybookExampleButtonComponent,`,
|
|
131
|
+
` tags: ['autodocs'],`,
|
|
132
|
+
` args: { onClick: fn() },`,
|
|
133
|
+
`};`,
|
|
134
|
+
``,
|
|
135
|
+
`export default meta;`,
|
|
136
|
+
`type Story = StoryObj<StorybookExampleButtonComponent>;`,
|
|
137
|
+
``,
|
|
138
|
+
`export const Default: Story = {`,
|
|
139
|
+
` args: { label: 'Clique!' },`,
|
|
140
|
+
`};`,
|
|
141
|
+
``,
|
|
142
|
+
`export const ComIconeTexto: Story = {`,
|
|
143
|
+
` args: { label: 'Salvar' },`,
|
|
144
|
+
`};`,
|
|
145
|
+
``,
|
|
146
|
+
`export const Desabilitado: Story = {`,
|
|
147
|
+
` args: { label: 'Bloqueado', isDisabled: true },`,
|
|
148
|
+
`};`,
|
|
149
|
+
``,
|
|
150
|
+
];
|
|
151
|
+
|
|
152
|
+
const STORYBOOK_SETUP_DOC = `# Storybook — Setup gerado pelo cao-comp
|
|
153
|
+
|
|
154
|
+
Este diretorio contem o setup minimo do Storybook para visualizar os
|
|
155
|
+
componentes da lib ngx-opalbytes-components em um projeto externo.
|
|
156
|
+
|
|
157
|
+
## 1. Instalar as dependencias (no destino)
|
|
158
|
+
|
|
159
|
+
Adicione as dependencias de desenvolvimento:
|
|
160
|
+
|
|
161
|
+
\`\`\`bash
|
|
162
|
+
npm i -D storybook @storybook/angular-vite @storybook/addon-essentials @storybook/addon-a11y @storybook/addon-docs @storybook/addon-onboarding @compodoc/compodoc
|
|
163
|
+
\`\`\`
|
|
164
|
+
|
|
165
|
+
Certifique-se de que as peer dependencies dos componentes estao instaladas:
|
|
166
|
+
\`@angular/core\`, \`@angular/common\`, \`@angular/material\`, \`@angular/cdk\`,
|
|
167
|
+
\`@lucide/angular\` e \`ngx-mask\`.
|
|
168
|
+
|
|
169
|
+
## 2. Copiar os componentes que deseja visualizar
|
|
170
|
+
|
|
171
|
+
\`\`\`bash
|
|
172
|
+
cao-comp base-button ./src/app/components
|
|
173
|
+
cao-comp base-input ./src/app/components
|
|
174
|
+
cao-comp --list # lista todos os componentes disponiveis
|
|
175
|
+
\`\`\`
|
|
176
|
+
|
|
177
|
+
## 3. Criar stories para os componentes copiados
|
|
178
|
+
|
|
179
|
+
Abra \`src/stories/CaoButton.stories.ts\` (exemplo gerado) ou crie arquivos
|
|
180
|
+
\`*.stories.ts\` junto dos componentes. Exemplo:
|
|
181
|
+
|
|
182
|
+
\`\`\`ts
|
|
183
|
+
import type { Meta, StoryObj } from '@storybook/angular-vite';
|
|
184
|
+
import { fn } from 'storybook/test';
|
|
185
|
+
import { CaoBaseButtonComponent } from '../../app/components/base-button/base-button.component';
|
|
186
|
+
|
|
187
|
+
const meta: Meta<CaoBaseButtonComponent> = {
|
|
188
|
+
title: 'Components/Base Button',
|
|
189
|
+
component: CaoBaseButtonComponent,
|
|
190
|
+
tags: ['autodocs'],
|
|
191
|
+
args: { buttonClick: fn() },
|
|
192
|
+
};
|
|
193
|
+
|
|
194
|
+
export default meta;
|
|
195
|
+
type Story = StoryObj<CaoBaseButtonComponent>;
|
|
196
|
+
|
|
197
|
+
export const Default: Story = { args: { buttonText: 'Clique!' } };
|
|
198
|
+
export const ComIcone: Story = { args: { buttonText: 'Salvar', leadingIcon: 'Save', isLucideIcon: true } };
|
|
199
|
+
\`\`\`
|
|
200
|
+
|
|
201
|
+
## 4. Rodar
|
|
202
|
+
|
|
203
|
+
\`\`\`bash
|
|
204
|
+
# Servidor de desenvolvimento (porta 6006)
|
|
205
|
+
npx storybook dev -c .storybook -p 6006
|
|
206
|
+
|
|
207
|
+
# Build estatico
|
|
208
|
+
npx storybook build -c .storybook -o storybook-static
|
|
209
|
+
\`\`\`
|
|
210
|
+
|
|
211
|
+
Dica: adicione ao package.json do projeto de destino:
|
|
212
|
+
|
|
213
|
+
\`\`\`json
|
|
214
|
+
{
|
|
215
|
+
"scripts": {
|
|
216
|
+
"storybook": "storybook dev -c .storybook -p 6006",
|
|
217
|
+
"build-storybook": "storybook build -c .storybook -o storybook-static"
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
\`\`\`
|
|
221
|
+
|
|
222
|
+
## Opcional: Compodoc (docs automaticas)
|
|
223
|
+
|
|
224
|
+
1. Gere o JSON de documentacao na raiz do destino:
|
|
225
|
+
\`\`\`bash
|
|
226
|
+
npx @compodoc/compodoc -p tsconfig.json -e json -d .
|
|
227
|
+
\`\`\`
|
|
228
|
+
2. No \`.storybook/main.ts\`, altere \`"compodoc": false\` para \`"compodoc": true\`.
|
|
229
|
+
3. No \`.storybook/preview.ts\`, descomente o bloco do Compodoc.
|
|
230
|
+
|
|
231
|
+
> O \`--force\` sobrescreve os arquivos gerados pelo cao-comp no destino.
|
|
232
|
+
`;
|
|
233
|
+
|
|
234
|
+
function resolveTemplatesDir() {
|
|
235
|
+
const candidates = [
|
|
236
|
+
path.join(__dirname, '..', 'templates'),
|
|
237
|
+
path.join(__dirname, '..', 'src', 'lib', 'shared', 'components'),
|
|
238
|
+
path.join(__dirname, '..', '..', 'src', 'lib', 'shared', 'components'),
|
|
239
|
+
];
|
|
240
|
+
for (const dir of candidates) {
|
|
241
|
+
if (fs.existsSync(dir) && fs.statSync(dir).isDirectory()) {
|
|
242
|
+
return dir;
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
return null;
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
function resolvePackageVersion() {
|
|
249
|
+
const candidates = [
|
|
250
|
+
path.join(__dirname, '..', 'package.json'),
|
|
251
|
+
path.join(__dirname, '..', '..', 'package.json'),
|
|
252
|
+
path.join(__dirname, '..', '..', '..', 'package.json'),
|
|
253
|
+
];
|
|
254
|
+
for (const file of candidates) {
|
|
255
|
+
if (fs.existsSync(file)) {
|
|
256
|
+
try {
|
|
257
|
+
const pkg = JSON.parse(fs.readFileSync(file, 'utf8'));
|
|
258
|
+
if (pkg && pkg.version) {
|
|
259
|
+
return pkg.version;
|
|
260
|
+
}
|
|
261
|
+
} catch (_) {
|
|
262
|
+
/* ignore */
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
}
|
|
266
|
+
return 'desconhecida';
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
function listComponents(templatesDir) {
|
|
270
|
+
return fs
|
|
271
|
+
.readdirSync(templatesDir, { withFileTypes: true })
|
|
272
|
+
.filter((e) => e.isDirectory())
|
|
273
|
+
.map((e) => e.name)
|
|
274
|
+
.sort();
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
function copyRecursive(src, dest, force, conflicts) {
|
|
278
|
+
for (const entry of fs.readdirSync(src, { withFileTypes: true })) {
|
|
279
|
+
const srcPath = path.join(src, entry.name);
|
|
280
|
+
const destPath = path.join(dest, entry.name);
|
|
281
|
+
if (entry.isDirectory()) {
|
|
282
|
+
fs.mkdirSync(destPath, { recursive: true });
|
|
283
|
+
copyRecursive(srcPath, destPath, force, conflicts);
|
|
284
|
+
} else {
|
|
285
|
+
if (fs.existsSync(destPath) && !force) {
|
|
286
|
+
conflicts.push(destPath);
|
|
287
|
+
continue;
|
|
288
|
+
}
|
|
289
|
+
fs.mkdirSync(path.dirname(destPath), { recursive: true });
|
|
290
|
+
fs.copyFileSync(srcPath, destPath);
|
|
291
|
+
}
|
|
292
|
+
}
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
function writeFileIfAllowed(filePath, content, force, conflicts) {
|
|
296
|
+
if (fs.existsSync(filePath) && !force) {
|
|
297
|
+
conflicts.push(filePath);
|
|
298
|
+
return false;
|
|
299
|
+
}
|
|
300
|
+
fs.mkdirSync(path.dirname(filePath), { recursive: true });
|
|
301
|
+
fs.writeFileSync(filePath, content);
|
|
302
|
+
return true;
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
function setupStorybook(destination, force) {
|
|
306
|
+
const root = path.resolve(destination);
|
|
307
|
+
const conflicts = [];
|
|
308
|
+
const created = [];
|
|
309
|
+
|
|
310
|
+
for (const [rel, content] of Object.entries(STORYBOOK_FILES)) {
|
|
311
|
+
const file = path.join(root, rel);
|
|
312
|
+
if (writeFileIfAllowed(file, content, force, conflicts)) {
|
|
313
|
+
created.push(path.relative(root, file));
|
|
314
|
+
}
|
|
315
|
+
}
|
|
316
|
+
|
|
317
|
+
const storyFile = path.join(root, 'src', 'stories', 'CaoButton.stories.ts');
|
|
318
|
+
if (writeFileIfAllowed(storyFile, EXAMPLE_STORY_LINES.join('\n'), force, conflicts)) {
|
|
319
|
+
created.push(path.relative(root, storyFile));
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
const docFile = path.join(root, 'STORYBOOK-SETUP.md');
|
|
323
|
+
if (writeFileIfAllowed(docFile, STORYBOOK_SETUP_DOC, force, conflicts)) {
|
|
324
|
+
created.push(path.relative(root, docFile));
|
|
325
|
+
}
|
|
326
|
+
|
|
327
|
+
if (conflicts.length) {
|
|
328
|
+
process.stderr.write(
|
|
329
|
+
`Erro: os seguintes arquivos ja existem no destino (use --force para sobrescrever):\n` +
|
|
330
|
+
conflicts.map((c) => ` - ${c}`).join('\n') +
|
|
331
|
+
'\n'
|
|
332
|
+
);
|
|
333
|
+
return 1;
|
|
334
|
+
}
|
|
335
|
+
|
|
336
|
+
process.stdout.write(
|
|
337
|
+
`Setup de Storybook gerado em "${root}".\n` +
|
|
338
|
+
`Arquivos criados:\n` +
|
|
339
|
+
created.map((c) => ` - ${c}`).join('\n') +
|
|
340
|
+
'\n' +
|
|
341
|
+
`Leia ${path.join(root, 'STORYBOOK-SETUP.md')} para instalar as dependencias e rodar.\n`
|
|
342
|
+
);
|
|
343
|
+
return 0;
|
|
344
|
+
}
|
|
345
|
+
|
|
346
|
+
function parseArgs(argv) {
|
|
347
|
+
const positionals = [];
|
|
348
|
+
const flags = { help: false, list: false, force: false, version: false };
|
|
349
|
+
for (let i = 0; i < argv.length; i++) {
|
|
350
|
+
const arg = argv[i];
|
|
351
|
+
switch (arg) {
|
|
352
|
+
case '-h':
|
|
353
|
+
case '--help':
|
|
354
|
+
flags.help = true;
|
|
355
|
+
break;
|
|
356
|
+
case '-l':
|
|
357
|
+
case '--list':
|
|
358
|
+
flags.list = true;
|
|
359
|
+
break;
|
|
360
|
+
case '-f':
|
|
361
|
+
case '--force':
|
|
362
|
+
flags.force = true;
|
|
363
|
+
break;
|
|
364
|
+
case '-v':
|
|
365
|
+
case '--version':
|
|
366
|
+
flags.version = true;
|
|
367
|
+
break;
|
|
368
|
+
default:
|
|
369
|
+
positionals.push(arg);
|
|
370
|
+
}
|
|
371
|
+
}
|
|
372
|
+
return { positionals, flags };
|
|
373
|
+
}
|
|
374
|
+
|
|
375
|
+
function main() {
|
|
376
|
+
const argv = process.argv.slice(2);
|
|
377
|
+
const { positionals, flags } = parseArgs(argv);
|
|
378
|
+
|
|
379
|
+
if (flags.help) {
|
|
380
|
+
process.stdout.write(USAGE + '\n');
|
|
381
|
+
return 0;
|
|
382
|
+
}
|
|
383
|
+
|
|
384
|
+
if (flags.version) {
|
|
385
|
+
process.stdout.write(`cao-comp ${resolvePackageVersion()}\n`);
|
|
386
|
+
return 0;
|
|
387
|
+
}
|
|
388
|
+
|
|
389
|
+
const templatesDir = resolveTemplatesDir();
|
|
390
|
+
if (!templatesDir) {
|
|
391
|
+
process.stderr.write(
|
|
392
|
+
'Erro: nao foi possivel localizar a pasta de templates dos componentes.\n'
|
|
393
|
+
);
|
|
394
|
+
return 1;
|
|
395
|
+
}
|
|
396
|
+
|
|
397
|
+
if (flags.list) {
|
|
398
|
+
const components = listComponents(templatesDir);
|
|
399
|
+
process.stdout.write('Componentes disponiveis:\n');
|
|
400
|
+
for (const c of components) {
|
|
401
|
+
process.stdout.write(` - ${c}\n`);
|
|
402
|
+
}
|
|
403
|
+
return 0;
|
|
404
|
+
}
|
|
405
|
+
|
|
406
|
+
const [first, second] = positionals;
|
|
407
|
+
|
|
408
|
+
if (first === 'storybook') {
|
|
409
|
+
if (!second) {
|
|
410
|
+
process.stderr.write(
|
|
411
|
+
'Erro: informe o destino do Storybook.\n\n' + USAGE + '\n'
|
|
412
|
+
);
|
|
413
|
+
return 1;
|
|
414
|
+
}
|
|
415
|
+
return setupStorybook(second, flags.force);
|
|
416
|
+
}
|
|
417
|
+
|
|
418
|
+
const component = first;
|
|
419
|
+
const destination = second;
|
|
420
|
+
if (!component || !destination) {
|
|
421
|
+
process.stderr.write(
|
|
422
|
+
'Erro: informe o componente e o destino.\n\n' + USAGE + '\n'
|
|
423
|
+
);
|
|
424
|
+
return 1;
|
|
425
|
+
}
|
|
426
|
+
|
|
427
|
+
const sourceDir = path.join(templatesDir, component);
|
|
428
|
+
if (!fs.existsSync(sourceDir) || !fs.statSync(sourceDir).isDirectory()) {
|
|
429
|
+
const available = listComponents(templatesDir).join(', ');
|
|
430
|
+
process.stderr.write(
|
|
431
|
+
`Erro: componente "${component}" nao encontrado.\n` +
|
|
432
|
+
`Componentes disponiveis: ${available}\n`
|
|
433
|
+
);
|
|
434
|
+
return 1;
|
|
435
|
+
}
|
|
436
|
+
|
|
437
|
+
fs.mkdirSync(destination, { recursive: true });
|
|
438
|
+
const conflicts = [];
|
|
439
|
+
copyRecursive(sourceDir, destination, flags.force, conflicts);
|
|
440
|
+
|
|
441
|
+
if (conflicts.length) {
|
|
442
|
+
process.stderr.write(
|
|
443
|
+
`Erro: os seguintes arquivos ja existem no destino (use --force para sobrescrever):\n` +
|
|
444
|
+
conflicts.map((c) => ` - ${c}`).join('\n') +
|
|
445
|
+
'\n'
|
|
446
|
+
);
|
|
447
|
+
return 1;
|
|
448
|
+
}
|
|
449
|
+
|
|
450
|
+
process.stdout.write(
|
|
451
|
+
`Componente "${component}" copiado para "${destination}".\n`
|
|
452
|
+
);
|
|
453
|
+
return 0;
|
|
454
|
+
}
|
|
455
|
+
|
|
456
|
+
process.exit(main());
|