@seedgrid/ai-toolkit 0.0.0-stage → 0.3.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +162 -2
- package/dist/adapters/claude.js +114 -0
- package/dist/adapters/codex.js +108 -0
- package/dist/adapters/index.js +17 -0
- package/dist/adapters/shared.js +142 -0
- package/dist/adapters/types.js +1 -0
- package/dist/cli.js +209 -0
- package/dist/commands/common.js +98 -0
- package/dist/commands/doctor.js +290 -0
- package/dist/commands/init.js +9 -0
- package/dist/commands/install.js +107 -0
- package/dist/commands/remove.js +54 -0
- package/dist/commands/review.js +127 -0
- package/dist/commands/selfinstall.js +63 -0
- package/dist/commands/status.js +73 -0
- package/dist/commands/update.js +8 -0
- package/dist/commands/validate.js +27 -0
- package/dist/core/apply.js +181 -0
- package/dist/core/blocks.js +64 -0
- package/dist/core/content.js +528 -0
- package/dist/core/env.js +40 -0
- package/dist/core/frontmatter.js +29 -0
- package/dist/core/hash.js +14 -0
- package/dist/core/inspect.js +51 -0
- package/dist/core/lock.js +124 -0
- package/dist/core/paths.js +65 -0
- package/dist/core/plan.js +242 -0
- package/dist/core/tools.js +62 -0
- package/dist/core/types.js +11 -0
- package/dist/core/updates.js +121 -0
- package/docs/arquitetura.md +80 -0
- package/docs/compatibilidade.md +50 -0
- package/docs/formato.md +155 -0
- package/docs/instalacao.md +105 -0
- package/docs/manutencao.md +115 -0
- package/package.json +43 -4
- package/seedgridKB/SeedGrid/Extensions/Catalogo-de-enums.md +161 -0
- package/seedgridKB/SeedGrid/Extensions/Catalogo-de-propriedades.md +971 -0
- package/seedgridKB/SeedGrid/Extensions/Indice.md +63 -0
- package/seedgridKB/SeedGrid/Extensions/ai-pricing/Configuracao.md +124 -0
- package/seedgridKB/SeedGrid/Extensions/ai-pricing/Enums.md +40 -0
- package/seedgridKB/SeedGrid/Extensions/ai-pricing/Exemplos.md +97 -0
- package/seedgridKB/SeedGrid/Extensions/ai-pricing/Visao-geral.md +114 -0
- package/seedgridKB/SeedGrid/Extensions/apikeys/Configuracao-Rust.md +69 -0
- package/seedgridKB/SeedGrid/Extensions/apikeys/Configuracao.md +88 -0
- package/seedgridKB/SeedGrid/Extensions/apikeys/Enums.md +33 -0
- package/seedgridKB/SeedGrid/Extensions/apikeys/Exemplos.md +121 -0
- package/seedgridKB/SeedGrid/Extensions/apikeys/Rust.md +126 -0
- package/seedgridKB/SeedGrid/Extensions/apikeys/Visao-geral.md +111 -0
- package/seedgridKB/SeedGrid/Extensions/audit/Configuracao-Rust.md +93 -0
- package/seedgridKB/SeedGrid/Extensions/audit/Configuracao.md +127 -0
- package/seedgridKB/SeedGrid/Extensions/audit/Enums.md +66 -0
- package/seedgridKB/SeedGrid/Extensions/audit/Exemplos.md +151 -0
- package/seedgridKB/SeedGrid/Extensions/audit/Rust.md +120 -0
- package/seedgridKB/SeedGrid/Extensions/audit/Visao-geral.md +114 -0
- package/seedgridKB/SeedGrid/Extensions/backup/Configuracao-Rust.md +136 -0
- package/seedgridKB/SeedGrid/Extensions/backup/Configuracao.md +319 -0
- package/seedgridKB/SeedGrid/Extensions/backup/Enums.md +131 -0
- package/seedgridKB/SeedGrid/Extensions/backup/Exemplos.md +210 -0
- package/seedgridKB/SeedGrid/Extensions/backup/Rust.md +135 -0
- package/seedgridKB/SeedGrid/Extensions/backup/Visao-geral.md +150 -0
- package/seedgridKB/SeedGrid/Extensions/billing/Configuracao-Rust.md +86 -0
- package/seedgridKB/SeedGrid/Extensions/billing/Configuracao.md +243 -0
- package/seedgridKB/SeedGrid/Extensions/billing/Enums.md +165 -0
- package/seedgridKB/SeedGrid/Extensions/billing/Exemplos.md +205 -0
- package/seedgridKB/SeedGrid/Extensions/billing/Rust.md +109 -0
- package/seedgridKB/SeedGrid/Extensions/billing/Visao-geral.md +181 -0
- package/seedgridKB/SeedGrid/Extensions/broker/Configuracao-Rust.md +40 -0
- package/seedgridKB/SeedGrid/Extensions/broker/Visao-geral.md +114 -0
- package/seedgridKB/SeedGrid/Extensions/cache/Configuracao-Rust.md +73 -0
- package/seedgridKB/SeedGrid/Extensions/cache/Configuracao.md +112 -0
- package/seedgridKB/SeedGrid/Extensions/cache/Enums.md +36 -0
- package/seedgridKB/SeedGrid/Extensions/cache/Exemplos.md +149 -0
- package/seedgridKB/SeedGrid/Extensions/cache/Rust.md +81 -0
- package/seedgridKB/SeedGrid/Extensions/cache/Visao-geral.md +90 -0
- package/seedgridKB/SeedGrid/Extensions/commons/Configuracao.md +107 -0
- package/seedgridKB/SeedGrid/Extensions/commons/Enums.md +105 -0
- package/seedgridKB/SeedGrid/Extensions/commons/Exemplos.md +141 -0
- package/seedgridKB/SeedGrid/Extensions/commons/Visao-geral.md +99 -0
- package/seedgridKB/SeedGrid/Extensions/exchange/Configuracao.md +122 -0
- package/seedgridKB/SeedGrid/Extensions/exchange/Enums.md +29 -0
- package/seedgridKB/SeedGrid/Extensions/exchange/Exemplos.md +82 -0
- package/seedgridKB/SeedGrid/Extensions/exchange/Visao-geral.md +118 -0
- package/seedgridKB/SeedGrid/Extensions/filemanagement/Configuracao-Rust.md +110 -0
- package/seedgridKB/SeedGrid/Extensions/filemanagement/Configuracao.md +157 -0
- package/seedgridKB/SeedGrid/Extensions/filemanagement/Exemplos.md +157 -0
- package/seedgridKB/SeedGrid/Extensions/filemanagement/Rust.md +70 -0
- package/seedgridKB/SeedGrid/Extensions/filemanagement/Visao-geral.md +88 -0
- package/seedgridKB/SeedGrid/Extensions/login-tenancy/Configuracao-Rust.md +124 -0
- package/seedgridKB/SeedGrid/Extensions/login-tenancy/Configuracao.md +195 -0
- package/seedgridKB/SeedGrid/Extensions/login-tenancy/Enums.md +71 -0
- package/seedgridKB/SeedGrid/Extensions/login-tenancy/Exemplos.md +149 -0
- package/seedgridKB/SeedGrid/Extensions/login-tenancy/Rust.md +139 -0
- package/seedgridKB/SeedGrid/Extensions/login-tenancy/Visao-geral.md +130 -0
- package/seedgridKB/SeedGrid/Extensions/notification/Configuracao.md +141 -0
- package/seedgridKB/SeedGrid/Extensions/notification/Enums.md +52 -0
- package/seedgridKB/SeedGrid/Extensions/notification/Exemplos.md +141 -0
- package/seedgridKB/SeedGrid/Extensions/notification/Visao-geral.md +113 -0
- package/seedgridKB/SeedGrid/Extensions/privacy/Configuracao-Rust.md +67 -0
- package/seedgridKB/SeedGrid/Extensions/privacy/Configuracao.md +94 -0
- package/seedgridKB/SeedGrid/Extensions/privacy/Enums.md +79 -0
- package/seedgridKB/SeedGrid/Extensions/privacy/Exemplos.md +172 -0
- package/seedgridKB/SeedGrid/Extensions/privacy/Rust.md +107 -0
- package/seedgridKB/SeedGrid/Extensions/privacy/Visao-geral.md +90 -0
- package/seedgridKB/SeedGrid/Extensions/realtime/Configuracao-Rust.md +72 -0
- package/seedgridKB/SeedGrid/Extensions/realtime/Configuracao.md +104 -0
- package/seedgridKB/SeedGrid/Extensions/realtime/Exemplos.md +104 -0
- package/seedgridKB/SeedGrid/Extensions/realtime/Rust.md +69 -0
- package/seedgridKB/SeedGrid/Extensions/realtime/Visao-geral.md +105 -0
- package/seedgridKB/SeedGrid/Extensions/resilience/Configuracao-Rust.md +68 -0
- package/seedgridKB/SeedGrid/Extensions/resilience/Configuracao.md +186 -0
- package/seedgridKB/SeedGrid/Extensions/resilience/Enums.md +96 -0
- package/seedgridKB/SeedGrid/Extensions/resilience/Exemplos.md +229 -0
- package/seedgridKB/SeedGrid/Extensions/resilience/Rust.md +80 -0
- package/seedgridKB/SeedGrid/Extensions/resilience/Visao-geral.md +112 -0
- package/seedgridKB/SeedGrid/Extensions/runtime/Configuracao-Rust.md +90 -0
- package/seedgridKB/SeedGrid/Extensions/runtime/Visao-geral.md +114 -0
- package/seedgridKB/SeedGrid/Extensions/security/Configuracao-Rust.md +327 -0
- package/seedgridKB/SeedGrid/Extensions/security/Configuracao.md +510 -0
- package/seedgridKB/SeedGrid/Extensions/security/Enums.md +95 -0
- package/seedgridKB/SeedGrid/Extensions/security/Exemplos.md +218 -0
- package/seedgridKB/SeedGrid/Extensions/security/Rust.md +203 -0
- package/seedgridKB/SeedGrid/Extensions/security/Visao-geral.md +131 -0
- package/seedgridKB/SeedGrid/Extensions/subdomain-tenancy/Configuracao-Rust.md +188 -0
- package/seedgridKB/SeedGrid/Extensions/subdomain-tenancy/Configuracao.md +345 -0
- package/seedgridKB/SeedGrid/Extensions/subdomain-tenancy/Enums.md +117 -0
- package/seedgridKB/SeedGrid/Extensions/subdomain-tenancy/Exemplos.md +205 -0
- package/seedgridKB/SeedGrid/Extensions/subdomain-tenancy/Rust.md +161 -0
- package/seedgridKB/SeedGrid/Extensions/subdomain-tenancy/Visao-geral.md +142 -0
- package/seedgridKB/SeedGrid/Extensions/whatsapp/Configuracao-Rust.md +75 -0
- package/seedgridKB/SeedGrid/Extensions/whatsapp/Configuracao.md +152 -0
- package/seedgridKB/SeedGrid/Extensions/whatsapp/Enums.md +198 -0
- package/seedgridKB/SeedGrid/Extensions/whatsapp/Exemplos.md +173 -0
- package/seedgridKB/SeedGrid/Extensions/whatsapp/Rust.md +83 -0
- package/seedgridKB/SeedGrid/Extensions/whatsapp/Visao-geral.md +99 -0
- package/seedgridKB/SeedGrid/Mapa-dos-repositorios.md +112 -0
- package/seedgridKB/SeedGrid/SeedGrid-components/Indice.md +323 -0
- package/seedgridKB/SeedGrid/SeedGrid-components/buttons/API.md +257 -0
- package/seedgridKB/SeedGrid/SeedGrid-components/buttons/Exemplos.md +307 -0
- package/seedgridKB/SeedGrid/SeedGrid-components/buttons/Visao-geral.md +51 -0
- package/seedgridKB/SeedGrid/SeedGrid-components/datatable/API.md +174 -0
- package/seedgridKB/SeedGrid/SeedGrid-components/datatable/Exemplos.md +236 -0
- package/seedgridKB/SeedGrid/SeedGrid-components/datatable/Visao-geral.md +76 -0
- package/seedgridKB/SeedGrid/SeedGrid-components/digits/API.md +339 -0
- package/seedgridKB/SeedGrid/SeedGrid-components/digits/Exemplos.md +311 -0
- package/seedgridKB/SeedGrid/SeedGrid-components/digits/Visao-geral.md +57 -0
- package/seedgridKB/SeedGrid/SeedGrid-components/editor/API.md +125 -0
- package/seedgridKB/SeedGrid/SeedGrid-components/editor/Exemplos.md +116 -0
- package/seedgridKB/SeedGrid/SeedGrid-components/editor/Visao-geral.md +86 -0
- package/seedgridKB/SeedGrid/SeedGrid-components/feedback-e-exibicao/API.md +490 -0
- package/seedgridKB/SeedGrid/SeedGrid-components/feedback-e-exibicao/Exemplos.md +544 -0
- package/seedgridKB/SeedGrid/SeedGrid-components/feedback-e-exibicao/Visao-geral.md +69 -0
- package/seedgridKB/SeedGrid/SeedGrid-components/fundamentos/API.md +113 -0
- package/seedgridKB/SeedGrid/SeedGrid-components/fundamentos/Exemplos.md +159 -0
- package/seedgridKB/SeedGrid/SeedGrid-components/fundamentos/Visao-geral.md +92 -0
- package/seedgridKB/SeedGrid/SeedGrid-components/gadgets/API.md +516 -0
- package/seedgridKB/SeedGrid/SeedGrid-components/gadgets/Exemplos.md +629 -0
- package/seedgridKB/SeedGrid/SeedGrid-components/gadgets/Visao-geral.md +80 -0
- package/seedgridKB/SeedGrid/SeedGrid-components/inputs-selecao/API.md +615 -0
- package/seedgridKB/SeedGrid/SeedGrid-components/inputs-selecao/Exemplos.md +384 -0
- package/seedgridKB/SeedGrid/SeedGrid-components/inputs-selecao/Visao-geral.md +111 -0
- package/seedgridKB/SeedGrid/SeedGrid-components/inputs-texto/API.md +661 -0
- package/seedgridKB/SeedGrid/SeedGrid-components/inputs-texto/Exemplos.md +312 -0
- package/seedgridKB/SeedGrid/SeedGrid-components/inputs-texto/Visao-geral.md +123 -0
- package/seedgridKB/SeedGrid/SeedGrid-components/layout/API.md +1090 -0
- package/seedgridKB/SeedGrid/SeedGrid-components/layout/Exemplos.md +1172 -0
- package/seedgridKB/SeedGrid/SeedGrid-components/layout/Visao-geral.md +98 -0
- package/seedgridKB/SeedGrid/SeedGrid-components/modulos/Visao-geral.md +98 -0
- package/seedgridKB/SeedGrid/SeedGrid-components/modulos/fe-apikeys.md +118 -0
- package/seedgridKB/SeedGrid/SeedGrid-components/modulos/fe-audit.md +88 -0
- package/seedgridKB/SeedGrid/SeedGrid-components/modulos/fe-backup.md +131 -0
- package/seedgridKB/SeedGrid/SeedGrid-components/modulos/fe-billing-platform.md +132 -0
- package/seedgridKB/SeedGrid/SeedGrid-components/modulos/fe-billing-user.md +120 -0
- package/seedgridKB/SeedGrid/SeedGrid-components/modulos/fe-login-tenancy.md +119 -0
- package/seedgridKB/SeedGrid/SeedGrid-components/modulos/fe-security.md +427 -0
- package/seedgridKB/SeedGrid/SeedGrid-components/modulos/fe-self-enter.md +104 -0
- package/seedgridKB/SeedGrid/SeedGrid-components/modulos/fe-subdomain-tenancy.md +110 -0
- package/seedgridKB/SeedGrid/SeedGrid-components/navegacao-e-overlay/API.md +490 -0
- package/seedgridKB/SeedGrid/SeedGrid-components/navegacao-e-overlay/Exemplos.md +561 -0
- package/seedgridKB/SeedGrid/SeedGrid-components/navegacao-e-overlay/Visao-geral.md +82 -0
- package/seedgridKB/SeedGrid/SeedGrid-components/pacotes/Visao-geral.md +68 -0
- package/seedgridKB/SeedGrid/SeedGrid-components/pacotes/fe-commons.md +61 -0
- package/seedgridKB/SeedGrid/SeedGrid-components/pacotes/fe-core.md +140 -0
- package/seedgridKB/SeedGrid/SeedGrid-components/pacotes/fe-playground.md +112 -0
- package/seedgridKB/SeedGrid/SeedGrid-components/pacotes/fe-theme.md +97 -0
- package/seedgridKB/SeedGrid/SeedGrid-components/providers/API.md +177 -0
- package/seedgridKB/SeedGrid/SeedGrid-components/providers/Exemplos.md +332 -0
- package/seedgridKB/SeedGrid/SeedGrid-components/providers/Visao-geral.md +106 -0
- package/seedgridKB/SeedGrid/SeedGrid-components/showcase.md +70 -0
- package/seedgridKB/SeedGrid/Toolkit/agents/arquiteto.md +53 -0
- package/seedgridKB/SeedGrid/Toolkit/agents/backend-java.md +45 -0
- package/seedgridKB/SeedGrid/Toolkit/agents/backend-rust.md +43 -0
- package/seedgridKB/SeedGrid/Toolkit/agents/frontend-react.md +41 -0
- package/seedgridKB/SeedGrid/Toolkit/agents/qa.md +44 -0
- package/seedgridKB/SeedGrid/Toolkit/agents/revisor.md +40 -0
- package/seedgridKB/SeedGrid/Toolkit/references/fluxo-de-trabalho.md +78 -0
- package/seedgridKB/SeedGrid/Toolkit/references/glossario.md +15 -0
- package/seedgridKB/SeedGrid/Toolkit/references/modos-shared-native.md +27 -0
- package/seedgridKB/SeedGrid/Toolkit/rules/backend-java-seedgrid.md +54 -0
- package/seedgridKB/SeedGrid/Toolkit/rules/coordenacao.md +39 -0
- package/seedgridKB/SeedGrid/Toolkit/rules/formato-entrega.md +29 -0
- package/seedgridKB/SeedGrid/Toolkit/rules/frontend-seedgrid.md +47 -0
- package/seedgridKB/SeedGrid/Toolkit/rules/personalizacao-local.md +22 -0
- package/seedgridKB/SeedGrid/Toolkit/skills/planejar-mudanca/SKILL.md +38 -0
- package/seedgridKB/SeedGrid/Toolkit/skills/revisar-codigo/SKILL.md +33 -0
- package/seedgridKB/SeedGrid/Toolkit/skills/revisar-codigo/references/checklist.md +25 -0
- package/seedgridKB/SeedGrid/Toolkit/skills/seedgrid-backend-crud/SKILL.md +29 -0
- package/seedgridKB/SeedGrid/Toolkit/skills/seedgrid-bump/SKILL.md +26 -0
- package/seedgridKB/SeedGrid/Toolkit/skills/seedgrid-crud/SKILL.md +221 -0
- package/seedgridKB/SeedGrid/Toolkit/skills/seedgrid-crud/agents/openai.yaml +4 -0
- package/seedgridKB/SeedGrid/Toolkit/skills/seedgrid-crud/references/checklist.md +31 -0
- package/seedgridKB/SeedGrid/Toolkit/skills/seedgrid-crud/references/patterns.md +185 -0
- package/seedgridKB/SeedGrid/Toolkit/skills/seedgrid-crud/references/routing.md +66 -0
- package/seedgridKB/SeedGrid/Toolkit/skills/seedgrid-new-screen/SKILL.md +56 -0
- package/seedgridKB/SeedGrid/Toolkit/skills/seedgrid-new-screen/agents/openai.yaml +4 -0
- package/seedgridKB/SeedGrid/Toolkit/skills/seedgrid-new-screen/references/checklist.md +32 -0
- package/seedgridKB/SeedGrid/Toolkit/skills/seedgrid-new-screen/references/steps.md +114 -0
- package/seedgridKB/SeedGrid/Toolkit/skills/seedgrid-review/SKILL.md +61 -0
- package/seedgridKB/SeedGrid/Toolkit/skills/validar-mudanca/SKILL.md +29 -0
- package/seedgridKB/SeedGrid/Toolkit/templates/decisao-arquitetura.md +29 -0
- package/seedgridKB/SeedGrid/Toolkit/templates/especificacao-tarefa.md +32 -0
- package/seedgridKB/SeedGrid/Toolkit/templates/relatorio-validacao.md +30 -0
- package/seedgridKB/SeedGrid/Versoes.md +64 -0
- package/seedgridKB/SeedGrid/Visao-geral.md +35 -0
- package/seedgridKB/manifest.json +142 -0
|
@@ -0,0 +1,1172 @@
|
|
|
1
|
+
---
|
|
2
|
+
tags: [seedgrid, front, component, layout]
|
|
3
|
+
fonte: front/seedgrid-fe-components/apps/showcase/src/app/components; front/seedgrid-fe-components/packages/seedgrid-fe-components/src/layout
|
|
4
|
+
branch: main
|
|
5
|
+
commit: ad30fc11de
|
|
6
|
+
analisado-em: 2026-10-14
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
# Exemplos — layout
|
|
10
|
+
|
|
11
|
+
API: [[SeedGrid/SeedGrid-components/layout/API|Layout — API]] · Visão geral: [[SeedGrid/SeedGrid-components/layout/Visao-geral|Layout — visão geral]]
|
|
12
|
+
|
|
13
|
+
Exemplos copiados 1:1 dos arquivos `samples/*.tsx.sample` do showcase (caminhos relativos a `front/seedgrid-fe-components/`), salvo indicação. Todos foram verificados com type-check TypeScript (`strict`) contra `packages/seedgrid-fe-components/src/index.ts` em 2026-10-14 — sem erros. Classes Tailwind e ícones `lucide-react` vêm do showcase; `lucide-react` é peer dependency do pacote.
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
## SgStack
|
|
17
|
+
|
|
18
|
+
### column-row
|
|
19
|
+
|
|
20
|
+
Fonte: `apps/showcase/src/app/components/sg-stack/samples/column-row.tsx.sample`. Coluna com `gap` e linha com `justify="between"` / `align="center"`.
|
|
21
|
+
|
|
22
|
+
```tsx
|
|
23
|
+
import React from "react";
|
|
24
|
+
import { SgButton, SgStack } from "@seedgrid/fe-components";
|
|
25
|
+
|
|
26
|
+
export default function Example() {
|
|
27
|
+
return (
|
|
28
|
+
<>
|
|
29
|
+
<SgStack gap={8}>
|
|
30
|
+
<SgButton>Save</SgButton>
|
|
31
|
+
<SgButton appearance="outline">Cancelar</SgButton>
|
|
32
|
+
</SgStack>
|
|
33
|
+
<SgStack direction="row" justify="between" align="center">
|
|
34
|
+
<span>Title</span>
|
|
35
|
+
<SgButton size="sm">Confirmar</SgButton>
|
|
36
|
+
</SgStack>
|
|
37
|
+
</>
|
|
38
|
+
);
|
|
39
|
+
}
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
## SgGrid
|
|
44
|
+
|
|
45
|
+
### columns-responsivo
|
|
46
|
+
|
|
47
|
+
Fonte: `apps/showcase/src/app/components/sg-grid/samples/columns-responsivo.tsx.sample`. Colunas por breakpoint (`base`/`sm`/`lg`/`xl`) e filho `SgPanel` com `span={2}`.
|
|
48
|
+
|
|
49
|
+
```tsx
|
|
50
|
+
import React from "react";
|
|
51
|
+
import { SgGrid, SgPanel, SgStack } from "@seedgrid/fe-components";
|
|
52
|
+
|
|
53
|
+
function Card(props: { title: string; subtitle?: string }) {
|
|
54
|
+
return <SgPanel padding={12} className="rounded-lg"><SgStack gap={8}><p className="font-medium">{props.title}</p><p className="text-xs text-muted-foreground">{props.subtitle ?? "Card padrao"}</p></SgStack></SgPanel>;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
export default function Example() {
|
|
58
|
+
return (
|
|
59
|
+
<SgGrid columns={{ base: 1, sm: 2, lg: 3, xl: 4 }} gap={12}>
|
|
60
|
+
<Card title="Card 1" />
|
|
61
|
+
<Card title="Card 2" />
|
|
62
|
+
<SgPanel span={2} padding={12} className="rounded-lg"><SgStack gap={8}><p className="font-medium">Card 3 (span 2)</p><p className="text-xs text-muted-foreground">Ocupa 2 colunas.</p></SgStack></SgPanel>
|
|
63
|
+
<Card title="Card 4" />
|
|
64
|
+
<Card title="Card 5" />
|
|
65
|
+
<Card title="Card 6" />
|
|
66
|
+
</SgGrid>
|
|
67
|
+
);
|
|
68
|
+
}
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
### auto-fit-rowspan
|
|
72
|
+
|
|
73
|
+
Fonte: `apps/showcase/src/app/components/sg-grid/samples/auto-fit-rowspan.tsx.sample`. `minItemWidth` (auto-fit), `rowHeight`, `dense` e filhos com `span`/`rowSpan`.
|
|
74
|
+
|
|
75
|
+
```tsx
|
|
76
|
+
import React from "react";
|
|
77
|
+
import { SgGrid, SgPanel, SgStack } from "@seedgrid/fe-components";
|
|
78
|
+
|
|
79
|
+
function Card(props: { title: string; subtitle?: string }) {
|
|
80
|
+
return <SgPanel padding={12} className="rounded-lg"><SgStack gap={8}><p className="font-medium">{props.title}</p><p className="text-xs text-muted-foreground">{props.subtitle ?? "Card padrao"}</p></SgStack></SgPanel>;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
export default function Example() {
|
|
84
|
+
return (
|
|
85
|
+
<SgGrid minItemWidth="16rem" gap={12} rowHeight={120} dense>
|
|
86
|
+
<Card title="Card A" />
|
|
87
|
+
<SgPanel rowSpan={2} padding={12} className="rounded-lg"><SgStack gap={8}><p className="font-medium">Card B (rowSpan 2)</p><p className="text-xs text-muted-foreground">Ocupa 2 linhas do grid.</p></SgStack></SgPanel>
|
|
88
|
+
<Card title="Card C" />
|
|
89
|
+
<SgPanel span={2} padding={12} className="rounded-lg"><SgStack gap={8}><p className="font-medium">Card D (span 2)</p><p className="text-xs text-muted-foreground">Ocupa 2 colunas.</p></SgStack></SgPanel>
|
|
90
|
+
<Card title="Card E" />
|
|
91
|
+
<Card title="Card F" />
|
|
92
|
+
</SgGrid>
|
|
93
|
+
);
|
|
94
|
+
}
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
|
|
98
|
+
## SgPanel
|
|
99
|
+
|
|
100
|
+
### align-width-height
|
|
101
|
+
|
|
102
|
+
Fonte: `apps/showcase/src/app/components/sg-panel/samples/align-width-height.tsx.sample`. Docking: painéis filhos com `align` top/left/right/bottom/client; `width`/`height` numéricos são %.
|
|
103
|
+
|
|
104
|
+
```tsx
|
|
105
|
+
import React from "react";
|
|
106
|
+
import { SgPanel, SgStack } from "@seedgrid/fe-components";
|
|
107
|
+
|
|
108
|
+
export default function Example() {
|
|
109
|
+
return (
|
|
110
|
+
<SgPanel className="h-[430px] rounded-xl bg-muted/30" padding={12}>
|
|
111
|
+
<SgPanel className="h-full w-full rounded-lg bg-background p-3" contentGap={8}>
|
|
112
|
+
<SgPanel align="top" height={12} padding={10} className="rounded-md">
|
|
113
|
+
<SgStack direction="row" justify="between" align="center">
|
|
114
|
+
<span className="text-sm font-medium">Header</span>
|
|
115
|
+
<span className="rounded border border-border px-2 py-0.5 text-xs text-muted-foreground">top + height=12%</span>
|
|
116
|
+
</SgStack>
|
|
117
|
+
</SgPanel>
|
|
118
|
+
<SgPanel align="left" width={20} padding={10} className="rounded-md">
|
|
119
|
+
<SgStack gap={6}>
|
|
120
|
+
<span className="text-xs font-medium text-muted-foreground">MENU</span>
|
|
121
|
+
<SgPanel borderStyle="none" className="rounded bg-muted/40" padding={6}>Dashboard</SgPanel>
|
|
122
|
+
<SgPanel borderStyle="none" className="rounded bg-muted/40" padding={6}>Relatorios</SgPanel>
|
|
123
|
+
<SgPanel borderStyle="none" className="rounded bg-muted/40" padding={6}>Clientes</SgPanel>
|
|
124
|
+
<span className="pt-1 text-[11px] text-muted-foreground">left + width=20%</span>
|
|
125
|
+
</SgStack>
|
|
126
|
+
</SgPanel>
|
|
127
|
+
<SgPanel align="right" width="18%" padding={10} className="rounded-md">
|
|
128
|
+
<SgStack gap={6}>
|
|
129
|
+
<span className="text-xs font-medium text-muted-foreground">ACOES</span>
|
|
130
|
+
<SgPanel borderStyle="none" className="rounded bg-muted/40" padding={6}>Filtrar</SgPanel>
|
|
131
|
+
<SgPanel borderStyle="none" className="rounded bg-muted/40" padding={6}>Exportar</SgPanel>
|
|
132
|
+
<span className="pt-1 text-[11px] text-muted-foreground">right + width=18%</span>
|
|
133
|
+
</SgStack>
|
|
134
|
+
</SgPanel>
|
|
135
|
+
<SgPanel align="bottom" height="10%" padding={10} className="rounded-md">
|
|
136
|
+
<SgStack direction="row" justify="between" align="center">
|
|
137
|
+
<span className="text-sm">Footer</span>
|
|
138
|
+
<span className="rounded border border-border px-2 py-0.5 text-xs text-muted-foreground">bottom + height=10%</span>
|
|
139
|
+
</SgStack>
|
|
140
|
+
</SgPanel>
|
|
141
|
+
<SgPanel align="client" padding={10} className="rounded-md">
|
|
142
|
+
<SgStack gap={8}>
|
|
143
|
+
<span className="text-sm font-medium">Area client</span>
|
|
144
|
+
<SgPanel borderStyle="solid" className="h-24 rounded bg-muted/20" />
|
|
145
|
+
<span className="text-xs text-muted-foreground">client ocupa o restante automaticamente.</span>
|
|
146
|
+
</SgStack>
|
|
147
|
+
</SgPanel>
|
|
148
|
+
</SgPanel>
|
|
149
|
+
</SgPanel>
|
|
150
|
+
);
|
|
151
|
+
}
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
|
|
155
|
+
## SgScreen
|
|
156
|
+
|
|
157
|
+
### complete-example
|
|
158
|
+
|
|
159
|
+
Fonte: `apps/showcase/src/app/components/sg-screen/samples/complete-example.tsx.sample`. `SgScreen` não-fullscreen contendo um `SgPanel` com docking.
|
|
160
|
+
|
|
161
|
+
```tsx
|
|
162
|
+
"use client";
|
|
163
|
+
|
|
164
|
+
import React from "react";
|
|
165
|
+
import { SgScreen, SgPanel, SgStack } from "@seedgrid/fe-components";
|
|
166
|
+
|
|
167
|
+
export default function ExampleSgScreenPage() {
|
|
168
|
+
return (
|
|
169
|
+
<SgPanel className="h-[420px] rounded-xl bg-muted/30" padding={12}>
|
|
170
|
+
<SgScreen fullscreen={false} padding={10} className="rounded-lg bg-zinc-100">
|
|
171
|
+
<SgPanel className="h-full w-full" contentPadding={8} contentGap={8}>
|
|
172
|
+
<SgPanel align="top" height={12} padding={10} className="rounded-md">
|
|
173
|
+
<SgStack direction="row" justify="between" align="center">
|
|
174
|
+
<span className="text-sm font-medium">Header</span>
|
|
175
|
+
<span className="text-xs text-muted-foreground">top + height=12%</span>
|
|
176
|
+
</SgStack>
|
|
177
|
+
</SgPanel>
|
|
178
|
+
|
|
179
|
+
<SgPanel align="left" width={20} padding={10} className="rounded-md">
|
|
180
|
+
<SgStack gap={6}>
|
|
181
|
+
<span className="text-xs font-medium text-muted-foreground">MENU</span>
|
|
182
|
+
<SgPanel borderStyle="none" className="rounded bg-muted/40" padding={6}>Dashboard</SgPanel>
|
|
183
|
+
<SgPanel borderStyle="none" className="rounded bg-muted/40" padding={6}>Relatorios</SgPanel>
|
|
184
|
+
<SgPanel borderStyle="none" className="rounded bg-muted/40" padding={6}>Clientes</SgPanel>
|
|
185
|
+
</SgStack>
|
|
186
|
+
</SgPanel>
|
|
187
|
+
|
|
188
|
+
<SgPanel align="right" width="18%" padding={10} className="rounded-md">
|
|
189
|
+
<SgStack gap={6}>
|
|
190
|
+
<span className="text-xs font-medium text-muted-foreground">ACOES</span>
|
|
191
|
+
<SgPanel borderStyle="none" className="rounded bg-muted/40" padding={6}>Filtrar</SgPanel>
|
|
192
|
+
<SgPanel borderStyle="none" className="rounded bg-muted/40" padding={6}>Exportar</SgPanel>
|
|
193
|
+
</SgStack>
|
|
194
|
+
</SgPanel>
|
|
195
|
+
|
|
196
|
+
<SgPanel align="bottom" height="10%" padding={10} className="rounded-md">
|
|
197
|
+
<SgStack direction="row" justify="between" align="center">
|
|
198
|
+
<span className="text-sm">Footer</span>
|
|
199
|
+
<span className="text-xs text-muted-foreground">bottom + height=10%</span>
|
|
200
|
+
</SgStack>
|
|
201
|
+
</SgPanel>
|
|
202
|
+
|
|
203
|
+
<SgPanel align="client" padding={10} className="rounded-md">
|
|
204
|
+
<SgStack gap={8}>
|
|
205
|
+
<span className="text-sm font-medium">Area client</span>
|
|
206
|
+
<SgPanel borderStyle="solid" className="h-24 rounded bg-muted/20" />
|
|
207
|
+
<span className="text-xs text-muted-foreground">
|
|
208
|
+
Esta area ocupa todo o espaco restante.
|
|
209
|
+
</span>
|
|
210
|
+
</SgStack>
|
|
211
|
+
</SgPanel>
|
|
212
|
+
</SgPanel>
|
|
213
|
+
</SgScreen>
|
|
214
|
+
</SgPanel>
|
|
215
|
+
);
|
|
216
|
+
}
|
|
217
|
+
```
|
|
218
|
+
|
|
219
|
+
|
|
220
|
+
## SgGroupBox
|
|
221
|
+
|
|
222
|
+
### basico
|
|
223
|
+
|
|
224
|
+
Fonte: `apps/showcase/src/app/components/sg-group-box/samples/basico.tsx.sample`. Agrupamento com título (`fieldset`/`legend`).
|
|
225
|
+
|
|
226
|
+
```tsx
|
|
227
|
+
import { SgGroupBox } from "@seedgrid/fe-components";
|
|
228
|
+
|
|
229
|
+
export default function Example() {
|
|
230
|
+
return (
|
|
231
|
+
<SgGroupBox
|
|
232
|
+
title="Dados pessoais"
|
|
233
|
+
style={{ boxShadow: "inset 0 0 0 1px rgba(59, 130, 246, 0.2)" }}
|
|
234
|
+
>
|
|
235
|
+
<div className="grid gap-3 sm:grid-cols-2">
|
|
236
|
+
<div>Campo 1</div>
|
|
237
|
+
<div>Campo 2</div>
|
|
238
|
+
</div>
|
|
239
|
+
</SgGroupBox>
|
|
240
|
+
);
|
|
241
|
+
}
|
|
242
|
+
```
|
|
243
|
+
|
|
244
|
+
|
|
245
|
+
## SgCard
|
|
246
|
+
|
|
247
|
+
### basico
|
|
248
|
+
|
|
249
|
+
Fonte: `apps/showcase/src/app/components/sg-card/samples/basico.tsx.sample`. Título, descrição, corpo e rodapé.
|
|
250
|
+
|
|
251
|
+
```tsx
|
|
252
|
+
import React from "react";
|
|
253
|
+
import { SgCard } from "@seedgrid/fe-components";
|
|
254
|
+
|
|
255
|
+
export default function Example() {
|
|
256
|
+
return (
|
|
257
|
+
<SgCard
|
|
258
|
+
title="Resumo financeiro"
|
|
259
|
+
description="Visao consolidada do dia"
|
|
260
|
+
footer={
|
|
261
|
+
<div className="flex items-center justify-between text-xs text-muted-foreground">
|
|
262
|
+
<span>Atualizado agora</span>
|
|
263
|
+
<span>Ultima sincronizacao</span>
|
|
264
|
+
</div>
|
|
265
|
+
}
|
|
266
|
+
>
|
|
267
|
+
<div className="space-y-2 text-sm">
|
|
268
|
+
<div className="flex items-center justify-between">
|
|
269
|
+
<span className="text-muted-foreground">Receita</span>
|
|
270
|
+
<span className="font-semibold">R$ 12.400</span>
|
|
271
|
+
</div>
|
|
272
|
+
<div className="flex items-center justify-between">
|
|
273
|
+
<span className="text-muted-foreground">Pedidos</span>
|
|
274
|
+
<span className="font-semibold">83</span>
|
|
275
|
+
</div>
|
|
276
|
+
</div>
|
|
277
|
+
</SgCard>
|
|
278
|
+
);
|
|
279
|
+
}
|
|
280
|
+
```
|
|
281
|
+
|
|
282
|
+
### colapsavel
|
|
283
|
+
|
|
284
|
+
Fonte: `apps/showcase/src/app/components/sg-card/samples/colapsavel.tsx.sample`. `collapsible` com `defaultOpen` e alinhamento do botão de colapso.
|
|
285
|
+
|
|
286
|
+
```tsx
|
|
287
|
+
import React from "react";
|
|
288
|
+
import { SgButton, SgCard } from "@seedgrid/fe-components";
|
|
289
|
+
|
|
290
|
+
export default function Example() {
|
|
291
|
+
return (
|
|
292
|
+
<>
|
|
293
|
+
<SgCard
|
|
294
|
+
title="Painel recolhido"
|
|
295
|
+
description="Abre sob demanda"
|
|
296
|
+
collapsible
|
|
297
|
+
defaultOpen={false}
|
|
298
|
+
collapseToggleAlign="right"
|
|
299
|
+
collapseIconSize={20}
|
|
300
|
+
footer={<div className="flex justify-end"><SgButton size="sm">Acao</SgButton></div>}
|
|
301
|
+
>
|
|
302
|
+
<div className="text-sm text-muted-foreground">Conteudo recolhivel do card.</div>
|
|
303
|
+
</SgCard>
|
|
304
|
+
|
|
305
|
+
<SgCard
|
|
306
|
+
title="Painel aberto"
|
|
307
|
+
description="Comeca expandido"
|
|
308
|
+
collapsible
|
|
309
|
+
defaultOpen
|
|
310
|
+
collapseToggleAlign="right"
|
|
311
|
+
collapseIconSize={20}
|
|
312
|
+
footer={
|
|
313
|
+
<div className="flex items-center justify-between text-xs text-muted-foreground">
|
|
314
|
+
<span>128 itens</span>
|
|
315
|
+
<span>R$ 9.820</span>
|
|
316
|
+
</div>
|
|
317
|
+
}
|
|
318
|
+
>
|
|
319
|
+
<div className="space-y-2 text-sm">
|
|
320
|
+
<div className="flex items-center justify-between">
|
|
321
|
+
<span className="text-muted-foreground">Tickets</span>
|
|
322
|
+
<span className="font-semibold">128</span>
|
|
323
|
+
</div>
|
|
324
|
+
<div className="flex items-center justify-between">
|
|
325
|
+
<span className="text-muted-foreground">Valor</span>
|
|
326
|
+
<span className="font-semibold">R$ 9.820</span>
|
|
327
|
+
</div>
|
|
328
|
+
</div>
|
|
329
|
+
</SgCard>
|
|
330
|
+
</>
|
|
331
|
+
);
|
|
332
|
+
}
|
|
333
|
+
```
|
|
334
|
+
|
|
335
|
+
### draggable-persistence
|
|
336
|
+
|
|
337
|
+
Fonte: `apps/showcase/src/app/components/sg-card/samples/draggable-persistence.tsx.sample`. Arraste pelo cabeçalho com posição persistida via `SgEnvironmentProvider` (`dragPersistKey`).
|
|
338
|
+
|
|
339
|
+
```tsx
|
|
340
|
+
import React from "react";
|
|
341
|
+
import { SgCard, SgEnvironmentProvider } from "@seedgrid/fe-components";
|
|
342
|
+
|
|
343
|
+
export default function Example() {
|
|
344
|
+
return (
|
|
345
|
+
<SgEnvironmentProvider
|
|
346
|
+
value={{
|
|
347
|
+
namespaceProvider: { getNamespace: () => "showcase" },
|
|
348
|
+
persistence: { scope: "app:showcase", mode: "fallback", stateVersion: 1 }
|
|
349
|
+
}}
|
|
350
|
+
>
|
|
351
|
+
<div className="relative h-[300px] overflow-hidden rounded-xl border border-dashed border-border/70 bg-muted/20 p-2">
|
|
352
|
+
<SgCard
|
|
353
|
+
id="sg-card-draggable-demo"
|
|
354
|
+
draggable
|
|
355
|
+
defaultPosition={{ x: 16, y: 16 }}
|
|
356
|
+
dragPersistKey="sg-card-draggable-demo"
|
|
357
|
+
title="Drag me by the title bar"
|
|
358
|
+
description="Try moving and refreshing this page."
|
|
359
|
+
collapsible
|
|
360
|
+
collapseToggleAlign="right"
|
|
361
|
+
collapseIconSize={20}
|
|
362
|
+
bgColor="#ffffff"
|
|
363
|
+
footer={<div className="text-xs text-muted-foreground">Persisted drag position.</div>}
|
|
364
|
+
>
|
|
365
|
+
<div className="space-y-2 text-sm">
|
|
366
|
+
<div className="flex items-center justify-between">
|
|
367
|
+
<span className="text-muted-foreground">Status</span>
|
|
368
|
+
<span className="font-semibold text-emerald-600">Online</span>
|
|
369
|
+
</div>
|
|
370
|
+
<div className="flex items-center justify-between">
|
|
371
|
+
<span className="text-muted-foreground">Region</span>
|
|
372
|
+
<span className="font-semibold">Sao Paulo</span>
|
|
373
|
+
</div>
|
|
374
|
+
</div>
|
|
375
|
+
</SgCard>
|
|
376
|
+
</div>
|
|
377
|
+
</SgEnvironmentProvider>
|
|
378
|
+
);
|
|
379
|
+
}
|
|
380
|
+
```
|
|
381
|
+
|
|
382
|
+
|
|
383
|
+
## SgAccordion
|
|
384
|
+
|
|
385
|
+
### basico-vertical-single
|
|
386
|
+
|
|
387
|
+
Fonte: `apps/showcase/src/app/components/sg-accordion/samples/basico-vertical-single.tsx.sample`. Uso mínimo: só `items` (abre o primeiro por padrão).
|
|
388
|
+
|
|
389
|
+
```tsx
|
|
390
|
+
import * as React from "react";
|
|
391
|
+
import { SgAccordion, type SgAccordionItem } from "@seedgrid/fe-components";
|
|
392
|
+
|
|
393
|
+
const items: SgAccordionItem[] = [
|
|
394
|
+
{ id: "personal", title: "Dados pessoais", content: <p className="text-sm">Nome, email e telefone.</p> },
|
|
395
|
+
{ id: "address", title: "Endereco", content: <p className="text-sm">Rua, cidade e CEP.</p> },
|
|
396
|
+
{ id: "billing", title: "Faturamento", content: <p className="text-sm">Cobranca e historico.</p> }
|
|
397
|
+
];
|
|
398
|
+
|
|
399
|
+
export default function Example() {
|
|
400
|
+
return <SgAccordion items={items} />;
|
|
401
|
+
}
|
|
402
|
+
```
|
|
403
|
+
|
|
404
|
+
### controlado-por-estado
|
|
405
|
+
|
|
406
|
+
Fonte: `apps/showcase/src/app/components/sg-accordion/samples/controlado-por-estado.tsx.sample`. Modo controlado com `activeIndex` + `onActiveIndexChange`.
|
|
407
|
+
|
|
408
|
+
```tsx
|
|
409
|
+
import * as React from "react";
|
|
410
|
+
import { SgAccordion, SgButton, type SgAccordionItem } from "@seedgrid/fe-components";
|
|
411
|
+
|
|
412
|
+
const items: SgAccordionItem[] = [
|
|
413
|
+
{ id: "personal", title: "Dados pessoais", content: <p className="text-sm">Conteudo 1</p> },
|
|
414
|
+
{ id: "address", title: "Endereco", content: <p className="text-sm">Conteudo 2</p> },
|
|
415
|
+
{ id: "billing", title: "Faturamento", content: <p className="text-sm">Conteudo 3</p> }
|
|
416
|
+
];
|
|
417
|
+
|
|
418
|
+
export default function Example() {
|
|
419
|
+
const [activeIndex, setActiveIndex] = React.useState<number[]>([0]);
|
|
420
|
+
|
|
421
|
+
return (
|
|
422
|
+
<div className="space-y-3">
|
|
423
|
+
<SgAccordion items={items} activeIndex={activeIndex} onActiveIndexChange={setActiveIndex} />
|
|
424
|
+
<div className="flex flex-wrap gap-2">
|
|
425
|
+
<SgButton size="sm" appearance="outline" onClick={() => setActiveIndex([0])}>Abrir 1</SgButton>
|
|
426
|
+
<SgButton size="sm" appearance="outline" onClick={() => setActiveIndex([1])}>Abrir 2</SgButton>
|
|
427
|
+
<SgButton size="sm" appearance="outline" onClick={() => setActiveIndex([2])}>Abrir 3</SgButton>
|
|
428
|
+
<SgButton size="sm" appearance="outline" onClick={() => setActiveIndex([])}>Fechar todos</SgButton>
|
|
429
|
+
</div>
|
|
430
|
+
</div>
|
|
431
|
+
);
|
|
432
|
+
}
|
|
433
|
+
```
|
|
434
|
+
|
|
435
|
+
|
|
436
|
+
## SgPageControl
|
|
437
|
+
|
|
438
|
+
### basico
|
|
439
|
+
|
|
440
|
+
Fonte: `apps/showcase/src/app/components/sg-page-control/samples/basico.tsx.sample`. Abas declaradas com `SgPageControlPage` e página inicial por id.
|
|
441
|
+
|
|
442
|
+
```tsx
|
|
443
|
+
import React from "react";
|
|
444
|
+
import { Receipt, ShieldCheck, UserRound } from "lucide-react";
|
|
445
|
+
import { SgPageControl, SgPageControlPage } from "@seedgrid/fe-components";
|
|
446
|
+
|
|
447
|
+
export default function Example() {
|
|
448
|
+
return (
|
|
449
|
+
<SgPageControl
|
|
450
|
+
defaultActivePageId="registration"
|
|
451
|
+
style={{ border: "1px solid rgba(59, 130, 246, 0.25)", borderRadius: 12 }}
|
|
452
|
+
>
|
|
453
|
+
<SgPageControlPage
|
|
454
|
+
id="registration"
|
|
455
|
+
title="Registration"
|
|
456
|
+
icon={<UserRound className="size-4" />}
|
|
457
|
+
style={{ backgroundColor: "rgba(59, 130, 246, 0.08)" }}
|
|
458
|
+
>
|
|
459
|
+
Registration content
|
|
460
|
+
</SgPageControlPage>
|
|
461
|
+
<SgPageControlPage id="fiscal" title="Fiscal" icon={<Receipt className="size-4" />}>
|
|
462
|
+
Fiscal content
|
|
463
|
+
</SgPageControlPage>
|
|
464
|
+
<SgPageControlPage id="access" title="Access" icon={<ShieldCheck className="size-4" />}>
|
|
465
|
+
Access content
|
|
466
|
+
</SgPageControlPage>
|
|
467
|
+
</SgPageControl>
|
|
468
|
+
);
|
|
469
|
+
}
|
|
470
|
+
```
|
|
471
|
+
|
|
472
|
+
### controle-externo
|
|
473
|
+
|
|
474
|
+
Fonte: `apps/showcase/src/app/components/sg-page-control/samples/controle-externo.tsx.sample`. Controle externo por `activePageId` e estilo `pills`.
|
|
475
|
+
|
|
476
|
+
```tsx
|
|
477
|
+
import React from "react";
|
|
478
|
+
import { FolderKanban, Receipt, ShieldCheck, UserRound } from "lucide-react";
|
|
479
|
+
import { SgButton, SgPageControl, SgPageControlPage } from "@seedgrid/fe-components";
|
|
480
|
+
|
|
481
|
+
export default function Example() {
|
|
482
|
+
const [activePageId, setActivePageId] = React.useState("registration");
|
|
483
|
+
|
|
484
|
+
return (
|
|
485
|
+
<div className="space-y-4">
|
|
486
|
+
<div className="flex flex-wrap gap-2">
|
|
487
|
+
<SgButton size="sm" appearance="outline" onClick={() => setActivePageId("registration")}>Go to Registration</SgButton>
|
|
488
|
+
<SgButton size="sm" appearance="outline" onClick={() => setActivePageId("fiscal")}>Go to Fiscal</SgButton>
|
|
489
|
+
<SgButton size="sm" appearance="outline" onClick={() => setActivePageId("access")}>Go to Access</SgButton>
|
|
490
|
+
<SgButton size="sm" appearance="outline" onClick={() => setActivePageId("integrations")}>Go to Integrations</SgButton>
|
|
491
|
+
</div>
|
|
492
|
+
|
|
493
|
+
<SgPageControl activePageId={activePageId} onActivePageIdChange={(pageId) => setActivePageId(pageId)} pageControlStyle="pills">
|
|
494
|
+
<SgPageControlPage id="registration" title="Registration" icon={<UserRound className="size-4" />}>Registration content</SgPageControlPage>
|
|
495
|
+
<SgPageControlPage id="fiscal" title="Fiscal" icon={<Receipt className="size-4" />}>Fiscal content</SgPageControlPage>
|
|
496
|
+
<SgPageControlPage id="access" title="Access" icon={<ShieldCheck className="size-4" />}>Access content</SgPageControlPage>
|
|
497
|
+
<SgPageControlPage id="integrations" title="Integrations" icon={<FolderKanban className="size-4" />}>Integrations content</SgPageControlPage>
|
|
498
|
+
</SgPageControl>
|
|
499
|
+
</div>
|
|
500
|
+
);
|
|
501
|
+
}
|
|
502
|
+
```
|
|
503
|
+
|
|
504
|
+
|
|
505
|
+
## SgExpandablePanel
|
|
506
|
+
|
|
507
|
+
### overlay-comportamento
|
|
508
|
+
|
|
509
|
+
Fonte: `apps/showcase/src/app/components/sg-expandable-panel/samples/overlay-comportamento.tsx.sample`. Overlay com foco preso, Esc, clique fora, backdrop e resize.
|
|
510
|
+
|
|
511
|
+
```tsx
|
|
512
|
+
import React from "react";
|
|
513
|
+
import { SgButton, SgExpandablePanel } from "@seedgrid/fe-components";
|
|
514
|
+
|
|
515
|
+
export default function Example() {
|
|
516
|
+
const [open, setOpen] = React.useState(false);
|
|
517
|
+
|
|
518
|
+
return (
|
|
519
|
+
<>
|
|
520
|
+
<div className="flex flex-wrap gap-2">
|
|
521
|
+
<SgButton onClick={() => setOpen(true)}>Abrir drawer</SgButton>
|
|
522
|
+
</div>
|
|
523
|
+
|
|
524
|
+
<SgExpandablePanel
|
|
525
|
+
mode="overlay"
|
|
526
|
+
expandTo="left"
|
|
527
|
+
placement="center"
|
|
528
|
+
open={open}
|
|
529
|
+
onOpenChange={setOpen}
|
|
530
|
+
size={{ default: 360, min: 260, max: 640 }}
|
|
531
|
+
resizable
|
|
532
|
+
closeOnEsc
|
|
533
|
+
closeOnOutsideClick
|
|
534
|
+
trapFocus
|
|
535
|
+
showBackdrop
|
|
536
|
+
handle={<div className="mx-auto h-1.5 w-12 rounded-full bg-muted-foreground/35" />}
|
|
537
|
+
header={<div className="font-medium">Drawer com foco preso</div>}
|
|
538
|
+
footer={
|
|
539
|
+
<div className="flex justify-end">
|
|
540
|
+
<SgButton size="sm" onClick={() => setOpen(false)}>Fechar</SgButton>
|
|
541
|
+
</div>
|
|
542
|
+
}
|
|
543
|
+
>
|
|
544
|
+
<div className="space-y-2 text-sm">
|
|
545
|
+
<p>Props: placement, closeOnEsc, closeOnOutsideClick, trapFocus e showBackdrop.</p>
|
|
546
|
+
<label className="flex items-center gap-2">
|
|
547
|
+
<input type="checkbox" defaultChecked />
|
|
548
|
+
<span>Somente ativos</span>
|
|
549
|
+
</label>
|
|
550
|
+
</div>
|
|
551
|
+
</SgExpandablePanel>
|
|
552
|
+
</>
|
|
553
|
+
);
|
|
554
|
+
}
|
|
555
|
+
```
|
|
556
|
+
|
|
557
|
+
### inline-controlado-resize
|
|
558
|
+
|
|
559
|
+
Fonte: `apps/showcase/src/app/components/sg-expandable-panel/samples/inline-controlado-resize.tsx.sample`. Inline controlado com `onSizeChange`.
|
|
560
|
+
|
|
561
|
+
```tsx
|
|
562
|
+
import React from "react";
|
|
563
|
+
import { SgButton, SgExpandablePanel } from "@seedgrid/fe-components";
|
|
564
|
+
|
|
565
|
+
export default function Example() {
|
|
566
|
+
const [open, setOpen] = React.useState(true);
|
|
567
|
+
const [size, setSize] = React.useState<number | string>(320);
|
|
568
|
+
|
|
569
|
+
return (
|
|
570
|
+
<div className="h-[360px] overflow-hidden rounded-lg border border-border">
|
|
571
|
+
<div className="flex h-full">
|
|
572
|
+
<div className="flex-1 space-y-3 p-4">
|
|
573
|
+
<h3 className="text-base font-semibold">Area principal</h3>
|
|
574
|
+
<p className="text-sm text-muted-foreground">Exemplo inline controlado com resize.</p>
|
|
575
|
+
<div className="flex flex-wrap gap-2">
|
|
576
|
+
<SgButton size="sm" onClick={() => setOpen((v) => !v)}>
|
|
577
|
+
{open ? "Fechar inspector" : "Abrir inspector"}
|
|
578
|
+
</SgButton>
|
|
579
|
+
</div>
|
|
580
|
+
<p className="text-xs text-muted-foreground">Largura atual: {String(size)}px</p>
|
|
581
|
+
</div>
|
|
582
|
+
|
|
583
|
+
<SgExpandablePanel
|
|
584
|
+
mode="inline"
|
|
585
|
+
expandTo="left"
|
|
586
|
+
open={open}
|
|
587
|
+
onOpenChange={setOpen}
|
|
588
|
+
size={{ default: 320, min: 240, max: 560 }}
|
|
589
|
+
resizable
|
|
590
|
+
onSizeChange={setSize}
|
|
591
|
+
header={<div className="font-medium">Inspector</div>}
|
|
592
|
+
footer={<div className="text-xs text-muted-foreground">Rodape inline</div>}
|
|
593
|
+
>
|
|
594
|
+
<div className="space-y-3 text-sm">
|
|
595
|
+
<p>Conteudo do inspector.</p>
|
|
596
|
+
<p>Props: open, onOpenChange, size, resizable, onSizeChange.</p>
|
|
597
|
+
</div>
|
|
598
|
+
</SgExpandablePanel>
|
|
599
|
+
</div>
|
|
600
|
+
</div>
|
|
601
|
+
);
|
|
602
|
+
}
|
|
603
|
+
```
|
|
604
|
+
|
|
605
|
+
|
|
606
|
+
## SgCarousel
|
|
607
|
+
|
|
608
|
+
### layout-carousel-autoplay
|
|
609
|
+
|
|
610
|
+
Autoplay com `onIndexChange`. **Composto** a partir de `apps/showcase/src/app/components/sg-carousel/samples/auto-play.tsx.sample` e `com-callbacks.tsx.sample` (que no showcase são fragmentos JSX) mais a função `createCarouselItems` de `sg-carousel/page.tsx` (3 imagens em vez de 6).
|
|
611
|
+
|
|
612
|
+
```tsx
|
|
613
|
+
import React from "react";
|
|
614
|
+
import { SgCarousel, SgGrid } from "@seedgrid/fe-components";
|
|
615
|
+
|
|
616
|
+
const sampleImages = [
|
|
617
|
+
{ id: 1, title: "Item 1", url: "https://picsum.photos/1200/700?random=101" },
|
|
618
|
+
{ id: 2, title: "Item 2", url: "https://picsum.photos/1200/700?random=102" },
|
|
619
|
+
{ id: 3, title: "Item 3", url: "https://picsum.photos/1200/700?random=103" }
|
|
620
|
+
];
|
|
621
|
+
|
|
622
|
+
const createCarouselItems = (items = sampleImages) =>
|
|
623
|
+
items.map((item) => (
|
|
624
|
+
<div key={item.id} className="relative h-full overflow-hidden rounded-lg text-white shadow-lg">
|
|
625
|
+
<img src={item.url} alt={item.title} loading="lazy" className="h-full w-full object-cover" />
|
|
626
|
+
<div className="pointer-events-none absolute inset-0 bg-black/35" />
|
|
627
|
+
<SgGrid columns={1} justify="center" align="center" className="absolute inset-0">
|
|
628
|
+
<div className="text-center">
|
|
629
|
+
<h3 className="text-3xl font-bold">{item.title}</h3>
|
|
630
|
+
<p className="mt-2 text-sm opacity-90">Slide {item.id}</p>
|
|
631
|
+
</div>
|
|
632
|
+
</SgGrid>
|
|
633
|
+
</div>
|
|
634
|
+
));
|
|
635
|
+
|
|
636
|
+
export default function Example() {
|
|
637
|
+
const [activeIndex, setActiveIndex] = React.useState(0);
|
|
638
|
+
return (
|
|
639
|
+
<div className="space-y-2">
|
|
640
|
+
<div className="h-64">
|
|
641
|
+
<SgCarousel
|
|
642
|
+
items={createCarouselItems()}
|
|
643
|
+
numVisible={1}
|
|
644
|
+
autoPlay
|
|
645
|
+
autoPlayInterval={2000}
|
|
646
|
+
orientation="horizontal"
|
|
647
|
+
height="100%"
|
|
648
|
+
onIndexChange={setActiveIndex}
|
|
649
|
+
/>
|
|
650
|
+
</div>
|
|
651
|
+
<p className="text-sm">Índice ativo: {activeIndex}</p>
|
|
652
|
+
</div>
|
|
653
|
+
);
|
|
654
|
+
}
|
|
655
|
+
```
|
|
656
|
+
|
|
657
|
+
|
|
658
|
+
## SgBreadcrumb
|
|
659
|
+
|
|
660
|
+
### basico
|
|
661
|
+
|
|
662
|
+
Fonte: `apps/showcase/src/app/components/sg-breadcrumb/samples/basico.tsx.sample`. Itens com ícone, separador `chevron` e ícone de início.
|
|
663
|
+
|
|
664
|
+
```tsx
|
|
665
|
+
import React from "react";
|
|
666
|
+
import { Box, Building2, FilePenLine, Layers3 } from "lucide-react";
|
|
667
|
+
import { SgBreadcrumb, type SgBreadcrumbItem } from "@seedgrid/fe-components";
|
|
668
|
+
|
|
669
|
+
const items: SgBreadcrumbItem[] = [
|
|
670
|
+
{ id: "modules", label: "Modules", href: "/modules", icon: <Layers3 className="size-4" /> },
|
|
671
|
+
{ id: "registrations", label: "Registrations", href: "/modules/registrations", icon: <Building2 className="size-4" /> },
|
|
672
|
+
{ id: "products", label: "Products", href: "/modules/registrations/products", icon: <Box className="size-4" /> },
|
|
673
|
+
{ id: "edit", label: "Edit", icon: <FilePenLine className="size-4" /> }
|
|
674
|
+
];
|
|
675
|
+
|
|
676
|
+
export default function Example() {
|
|
677
|
+
return <SgBreadcrumb items={items} separator="chevron" showHomeIcon />;
|
|
678
|
+
}
|
|
679
|
+
```
|
|
680
|
+
|
|
681
|
+
### overflow
|
|
682
|
+
|
|
683
|
+
Fonte: `apps/showcase/src/app/components/sg-breadcrumb/samples/overflow.tsx.sample`. `maxItems` com colapso e `overflowBehavior="scroll"`.
|
|
684
|
+
|
|
685
|
+
```tsx
|
|
686
|
+
import React from "react";
|
|
687
|
+
import { SgBreadcrumb, type SgBreadcrumbItem } from "@seedgrid/fe-components";
|
|
688
|
+
|
|
689
|
+
const longItems: SgBreadcrumbItem[] = [
|
|
690
|
+
{ id: "home", label: "Home", href: "/" },
|
|
691
|
+
{ id: "admin", label: "Admin", href: "/admin" },
|
|
692
|
+
{ id: "tenant", label: "Multi Tenancy", href: "/admin/tenant" },
|
|
693
|
+
{ id: "billing", label: "Billing", href: "/admin/tenant/billing" },
|
|
694
|
+
{ id: "plans", label: "Subscription", href: "/admin/tenant/billing/subscription" },
|
|
695
|
+
{ id: "edit", label: "Edit plan" }
|
|
696
|
+
];
|
|
697
|
+
|
|
698
|
+
export default function Example() {
|
|
699
|
+
return (
|
|
700
|
+
<div className="space-y-4">
|
|
701
|
+
<SgBreadcrumb items={longItems} maxItems={4} overflowBehavior="collapse" separator="slash" />
|
|
702
|
+
<div className="max-w-[360px] rounded-lg border border-border p-2">
|
|
703
|
+
<SgBreadcrumb items={longItems} overflowBehavior="scroll" separator="dot" />
|
|
704
|
+
</div>
|
|
705
|
+
</div>
|
|
706
|
+
);
|
|
707
|
+
}
|
|
708
|
+
```
|
|
709
|
+
|
|
710
|
+
|
|
711
|
+
## SgMenu
|
|
712
|
+
|
|
713
|
+
### sidebar-fixa
|
|
714
|
+
|
|
715
|
+
Fonte: `apps/showcase/src/app/components/sg-menu/samples/sidebar-fixa.tsx.sample`. Sidebar recolhível controlada, busca, marca, usuário e `onNavigate`.
|
|
716
|
+
|
|
717
|
+
```tsx
|
|
718
|
+
import React from "react";
|
|
719
|
+
import { ClipboardList, Home, LayoutGrid, Search, Settings, Users } from "lucide-react";
|
|
720
|
+
import { SgMenu, type SgMenuNode } from "@seedgrid/fe-components";
|
|
721
|
+
|
|
722
|
+
const MENU: SgMenuNode[] = [
|
|
723
|
+
{ id: "dashboard", label: "Dashboard", url: "/dashboard", icon: <Home className="size-4" /> },
|
|
724
|
+
{ id: "customers", label: "Customers", icon: <Users className="size-4" />, children: [{ id: "customers-new", label: "New", icon: <LayoutGrid className="size-4" /> }, { id: "customers-reports", label: "Reports", icon: <ClipboardList className="size-4" /> }] },
|
|
725
|
+
{ id: "orders", label: "Orders", icon: <LayoutGrid className="size-4" />, children: [{ id: "orders-sales", label: "Sales", icon: <Search className="size-4" /> }] },
|
|
726
|
+
{ id: "profile", label: "Profile", url: "/profile", icon: <Settings className="size-4" /> }
|
|
727
|
+
];
|
|
728
|
+
|
|
729
|
+
const USER_MENU: SgMenuNode[] = [{ id: "perfil", label: "My profile", onClick: () => {} }, { id: "logout", label: "Sign out", onClick: () => {} }];
|
|
730
|
+
|
|
731
|
+
export default function Example() {
|
|
732
|
+
const [activeId, setActiveId] = React.useState("dashboard");
|
|
733
|
+
const [collapsed, setCollapsed] = React.useState(false);
|
|
734
|
+
return (
|
|
735
|
+
<div className="h-[460px] overflow-hidden rounded-lg border border-border">
|
|
736
|
+
<div className="flex h-full">
|
|
737
|
+
<SgMenu menu={MENU} selection={{ activeId }} menuStyle="sidebar" mode="accordion" collapsed={collapsed} onCollapsedChange={setCollapsed} showCollapseButton search={{ enabled: true, placeholder: "Search module..." }} brand={{ title: "SeedGrid ERP" }} user={{ name: "Lucia Souza", subtitle: "Finance" }} userMenu={USER_MENU} onNavigate={(node) => setActiveId(node.id)} />
|
|
738
|
+
<div className="flex-1 space-y-3 p-4"><h3 className="text-base font-semibold">Main content</h3><p className="text-sm text-muted-foreground">Active item: <span className="font-medium text-foreground">{activeId}</span></p></div>
|
|
739
|
+
</div>
|
|
740
|
+
</div>
|
|
741
|
+
);
|
|
742
|
+
}
|
|
743
|
+
```
|
|
744
|
+
|
|
745
|
+
### drawer-mobile
|
|
746
|
+
|
|
747
|
+
Fonte: `apps/showcase/src/app/components/sg-menu/samples/drawer-mobile.tsx.sample`. Drawer controlado (`open`/`onOpenChange`) com pin.
|
|
748
|
+
|
|
749
|
+
```tsx
|
|
750
|
+
import React from "react";
|
|
751
|
+
import { ClipboardList, Home, LayoutGrid, Search, Settings, Users } from "lucide-react";
|
|
752
|
+
import { SgButton, SgMenu, type SgMenuNode } from "@seedgrid/fe-components";
|
|
753
|
+
|
|
754
|
+
const MENU: SgMenuNode[] = [
|
|
755
|
+
{ id: "dashboard", label: "Dashboard", url: "/dashboard", icon: <Home className="size-4" /> },
|
|
756
|
+
{ id: "customers", label: "Customers", icon: <Users className="size-4" />, children: [{ id: "customers-new", label: "New", icon: <LayoutGrid className="size-4" /> }, { id: "customers-reports", label: "Reports", icon: <ClipboardList className="size-4" /> }] },
|
|
757
|
+
{ id: "orders", label: "Orders", icon: <LayoutGrid className="size-4" />, children: [{ id: "orders-sales", label: "Sales", icon: <Search className="size-4" /> }] },
|
|
758
|
+
{ id: "profile", label: "Profile", url: "/profile", icon: <Settings className="size-4" /> }
|
|
759
|
+
];
|
|
760
|
+
|
|
761
|
+
export default function Example() {
|
|
762
|
+
const [activeId, setActiveId] = React.useState("dashboard");
|
|
763
|
+
const [drawerOpen, setDrawerOpen] = React.useState(false);
|
|
764
|
+
const [drawerPinned, setDrawerPinned] = React.useState(false);
|
|
765
|
+
return (
|
|
766
|
+
<>
|
|
767
|
+
<div className="flex flex-wrap gap-2">
|
|
768
|
+
<SgButton onClick={() => setDrawerOpen(true)}>Open mobile menu</SgButton>
|
|
769
|
+
<SgButton appearance="outline" onClick={() => setDrawerPinned((v) => !v)}>{drawerPinned ? "Unpin drawer" : "Pin drawer"}</SgButton>
|
|
770
|
+
</div>
|
|
771
|
+
<SgMenu menu={MENU} selection={{ activeId }} menuStyle="drawer" open={drawerOpen} onOpenChange={setDrawerOpen} pinned={drawerPinned} onPinnedChange={setDrawerPinned} showPinButton closeOnNavigate search={{ enabled: true, placeholder: "Search..." }} brand={{ title: "SeedGrid ERP" }} onNavigate={(node) => setActiveId(node.id)} />
|
|
772
|
+
</>
|
|
773
|
+
);
|
|
774
|
+
}
|
|
775
|
+
```
|
|
776
|
+
|
|
777
|
+
|
|
778
|
+
## SgTreeView
|
|
779
|
+
|
|
780
|
+
### basico
|
|
781
|
+
|
|
782
|
+
Fonte: `apps/showcase/src/app/components/sg-tree-view/samples/basico.tsx.sample`. Checkboxes controlados, busca e leitura via `SgTreeViewRef`.
|
|
783
|
+
|
|
784
|
+
```tsx
|
|
785
|
+
import React from "react";
|
|
786
|
+
import { BarChart3, FileText, Shield, Users } from "lucide-react";
|
|
787
|
+
import { SgCard, SgTreeView, type SgTreeNode, type SgTreeViewRef } from "@seedgrid/fe-components";
|
|
788
|
+
|
|
789
|
+
const nodes: SgTreeNode[] = [
|
|
790
|
+
{
|
|
791
|
+
id: "root",
|
|
792
|
+
label: "Admin",
|
|
793
|
+
icon: <Shield className="h-4 w-4" />,
|
|
794
|
+
children: [
|
|
795
|
+
{
|
|
796
|
+
id: "users",
|
|
797
|
+
label: "Users",
|
|
798
|
+
icon: <Users className="h-4 w-4" />,
|
|
799
|
+
children: [
|
|
800
|
+
{ id: "users.list", label: "List users", icon: <FileText className="h-4 w-4" /> },
|
|
801
|
+
{ id: "users.create", label: "Create user", icon: <FileText className="h-4 w-4" /> }
|
|
802
|
+
]
|
|
803
|
+
},
|
|
804
|
+
{
|
|
805
|
+
id: "reports",
|
|
806
|
+
label: "Reports",
|
|
807
|
+
icon: <BarChart3 className="h-4 w-4" />,
|
|
808
|
+
children: [
|
|
809
|
+
{ id: "reports.sales", label: "Sales report", icon: <FileText className="h-4 w-4" /> },
|
|
810
|
+
{ id: "reports.financial", label: "Financial report", icon: <FileText className="h-4 w-4" /> }
|
|
811
|
+
]
|
|
812
|
+
}
|
|
813
|
+
]
|
|
814
|
+
}
|
|
815
|
+
];
|
|
816
|
+
|
|
817
|
+
export default function Example() {
|
|
818
|
+
const [checkedIds, setCheckedIds] = React.useState<string[]>([]);
|
|
819
|
+
const [readAll, setReadAll] = React.useState<string[]>([]);
|
|
820
|
+
const [readLeafs, setReadLeafs] = React.useState<string[]>([]);
|
|
821
|
+
const treeRef = React.useRef<SgTreeViewRef>(null);
|
|
822
|
+
|
|
823
|
+
return (
|
|
824
|
+
<>
|
|
825
|
+
<SgCard title="Permissions">
|
|
826
|
+
<SgTreeView
|
|
827
|
+
ref={treeRef}
|
|
828
|
+
nodes={nodes}
|
|
829
|
+
searchable
|
|
830
|
+
searchPlaceholder="Search..."
|
|
831
|
+
checkable
|
|
832
|
+
checkedIds={checkedIds}
|
|
833
|
+
onCheckedChange={setCheckedIds}
|
|
834
|
+
onLeafClick={(id) => console.log(id)}
|
|
835
|
+
style={{ border: "1px solid rgba(59, 130, 246, 0.2)", borderRadius: 12, padding: 8 }}
|
|
836
|
+
/>
|
|
837
|
+
</SgCard>
|
|
838
|
+
|
|
839
|
+
<div className="mt-3 flex gap-2">
|
|
840
|
+
<button type="button" className="rounded-md border border-border px-3 py-2 text-sm" onClick={() => setReadAll(treeRef.current?.getCheckedIds() ?? [])}>
|
|
841
|
+
Ler todos os checkeds
|
|
842
|
+
</button>
|
|
843
|
+
<button type="button" className="rounded-md border border-border px-3 py-2 text-sm" onClick={() => setReadLeafs(treeRef.current?.getCheckedLeafIds() ?? [])}>
|
|
844
|
+
Ler apenas leafs
|
|
845
|
+
</button>
|
|
846
|
+
</div>
|
|
847
|
+
|
|
848
|
+
<div className="mt-3 grid gap-2 text-xs text-muted-foreground">
|
|
849
|
+
<div>checkedIds: {readAll.join(", ") || "-"}</div>
|
|
850
|
+
<div>leafIds: {readLeafs.join(", ") || "-"}</div>
|
|
851
|
+
</div>
|
|
852
|
+
</>
|
|
853
|
+
);
|
|
854
|
+
}
|
|
855
|
+
```
|
|
856
|
+
|
|
857
|
+
### confirm
|
|
858
|
+
|
|
859
|
+
Fonte: `apps/showcase/src/app/components/sg-tree-view/samples/confirm.tsx.sample`. `checkMode="confirm"` com `confirmBar`.
|
|
860
|
+
|
|
861
|
+
```tsx
|
|
862
|
+
import React from "react";
|
|
863
|
+
import { BarChart3, FileText, Shield, Users } from "lucide-react";
|
|
864
|
+
import { SgCard, SgTreeView, type SgTreeNode, type SgTreeViewRef } from "@seedgrid/fe-components";
|
|
865
|
+
|
|
866
|
+
const nodes: SgTreeNode[] = [
|
|
867
|
+
{
|
|
868
|
+
id: "root",
|
|
869
|
+
label: "Admin",
|
|
870
|
+
icon: <Shield className="h-4 w-4" />,
|
|
871
|
+
children: [
|
|
872
|
+
{
|
|
873
|
+
id: "users",
|
|
874
|
+
label: "Users",
|
|
875
|
+
icon: <Users className="h-4 w-4" />,
|
|
876
|
+
children: [
|
|
877
|
+
{ id: "users.list", label: "List users", icon: <FileText className="h-4 w-4" /> },
|
|
878
|
+
{ id: "users.create", label: "Create user", icon: <FileText className="h-4 w-4" /> }
|
|
879
|
+
]
|
|
880
|
+
},
|
|
881
|
+
{
|
|
882
|
+
id: "reports",
|
|
883
|
+
label: "Reports",
|
|
884
|
+
icon: <BarChart3 className="h-4 w-4" />,
|
|
885
|
+
children: [
|
|
886
|
+
{ id: "reports.sales", label: "Sales report", icon: <FileText className="h-4 w-4" /> },
|
|
887
|
+
{ id: "reports.financial", label: "Financial report", icon: <FileText className="h-4 w-4" /> }
|
|
888
|
+
]
|
|
889
|
+
}
|
|
890
|
+
]
|
|
891
|
+
}
|
|
892
|
+
];
|
|
893
|
+
|
|
894
|
+
export default function Example() {
|
|
895
|
+
const [confirmed, setConfirmed] = React.useState<string[]>([]);
|
|
896
|
+
const treeRef = React.useRef<SgTreeViewRef>(null);
|
|
897
|
+
|
|
898
|
+
return (
|
|
899
|
+
<>
|
|
900
|
+
<SgCard title="Confirm selection">
|
|
901
|
+
<SgTreeView
|
|
902
|
+
ref={treeRef}
|
|
903
|
+
nodes={nodes}
|
|
904
|
+
searchable
|
|
905
|
+
searchPlaceholder="Search..."
|
|
906
|
+
checkable
|
|
907
|
+
checkMode="confirm"
|
|
908
|
+
confirmSelection="leafOnly"
|
|
909
|
+
confirmBar={{
|
|
910
|
+
label: "Confirmar",
|
|
911
|
+
showCancel: true,
|
|
912
|
+
cancelLabel: "Limpar",
|
|
913
|
+
onConfirm: (ids) => setConfirmed(ids),
|
|
914
|
+
onCancel: () => treeRef.current?.clearChecked()
|
|
915
|
+
}}
|
|
916
|
+
/>
|
|
917
|
+
</SgCard>
|
|
918
|
+
<div className="mt-3 text-xs text-muted-foreground">confirmIds: {confirmed.join(", ") || "-"}</div>
|
|
919
|
+
</>
|
|
920
|
+
);
|
|
921
|
+
}
|
|
922
|
+
```
|
|
923
|
+
|
|
924
|
+
### json-checked
|
|
925
|
+
|
|
926
|
+
Fonte: `apps/showcase/src/app/components/sg-tree-view/samples/json-checked.tsx.sample`. Montagem a partir de JSON com `sgTreeFromJsonWithChecked`.
|
|
927
|
+
|
|
928
|
+
```tsx
|
|
929
|
+
import React from "react";
|
|
930
|
+
import { SgTreeView, sgTreeFromJsonWithChecked } from "@seedgrid/fe-components";
|
|
931
|
+
|
|
932
|
+
const json = [
|
|
933
|
+
{
|
|
934
|
+
id: "root",
|
|
935
|
+
label: "Admin",
|
|
936
|
+
children: [
|
|
937
|
+
{
|
|
938
|
+
id: "users",
|
|
939
|
+
label: "Users",
|
|
940
|
+
children: [
|
|
941
|
+
{ id: "users.list", label: "List users", checked: true },
|
|
942
|
+
{ id: "users.create", label: "Create user" }
|
|
943
|
+
]
|
|
944
|
+
},
|
|
945
|
+
{
|
|
946
|
+
id: "reports",
|
|
947
|
+
label: "Reports",
|
|
948
|
+
children: [
|
|
949
|
+
{ id: "reports.sales", label: "Sales report", checked: true },
|
|
950
|
+
{ id: "reports.financial", label: "Financial report" }
|
|
951
|
+
]
|
|
952
|
+
}
|
|
953
|
+
]
|
|
954
|
+
}
|
|
955
|
+
];
|
|
956
|
+
|
|
957
|
+
export default function Example() {
|
|
958
|
+
const { nodes, checkedIds } = sgTreeFromJsonWithChecked(json);
|
|
959
|
+
|
|
960
|
+
return (
|
|
961
|
+
<SgTreeView
|
|
962
|
+
nodes={nodes}
|
|
963
|
+
checkable
|
|
964
|
+
defaultCheckedIds={checkedIds}
|
|
965
|
+
defaultExpandedIds={["root", "users"]}
|
|
966
|
+
/>
|
|
967
|
+
);
|
|
968
|
+
}
|
|
969
|
+
```
|
|
970
|
+
|
|
971
|
+
|
|
972
|
+
## SgDockLayout + SgDockZone
|
|
973
|
+
|
|
974
|
+
### basico
|
|
975
|
+
|
|
976
|
+
Fonte: `apps/showcase/src/app/components/sg-dock-layout/samples/basico.tsx.sample`. Layout com quatro zonas e toolbars arrastáveis (estado persistido em `dock-layout:<id>`).
|
|
977
|
+
|
|
978
|
+
```tsx
|
|
979
|
+
import React from "react";
|
|
980
|
+
import { SgDockLayout, SgDockZone, SgToolBar, SgToolbarIconButton } from "@seedgrid/fe-components";
|
|
981
|
+
import { ClipboardList, Home, LayoutGrid, Search, Settings, Users } from "lucide-react";
|
|
982
|
+
|
|
983
|
+
export default function Example() {
|
|
984
|
+
return (
|
|
985
|
+
<div className="relative h-[420px] overflow-hidden rounded-xl border border-border bg-black">
|
|
986
|
+
<SgDockLayout
|
|
987
|
+
id="showcase-dock-basic-v9"
|
|
988
|
+
className="grid h-full grid-cols-[8rem_1fr_8rem] grid-rows-[auto_1fr_auto]"
|
|
989
|
+
style={{ boxShadow: "inset 0 0 0 1px rgba(255, 255, 255, 0.08)" }}
|
|
990
|
+
>
|
|
991
|
+
<SgDockZone
|
|
992
|
+
zone="top"
|
|
993
|
+
className="col-span-3 row-start-1 items-start border-b border-white/20"
|
|
994
|
+
style={{ backgroundColor: "rgba(255, 255, 255, 0.03)" }}
|
|
995
|
+
>
|
|
996
|
+
<SgToolBar id="tb-main-basic-v9" dockZone="top" orientationDirection="horizontal-left" title="Topo" draggable>
|
|
997
|
+
<SgToolbarIconButton icon={<Home className="size-4" />} label="Home" hint="Ir para inicio" />
|
|
998
|
+
<SgToolbarIconButton icon={<Search className="size-4" />} label="Buscar" hint="Pesquisar registros" />
|
|
999
|
+
</SgToolBar>
|
|
1000
|
+
<SgToolBar id="tb-top-extra-basic-v9" dockZone="top" orientationDirection="horizontal-left" title="Acoes" draggable>
|
|
1001
|
+
<SgToolbarIconButton icon={<LayoutGrid className="size-4" />} label="Painel" hint="Abrir painel" />
|
|
1002
|
+
<SgToolbarIconButton icon={<ClipboardList className="size-4" />} label="Relatorio" hint="Abrir relatorios" />
|
|
1003
|
+
</SgToolBar>
|
|
1004
|
+
</SgDockZone>
|
|
1005
|
+
|
|
1006
|
+
<SgDockZone zone="left" className="col-start-1 row-start-2 items-start border-r border-white/20">
|
|
1007
|
+
<SgToolBar id="tb-left-basic-v9" dockZone="left" orientationDirection="vertical-down" title="Navegacao" collapsible draggable>
|
|
1008
|
+
<SgToolbarIconButton icon={<Users className="size-4" />} label="Clientes" hint="Abrir clientes" />
|
|
1009
|
+
<SgToolbarIconButton icon={<Settings className="size-4" />} label="Config" hint="Abrir configuracoes" />
|
|
1010
|
+
</SgToolBar>
|
|
1011
|
+
</SgDockZone>
|
|
1012
|
+
|
|
1013
|
+
<SgDockZone zone="right" className="col-start-3 row-start-2 items-start border-l border-white/20">
|
|
1014
|
+
<SgToolBar id="tb-right-basic-v9" dockZone="right" orientationDirection="vertical-down" title="Equipe" collapsible draggable>
|
|
1015
|
+
<SgToolbarIconButton icon={<Users className="size-4" />} label="Usuarios" hint="Gerenciar usuarios" />
|
|
1016
|
+
<SgToolbarIconButton icon={<Settings className="size-4" />} label="Ajustes" hint="Abrir ajustes" />
|
|
1017
|
+
</SgToolBar>
|
|
1018
|
+
</SgDockZone>
|
|
1019
|
+
|
|
1020
|
+
<SgDockZone zone="bottom" className="col-span-3 row-start-3 items-end border-t border-white/20">
|
|
1021
|
+
<SgToolBar id="tb-bottom-a-basic-v9" dockZone="bottom" orientationDirection="horizontal-left" title="Rodape A" draggable>
|
|
1022
|
+
<SgToolbarIconButton icon={<LayoutGrid className="size-4" />} label="Painel" hint="Abrir painel" />
|
|
1023
|
+
<SgToolbarIconButton icon={<Search className="size-4" />} label="Buscar" hint="Pesquisar no rodape" />
|
|
1024
|
+
</SgToolBar>
|
|
1025
|
+
<SgToolBar id="tb-bottom-b-basic-v9" dockZone="bottom" orientationDirection="horizontal-left" title="Rodape B" draggable>
|
|
1026
|
+
<SgToolbarIconButton icon={<ClipboardList className="size-4" />} label="Tarefas" hint="Abrir tarefas" />
|
|
1027
|
+
<SgToolbarIconButton icon={<Home className="size-4" />} label="Home" hint="Voltar ao inicio" />
|
|
1028
|
+
</SgToolBar>
|
|
1029
|
+
</SgDockZone>
|
|
1030
|
+
</SgDockLayout>
|
|
1031
|
+
</div>
|
|
1032
|
+
);
|
|
1033
|
+
}
|
|
1034
|
+
```
|
|
1035
|
+
|
|
1036
|
+
|
|
1037
|
+
## SgDockScreen
|
|
1038
|
+
|
|
1039
|
+
### basico
|
|
1040
|
+
|
|
1041
|
+
Fonte: `apps/showcase/src/app/components/sg-dock-screen/samples/basico.tsx.sample`. Mesma composição com a grade pronta do `SgDockScreen` (zonas sem `className`).
|
|
1042
|
+
|
|
1043
|
+
```tsx
|
|
1044
|
+
import React from "react";
|
|
1045
|
+
import { SgDockScreen, SgDockZone, SgToolBar, SgToolbarIconButton } from "@seedgrid/fe-components";
|
|
1046
|
+
import { ClipboardList, Home, LayoutGrid, Search, Settings, Users } from "lucide-react";
|
|
1047
|
+
|
|
1048
|
+
export default function Example() {
|
|
1049
|
+
return (
|
|
1050
|
+
<SgDockScreen
|
|
1051
|
+
id="showcase-dock-screen-basic-v1"
|
|
1052
|
+
fullscreen={false}
|
|
1053
|
+
height={420}
|
|
1054
|
+
className="overflow-hidden rounded-xl border border-border bg-background"
|
|
1055
|
+
>
|
|
1056
|
+
<SgDockZone zone="top">
|
|
1057
|
+
<SgToolBar id="tb-top-dock-screen-v1" dockZone="top" orientationDirection="horizontal-left" title="Topo" draggable>
|
|
1058
|
+
<SgToolbarIconButton icon={<Home className="size-4" />} label="Inicio" hint="Ir para inicio" />
|
|
1059
|
+
<SgToolbarIconButton icon={<Search className="size-4" />} label="Buscar" hint="Pesquisar dados" />
|
|
1060
|
+
</SgToolBar>
|
|
1061
|
+
</SgDockZone>
|
|
1062
|
+
|
|
1063
|
+
<SgDockZone zone="bottom">
|
|
1064
|
+
<SgToolBar id="tb-bottom-dock-screen-v1" dockZone="bottom" orientationDirection="horizontal-left" title="Base" draggable>
|
|
1065
|
+
<SgToolbarIconButton icon={<LayoutGrid className="size-4" />} label="Painel" hint="Abrir painel" />
|
|
1066
|
+
<SgToolbarIconButton icon={<ClipboardList className="size-4" />} label="Relatorio" hint="Abrir relatorios" />
|
|
1067
|
+
</SgToolBar>
|
|
1068
|
+
</SgDockZone>
|
|
1069
|
+
|
|
1070
|
+
<SgDockZone zone="left">
|
|
1071
|
+
<SgToolBar id="tb-left-dock-screen-v1" dockZone="left" orientationDirection="vertical-down" title="Navegacao" collapsible draggable>
|
|
1072
|
+
<SgToolbarIconButton icon={<Users className="size-4" />} label="Clientes" hint="Abrir clientes" />
|
|
1073
|
+
<SgToolbarIconButton icon={<Settings className="size-4" />} label="Config" hint="Abrir configuracoes" />
|
|
1074
|
+
</SgToolBar>
|
|
1075
|
+
</SgDockZone>
|
|
1076
|
+
|
|
1077
|
+
<SgDockZone zone="right">
|
|
1078
|
+
<SgToolBar id="tb-right-dock-screen-v1" dockZone="right" orientationDirection="vertical-down" title="Equipe" collapsible draggable>
|
|
1079
|
+
<SgToolbarIconButton icon={<Users className="size-4" />} label="Usuarios" hint="Gerenciar usuarios" />
|
|
1080
|
+
<SgToolbarIconButton icon={<Settings className="size-4" />} label="Ajustes" hint="Abrir ajustes" />
|
|
1081
|
+
</SgToolBar>
|
|
1082
|
+
</SgDockZone>
|
|
1083
|
+
|
|
1084
|
+
<SgDockZone zone="free">
|
|
1085
|
+
<div className="pointer-events-none text-sm text-muted-foreground">Area central livre</div>
|
|
1086
|
+
</SgDockZone>
|
|
1087
|
+
</SgDockScreen>
|
|
1088
|
+
);
|
|
1089
|
+
}
|
|
1090
|
+
```
|
|
1091
|
+
|
|
1092
|
+
|
|
1093
|
+
## SgToolBar + SgToolbarIconButton
|
|
1094
|
+
|
|
1095
|
+
### basico
|
|
1096
|
+
|
|
1097
|
+
Fonte: `apps/showcase/src/app/components/sg-toolbar/samples/basico.tsx.sample`. Toolbar vertical numa zona `free`, botões com `hint` e `severity`.
|
|
1098
|
+
|
|
1099
|
+
```tsx
|
|
1100
|
+
import React from "react";
|
|
1101
|
+
import { SgDockLayout, SgDockZone, SgToolBar, SgToolbarIconButton } from "@seedgrid/fe-components";
|
|
1102
|
+
import { Home, Settings, Users } from "lucide-react";
|
|
1103
|
+
|
|
1104
|
+
export default function Example() {
|
|
1105
|
+
return (
|
|
1106
|
+
<div className="w-full">
|
|
1107
|
+
<SgDockLayout id="tb-layout-basic" className="grid grid-cols-1 grid-rows-1">
|
|
1108
|
+
<SgDockZone zone="free" className="col-start-1 row-start-1 !items-start !justify-start !p-0">
|
|
1109
|
+
<SgToolBar id="tb-basic" title="Navegacao" orientationDirection="vertical-down">
|
|
1110
|
+
<SgToolbarIconButton icon={<Home className="size-4" />} label="Home" hint="Ir para Home" severity="primary" className="ring-1 ring-primary/30" style={{ minWidth: 132 }} />
|
|
1111
|
+
<SgToolbarIconButton icon={<Users className="size-4" />} label="Usuarios" hint="Abrir lista de usuarios" />
|
|
1112
|
+
<SgToolbarIconButton icon={<Settings className="size-4" />} label="Configuracoes" hint="Abrir configuracoes" />
|
|
1113
|
+
</SgToolBar>
|
|
1114
|
+
</SgDockZone>
|
|
1115
|
+
</SgDockLayout>
|
|
1116
|
+
</div>
|
|
1117
|
+
);
|
|
1118
|
+
}
|
|
1119
|
+
```
|
|
1120
|
+
|
|
1121
|
+
### onclick-assincrono-com-toast
|
|
1122
|
+
|
|
1123
|
+
Fonte: `apps/showcase/src/app/components/sg-toolbar/samples/onclick-assincrono-com-toast.tsx.sample`. `onClick` assíncrono: o botão entra em loading até a Promise resolver.
|
|
1124
|
+
|
|
1125
|
+
```tsx
|
|
1126
|
+
import React from "react";
|
|
1127
|
+
import { SgDockLayout, SgDockZone, SgToolBar, SgToolbarIconButton, toast } from "@seedgrid/fe-components";
|
|
1128
|
+
import { Pencil, Plus, Trash2 } from "lucide-react";
|
|
1129
|
+
|
|
1130
|
+
export default function Example() {
|
|
1131
|
+
return (
|
|
1132
|
+
<div className="w-full">
|
|
1133
|
+
<SgDockLayout id="tb-layout-async" className="grid grid-cols-1 grid-rows-1">
|
|
1134
|
+
<SgDockZone zone="free" className="col-start-1 row-start-1 !items-start !justify-start !p-0">
|
|
1135
|
+
<SgToolBar id="tb-async" title="Acoes rapidas" orientationDirection="horizontal-left" collapsible>
|
|
1136
|
+
<SgToolbarIconButton
|
|
1137
|
+
icon={<Plus className="size-4" />}
|
|
1138
|
+
label="Criar"
|
|
1139
|
+
hint="Criar novo registro"
|
|
1140
|
+
severity="success"
|
|
1141
|
+
onClick={async () => {
|
|
1142
|
+
await new Promise((resolve) => setTimeout(resolve, 1000));
|
|
1143
|
+
toast.success("Acao Criar concluida");
|
|
1144
|
+
}}
|
|
1145
|
+
/>
|
|
1146
|
+
<SgToolbarIconButton
|
|
1147
|
+
icon={<Pencil className="size-4" />}
|
|
1148
|
+
label="Editar"
|
|
1149
|
+
hint="Editar registro selecionado"
|
|
1150
|
+
severity="info"
|
|
1151
|
+
onClick={async () => {
|
|
1152
|
+
await new Promise((resolve) => setTimeout(resolve, 1000));
|
|
1153
|
+
toast.info("Acao Editar concluida");
|
|
1154
|
+
}}
|
|
1155
|
+
/>
|
|
1156
|
+
<SgToolbarIconButton
|
|
1157
|
+
icon={<Trash2 className="size-4" />}
|
|
1158
|
+
label="Excluir"
|
|
1159
|
+
hint="Excluir registro selecionado"
|
|
1160
|
+
severity="danger"
|
|
1161
|
+
onClick={async () => {
|
|
1162
|
+
await new Promise((resolve) => setTimeout(resolve, 1000));
|
|
1163
|
+
toast.warning("Acao Excluir concluida");
|
|
1164
|
+
}}
|
|
1165
|
+
/>
|
|
1166
|
+
</SgToolBar>
|
|
1167
|
+
</SgDockZone>
|
|
1168
|
+
</SgDockLayout>
|
|
1169
|
+
</div>
|
|
1170
|
+
);
|
|
1171
|
+
}
|
|
1172
|
+
```
|