@snksergio/design-system 0.61.0 → 0.63.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (193) hide show
  1. package/dist-lib/ai/blocos/chart/budget-breakdown.tsx +174 -0
  2. package/dist-lib/ai/blocos/indice.md +43 -0
  3. package/dist-lib/ai/blocos/paneldetail/detalhe-com-tabela.tsx +450 -0
  4. package/dist-lib/ai/blocos/paneldetail/detalhe-de-tarefa-com-abas.tsx +570 -0
  5. package/dist-lib/ai/blocos/paneldetail/detalhe-do-registro.tsx +555 -0
  6. package/dist-lib/ai/componentes/AlertModal.md +47 -0
  7. package/dist-lib/ai/componentes/AppShell.md +117 -0
  8. package/dist-lib/ai/componentes/Breadcrumb.md +187 -0
  9. package/dist-lib/ai/componentes/Button.md +116 -0
  10. package/dist-lib/ai/componentes/ButtonGroup.md +162 -0
  11. package/dist-lib/ai/componentes/CardCheckbox.md +99 -0
  12. package/dist-lib/ai/componentes/CardOption.md +133 -0
  13. package/dist-lib/ai/componentes/Chart.md +93 -0
  14. package/dist-lib/ai/componentes/Chip.md +68 -0
  15. package/dist-lib/ai/componentes/ChoroplethMap.md +118 -0
  16. package/dist-lib/ai/componentes/ColorPicker.md +70 -0
  17. package/dist-lib/ai/componentes/Combobox.md +51 -0
  18. package/dist-lib/ai/componentes/ConversationListItem.md +90 -0
  19. package/dist-lib/ai/componentes/DataList.md +111 -0
  20. package/dist-lib/ai/componentes/DataTable.md +867 -0
  21. package/dist-lib/ai/componentes/DatePicker.md +84 -0
  22. package/dist-lib/ai/componentes/DateSeparatorChip.md +59 -0
  23. package/dist-lib/ai/componentes/EmptyState.md +72 -0
  24. package/dist-lib/ai/componentes/FileUploadField.md +95 -0
  25. package/dist-lib/ai/componentes/FloatingPanel.md +118 -0
  26. package/dist-lib/ai/componentes/FooterTable.md +62 -0
  27. package/dist-lib/ai/componentes/FormField.md +110 -0
  28. package/dist-lib/ai/componentes/Gantt.md +552 -0
  29. package/dist-lib/ai/componentes/Header.md +98 -0
  30. package/dist-lib/ai/componentes/Icon.md +65 -0
  31. package/dist-lib/ai/componentes/Kanban.md +343 -0
  32. package/dist-lib/ai/componentes/Kpi.md +103 -0
  33. package/dist-lib/ai/componentes/List.md +61 -0
  34. package/dist-lib/ai/componentes/MarkdownText.md +59 -0
  35. package/dist-lib/ai/componentes/MenuSidebar.md +128 -0
  36. package/dist-lib/ai/componentes/MessageAck.md +53 -0
  37. package/dist-lib/ai/componentes/MessageBubble.md +115 -0
  38. package/dist-lib/ai/componentes/MessageComposer.md +80 -0
  39. package/dist-lib/ai/componentes/MessageVariablesPicker.md +104 -0
  40. package/dist-lib/ai/componentes/Modal.md +88 -0
  41. package/dist-lib/ai/componentes/MonthYearPicker.md +49 -0
  42. package/dist-lib/ai/componentes/PageHeader.md +129 -0
  43. package/dist-lib/ai/componentes/Panel.md +84 -0
  44. package/dist-lib/ai/componentes/Scheduler.md +421 -0
  45. package/dist-lib/ai/componentes/ScreenLoader.md +60 -0
  46. package/dist-lib/ai/componentes/SingleMenuSidebar.md +171 -0
  47. package/dist-lib/ai/componentes/Spinner.md +52 -0
  48. package/dist-lib/ai/componentes/Table.md +192 -0
  49. package/dist-lib/ai/componentes/TableToolbar.md +87 -0
  50. package/dist-lib/ai/componentes/TabsNavigation.md +152 -0
  51. package/dist-lib/ai/componentes/Toast.md +49 -0
  52. package/dist-lib/ai/componentes/_primitivos.md +74 -0
  53. package/dist-lib/ai/componentes/avatar-ig.md +181 -0
  54. package/dist-lib/ai/componentes/indice.json +49 -0
  55. package/dist-lib/ai/exemplos/app-shell/app-shell-example.tsx +140 -0
  56. package/dist-lib/ai/exemplos/app-shell/index.ts +3 -0
  57. package/dist-lib/ai/exemplos/app-shell/nav-data.ts +97 -0
  58. package/dist-lib/ai/exemplos/app-shell/routes.tsx +75 -0
  59. package/dist-lib/ai/exemplos/chat/chat-screen.tsx +152 -0
  60. package/dist-lib/ai/exemplos/chat/chat-v2-mocks.ts +171 -0
  61. package/dist-lib/ai/exemplos/chat/chat-v2.styles.ts +23 -0
  62. package/dist-lib/ai/exemplos/chat/chat-v2.types.ts +81 -0
  63. package/dist-lib/ai/exemplos/chat/components/ChannelDot/channel-dot.tsx +28 -0
  64. package/dist-lib/ai/exemplos/chat/components/ConversationActionsMenu/conversation-actions-menu.tsx +83 -0
  65. package/dist-lib/ai/exemplos/chat/components/ConversationActionsMenu/index.ts +4 -0
  66. package/dist-lib/ai/exemplos/chat/components/ConversationColumn/conversation-column.styles.ts +22 -0
  67. package/dist-lib/ai/exemplos/chat/components/ConversationColumn/conversation-column.tsx +203 -0
  68. package/dist-lib/ai/exemplos/chat/components/ConversationColumn/conversation-column.types.ts +10 -0
  69. package/dist-lib/ai/exemplos/chat/components/ConversationColumn/index.ts +2 -0
  70. package/dist-lib/ai/exemplos/chat/components/ConversationListItem/conversation-list-item.styles.ts +55 -0
  71. package/dist-lib/ai/exemplos/chat/components/ConversationListItem/conversation-list-item.tsx +52 -0
  72. package/dist-lib/ai/exemplos/chat/components/ConversationListItem/conversation-list-item.types.ts +7 -0
  73. package/dist-lib/ai/exemplos/chat/components/ConversationListItem/index.ts +2 -0
  74. package/dist-lib/ai/exemplos/chat/components/DateSeparator/date-separator.tsx +18 -0
  75. package/dist-lib/ai/exemplos/chat/components/DetailField/detail-field.tsx +23 -0
  76. package/dist-lib/ai/exemplos/chat/components/DetailSection/detail-section.tsx +41 -0
  77. package/dist-lib/ai/exemplos/chat/components/DetailSection/index.ts +1 -0
  78. package/dist-lib/ai/exemplos/chat/components/DetailsColumn/details-column.styles.ts +30 -0
  79. package/dist-lib/ai/exemplos/chat/components/DetailsColumn/details-column.tsx +142 -0
  80. package/dist-lib/ai/exemplos/chat/components/DetailsColumn/details-column.types.ts +16 -0
  81. package/dist-lib/ai/exemplos/chat/components/DetailsColumn/index.ts +5 -0
  82. package/dist-lib/ai/exemplos/chat/components/FilterRow/filter-row.styles.ts +37 -0
  83. package/dist-lib/ai/exemplos/chat/components/FilterRow/filter-row.tsx +45 -0
  84. package/dist-lib/ai/exemplos/chat/components/FilterRow/index.ts +1 -0
  85. package/dist-lib/ai/exemplos/chat/components/FiltersColumn/filters-column.styles.ts +27 -0
  86. package/dist-lib/ai/exemplos/chat/components/FiltersColumn/filters-column.tsx +66 -0
  87. package/dist-lib/ai/exemplos/chat/components/FiltersColumn/filters-column.types.ts +13 -0
  88. package/dist-lib/ai/exemplos/chat/components/FiltersColumn/filters-rail.tsx +38 -0
  89. package/dist-lib/ai/exemplos/chat/components/FiltersColumn/index.ts +6 -0
  90. package/dist-lib/ai/exemplos/chat/components/MessageBubble/index.ts +2 -0
  91. package/dist-lib/ai/exemplos/chat/components/MessageBubble/message-bubble.styles.ts +37 -0
  92. package/dist-lib/ai/exemplos/chat/components/MessageBubble/message-bubble.tsx +29 -0
  93. package/dist-lib/ai/exemplos/chat/components/MessageBubble/message-bubble.types.ts +5 -0
  94. package/dist-lib/ai/exemplos/chat/components/PersonAvatar/index.ts +5 -0
  95. package/dist-lib/ai/exemplos/chat/components/PersonAvatar/person-avatar.tsx +31 -0
  96. package/dist-lib/ai/exemplos/chat/components/QueueColumn/index.ts +2 -0
  97. package/dist-lib/ai/exemplos/chat/components/QueueColumn/queue-column.styles.ts +19 -0
  98. package/dist-lib/ai/exemplos/chat/components/QueueColumn/queue-column.tsx +140 -0
  99. package/dist-lib/ai/exemplos/chat/components/QueueColumn/queue-column.types.ts +13 -0
  100. package/dist-lib/ai/exemplos/chat/components/RailItem/index.ts +1 -0
  101. package/dist-lib/ai/exemplos/chat/components/RailItem/rail-item.styles.ts +30 -0
  102. package/dist-lib/ai/exemplos/chat/components/RailItem/rail-item.tsx +42 -0
  103. package/dist-lib/ai/exemplos/chat/hooks/use-resizable.ts +98 -0
  104. package/dist-lib/ai/exemplos/chat/index.ts +1 -0
  105. package/dist-lib/ai/exemplos/clientes/_table-data.ts +59 -0
  106. package/dist-lib/ai/exemplos/clientes/clientes-screen.tsx +505 -0
  107. package/dist-lib/ai/exemplos/clientes/clientes-showcase-mocks.ts +117 -0
  108. package/dist-lib/ai/exemplos/clientes/clientes-showcase.styles.ts +13 -0
  109. package/dist-lib/ai/exemplos/clientes/clientes-showcase.types.ts +16 -0
  110. package/dist-lib/ai/exemplos/clientes/components/DetailDrawer/detail-drawer.styles.ts +28 -0
  111. package/dist-lib/ai/exemplos/clientes/components/DetailDrawer/detail-drawer.tsx +303 -0
  112. package/dist-lib/ai/exemplos/clientes/components/DetailDrawer/detail-drawer.types.ts +14 -0
  113. package/dist-lib/ai/exemplos/clientes/components/DetailDrawer/index.ts +2 -0
  114. package/dist-lib/ai/exemplos/clientes/components/NovoClienteDrawer/index.ts +2 -0
  115. package/dist-lib/ai/exemplos/clientes/components/NovoClienteDrawer/novo-cliente-drawer.tsx +207 -0
  116. package/dist-lib/ai/exemplos/clientes/index.ts +1 -0
  117. package/dist-lib/ai/exemplos/dashboard/dashboard-brazil-map.ts +33 -0
  118. package/dist-lib/ai/exemplos/dashboard/dashboard-screen.tsx +1110 -0
  119. package/dist-lib/ai/exemplos/dashboard/index.ts +1 -0
  120. package/dist-lib/ai/exemplos/edit-page/components/StepNav.tsx +81 -0
  121. package/dist-lib/ai/exemplos/edit-page/components/section-card.tsx +85 -0
  122. package/dist-lib/ai/exemplos/edit-page/edit-page-screen.tsx +234 -0
  123. package/dist-lib/ai/exemplos/edit-page/index.ts +1 -0
  124. package/dist-lib/ai/exemplos/finance/_table-data.ts +57 -0
  125. package/dist-lib/ai/exemplos/finance/clientes-financeiro-mocks.ts +227 -0
  126. package/dist-lib/ai/exemplos/finance/clientes-financeiro.types.ts +75 -0
  127. package/dist-lib/ai/exemplos/finance/clientes-showcase-mocks.ts +117 -0
  128. package/dist-lib/ai/exemplos/finance/clientes-showcase.styles.ts +13 -0
  129. package/dist-lib/ai/exemplos/finance/clientes-showcase.types.ts +16 -0
  130. package/dist-lib/ai/exemplos/finance/components/EditarFinanceDrawer/editar-finance-drawer.tsx +241 -0
  131. package/dist-lib/ai/exemplos/finance/components/EditarFinanceDrawer/index.ts +5 -0
  132. package/dist-lib/ai/exemplos/finance/components/ExtratoExpansion/extrato-expansion.tsx +172 -0
  133. package/dist-lib/ai/exemplos/finance/components/ExtratoExpansion/index.ts +1 -0
  134. package/dist-lib/ai/exemplos/finance/components/FinanceDetailPanel/finance-detail-panel.tsx +241 -0
  135. package/dist-lib/ai/exemplos/finance/components/FinanceDetailPanel/index.ts +2 -0
  136. package/dist-lib/ai/exemplos/finance/components/NovoClienteDrawer/index.ts +2 -0
  137. package/dist-lib/ai/exemplos/finance/components/NovoClienteDrawer/novo-cliente-drawer.tsx +207 -0
  138. package/dist-lib/ai/exemplos/finance/components/SacarDialog/index.ts +2 -0
  139. package/dist-lib/ai/exemplos/finance/components/SacarDialog/sacar-dialog.tsx +346 -0
  140. package/dist-lib/ai/exemplos/finance/finance-screen.tsx +821 -0
  141. package/dist-lib/ai/exemplos/finance/index.ts +1 -0
  142. package/dist-lib/ai/exemplos/gantt/_gantt-data.tsx +402 -0
  143. package/dist-lib/ai/exemplos/gantt/gantt-screen.tsx +512 -0
  144. package/dist-lib/ai/exemplos/gantt/index.ts +1 -0
  145. package/dist-lib/ai/exemplos/login/index.ts +1 -0
  146. package/dist-lib/ai/exemplos/login/login-screen.tsx +246 -0
  147. package/dist-lib/ai/exemplos/mapa-rede/components/ConsultorDetailPanel/consultor-detail-panel.tsx +158 -0
  148. package/dist-lib/ai/exemplos/mapa-rede/components/ConsultorDetailPanel/index.ts +2 -0
  149. package/dist-lib/ai/exemplos/mapa-rede/index.ts +1 -0
  150. package/dist-lib/ai/exemplos/mapa-rede/mapa-de-rede-mocks.ts +655 -0
  151. package/dist-lib/ai/exemplos/mapa-rede/mapa-de-rede.types.ts +53 -0
  152. package/dist-lib/ai/exemplos/mapa-rede/mapa-rede-screen.tsx +227 -0
  153. package/dist-lib/ai/exemplos/order-detail/components/ActivityTab.tsx +77 -0
  154. package/dist-lib/ai/exemplos/order-detail/components/AttachmentsTab.tsx +45 -0
  155. package/dist-lib/ai/exemplos/order-detail/components/CommentsTab.tsx +111 -0
  156. package/dist-lib/ai/exemplos/order-detail/components/DetailsTab.tsx +189 -0
  157. package/dist-lib/ai/exemplos/order-detail/components/OverviewTab.tsx +200 -0
  158. package/dist-lib/ai/exemplos/order-detail/components/section-card.tsx +85 -0
  159. package/dist-lib/ai/exemplos/order-detail/index.ts +1 -0
  160. package/dist-lib/ai/exemplos/order-detail/order-detail-screen.tsx +119 -0
  161. package/dist-lib/ai/exemplos/order-detail/order-mocks.ts +186 -0
  162. package/dist-lib/ai/exemplos/order-detail/order.types.ts +118 -0
  163. package/dist-lib/ai/global/componentes.md +217 -0
  164. package/dist-lib/ai/global/composicao.md +182 -0
  165. package/dist-lib/ai/indice.json +192 -0
  166. package/dist-lib/ai/lint/ds-lint-patterns.mjs +115 -0
  167. package/dist-lib/ai/manifest.json +42 -0
  168. package/dist-lib/ai/regras/design.md +88 -0
  169. package/dist-lib/ai/regras/temas.md +192 -0
  170. package/dist-lib/ai/regras-por-componente.json +103 -0
  171. package/dist-lib/ai/roteiros/app-builder/roteiro.md +155 -0
  172. package/dist-lib/ai/roteiros/auth-builder/roteiro.md +42 -0
  173. package/dist-lib/ai/roteiros/cards/roteiro.md +34 -0
  174. package/dist-lib/ai/roteiros/charts/roteiro.md +32 -0
  175. package/dist-lib/ai/roteiros/chat/roteiro.md +31 -0
  176. package/dist-lib/ai/roteiros/crud-builder/blueprint.md +63 -0
  177. package/dist-lib/ai/roteiros/crud-builder/entrevista.md +139 -0
  178. package/dist-lib/ai/roteiros/crud-builder/geracao.md +113 -0
  179. package/dist-lib/ai/roteiros/crud-builder/roteiro.md +89 -0
  180. package/dist-lib/ai/roteiros/dashboard-builder/blueprint.md +47 -0
  181. package/dist-lib/ai/roteiros/dashboard-builder/entrevista.md +62 -0
  182. package/dist-lib/ai/roteiros/dashboard-builder/geracao.md +88 -0
  183. package/dist-lib/ai/roteiros/dashboard-builder/roteiro.md +88 -0
  184. package/dist-lib/ai/roteiros/drawers/roteiro.md +41 -0
  185. package/dist-lib/ai/roteiros/list-builder/blueprint.md +94 -0
  186. package/dist-lib/ai/roteiros/list-builder/entrevista.md +188 -0
  187. package/dist-lib/ai/roteiros/list-builder/geracao.md +63 -0
  188. package/dist-lib/ai/roteiros/list-builder/roteiro.md +91 -0
  189. package/dist-lib/ai/roteiros/module-replicator/roteiro.md +56 -0
  190. package/dist-lib/ai/roteiros/page-detail/roteiro.md +32 -0
  191. package/dist-lib/ai/roteiros/page-edit/roteiro.md +31 -0
  192. package/dist-lib/ai/roteiros/screen-composer/roteiro.md +95 -0
  193. package/package.json +4 -1
