@1e99/components 0.1.0 → 0.1.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/LICENSE +21 -0
- package/README.md +57 -188
- package/package.json +4 -3
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 1e99
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
CHANGED
|
@@ -1,42 +1,32 @@
|
|
|
1
1
|
# @1e99/components
|
|
2
2
|
|
|
3
|
-
Componentes React
|
|
4
|
-
`GoogleSignInButton` e `Selector` foram extraídos fielmente de
|
|
5
|
-
`domain-website` e `curriculo`, sem introduzir dependência de Next.js,
|
|
6
|
-
autenticação, i18n ou geração de PDF.
|
|
3
|
+
Componentes React reutilizáveis, estilizados com Tailwind CSS.
|
|
7
4
|
|
|
8
|
-
## Instalação
|
|
9
|
-
|
|
10
|
-
Após a primeira publicação pública, instale o pacote no app consumidor:
|
|
5
|
+
## Instalação
|
|
11
6
|
|
|
12
7
|
```sh
|
|
13
8
|
pnpm add @1e99/components
|
|
14
9
|
```
|
|
15
10
|
|
|
16
|
-
O pacote declara `react`, `react-dom`, `react-icons` e `tailwindcss` como
|
|
17
|
-
|
|
18
|
-
ícones Google e Lucide que o pacote renderiza, sem duplicar SVGs manualmente.
|
|
11
|
+
O pacote declara `react`, `react-dom`, `react-icons` e `tailwindcss` como peer
|
|
12
|
+
dependencies.
|
|
19
13
|
|
|
20
14
|
### Tailwind CSS 4
|
|
21
15
|
|
|
22
|
-
O Tailwind 4 não
|
|
23
|
-
|
|
24
|
-
|
|
16
|
+
O Tailwind 4 não examina automaticamente classes em `node_modules`. Na folha
|
|
17
|
+
CSS que importa o Tailwind, adicione uma diretiva `@source` cujo caminho seja
|
|
18
|
+
relativo a ela:
|
|
25
19
|
|
|
26
20
|
```css
|
|
21
|
+
@import "tailwindcss";
|
|
27
22
|
@source "../../node_modules/@1e99/components/dist";
|
|
28
23
|
```
|
|
29
24
|
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
- `domain-website/src/app/globals.css`;
|
|
33
|
-
- `curriculo/src/app/brand.css`.
|
|
34
|
-
|
|
35
|
-
Os dois projetos já fornecem os tokens usados pela navbar, incluindo
|
|
25
|
+
Os componentes usam tokens Tailwind do tema do aplicativo, como
|
|
36
26
|
`surface-page`, `content-primary`, `content-secondary`, `border-subtle`,
|
|
37
27
|
`action-primary`, `surface-raised`, `content-inverse`, `shadow-card`,
|
|
38
28
|
`shadow-float`, `shadow-focus`, `ease-brand`, `shell`, `control` e `card`.
|
|
39
|
-
O pacote não
|
|
29
|
+
O pacote não cria tokens nem importa CSS global.
|
|
40
30
|
|
|
41
31
|
## Uso
|
|
42
32
|
|
|
@@ -48,117 +38,65 @@ import {
|
|
|
48
38
|
Selector,
|
|
49
39
|
} from "@1e99/components";
|
|
50
40
|
|
|
51
|
-
|
|
52
|
-
label:
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
};
|
|
56
|
-
|
|
57
|
-
const localeOptions = [
|
|
58
|
-
{ value: "pt", label: "Português", languageTag: "pt-BR" },
|
|
59
|
-
{ value: "en", label: "English", languageTag: "en" },
|
|
60
|
-
{ value: "es", label: "Español", languageTag: "es" },
|
|
61
|
-
] satisfies readonly LocaleOption[];
|
|
41
|
+
const languageOptions = [
|
|
42
|
+
{label: "Português", value: "pt"},
|
|
43
|
+
{label: "English", value: "en"},
|
|
44
|
+
] as const;
|
|
62
45
|
|
|
63
46
|
function Header() {
|
|
64
|
-
const [
|
|
47
|
+
const [language, setLanguage] = useState("pt");
|
|
65
48
|
|
|
66
49
|
return (
|
|
67
50
|
<Navbar
|
|
68
|
-
brand={<a href="/"><BrandLogo /></a>}
|
|
69
|
-
items={[
|
|
70
|
-
{ href: "/apps", label: "Apps" },
|
|
71
|
-
{ href: "/about", label: "Sobre" },
|
|
72
|
-
]}
|
|
73
|
-
navigationLabel="Navegação principal"
|
|
74
|
-
renderLink={({ href, children, className }) => (
|
|
75
|
-
<Link className={className} href={href}>{children}</Link>
|
|
76
|
-
)}
|
|
77
51
|
actions={
|
|
78
52
|
<div className="hidden items-center gap-3 md:flex">
|
|
79
53
|
<Selector
|
|
80
|
-
label=
|
|
81
|
-
onValueChange={
|
|
82
|
-
options={
|
|
83
|
-
|
|
84
|
-
<span lang={option.languageTag}>{option.label}</span>
|
|
85
|
-
)}
|
|
86
|
-
renderTrigger={({ selectedOption, value }) => (
|
|
87
|
-
<span lang={selectedOption?.languageTag}>
|
|
88
|
-
{selectedOption?.label ?? value}
|
|
89
|
-
</span>
|
|
90
|
-
)}
|
|
91
|
-
value={locale}
|
|
54
|
+
label="Idioma"
|
|
55
|
+
onValueChange={setLanguage}
|
|
56
|
+
options={languageOptions}
|
|
57
|
+
value={language}
|
|
92
58
|
/>
|
|
93
59
|
<GoogleSignInButton
|
|
94
|
-
label=
|
|
95
|
-
onClick={
|
|
60
|
+
label="Entrar com Google"
|
|
61
|
+
onClick={() => undefined}
|
|
96
62
|
/>
|
|
97
63
|
</div>
|
|
98
64
|
}
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
navigationLabel: t("mobileNavigation"),
|
|
106
|
-
actions: <MobileAccountActions />,
|
|
107
|
-
}}
|
|
65
|
+
brand={<a aria-label="Início" href="/">Marca</a>}
|
|
66
|
+
items={[
|
|
67
|
+
{href: "/products", label: "Produtos"},
|
|
68
|
+
{href: "/about", label: "Sobre"},
|
|
69
|
+
]}
|
|
70
|
+
navigationLabel="Navegação principal"
|
|
108
71
|
/>
|
|
109
72
|
);
|
|
110
73
|
}
|
|
111
74
|
```
|
|
112
75
|
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
| `linkTreatment` | `plain` (padrão), `underlined` | curriculo / domain-website |
|
|
118
|
-
| `linkWeight` | `semibold` (padrão), `bold` | domain-website / curriculo |
|
|
119
|
-
| `mobileNavigation` | ausente ou objeto de disclosure | curriculo / domain-website |
|
|
120
|
-
|
|
121
|
-
`brand` e `actions` são slots e, junto da navegação desktop, permanecem como
|
|
122
|
-
regiões irmãs no container — o mesmo layout dos dois headers fonte. O objeto
|
|
123
|
-
`mobileNavigation` reproduz o menu do domain (botão azul de 48px e painel
|
|
124
|
-
elevado); ele fica ausente no perfil do currículo. `renderLink` recebe `href`,
|
|
125
|
-
`children` e `className`, permitindo usar `next/link`, `next-intl/link` ou
|
|
126
|
-
outro roteador sem acoplar o pacote a ele.
|
|
127
|
-
|
|
128
|
-
### Controles de header
|
|
76
|
+
`Navbar` mantém marca, itens de navegação e ações como regiões independentes.
|
|
77
|
+
Use `renderLink` para integrar um roteador próprio sem acoplar o pacote a uma
|
|
78
|
+
biblioteca de navegação. Os itens podem ser adicionados ou removidos, e
|
|
79
|
+
`actions` e `mobileNavigation.actions` aceitam qualquer nó React.
|
|
129
80
|
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
`Selector` é um disclosure genérico para uma coleção controlada. Cada opção
|
|
138
|
-
tem apenas `value` estável e `label` como contrato-base; o consumidor pode
|
|
139
|
-
acrescentar campos ao tipar sua própria coleção, como `languageTag`, descrição
|
|
140
|
-
ou ícone. `value` e `onValueChange` são controlados pelo consumidor: ao clicar
|
|
141
|
-
em uma opção, o componente informa o novo valor e fecha o disclosure, mas não
|
|
142
|
-
navega nem atualiza estado por conta própria.
|
|
81
|
+
| Prop | Opções | Finalidade |
|
|
82
|
+
| --- | --- | --- |
|
|
83
|
+
| `width` | `content` (padrão), `wide` | Largura máxima da navegação |
|
|
84
|
+
| `layer` | `standard` (padrão), `above` | Camada de empilhamento |
|
|
85
|
+
| `linkTreatment` | `plain` (padrão), `underlined` | Aparência dos links |
|
|
86
|
+
| `linkWeight` | `semibold` (padrão), `bold` | Peso dos links |
|
|
87
|
+
| `mobileNavigation` | ausente ou objeto de disclosure | Navegação móvel opcional |
|
|
143
88
|
|
|
144
|
-
`
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
forma, atributos como `lang` ficam no conteúdo do aplicativo consumidor, não
|
|
148
|
-
no tipo genérico do pacote. O componente preserva botões com `aria-pressed`,
|
|
149
|
-
`select-none`, as densidades `standard` (padrão), `compact` e
|
|
150
|
-
`compact-mobile` e `whiteSurface`. Sem `triggerAriaLabel`, o nome acessível do
|
|
151
|
-
gatilho vem do conteúdo selecionado visível; use essa prop quando o consumidor
|
|
152
|
-
precisar de um nome mais descritivo e atualize-o junto do valor controlado.
|
|
89
|
+
`GoogleSignInButton` recebe uma `label` obrigatória e os atributos nativos de
|
|
90
|
+
um botão, como `onClick`, `disabled` e `aria-*`. Autenticação, estado de
|
|
91
|
+
carregamento e traduções pertencem ao aplicativo que o utiliza.
|
|
153
92
|
|
|
154
|
-
`
|
|
155
|
-
`
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
próprias em `Controls/Selector` e `Controls/GoogleSignInButton`.
|
|
93
|
+
`Selector` é controlado: `value` determina a opção visível e
|
|
94
|
+
`onValueChange` informa uma nova escolha. As opções exigem somente `value` e
|
|
95
|
+
`label`, mas podem ser estendidas com outros campos e apresentadas por
|
|
96
|
+
`renderOption` e `renderTrigger`. O componente não navega nem muda estado por
|
|
97
|
+
conta própria.
|
|
160
98
|
|
|
161
|
-
## Desenvolvimento
|
|
99
|
+
## Desenvolvimento
|
|
162
100
|
|
|
163
101
|
```sh
|
|
164
102
|
pnpm lint
|
|
@@ -172,90 +110,21 @@ pnpm build-storybook
|
|
|
172
110
|
pnpm pack:check
|
|
173
111
|
```
|
|
174
112
|
|
|
175
|
-
`pnpm lint`
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
ambos devem passar antes de o histórico ser criado.
|
|
179
|
-
|
|
180
|
-
`pnpm test` roda testes de contrato em Vitest + Testing Library. As stories
|
|
181
|
-
exibem o playground configurável da navbar, o seletor genérico e o botão
|
|
182
|
-
Google, incluindo o SVG oficial somente como asset de demonstração do
|
|
183
|
-
Storybook. Elas são verificadas em Chromium por `pnpm test:stories`, com os
|
|
184
|
-
addons oficiais de acessibilidade e Vitest.
|
|
185
|
-
|
|
186
|
-
Em uma máquina Linux nova, instale as dependências do Chromium uma vez antes
|
|
187
|
-
do teste de stories:
|
|
113
|
+
Husky executa `pnpm lint` e `pnpm test` antes de cada commit. As stories são
|
|
114
|
+
verificadas em Chromium por `pnpm test:stories`; em uma máquina Linux nova,
|
|
115
|
+
instale as dependências uma vez:
|
|
188
116
|
|
|
189
117
|
```sh
|
|
190
118
|
pnpm exec playwright install chromium
|
|
191
119
|
sudo pnpm exec playwright install-deps chromium
|
|
192
120
|
```
|
|
193
121
|
|
|
194
|
-
|
|
122
|
+
Cada componente fica em `src/components/<nome>/`, junto dos seus testes e
|
|
123
|
+
stories. `src/index.ts` é o ponto de entrada público, e testes transversais
|
|
124
|
+
ficam em `test/`.
|
|
195
125
|
|
|
196
|
-
|
|
197
|
-
testes e story (quando houver) ficam juntos. `src/index.ts` é o único ponto de
|
|
198
|
-
entrada público; mudar a organização interna não altera como os aplicativos
|
|
199
|
-
importam `@1e99/components`. Testes transversais ficam em `test/`.
|
|
126
|
+
## Licença
|
|
200
127
|
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
configuração de registry e token em cada consumidor. GitHub Packages é uma
|
|
205
|
-
alternativa para distribuição privada, mas exige registry e token GitHub nos
|
|
206
|
-
aplicativos.
|
|
207
|
-
|
|
208
|
-
`.github/workflows/ci.yml` valida pull requests e pushes para `main` com lint,
|
|
209
|
-
tipos, testes, build, Storybook e prévia do tarball. `.github/workflows/publish.yml`
|
|
210
|
-
repete essas verificações e publica somente quando uma tag `vX.Y.Z` corresponde
|
|
211
|
-
exatamente à versão em `package.json` e aponta para um commit ancestral de
|
|
212
|
-
`main`. Os actions usados nos workflows estão fixados em commits revisáveis.
|
|
213
|
-
|
|
214
|
-
### Primeiro release pelo CI
|
|
215
|
-
|
|
216
|
-
O bootstrap usa temporariamente o secret de repositório `NPM_TOKEN`. Crie-o no
|
|
217
|
-
npm como token granular, com **Bypass two-factor authentication**, permissão
|
|
218
|
-
**Read and write (publish and stage)** limitada ao escopo `@1e99` e expiração
|
|
219
|
-
curta. Salve-o em GitHub → `1e99/components` → Settings → Secrets and variables
|
|
220
|
-
→ Actions como `NPM_TOKEN`. Nunca grave ou compartilhe esse valor por chat,
|
|
221
|
-
issues, commits ou logs.
|
|
222
|
-
|
|
223
|
-
Como `@1e99/components` ainda não existe antes do primeiro publish, o escopo
|
|
224
|
-
inteiro é uma exceção temporária de bootstrap: revogue o token assim que OIDC
|
|
225
|
-
for configurado. O npm anuncia a remoção do publish direto com tokens granular
|
|
226
|
-
de bypass de 2FA em janeiro de 2027; se o primeiro release for adiado além
|
|
227
|
-
disso, use o fluxo de staged publishing do npm em vez de manter um token.
|
|
228
|
-
|
|
229
|
-
Antes de criar a tag pública, confirme a política de licença: o pacote está
|
|
230
|
-
como `UNLICENSED` e essa decisão precisa de aprovação explícita para publicação
|
|
231
|
-
pública.
|
|
232
|
-
|
|
233
|
-
Envie os commits e a tag correspondente à versão:
|
|
234
|
-
|
|
235
|
-
```sh
|
|
236
|
-
git push origin main
|
|
237
|
-
git tag v0.1.0
|
|
238
|
-
git push origin v0.1.0
|
|
239
|
-
```
|
|
240
|
-
|
|
241
|
-
O workflow recusa a tag se `package.json` não estiver em `0.1.0` e publica com
|
|
242
|
-
`publishConfig.access: public` se todas as verificações passarem.
|
|
243
|
-
Configure também regras do GitHub para exigir o CI antes de merge em `main` e
|
|
244
|
-
restringir a criação e atualização de tags `v*` a mantenedores autorizados.
|
|
245
|
-
|
|
246
|
-
### Migrar para Trusted Publishing
|
|
247
|
-
|
|
248
|
-
Depois que a primeira release for publicada, habilite 2FA na conta npm e abra
|
|
249
|
-
as configurações de `@1e99/components` no npm. Em **Trusted Publisher**, escolha
|
|
250
|
-
GitHub Actions e informe organização `1e99`, repositório `components` e arquivo
|
|
251
|
-
de workflow `publish.yml`; permita publicação direta com `npm publish`.
|
|
252
|
-
|
|
253
|
-
Em seguida, apague o secret `NPM_TOKEN` do GitHub e revogue o token no npm. As
|
|
254
|
-
tags futuras usarão OIDC com credenciais efêmeras do GitHub Actions e gerarão
|
|
255
|
-
provenance automaticamente. Para uma próxima versão, atualize a versão e envie
|
|
256
|
-
a tag criada pelo gerenciador:
|
|
257
|
-
|
|
258
|
-
```sh
|
|
259
|
-
pnpm version patch
|
|
260
|
-
git push origin main --follow-tags
|
|
261
|
-
```
|
|
128
|
+
Este pacote é licenciado sob a [MIT License](LICENSE). Você pode usar, copiar,
|
|
129
|
+
modificar, distribuir e sublicenciar o software, inclusive comercialmente,
|
|
130
|
+
desde que preserve o aviso de copyright e a licença.
|
package/package.json
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@1e99/components",
|
|
3
|
-
"version": "0.1.
|
|
4
|
-
"description": "
|
|
3
|
+
"version": "0.1.1",
|
|
4
|
+
"description": "Reusable React components built with Tailwind CSS.",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
7
7
|
"url": "https://github.com/1e99/components.git"
|
|
8
8
|
},
|
|
9
|
-
"license": "
|
|
9
|
+
"license": "MIT",
|
|
10
10
|
"type": "module",
|
|
11
11
|
"sideEffects": false,
|
|
12
12
|
"main": "./dist/index.js",
|
|
@@ -19,6 +19,7 @@
|
|
|
19
19
|
},
|
|
20
20
|
"files": [
|
|
21
21
|
"dist",
|
|
22
|
+
"LICENSE",
|
|
22
23
|
"README.md"
|
|
23
24
|
],
|
|
24
25
|
"scripts": {
|