@sbkbs/ui 1.0.4 → 1.0.6

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 CHANGED
@@ -1,115 +1,115 @@
1
- # @sbkbs/ui
2
-
3
- Biblioteca de componentes UI e tema global para manter o mesmo padrão visual entre projetos SBK BS.
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
- "@sbkbs/ui": "^1.0.2"
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 '@sbkbs/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 '@sbkbs/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 '@sbkbs/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 `"@sbkbs/ui": "*"` nas dependências; depois `npm install` na raiz.
83
- - **Outro repositório:** use dependência por Git (`"@sbkbs/ui": "git+https://..."`) ou publique em um registry npm e instale com `npm install @sbkbs/ui`.
84
-
85
- Guia completo: [docs/COMPARTILHAR_LIB_UI.md](../docs/COMPARTILHAR_LIB_UI.md).
86
-
87
- ## Desenvolvimento
88
-
89
- - **Build**: `npm run build` dentro de `ui`.
90
- - **Watch**: `npm run dev` dentro de `ui`.
91
- - **Playground**: `npm run playground`
92
- - **Storybook**: `npm run storybook`
93
- - **Testes**: `npm run test`
94
-
95
- ## Estrutura
96
-
97
- ```
98
- ui/
99
- src/
100
- index.ts
101
- theme/
102
- theme.css
103
- ThemeProvider.tsx
104
- components/
105
- Button/
106
- Card/
107
- Input/
108
- Modal/
109
- Title/
110
- Subtitle/
111
- Paragraph/
112
- Header/
113
- Footer/
114
- dist/
115
- ```
1
+ # @sbkbs/ui
2
+
3
+ Biblioteca de componentes UI e tema global para manter o mesmo padrão visual entre projetos SBK BS.
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
+ "@sbkbs/ui": "^1.0.2"
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 '@sbkbs/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 '@sbkbs/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 '@sbkbs/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 `"@sbkbs/ui": "*"` nas dependências; depois `npm install` na raiz.
83
+ - **Outro repositório:** use dependência por Git (`"@sbkbs/ui": "git+https://..."`) ou publique em um registry npm e instale com `npm install @sbkbs/ui`.
84
+
85
+ Guia completo: [docs/COMPARTILHAR_LIB_UI.md](../docs/COMPARTILHAR_LIB_UI.md).
86
+
87
+ ## Desenvolvimento
88
+
89
+ - **Build**: `npm run build` dentro de `ui`.
90
+ - **Watch**: `npm run dev` dentro de `ui`.
91
+ - **Playground**: `npm run playground`
92
+ - **Storybook**: `npm run storybook`
93
+ - **Testes**: `npm run test`
94
+
95
+ ## Estrutura
96
+
97
+ ```
98
+ ui/
99
+ src/
100
+ index.ts
101
+ theme/
102
+ theme.css
103
+ ThemeProvider.tsx
104
+ components/
105
+ Button/
106
+ Card/
107
+ Input/
108
+ Modal/
109
+ Title/
110
+ Subtitle/
111
+ Paragraph/
112
+ Header/
113
+ Footer/
114
+ dist/
115
+ ```
@@ -0,0 +1,11 @@
1
+ import type React from 'react';
2
+ export interface AvatarProps extends React.HTMLAttributes<HTMLSpanElement> {
3
+ /** Texto alternativo / label acessível para a imagem ou iniciais. */
4
+ alt: string;
5
+ /** URL da imagem. Se ausente ou falhar no carregamento, exibe as iniciais. */
6
+ src?: string;
7
+ size?: 'xs' | 'sm' | 'md' | 'lg' | 'xl';
8
+ /** Formato do avatar. Padrão: 'circle' */
9
+ shape?: 'circle' | 'square';
10
+ }
11
+ export declare const Avatar: React.FC<AvatarProps>;
@@ -4,9 +4,9 @@ export interface FooterProps {
4
4
  className?: string;
5
5
  /** Texto alternativo do logo */
6
6
  logoAlt?: string;
7
- /** Texto exibido se a imagem do logo falhar (ex.: "SBK") */
7
+ /** Fallback textual — não utilizado no design padrão, mantido por compatibilidade */
8
8
  logoFallbackText?: string;
9
- /** URL da imagem do logo */
9
+ /** URL de imagem para substituir o logo SVG padrão */
10
10
  logoSrc?: string;
11
11
  /** Texto antes do logo (ex.: "Powered by") */
12
12
  poweredByText?: string;
@@ -1,54 +1,119 @@
1
- import { jsx as r, jsxs as n } from "react/jsx-runtime";
2
- import { useState as c } from "react";
3
- const p = ({
4
- poweredByText: t = "Powered by",
5
- logoSrc: e,
6
- logoAlt: i = "Logo",
7
- logoFallbackText: s,
8
- className: o = ""
9
- }) => {
10
- const [a, l] = c(!0);
11
- return /* @__PURE__ */ r(
12
- "footer",
1
+ import { jsx as e, jsxs as i } from "react/jsx-runtime";
2
+ import { useState as h, useEffect as f } from "react";
3
+ import { cn as u } from "../../utils/cn.js";
4
+ const d = () => typeof document > "u" ? "light" : document.documentElement.getAttribute("data-theme") === "dark" ? "dark" : "light", p = ({ color: t, height: r = 28, opacity: s = 1 }) => {
5
+ const n = Math.round(r * 2.098961562306262);
6
+ return /* @__PURE__ */ e(
7
+ "svg",
13
8
  {
14
- className: [
15
- "relative z-[1] flex w-full shrink-0 items-center justify-center border-t border-[var(--border-color)] bg-[var(--bg-secondary)] px-[var(--spacing-2xl)] py-[var(--spacing-lg)]",
16
- o
17
- ].filter(Boolean).join(" "),
18
- children: /* @__PURE__ */ n("div", { className: "flex items-center gap-[var(--spacing-md)]", children: [
19
- t && /* @__PURE__ */ r("span", { className: "text-[0.95rem] font-normal text-[var(--text-secondary)]", children: t }),
20
- (e || s) && /* @__PURE__ */ n("div", { className: "flex items-center", children: [
21
- e && a && /* @__PURE__ */ r(
22
- "img",
9
+ "aria-label": "SBK",
10
+ height: r,
11
+ style: { opacity: s },
12
+ viewBox: "39.15 180.84 541.7 258.08",
13
+ width: n,
14
+ xmlns: "http://www.w3.org/2000/svg",
15
+ children: /* @__PURE__ */ e("g", { transform: "translate(-49, 122)", children: /* @__PURE__ */ i("g", { children: [
16
+ /* @__PURE__ */ i("g", { children: [
17
+ /* @__PURE__ */ e(
18
+ "path",
19
+ {
20
+ d: "m225.13 266.26c-27.48 0-47.67-12.07-50.38-41.01h14.16c0.62 21.44 17.69 29.56 36.85 29.56 18.11 0 39.14-7.91 39.14-29.14 0-16.24-13.12-23.74-32.48-29.99l-11.03-3.53c-24.36-7.71-42.27-16.66-42.27-40.19 0-28.1 24.78-39.97 49.76-39.97 22.9 0 46.64 8.54 47.05 35.18h-13.95c-1.87-18.32-15.82-23.94-32.47-23.94-17.29 0-36.65 7.71-36.65 27.69 0 14.78 11.04 22.28 34.36 29.77l12.49 3.96c24.36 7.7 38.3 15.82 38.93 38.73 0 30.18-26.65 42.88-53.51 42.88z",
21
+ fill: t,
22
+ stroke: t,
23
+ strokeMiterlimit: 10,
24
+ strokeWidth: 2
25
+ }
26
+ ),
27
+ /* @__PURE__ */ e(
28
+ "path",
29
+ {
30
+ d: "m351.42 264.39h-41.43v-150.53h41.43c8.53 0 17.9-0.2 26.23 2.09 16.24 4.58 27.48 17.9 27.48 35.18 0 18.74-10.41 29.98-27.9 34.56 20.82 2.71 34.15 15.2 34.15 36.85 0 34.56-31.86 41.85-59.96 41.85zm8.12-138.45h-36.02v56.49h32.06c19.16 0 34.98-8.81 34.98-30.26 0-18.74-14.16-26.23-31.02-26.23zm-1.46 63.19h-34.56v63.18h26.65c21.86 0 46.84-1.45 46.84-29.98 0-24.77-18.11-33.2-38.93-33.2z",
31
+ fill: t,
32
+ fillRule: "evenodd",
33
+ stroke: t,
34
+ strokeMiterlimit: 10,
35
+ strokeWidth: 2
36
+ }
37
+ ),
38
+ /* @__PURE__ */ e(
39
+ "path",
23
40
  {
24
- alt: i,
25
- className: "h-6 w-auto object-contain",
26
- onError: (m) => {
27
- l(!1);
28
- },
29
- src: e,
30
- style: {
31
- filter: "brightness(0)"
32
- }
41
+ d: "m443.77 264.39v-150.53h13.53v150.53zm88.07 0l-73.7-81.61 67.03-68.92h18.12l-68.91 67.88 75.99 82.65z",
42
+ fill: t,
43
+ stroke: t,
44
+ strokeMiterlimit: 10,
45
+ strokeWidth: 2
46
+ }
47
+ )
48
+ ] }),
49
+ /* @__PURE__ */ i("g", { children: [
50
+ /* @__PURE__ */ e(
51
+ "path",
52
+ {
53
+ d: "m99.09 118.17l-0.21 57.98-9.73 0.24 0.56-62.81c0.26-29.03 26.91-53.16 56.3-53.26l151.74-0.48c0.62 3.58 0.63 6.35 0.05 9.92l-150.35 0.22c-26.28 0.04-48.26 21.9-48.36 48.19z",
54
+ fill: t
33
55
  }
34
56
  ),
35
- s && /* @__PURE__ */ r(
36
- "span",
57
+ /* @__PURE__ */ e(
58
+ "path",
37
59
  {
38
- className: "flex items-center text-base font-bold tracking-[0.1em] text-[var(--md-primary)]",
39
- style: {
40
- display: e && a ? "none" : "flex",
41
- fontFamily: '"Orbitron", sans-serif'
42
- },
43
- children: s
60
+ d: "m419.9 315.79l0.22-9.33 149.3-0.15c25.73-0.02 48.97-20.27 49.14-45.96l0.4-60.49q4.64-0.28 9.57-0.07l0.32 52.61c0.21 33.16-23.62 63.29-57.93 63.33l-135.88 0.19z",
61
+ fill: t
44
62
  }
45
63
  )
46
64
  ] })
65
+ ] }) })
66
+ }
67
+ );
68
+ }, b = ({
69
+ poweredByText: t = "Powered by",
70
+ logoSrc: r,
71
+ logoAlt: s = "SBK",
72
+ className: o = ""
73
+ }) => {
74
+ const [n, m] = h(() => d());
75
+ f(() => {
76
+ const a = () => m(d());
77
+ if (a(), typeof MutationObserver > "u") return;
78
+ const c = new MutationObserver(a);
79
+ return c.observe(document.documentElement, { attributes: !0, attributeFilter: ["data-theme"] }), () => c.disconnect();
80
+ }, []);
81
+ const l = n === "dark";
82
+ return /* @__PURE__ */ e(
83
+ "footer",
84
+ {
85
+ className: u(
86
+ "relative z-[1] w-full shrink-0 box-border",
87
+ "flex items-center justify-center",
88
+ "py-5 px-14",
89
+ "border-t border-[var(--border-color)]",
90
+ "bg-[var(--bg-secondary)]",
91
+ o
92
+ ),
93
+ children: /* @__PURE__ */ i("div", { className: "flex items-center gap-2.5", children: [
94
+ t && /* @__PURE__ */ e("span", { className: "font-primary text-xs font-normal text-[var(--text-muted)]", children: t }),
95
+ r ? /* @__PURE__ */ e(
96
+ "img",
97
+ {
98
+ alt: s,
99
+ src: r,
100
+ className: "h-7 w-auto object-contain",
101
+ style: { opacity: l ? 0.65 : 0.75 }
102
+ }
103
+ ) : /* @__PURE__ */ e(
104
+ p,
105
+ {
106
+ color: l ? "#ffffff" : "#1F3A3A",
107
+ height: 28,
108
+ opacity: l ? 0.65 : 0.75
109
+ }
110
+ )
47
111
  ] })
48
112
  }
49
113
  );
50
114
  };
115
+ b.displayName = "Footer";
51
116
  export {
52
- p as Footer
117
+ b as Footer
53
118
  };
54
119
  //# sourceMappingURL=Footer.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"Footer.js","sources":["../../../src/components/Footer/Footer.tsx"],"sourcesContent":["import type React from 'react';\nimport { useState } from 'react';\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 const [logoVisible, setLogoVisible] = useState(true);\n return (\n <footer\n className={[\n 'relative z-[1] flex w-full shrink-0 items-center justify-center border-t border-[var(--border-color)] bg-[var(--bg-secondary)] px-[var(--spacing-2xl)] py-[var(--spacing-lg)]',\n className,\n ]\n .filter(Boolean)\n .join(' ')}\n >\n <div className=\"flex items-center gap-[var(--spacing-md)]\">\n {poweredByText && (\n <span className=\"text-[0.95rem] font-normal text-[var(--text-secondary)]\">\n {poweredByText}\n </span>\n )}\n {(logoSrc || logoFallbackText) && (\n <div className=\"flex items-center\">\n {logoSrc && logoVisible && (\n <img\n alt={logoAlt}\n className=\"h-6 w-auto object-contain\"\n onError={(_e) => {\n setLogoVisible(false);\n }}\n src={logoSrc}\n style={{\n filter: 'brightness(0)',\n }}\n />\n )}\n {logoFallbackText && (\n <span\n className=\"flex items-center text-base font-bold tracking-[0.1em] text-[var(--md-primary)]\"\n style={{\n display: logoSrc && logoVisible ? 'none' : 'flex',\n fontFamily: '\"Orbitron\", sans-serif',\n }}\n >\n {logoFallbackText}\n </span>\n )}\n </div>\n )}\n </div>\n </footer>\n );\n};\n"],"names":["Footer","poweredByText","logoSrc","logoAlt","logoFallbackText","className","logoVisible","setLogoVisible","useState","jsx","jsxs","_e"],"mappings":";;AAgBO,MAAMA,IAAgC,CAAC;AAAA,EAC5C,eAAAC,IAAgB;AAAA,EAChB,SAAAC;AAAA,EACA,SAAAC,IAAU;AAAA,EACV,kBAAAC;AAAA,EACA,WAAAC,IAAY;AACd,MAAM;AACJ,QAAM,CAACC,GAAaC,CAAc,IAAIC,EAAS,EAAI;AACnD,SACE,gBAAAC;AAAA,IAAC;AAAA,IAAA;AAAA,MACC,WAAW;AAAA,QACT;AAAA,QACAJ;AAAA,MAAA,EAEC,OAAO,OAAO,EACd,KAAK,GAAG;AAAA,MAEX,UAAA,gBAAAK,EAAC,OAAA,EAAI,WAAU,6CACZ,UAAA;AAAA,QAAAT,KACC,gBAAAQ,EAAC,QAAA,EAAK,WAAU,2DACb,UAAAR,GACH;AAAA,SAEAC,KAAWE,MACX,gBAAAM,EAAC,OAAA,EAAI,WAAU,qBACZ,UAAA;AAAA,UAAAR,KAAWI,KACV,gBAAAG;AAAA,YAAC;AAAA,YAAA;AAAA,cACC,KAAKN;AAAA,cACL,WAAU;AAAA,cACV,SAAS,CAACQ,MAAO;AACf,gBAAAJ,EAAe,EAAK;AAAA,cACtB;AAAA,cACA,KAAKL;AAAA,cACL,OAAO;AAAA,gBACL,QAAQ;AAAA,cAAA;AAAA,YACV;AAAA,UAAA;AAAA,UAGHE,KACC,gBAAAK;AAAA,YAAC;AAAA,YAAA;AAAA,cACC,WAAU;AAAA,cACV,OAAO;AAAA,gBACL,SAASP,KAAWI,IAAc,SAAS;AAAA,gBAC3C,YAAY;AAAA,cAAA;AAAA,cAGb,UAAAF;AAAA,YAAA;AAAA,UAAA;AAAA,QACH,EAAA,CAEJ;AAAA,MAAA,EAAA,CAEJ;AAAA,IAAA;AAAA,EAAA;AAGN;"}
1
+ {"version":3,"file":"Footer.js","sources":["../../../src/components/Footer/Footer.tsx"],"sourcesContent":["import type React from 'react';\nimport { useEffect, useState } from 'react';\nimport { cn } from '../../utils/cn';\n\nexport interface FooterProps {\n /** Classe CSS adicional */\n className?: string;\n /** Texto alternativo do logo */\n logoAlt?: string;\n /** Fallback textual — não utilizado no design padrão, mantido por compatibilidade */\n logoFallbackText?: string;\n /** URL de imagem para substituir o logo SVG padrão */\n logoSrc?: string;\n /** Texto antes do logo (ex.: \"Powered by\") */\n poweredByText?: string;\n}\n\nconst detectTheme = () => {\n if (typeof document === 'undefined') return 'light';\n return document.documentElement.getAttribute('data-theme') === 'dark' ? 'dark' : 'light';\n};\n\ninterface SbkLogoProps {\n color: string;\n height?: number;\n opacity?: number;\n}\n\nconst SbkLogo: React.FC<SbkLogoProps> = ({ color, height = 28, opacity = 1 }) => {\n const aspect = 541.7 / 258.08;\n const width = Math.round(height * aspect);\n return (\n <svg\n aria-label=\"SBK\"\n height={height}\n style={{ opacity }}\n viewBox=\"39.15 180.84 541.7 258.08\"\n width={width}\n xmlns=\"http://www.w3.org/2000/svg\"\n >\n <g transform=\"translate(-49, 122)\">\n <g>\n <g>\n {/* S */}\n <path\n d=\"m225.13 266.26c-27.48 0-47.67-12.07-50.38-41.01h14.16c0.62 21.44 17.69 29.56 36.85 29.56 18.11 0 39.14-7.91 39.14-29.14 0-16.24-13.12-23.74-32.48-29.99l-11.03-3.53c-24.36-7.71-42.27-16.66-42.27-40.19 0-28.1 24.78-39.97 49.76-39.97 22.9 0 46.64 8.54 47.05 35.18h-13.95c-1.87-18.32-15.82-23.94-32.47-23.94-17.29 0-36.65 7.71-36.65 27.69 0 14.78 11.04 22.28 34.36 29.77l12.49 3.96c24.36 7.7 38.3 15.82 38.93 38.73 0 30.18-26.65 42.88-53.51 42.88z\"\n fill={color}\n stroke={color}\n strokeMiterlimit={10}\n strokeWidth={2}\n />\n {/* B */}\n <path\n d=\"m351.42 264.39h-41.43v-150.53h41.43c8.53 0 17.9-0.2 26.23 2.09 16.24 4.58 27.48 17.9 27.48 35.18 0 18.74-10.41 29.98-27.9 34.56 20.82 2.71 34.15 15.2 34.15 36.85 0 34.56-31.86 41.85-59.96 41.85zm8.12-138.45h-36.02v56.49h32.06c19.16 0 34.98-8.81 34.98-30.26 0-18.74-14.16-26.23-31.02-26.23zm-1.46 63.19h-34.56v63.18h26.65c21.86 0 46.84-1.45 46.84-29.98 0-24.77-18.11-33.2-38.93-33.2z\"\n fill={color}\n fillRule=\"evenodd\"\n stroke={color}\n strokeMiterlimit={10}\n strokeWidth={2}\n />\n {/* K */}\n <path\n d=\"m443.77 264.39v-150.53h13.53v150.53zm88.07 0l-73.7-81.61 67.03-68.92h18.12l-68.91 67.88 75.99 82.65z\"\n fill={color}\n stroke={color}\n strokeMiterlimit={10}\n strokeWidth={2}\n />\n </g>\n <g>\n {/* Arco superior */}\n <path\n d=\"m99.09 118.17l-0.21 57.98-9.73 0.24 0.56-62.81c0.26-29.03 26.91-53.16 56.3-53.26l151.74-0.48c0.62 3.58 0.63 6.35 0.05 9.92l-150.35 0.22c-26.28 0.04-48.26 21.9-48.36 48.19z\"\n fill={color}\n />\n {/* Arco inferior */}\n <path\n d=\"m419.9 315.79l0.22-9.33 149.3-0.15c25.73-0.02 48.97-20.27 49.14-45.96l0.4-60.49q4.64-0.28 9.57-0.07l0.32 52.61c0.21 33.16-23.62 63.29-57.93 63.33l-135.88 0.19z\"\n fill={color}\n />\n </g>\n </g>\n </g>\n </svg>\n );\n};\n\nexport const Footer: React.FC<FooterProps> = ({\n poweredByText = 'Powered by',\n logoSrc,\n logoAlt = 'SBK',\n className = '',\n}) => {\n const [theme, setTheme] = useState<'light' | 'dark'>(() => detectTheme() as 'light' | 'dark');\n\n useEffect(() => {\n const sync = () => setTheme(detectTheme() as 'light' | 'dark');\n sync();\n if (typeof MutationObserver === 'undefined') return;\n const observer = new MutationObserver(sync);\n observer.observe(document.documentElement, { attributes: true, attributeFilter: ['data-theme'] });\n return () => observer.disconnect();\n }, []);\n\n const isDark = theme === 'dark';\n\n return (\n <footer\n className={cn(\n 'relative z-[1] w-full shrink-0 box-border',\n 'flex items-center justify-center',\n 'py-5 px-14',\n 'border-t border-[var(--border-color)]',\n 'bg-[var(--bg-secondary)]',\n className,\n )}\n >\n <div className=\"flex items-center gap-2.5\">\n {poweredByText && (\n <span className=\"font-primary text-xs font-normal text-[var(--text-muted)]\">\n {poweredByText}\n </span>\n )}\n\n {logoSrc ? (\n <img\n alt={logoAlt}\n src={logoSrc}\n className=\"h-7 w-auto object-contain\"\n style={{ opacity: isDark ? 0.65 : 0.75 }}\n />\n ) : (\n <SbkLogo\n color={isDark ? '#ffffff' : '#1F3A3A'}\n height={28}\n opacity={isDark ? 0.65 : 0.75}\n />\n )}\n </div>\n </footer>\n );\n};\n\nFooter.displayName = 'Footer';\n"],"names":["detectTheme","SbkLogo","color","height","opacity","width","jsx","jsxs","Footer","poweredByText","logoSrc","logoAlt","className","theme","setTheme","useState","useEffect","sync","observer","isDark","cn"],"mappings":"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"}
@@ -5,19 +5,25 @@ export interface HeaderProps {
5
5
  className?: string;
6
6
  /** Texto alternativo do logo */
7
7
  logoAlt?: string;
8
- /** URL da imagem do logo (tema escuro). Se não informado, usa logoSrc. */
8
+ /** URL de imagem para substituir o logo SVG padrão (tema escuro) */
9
9
  logoDarkSrc?: string;
10
- /** URL da imagem do logo (tema claro) */
10
+ /** URL de imagem para substituir o logo SVG padrão (tema claro) */
11
11
  logoSrc?: string;
12
+ /** Callback ao clicar no ícone de menu (hamburger) */
13
+ onMenuClick?: () => void;
12
14
  /** Callback ao clicar na área do logo/título */
13
15
  onLogoClick?: () => void;
14
- /** Conteúdo da área direita (ex.: seletor de idioma, toggle tema, menu usuário) */
16
+ /** Conteúdo da área direita (pills de idioma/tema, etc.) */
15
17
  rightContent?: React.ReactNode;
18
+ /** Exibe o ícone hamburger à esquerda — padrão: true */
19
+ showMenuIcon?: boolean;
16
20
  /** Subtítulo abaixo do título */
17
21
  subtitle?: React.ReactNode;
18
- /** Tema opcional para escolher o logo correto sem depender do ThemeProvider do UI */
22
+ /** Tema opcional para escolher o logo correto sem depender do ThemeProvider */
19
23
  theme?: Theme;
20
- /** Título exibido ao lado do logo (ex.: "OFÍCIO.IA") */
24
+ /** Título exibido ao lado do logo */
21
25
  title?: React.ReactNode;
26
+ /** Iniciais do usuário no avatar circular turquesa (ex.: "CF") */
27
+ userInitials?: string;
22
28
  }
23
29
  export declare const Header: React.FC<HeaderProps>;