@@ -0,0 +1,246 @@
1
+ import { useState } from "react";
2
+ import type { ReactNode } from "react";
3
+ import { Eye, EyeOff, LifeBuoy, Hexagon, ShieldCheck, Zap } from "lucide-react";
4
+ import { Button } from "@/components/ui/Button";
5
+ import { FormFieldInput, FormFieldCheckbox } from "@/components/ui/FormField";
6
+ import { SidebarBrandIcon } from "@/components/ui/MenuSidebar";
7
+
8
+ /**
9
+ * LoginScreen — tela de login split (form à esquerda, painel à direita).
10
+ * Self-contained e configurável por props:
11
+ *
12
+ * - `logo` — marca no topo do form (default: logo iGreen; passe o do seu app).
13
+ * - `rightVariant` — painel direito: "text" (marca 100% por tokens, sem asset) ·
14
+ * "image" (só a imagem) · "image-text" (imagem + headline sobreposta).
15
+ * **Default "image"** — sem `image`, cai no painel de texto (nunca quebra).
16
+ * - `image` — URL da imagem (variants image/-text e do fundo `ambient`).
17
+ * - `ambient` — fundo ambiente: a imagem borrada/escurecida atrás do card (destaque).
18
+ * - `panelTitle` / `panelSubtitle` — copy do painel (text e image-text).
19
+ *
20
+ * Mockado: `onSubmit` só previne o default — o consumidor pluga a auth real.
21
+ */
22
+ export interface LoginScreenProps {
23
+ logo?: ReactNode;
24
+ rightVariant?: "text" | "image" | "image-text";
25
+ image?: string;
26
+ ambient?: boolean;
27
+ panelTitle?: string;
28
+ panelSubtitle?: string;
29
+ }
30
+
31
+ const SELLING_POINTS = [
32
+ { icon: Zap, label: "Acompanhe seus resultados em tempo real" },
33
+ { icon: ShieldCheck, label: "Acesso seguro à sua conta" },
34
+ ];
35
+
36
+ export function LoginScreen({
37
+ logo = <SidebarBrandIcon size={24} />,
38
+ rightVariant = "image",
39
+ image,
40
+ ambient = false,
41
+ panelTitle = "Tudo o que você precisa, num só lugar.",
42
+ panelSubtitle = "Gerencie seus dados, acompanhe resultados e cresça com a sua equipe.",
43
+ }: LoginScreenProps = {}) {
44
+ const [email, setEmail] = useState("");
45
+ const [senha, setSenha] = useState("");
46
+ const [showSenha, setShowSenha] = useState(false);
47
+ const [manter, setManter] = useState(true);
48
+
49
+ const entrar = (e: React.FormEvent) => {
50
+ e.preventDefault();
51
+ // Mock: plugue a autenticação real do seu app aqui.
52
+ };
53
+
54
+ // Sem imagem, os variants de imagem caem no painel de marca (nunca quebra).
55
+ const variant = rightVariant !== "text" && !image ? "text" : rightVariant;
56
+ const hasAmbient = ambient && !!image;
57
+
58
+ return (
59
+ <div className="relative flex min-h-screen flex-col items-center justify-center gap-gp-2xl overflow-hidden bg-bg-canvas p-pad-2xl">
60
+ {/* Fundo ambiente: a imagem borrada + escurecida atrás de tudo. */}
61
+ {hasAmbient && (
62
+ <>
63
+ <img
64
+ src={image}
65
+ aria-hidden
66
+ alt=""
67
+ className="pointer-events-none absolute inset-0 size-full scale-110 object-cover opacity-20 blur-[60px] saturate-150"
68
+ />
69
+ <div
70
+ aria-hidden
71
+ className="pointer-events-none absolute inset-0 bg-bg-canvas/85"
72
+ />
73
+ </>
74
+ )}
75
+
76
+ <div className="relative z-10 grid w-full max-w-[1000px] overflow-hidden rounded-radius-2xl border border-border-subtle shadow-sh-lg lg:min-h-[620px] lg:grid-cols-2">
77
+ {/* ── Esquerda: formulário ── */}
78
+ <div className="flex flex-col justify-center gap-gp-3xl bg-bg-surface p-pad-4xl lg:px-[40px] lg:py-pad-6xl">
79
+ <div className="mb-gp-md flex flex-col items-center gap-gp-lg text-center">
80
+ <span className="grid size-[48px] place-items-center rounded-radius-2xl bg-bg-brand text-fg-on-brand shadow-sh-sm">
81
+ {logo}
82
+ </span>
83
+ <div className="flex flex-col gap-gp-2xs">
84
+ <h1 className="text-heading-xs font-bold text-fg-default">
85
+ Bem-vindo de volta
86
+ </h1>
87
+ <p className="mx-auto max-w-[300px] text-body-md text-fg-muted">
88
+ Adicione suas credenciais abaixo para acessar sua conta.
89
+ </p>
90
+ </div>
91
+ </div>
92
+
93
+ <form className="flex flex-col gap-form-gap" onSubmit={entrar}>
94
+ <FormFieldInput
95
+ label="Email"
96
+ type="email"
97
+ autoComplete="email"
98
+ placeholder="voce@email.com"
99
+ helperText="Use o email cadastrado na sua conta."
100
+ className="min-h-form-xl"
101
+ value={email}
102
+ onChange={(e) => setEmail(e.target.value)}
103
+ />
104
+
105
+ <FormFieldInput
106
+ label="Senha"
107
+ type={showSenha ? "text" : "password"}
108
+ autoComplete="current-password"
109
+ placeholder="Sua senha"
110
+ className="min-h-form-xl"
111
+ value={senha}
112
+ onChange={(e) => setSenha(e.target.value)}
113
+ endAddon={
114
+ <button
115
+ type="button"
116
+ aria-label={showSenha ? "Ocultar senha" : "Mostrar senha"}
117
+ onClick={() => setShowSenha((s) => !s)}
118
+ className="grid place-items-center rounded-radius-sm text-fg-muted transition-colors hover:text-fg-default focus-visible:outline-none focus-visible:ring-4 focus-visible:ring-ring-brand [&>svg]:size-icon-sm"
119
+ >
120
+ {showSenha ? <EyeOff /> : <Eye />}
121
+ </button>
122
+ }
123
+ />
124
+
125
+ <div className="flex items-center justify-between gap-gp-md">
126
+ <FormFieldCheckbox
127
+ label="Manter conectado"
128
+ checked={manter}
129
+ onCheckedChange={(v) => setManter(v === true)}
130
+ />
131
+ <button
132
+ type="button"
133
+ className="shrink-0 whitespace-nowrap rounded-radius-sm text-body-sm font-medium text-fg-brand transition-colors hover:underline focus-visible:outline-none focus-visible:ring-4 focus-visible:ring-ring-brand"
134
+ >
135
+ Esqueceu a senha?
136
+ </button>
137
+ </div>
138
+
139
+ <Button
140
+ type="submit"
141
+ color="primary"
142
+ variant="filled"
143
+ size="lg"
144
+ className="w-full min-h-form-xl"
145
+ >
146
+ Entrar
147
+ </Button>
148
+ </form>
149
+
150
+ <p className="mt-gp-md flex flex-wrap items-center justify-center gap-gp-xs text-body-sm text-fg-muted [&>svg]:size-icon-sm [&>svg]:text-fg-subtle">
151
+ <LifeBuoy />
152
+ Precisa de ajuda para acessar?{" "}
153
+ <a
154
+ href="#"
155
+ className="rounded-radius-sm font-medium text-fg-brand transition-colors hover:underline focus-visible:outline-none focus-visible:ring-4 focus-visible:ring-ring-brand"
156
+ >
157
+ Fale com o suporte
158
+ </a>
159
+ </p>
160
+ </div>
161
+
162
+ {/* ── Direita: painel (some no mobile) ── */}
163
+ <div className="relative hidden overflow-hidden bg-bg-brand lg:block">
164
+ {variant === "text" && (
165
+ <BrandPanel title={panelTitle} subtitle={panelSubtitle} />
166
+ )}
167
+
168
+ {variant === "image" && (
169
+ <img
170
+ src={image}
171
+ alt=""
172
+ aria-hidden
173
+ className="absolute inset-0 h-full w-full object-cover"
174
+ />
175
+ )}
176
+
177
+ {variant === "image-text" && (
178
+ <>
179
+ <img
180
+ src={image}
181
+ alt=""
182
+ aria-hidden
183
+ className="absolute inset-0 h-full w-full object-cover"
184
+ />
185
+ {/* Overlay escuro pra legibilidade do texto sobre a foto (exceção: texto sobre imagem). */}
186
+ <div
187
+ aria-hidden
188
+ className="absolute inset-0 bg-gradient-to-t from-black/75 via-black/25 to-transparent"
189
+ />
190
+ <div className="absolute inset-x-0 bottom-0 flex flex-col gap-gp-md p-pad-6xl text-white">
191
+ <h2 className="text-heading-sm font-semibold leading-tight">
192
+ {panelTitle}
193
+ </h2>
194
+ <p className="max-w-[360px] text-body-md text-white/85">
195
+ {panelSubtitle}
196
+ </p>
197
+ </div>
198
+ </>
199
+ )}
200
+ </div>
201
+ </div>
202
+
203
+ <p className="relative z-10 text-center text-caption-sm text-fg-subtle">
204
+ Ao continuar, você concorda com os Termos de Uso e a Política de
205
+ Privacidade.
206
+ </p>
207
+ </div>
208
+ );
209
+ }
210
+
211
+ /** Painel de marca 100% por tokens (variant "text") — sem asset externo. */
212
+ function BrandPanel({ title, subtitle }: { title: string; subtitle: string }) {
213
+ return (
214
+ <div className="flex h-full flex-col justify-between">
215
+ <div
216
+ aria-hidden
217
+ className="pointer-events-none absolute inset-0 opacity-[0.14] [background:radial-gradient(circle_at_18%_18%,var(--color-fg-on-brand)_0,transparent_42%),radial-gradient(circle_at_88%_8%,var(--color-fg-on-brand)_0,transparent_32%)]"
218
+ />
219
+ <div
220
+ aria-hidden
221
+ className="pointer-events-none absolute inset-0 bg-gradient-to-br from-transparent via-transparent to-fg-default/25"
222
+ />
223
+ <div className="relative z-10 flex flex-col gap-gp-lg p-pad-6xl text-fg-on-brand">
224
+ <span className="grid size-[44px] place-items-center rounded-radius-xl bg-fg-on-brand/15 [&>svg]:size-icon-md">
225
+ <Hexagon strokeWidth={1.8} />
226
+ </span>
227
+ <div className="flex flex-col gap-gp-md">
228
+ <h2 className="text-heading-sm font-semibold leading-tight">{title}</h2>
229
+ <p className="max-w-[340px] text-body-md text-fg-on-brand/80">{subtitle}</p>
230
+ </div>
231
+ </div>
232
+ <ul className="relative z-10 flex flex-col gap-gp-lg p-pad-6xl text-fg-on-brand">
233
+ {SELLING_POINTS.map(({ icon: Icon, label }) => (
234
+ <li key={label} className="flex items-center gap-gp-md">
235
+ <span className="grid size-comp-lg shrink-0 place-items-center rounded-radius-full bg-fg-on-brand/15 [&>svg]:size-icon-sm">
236
+ <Icon strokeWidth={1.8} />
237
+ </span>
238
+ <span className="text-body-md text-fg-on-brand/90">{label}</span>
239
+ </li>
240
+ ))}
241
+ </ul>
242
+ </div>
243
+ );
244
+ }
245
+
246
+ export default LoginScreen;
@@ -0,0 +1,158 @@
1
+ import { Pencil, UserMinus } from "lucide-react";
2
+ import {
3
+ FloatingPanel,
4
+ FloatingPanelSection,
5
+ FloatingPanelField,
6
+ } from "@/components/ui/FloatingPanel";
7
+ import { Avatar } from "@/components/ui/avatar-ig";
8
+ import { Button } from "@/components/ui/Button/button";
9
+ import { Chip } from "@/components/ui/Chip";
10
+ import {
11
+ GRADUACAO,
12
+ REGIAO,
13
+ formatLongDate,
14
+ formatNum,
15
+ initials,
16
+ levelOf,
17
+ subtreeLabel,
18
+ } from "../../mapa-de-rede-mocks";
19
+ import type { Consultor } from "../../mapa-de-rede.types";
20
+
21
+ export type ConsultorDetailPanelProps = {
22
+ consultor: Consultor | null;
23
+ onClose: () => void;
24
+ onEdit?: (c: Consultor) => void;
25
+ onRemove?: (c: Consultor) => void;
26
+ };
27
+
28
+ export function ConsultorDetailPanel({
29
+ consultor,
30
+ onClose,
31
+ onEdit,
32
+ onRemove,
33
+ }: ConsultorDetailPanelProps) {
34
+ if (!consultor) return null;
35
+
36
+ const grad = GRADUACAO[consultor.graduacao];
37
+ const diretos = consultor.children?.length ?? 0;
38
+
39
+ return (
40
+ <FloatingPanel
41
+ open={consultor !== null}
42
+ onOpenChange={(open) => {
43
+ if (!open) onClose();
44
+ }}
45
+ side="right"
46
+ size="md"
47
+ resizable
48
+ maximizable
49
+ bodyPadded={false}
50
+ resizableStorageKey="mapa-de-rede.detail-panel.width"
51
+ titleSlot={
52
+ <div className="flex min-w-0 items-center gap-gp-md">
53
+ <Avatar
54
+ size="md"
55
+ colorHex={consultor.avatarColor}
56
+ className="shrink-0 text-caption-md font-bold"
57
+ >
58
+ {initials(consultor.name)}
59
+ </Avatar>
60
+ <div className="flex min-w-0 flex-col gap-gp-2xs">
61
+ <span className="truncate text-body-md font-semibold text-fg-default">
62
+ {consultor.name}
63
+ </span>
64
+ <span className="flex flex-wrap items-center gap-gp-sm">
65
+ <Chip color="neutral" variant="soft" size="sm" shape="pill">
66
+ {levelOf(consultor.id)}
67
+ </Chip>
68
+ <Chip color={grad.color} variant="soft" size="sm" shape="pill">
69
+ {grad.label}
70
+ </Chip>
71
+ {consultor.pro && (
72
+ <Chip color="success" variant="soft" size="sm" shape="pill">
73
+ PRO
74
+ </Chip>
75
+ )}
76
+ </span>
77
+ </div>
78
+ </div>
79
+ }
80
+ footer={
81
+ <div className="flex items-center gap-gp-md">
82
+ <Button
83
+ variant="outline"
84
+ color="secondary"
85
+ size="md"
86
+ iconLeft={<Pencil />}
87
+ className="flex-1"
88
+ onClick={() => onEdit?.(consultor)}
89
+ >
90
+ Editar
91
+ </Button>
92
+ <Button
93
+ variant="outline"
94
+ color="critical"
95
+ size="icon-md"
96
+ aria-label="Remover da rede"
97
+ onClick={() => onRemove?.(consultor)}
98
+ >
99
+ <UserMinus />
100
+ </Button>
101
+ </div>
102
+ }
103
+ >
104
+ <FloatingPanelSection title="Desempenho próprio">
105
+ <FloatingPanelField
106
+ label="GP próprio"
107
+ value={formatNum(consultor.gpProprio)}
108
+ />
109
+ <FloatingPanelField
110
+ label="Clientes diretos"
111
+ value={formatNum(consultor.clientes)}
112
+ />
113
+ <FloatingPanelField
114
+ label="Descendentes diretos"
115
+ value={formatNum(diretos)}
116
+ />
117
+ </FloatingPanelSection>
118
+
119
+ <FloatingPanelSection title="Subárvore (agregado)">
120
+ {consultor.subtree ? (
121
+ <>
122
+ <FloatingPanelField
123
+ label="Consultores"
124
+ value={formatNum(consultor.subtree.consultores)}
125
+ />
126
+ <FloatingPanelField
127
+ label="GP da rede"
128
+ value={formatNum(consultor.subtree.gp)}
129
+ />
130
+ <FloatingPanelField
131
+ label="Clientes da rede"
132
+ value={formatNum(consultor.subtree.clientes)}
133
+ />
134
+ </>
135
+ ) : (
136
+ <p className="px-pad-xl py-pad-md text-body-sm text-fg-muted">
137
+ {subtreeLabel(consultor)}
138
+ </p>
139
+ )}
140
+ </FloatingPanelSection>
141
+
142
+ <FloatingPanelSection title="Contato & atuação">
143
+ <FloatingPanelField label="Email" value={consultor.email} />
144
+ <FloatingPanelField label="Telefone" value={consultor.phone} />
145
+ <FloatingPanelField label="Localização" value={consultor.location} />
146
+ <FloatingPanelField label="Região" value={REGIAO[consultor.regiao]} />
147
+ <FloatingPanelField
148
+ label="Consultor desde"
149
+ value={formatLongDate(consultor.since)}
150
+ />
151
+ <FloatingPanelField
152
+ label="Última atividade"
153
+ value={consultor.lastActive}
154
+ />
155
+ </FloatingPanelSection>
156
+ </FloatingPanel>
157
+ );
158
+ }
@@ -0,0 +1,2 @@
1
+ export { ConsultorDetailPanel } from "./consultor-detail-panel";
2
+ export type { ConsultorDetailPanelProps } from "./consultor-detail-panel";
@@ -0,0 +1 @@
1
+ export { MapaDeRedeScreen, default } from "./mapa-rede-screen";