@sbkbs/ui 1.0.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 +112 -0
- package/dist/components/Button/Button.d.ts +16 -0
- package/dist/components/Card/Card.d.ts +9 -0
- package/dist/components/Footer/Footer.d.ts +15 -0
- package/dist/components/Header/Header.d.ts +24 -0
- package/dist/components/Input/Input.d.ts +12 -0
- package/dist/components/Modal/Modal.d.ts +14 -0
- package/dist/components/Paragraph/Paragraph.d.ts +11 -0
- package/dist/components/Subtitle/Subtitle.d.ts +11 -0
- package/dist/components/Title/Title.d.ts +11 -0
- package/dist/index.d.ts +26 -0
- package/dist/oficios-ui.css +1 -0
- package/dist/oficios-ui.js +343 -0
- package/dist/oficios-ui.js.map +1 -0
- package/dist/oficios-ui.umd.cjs +2 -0
- package/dist/oficios-ui.umd.cjs.map +1 -0
- package/dist/theme/ThemeProvider.d.ts +13 -0
- package/dist/theme.css +295 -0
- package/package.json +63 -0
package/README.md
ADDED
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
# @oficios/ui
|
|
2
|
+
|
|
3
|
+
Biblioteca de componentes UI e tema global para manter o mesmo padrão visual entre projetos (OFICIO.IA, CADASTRO.IA, etc.).
|
|
4
|
+
|
|
5
|
+
## Conteúdo
|
|
6
|
+
|
|
7
|
+
- **Tema**: variáveis CSS (Material Design 3) light/dark + **Guia de marca SBK** (cores e tipografia Jakarta) em `theme/theme.css` + `ThemeProvider` React.
|
|
8
|
+
- **Componentes**: `Button`, `Card`, `Input`, `Modal`, `Title`, `Subtitle`, `Paragraph`, `Header`, `Footer`.
|
|
9
|
+
- **Paletas de botão**: escolha a cor do botão primary via prop `palette` ou `data-button-palette` no pai (`verde-vibrante`, `grafite-azulado`, etc.).
|
|
10
|
+
|
|
11
|
+
## Uso em outro projeto
|
|
12
|
+
|
|
13
|
+
### 1. Instalar no monorepo
|
|
14
|
+
|
|
15
|
+
No `package.json` do app (ex.: frontend), adicione:
|
|
16
|
+
|
|
17
|
+
```json
|
|
18
|
+
"dependencies": {
|
|
19
|
+
"@oficios/ui": "*"
|
|
20
|
+
}
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
Rode `npm install` na raiz do monorepo.
|
|
24
|
+
|
|
25
|
+
### 2. Tema (variáveis CSS)
|
|
26
|
+
|
|
27
|
+
Os componentes usam variáveis CSS (`--md-surface`, `--primary-color`, etc.). O consumidor pode:
|
|
28
|
+
|
|
29
|
+
- Usar o tema da lib: `import '@oficios/ui/theme.css';` no entry (ex.: `main.tsx`), ou
|
|
30
|
+
- Definir as mesmas variáveis no próprio CSS do projeto (o frontend OFICIO.IA já tem `theme.css` próprio).
|
|
31
|
+
|
|
32
|
+
### 3. ThemeProvider (opcional)
|
|
33
|
+
|
|
34
|
+
Para light/dark com toggle e persistência em `localStorage`:
|
|
35
|
+
|
|
36
|
+
```tsx
|
|
37
|
+
import { ThemeProvider } from '@oficios/ui';
|
|
38
|
+
|
|
39
|
+
root.render(
|
|
40
|
+
<ThemeProvider defaultTheme="light">
|
|
41
|
+
<App />
|
|
42
|
+
</ThemeProvider>
|
|
43
|
+
);
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
### 4. Componentes
|
|
47
|
+
|
|
48
|
+
```tsx
|
|
49
|
+
import { Button, Card, Input, Modal, Title, Subtitle, Paragraph, Header, Footer } from '@oficios/ui';
|
|
50
|
+
|
|
51
|
+
<Button variant="primary" size="md" palette="verde-vibrante">Salvar</Button>
|
|
52
|
+
<Card variant="elevated" padding="lg" hoverable>...</Card>
|
|
53
|
+
<Input label="E-mail" size="md" />
|
|
54
|
+
<Modal isOpen={open} onClose={() => setOpen(false)} title="Título">...</Modal>
|
|
55
|
+
<Title size="2xl" weight="bold">Título</Title>
|
|
56
|
+
<Subtitle size="md" muted>Subtítulo</Subtitle>
|
|
57
|
+
<Paragraph size="md">Texto.</Paragraph>
|
|
58
|
+
|
|
59
|
+
<Header
|
|
60
|
+
logoSrc="/logo.png"
|
|
61
|
+
logoDarkSrc="/logo-dark.png"
|
|
62
|
+
title="OFÍCIO.IA"
|
|
63
|
+
subtitle="Subtítulo"
|
|
64
|
+
onLogoClick={() => navigate('/home')}
|
|
65
|
+
rightContent={<>
|
|
66
|
+
<LanguageSelector />
|
|
67
|
+
<ThemeToggle />
|
|
68
|
+
<UserMenu />
|
|
69
|
+
</>}
|
|
70
|
+
/>
|
|
71
|
+
<Footer poweredByText="Powered by" logoSrc="/logo.png" logoFallbackText="SBK" />
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
### Guia de marca (tema)
|
|
75
|
+
|
|
76
|
+
Cores disponíveis como variáveis CSS: `--brand-verde-vibrante`, `--brand-grafite-azulado`, `--brand-verde-profundo`, `--brand-azul-acinzentado`, `--brand-cinza-medio`, `--brand-cinza-escuro`, `--brand-off-white`, e paleta "O Criador" (`--brand-azul-intenso`, `--brand-verde-lima`, etc.). Tipografia: `--font-primary` / `--font-heading` = Plus Jakarta Sans (Google Fonts).
|
|
77
|
+
|
|
78
|
+
Paletas de botão (prop `palette` ou `data-button-palette` no pai): `verde-vibrante` | `verde-profundo` | `grafite-azulado` | `azul-acinzentado` | `cinza-medio` | `cinza-escuro` | `off-white`.
|
|
79
|
+
|
|
80
|
+
## Compartilhar com outro projeto
|
|
81
|
+
|
|
82
|
+
- **Mesmo monorepo:** adicione o app em `workspaces` e use `"@oficios/ui": "*"` nas dependências; depois `npm install` na raiz.
|
|
83
|
+
- **Outro repositório:** use dependência por Git (`"@oficios/ui": "git+https://..."`) ou publique em um registry npm e instale com `npm install @oficios/ui`.
|
|
84
|
+
|
|
85
|
+
Guia completo: [docs/COMPARTILHAR_LIB_UI.md](../docs/COMPARTILHAR_LIB_UI.md).
|
|
86
|
+
|
|
87
|
+
## Desenvolvimento
|
|
88
|
+
|
|
89
|
+
- **Build**: `npm run build -w @oficios/ui` (na raiz) ou `npm run build` dentro de `ui`.
|
|
90
|
+
- **Watch**: `npm run dev -w @oficios/ui` para rebuild ao editar.
|
|
91
|
+
|
|
92
|
+
## Estrutura
|
|
93
|
+
|
|
94
|
+
```
|
|
95
|
+
ui/
|
|
96
|
+
src/
|
|
97
|
+
index.ts
|
|
98
|
+
theme/
|
|
99
|
+
theme.css
|
|
100
|
+
ThemeProvider.tsx
|
|
101
|
+
components/
|
|
102
|
+
Button/
|
|
103
|
+
Card/
|
|
104
|
+
Input/
|
|
105
|
+
Modal/
|
|
106
|
+
Title/
|
|
107
|
+
Subtitle/
|
|
108
|
+
Paragraph/
|
|
109
|
+
Header/
|
|
110
|
+
Footer/
|
|
111
|
+
dist/
|
|
112
|
+
```
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type React from 'react';
|
|
2
|
+
import './Button.css';
|
|
3
|
+
/** Paletas do guia de marca (só afeta variant primary). Use para escolher o modelo de cor do botão. */
|
|
4
|
+
export type ButtonPalette = 'verde-vibrante' | 'verde-profundo' | 'grafite-azulado' | 'azul-acinzentado' | 'cinza-medio' | 'cinza-escuro' | 'off-white';
|
|
5
|
+
export interface ButtonProps extends React.ButtonHTMLAttributes<HTMLButtonElement> {
|
|
6
|
+
children: React.ReactNode;
|
|
7
|
+
fullWidth?: boolean;
|
|
8
|
+
isLoading?: boolean;
|
|
9
|
+
leftIcon?: React.ReactNode;
|
|
10
|
+
/** Paleta de cor do guia de marca (aplica-se ao primary). Ignorado em outros variants. */
|
|
11
|
+
palette?: ButtonPalette;
|
|
12
|
+
rightIcon?: React.ReactNode;
|
|
13
|
+
size?: 'xs' | 'sm' | 'md' | 'lg' | 'xl';
|
|
14
|
+
variant?: 'primary' | 'secondary' | 'success' | 'error' | 'warning' | 'info' | 'neutral' | 'ghost';
|
|
15
|
+
}
|
|
16
|
+
export declare const Button: React.FC<ButtonProps>;
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type React from 'react';
|
|
2
|
+
import './Card.css';
|
|
3
|
+
export interface CardProps extends React.HTMLAttributes<HTMLDivElement> {
|
|
4
|
+
children: React.ReactNode;
|
|
5
|
+
hoverable?: boolean;
|
|
6
|
+
padding?: 'none' | 'sm' | 'md' | 'lg' | 'xl';
|
|
7
|
+
variant?: 'default' | 'elevated' | 'outlined' | 'flat';
|
|
8
|
+
}
|
|
9
|
+
export declare const Card: React.FC<CardProps>;
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type React from 'react';
|
|
2
|
+
import './Footer.css';
|
|
3
|
+
export interface FooterProps {
|
|
4
|
+
/** Classe CSS adicional */
|
|
5
|
+
className?: string;
|
|
6
|
+
/** Texto alternativo do logo */
|
|
7
|
+
logoAlt?: string;
|
|
8
|
+
/** Texto exibido se a imagem do logo falhar (ex.: "SBK") */
|
|
9
|
+
logoFallbackText?: string;
|
|
10
|
+
/** URL da imagem do logo */
|
|
11
|
+
logoSrc?: string;
|
|
12
|
+
/** Texto antes do logo (ex.: "Powered by") */
|
|
13
|
+
poweredByText?: string;
|
|
14
|
+
}
|
|
15
|
+
export declare const Footer: React.FC<FooterProps>;
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import type React from 'react';
|
|
2
|
+
import type { Theme } from '../../theme/ThemeProvider';
|
|
3
|
+
import './Header.css';
|
|
4
|
+
export interface HeaderProps {
|
|
5
|
+
/** Classe CSS adicional */
|
|
6
|
+
className?: string;
|
|
7
|
+
/** Texto alternativo do logo */
|
|
8
|
+
logoAlt?: string;
|
|
9
|
+
/** URL da imagem do logo (tema escuro). Se não informado, usa logoSrc. */
|
|
10
|
+
logoDarkSrc?: string;
|
|
11
|
+
/** URL da imagem do logo (tema claro) */
|
|
12
|
+
logoSrc?: string;
|
|
13
|
+
/** Callback ao clicar na área do logo/título */
|
|
14
|
+
onLogoClick?: () => void;
|
|
15
|
+
/** Conteúdo da área direita (ex.: seletor de idioma, toggle tema, menu usuário) */
|
|
16
|
+
rightContent?: React.ReactNode;
|
|
17
|
+
/** Subtítulo abaixo do título */
|
|
18
|
+
subtitle?: React.ReactNode;
|
|
19
|
+
/** Tema opcional para escolher o logo correto sem depender do ThemeProvider do UI */
|
|
20
|
+
theme?: Theme;
|
|
21
|
+
/** Título exibido ao lado do logo (ex.: "OFÍCIO.IA") */
|
|
22
|
+
title?: React.ReactNode;
|
|
23
|
+
}
|
|
24
|
+
export declare const Header: React.FC<HeaderProps>;
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type React from 'react';
|
|
2
|
+
import './Input.css';
|
|
3
|
+
export interface InputProps extends Omit<React.InputHTMLAttributes<HTMLInputElement>, 'size'> {
|
|
4
|
+
error?: string;
|
|
5
|
+
fullWidth?: boolean;
|
|
6
|
+
helperText?: string;
|
|
7
|
+
label?: string;
|
|
8
|
+
leftIcon?: React.ReactNode;
|
|
9
|
+
rightIcon?: React.ReactNode;
|
|
10
|
+
size?: 'sm' | 'md' | 'lg';
|
|
11
|
+
}
|
|
12
|
+
export declare const Input: React.FC<InputProps>;
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type React from 'react';
|
|
2
|
+
import './Modal.css';
|
|
3
|
+
export interface ModalProps {
|
|
4
|
+
children: React.ReactNode;
|
|
5
|
+
className?: string;
|
|
6
|
+
closeOnOverlayClick?: boolean;
|
|
7
|
+
isOpen: boolean;
|
|
8
|
+
onClose: () => void;
|
|
9
|
+
showCloseButton?: boolean;
|
|
10
|
+
size?: 'sm' | 'md' | 'lg' | 'xl' | 'full';
|
|
11
|
+
subtitle?: string;
|
|
12
|
+
title?: string | React.ReactNode;
|
|
13
|
+
}
|
|
14
|
+
export declare const Modal: React.FC<ModalProps>;
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type React from 'react';
|
|
2
|
+
import './Paragraph.css';
|
|
3
|
+
export interface ParagraphProps extends React.HTMLAttributes<HTMLParagraphElement> {
|
|
4
|
+
align?: 'left' | 'center' | 'right' | 'justify';
|
|
5
|
+
as?: 'p' | 'span' | 'div';
|
|
6
|
+
children: React.ReactNode;
|
|
7
|
+
muted?: boolean;
|
|
8
|
+
size?: 'xs' | 'sm' | 'md' | 'lg';
|
|
9
|
+
weight?: 'light' | 'normal' | 'medium';
|
|
10
|
+
}
|
|
11
|
+
export declare const Paragraph: React.FC<ParagraphProps>;
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type React from 'react';
|
|
2
|
+
import './Subtitle.css';
|
|
3
|
+
export interface SubtitleProps extends React.HTMLAttributes<HTMLParagraphElement> {
|
|
4
|
+
align?: 'left' | 'center' | 'right';
|
|
5
|
+
as?: 'p' | 'span' | 'div';
|
|
6
|
+
children: React.ReactNode;
|
|
7
|
+
muted?: boolean;
|
|
8
|
+
size?: 'xs' | 'sm' | 'md' | 'lg';
|
|
9
|
+
weight?: 'normal' | 'medium' | 'semibold';
|
|
10
|
+
}
|
|
11
|
+
export declare const Subtitle: React.FC<SubtitleProps>;
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type React from 'react';
|
|
2
|
+
import './Title.css';
|
|
3
|
+
export interface TitleProps extends React.HTMLAttributes<HTMLHeadingElement> {
|
|
4
|
+
align?: 'left' | 'center' | 'right';
|
|
5
|
+
as?: 'h1' | 'h2' | 'h3' | 'h4' | 'h5' | 'h6';
|
|
6
|
+
children: React.ReactNode;
|
|
7
|
+
gradient?: boolean;
|
|
8
|
+
size?: 'xs' | 'sm' | 'md' | 'lg' | 'xl' | '2xl' | '3xl' | '4xl';
|
|
9
|
+
weight?: 'light' | 'normal' | 'medium' | 'semibold' | 'bold' | 'extrabold';
|
|
10
|
+
}
|
|
11
|
+
export declare const Title: React.FC<TitleProps>;
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @oficios/ui
|
|
3
|
+
* Biblioteca de componentes UI e tema para manter padrão visual entre projetos.
|
|
4
|
+
*
|
|
5
|
+
* Uso no projeto consumidor:
|
|
6
|
+
* 1. Importar o CSS do tema uma vez (ex.: no main.tsx):
|
|
7
|
+
* import '@oficios/ui/theme.css';
|
|
8
|
+
* ou import '@oficios/ui/styles.css' (tema + estilos dos componentes).
|
|
9
|
+
* 2. Envolver a app com ThemeProvider (opcional, para light/dark):
|
|
10
|
+
* import { ThemeProvider } from '@oficios/ui';
|
|
11
|
+
* 3. Usar os componentes:
|
|
12
|
+
* import { Button, Card } from '@oficios/ui';
|
|
13
|
+
* O tema (variáveis CSS) deve ser carregado pelo consumidor (ex.: frontend já tem theme.css).
|
|
14
|
+
*/
|
|
15
|
+
import './tailwind.css';
|
|
16
|
+
import './theme/theme.css';
|
|
17
|
+
export { Button, type ButtonPalette, type ButtonProps, } from './components/Button/Button';
|
|
18
|
+
export { Card, type CardProps } from './components/Card/Card';
|
|
19
|
+
export { Footer, type FooterProps } from './components/Footer/Footer';
|
|
20
|
+
export { Header, type HeaderProps } from './components/Header/Header';
|
|
21
|
+
export { Input, type InputProps } from './components/Input/Input';
|
|
22
|
+
export { Modal, type ModalProps } from './components/Modal/Modal';
|
|
23
|
+
export { Paragraph, type ParagraphProps, } from './components/Paragraph/Paragraph';
|
|
24
|
+
export { Subtitle, type SubtitleProps } from './components/Subtitle/Subtitle';
|
|
25
|
+
export { Title, type TitleProps } from './components/Title/Title';
|
|
26
|
+
export { type Theme, ThemeProvider, useTheme, } from './theme/ThemeProvider';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
@import"https://fonts.googleapis.com/css2?family=Plus+Jakarta+Sans:ital,wght@0,300;0,400;0,500;0,600;0,700;0,800;1,400;1,500&display=swap";@import"https://fonts.googleapis.com/css2?family=Orbitron:wght@400;500;600;700;800;900&display=swap";*,:before,:after{--tw-border-spacing-x: 0;--tw-border-spacing-y: 0;--tw-translate-x: 0;--tw-translate-y: 0;--tw-rotate: 0;--tw-skew-x: 0;--tw-skew-y: 0;--tw-scale-x: 1;--tw-scale-y: 1;--tw-pan-x: ;--tw-pan-y: ;--tw-pinch-zoom: ;--tw-scroll-snap-strictness: proximity;--tw-gradient-from-position: ;--tw-gradient-via-position: ;--tw-gradient-to-position: ;--tw-ordinal: ;--tw-slashed-zero: ;--tw-numeric-figure: ;--tw-numeric-spacing: ;--tw-numeric-fraction: ;--tw-ring-inset: ;--tw-ring-offset-width: 0px;--tw-ring-offset-color: #fff;--tw-ring-color: rgb(59 130 246 / .5);--tw-ring-offset-shadow: 0 0 #0000;--tw-ring-shadow: 0 0 #0000;--tw-shadow: 0 0 #0000;--tw-shadow-colored: 0 0 #0000;--tw-blur: ;--tw-brightness: ;--tw-contrast: ;--tw-grayscale: ;--tw-hue-rotate: ;--tw-invert: ;--tw-saturate: ;--tw-sepia: ;--tw-drop-shadow: ;--tw-backdrop-blur: ;--tw-backdrop-brightness: ;--tw-backdrop-contrast: ;--tw-backdrop-grayscale: ;--tw-backdrop-hue-rotate: ;--tw-backdrop-invert: ;--tw-backdrop-opacity: ;--tw-backdrop-saturate: ;--tw-backdrop-sepia: ;--tw-contain-size: ;--tw-contain-layout: ;--tw-contain-paint: ;--tw-contain-style: }::backdrop{--tw-border-spacing-x: 0;--tw-border-spacing-y: 0;--tw-translate-x: 0;--tw-translate-y: 0;--tw-rotate: 0;--tw-skew-x: 0;--tw-skew-y: 0;--tw-scale-x: 1;--tw-scale-y: 1;--tw-pan-x: ;--tw-pan-y: ;--tw-pinch-zoom: ;--tw-scroll-snap-strictness: proximity;--tw-gradient-from-position: ;--tw-gradient-via-position: ;--tw-gradient-to-position: ;--tw-ordinal: ;--tw-slashed-zero: ;--tw-numeric-figure: ;--tw-numeric-spacing: ;--tw-numeric-fraction: ;--tw-ring-inset: ;--tw-ring-offset-width: 0px;--tw-ring-offset-color: #fff;--tw-ring-color: rgb(59 130 246 / .5);--tw-ring-offset-shadow: 0 0 #0000;--tw-ring-shadow: 0 0 #0000;--tw-shadow: 0 0 #0000;--tw-shadow-colored: 0 0 #0000;--tw-blur: ;--tw-brightness: ;--tw-contrast: ;--tw-grayscale: ;--tw-hue-rotate: ;--tw-invert: ;--tw-saturate: ;--tw-sepia: ;--tw-drop-shadow: ;--tw-backdrop-blur: ;--tw-backdrop-brightness: ;--tw-backdrop-contrast: ;--tw-backdrop-grayscale: ;--tw-backdrop-hue-rotate: ;--tw-backdrop-invert: ;--tw-backdrop-opacity: ;--tw-backdrop-saturate: ;--tw-backdrop-sepia: ;--tw-contain-size: ;--tw-contain-layout: ;--tw-contain-paint: ;--tw-contain-style: }*,:before,:after{box-sizing:border-box;border-width:0;border-style:solid;border-color:#e5e7eb}:before,:after{--tw-content: ""}html,:host{line-height:1.5;-webkit-text-size-adjust:100%;-moz-tab-size:4;-o-tab-size:4;tab-size:4;font-family:ui-sans-serif,system-ui,sans-serif,"Apple Color Emoji","Segoe UI Emoji",Segoe UI Symbol,"Noto Color Emoji";font-feature-settings:normal;font-variation-settings:normal;-webkit-tap-highlight-color:transparent}body{margin:0;line-height:inherit}hr{height:0;color:inherit;border-top-width:1px}abbr:where([title]){-webkit-text-decoration:underline dotted;text-decoration:underline dotted}h1,h2,h3,h4,h5,h6{font-size:inherit;font-weight:inherit}a{color:inherit;text-decoration:inherit}b,strong{font-weight:bolder}code,kbd,samp,pre{font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace;font-feature-settings:normal;font-variation-settings:normal;font-size:1em}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sub{bottom:-.25em}sup{top:-.5em}table{text-indent:0;border-color:inherit;border-collapse:collapse}button,input,optgroup,select,textarea{font-family:inherit;font-feature-settings:inherit;font-variation-settings:inherit;font-size:100%;font-weight:inherit;line-height:inherit;letter-spacing:inherit;color:inherit;margin:0;padding:0}button,select{text-transform:none}button,input:where([type=button]),input:where([type=reset]),input:where([type=submit]){-webkit-appearance:button;background-color:transparent;background-image:none}:-moz-focusring{outline:auto}:-moz-ui-invalid{box-shadow:none}progress{vertical-align:baseline}::-webkit-inner-spin-button,::-webkit-outer-spin-button{height:auto}[type=search]{-webkit-appearance:textfield;outline-offset:-2px}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{-webkit-appearance:button;font:inherit}summary{display:list-item}blockquote,dl,dd,h1,h2,h3,h4,h5,h6,hr,figure,p,pre{margin:0}fieldset{margin:0;padding:0}legend{padding:0}ol,ul,menu{list-style:none;margin:0;padding:0}dialog{padding:0}textarea{resize:vertical}input::-moz-placeholder,textarea::-moz-placeholder{opacity:1;color:#9ca3af}input::placeholder,textarea::placeholder{opacity:1;color:#9ca3af}button,[role=button]{cursor:pointer}:disabled{cursor:default}img,svg,video,canvas,audio,iframe,embed,object{display:block;vertical-align:middle}img,video{max-width:100%;height:auto}[hidden]:where(:not([hidden=until-found])){display:none}.fixed{position:fixed}.absolute{position:absolute}.relative{position:relative}.block{display:block}.flex{display:flex}.grid{display:grid}.hidden{display:none}.flex-shrink{flex-shrink:1}.transform{transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skew(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.flex-wrap{flex-wrap:wrap}.border{border-width:1px}.outline{outline-style:solid}.blur{--tw-blur: blur(8px);filter:var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow)}.invert{--tw-invert: invert(100%);filter:var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow)}.filter{filter:var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow)}.backdrop-filter{-webkit-backdrop-filter:var(--tw-backdrop-blur) var(--tw-backdrop-brightness) var(--tw-backdrop-contrast) var(--tw-backdrop-grayscale) var(--tw-backdrop-hue-rotate) var(--tw-backdrop-invert) var(--tw-backdrop-opacity) var(--tw-backdrop-saturate) var(--tw-backdrop-sepia);backdrop-filter:var(--tw-backdrop-blur) var(--tw-backdrop-brightness) var(--tw-backdrop-contrast) var(--tw-backdrop-grayscale) var(--tw-backdrop-hue-rotate) var(--tw-backdrop-invert) var(--tw-backdrop-opacity) var(--tw-backdrop-saturate) var(--tw-backdrop-sepia)}.transition{transition-property:color,background-color,border-color,text-decoration-color,fill,stroke,opacity,box-shadow,transform,filter,backdrop-filter;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}:root{--brand-verde-vibrante: #01b2aa;--brand-verde-profundo: #1f3a3a;--brand-grafite-azulado: #0f2f3a;--brand-azul-acinzentado: #5f7b8d;--brand-cinza-medio: #4b4b4b;--brand-cinza-escuro: #24262d;--brand-off-white: #ffffff;--brand-neutral-75: rgba(255, 255, 255, .75);--brand-branco: #ffffff;--brand-preto: #000000;--brand-cinza: #989495;--brand-azul-lavanda: #777dac;--brand-azul-intenso: #132c3b;--brand-cinza-azulado: #b4c2c7;--brand-verde-lima: #cffe40;--brand-off-white-criador: #e4e4e4;--brand-azul-escuro: #071a5c}:root{--font-primary: "Plus Jakarta Sans", -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;--font-secondary: "Plus Jakarta Sans", var(--font-primary);--font-heading: var(--font-primary);--font-body: var(--font-primary)}html{font-family:var(--font-body);font-size:1rem}:root{--primary-color: var(--brand-verde-vibrante);--primary-color-dark: var(--brand-verde-profundo);--primary-color-light: color-mix( in srgb, var(--brand-verde-vibrante) 84%, white );--primary-color-hover: var(--brand-verde-profundo);--md-primary: var(--brand-verde-vibrante);--md-on-primary: #ffffff;--md-primary-container: color-mix( in srgb, var(--brand-verde-vibrante) 18%, white );--md-on-primary-container: var(--brand-grafite-azulado);--secondary-color: var(--brand-grafite-azulado);--color-primary: var(--primary-color);--color-on-primary: var(--md-on-primary);--color-secondary: var(--secondary-color);--color-on-secondary: var(--md-on-secondary);--color-surface: var(--md-surface);--color-on-surface: var(--md-on-surface);--color-contrast: var(--brand-verde-lima);--md-secondary: var(--brand-grafite-azulado);--md-on-secondary: #ffffff;--md-outline: var(--brand-azul-acinzentado);--md-outline-variant: color-mix( in srgb, var(--brand-azul-acinzentado) 35%, white );--success-color: #22c55e;--success-color-light: #4ade80;--error-color: #ef4444;--error-color-light: #f87171;--md-error: #ba1a1a;--md-on-error: #ffffff;--warning-color: #f59e0b;--warning-color-light: #fbbe24;--info-color: #3b82f6;--info-color-light: #60a5fa;--neutral-color: var(--brand-cinza-medio);--neutral-color-light: var(--brand-azul-acinzentado);--secondary-color-light: var(--brand-azul-acinzentado);--bg-hover: color-mix(in srgb, var(--brand-grafite-azulado) 8%, white);--bg-active: color-mix(in srgb, var(--brand-grafite-azulado) 14%, white);--md-on-surface: var(--brand-grafite-azulado);--accent-color: var(--primary-color);--accent-color-hover: var(--primary-color-hover);--bg-primary: var(--brand-neutral-75);--bg-secondary: #ffffff;--bg-tertiary: color-mix(in srgb, var(--brand-azul-acinzentado) 14%, white);--md-surface: #ffffff;--md-surface-container: var(--brand-neutral-75);--md-surface-container-high: color-mix( in srgb, var(--brand-azul-acinzentado) 14%, white );--border-color-hover: color-mix( in srgb, var(--brand-grafite-azulado) 32%, white );--bg-card: #ffffff;--bg-card-hover: color-mix(in srgb, var(--brand-azul-acinzentado) 8%, white);--bg-card-border: color-mix( in srgb, var(--brand-azul-acinzentado) 28%, white );--text-primary: var(--brand-grafite-azulado);--text-secondary: var(--brand-cinza-escuro);--text-tertiary: var(--brand-cinza-medio);--text-muted: var(--brand-cinza-medio);--text-on-primary: #ffffff;--border-color: color-mix(in srgb, var(--brand-azul-acinzentado) 30%, white);--border-color-focus: color-mix( in srgb, var(--brand-verde-vibrante) 52%, transparent );--shadow-xs: 0 .0625rem .125rem rgba(0, 0, 0, .05);--shadow-sm: 0 .125rem .25rem rgba(0, 0, 0, .08);--shadow-md: 0 .25rem .75rem rgba(0, 0, 0, .1);--shadow-lg: 0 .5rem 1.5rem rgba(0, 0, 0, .12);--font-size-xs: .75rem;--font-size-sm: .875rem;--font-size-base: 1rem;--font-size-md: 1.125rem;--font-size-lg: 1.25rem;--font-size-xl: 1.5rem;--font-weight-normal: 400;--font-weight-medium: 500;--font-weight-semibold: 600;--font-weight-bold: 700;--line-height-normal: 1.5;--spacing-xs: .25rem;--spacing-sm: .5rem;--spacing-md: .75rem;--spacing-lg: 1rem;--spacing-xl: 1.5rem;--spacing-2xl: 2rem;--border-radius-sm: .375rem;--border-radius-md: .5rem;--border-radius-lg: .75rem;--border-width-thin: .0625rem;--transition-base: .3s ease;--transition-all: all var(--transition-base);--transition-colors: color var(--transition-base), background-color var(--transition-base), border-color var(--transition-base);--z-index-dropdown: 1000;--z-index-modal-backdrop: 1040;--z-index-modal: 1050;--border-radius-2xl: 1.25rem;--shadow-2xl: 0 1.25rem 3.75rem rgba(0, 0, 0, .2);--font-size-2xl: 1.75rem;--font-size-3xl: 2rem;--font-size-4xl: 2.5rem;--font-weight-light: 300;--line-height-tight: 1.2;--line-height-relaxed: 1.6;--line-height-loose: 1.8;--md-on-surface-variant: #44474e;--spacing-3xl: 2.5rem}[data-theme=dark],.theme-dark{--bg-primary: #0f141a;--bg-secondary: #161b22;--bg-card: #161b22;--bg-card-hover: #1e2630;--bg-card-border: #2f3a46;--md-surface: #161b22;--md-on-surface: #e6e8eb;--md-on-surface-variant: #c2c7cf;--md-outline-variant: #44474e;--md-primary: var(--brand-verde-vibrante);--md-on-primary: #062126;--primary-color: var(--brand-verde-vibrante);--primary-color-light: color-mix( in srgb, var(--brand-verde-vibrante) 85%, white );--primary-color-hover: var(--brand-verde-profundo);--secondary-color: var(--brand-azul-acinzentado);--color-primary: var(--primary-color);--color-on-primary: var(--md-on-primary);--color-secondary: var(--secondary-color);--color-on-secondary: var(--md-on-secondary);--color-surface: var(--md-surface);--color-on-surface: var(--md-on-surface);--color-contrast: var(--brand-off-white);--text-primary: #e6e8eb;--text-secondary: #d1d5db;--text-muted: #9ca3af;--border-color: #2f3a46;--shadow-sm: 0 .125rem .25rem 0 rgba(0, 0, 0, .4);--shadow-md: 0 .25rem .5rem 0 rgba(0, 0, 0, .5);--shadow-lg: 0 .5rem 1rem 0 rgba(0, 0, 0, .6)}[data-button-palette=verde-vibrante],.btn--palette-verde-vibrante.btn--primary,[data-button-palette=verde-vibrante] .btn--primary{--md-primary: var(--brand-verde-vibrante);--primary-color-hover: var(--brand-verde-profundo)}[data-button-palette=verde-profundo],.btn--palette-verde-profundo.btn--primary,[data-button-palette=verde-profundo] .btn--primary{--md-primary: var(--brand-verde-profundo);--primary-color-hover: var(--brand-grafite-azulado)}[data-button-palette=grafite-azulado],.btn--palette-grafite-azulado.btn--primary,[data-button-palette=grafite-azulado] .btn--primary{--md-primary: var(--brand-grafite-azulado);--primary-color-hover: var(--brand-cinza-escuro)}[data-button-palette=azul-acinzentado],.btn--palette-azul-acinzentado.btn--primary,[data-button-palette=azul-acinzentado] .btn--primary{--md-primary: var(--brand-azul-acinzentado);--primary-color-hover: var(--brand-grafite-azulado)}[data-button-palette=cinza-medio],.btn--palette-cinza-medio.btn--primary,[data-button-palette=cinza-medio] .btn--primary{--md-primary: var(--brand-cinza-medio);--primary-color-hover: var(--brand-cinza-escuro)}[data-button-palette=cinza-escuro],.btn--palette-cinza-escuro.btn--primary,[data-button-palette=cinza-escuro] .btn--primary{--md-primary: var(--brand-cinza-escuro);--primary-color-hover: var(--brand-preto)}[data-button-palette=off-white],.btn--palette-off-white.btn--primary,[data-button-palette=off-white] .btn--primary{--md-primary: var(--brand-off-white);--md-on-primary: var(--brand-grafite-azulado);--primary-color-hover: var(--brand-branco)}.btn{position:relative;display:inline-flex;align-items:center;justify-content:center;overflow:hidden;-webkit-user-select:none;-moz-user-select:none;user-select:none;white-space:nowrap;gap:var(--spacing-sm);font-family:inherit;font-weight:var(--font-weight-semibold);cursor:pointer;border:var(--border-width-thin) solid transparent;border-radius:var(--border-radius-md);transition:var(--transition-all)}.btn:focus-visible{outline:2px solid var(--md-primary);outline-offset:2px}.btn:disabled{pointer-events:none;cursor:not-allowed;opacity:.6}.btn--xs{min-height:1.75rem;padding:var(--spacing-xs) var(--spacing-sm);font-size:var(--font-size-xs)}.btn--sm{min-height:2rem;padding:var(--spacing-sm) var(--spacing-md);font-size:var(--font-size-sm)}.btn--md{min-height:2.5rem;padding:var(--spacing-md) var(--spacing-lg);font-size:var(--font-size-base)}.btn--lg{min-height:3rem;padding:var(--spacing-lg) var(--spacing-xl);font-size:var(--font-size-lg)}.btn--xl{min-height:3.5rem;padding:var(--spacing-xl) var(--spacing-2xl);font-size:var(--font-size-xl)}.btn--primary{color:var(--md-on-primary);background:var(--md-primary);box-shadow:var(--shadow-sm)}.btn--primary:hover:not(:disabled){background:var(--primary-color-hover);box-shadow:var(--shadow-md);transform:translateY(-.125rem)}.btn--secondary{color:var(--md-on-secondary);background:var(--md-secondary);box-shadow:var(--shadow-sm)}.btn--secondary:hover:not(:disabled){background:var(--secondary-color-light);box-shadow:var(--shadow-md);transform:translateY(-.125rem)}.btn--success{color:#fff;background:var(--success-color);box-shadow:var(--shadow-sm)}.btn--success:hover:not(:disabled){background:var(--success-color-light);box-shadow:var(--shadow-md);transform:translateY(-.125rem)}.btn--error{color:var(--md-on-error);background:var(--md-error);box-shadow:var(--shadow-sm)}.btn--error:hover:not(:disabled){background:var(--error-color-light);box-shadow:var(--shadow-md);transform:translateY(-.125rem)}.btn--warning{color:#fff;background:var(--warning-color);box-shadow:var(--shadow-sm)}.btn--warning:hover:not(:disabled){background:var(--warning-color-light);box-shadow:var(--shadow-md);transform:translateY(-.125rem)}.btn--info{color:#fff;background:var(--info-color);box-shadow:var(--shadow-sm)}.btn--info:hover:not(:disabled){background:var(--info-color-light);box-shadow:var(--shadow-md);transform:translateY(-.125rem)}.btn--neutral{color:#fff;background:var(--neutral-color);box-shadow:var(--shadow-sm)}.btn--neutral:hover:not(:disabled){background:var(--neutral-color-light);box-shadow:var(--shadow-md);transform:translateY(-.125rem)}.btn--ghost{color:var(--md-on-surface);background:transparent;border-color:var(--md-outline-variant)}.btn--ghost:hover:not(:disabled){color:var(--md-primary);background:var(--bg-hover);border-color:var(--border-color-hover)}.btn--full-width{width:100%}.btn__spinner{position:absolute;display:inline-flex;align-items:center;justify-content:center;width:1em;height:1em;animation:btn-spin .9s linear infinite}@keyframes btn-spin{to{transform:rotate(360deg)}}.btn__icon{display:inline-flex;flex-shrink:0;align-items:center;justify-content:center}.btn__icon--left{margin-right:var(--spacing-xs)}.btn__icon--right{margin-left:var(--spacing-xs)}.btn__content{display:inline-flex;align-items:center;justify-content:center}.btn--loading .btn__content{opacity:0}.card{position:relative;overflow:hidden;background:var(--md-surface);border-radius:var(--border-radius-lg);transition:var(--transition-all)}.card--default{background:var(--md-surface);border:var(--border-width-thin) solid var(--md-outline-variant);box-shadow:var(--shadow-sm)}.card--elevated{background:var(--md-surface);border:var(--border-width-thin) solid var(--md-outline-variant);box-shadow:var(--shadow-lg)}.card--outlined{background:transparent;border:var(--border-width-thin) solid var(--md-outline-variant);box-shadow:none}.card--flat{background:var(--md-surface);border:none;box-shadow:none}.card--padding-none{padding:0}.card--padding-sm{padding:var(--spacing-md)}.card--padding-md{padding:var(--spacing-lg)}.card--padding-lg{padding:var(--spacing-xl)}.card--padding-xl{padding:var(--spacing-2xl)}.card--hoverable:hover{box-shadow:var(--shadow-md)}.app-footer{position:relative;z-index:1;display:flex;flex-shrink:0;align-items:center;justify-content:center;width:100%;max-height:5vh;padding:var(--spacing-lg) var(--spacing-2xl);background:var(--bg-secondary);border-top:1px solid var(--border-color)}.app-footer-powered{display:flex;gap:var(--spacing-md);align-items:center}.app-footer-powered-text{font-size:.95rem;font-weight:var(--font-weight-normal);color:var(--text-secondary)}.app-footer-logo-wrap{display:flex;align-items:center}.app-footer-logo{width:auto;height:1.5rem;-o-object-fit:contain;object-fit:contain}[data-theme=dark] .app-footer-logo{filter:brightness(0) invert(1)}[data-theme=light] .app-footer-logo{filter:brightness(0)}.app-footer-logo-fallback{display:flex;align-items:center;font-family:Orbitron,sans-serif;font-size:1rem;font-weight:700;color:var(--md-primary);letter-spacing:.1em}.app-header{position:fixed;top:0;right:0;left:0;z-index:1000;width:100%;-webkit-backdrop-filter:blur(12px);backdrop-filter:blur(12px);transition:background .3s cubic-bezier(.4,0,.2,1)}.app-header-top-bar{width:100%;height:.125rem;background:var(--md-primary)}.app-header-content{display:flex;align-items:center;justify-content:space-between;padding:.5rem 1.5rem;box-shadow:var(--shadow-sm);transition:background .3s cubic-bezier(.4,0,.2,1),border-color .3s cubic-bezier(.4,0,.2,1)}[data-theme=light] .app-header-content,[data-theme=dark] .app-header-content{color:var(--md-on-surface);background:color-mix(in srgb,var(--md-surface) 18%,transparent);border-bottom:1px solid color-mix(in srgb,var(--md-outline-variant) 30%,transparent)}.app-header.scrolled .app-header-content{background:color-mix(in srgb,var(--md-surface) 14%,transparent);border-bottom-color:color-mix(in srgb,var(--md-outline-variant) 22%,transparent)}.app-header-left{display:flex;gap:.75rem;align-items:center;cursor:pointer;transition:opacity .2s ease}.app-header-left:hover{opacity:.8}.app-header-logo{display:flex;flex-shrink:0;align-items:center;justify-content:center;width:4rem;height:4rem}.app-header-logo img{width:100%;height:100%;-o-object-fit:contain;object-fit:contain}.logo-icon-fallback{display:none;width:100%;height:100%}.app-header-title{display:flex;flex-direction:column;gap:.25rem}.app-header-title h1{display:inline-flex;align-items:baseline;margin:0;font-family:Orbitron,sans-serif;font-size:1.375rem;font-weight:700;line-height:1.2;color:var(--md-on-surface);letter-spacing:.05em}.app-header-title-highlight{color:var(--md-primary)}.app-header-title p{margin:0;font-size:.8125rem;font-weight:400;color:var(--md-on-surface-variant)}.app-header-right{display:flex;flex-shrink:0;gap:.75rem;align-items:center}@media(max-width:768px){.app-header-content{flex-direction:column;gap:.75rem;padding:.75rem 1rem}.app-header-right{flex-wrap:wrap;justify-content:space-between;width:100%}.app-header-title h1{font-size:1.25rem}.app-header-title p{font-size:.75rem}}.input-wrapper{display:flex;flex-direction:column;gap:var(--spacing-xs)}.input-wrapper--full-width{width:100%}.input-label{font-size:var(--font-size-sm);font-weight:var(--font-weight-semibold);color:var(--md-on-surface)}.input-container{position:relative;display:flex;width:100%;align-items:center}.input-container .input-icon--left{left:var(--spacing-md)}.input-container .input-icon--right{right:var(--spacing-md)}.input{width:100%;font-family:inherit;font-size:inherit;color:var(--md-on-surface);outline:none;background:var(--md-surface);border:var(--border-width-thin) solid var(--md-outline-variant);border-radius:var(--border-radius-md);transition:var(--transition-all)}.input::-moz-placeholder{color:var(--md-on-surface-variant);opacity:.7}.input::placeholder{color:var(--md-on-surface-variant);opacity:.7}.input:hover:not(:disabled):not(:focus){border-color:var(--border-color-hover)}.input:focus{border-color:var(--border-color-focus);box-shadow:0 0 0 .1875rem #2f5d8c26}.input:disabled{cursor:not-allowed;background:var(--md-surface-container-high);opacity:.6}.input--sm{min-height:2rem;padding:var(--spacing-sm) var(--spacing-md);font-size:var(--font-size-sm)}.input--md{min-height:2.5rem;padding:var(--spacing-md) var(--spacing-lg);font-size:var(--font-size-base)}.input--lg{min-height:3rem;padding:var(--spacing-lg) var(--spacing-xl);font-size:var(--font-size-lg)}.input--has-left-icon{padding-left:2.5rem}.input--has-right-icon{padding-right:2.5rem}.input-icon{position:absolute;z-index:1;display:flex;align-items:center;justify-content:center;color:var(--md-on-surface-variant);pointer-events:none}.input-container:focus-within .input-icon{color:var(--md-primary)}.input-icon svg{width:1.125rem;height:1.125rem}.input--error{border-color:var(--md-error)}.input--error:focus{border-color:var(--md-error);box-shadow:0 0 0 .1875rem #ba1a1a33}.input-error{display:block;margin-top:var(--spacing-xs);font-size:var(--font-size-xs);color:var(--md-error)}.input-helper{display:block;margin-top:var(--spacing-xs);font-size:var(--font-size-xs);color:var(--md-on-surface-variant)}.modal-overlay{position:fixed;inset:0;z-index:var(--z-index-modal-backdrop);display:flex;align-items:center;justify-content:center;min-height:100dvh;padding:var(--spacing-lg);overflow-y:auto;background:#00000080;-webkit-backdrop-filter:blur(8px);backdrop-filter:blur(8px);animation:modal-fade-in var(--transition-base)}@keyframes modal-fade-in{0%{opacity:0}to{opacity:1}}.modal{position:relative;z-index:var(--z-index-modal);display:flex;width:100%;flex-direction:column;max-width:100%;max-height:90vh;margin:auto;overflow:hidden;background:var(--md-surface);border:var(--border-width-thin) solid var(--md-outline-variant);border-radius:var(--border-radius-2xl);box-shadow:var(--shadow-2xl);animation:modal-slide-up var(--transition-base)}@keyframes modal-slide-up{0%{transform:translateY(1.25rem);opacity:0}to{transform:translateY(0);opacity:1}}.modal--sm{max-width:25rem}.modal--md{max-width:31.25rem}.modal--lg{max-width:43.75rem}.modal--xl{max-width:56.25rem}.modal--full{max-width:90vw;max-height:90vh}.modal-header{display:flex;flex-shrink:0;gap:var(--spacing-lg);align-items:flex-start;justify-content:space-between;padding:var(--spacing-2xl);border-bottom:var(--border-width-thin) solid var(--md-outline-variant)}.modal-header-content{flex:1}.modal-title{margin:0 0 var(--spacing-xs) 0;font-size:var(--font-size-2xl);font-weight:var(--font-weight-semibold);line-height:var(--line-height-tight);color:var(--md-on-surface)}.modal-subtitle{margin:0;font-size:var(--font-size-base);line-height:var(--line-height-normal);color:var(--md-on-surface-variant)}.modal-close{display:flex;flex-shrink:0;align-items:center;justify-content:center;width:2.25rem;height:2.25rem;color:var(--md-on-surface);cursor:pointer;background:var(--md-surface-container-high);border:none;border-radius:var(--border-radius-md);transition:var(--transition-all)}.modal-close:hover{color:var(--md-error);background:color-mix(in srgb,var(--md-error) 15%,var(--md-surface))}.modal-close svg{width:1.25rem;height:1.25rem}.modal-content{display:flex;flex:1;flex-direction:column;min-height:0;padding:var(--spacing-2xl);overflow-x:hidden;overflow-y:auto}.modal:not(:has(.modal-header)) .modal-content{padding-top:var(--spacing-2xl)}.paragraph{margin:0;line-height:var(--line-height-relaxed);color:var(--text-primary);transition:var(--transition-colors)}.paragraph--xs{font-size:var(--font-size-xs);line-height:var(--line-height-normal)}.paragraph--sm{font-size:var(--font-size-sm);line-height:var(--line-height-normal)}.paragraph--md{font-size:var(--font-size-base);line-height:var(--line-height-relaxed)}.paragraph--lg{font-size:var(--font-size-lg);line-height:var(--line-height-loose)}.paragraph--light{font-weight:var(--font-weight-light)}.paragraph--normal{font-weight:var(--font-weight-normal)}.paragraph--medium{font-weight:var(--font-weight-medium)}.paragraph--align-left{text-align:left}.paragraph--align-center{text-align:center}.paragraph--align-right{text-align:right}.paragraph--align-justify{text-align:justify}.paragraph--muted{color:var(--text-muted)}.subtitle{margin:0;line-height:var(--line-height-normal);color:var(--text-secondary);transition:var(--transition-colors)}.subtitle--xs{font-size:var(--font-size-xs)}.subtitle--sm{font-size:var(--font-size-sm)}.subtitle--md{font-size:var(--font-size-base)}.subtitle--lg{font-size:var(--font-size-lg)}.subtitle--normal{font-weight:var(--font-weight-normal)}.subtitle--medium{font-weight:var(--font-weight-medium)}.subtitle--semibold{font-weight:var(--font-weight-semibold)}.subtitle--align-left{text-align:left}.subtitle--align-center{text-align:center}.subtitle--align-right{text-align:right}.subtitle--muted{color:var(--text-muted);opacity:.8}.title{margin:0;line-height:var(--line-height-tight);color:var(--text-primary);transition:var(--transition-colors)}.title--xs{font-size:var(--font-size-sm)}.title--sm{font-size:var(--font-size-base)}.title--md{font-size:var(--font-size-lg)}.title--lg{font-size:var(--font-size-xl)}.title--xl{font-size:var(--font-size-2xl)}.title--2xl{font-size:var(--font-size-3xl)}.title--3xl{font-size:var(--font-size-4xl)}.title--4xl{font-size:3rem}.title--light{font-weight:var(--font-weight-light)}.title--normal{font-weight:var(--font-weight-normal)}.title--medium{font-weight:var(--font-weight-medium)}.title--semibold{font-weight:var(--font-weight-semibold)}.title--bold{font-weight:var(--font-weight-bold)}.title--extrabold{font-weight:800}.title--align-left{text-align:left}.title--align-center{text-align:center}.title--align-right{text-align:right}.title--gradient{-webkit-text-fill-color:transparent;background:linear-gradient(135deg,var(--text-primary) 0%,var(--primary-color) 50%,var(--secondary-color) 100%);-webkit-background-clip:text;background-clip:text}[data-theme=dark] .title--gradient{background:linear-gradient(135deg,#ffffff 0%,var(--primary-color-light) 50%,var(--secondary-color) 100%);-webkit-background-clip:text;background-clip:text}
|
|
@@ -0,0 +1,343 @@
|
|
|
1
|
+
import { jsxs as m, jsx as e } from "react/jsx-runtime";
|
|
2
|
+
import { useState as y, useEffect as C, useContext as k, createContext as E } from "react";
|
|
3
|
+
const M = ({
|
|
4
|
+
variant: a = "primary",
|
|
5
|
+
size: t = "md",
|
|
6
|
+
fullWidth: n = !1,
|
|
7
|
+
isLoading: s = !1,
|
|
8
|
+
leftIcon: r,
|
|
9
|
+
rightIcon: l,
|
|
10
|
+
children: o,
|
|
11
|
+
className: d = "",
|
|
12
|
+
disabled: h,
|
|
13
|
+
palette: p,
|
|
14
|
+
...i
|
|
15
|
+
}) => {
|
|
16
|
+
const c = `btn--${a}`, b = `btn--${t}`, f = n ? "btn--full-width" : "", g = s ? "btn--loading" : "", $ = p && a === "primary" ? `btn--palette-${p}` : "", v = `btn ${c} ${b} ${f} ${g} ${$} ${d}`.trim();
|
|
17
|
+
return /* @__PURE__ */ m(
|
|
18
|
+
"button",
|
|
19
|
+
{
|
|
20
|
+
className: v,
|
|
21
|
+
disabled: h || s,
|
|
22
|
+
...i,
|
|
23
|
+
children: [
|
|
24
|
+
s && /* @__PURE__ */ e("span", { "aria-hidden": "true", className: "btn__spinner", children: /* @__PURE__ */ m(
|
|
25
|
+
"svg",
|
|
26
|
+
{
|
|
27
|
+
fill: "none",
|
|
28
|
+
stroke: "currentColor",
|
|
29
|
+
strokeWidth: "2",
|
|
30
|
+
viewBox: "0 0 24 24",
|
|
31
|
+
children: [
|
|
32
|
+
/* @__PURE__ */ e("circle", { cx: "12", cy: "12", r: "10", strokeOpacity: "0.25" }),
|
|
33
|
+
/* @__PURE__ */ e("path", { d: "M12 2 A10 10 0 0 1 22 12", strokeLinecap: "round" })
|
|
34
|
+
]
|
|
35
|
+
}
|
|
36
|
+
) }),
|
|
37
|
+
!s && r && /* @__PURE__ */ e("span", { className: "btn__icon btn__icon--left", children: r }),
|
|
38
|
+
/* @__PURE__ */ e("span", { className: "btn__content", children: o }),
|
|
39
|
+
!s && l && /* @__PURE__ */ e("span", { className: "btn__icon btn__icon--right", children: l })
|
|
40
|
+
]
|
|
41
|
+
}
|
|
42
|
+
);
|
|
43
|
+
}, S = ({
|
|
44
|
+
variant: a = "default",
|
|
45
|
+
padding: t = "md",
|
|
46
|
+
hoverable: n = !1,
|
|
47
|
+
children: s,
|
|
48
|
+
className: r = "",
|
|
49
|
+
...l
|
|
50
|
+
}) => {
|
|
51
|
+
const o = "card", d = `card--${a}`, h = `card--padding-${t}`, i = `${o} ${d} ${h} ${n ? "card--hoverable" : ""} ${r}`.trim();
|
|
52
|
+
return /* @__PURE__ */ e("div", { className: i, ...l, children: s });
|
|
53
|
+
}, T = ({
|
|
54
|
+
poweredByText: a = "Powered by",
|
|
55
|
+
logoSrc: t,
|
|
56
|
+
logoAlt: n = "Logo",
|
|
57
|
+
logoFallbackText: s,
|
|
58
|
+
className: r = ""
|
|
59
|
+
}) => /* @__PURE__ */ e("footer", { className: `app-footer ${r}`.trim(), children: /* @__PURE__ */ m("div", { className: "app-footer-powered", children: [
|
|
60
|
+
a && /* @__PURE__ */ e("span", { className: "app-footer-powered-text", children: a }),
|
|
61
|
+
(t || s) && /* @__PURE__ */ m("div", { className: "app-footer-logo-wrap", children: [
|
|
62
|
+
t && /* @__PURE__ */ e(
|
|
63
|
+
"img",
|
|
64
|
+
{
|
|
65
|
+
alt: n,
|
|
66
|
+
className: "app-footer-logo",
|
|
67
|
+
onError: (l) => {
|
|
68
|
+
l.target.style.display = "none";
|
|
69
|
+
const o = l.target.nextElementSibling;
|
|
70
|
+
o && (o.style.display = "flex");
|
|
71
|
+
},
|
|
72
|
+
src: t
|
|
73
|
+
}
|
|
74
|
+
),
|
|
75
|
+
s && /* @__PURE__ */ e(
|
|
76
|
+
"span",
|
|
77
|
+
{
|
|
78
|
+
className: "app-footer-logo-fallback",
|
|
79
|
+
style: { display: t ? "none" : "flex" },
|
|
80
|
+
children: s
|
|
81
|
+
}
|
|
82
|
+
)
|
|
83
|
+
] })
|
|
84
|
+
] }) }), N = () => typeof document > "u" ? "light" : document.documentElement.getAttribute("data-theme") === "dark" ? "dark" : "light", P = ({
|
|
85
|
+
logoSrc: a,
|
|
86
|
+
logoDarkSrc: t,
|
|
87
|
+
logoAlt: n = "Logo",
|
|
88
|
+
title: s,
|
|
89
|
+
subtitle: r,
|
|
90
|
+
theme: l,
|
|
91
|
+
onLogoClick: o,
|
|
92
|
+
rightContent: d,
|
|
93
|
+
className: h = ""
|
|
94
|
+
}) => {
|
|
95
|
+
const [p, i] = y(!1), [u, c] = y(
|
|
96
|
+
() => l ?? N()
|
|
97
|
+
), b = u === "dark" && t ? t : a;
|
|
98
|
+
C(() => {
|
|
99
|
+
const $ = () => i(window.scrollY > 10);
|
|
100
|
+
return window.addEventListener("scroll", $, { passive: !0 }), () => window.removeEventListener("scroll", $);
|
|
101
|
+
}, []), C(() => {
|
|
102
|
+
if (l) {
|
|
103
|
+
c(l);
|
|
104
|
+
return;
|
|
105
|
+
}
|
|
106
|
+
const $ = () => c(N());
|
|
107
|
+
if ($(), typeof MutationObserver > "u")
|
|
108
|
+
return;
|
|
109
|
+
const v = new MutationObserver($);
|
|
110
|
+
return v.observe(document.documentElement, {
|
|
111
|
+
attributes: !0,
|
|
112
|
+
attributeFilter: ["data-theme"]
|
|
113
|
+
}), () => v.disconnect();
|
|
114
|
+
}, [l]);
|
|
115
|
+
const f = () => o?.(), g = ($) => {
|
|
116
|
+
$.key === "Enter" && o?.();
|
|
117
|
+
};
|
|
118
|
+
return /* @__PURE__ */ m(
|
|
119
|
+
"header",
|
|
120
|
+
{
|
|
121
|
+
className: `app-header ${p ? "scrolled" : ""} ${h}`.trim(),
|
|
122
|
+
children: [
|
|
123
|
+
/* @__PURE__ */ e("div", { className: "app-header-top-bar" }),
|
|
124
|
+
/* @__PURE__ */ m("div", { className: "app-header-content", children: [
|
|
125
|
+
/* @__PURE__ */ m(
|
|
126
|
+
"div",
|
|
127
|
+
{
|
|
128
|
+
className: "app-header-left",
|
|
129
|
+
onClick: o ? f : void 0,
|
|
130
|
+
onKeyDown: o ? g : void 0,
|
|
131
|
+
role: o ? "button" : void 0,
|
|
132
|
+
tabIndex: o ? 0 : void 0,
|
|
133
|
+
children: [
|
|
134
|
+
b && /* @__PURE__ */ m("div", { className: "app-header-logo", children: [
|
|
135
|
+
/* @__PURE__ */ e(
|
|
136
|
+
"img",
|
|
137
|
+
{
|
|
138
|
+
alt: n,
|
|
139
|
+
onError: ($) => {
|
|
140
|
+
$.target.style.display = "none";
|
|
141
|
+
const v = $.target.nextElementSibling;
|
|
142
|
+
v && (v.style.display = "block");
|
|
143
|
+
},
|
|
144
|
+
src: b
|
|
145
|
+
}
|
|
146
|
+
),
|
|
147
|
+
/* @__PURE__ */ m(
|
|
148
|
+
"svg",
|
|
149
|
+
{
|
|
150
|
+
className: "logo-icon-fallback",
|
|
151
|
+
fill: "none",
|
|
152
|
+
stroke: "currentColor",
|
|
153
|
+
strokeWidth: "2",
|
|
154
|
+
viewBox: "0 0 24 24",
|
|
155
|
+
children: [
|
|
156
|
+
/* @__PURE__ */ e("path", { d: "M12 2L2 7l10 5 10-5-10-5z" }),
|
|
157
|
+
/* @__PURE__ */ e("path", { d: "M2 17l10 5 10-5M2 12l10 5 10-5" })
|
|
158
|
+
]
|
|
159
|
+
}
|
|
160
|
+
)
|
|
161
|
+
] }),
|
|
162
|
+
(s || r) && /* @__PURE__ */ m("div", { className: "app-header-title", children: [
|
|
163
|
+
s && /* @__PURE__ */ e("h1", { children: s }),
|
|
164
|
+
r && /* @__PURE__ */ e("p", { children: r })
|
|
165
|
+
] })
|
|
166
|
+
]
|
|
167
|
+
}
|
|
168
|
+
),
|
|
169
|
+
d && /* @__PURE__ */ e("div", { className: "app-header-right", children: d })
|
|
170
|
+
] })
|
|
171
|
+
]
|
|
172
|
+
}
|
|
173
|
+
);
|
|
174
|
+
}, W = ({
|
|
175
|
+
label: a,
|
|
176
|
+
error: t,
|
|
177
|
+
helperText: n,
|
|
178
|
+
leftIcon: s,
|
|
179
|
+
rightIcon: r,
|
|
180
|
+
fullWidth: l = !1,
|
|
181
|
+
size: o = "md",
|
|
182
|
+
className: d = "",
|
|
183
|
+
id: h,
|
|
184
|
+
...p
|
|
185
|
+
}) => {
|
|
186
|
+
const i = h || `input-${Math.random().toString(36).substring(2, 9)}`, u = !!t, c = "input", b = `input--${o}`, x = `${c} ${b} ${u ? "input--error" : ""} ${l ? "input--full-width" : ""} ${s ? "input--has-left-icon" : ""} ${r ? "input--has-right-icon" : ""} ${d}`.trim();
|
|
187
|
+
return /* @__PURE__ */ m(
|
|
188
|
+
"div",
|
|
189
|
+
{
|
|
190
|
+
className: `input-wrapper ${l ? "input-wrapper--full-width" : ""}`,
|
|
191
|
+
children: [
|
|
192
|
+
a && /* @__PURE__ */ e("label", { className: "input-label", htmlFor: i, children: a }),
|
|
193
|
+
/* @__PURE__ */ m("div", { className: "input-container", children: [
|
|
194
|
+
s && /* @__PURE__ */ e("span", { className: "input-icon input-icon--left", children: s }),
|
|
195
|
+
/* @__PURE__ */ e(
|
|
196
|
+
"input",
|
|
197
|
+
{
|
|
198
|
+
"aria-describedby": t ? `${i}-error` : n ? `${i}-helper` : void 0,
|
|
199
|
+
"aria-invalid": u ? !0 : void 0,
|
|
200
|
+
className: x,
|
|
201
|
+
id: i,
|
|
202
|
+
...p
|
|
203
|
+
}
|
|
204
|
+
),
|
|
205
|
+
r && /* @__PURE__ */ e("span", { className: "input-icon input-icon--right", children: r })
|
|
206
|
+
] }),
|
|
207
|
+
t && /* @__PURE__ */ e("span", { className: "input-error", id: `${i}-error`, role: "alert", children: t }),
|
|
208
|
+
n && !t && /* @__PURE__ */ e("span", { className: "input-helper", id: `${i}-helper`, children: n })
|
|
209
|
+
]
|
|
210
|
+
}
|
|
211
|
+
);
|
|
212
|
+
}, I = ({
|
|
213
|
+
isOpen: a,
|
|
214
|
+
onClose: t,
|
|
215
|
+
title: n,
|
|
216
|
+
subtitle: s,
|
|
217
|
+
children: r,
|
|
218
|
+
size: l = "md",
|
|
219
|
+
showCloseButton: o = !0,
|
|
220
|
+
closeOnOverlayClick: d = !0,
|
|
221
|
+
className: h = ""
|
|
222
|
+
}) => {
|
|
223
|
+
if (C(() => (a ? document.body.style.overflow = "hidden" : document.body.style.overflow = "", () => {
|
|
224
|
+
document.body.style.overflow = "";
|
|
225
|
+
}), [a]), C(() => {
|
|
226
|
+
const c = (b) => {
|
|
227
|
+
b.key === "Escape" && a && t();
|
|
228
|
+
};
|
|
229
|
+
return a && document.addEventListener("keydown", c), () => document.removeEventListener("keydown", c);
|
|
230
|
+
}, [a, t]), !a)
|
|
231
|
+
return null;
|
|
232
|
+
const p = (c) => {
|
|
233
|
+
d && c.target === c.currentTarget && t();
|
|
234
|
+
}, u = `modal ${`modal--${l}`} ${h}`.trim();
|
|
235
|
+
return /* @__PURE__ */ e(
|
|
236
|
+
"div",
|
|
237
|
+
{
|
|
238
|
+
"aria-labelledby": n ? "modal-title" : void 0,
|
|
239
|
+
"aria-modal": "true",
|
|
240
|
+
className: "modal-overlay",
|
|
241
|
+
onClick: p,
|
|
242
|
+
role: "dialog",
|
|
243
|
+
children: /* @__PURE__ */ m("div", { className: u, children: [
|
|
244
|
+
(n || s || o) && /* @__PURE__ */ m("div", { className: "modal-header", children: [
|
|
245
|
+
(n || s) && /* @__PURE__ */ m("div", { className: "modal-header-content", children: [
|
|
246
|
+
n && /* @__PURE__ */ e("h2", { className: "modal-title", id: "modal-title", children: n }),
|
|
247
|
+
s && /* @__PURE__ */ e("p", { className: "modal-subtitle", children: s })
|
|
248
|
+
] }),
|
|
249
|
+
o && /* @__PURE__ */ e(
|
|
250
|
+
"button",
|
|
251
|
+
{
|
|
252
|
+
"aria-label": "Fechar modal",
|
|
253
|
+
className: "modal-close",
|
|
254
|
+
onClick: t,
|
|
255
|
+
type: "button",
|
|
256
|
+
children: /* @__PURE__ */ m(
|
|
257
|
+
"svg",
|
|
258
|
+
{
|
|
259
|
+
fill: "none",
|
|
260
|
+
stroke: "currentColor",
|
|
261
|
+
strokeWidth: "2",
|
|
262
|
+
viewBox: "0 0 24 24",
|
|
263
|
+
children: [
|
|
264
|
+
/* @__PURE__ */ e("line", { x1: "18", x2: "6", y1: "6", y2: "18" }),
|
|
265
|
+
/* @__PURE__ */ e("line", { x1: "6", x2: "18", y1: "6", y2: "18" })
|
|
266
|
+
]
|
|
267
|
+
}
|
|
268
|
+
)
|
|
269
|
+
}
|
|
270
|
+
)
|
|
271
|
+
] }),
|
|
272
|
+
/* @__PURE__ */ e("div", { className: "modal-content", children: r })
|
|
273
|
+
] })
|
|
274
|
+
}
|
|
275
|
+
);
|
|
276
|
+
}, R = ({
|
|
277
|
+
as: a = "p",
|
|
278
|
+
size: t = "md",
|
|
279
|
+
weight: n = "normal",
|
|
280
|
+
align: s = "left",
|
|
281
|
+
muted: r = !1,
|
|
282
|
+
children: l,
|
|
283
|
+
className: o = "",
|
|
284
|
+
...d
|
|
285
|
+
}) => {
|
|
286
|
+
const h = a, p = "paragraph", i = `paragraph--${t}`, u = `paragraph--${n}`, c = `paragraph--align-${s}`, f = `${p} ${i} ${u} ${c} ${r ? "paragraph--muted" : ""} ${o}`.trim();
|
|
287
|
+
return /* @__PURE__ */ e(h, { className: f, ...d, children: l });
|
|
288
|
+
}, A = ({
|
|
289
|
+
as: a = "p",
|
|
290
|
+
size: t = "md",
|
|
291
|
+
weight: n = "normal",
|
|
292
|
+
align: s = "left",
|
|
293
|
+
muted: r = !1,
|
|
294
|
+
children: l,
|
|
295
|
+
className: o = "",
|
|
296
|
+
...d
|
|
297
|
+
}) => {
|
|
298
|
+
const h = a, p = "subtitle", i = `subtitle--${t}`, u = `subtitle--${n}`, c = `subtitle--align-${s}`, f = `${p} ${i} ${u} ${c} ${r ? "subtitle--muted" : ""} ${o}`.trim();
|
|
299
|
+
return /* @__PURE__ */ e(h, { className: f, ...d, children: l });
|
|
300
|
+
}, j = ({
|
|
301
|
+
as: a = "h1",
|
|
302
|
+
size: t = "2xl",
|
|
303
|
+
weight: n = "bold",
|
|
304
|
+
align: s = "left",
|
|
305
|
+
gradient: r = !1,
|
|
306
|
+
children: l,
|
|
307
|
+
className: o = "",
|
|
308
|
+
...d
|
|
309
|
+
}) => {
|
|
310
|
+
const h = a, p = "title", i = `title--${t}`, u = `title--${n}`, c = `title--align-${s}`, f = `${p} ${i} ${u} ${c} ${r ? "title--gradient" : ""} ${o}`.trim();
|
|
311
|
+
return /* @__PURE__ */ e(h, { className: f, ...d, children: l });
|
|
312
|
+
}, w = E(void 0), B = () => {
|
|
313
|
+
const a = k(w);
|
|
314
|
+
if (!a)
|
|
315
|
+
throw new Error("useTheme must be used within a ThemeProvider");
|
|
316
|
+
return a;
|
|
317
|
+
}, F = ({
|
|
318
|
+
children: a,
|
|
319
|
+
defaultTheme: t = "light"
|
|
320
|
+
}) => {
|
|
321
|
+
const [n, s] = y(() => typeof window > "u" ? t : window.localStorage.getItem("theme") || t);
|
|
322
|
+
C(() => {
|
|
323
|
+
typeof window > "u" || (window.localStorage.setItem("theme", n), document.documentElement.setAttribute("data-theme", n));
|
|
324
|
+
}, [n]);
|
|
325
|
+
const r = () => {
|
|
326
|
+
s((l) => l === "dark" ? "light" : "dark");
|
|
327
|
+
};
|
|
328
|
+
return /* @__PURE__ */ e(w.Provider, { value: { theme: n, toggleTheme: r }, children: a });
|
|
329
|
+
};
|
|
330
|
+
export {
|
|
331
|
+
M as Button,
|
|
332
|
+
S as Card,
|
|
333
|
+
T as Footer,
|
|
334
|
+
P as Header,
|
|
335
|
+
W as Input,
|
|
336
|
+
I as Modal,
|
|
337
|
+
R as Paragraph,
|
|
338
|
+
A as Subtitle,
|
|
339
|
+
F as ThemeProvider,
|
|
340
|
+
j as Title,
|
|
341
|
+
B as useTheme
|
|
342
|
+
};
|
|
343
|
+
//# sourceMappingURL=oficios-ui.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"oficios-ui.js","sources":["../src/components/Button/Button.tsx","../src/components/Card/Card.tsx","../src/components/Footer/Footer.tsx","../src/components/Header/Header.tsx","../src/components/Input/Input.tsx","../src/components/Modal/Modal.tsx","../src/components/Paragraph/Paragraph.tsx","../src/components/Subtitle/Subtitle.tsx","../src/components/Title/Title.tsx","../src/theme/ThemeProvider.tsx"],"sourcesContent":["import type React from 'react';\nimport './Button.css';\n\n/** Paletas do guia de marca (só afeta variant primary). Use para escolher o modelo de cor do botão. */\nexport type ButtonPalette =\n | 'verde-vibrante'\n | 'verde-profundo'\n | 'grafite-azulado'\n | 'azul-acinzentado'\n | 'cinza-medio'\n | 'cinza-escuro'\n | 'off-white';\n\nexport interface ButtonProps\n extends React.ButtonHTMLAttributes<HTMLButtonElement> {\n children: React.ReactNode;\n fullWidth?: boolean;\n isLoading?: boolean;\n leftIcon?: React.ReactNode;\n /** Paleta de cor do guia de marca (aplica-se ao primary). Ignorado em outros variants. */\n palette?: ButtonPalette;\n rightIcon?: React.ReactNode;\n size?: 'xs' | 'sm' | 'md' | 'lg' | 'xl';\n variant?:\n | 'primary'\n | 'secondary'\n | 'success'\n | 'error'\n | 'warning'\n | 'info'\n | 'neutral'\n | 'ghost';\n}\n\nexport const Button: React.FC<ButtonProps> = ({\n variant = 'primary',\n size = 'md',\n fullWidth = false,\n isLoading = false,\n leftIcon,\n rightIcon,\n children,\n className = '',\n disabled,\n palette,\n ...props\n}) => {\n const baseClass = 'btn';\n const variantClass = `btn--${variant}`;\n const sizeClass = `btn--${size}`;\n const fullWidthClass = fullWidth ? 'btn--full-width' : '';\n const loadingClass = isLoading ? 'btn--loading' : '';\n const paletteClass =\n palette && variant === 'primary' ? `btn--palette-${palette}` : '';\n const combinedClass =\n `${baseClass} ${variantClass} ${sizeClass} ${fullWidthClass} ${loadingClass} ${paletteClass} ${className}`.trim();\n\n return (\n <button\n className={combinedClass}\n disabled={disabled || isLoading}\n {...props}\n >\n {isLoading && (\n <span aria-hidden=\"true\" className=\"btn__spinner\">\n <svg\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n viewBox=\"0 0 24 24\"\n >\n <circle cx=\"12\" cy=\"12\" r=\"10\" strokeOpacity=\"0.25\" />\n <path d=\"M12 2 A10 10 0 0 1 22 12\" strokeLinecap=\"round\" />\n </svg>\n </span>\n )}\n {!isLoading && leftIcon && (\n <span className=\"btn__icon btn__icon--left\">{leftIcon}</span>\n )}\n <span className=\"btn__content\">{children}</span>\n {!isLoading && rightIcon && (\n <span className=\"btn__icon btn__icon--right\">{rightIcon}</span>\n )}\n </button>\n );\n};\n","import type React from 'react';\nimport './Card.css';\n\nexport interface CardProps extends React.HTMLAttributes<HTMLDivElement> {\n children: React.ReactNode;\n hoverable?: boolean;\n padding?: 'none' | 'sm' | 'md' | 'lg' | 'xl';\n variant?: 'default' | 'elevated' | 'outlined' | 'flat';\n}\n\nexport const Card: React.FC<CardProps> = ({\n variant = 'default',\n padding = 'md',\n hoverable = false,\n children,\n className = '',\n ...props\n}) => {\n const baseClass = 'card';\n const variantClass = `card--${variant}`;\n const paddingClass = `card--padding-${padding}`;\n const hoverableClass = hoverable ? 'card--hoverable' : '';\n const combinedClass =\n `${baseClass} ${variantClass} ${paddingClass} ${hoverableClass} ${className}`.trim();\n\n return (\n <div className={combinedClass} {...props}>\n {children}\n </div>\n );\n};\n","import type React from 'react';\nimport './Footer.css';\n\nexport interface FooterProps {\n /** Classe CSS adicional */\n className?: string;\n /** Texto alternativo do logo */\n logoAlt?: string;\n /** Texto exibido se a imagem do logo falhar (ex.: \"SBK\") */\n logoFallbackText?: string;\n /** URL da imagem do logo */\n logoSrc?: string;\n /** Texto antes do logo (ex.: \"Powered by\") */\n poweredByText?: string;\n}\n\nexport const Footer: React.FC<FooterProps> = ({\n poweredByText = 'Powered by',\n logoSrc,\n logoAlt = 'Logo',\n logoFallbackText,\n className = '',\n}) => {\n return (\n <footer className={`app-footer ${className}`.trim()}>\n <div className=\"app-footer-powered\">\n {poweredByText && (\n <span className=\"app-footer-powered-text\">{poweredByText}</span>\n )}\n {(logoSrc || logoFallbackText) && (\n <div className=\"app-footer-logo-wrap\">\n {logoSrc && (\n <img\n alt={logoAlt}\n className=\"app-footer-logo\"\n onError={(e) => {\n (e.target as HTMLImageElement).style.display = 'none';\n const next = (e.target as HTMLElement)\n .nextElementSibling as HTMLElement;\n if (next) {\n next.style.display = 'flex';\n }\n }}\n src={logoSrc}\n />\n )}\n {logoFallbackText && (\n <span\n className=\"app-footer-logo-fallback\"\n style={{ display: logoSrc ? 'none' : 'flex' }}\n >\n {logoFallbackText}\n </span>\n )}\n </div>\n )}\n </div>\n </footer>\n );\n};\n","import type React from 'react';\nimport { useEffect, useState } from 'react';\nimport type { Theme } from '../../theme/ThemeProvider';\nimport './Header.css';\n\nexport interface HeaderProps {\n /** Classe CSS adicional */\n className?: string;\n /** Texto alternativo do logo */\n logoAlt?: string;\n /** URL da imagem do logo (tema escuro). Se não informado, usa logoSrc. */\n logoDarkSrc?: string;\n /** URL da imagem do logo (tema claro) */\n logoSrc?: string;\n /** Callback ao clicar na área do logo/título */\n onLogoClick?: () => void;\n /** Conteúdo da área direita (ex.: seletor de idioma, toggle tema, menu usuário) */\n rightContent?: React.ReactNode;\n /** Subtítulo abaixo do título */\n subtitle?: React.ReactNode;\n /** Tema opcional para escolher o logo correto sem depender do ThemeProvider do UI */\n theme?: Theme;\n /** Título exibido ao lado do logo (ex.: \"OFÍCIO.IA\") */\n title?: React.ReactNode;\n}\n\nconst detectTheme = (): Theme => {\n if (typeof document === 'undefined') {\n return 'light';\n }\n\n return document.documentElement.getAttribute('data-theme') === 'dark'\n ? 'dark'\n : 'light';\n};\n\nexport const Header: React.FC<HeaderProps> = ({\n logoSrc,\n logoDarkSrc,\n logoAlt = 'Logo',\n title,\n subtitle,\n theme,\n onLogoClick,\n rightContent,\n className = '',\n}) => {\n const [isScrolled, setIsScrolled] = useState(false);\n const [resolvedTheme, setResolvedTheme] = useState<Theme>(\n () => theme ?? detectTheme()\n );\n\n const logoSrcResolved =\n resolvedTheme === 'dark' && logoDarkSrc ? logoDarkSrc : logoSrc;\n\n useEffect(() => {\n const handleScroll = () => setIsScrolled(window.scrollY > 10);\n window.addEventListener('scroll', handleScroll, { passive: true });\n return () => window.removeEventListener('scroll', handleScroll);\n }, []);\n\n useEffect(() => {\n if (theme) {\n setResolvedTheme(theme);\n return;\n }\n\n const syncTheme = () => setResolvedTheme(detectTheme());\n syncTheme();\n\n if (typeof MutationObserver === 'undefined') {\n return;\n }\n\n const observer = new MutationObserver(syncTheme);\n observer.observe(document.documentElement, {\n attributes: true,\n attributeFilter: ['data-theme'],\n });\n\n return () => observer.disconnect();\n }, [theme]);\n\n const handleClick = () => onLogoClick?.();\n const handleKeyDown = (e: React.KeyboardEvent) => {\n if (e.key === 'Enter') {\n onLogoClick?.();\n }\n };\n\n return (\n <header\n className={`app-header ${isScrolled ? 'scrolled' : ''} ${className}`.trim()}\n >\n <div className=\"app-header-top-bar\" />\n <div className=\"app-header-content\">\n <div\n className=\"app-header-left\"\n onClick={onLogoClick ? handleClick : undefined}\n onKeyDown={onLogoClick ? handleKeyDown : undefined}\n role={onLogoClick ? 'button' : undefined}\n tabIndex={onLogoClick ? 0 : undefined}\n >\n {logoSrcResolved && (\n <div className=\"app-header-logo\">\n <img\n alt={logoAlt}\n onError={(e) => {\n (e.target as HTMLImageElement).style.display = 'none';\n const next = (e.target as HTMLElement)\n .nextElementSibling as HTMLElement;\n if (next) {\n next.style.display = 'block';\n }\n }}\n src={logoSrcResolved}\n />\n <svg\n className=\"logo-icon-fallback\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n viewBox=\"0 0 24 24\"\n >\n <path d=\"M12 2L2 7l10 5 10-5-10-5z\" />\n <path d=\"M2 17l10 5 10-5M2 12l10 5 10-5\" />\n </svg>\n </div>\n )}\n {(title || subtitle) && (\n <div className=\"app-header-title\">\n {title && <h1>{title}</h1>}\n {subtitle && <p>{subtitle}</p>}\n </div>\n )}\n </div>\n {rightContent && <div className=\"app-header-right\">{rightContent}</div>}\n </div>\n </header>\n );\n};\n","import type React from 'react';\nimport './Input.css';\n\nexport interface InputProps\n extends Omit<React.InputHTMLAttributes<HTMLInputElement>, 'size'> {\n error?: string;\n fullWidth?: boolean;\n helperText?: string;\n label?: string;\n leftIcon?: React.ReactNode;\n rightIcon?: React.ReactNode;\n size?: 'sm' | 'md' | 'lg';\n}\n\nexport const Input: React.FC<InputProps> = ({\n label,\n error,\n helperText,\n leftIcon,\n rightIcon,\n fullWidth = false,\n size = 'md',\n className = '',\n id,\n ...props\n}) => {\n const inputId = id || `input-${Math.random().toString(36).substring(2, 9)}`;\n const hasError = !!error;\n const baseClass = 'input';\n const sizeClass = `input--${size}`;\n const errorClass = hasError ? 'input--error' : '';\n const fullWidthClass = fullWidth ? 'input--full-width' : '';\n const hasLeftIconClass = leftIcon ? 'input--has-left-icon' : '';\n const hasRightIconClass = rightIcon ? 'input--has-right-icon' : '';\n const combinedClass =\n `${baseClass} ${sizeClass} ${errorClass} ${fullWidthClass} ${hasLeftIconClass} ${hasRightIconClass} ${className}`.trim();\n\n return (\n <div\n className={`input-wrapper ${fullWidth ? 'input-wrapper--full-width' : ''}`}\n >\n {label && (\n <label className=\"input-label\" htmlFor={inputId}>\n {label}\n </label>\n )}\n <div className=\"input-container\">\n {leftIcon && (\n <span className=\"input-icon input-icon--left\">{leftIcon}</span>\n )}\n <input\n aria-describedby={\n error\n ? `${inputId}-error`\n : helperText\n ? `${inputId}-helper`\n : undefined\n }\n aria-invalid={hasError ? true : undefined}\n className={combinedClass}\n id={inputId}\n {...props}\n />\n {rightIcon && (\n <span className=\"input-icon input-icon--right\">{rightIcon}</span>\n )}\n </div>\n {error && (\n <span className=\"input-error\" id={`${inputId}-error`} role=\"alert\">\n {error}\n </span>\n )}\n {helperText && !error && (\n <span className=\"input-helper\" id={`${inputId}-helper`}>\n {helperText}\n </span>\n )}\n </div>\n );\n};\n","import type React from 'react';\nimport { useEffect } from 'react';\nimport './Modal.css';\n\nexport interface ModalProps {\n children: React.ReactNode;\n className?: string;\n closeOnOverlayClick?: boolean;\n isOpen: boolean;\n onClose: () => void;\n showCloseButton?: boolean;\n size?: 'sm' | 'md' | 'lg' | 'xl' | 'full';\n subtitle?: string;\n title?: string | React.ReactNode;\n}\n\nexport const Modal: React.FC<ModalProps> = ({\n isOpen,\n onClose,\n title,\n subtitle,\n children,\n size = 'md',\n showCloseButton = true,\n closeOnOverlayClick = true,\n className = '',\n}) => {\n useEffect(() => {\n if (isOpen) {\n document.body.style.overflow = 'hidden';\n } else {\n document.body.style.overflow = '';\n }\n return () => {\n document.body.style.overflow = '';\n };\n }, [isOpen]);\n\n useEffect(() => {\n const handleEscape = (e: KeyboardEvent) => {\n if (e.key === 'Escape' && isOpen) {\n onClose();\n }\n };\n if (isOpen) {\n document.addEventListener('keydown', handleEscape);\n }\n return () => document.removeEventListener('keydown', handleEscape);\n }, [isOpen, onClose]);\n\n if (!isOpen) {\n return null;\n }\n\n const handleOverlayClick = (e: React.MouseEvent<HTMLDivElement>) => {\n if (closeOnOverlayClick && e.target === e.currentTarget) {\n onClose();\n }\n };\n\n const sizeClass = `modal--${size}`;\n const combinedClass = `modal ${sizeClass} ${className}`.trim();\n\n return (\n <div\n aria-labelledby={title ? 'modal-title' : undefined}\n aria-modal=\"true\"\n className=\"modal-overlay\"\n onClick={handleOverlayClick}\n role=\"dialog\"\n >\n <div className={combinedClass}>\n {(title || subtitle || showCloseButton) && (\n <div className=\"modal-header\">\n {(title || subtitle) && (\n <div className=\"modal-header-content\">\n {title && (\n <h2 className=\"modal-title\" id=\"modal-title\">\n {title}\n </h2>\n )}\n {subtitle && <p className=\"modal-subtitle\">{subtitle}</p>}\n </div>\n )}\n {showCloseButton && (\n <button\n aria-label=\"Fechar modal\"\n className=\"modal-close\"\n onClick={onClose}\n type=\"button\"\n >\n <svg\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n viewBox=\"0 0 24 24\"\n >\n <line x1=\"18\" x2=\"6\" y1=\"6\" y2=\"18\" />\n <line x1=\"6\" x2=\"18\" y1=\"6\" y2=\"18\" />\n </svg>\n </button>\n )}\n </div>\n )}\n <div className=\"modal-content\">{children}</div>\n </div>\n </div>\n );\n};\n","import type React from 'react';\nimport './Paragraph.css';\n\nexport interface ParagraphProps\n extends React.HTMLAttributes<HTMLParagraphElement> {\n align?: 'left' | 'center' | 'right' | 'justify';\n as?: 'p' | 'span' | 'div';\n children: React.ReactNode;\n muted?: boolean;\n size?: 'xs' | 'sm' | 'md' | 'lg';\n weight?: 'light' | 'normal' | 'medium';\n}\n\nexport const Paragraph: React.FC<ParagraphProps> = ({\n as = 'p',\n size = 'md',\n weight = 'normal',\n align = 'left',\n muted = false,\n children,\n className = '',\n ...props\n}) => {\n const Component = as;\n const baseClass = 'paragraph';\n const sizeClass = `paragraph--${size}`;\n const weightClass = `paragraph--${weight}`;\n const alignClass = `paragraph--align-${align}`;\n const mutedClass = muted ? 'paragraph--muted' : '';\n const combinedClass =\n `${baseClass} ${sizeClass} ${weightClass} ${alignClass} ${mutedClass} ${className}`.trim();\n\n return (\n <Component className={combinedClass} {...props}>\n {children}\n </Component>\n );\n};\n","import type React from 'react';\nimport './Subtitle.css';\n\nexport interface SubtitleProps\n extends React.HTMLAttributes<HTMLParagraphElement> {\n align?: 'left' | 'center' | 'right';\n as?: 'p' | 'span' | 'div';\n children: React.ReactNode;\n muted?: boolean;\n size?: 'xs' | 'sm' | 'md' | 'lg';\n weight?: 'normal' | 'medium' | 'semibold';\n}\n\nexport const Subtitle: React.FC<SubtitleProps> = ({\n as = 'p',\n size = 'md',\n weight = 'normal',\n align = 'left',\n muted = false,\n children,\n className = '',\n ...props\n}) => {\n const Component = as;\n const baseClass = 'subtitle';\n const sizeClass = `subtitle--${size}`;\n const weightClass = `subtitle--${weight}`;\n const alignClass = `subtitle--align-${align}`;\n const mutedClass = muted ? 'subtitle--muted' : '';\n const combinedClass =\n `${baseClass} ${sizeClass} ${weightClass} ${alignClass} ${mutedClass} ${className}`.trim();\n\n return (\n <Component className={combinedClass} {...props}>\n {children}\n </Component>\n );\n};\n","import type React from 'react';\nimport './Title.css';\n\nexport interface TitleProps extends React.HTMLAttributes<HTMLHeadingElement> {\n align?: 'left' | 'center' | 'right';\n as?: 'h1' | 'h2' | 'h3' | 'h4' | 'h5' | 'h6';\n children: React.ReactNode;\n gradient?: boolean;\n size?: 'xs' | 'sm' | 'md' | 'lg' | 'xl' | '2xl' | '3xl' | '4xl';\n weight?: 'light' | 'normal' | 'medium' | 'semibold' | 'bold' | 'extrabold';\n}\n\nexport const Title: React.FC<TitleProps> = ({\n as = 'h1',\n size = '2xl',\n weight = 'bold',\n align = 'left',\n gradient = false,\n children,\n className = '',\n ...props\n}) => {\n const Component = as;\n const baseClass = 'title';\n const sizeClass = `title--${size}`;\n const weightClass = `title--${weight}`;\n const alignClass = `title--align-${align}`;\n const gradientClass = gradient ? 'title--gradient' : '';\n const combinedClass =\n `${baseClass} ${sizeClass} ${weightClass} ${alignClass} ${gradientClass} ${className}`.trim();\n\n return (\n <Component className={combinedClass} {...props}>\n {children}\n </Component>\n );\n};\n","import {\n createContext,\n type ReactNode,\n useContext,\n useEffect,\n useState,\n} from 'react';\n\nexport type Theme = 'light' | 'dark';\n\ninterface ThemeContextType {\n theme: Theme;\n toggleTheme: () => void;\n}\n\nconst ThemeContext = createContext<ThemeContextType | undefined>(undefined);\n\nexport const useTheme = (): ThemeContextType => {\n const context = useContext(ThemeContext);\n if (!context) {\n throw new Error('useTheme must be used within a ThemeProvider');\n }\n return context;\n};\n\ninterface ThemeProviderProps {\n children: ReactNode;\n defaultTheme?: Theme;\n}\n\nexport const ThemeProvider = ({\n children,\n defaultTheme = 'light',\n}: ThemeProviderProps) => {\n const [theme, setTheme] = useState<Theme>(() => {\n if (typeof window === 'undefined') {\n return defaultTheme;\n }\n const saved = window.localStorage.getItem('theme');\n return (saved as Theme) || defaultTheme;\n });\n\n useEffect(() => {\n if (typeof window === 'undefined') {\n return;\n }\n window.localStorage.setItem('theme', theme);\n document.documentElement.setAttribute('data-theme', theme);\n }, [theme]);\n\n const toggleTheme = (): void => {\n setTheme((prev) => (prev === 'dark' ? 'light' : 'dark'));\n };\n\n return (\n <ThemeContext.Provider value={{ theme, toggleTheme }}>\n {children}\n </ThemeContext.Provider>\n );\n};\n"],"names":["Button","variant","size","fullWidth","isLoading","leftIcon","rightIcon","children","className","disabled","palette","props","variantClass","sizeClass","fullWidthClass","loadingClass","paletteClass","combinedClass","jsxs","jsx","Card","padding","hoverable","baseClass","paddingClass","Footer","poweredByText","logoSrc","logoAlt","logoFallbackText","e","next","detectTheme","Header","logoDarkSrc","title","subtitle","theme","onLogoClick","rightContent","isScrolled","setIsScrolled","useState","resolvedTheme","setResolvedTheme","logoSrcResolved","useEffect","handleScroll","syncTheme","observer","handleClick","handleKeyDown","Input","label","error","helperText","id","inputId","hasError","Modal","isOpen","onClose","showCloseButton","closeOnOverlayClick","handleEscape","handleOverlayClick","Paragraph","as","weight","align","muted","Component","weightClass","alignClass","Subtitle","Title","gradient","ThemeContext","createContext","useTheme","context","useContext","ThemeProvider","defaultTheme","setTheme","toggleTheme","prev"],"mappings":"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"}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
(function(c,e){typeof exports=="object"&&typeof module<"u"?e(exports,require("react/jsx-runtime"),require("react")):typeof define=="function"&&define.amd?define(["exports","react/jsx-runtime","react"],e):(c=typeof globalThis<"u"?globalThis:c||self,e(c.OficiosUI={},c.jsxRuntime,c.React))})(this,(function(c,e,$){"use strict";const w=({variant:t="primary",size:a="md",fullWidth:n=!1,isLoading:s=!1,leftIcon:r,rightIcon:l,children:o,className:h="",disabled:p,palette:m,...d})=>{const i=`btn--${t}`,b=`btn--${a}`,v=n?"btn--full-width":"",g=s?"btn--loading":"",u=m&&t==="primary"?`btn--palette-${m}`:"",C=`btn ${i} ${b} ${v} ${g} ${u} ${h}`.trim();return e.jsxs("button",{className:C,disabled:p||s,...d,children:[s&&e.jsx("span",{"aria-hidden":"true",className:"btn__spinner",children:e.jsxs("svg",{fill:"none",stroke:"currentColor",strokeWidth:"2",viewBox:"0 0 24 24",children:[e.jsx("circle",{cx:"12",cy:"12",r:"10",strokeOpacity:"0.25"}),e.jsx("path",{d:"M12 2 A10 10 0 0 1 22 12",strokeLinecap:"round"})]})}),!s&&r&&e.jsx("span",{className:"btn__icon btn__icon--left",children:r}),e.jsx("span",{className:"btn__content",children:o}),!s&&l&&e.jsx("span",{className:"btn__icon btn__icon--right",children:l})]})},E=({variant:t="default",padding:a="md",hoverable:n=!1,children:s,className:r="",...l})=>{const o="card",h=`card--${t}`,p=`card--padding-${a}`,d=`${o} ${h} ${p} ${n?"card--hoverable":""} ${r}`.trim();return e.jsx("div",{className:d,...l,children:s})},k=({poweredByText:t="Powered by",logoSrc:a,logoAlt:n="Logo",logoFallbackText:s,className:r=""})=>e.jsx("footer",{className:`app-footer ${r}`.trim(),children:e.jsxs("div",{className:"app-footer-powered",children:[t&&e.jsx("span",{className:"app-footer-powered-text",children:t}),(a||s)&&e.jsxs("div",{className:"app-footer-logo-wrap",children:[a&&e.jsx("img",{alt:n,className:"app-footer-logo",onError:l=>{l.target.style.display="none";const o=l.target.nextElementSibling;o&&(o.style.display="flex")},src:a}),s&&e.jsx("span",{className:"app-footer-logo-fallback",style:{display:a?"none":"flex"},children:s})]})]})}),y=()=>typeof document>"u"?"light":document.documentElement.getAttribute("data-theme")==="dark"?"dark":"light",T=({logoSrc:t,logoDarkSrc:a,logoAlt:n="Logo",title:s,subtitle:r,theme:l,onLogoClick:o,rightContent:h,className:p=""})=>{const[m,d]=$.useState(!1),[f,i]=$.useState(()=>l??y()),b=f==="dark"&&a?a:t;$.useEffect(()=>{const u=()=>d(window.scrollY>10);return window.addEventListener("scroll",u,{passive:!0}),()=>window.removeEventListener("scroll",u)},[]),$.useEffect(()=>{if(l){i(l);return}const u=()=>i(y());if(u(),typeof MutationObserver>"u")return;const C=new MutationObserver(u);return C.observe(document.documentElement,{attributes:!0,attributeFilter:["data-theme"]}),()=>C.disconnect()},[l]);const v=()=>o?.(),g=u=>{u.key==="Enter"&&o?.()};return e.jsxs("header",{className:`app-header ${m?"scrolled":""} ${p}`.trim(),children:[e.jsx("div",{className:"app-header-top-bar"}),e.jsxs("div",{className:"app-header-content",children:[e.jsxs("div",{className:"app-header-left",onClick:o?v:void 0,onKeyDown:o?g:void 0,role:o?"button":void 0,tabIndex:o?0:void 0,children:[b&&e.jsxs("div",{className:"app-header-logo",children:[e.jsx("img",{alt:n,onError:u=>{u.target.style.display="none";const C=u.target.nextElementSibling;C&&(C.style.display="block")},src:b}),e.jsxs("svg",{className:"logo-icon-fallback",fill:"none",stroke:"currentColor",strokeWidth:"2",viewBox:"0 0 24 24",children:[e.jsx("path",{d:"M12 2L2 7l10 5 10-5-10-5z"}),e.jsx("path",{d:"M2 17l10 5 10-5M2 12l10 5 10-5"})]})]}),(s||r)&&e.jsxs("div",{className:"app-header-title",children:[s&&e.jsx("h1",{children:s}),r&&e.jsx("p",{children:r})]})]}),h&&e.jsx("div",{className:"app-header-right",children:h})]})]})},x=({label:t,error:a,helperText:n,leftIcon:s,rightIcon:r,fullWidth:l=!1,size:o="md",className:h="",id:p,...m})=>{const d=p||`input-${Math.random().toString(36).substring(2,9)}`,f=!!a,i="input",b=`input--${o}`,I=`${i} ${b} ${f?"input--error":""} ${l?"input--full-width":""} ${s?"input--has-left-icon":""} ${r?"input--has-right-icon":""} ${h}`.trim();return e.jsxs("div",{className:`input-wrapper ${l?"input-wrapper--full-width":""}`,children:[t&&e.jsx("label",{className:"input-label",htmlFor:d,children:t}),e.jsxs("div",{className:"input-container",children:[s&&e.jsx("span",{className:"input-icon input-icon--left",children:s}),e.jsx("input",{"aria-describedby":a?`${d}-error`:n?`${d}-helper`:void 0,"aria-invalid":f?!0:void 0,className:I,id:d,...m}),r&&e.jsx("span",{className:"input-icon input-icon--right",children:r})]}),a&&e.jsx("span",{className:"input-error",id:`${d}-error`,role:"alert",children:a}),n&&!a&&e.jsx("span",{className:"input-helper",id:`${d}-helper`,children:n})]})},S=({isOpen:t,onClose:a,title:n,subtitle:s,children:r,size:l="md",showCloseButton:o=!0,closeOnOverlayClick:h=!0,className:p=""})=>{if($.useEffect(()=>(t?document.body.style.overflow="hidden":document.body.style.overflow="",()=>{document.body.style.overflow=""}),[t]),$.useEffect(()=>{const i=b=>{b.key==="Escape"&&t&&a()};return t&&document.addEventListener("keydown",i),()=>document.removeEventListener("keydown",i)},[t,a]),!t)return null;const m=i=>{h&&i.target===i.currentTarget&&a()},f=`modal ${`modal--${l}`} ${p}`.trim();return e.jsx("div",{"aria-labelledby":n?"modal-title":void 0,"aria-modal":"true",className:"modal-overlay",onClick:m,role:"dialog",children:e.jsxs("div",{className:f,children:[(n||s||o)&&e.jsxs("div",{className:"modal-header",children:[(n||s)&&e.jsxs("div",{className:"modal-header-content",children:[n&&e.jsx("h2",{className:"modal-title",id:"modal-title",children:n}),s&&e.jsx("p",{className:"modal-subtitle",children:s})]}),o&&e.jsx("button",{"aria-label":"Fechar modal",className:"modal-close",onClick:a,type:"button",children:e.jsxs("svg",{fill:"none",stroke:"currentColor",strokeWidth:"2",viewBox:"0 0 24 24",children:[e.jsx("line",{x1:"18",x2:"6",y1:"6",y2:"18"}),e.jsx("line",{x1:"6",x2:"18",y1:"6",y2:"18"})]})})]}),e.jsx("div",{className:"modal-content",children:r})]})})},_=({as:t="p",size:a="md",weight:n="normal",align:s="left",muted:r=!1,children:l,className:o="",...h})=>{const p=t,m="paragraph",d=`paragraph--${a}`,f=`paragraph--${n}`,i=`paragraph--align-${s}`,v=`${m} ${d} ${f} ${i} ${r?"paragraph--muted":""} ${o}`.trim();return e.jsx(p,{className:v,...h,children:l})},M=({as:t="p",size:a="md",weight:n="normal",align:s="left",muted:r=!1,children:l,className:o="",...h})=>{const p=t,m="subtitle",d=`subtitle--${a}`,f=`subtitle--${n}`,i=`subtitle--align-${s}`,v=`${m} ${d} ${f} ${i} ${r?"subtitle--muted":""} ${o}`.trim();return e.jsx(p,{className:v,...h,children:l})},z=({as:t="h1",size:a="2xl",weight:n="bold",align:s="left",gradient:r=!1,children:l,className:o="",...h})=>{const p=t,m="title",d=`title--${a}`,f=`title--${n}`,i=`title--align-${s}`,v=`${m} ${d} ${f} ${i} ${r?"title--gradient":""} ${o}`.trim();return e.jsx(p,{className:v,...h,children:l})},N=$.createContext(void 0),P=()=>{const t=$.useContext(N);if(!t)throw new Error("useTheme must be used within a ThemeProvider");return t},j=({children:t,defaultTheme:a="light"})=>{const[n,s]=$.useState(()=>typeof window>"u"?a:window.localStorage.getItem("theme")||a);$.useEffect(()=>{typeof window>"u"||(window.localStorage.setItem("theme",n),document.documentElement.setAttribute("data-theme",n))},[n]);const r=()=>{s(l=>l==="dark"?"light":"dark")};return e.jsx(N.Provider,{value:{theme:n,toggleTheme:r},children:t})};c.Button=w,c.Card=E,c.Footer=k,c.Header=T,c.Input=x,c.Modal=S,c.Paragraph=_,c.Subtitle=M,c.ThemeProvider=j,c.Title=z,c.useTheme=P,Object.defineProperty(c,Symbol.toStringTag,{value:"Module"})}));
|
|
2
|
+
//# sourceMappingURL=oficios-ui.umd.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"oficios-ui.umd.cjs","sources":["../src/components/Button/Button.tsx","../src/components/Card/Card.tsx","../src/components/Footer/Footer.tsx","../src/components/Header/Header.tsx","../src/components/Input/Input.tsx","../src/components/Modal/Modal.tsx","../src/components/Paragraph/Paragraph.tsx","../src/components/Subtitle/Subtitle.tsx","../src/components/Title/Title.tsx","../src/theme/ThemeProvider.tsx"],"sourcesContent":["import type React from 'react';\nimport './Button.css';\n\n/** Paletas do guia de marca (só afeta variant primary). Use para escolher o modelo de cor do botão. */\nexport type ButtonPalette =\n | 'verde-vibrante'\n | 'verde-profundo'\n | 'grafite-azulado'\n | 'azul-acinzentado'\n | 'cinza-medio'\n | 'cinza-escuro'\n | 'off-white';\n\nexport interface ButtonProps\n extends React.ButtonHTMLAttributes<HTMLButtonElement> {\n children: React.ReactNode;\n fullWidth?: boolean;\n isLoading?: boolean;\n leftIcon?: React.ReactNode;\n /** Paleta de cor do guia de marca (aplica-se ao primary). Ignorado em outros variants. */\n palette?: ButtonPalette;\n rightIcon?: React.ReactNode;\n size?: 'xs' | 'sm' | 'md' | 'lg' | 'xl';\n variant?:\n | 'primary'\n | 'secondary'\n | 'success'\n | 'error'\n | 'warning'\n | 'info'\n | 'neutral'\n | 'ghost';\n}\n\nexport const Button: React.FC<ButtonProps> = ({\n variant = 'primary',\n size = 'md',\n fullWidth = false,\n isLoading = false,\n leftIcon,\n rightIcon,\n children,\n className = '',\n disabled,\n palette,\n ...props\n}) => {\n const baseClass = 'btn';\n const variantClass = `btn--${variant}`;\n const sizeClass = `btn--${size}`;\n const fullWidthClass = fullWidth ? 'btn--full-width' : '';\n const loadingClass = isLoading ? 'btn--loading' : '';\n const paletteClass =\n palette && variant === 'primary' ? `btn--palette-${palette}` : '';\n const combinedClass =\n `${baseClass} ${variantClass} ${sizeClass} ${fullWidthClass} ${loadingClass} ${paletteClass} ${className}`.trim();\n\n return (\n <button\n className={combinedClass}\n disabled={disabled || isLoading}\n {...props}\n >\n {isLoading && (\n <span aria-hidden=\"true\" className=\"btn__spinner\">\n <svg\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n viewBox=\"0 0 24 24\"\n >\n <circle cx=\"12\" cy=\"12\" r=\"10\" strokeOpacity=\"0.25\" />\n <path d=\"M12 2 A10 10 0 0 1 22 12\" strokeLinecap=\"round\" />\n </svg>\n </span>\n )}\n {!isLoading && leftIcon && (\n <span className=\"btn__icon btn__icon--left\">{leftIcon}</span>\n )}\n <span className=\"btn__content\">{children}</span>\n {!isLoading && rightIcon && (\n <span className=\"btn__icon btn__icon--right\">{rightIcon}</span>\n )}\n </button>\n );\n};\n","import type React from 'react';\nimport './Card.css';\n\nexport interface CardProps extends React.HTMLAttributes<HTMLDivElement> {\n children: React.ReactNode;\n hoverable?: boolean;\n padding?: 'none' | 'sm' | 'md' | 'lg' | 'xl';\n variant?: 'default' | 'elevated' | 'outlined' | 'flat';\n}\n\nexport const Card: React.FC<CardProps> = ({\n variant = 'default',\n padding = 'md',\n hoverable = false,\n children,\n className = '',\n ...props\n}) => {\n const baseClass = 'card';\n const variantClass = `card--${variant}`;\n const paddingClass = `card--padding-${padding}`;\n const hoverableClass = hoverable ? 'card--hoverable' : '';\n const combinedClass =\n `${baseClass} ${variantClass} ${paddingClass} ${hoverableClass} ${className}`.trim();\n\n return (\n <div className={combinedClass} {...props}>\n {children}\n </div>\n );\n};\n","import type React from 'react';\nimport './Footer.css';\n\nexport interface FooterProps {\n /** Classe CSS adicional */\n className?: string;\n /** Texto alternativo do logo */\n logoAlt?: string;\n /** Texto exibido se a imagem do logo falhar (ex.: \"SBK\") */\n logoFallbackText?: string;\n /** URL da imagem do logo */\n logoSrc?: string;\n /** Texto antes do logo (ex.: \"Powered by\") */\n poweredByText?: string;\n}\n\nexport const Footer: React.FC<FooterProps> = ({\n poweredByText = 'Powered by',\n logoSrc,\n logoAlt = 'Logo',\n logoFallbackText,\n className = '',\n}) => {\n return (\n <footer className={`app-footer ${className}`.trim()}>\n <div className=\"app-footer-powered\">\n {poweredByText && (\n <span className=\"app-footer-powered-text\">{poweredByText}</span>\n )}\n {(logoSrc || logoFallbackText) && (\n <div className=\"app-footer-logo-wrap\">\n {logoSrc && (\n <img\n alt={logoAlt}\n className=\"app-footer-logo\"\n onError={(e) => {\n (e.target as HTMLImageElement).style.display = 'none';\n const next = (e.target as HTMLElement)\n .nextElementSibling as HTMLElement;\n if (next) {\n next.style.display = 'flex';\n }\n }}\n src={logoSrc}\n />\n )}\n {logoFallbackText && (\n <span\n className=\"app-footer-logo-fallback\"\n style={{ display: logoSrc ? 'none' : 'flex' }}\n >\n {logoFallbackText}\n </span>\n )}\n </div>\n )}\n </div>\n </footer>\n );\n};\n","import type React from 'react';\nimport { useEffect, useState } from 'react';\nimport type { Theme } from '../../theme/ThemeProvider';\nimport './Header.css';\n\nexport interface HeaderProps {\n /** Classe CSS adicional */\n className?: string;\n /** Texto alternativo do logo */\n logoAlt?: string;\n /** URL da imagem do logo (tema escuro). Se não informado, usa logoSrc. */\n logoDarkSrc?: string;\n /** URL da imagem do logo (tema claro) */\n logoSrc?: string;\n /** Callback ao clicar na área do logo/título */\n onLogoClick?: () => void;\n /** Conteúdo da área direita (ex.: seletor de idioma, toggle tema, menu usuário) */\n rightContent?: React.ReactNode;\n /** Subtítulo abaixo do título */\n subtitle?: React.ReactNode;\n /** Tema opcional para escolher o logo correto sem depender do ThemeProvider do UI */\n theme?: Theme;\n /** Título exibido ao lado do logo (ex.: \"OFÍCIO.IA\") */\n title?: React.ReactNode;\n}\n\nconst detectTheme = (): Theme => {\n if (typeof document === 'undefined') {\n return 'light';\n }\n\n return document.documentElement.getAttribute('data-theme') === 'dark'\n ? 'dark'\n : 'light';\n};\n\nexport const Header: React.FC<HeaderProps> = ({\n logoSrc,\n logoDarkSrc,\n logoAlt = 'Logo',\n title,\n subtitle,\n theme,\n onLogoClick,\n rightContent,\n className = '',\n}) => {\n const [isScrolled, setIsScrolled] = useState(false);\n const [resolvedTheme, setResolvedTheme] = useState<Theme>(\n () => theme ?? detectTheme()\n );\n\n const logoSrcResolved =\n resolvedTheme === 'dark' && logoDarkSrc ? logoDarkSrc : logoSrc;\n\n useEffect(() => {\n const handleScroll = () => setIsScrolled(window.scrollY > 10);\n window.addEventListener('scroll', handleScroll, { passive: true });\n return () => window.removeEventListener('scroll', handleScroll);\n }, []);\n\n useEffect(() => {\n if (theme) {\n setResolvedTheme(theme);\n return;\n }\n\n const syncTheme = () => setResolvedTheme(detectTheme());\n syncTheme();\n\n if (typeof MutationObserver === 'undefined') {\n return;\n }\n\n const observer = new MutationObserver(syncTheme);\n observer.observe(document.documentElement, {\n attributes: true,\n attributeFilter: ['data-theme'],\n });\n\n return () => observer.disconnect();\n }, [theme]);\n\n const handleClick = () => onLogoClick?.();\n const handleKeyDown = (e: React.KeyboardEvent) => {\n if (e.key === 'Enter') {\n onLogoClick?.();\n }\n };\n\n return (\n <header\n className={`app-header ${isScrolled ? 'scrolled' : ''} ${className}`.trim()}\n >\n <div className=\"app-header-top-bar\" />\n <div className=\"app-header-content\">\n <div\n className=\"app-header-left\"\n onClick={onLogoClick ? handleClick : undefined}\n onKeyDown={onLogoClick ? handleKeyDown : undefined}\n role={onLogoClick ? 'button' : undefined}\n tabIndex={onLogoClick ? 0 : undefined}\n >\n {logoSrcResolved && (\n <div className=\"app-header-logo\">\n <img\n alt={logoAlt}\n onError={(e) => {\n (e.target as HTMLImageElement).style.display = 'none';\n const next = (e.target as HTMLElement)\n .nextElementSibling as HTMLElement;\n if (next) {\n next.style.display = 'block';\n }\n }}\n src={logoSrcResolved}\n />\n <svg\n className=\"logo-icon-fallback\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n viewBox=\"0 0 24 24\"\n >\n <path d=\"M12 2L2 7l10 5 10-5-10-5z\" />\n <path d=\"M2 17l10 5 10-5M2 12l10 5 10-5\" />\n </svg>\n </div>\n )}\n {(title || subtitle) && (\n <div className=\"app-header-title\">\n {title && <h1>{title}</h1>}\n {subtitle && <p>{subtitle}</p>}\n </div>\n )}\n </div>\n {rightContent && <div className=\"app-header-right\">{rightContent}</div>}\n </div>\n </header>\n );\n};\n","import type React from 'react';\nimport './Input.css';\n\nexport interface InputProps\n extends Omit<React.InputHTMLAttributes<HTMLInputElement>, 'size'> {\n error?: string;\n fullWidth?: boolean;\n helperText?: string;\n label?: string;\n leftIcon?: React.ReactNode;\n rightIcon?: React.ReactNode;\n size?: 'sm' | 'md' | 'lg';\n}\n\nexport const Input: React.FC<InputProps> = ({\n label,\n error,\n helperText,\n leftIcon,\n rightIcon,\n fullWidth = false,\n size = 'md',\n className = '',\n id,\n ...props\n}) => {\n const inputId = id || `input-${Math.random().toString(36).substring(2, 9)}`;\n const hasError = !!error;\n const baseClass = 'input';\n const sizeClass = `input--${size}`;\n const errorClass = hasError ? 'input--error' : '';\n const fullWidthClass = fullWidth ? 'input--full-width' : '';\n const hasLeftIconClass = leftIcon ? 'input--has-left-icon' : '';\n const hasRightIconClass = rightIcon ? 'input--has-right-icon' : '';\n const combinedClass =\n `${baseClass} ${sizeClass} ${errorClass} ${fullWidthClass} ${hasLeftIconClass} ${hasRightIconClass} ${className}`.trim();\n\n return (\n <div\n className={`input-wrapper ${fullWidth ? 'input-wrapper--full-width' : ''}`}\n >\n {label && (\n <label className=\"input-label\" htmlFor={inputId}>\n {label}\n </label>\n )}\n <div className=\"input-container\">\n {leftIcon && (\n <span className=\"input-icon input-icon--left\">{leftIcon}</span>\n )}\n <input\n aria-describedby={\n error\n ? `${inputId}-error`\n : helperText\n ? `${inputId}-helper`\n : undefined\n }\n aria-invalid={hasError ? true : undefined}\n className={combinedClass}\n id={inputId}\n {...props}\n />\n {rightIcon && (\n <span className=\"input-icon input-icon--right\">{rightIcon}</span>\n )}\n </div>\n {error && (\n <span className=\"input-error\" id={`${inputId}-error`} role=\"alert\">\n {error}\n </span>\n )}\n {helperText && !error && (\n <span className=\"input-helper\" id={`${inputId}-helper`}>\n {helperText}\n </span>\n )}\n </div>\n );\n};\n","import type React from 'react';\nimport { useEffect } from 'react';\nimport './Modal.css';\n\nexport interface ModalProps {\n children: React.ReactNode;\n className?: string;\n closeOnOverlayClick?: boolean;\n isOpen: boolean;\n onClose: () => void;\n showCloseButton?: boolean;\n size?: 'sm' | 'md' | 'lg' | 'xl' | 'full';\n subtitle?: string;\n title?: string | React.ReactNode;\n}\n\nexport const Modal: React.FC<ModalProps> = ({\n isOpen,\n onClose,\n title,\n subtitle,\n children,\n size = 'md',\n showCloseButton = true,\n closeOnOverlayClick = true,\n className = '',\n}) => {\n useEffect(() => {\n if (isOpen) {\n document.body.style.overflow = 'hidden';\n } else {\n document.body.style.overflow = '';\n }\n return () => {\n document.body.style.overflow = '';\n };\n }, [isOpen]);\n\n useEffect(() => {\n const handleEscape = (e: KeyboardEvent) => {\n if (e.key === 'Escape' && isOpen) {\n onClose();\n }\n };\n if (isOpen) {\n document.addEventListener('keydown', handleEscape);\n }\n return () => document.removeEventListener('keydown', handleEscape);\n }, [isOpen, onClose]);\n\n if (!isOpen) {\n return null;\n }\n\n const handleOverlayClick = (e: React.MouseEvent<HTMLDivElement>) => {\n if (closeOnOverlayClick && e.target === e.currentTarget) {\n onClose();\n }\n };\n\n const sizeClass = `modal--${size}`;\n const combinedClass = `modal ${sizeClass} ${className}`.trim();\n\n return (\n <div\n aria-labelledby={title ? 'modal-title' : undefined}\n aria-modal=\"true\"\n className=\"modal-overlay\"\n onClick={handleOverlayClick}\n role=\"dialog\"\n >\n <div className={combinedClass}>\n {(title || subtitle || showCloseButton) && (\n <div className=\"modal-header\">\n {(title || subtitle) && (\n <div className=\"modal-header-content\">\n {title && (\n <h2 className=\"modal-title\" id=\"modal-title\">\n {title}\n </h2>\n )}\n {subtitle && <p className=\"modal-subtitle\">{subtitle}</p>}\n </div>\n )}\n {showCloseButton && (\n <button\n aria-label=\"Fechar modal\"\n className=\"modal-close\"\n onClick={onClose}\n type=\"button\"\n >\n <svg\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n viewBox=\"0 0 24 24\"\n >\n <line x1=\"18\" x2=\"6\" y1=\"6\" y2=\"18\" />\n <line x1=\"6\" x2=\"18\" y1=\"6\" y2=\"18\" />\n </svg>\n </button>\n )}\n </div>\n )}\n <div className=\"modal-content\">{children}</div>\n </div>\n </div>\n );\n};\n","import type React from 'react';\nimport './Paragraph.css';\n\nexport interface ParagraphProps\n extends React.HTMLAttributes<HTMLParagraphElement> {\n align?: 'left' | 'center' | 'right' | 'justify';\n as?: 'p' | 'span' | 'div';\n children: React.ReactNode;\n muted?: boolean;\n size?: 'xs' | 'sm' | 'md' | 'lg';\n weight?: 'light' | 'normal' | 'medium';\n}\n\nexport const Paragraph: React.FC<ParagraphProps> = ({\n as = 'p',\n size = 'md',\n weight = 'normal',\n align = 'left',\n muted = false,\n children,\n className = '',\n ...props\n}) => {\n const Component = as;\n const baseClass = 'paragraph';\n const sizeClass = `paragraph--${size}`;\n const weightClass = `paragraph--${weight}`;\n const alignClass = `paragraph--align-${align}`;\n const mutedClass = muted ? 'paragraph--muted' : '';\n const combinedClass =\n `${baseClass} ${sizeClass} ${weightClass} ${alignClass} ${mutedClass} ${className}`.trim();\n\n return (\n <Component className={combinedClass} {...props}>\n {children}\n </Component>\n );\n};\n","import type React from 'react';\nimport './Subtitle.css';\n\nexport interface SubtitleProps\n extends React.HTMLAttributes<HTMLParagraphElement> {\n align?: 'left' | 'center' | 'right';\n as?: 'p' | 'span' | 'div';\n children: React.ReactNode;\n muted?: boolean;\n size?: 'xs' | 'sm' | 'md' | 'lg';\n weight?: 'normal' | 'medium' | 'semibold';\n}\n\nexport const Subtitle: React.FC<SubtitleProps> = ({\n as = 'p',\n size = 'md',\n weight = 'normal',\n align = 'left',\n muted = false,\n children,\n className = '',\n ...props\n}) => {\n const Component = as;\n const baseClass = 'subtitle';\n const sizeClass = `subtitle--${size}`;\n const weightClass = `subtitle--${weight}`;\n const alignClass = `subtitle--align-${align}`;\n const mutedClass = muted ? 'subtitle--muted' : '';\n const combinedClass =\n `${baseClass} ${sizeClass} ${weightClass} ${alignClass} ${mutedClass} ${className}`.trim();\n\n return (\n <Component className={combinedClass} {...props}>\n {children}\n </Component>\n );\n};\n","import type React from 'react';\nimport './Title.css';\n\nexport interface TitleProps extends React.HTMLAttributes<HTMLHeadingElement> {\n align?: 'left' | 'center' | 'right';\n as?: 'h1' | 'h2' | 'h3' | 'h4' | 'h5' | 'h6';\n children: React.ReactNode;\n gradient?: boolean;\n size?: 'xs' | 'sm' | 'md' | 'lg' | 'xl' | '2xl' | '3xl' | '4xl';\n weight?: 'light' | 'normal' | 'medium' | 'semibold' | 'bold' | 'extrabold';\n}\n\nexport const Title: React.FC<TitleProps> = ({\n as = 'h1',\n size = '2xl',\n weight = 'bold',\n align = 'left',\n gradient = false,\n children,\n className = '',\n ...props\n}) => {\n const Component = as;\n const baseClass = 'title';\n const sizeClass = `title--${size}`;\n const weightClass = `title--${weight}`;\n const alignClass = `title--align-${align}`;\n const gradientClass = gradient ? 'title--gradient' : '';\n const combinedClass =\n `${baseClass} ${sizeClass} ${weightClass} ${alignClass} ${gradientClass} ${className}`.trim();\n\n return (\n <Component className={combinedClass} {...props}>\n {children}\n </Component>\n );\n};\n","import {\n createContext,\n type ReactNode,\n useContext,\n useEffect,\n useState,\n} from 'react';\n\nexport type Theme = 'light' | 'dark';\n\ninterface ThemeContextType {\n theme: Theme;\n toggleTheme: () => void;\n}\n\nconst ThemeContext = createContext<ThemeContextType | undefined>(undefined);\n\nexport const useTheme = (): ThemeContextType => {\n const context = useContext(ThemeContext);\n if (!context) {\n throw new Error('useTheme must be used within a ThemeProvider');\n }\n return context;\n};\n\ninterface ThemeProviderProps {\n children: ReactNode;\n defaultTheme?: Theme;\n}\n\nexport const ThemeProvider = ({\n children,\n defaultTheme = 'light',\n}: ThemeProviderProps) => {\n const [theme, setTheme] = useState<Theme>(() => {\n if (typeof window === 'undefined') {\n return defaultTheme;\n }\n const saved = window.localStorage.getItem('theme');\n return (saved as Theme) || defaultTheme;\n });\n\n useEffect(() => {\n if (typeof window === 'undefined') {\n return;\n }\n window.localStorage.setItem('theme', theme);\n document.documentElement.setAttribute('data-theme', theme);\n }, [theme]);\n\n const toggleTheme = (): void => {\n setTheme((prev) => (prev === 'dark' ? 'light' : 'dark'));\n };\n\n return (\n <ThemeContext.Provider value={{ theme, toggleTheme }}>\n {children}\n </ThemeContext.Provider>\n );\n};\n"],"names":["Button","variant","size","fullWidth","isLoading","leftIcon","rightIcon","children","className","disabled","palette","props","variantClass","sizeClass","fullWidthClass","loadingClass","paletteClass","combinedClass","jsxs","jsx","Card","padding","hoverable","baseClass","paddingClass","Footer","poweredByText","logoSrc","logoAlt","logoFallbackText","e","next","detectTheme","Header","logoDarkSrc","title","subtitle","theme","onLogoClick","rightContent","isScrolled","setIsScrolled","useState","resolvedTheme","setResolvedTheme","logoSrcResolved","useEffect","handleScroll","syncTheme","observer","handleClick","handleKeyDown","Input","label","error","helperText","id","inputId","hasError","Modal","isOpen","onClose","showCloseButton","closeOnOverlayClick","handleEscape","handleOverlayClick","Paragraph","as","weight","align","muted","Component","weightClass","alignClass","Subtitle","Title","gradient","ThemeContext","createContext","useTheme","context","useContext","ThemeProvider","defaultTheme","setTheme","toggleTheme","prev"],"mappings":"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"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { type ReactNode } from 'react';
|
|
2
|
+
export type Theme = 'light' | 'dark';
|
|
3
|
+
interface ThemeContextType {
|
|
4
|
+
theme: Theme;
|
|
5
|
+
toggleTheme: () => void;
|
|
6
|
+
}
|
|
7
|
+
export declare const useTheme: () => ThemeContextType;
|
|
8
|
+
interface ThemeProviderProps {
|
|
9
|
+
children: ReactNode;
|
|
10
|
+
defaultTheme?: Theme;
|
|
11
|
+
}
|
|
12
|
+
export declare const ThemeProvider: ({ children, defaultTheme, }: ThemeProviderProps) => import("react/jsx-runtime").JSX.Element;
|
|
13
|
+
export {};
|
package/dist/theme.css
ADDED
|
@@ -0,0 +1,295 @@
|
|
|
1
|
+
/* ============================================================
|
|
2
|
+
DESIGN SYSTEM - VARIÁVEIS GLOBAIS DE TEMA (@oficios/ui)
|
|
3
|
+
Guia de marca: cores e tipografia SBK
|
|
4
|
+
============================================================ */
|
|
5
|
+
|
|
6
|
+
@import url("https://fonts.googleapis.com/css2?family=Plus+Jakarta+Sans:ital,wght@0,300;0,400;0,500;0,600;0,700;0,800;1,400;1,500&display=swap");
|
|
7
|
+
|
|
8
|
+
/* ============================================================
|
|
9
|
+
GUIA DE MARCA - CORES (paleta fixa para referência e paletas)
|
|
10
|
+
============================================================ */
|
|
11
|
+
:root {
|
|
12
|
+
/* Cores principais do guia */
|
|
13
|
+
--brand-verde-vibrante: #01b2aa;
|
|
14
|
+
--brand-verde-profundo: #1f3a3a;
|
|
15
|
+
--brand-grafite-azulado: #0f2f3a;
|
|
16
|
+
--brand-azul-acinzentado: #5f7b8d;
|
|
17
|
+
--brand-cinza-medio: #4b4b4b;
|
|
18
|
+
--brand-cinza-escuro: #24262d;
|
|
19
|
+
--brand-off-white: #ffffff;
|
|
20
|
+
--brand-neutral-75: rgba(255, 255, 255, 0.75);
|
|
21
|
+
--brand-branco: #ffffff;
|
|
22
|
+
|
|
23
|
+
/* DNA da marca - O Criador */
|
|
24
|
+
--brand-preto: #000000;
|
|
25
|
+
--brand-cinza: #989495;
|
|
26
|
+
--brand-azul-lavanda: #777dac;
|
|
27
|
+
--brand-azul-intenso: #132c3b;
|
|
28
|
+
--brand-cinza-azulado: #b4c2c7;
|
|
29
|
+
--brand-verde-lima: #cffe40;
|
|
30
|
+
--brand-off-white-criador: #e4e4e4;
|
|
31
|
+
--brand-azul-escuro: #071a5c;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/* ============================================================
|
|
35
|
+
GUIA DE MARCA - TIPOGRAFIA (O Herói / O Criador)
|
|
36
|
+
Jakarta = headlines fortes; alta legibilidade; estrutura
|
|
37
|
+
============================================================ */
|
|
38
|
+
:root {
|
|
39
|
+
--font-primary:
|
|
40
|
+
"Plus Jakarta Sans", -apple-system, BlinkMacSystemFont, "Segoe UI",
|
|
41
|
+
sans-serif;
|
|
42
|
+
--font-secondary: "Plus Jakarta Sans", var(--font-primary);
|
|
43
|
+
--font-heading: var(--font-primary);
|
|
44
|
+
--font-body: var(--font-primary);
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
html {
|
|
48
|
+
font-family: var(--font-body);
|
|
49
|
+
font-size: 1rem;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
:root {
|
|
53
|
+
--primary-color: var(--brand-verde-vibrante);
|
|
54
|
+
--primary-color-dark: var(--brand-verde-profundo);
|
|
55
|
+
--primary-color-light: color-mix(
|
|
56
|
+
in srgb,
|
|
57
|
+
var(--brand-verde-vibrante) 84%,
|
|
58
|
+
white
|
|
59
|
+
);
|
|
60
|
+
--primary-color-hover: var(--brand-verde-profundo);
|
|
61
|
+
--md-primary: var(--brand-verde-vibrante);
|
|
62
|
+
--md-on-primary: #ffffff;
|
|
63
|
+
--md-primary-container: color-mix(
|
|
64
|
+
in srgb,
|
|
65
|
+
var(--brand-verde-vibrante) 18%,
|
|
66
|
+
white
|
|
67
|
+
);
|
|
68
|
+
--md-on-primary-container: var(--brand-grafite-azulado);
|
|
69
|
+
--secondary-color: var(--brand-grafite-azulado);
|
|
70
|
+
/* Tokens semânticos para integração com Tailwind */
|
|
71
|
+
--color-primary: var(--primary-color);
|
|
72
|
+
--color-on-primary: var(--md-on-primary);
|
|
73
|
+
--color-secondary: var(--secondary-color);
|
|
74
|
+
--color-on-secondary: var(--md-on-secondary);
|
|
75
|
+
--color-surface: var(--md-surface);
|
|
76
|
+
--color-on-surface: var(--md-on-surface);
|
|
77
|
+
--color-contrast: var(--brand-verde-lima);
|
|
78
|
+
|
|
79
|
+
--md-secondary: var(--brand-grafite-azulado);
|
|
80
|
+
--md-on-secondary: #ffffff;
|
|
81
|
+
--md-outline: var(--brand-azul-acinzentado);
|
|
82
|
+
--md-outline-variant: color-mix(
|
|
83
|
+
in srgb,
|
|
84
|
+
var(--brand-azul-acinzentado) 35%,
|
|
85
|
+
white
|
|
86
|
+
);
|
|
87
|
+
--success-color: #22c55e;
|
|
88
|
+
--success-color-light: #4ade80;
|
|
89
|
+
--error-color: #ef4444;
|
|
90
|
+
--error-color-light: #f87171;
|
|
91
|
+
--md-error: #ba1a1a;
|
|
92
|
+
--md-on-error: #ffffff;
|
|
93
|
+
--warning-color: #f59e0b;
|
|
94
|
+
--warning-color-light: #fbbe24;
|
|
95
|
+
--info-color: #3b82f6;
|
|
96
|
+
--info-color-light: #60a5fa;
|
|
97
|
+
--neutral-color: var(--brand-cinza-medio);
|
|
98
|
+
--neutral-color-light: var(--brand-azul-acinzentado);
|
|
99
|
+
--secondary-color-light: var(--brand-azul-acinzentado);
|
|
100
|
+
--bg-hover: color-mix(in srgb, var(--brand-grafite-azulado) 8%, white);
|
|
101
|
+
--bg-active: color-mix(in srgb, var(--brand-grafite-azulado) 14%, white);
|
|
102
|
+
--md-on-surface: var(--brand-grafite-azulado);
|
|
103
|
+
--accent-color: var(--primary-color);
|
|
104
|
+
--accent-color-hover: var(--primary-color-hover);
|
|
105
|
+
--bg-primary: var(--brand-neutral-75);
|
|
106
|
+
--bg-secondary: #ffffff;
|
|
107
|
+
--bg-tertiary: color-mix(in srgb, var(--brand-azul-acinzentado) 14%, white);
|
|
108
|
+
--md-surface: #ffffff;
|
|
109
|
+
--md-surface-container: var(--brand-neutral-75);
|
|
110
|
+
--md-surface-container-high: color-mix(
|
|
111
|
+
in srgb,
|
|
112
|
+
var(--brand-azul-acinzentado) 14%,
|
|
113
|
+
white
|
|
114
|
+
);
|
|
115
|
+
--border-color-hover: color-mix(
|
|
116
|
+
in srgb,
|
|
117
|
+
var(--brand-grafite-azulado) 32%,
|
|
118
|
+
white
|
|
119
|
+
);
|
|
120
|
+
--bg-card: #ffffff;
|
|
121
|
+
--bg-card-hover: color-mix(in srgb, var(--brand-azul-acinzentado) 8%, white);
|
|
122
|
+
--bg-card-border: color-mix(
|
|
123
|
+
in srgb,
|
|
124
|
+
var(--brand-azul-acinzentado) 28%,
|
|
125
|
+
white
|
|
126
|
+
);
|
|
127
|
+
--text-primary: var(--brand-grafite-azulado);
|
|
128
|
+
--text-secondary: var(--brand-cinza-escuro);
|
|
129
|
+
--text-tertiary: var(--brand-cinza-medio);
|
|
130
|
+
--text-muted: var(--brand-cinza-medio);
|
|
131
|
+
--text-on-primary: #ffffff;
|
|
132
|
+
--border-color: color-mix(in srgb, var(--brand-azul-acinzentado) 30%, white);
|
|
133
|
+
--border-color-focus: color-mix(
|
|
134
|
+
in srgb,
|
|
135
|
+
var(--brand-verde-vibrante) 52%,
|
|
136
|
+
transparent
|
|
137
|
+
);
|
|
138
|
+
--shadow-xs: 0 0.0625rem 0.125rem rgba(0, 0, 0, 0.05);
|
|
139
|
+
--shadow-sm: 0 0.125rem 0.25rem rgba(0, 0, 0, 0.08);
|
|
140
|
+
--shadow-md: 0 0.25rem 0.75rem rgba(0, 0, 0, 0.1);
|
|
141
|
+
--shadow-lg: 0 0.5rem 1.5rem rgba(0, 0, 0, 0.12);
|
|
142
|
+
--font-size-xs: 0.75rem;
|
|
143
|
+
--font-size-sm: 0.875rem;
|
|
144
|
+
--font-size-base: 1rem;
|
|
145
|
+
--font-size-md: 1.125rem;
|
|
146
|
+
--font-size-lg: 1.25rem;
|
|
147
|
+
--font-size-xl: 1.5rem;
|
|
148
|
+
--font-weight-normal: 400; /* Jakarta regular */
|
|
149
|
+
--font-weight-medium: 500;
|
|
150
|
+
--font-weight-semibold: 600; /* Jakarta seminegrito */
|
|
151
|
+
--font-weight-bold: 700;
|
|
152
|
+
--line-height-normal: 1.5;
|
|
153
|
+
--spacing-xs: 0.25rem;
|
|
154
|
+
--spacing-sm: 0.5rem;
|
|
155
|
+
--spacing-md: 0.75rem;
|
|
156
|
+
--spacing-lg: 1rem;
|
|
157
|
+
--spacing-xl: 1.5rem;
|
|
158
|
+
--spacing-2xl: 2rem;
|
|
159
|
+
--border-radius-sm: 0.375rem;
|
|
160
|
+
--border-radius-md: 0.5rem;
|
|
161
|
+
--border-radius-lg: 0.75rem;
|
|
162
|
+
--border-width-thin: 0.0625rem;
|
|
163
|
+
--transition-base: 0.3s ease;
|
|
164
|
+
--transition-all: all var(--transition-base);
|
|
165
|
+
--transition-colors:
|
|
166
|
+
color var(--transition-base), background-color var(--transition-base),
|
|
167
|
+
border-color var(--transition-base);
|
|
168
|
+
--z-index-dropdown: 1000;
|
|
169
|
+
--z-index-modal-backdrop: 1040;
|
|
170
|
+
--z-index-modal: 1050;
|
|
171
|
+
--border-radius-2xl: 1.25rem;
|
|
172
|
+
--shadow-2xl: 0 1.25rem 3.75rem rgba(0, 0, 0, 0.2);
|
|
173
|
+
--font-size-2xl: 1.75rem;
|
|
174
|
+
--font-size-3xl: 2rem;
|
|
175
|
+
--font-size-4xl: 2.5rem;
|
|
176
|
+
--font-weight-light: 300;
|
|
177
|
+
--line-height-tight: 1.2;
|
|
178
|
+
--line-height-relaxed: 1.6;
|
|
179
|
+
--line-height-loose: 1.8;
|
|
180
|
+
--md-on-surface-variant: #44474e;
|
|
181
|
+
--spacing-3xl: 2.5rem;
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
[data-theme="dark"],
|
|
185
|
+
.theme-dark {
|
|
186
|
+
--bg-primary: #0f141a;
|
|
187
|
+
--bg-secondary: #161b22;
|
|
188
|
+
--bg-card: #161b22;
|
|
189
|
+
--bg-card-hover: #1e2630;
|
|
190
|
+
--bg-card-border: #2f3a46;
|
|
191
|
+
--md-surface: #161b22;
|
|
192
|
+
--md-on-surface: #e6e8eb;
|
|
193
|
+
--md-on-surface-variant: #c2c7cf;
|
|
194
|
+
--md-outline-variant: #44474e;
|
|
195
|
+
--md-primary: var(--brand-verde-vibrante);
|
|
196
|
+
--md-on-primary: #062126;
|
|
197
|
+
--primary-color: var(--brand-verde-vibrante);
|
|
198
|
+
--primary-color-light: color-mix(
|
|
199
|
+
in srgb,
|
|
200
|
+
var(--brand-verde-vibrante) 85%,
|
|
201
|
+
white
|
|
202
|
+
);
|
|
203
|
+
--primary-color-hover: var(--brand-verde-profundo);
|
|
204
|
+
--secondary-color: var(--brand-azul-acinzentado);
|
|
205
|
+
--color-primary: var(--primary-color);
|
|
206
|
+
--color-on-primary: var(--md-on-primary);
|
|
207
|
+
--color-secondary: var(--secondary-color);
|
|
208
|
+
--color-on-secondary: var(--md-on-secondary);
|
|
209
|
+
--color-surface: var(--md-surface);
|
|
210
|
+
--color-on-surface: var(--md-on-surface);
|
|
211
|
+
--color-contrast: var(--brand-off-white);
|
|
212
|
+
--text-primary: #e6e8eb;
|
|
213
|
+
--text-secondary: #d1d5db;
|
|
214
|
+
--text-muted: #9ca3af;
|
|
215
|
+
--border-color: #2f3a46;
|
|
216
|
+
--shadow-sm: 0 0.125rem 0.25rem 0 rgba(0, 0, 0, 0.4);
|
|
217
|
+
--shadow-md: 0 0.25rem 0.5rem 0 rgba(0, 0, 0, 0.5);
|
|
218
|
+
--shadow-lg: 0 0.5rem 1rem 0 rgba(0, 0, 0, 0.6);
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
/* ============================================================
|
|
222
|
+
PALETAS DE BOTÃO (guia de marca)
|
|
223
|
+
Use data-button-palette no pai (ex.: body) ou prop palette no Button.
|
|
224
|
+
============================================================ */
|
|
225
|
+
[data-button-palette="verde-vibrante"],
|
|
226
|
+
.btn--palette-verde-vibrante.btn--primary {
|
|
227
|
+
--md-primary: var(--brand-verde-vibrante);
|
|
228
|
+
--primary-color-hover: var(--brand-verde-profundo);
|
|
229
|
+
}
|
|
230
|
+
[data-button-palette="verde-vibrante"] .btn--primary {
|
|
231
|
+
--md-primary: var(--brand-verde-vibrante);
|
|
232
|
+
--primary-color-hover: var(--brand-verde-profundo);
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
[data-button-palette="verde-profundo"],
|
|
236
|
+
.btn--palette-verde-profundo.btn--primary {
|
|
237
|
+
--md-primary: var(--brand-verde-profundo);
|
|
238
|
+
--primary-color-hover: var(--brand-grafite-azulado);
|
|
239
|
+
}
|
|
240
|
+
[data-button-palette="verde-profundo"] .btn--primary {
|
|
241
|
+
--md-primary: var(--brand-verde-profundo);
|
|
242
|
+
--primary-color-hover: var(--brand-grafite-azulado);
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
[data-button-palette="grafite-azulado"],
|
|
246
|
+
.btn--palette-grafite-azulado.btn--primary {
|
|
247
|
+
--md-primary: var(--brand-grafite-azulado);
|
|
248
|
+
--primary-color-hover: var(--brand-cinza-escuro);
|
|
249
|
+
}
|
|
250
|
+
[data-button-palette="grafite-azulado"] .btn--primary {
|
|
251
|
+
--md-primary: var(--brand-grafite-azulado);
|
|
252
|
+
--primary-color-hover: var(--brand-cinza-escuro);
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
[data-button-palette="azul-acinzentado"],
|
|
256
|
+
.btn--palette-azul-acinzentado.btn--primary {
|
|
257
|
+
--md-primary: var(--brand-azul-acinzentado);
|
|
258
|
+
--primary-color-hover: var(--brand-grafite-azulado);
|
|
259
|
+
}
|
|
260
|
+
[data-button-palette="azul-acinzentado"] .btn--primary {
|
|
261
|
+
--md-primary: var(--brand-azul-acinzentado);
|
|
262
|
+
--primary-color-hover: var(--brand-grafite-azulado);
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
[data-button-palette="cinza-medio"],
|
|
266
|
+
.btn--palette-cinza-medio.btn--primary {
|
|
267
|
+
--md-primary: var(--brand-cinza-medio);
|
|
268
|
+
--primary-color-hover: var(--brand-cinza-escuro);
|
|
269
|
+
}
|
|
270
|
+
[data-button-palette="cinza-medio"] .btn--primary {
|
|
271
|
+
--md-primary: var(--brand-cinza-medio);
|
|
272
|
+
--primary-color-hover: var(--brand-cinza-escuro);
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
[data-button-palette="cinza-escuro"],
|
|
276
|
+
.btn--palette-cinza-escuro.btn--primary {
|
|
277
|
+
--md-primary: var(--brand-cinza-escuro);
|
|
278
|
+
--primary-color-hover: var(--brand-preto);
|
|
279
|
+
}
|
|
280
|
+
[data-button-palette="cinza-escuro"] .btn--primary {
|
|
281
|
+
--md-primary: var(--brand-cinza-escuro);
|
|
282
|
+
--primary-color-hover: var(--brand-preto);
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
[data-button-palette="off-white"],
|
|
286
|
+
.btn--palette-off-white.btn--primary {
|
|
287
|
+
--md-primary: var(--brand-off-white);
|
|
288
|
+
--md-on-primary: var(--brand-grafite-azulado);
|
|
289
|
+
--primary-color-hover: var(--brand-branco);
|
|
290
|
+
}
|
|
291
|
+
[data-button-palette="off-white"] .btn--primary {
|
|
292
|
+
--md-primary: var(--brand-off-white);
|
|
293
|
+
--md-on-primary: var(--brand-grafite-azulado);
|
|
294
|
+
--primary-color-hover: var(--brand-branco);
|
|
295
|
+
}
|
package/package.json
ADDED
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@sbkbs/ui",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "Biblioteca de componentes UI SBK BS",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "./dist/oficios-ui.umd.cjs",
|
|
7
|
+
"module": "./dist/oficios-ui.js",
|
|
8
|
+
"types": "./dist/index.d.ts",
|
|
9
|
+
"exports": {
|
|
10
|
+
".": {
|
|
11
|
+
"types": "./dist/index.d.ts",
|
|
12
|
+
"import": "./dist/oficios-ui.js",
|
|
13
|
+
"require": "./dist/oficios-ui.umd.cjs",
|
|
14
|
+
"default": "./dist/oficios-ui.js"
|
|
15
|
+
},
|
|
16
|
+
"./theme.css": "./dist/theme.css",
|
|
17
|
+
"./styles.css": "./dist/oficios-ui.css"
|
|
18
|
+
},
|
|
19
|
+
"files": [
|
|
20
|
+
"dist"
|
|
21
|
+
],
|
|
22
|
+
"sideEffects": [
|
|
23
|
+
"**/*.css"
|
|
24
|
+
],
|
|
25
|
+
"scripts": {
|
|
26
|
+
"clean": "node -e \"require('fs').rmSync('dist', { recursive: true, force: true })\"",
|
|
27
|
+
"build": "vite build && tsc -p tsconfig.build.json && node -e \"require('fs').copyFileSync('src/theme/theme.css', 'dist/theme.css')\"",
|
|
28
|
+
"dev": "vite build --watch",
|
|
29
|
+
"prepublishOnly": "npm run clean && npm run build && npm run typecheck",
|
|
30
|
+
"playground": "vite",
|
|
31
|
+
"publish:public": "npm publish --access public",
|
|
32
|
+
"release:patch": "npm version patch && npm run publish:public",
|
|
33
|
+
"typecheck": "tsc --noEmit -p tsconfig.build.json"
|
|
34
|
+
},
|
|
35
|
+
"peerDependencies": {
|
|
36
|
+
"react": ">=18.0.0",
|
|
37
|
+
"react-dom": ">=18.0.0"
|
|
38
|
+
},
|
|
39
|
+
"devDependencies": {
|
|
40
|
+
"@types/react": "^18.2.43",
|
|
41
|
+
"@types/react-dom": "^18.2.17",
|
|
42
|
+
"@vitejs/plugin-react": "^4.2.1",
|
|
43
|
+
"autoprefixer": "^10.4.21",
|
|
44
|
+
"postcss": "^8.5.6",
|
|
45
|
+
"react": "^18.2.0",
|
|
46
|
+
"react-dom": "^18.2.0",
|
|
47
|
+
"tailwindcss": "^3.4.17",
|
|
48
|
+
"typescript": "^5.9.3",
|
|
49
|
+
"vite": "^7.3.1"
|
|
50
|
+
},
|
|
51
|
+
"keywords": [
|
|
52
|
+
"oficios",
|
|
53
|
+
"ui",
|
|
54
|
+
"design-system",
|
|
55
|
+
"react",
|
|
56
|
+
"components"
|
|
57
|
+
],
|
|
58
|
+
"author": "Carlos Augusto",
|
|
59
|
+
"license": "ISC",
|
|
60
|
+
"publishConfig": {
|
|
61
|
+
"access": "public"
|
|
62
|
+
}
|
|
63
|
+
}
|