@snksergio/design-system 0.1.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 (73) hide show
  1. package/README.md +260 -0
  2. package/dist-lib/chunks/app-shell-BNTvOETJ.mjs +2681 -0
  3. package/dist-lib/chunks/app-shell-BNTvOETJ.mjs.map +1 -0
  4. package/dist-lib/chunks/app-shell-CDy42aNI.mjs +2663 -0
  5. package/dist-lib/chunks/app-shell-CDy42aNI.mjs.map +1 -0
  6. package/dist-lib/chunks/app-shell-mocks-kWIVSzLs.mjs +208 -0
  7. package/dist-lib/chunks/app-shell-mocks-kWIVSzLs.mjs.map +1 -0
  8. package/dist-lib/chunks/app-shell-mocks-oO_IV3Gw.mjs +207 -0
  9. package/dist-lib/chunks/app-shell-mocks-oO_IV3Gw.mjs.map +1 -0
  10. package/dist-lib/chunks/badge-B_2Zt52o.mjs +797 -0
  11. package/dist-lib/chunks/badge-B_2Zt52o.mjs.map +1 -0
  12. package/dist-lib/chunks/badge-DKpXURa1.mjs +813 -0
  13. package/dist-lib/chunks/badge-DKpXURa1.mjs.map +1 -0
  14. package/dist-lib/chunks/chat-v2-mocks-BV9Wha_Z.mjs +192 -0
  15. package/dist-lib/chunks/chat-v2-mocks-BV9Wha_Z.mjs.map +1 -0
  16. package/dist-lib/chunks/chat-v2-mocks-DvZRkhmz.mjs +193 -0
  17. package/dist-lib/chunks/chat-v2-mocks-DvZRkhmz.mjs.map +1 -0
  18. package/dist-lib/chunks/chip-group-CsKBBHW2.mjs +796 -0
  19. package/dist-lib/chunks/chip-group-CsKBBHW2.mjs.map +1 -0
  20. package/dist-lib/chunks/chip-group-D3D0i72q.mjs +780 -0
  21. package/dist-lib/chunks/chip-group-D3D0i72q.mjs.map +1 -0
  22. package/dist-lib/chunks/clientes-showcase-mocks-BMfbNNJh.mjs +185 -0
  23. package/dist-lib/chunks/clientes-showcase-mocks-BMfbNNJh.mjs.map +1 -0
  24. package/dist-lib/chunks/clientes-showcase-mocks-Cq9u3nGZ.mjs +169 -0
  25. package/dist-lib/chunks/clientes-showcase-mocks-Cq9u3nGZ.mjs.map +1 -0
  26. package/dist-lib/chunks/input-374MpdBL.mjs +72 -0
  27. package/dist-lib/chunks/input-374MpdBL.mjs.map +1 -0
  28. package/dist-lib/chunks/input-DF4XAWmr.mjs +56 -0
  29. package/dist-lib/chunks/input-DF4XAWmr.mjs.map +1 -0
  30. package/dist-lib/chunks/page-header-Dw-3wqAG.mjs +75 -0
  31. package/dist-lib/chunks/page-header-Dw-3wqAG.mjs.map +1 -0
  32. package/dist-lib/chunks/page-header-mC1gGtOI.mjs +76 -0
  33. package/dist-lib/chunks/page-header-mC1gGtOI.mjs.map +1 -0
  34. package/dist-lib/chunks/panel-Ds15whqp.mjs +9717 -0
  35. package/dist-lib/chunks/panel-Ds15whqp.mjs.map +1 -0
  36. package/dist-lib/chunks/panel-bzNmFlEZ.mjs +9737 -0
  37. package/dist-lib/chunks/panel-bzNmFlEZ.mjs.map +1 -0
  38. package/dist-lib/chunks/useTheme-BUPLZBMs.mjs +66 -0
  39. package/dist-lib/chunks/useTheme-BUPLZBMs.mjs.map +1 -0
  40. package/dist-lib/chunks/useTheme-Dee4mo-A.mjs +65 -0
  41. package/dist-lib/chunks/useTheme-Dee4mo-A.mjs.map +1 -0
  42. package/dist-lib/index.cjs +1207 -0
  43. package/dist-lib/index.cjs.map +1 -0
  44. package/dist-lib/index.d.ts +2 -0
  45. package/dist-lib/index.mjs +1209 -0
  46. package/dist-lib/index.mjs.map +1 -0
  47. package/dist-lib/preview/chat.cjs +1120 -0
  48. package/dist-lib/preview/chat.cjs.map +1 -0
  49. package/dist-lib/preview/chat.d.ts +6 -0
  50. package/dist-lib/preview/chat.mjs +1120 -0
  51. package/dist-lib/preview/chat.mjs.map +1 -0
  52. package/dist-lib/preview/clientes.cjs +897 -0
  53. package/dist-lib/preview/clientes.cjs.map +1 -0
  54. package/dist-lib/preview/clientes.d.ts +6 -0
  55. package/dist-lib/preview/clientes.mjs +897 -0
  56. package/dist-lib/preview/clientes.mjs.map +1 -0
  57. package/dist-lib/preview/dashboard.cjs +733 -0
  58. package/dist-lib/preview/dashboard.cjs.map +1 -0
  59. package/dist-lib/preview/dashboard.d.ts +4 -0
  60. package/dist-lib/preview/dashboard.mjs +733 -0
  61. package/dist-lib/preview/dashboard.mjs.map +1 -0
  62. package/dist-lib/preview/mocks.cjs +15 -0
  63. package/dist-lib/preview/mocks.cjs.map +1 -0
  64. package/dist-lib/preview/mocks.d.ts +2 -0
  65. package/dist-lib/preview/mocks.mjs +15 -0
  66. package/dist-lib/preview/mocks.mjs.map +1 -0
  67. package/dist-lib/theme.css +668 -0
  68. package/dist-lib/tokens.cjs +915 -0
  69. package/dist-lib/tokens.cjs.map +1 -0
  70. package/dist-lib/tokens.d.ts +2 -0
  71. package/dist-lib/tokens.mjs +915 -0
  72. package/dist-lib/tokens.mjs.map +1 -0
  73. package/package.json +142 -0
@@ -0,0 +1 @@
1
+ {"version":3,"file":"clientes-showcase-mocks-Cq9u3nGZ.mjs","sources":["../../src/components/shadcn/separator.tsx","../../src/preview/components/doc-context.tsx","../../src/preview/pages/TableDoc.tsx","../../src/preview/pages/ClientesShowcase/clientes-showcase-mocks.ts"],"sourcesContent":["\"use client\"\n\nimport * as React from \"react\"\nimport * as SeparatorPrimitive from \"@radix-ui/react-separator\"\n\nimport { cn } from \"@/lib/utils\"\n\nconst Separator = React.forwardRef<\n React.ElementRef<typeof SeparatorPrimitive.Root>,\n React.ComponentPropsWithoutRef<typeof SeparatorPrimitive.Root>\n>(\n (\n { className, orientation = \"horizontal\", decorative = true, ...props },\n ref\n ) => (\n <SeparatorPrimitive.Root\n ref={ref}\n decorative={decorative}\n orientation={orientation}\n className={cn(\n \"shrink-0 bg-border\",\n orientation === \"horizontal\" ? \"h-[1px] w-full\" : \"h-full w-[1px]\",\n className\n )}\n {...props}\n />\n )\n)\nSeparator.displayName = SeparatorPrimitive.Root.displayName\n\nexport { Separator }\n","import { createContext, useContext } from \"react\";\n\ntype DocNavContext = {\n onNavigate: (pageId: string) => void;\n};\n\nconst DocNavCtx = createContext<DocNavContext>({ onNavigate: () => {} });\n\nexport function DocNavProvider({ onNavigate, children }: { onNavigate: (pageId: string) => void; children: React.ReactNode }) {\n return <DocNavCtx.Provider value={{ onNavigate }}>{children}</DocNavCtx.Provider>;\n}\n\nexport function useDocNav() {\n return useContext(DocNavCtx);\n}\n","import { useMemo, useState } from \"react\";\nimport {\n Hash,\n User,\n AtSign,\n Phone,\n CheckCircle2,\n Tag,\n Users as UsersIcon,\n DollarSign,\n Calendar,\n Type,\n MoreVertical,\n MoreHorizontal,\n Pencil,\n} from \"lucide-react\";\nimport {\n Table,\n TableBody,\n TableCardRow,\n TableCell,\n TableHead,\n TableHeadCell,\n TableRow,\n useColumnWidths,\n type SortDirection,\n type TableDensity,\n} from \"@/components/ui/Table\";\nimport { Badge } from \"@/components/shadcn/badge\";\nimport { Checkbox } from \"@/components/shadcn/checkbox\";\nimport { Button } from \"@/components/ui/Button/button\";\nimport { Chip } from \"@/components/ui/Chip\";\nimport {\n DocLayout,\n DocHeader,\n DocSeparator,\n SectionH2,\n ExampleSection,\n PropsTable,\n type PropItem,\n} from \"../components\";\n\n/* ═══════════════════════════════════════════════════════════════════════════\n Table Documentation Page\n ═══════════════════════════════════════════════════════════════════════════ */\n\nconst TOC = [\n { id: \"examples\", label: \"Examples\" },\n { id: \"ex-density\", label: \"Densidades\" },\n { id: \"ex-sticky\", label: \"Sticky header\" },\n { id: \"ex-pin-sort-resize\", label: \"Pin + Sort + Resize\" },\n { id: \"ex-selection\", label: \"Selection / hover\" },\n { id: \"ex-card-mode\", label: \"Card mode (responsive)\" },\n { id: \"ex-full\", label: \"Tabela completa\" },\n { id: \"api\", label: \"API Reference\" },\n { id: \"api-table\", label: \"<Table>\" },\n { id: \"api-head\", label: \"<TableHead>\" },\n { id: \"api-headcell\", label: \"<TableHeadCell>\" },\n { id: \"api-row\", label: \"<TableRow>\" },\n { id: \"api-cell\", label: \"<TableCell>\" },\n { id: \"api-cardrow\", label: \"<TableCardRow>\" },\n];\n\nconst TABLE_PROPS: PropItem[] = [\n { name: \"density\", type: '\"compact\" | \"standard\" | \"comfortable\"', defaultVal: '\"standard\"' },\n { name: \"cardBreakpoint\", type: \"number | false\", defaultVal: \"768\" },\n { name: \"ariaLabel\", type: \"string\", defaultVal: \"—\" },\n { name: \"className\", type: \"string\", defaultVal: \"—\" },\n { name: \"children\", type: \"ReactNode\", defaultVal: \"—\" },\n];\n\nconst HEAD_PROPS: PropItem[] = [\n { name: \"sticky\", type: \"boolean\", defaultVal: \"true\" },\n { name: \"className\", type: \"string\", defaultVal: \"—\" },\n];\n\nconst HEAD_CELL_PROPS: PropItem[] = [\n { name: \"width\", type: \"number\", defaultVal: \"—\" },\n { name: \"pinned\", type: '\"left\" | \"right\"', defaultVal: \"—\" },\n { name: \"pinOffset\", type: \"number\", defaultVal: \"—\" },\n { name: \"align\", type: '\"left\" | \"center\" | \"right\"', defaultVal: '\"left\"' },\n { name: \"sortable\", type: \"boolean\", defaultVal: \"false\" },\n { name: \"sortDirection\", type: '\"asc\" | \"desc\" | null', defaultVal: \"null\" },\n { name: \"onSortClick\", type: \"() => void\", defaultVal: \"—\" },\n { name: \"resizable\", type: \"boolean\", defaultVal: \"—\" },\n { name: \"onResize\", type: \"(widthPx: number) => void\", defaultVal: \"—\" },\n { name: \"onResizeEnd\", type: \"(widthPx: number) => void\", defaultVal: \"—\" },\n];\n\nconst ROW_PROPS: PropItem[] = [\n { name: \"selected\", type: \"boolean\", defaultVal: \"false\" },\n { name: \"clickable\", type: \"boolean\", defaultVal: \"auto (true se onClick)\" },\n { name: \"onClick\", type: \"(e: MouseEvent) => void\", defaultVal: \"—\" },\n];\n\nconst CELL_PROPS: PropItem[] = [\n { name: \"width\", type: \"number\", defaultVal: \"—\" },\n { name: \"pinned\", type: '\"left\" | \"right\"', defaultVal: \"—\" },\n { name: \"pinOffset\", type: \"number\", defaultVal: \"—\" },\n { name: \"align\", type: '\"left\" | \"center\" | \"right\"', defaultVal: '\"left\"' },\n { name: \"ellipsis\", type: \"boolean\", defaultVal: \"false\" },\n { name: \"label\", type: \"string (usado no card mode)\", defaultVal: \"—\" },\n];\n\nconst CARD_ROW_PROPS: PropItem[] = [\n { name: \"header\", type: \"ReactNode (esquerda)\", defaultVal: \"—\" },\n { name: \"headerActions\", type: \"ReactNode (direita)\", defaultVal: \"—\" },\n { name: \"items\", type: \"ReadonlyArray<{ label, value, key? }>\", defaultVal: \"—\" },\n { name: \"selected\", type: \"boolean\", defaultVal: \"false\" },\n { name: \"clickable\", type: \"boolean\", defaultVal: \"auto\" },\n { name: \"onClick\", type: \"(e: MouseEvent) => void\", defaultVal: \"—\" },\n];\n\ntype User = {\n id: number;\n name: string;\n email: string;\n role: string;\n status: \"active\" | \"inactive\" | \"pending\";\n};\n\nconst SEED_USERS: User[] = [\n { id: 1, name: \"Ana Souza\", email: \"ana@igreen.com\", role: \"Admin\", status: \"active\" },\n { id: 2, name: \"Bruno Lima\", email: \"bruno@igreen.com\", role: \"Manager\", status: \"active\" },\n { id: 3, name: \"Carla Mendes\", email: \"carla@igreen.com\", role: \"Analyst\", status: \"pending\" },\n { id: 4, name: \"Diego Rocha\", email: \"diego@igreen.com\", role: \"Analyst\", status: \"inactive\" },\n { id: 5, name: \"Eduarda Lima\", email: \"eduarda@igreen.com\", role: \"Admin\", status: \"active\" },\n { id: 6, name: \"Felipe Costa\", email: \"felipe@igreen.com\", role: \"Manager\", status: \"active\" },\n { id: 7, name: \"Giovana Reis\", email: \"giovana@igreen.com\", role: \"Analyst\", status: \"active\" },\n { id: 8, name: \"Henrique Sá\", email: \"henrique@igreen.com\", role: \"Viewer\", status: \"pending\" },\n];\n\nconst statusColor: Record<User[\"status\"], \"success\" | \"warning\" | \"secondary\"> = {\n active: \"success\",\n pending: \"warning\",\n inactive: \"secondary\",\n};\n\n/* App.tsx uses: import TableDoc from \"./preview/pages/TableDoc\" (default import)\n Therefore: export default function TableDoc() */\nexport default function TableDoc() {\n return (\n <DocLayout toc={TOC}>\n <DocHeader\n category=\"Tables\"\n title=\"Table\"\n description=\"Primitivo de tabela em divs. API 'lego' controlada — você gerencia widths, sort, selection. Para tabelas feature-completas use <DataTable>.\"\n />\n\n <DocSeparator />\n\n {/* Hero preview */}\n <ExampleSection id=\"ex-hero\" title=\"\" description=\"\">\n <div className=\"w-full\">\n <HeroExample />\n </div>\n </ExampleSection>\n\n <SectionH2 id=\"examples\" title=\"Examples\" />\n\n <ExampleSection\n id=\"ex-density\"\n title=\"Densidades\"\n description=\"Três modos: compact (32px), standard (40px, default) e comfortable (44px). Density propaga automaticamente pelos subcomponentes via Context interno.\"\n code={`<Table density=\"compact\">\n <TableHead>{/* ... */}</TableHead>\n <TableBody>{/* ... */}</TableBody>\n</Table>`}\n >\n <div className=\"w-full\">\n <DensityExample />\n </div>\n </ExampleSection>\n\n <ExampleSection\n id=\"ex-sticky\"\n title=\"Sticky header\"\n description=\"Header sticky no topo durante scroll vertical (default). Use altura fixa no container pra ativar o scroll.\"\n code={`<div style={{ height: 320 }}>\n <Table>\n <TableHead sticky>{/* ... */}</TableHead>\n <TableBody>{/* ... */}</TableBody>\n </Table>\n</div>`}\n >\n <div className=\"w-full\">\n <StickyExample />\n </div>\n </ExampleSection>\n\n <ExampleSection\n id=\"ex-pin-sort-resize\"\n title=\"Pin + Sort + Resize\"\n description=\"Coluna fixa à esquerda (checkbox + nome) e à direita (actions). Headers clicáveis ciclam asc → desc → none. Drag no edge direito do header redimensiona.\"\n code={`const { widths, offsets } = useColumnWidths(cols);\n\n<TableHeadCell\n width={widths.name}\n pinned=\"left\"\n pinOffset={offsets.name}\n sortable\n sortDirection={sort.field === \"name\" ? sort.dir : null}\n onSortClick={() => toggleSort(\"name\")}\n resizable\n onResize={(w) => setWidth(\"name\", w)}\n>\n Nome\n</TableHeadCell>`}\n >\n <div className=\"w-full\">\n <PinSortResizeExample />\n </div>\n </ExampleSection>\n\n <ExampleSection\n id=\"ex-selection\"\n title=\"Selection / hover / clickable\"\n description=\"A row tem visual de selected (bg brand alpha) e hover. Combinar clickable + onClick faz a linha toda virar trigger.\"\n code={`<TableRow\n selected={isSelected(row.id)}\n clickable\n onClick={() => toggleRow(row.id)}\n>\n {/* cells */}\n</TableRow>`}\n >\n <div className=\"w-full\">\n <SelectionExample />\n </div>\n </ExampleSection>\n\n <ExampleSection\n id=\"ex-card-mode\"\n title=\"Card mode (responsive)\"\n description=\"No `<Table>` puro, o consumer renderiza `<TableCardRow>` manualmente em vez de `<TableRow>` quando o container fica estreito (decide via ResizeObserver/matchMedia). Já no `<DataTable>`, o switch é automático: abaixo de `cardBreakpoint` (default 768px), todas as rows viram cards automaticamente — sem trabalho extra.\"\n code={`<TableCardRow\n header={<strong>{row.name}</strong>}\n headerActions={<Button size=\"icon-xs\"><Pencil /></Button>}\n items={[\n { label: \"Email\", value: row.email },\n { label: \"Cargo\", value: row.role },\n ]}\n/>`}\n >\n <div className=\"w-full\">\n <CardModeExample />\n </div>\n </ExampleSection>\n\n <ExampleSection\n id=\"ex-full\"\n title=\"Tabela completa (estilo design-and-table-v2)\"\n description=\"Replica visual da tabela de CRUD: 13 colunas com icone de tipo, sort badge, cell borders, sticky right action column, strip lateral brand em selected, hover '...' na row, status/category/person/agent cells customizadas.\"\n code={`<Table cellBorders density=\"comfortable\">\n <TableHead>\n <TableHeadCell icon={Hash} width={120}>ID</TableHeadCell>\n <TableHeadCell icon={User} sortable sortDirection=\"asc\">Nome</TableHeadCell>\n <TableHeadCell icon={AtSign} headMenu={<Button>...</Button>}>Email</TableHeadCell>\n </TableHead>\n <TableBody>\n {rows.map(row => (\n <TableRow key={row.id} selected={isSelected(row.id)}>\n <TableCell>{row.id}</TableCell>\n <TableCell><PersonCell row={row} /></TableCell>\n </TableRow>\n ))}\n </TableBody>\n</Table>`}\n >\n <div className=\"w-full\">\n <ClientsTableExample />\n </div>\n </ExampleSection>\n\n {/* ── API Reference ───────────────────────────────────────────── */}\n <SectionH2 id=\"api\" title=\"API Reference\" />\n\n <div id=\"api-table\" className=\"mb-12\">\n <h3 className=\"text-title-lg font-semibold text-fg-default mb-gp-md\">&lt;Table&gt;</h3>\n <PropsTable items={TABLE_PROPS} />\n </div>\n\n <div id=\"api-head\" className=\"mb-12\">\n <h3 className=\"text-title-lg font-semibold text-fg-default mb-gp-md\">&lt;TableHead&gt;</h3>\n <PropsTable items={HEAD_PROPS} />\n </div>\n\n <div id=\"api-headcell\" className=\"mb-12\">\n <h3 className=\"text-title-lg font-semibold text-fg-default mb-gp-md\">&lt;TableHeadCell&gt;</h3>\n <PropsTable items={HEAD_CELL_PROPS} />\n </div>\n\n <div id=\"api-row\" className=\"mb-12\">\n <h3 className=\"text-title-lg font-semibold text-fg-default mb-gp-md\">&lt;TableRow&gt;</h3>\n <PropsTable items={ROW_PROPS} />\n </div>\n\n <div id=\"api-cell\" className=\"mb-12\">\n <h3 className=\"text-title-lg font-semibold text-fg-default mb-gp-md\">&lt;TableCell&gt;</h3>\n <PropsTable items={CELL_PROPS} />\n </div>\n\n <div id=\"api-cardrow\" className=\"mb-12\">\n <h3 className=\"text-title-lg font-semibold text-fg-default mb-gp-md\">&lt;TableCardRow&gt;</h3>\n <PropsTable items={CARD_ROW_PROPS} />\n </div>\n </DocLayout>\n );\n}\n\n/* ── Examples ─────────────────────────────────────────────────────── */\n\nfunction HeroExample() {\n const columns = useMemo(() => [\n { field: \"name\", headerName: \"Nome\", width: 180 },\n { field: \"email\", headerName: \"Email\", width: 220 },\n { field: \"status\", headerName: \"Status\", width: 100 },\n ], []);\n const { widths } = useColumnWidths(columns);\n\n return (\n <Table ariaLabel=\"Hero example\">\n <TableHead>\n {columns.map((c) => (\n <TableHeadCell key={c.field} width={widths[c.field]}>{c.headerName}</TableHeadCell>\n ))}\n </TableHead>\n <TableBody>\n {SEED_USERS.slice(0, 3).map((row) => (\n <TableRow key={row.id}>\n <TableCell width={widths.name}>{row.name}</TableCell>\n <TableCell width={widths.email}>{row.email}</TableCell>\n <TableCell width={widths.status}>\n <Badge color={statusColor[row.status]} variant=\"soft\" size=\"sm\">{row.status}</Badge>\n </TableCell>\n </TableRow>\n ))}\n </TableBody>\n </Table>\n );\n}\n\nfunction DensityExample() {\n const [density, setDensity] = useState<TableDensity>(\"standard\");\n const columns = useMemo(() => [\n { field: \"name\", headerName: \"Nome\", width: 180 },\n { field: \"email\", headerName: \"Email\", width: 220 },\n { field: \"role\", headerName: \"Cargo\", width: 120 },\n { field: \"status\", headerName: \"Status\", width: 110 },\n ], []);\n const { widths } = useColumnWidths(columns);\n\n return (\n <div className=\"flex flex-col gap-gp-md\">\n <div className=\"flex gap-gp-md\">\n {([\"compact\", \"standard\", \"comfortable\"] as const).map((d) => (\n <Button\n key={d}\n size=\"xs\"\n variant={density === d ? \"filled\" : \"outline\"}\n color={density === d ? \"primary\" : \"secondary\"}\n onClick={() => setDensity(d)}\n >\n {d}\n </Button>\n ))}\n </div>\n\n <Table density={density} ariaLabel=\"Density example\">\n <TableHead>\n {columns.map((c) => (\n <TableHeadCell key={c.field} width={widths[c.field]}>{c.headerName}</TableHeadCell>\n ))}\n </TableHead>\n <TableBody>\n {SEED_USERS.slice(0, 4).map((row) => (\n <TableRow key={row.id}>\n <TableCell width={widths.name}>{row.name}</TableCell>\n <TableCell width={widths.email}>{row.email}</TableCell>\n <TableCell width={widths.role}>{row.role}</TableCell>\n <TableCell width={widths.status}>\n <Badge color={statusColor[row.status]} variant=\"soft\" size=\"md\">{row.status}</Badge>\n </TableCell>\n </TableRow>\n ))}\n </TableBody>\n </Table>\n </div>\n );\n}\n\nfunction StickyExample() {\n const columns = useMemo(() => [\n { field: \"name\", headerName: \"Nome\", width: 180 },\n { field: \"email\", headerName: \"Email\", width: 220 },\n { field: \"role\", headerName: \"Cargo\", width: 120 },\n ], []);\n const { widths } = useColumnWidths(columns);\n const bigRows = useMemo(\n () => Array.from({ length: 30 }, (_, i) => SEED_USERS[i % SEED_USERS.length]),\n [],\n );\n\n return (\n <div style={{ height: 320 }}>\n <Table ariaLabel=\"Sticky example\">\n <TableHead>\n {columns.map((c) => (\n <TableHeadCell key={c.field} width={widths[c.field]}>{c.headerName}</TableHeadCell>\n ))}\n </TableHead>\n <TableBody>\n {bigRows.map((row, i) => (\n <TableRow key={`${row.id}-${i}`}>\n <TableCell width={widths.name}>{row.name}</TableCell>\n <TableCell width={widths.email}>{row.email}</TableCell>\n <TableCell width={widths.role}>{row.role}</TableCell>\n </TableRow>\n ))}\n </TableBody>\n </Table>\n </div>\n );\n}\n\nfunction PinSortResizeExample() {\n const initialCols = useMemo(\n () => [\n { field: \"select\", headerName: \"\", width: 56, pinned: \"left\" as const, resizable: false, sortable: false },\n { field: \"name\", headerName: \"Nome\", width: 160, pinned: \"left\" as const, resizable: true, sortable: true },\n { field: \"email\", headerName: \"Email\", width: 200, resizable: true, sortable: true },\n { field: \"role\", headerName: \"Cargo\", width: 120, resizable: true, sortable: true },\n { field: \"status\", headerName: \"Status\", width: 110, resizable: true, sortable: true },\n { field: \"actions\", headerName: \"\", width: 56, pinned: \"right\" as const, resizable: false, sortable: false },\n ],\n [],\n );\n\n const [widthMap, setWidthMap] = useState<Record<string, number>>({});\n const cols = useMemo(\n () => initialCols.map((c) => ({ ...c, width: widthMap[c.field] ?? c.width })),\n [initialCols, widthMap],\n );\n const { widths, offsets } = useColumnWidths(cols);\n\n const [sort, setSort] = useState<{ field: string; dir: SortDirection }>({ field: \"\", dir: null });\n const onSort = (field: string) => {\n setSort((prev) => {\n if (prev.field !== field) return { field, dir: \"asc\" };\n if (prev.dir === \"asc\") return { field, dir: \"desc\" };\n return { field: \"\", dir: null };\n });\n };\n\n return (\n <Table ariaLabel=\"Pin + sort + resize example\">\n <TableHead>\n {cols.map((c) => (\n <TableHeadCell\n key={c.field}\n width={widths[c.field]}\n pinned={c.pinned}\n pinOffset={offsets[c.field]}\n sortable={c.sortable}\n sortDirection={sort.field === c.field ? sort.dir : null}\n onSortClick={() => onSort(c.field)}\n resizable={c.resizable}\n onResize={(w) => setWidthMap((m) => ({ ...m, [c.field]: w }))}\n >\n {c.headerName}\n </TableHeadCell>\n ))}\n </TableHead>\n <TableBody>\n {SEED_USERS.map((row) => (\n <TableRow key={row.id}>\n <TableCell width={widths.select} pinned=\"left\" pinOffset={offsets.select}>\n <Checkbox aria-label={`Selecionar ${row.name}`} />\n </TableCell>\n <TableCell width={widths.name} pinned=\"left\" pinOffset={offsets.name} ellipsis>{row.name}</TableCell>\n <TableCell width={widths.email} ellipsis>{row.email}</TableCell>\n <TableCell width={widths.role}>{row.role}</TableCell>\n <TableCell width={widths.status}>\n <Badge color={statusColor[row.status]} variant=\"soft\" size=\"md\">{row.status}</Badge>\n </TableCell>\n <TableCell width={widths.actions} pinned=\"right\" pinOffset={offsets.actions} align=\"center\">\n <Button size=\"icon-xs\" variant=\"ghost\" color=\"secondary\" aria-label=\"Mais\">\n <MoreVertical />\n </Button>\n </TableCell>\n </TableRow>\n ))}\n </TableBody>\n </Table>\n );\n}\n\nfunction SelectionExample() {\n const [selected, setSelected] = useState<Set<number>>(new Set([2, 5]));\n const columns = useMemo(() => [\n { field: \"select\", headerName: \"\", width: 56 },\n { field: \"name\", headerName: \"Nome\", width: 180 },\n { field: \"email\", headerName: \"Email\", width: 220 },\n ], []);\n const { widths } = useColumnWidths(columns);\n\n const toggle = (id: number) => {\n setSelected((prev) => {\n const next = new Set(prev);\n if (next.has(id)) next.delete(id); else next.add(id);\n return next;\n });\n };\n\n const rows = SEED_USERS.slice(0, 6);\n const allSelected = selected.size === rows.length;\n const someSelected = selected.size > 0 && !allSelected;\n const toggleAll = () => {\n if (selected.size > 0) setSelected(new Set());\n else setSelected(new Set(rows.map((r) => r.id)));\n };\n\n return (\n <Table ariaLabel=\"Selection example\">\n <TableHead>\n <TableHeadCell width={widths.select} align=\"center\">\n <Checkbox\n checked={allSelected ? true : someSelected ? \"indeterminate\" : false}\n onCheckedChange={toggleAll}\n aria-label=\"Selecionar todos\"\n />\n </TableHeadCell>\n {columns.slice(1).map((c) => (\n <TableHeadCell key={c.field} width={widths[c.field]}>{c.headerName}</TableHeadCell>\n ))}\n </TableHead>\n <TableBody>\n {rows.map((row) => (\n <TableRow\n key={row.id}\n selected={selected.has(row.id)}\n clickable\n onClick={() => toggle(row.id)}\n >\n <TableCell width={widths.select} align=\"center\">\n <Checkbox\n checked={selected.has(row.id)}\n aria-label={`Selecionar ${row.name}`}\n onClick={(e) => e.stopPropagation()}\n onCheckedChange={() => toggle(row.id)}\n />\n </TableCell>\n <TableCell width={widths.name}>{row.name}</TableCell>\n <TableCell width={widths.email}>{row.email}</TableCell>\n </TableRow>\n ))}\n </TableBody>\n </Table>\n );\n}\n\nfunction CardModeExample() {\n return (\n <Table cardBreakpoint={768} ariaLabel=\"Card mode example\">\n <TableBody>\n {SEED_USERS.slice(0, 4).map((row) => (\n <TableCardRow\n key={row.id}\n header={\n <>\n <Checkbox aria-label={`Selecionar ${row.name}`} />\n <strong className=\"text-paragraph-md text-fg-strong\">{row.name}</strong>\n </>\n }\n headerActions={\n <Button size=\"icon-xs\" variant=\"ghost\" color=\"secondary\" aria-label=\"Editar\">\n <Pencil />\n </Button>\n }\n items={[\n { label: \"Email\", value: row.email },\n { label: \"Cargo\", value: row.role },\n {\n label: \"Status\",\n value: <Badge color={statusColor[row.status]} variant=\"soft\" size=\"md\">{row.status}</Badge>,\n },\n ]}\n />\n ))}\n </TableBody>\n </Table>\n );\n}\n\n/* ═══════════════════════════════════════════════════════════════════════════\n ClientsTable example: replica do design-and-table-v2\n ═══════════════════════════════════════════════════════════════════════════ */\n\nexport const STATUSES: Record<string, { label: string; color: string }> = {\n active: { label: \"Ativo\", color: \"var(--color-fg-success)\" },\n pending: { label: \"Pendente\", color: \"var(--color-fg-warning)\" },\n paused: { label: \"Pausado\", color: \"var(--color-fg-info)\" },\n inactive: { label: \"Inativo\", color: \"var(--color-fg-muted)\" },\n};\n\nexport type CategoryKind = \"warning\" | \"info\" | \"success\" | \"neutral\";\nexport const CATEGORIES: Record<string, { label: string; kind: CategoryKind }> = {\n royal: { label: \"Royal\", kind: \"warning\" },\n licenciado: { label: \"Licenciado\", kind: \"info\" },\n lead: { label: \"Lead\", kind: \"success\" },\n};\n\nexport const AGENTS: Record<string, { name: string; initials: string; color: string }> = {\n you: { name: \"Voce\", initials: \"VC\", color: \"#0a3a2e\" },\n aline: { name: \"Aline Castro\", initials: \"AC\", color: \"#f59e0b\" },\n carlos: { name: \"Carlos Souza\", initials: \"CS\", color: \"#8754ec\" },\n maria: { name: \"Maria Lima\", initials: \"ML\", color: \"#ef4444\" },\n};\n\nexport type ClientRow = {\n id: string;\n name: string;\n initials: string;\n avatarColor: string;\n email: string;\n phone: string;\n statusId: keyof typeof STATUSES;\n categoryId: keyof typeof CATEGORIES;\n location: string;\n value: number;\n agentId: keyof typeof AGENTS;\n createdAt: number;\n lastContact: number;\n};\n\nconst BASE_DATE = new Date(\"2026-04-15T12:00:00Z\").getTime();\nconst DAY_MS = 86400000;\n\nexport const CLIENTS_MOCK: ClientRow[] = [\n { id: \"CLI-2401\", name: \"Maria Silva\", initials: \"MS\", avatarColor: \"#f59e0b\", email: \"maria.silva@example.com\", phone: \"+55 11 91234-5678\", statusId: \"active\", categoryId: \"royal\", location: \"São Paulo, SP\", value: 4800, agentId: \"you\", createdAt: BASE_DATE - 65 * DAY_MS, lastContact: BASE_DATE - 2 * DAY_MS },\n { id: \"CLI-2402\", name: \"João Santos\", initials: \"JS\", avatarColor: \"#0a3a2e\", email: \"joao.santos@example.com\", phone: \"+55 11 92345-6789\", statusId: \"pending\", categoryId: \"licenciado\", location: \"Rio de Janeiro, RJ\", value: 12300, agentId: \"aline\", createdAt: BASE_DATE - 58 * DAY_MS, lastContact: BASE_DATE - 5 * DAY_MS },\n { id: \"CLI-2403\", name: \"Carlos Oliveira\", initials: \"CO\", avatarColor: \"#8754ec\", email: \"carlos.oliveira@example.com\", phone: \"+55 11 93456-7890\", statusId: \"active\", categoryId: \"lead\", location: \"Belo Horizonte, MG\", value: 2150, agentId: \"carlos\", createdAt: BASE_DATE - 51 * DAY_MS, lastContact: BASE_DATE - 1 * DAY_MS },\n { id: \"CLI-2404\", name: \"Ana Costa\", initials: \"AC\", avatarColor: \"#1cb280\", email: \"ana.costa@example.com\", phone: \"+55 11 94567-8901\", statusId: \"paused\", categoryId: \"royal\", location: \"Porto Alegre, RS\", value: 8900, agentId: \"maria\", createdAt: BASE_DATE - 44 * DAY_MS, lastContact: BASE_DATE - 12 * DAY_MS },\n { id: \"CLI-2405\", name: \"Pedro Pereira\", initials: \"PP\", avatarColor: \"#ef4444\", email: \"pedro.pereira@example.com\", phone: \"+55 11 95678-9012\", statusId: \"inactive\", categoryId: \"lead\", location: \"Curitiba, PR\", value: 1100, agentId: \"you\", createdAt: BASE_DATE - 37 * DAY_MS, lastContact: BASE_DATE - 30 * DAY_MS },\n { id: \"CLI-2406\", name: \"Lúcia Almeida\", initials: \"LA\", avatarColor: \"#f9a47a\", email: \"lucia.almeida@example.com\", phone: \"+55 11 96789-0123\", statusId: \"active\", categoryId: \"licenciado\", location: \"Recife, PE\", value: 6750, agentId: \"aline\", createdAt: BASE_DATE - 30 * DAY_MS, lastContact: BASE_DATE - 3 * DAY_MS },\n { id: \"CLI-2407\", name: \"Roberto Souza\", initials: \"RS\", avatarColor: \"#0088cc\", email: \"roberto.souza@example.com\", phone: \"+55 11 97890-1234\", statusId: \"pending\", categoryId: \"royal\", location: \"São Paulo, SP\", value: 15200, agentId: \"carlos\", createdAt: BASE_DATE - 23 * DAY_MS, lastContact: BASE_DATE - 7 * DAY_MS },\n { id: \"CLI-2408\", name: \"Fernanda Lima\", initials: \"FL\", avatarColor: \"#e1306c\", email: \"fernanda.lima@example.com\", phone: \"+55 11 98901-2345\", statusId: \"active\", categoryId: \"lead\", location: \"Rio de Janeiro, RJ\", value: 3400, agentId: \"maria\", createdAt: BASE_DATE - 16 * DAY_MS, lastContact: BASE_DATE - 1 * DAY_MS },\n { id: \"CLI-2409\", name: \"Bruno Rodrigues\", initials: \"BR\", avatarColor: \"#70c748\", email: \"bruno.rodrigues@example.com\", phone: \"+55 11 99012-3456\", statusId: \"paused\", categoryId: \"licenciado\", location: \"Belo Horizonte, MG\", value: 5600, agentId: \"you\", createdAt: BASE_DATE - 9 * DAY_MS, lastContact: BASE_DATE - 6 * DAY_MS },\n { id: \"CLI-2410\", name: \"Camila Ribeiro\", initials: \"CR\", avatarColor: \"#8754ec\", email: \"camila.ribeiro@example.com\", phone: \"+55 11 90123-4567\", statusId: \"active\", categoryId: \"royal\", location: \"Porto Alegre, RS\", value: 9800, agentId: \"aline\", createdAt: BASE_DATE - 2 * DAY_MS, lastContact: BASE_DATE },\n];\n\nconst MONTHS_SHORT = [\"jan\", \"fev\", \"mar\", \"abr\", \"mai\", \"jun\", \"jul\", \"ago\", \"set\", \"out\", \"nov\", \"dez\"];\nexport function formatDateShort(value: number): string {\n const d = new Date(value);\n const day = d.getDate().toString().padStart(2, \"0\");\n return `${day} de ${MONTHS_SHORT[d.getMonth()]}`;\n}\nexport function formatCurrency(value: number): string {\n return value.toLocaleString(\"pt-BR\", { style: \"currency\", currency: \"BRL\", minimumFractionDigits: 2 });\n}\n\nexport function ClientAvatar({ initials, color, sm = false }: { initials: string; color: string; sm?: boolean }) {\n return (\n <span\n className={`inline-grid place-items-center rounded-radius-full text-white font-bold shrink-0 ${sm ? \"size-[22px] text-[10px]\" : \"size-[28px] text-[11px]\"}`}\n style={{ background: color }}\n aria-hidden\n >\n {initials}\n </span>\n );\n}\n\nexport function PersonCell({ row }: { row: ClientRow }) {\n return (\n <span className=\"inline-flex items-center gap-gp-md whitespace-nowrap overflow-hidden\" title={row.name}>\n <ClientAvatar initials={row.initials} color={row.avatarColor} />\n <span className=\"truncate font-medium text-fg-default\">{row.name}</span>\n </span>\n );\n}\n\nexport function AgentCell({ agentId }: { agentId: keyof typeof AGENTS }) {\n const a = AGENTS[agentId];\n return (\n <span className=\"inline-flex items-center gap-gp-md whitespace-nowrap\" title={a.name}>\n <ClientAvatar initials={a.initials} color={a.color} sm />\n <span className=\"text-fg-default\">{a.name}</span>\n </span>\n );\n}\n\nexport function StatusDot({ statusId }: { statusId: keyof typeof STATUSES }) {\n const s = STATUSES[statusId];\n return (\n <span className=\"inline-flex items-center gap-gp-md text-fg-default\">\n <span className=\"size-[8px] rounded-radius-full shrink-0\" style={{ background: s.color }} aria-hidden />\n {s.label}\n </span>\n );\n}\n\nexport function CategoryChip({ categoryId }: { categoryId: keyof typeof CATEGORIES }) {\n const c = CATEGORIES[categoryId];\n const colorMap = {\n warning: \"warning\",\n info: \"info\",\n success: \"success\",\n neutral: \"neutral\",\n } as const;\n return (\n <Chip color={colorMap[c.kind]} variant=\"soft\" size=\"sm\">\n {c.label}\n </Chip>\n );\n}\n\nexport function ClientsTableExample() {\n const [selected, setSelected] = useState<Set<string>>(new Set([\"CLI-2401\"]));\n const [openRowId, setOpenRowId] = useState<string | null>(null);\n const [sortDir, setSortDir] = useState<SortDirection>(\"asc\");\n\n const toggle = (id: string) => {\n setSelected((prev) => {\n const next = new Set(prev);\n if (next.has(id)) next.delete(id); else next.add(id);\n return next;\n });\n };\n\n const allSelected = selected.size === CLIENTS_MOCK.length;\n const someSelected = selected.size > 0 && !allSelected;\n const toggleAll = () => {\n if (selected.size > 0) setSelected(new Set());\n else setSelected(new Set(CLIENTS_MOCK.map((r) => r.id)));\n };\n\n const cycleSort = () => {\n setSortDir((prev) => (prev === \"asc\" ? \"desc\" : prev === \"desc\" ? null : \"asc\"));\n };\n\n const initialCols = useMemo(() => [\n { field: \"select\", headerName: \"\", width: 56 },\n { field: \"id\", headerName: \"ID\", width: 120, icon: Hash },\n { field: \"name\", headerName: \"Nome\", width: 220, icon: User },\n { field: \"email\", headerName: \"Email\", width: 240, icon: AtSign },\n { field: \"phone\", headerName: \"Telefone\", width: 170, icon: Phone },\n { field: \"status\", headerName: \"Status\", width: 140, icon: CheckCircle2 },\n { field: \"category\", headerName: \"Categoria\", width: 130, icon: Tag },\n { field: \"agent\", headerName: \"Atribuido\", width: 170, icon: UsersIcon },\n { field: \"value\", headerName: \"Valor\", width: 130, icon: DollarSign },\n { field: \"createdAt\", headerName: \"Criado em\", width: 130, icon: Calendar },\n { field: \"lastContact\", headerName: \"Ultimo contato\", width: 150, icon: Calendar },\n { field: \"location\", headerName: \"Localizacao\", width: 150, icon: Type },\n { field: \"actions\", headerName: \"\", width: 44 },\n ], []);\n\n const [widthMap, setWidthMap] = useState<Record<string, number>>({});\n const cols = useMemo(\n () => initialCols.map((c) => ({ ...c, width: widthMap[c.field] ?? c.width })),\n [initialCols, widthMap],\n );\n\n const { widths } = useColumnWidths(cols);\n\n return (\n <Table cellBorders density=\"comfortable\" ariaLabel=\"Tabela de clientes\">\n <TableHead>\n <TableHeadCell width={widths.select} align=\"center\">\n <Checkbox\n checked={allSelected ? true : someSelected ? \"indeterminate\" : false}\n onCheckedChange={toggleAll}\n aria-label=\"Selecionar todos\"\n />\n </TableHeadCell>\n\n {cols.slice(1, -1).map((c) => (\n <TableHeadCell\n key={c.field}\n width={widths[c.field]}\n icon={c.icon}\n sortable={c.field === \"name\"}\n sortDirection={c.field === \"name\" ? sortDir : null}\n sortIndex={1}\n onSortClick={c.field === \"name\" ? cycleSort : undefined}\n resizable\n onResize={(w) => setWidthMap((m) => ({ ...m, [c.field]: w }))}\n headMenu={\n <Button size=\"icon-2xs\" variant=\"ghost\" color=\"secondary\" aria-label={`Menu da coluna ${c.headerName}`} onClick={(e: React.MouseEvent) => e.stopPropagation()}>\n <MoreVertical />\n </Button>\n }\n >\n {c.headerName}\n </TableHeadCell>\n ))}\n\n <TableHeadCell width={widths.actions} align=\"center\" />\n </TableHead>\n\n <TableBody>\n {CLIENTS_MOCK.map((row) => {\n const isSelected = selected.has(row.id);\n return (\n <TableRow\n key={row.id}\n selected={isSelected}\n open={openRowId === row.id}\n clickable\n onClick={() => setOpenRowId((cur) => (cur === row.id ? null : row.id))}\n >\n <TableCell width={widths.select} align=\"center\">\n <Checkbox\n checked={isSelected}\n onCheckedChange={() => toggle(row.id)}\n onClick={(e: React.MouseEvent) => e.stopPropagation()}\n aria-label={`Selecionar ${row.name}`}\n />\n </TableCell>\n\n <TableCell width={widths.id}>\n <span className=\"text-fg-muted tabular-nums\">{row.id}</span>\n </TableCell>\n\n <TableCell width={widths.name}>\n <PersonCell row={row} />\n </TableCell>\n\n <TableCell width={widths.email}>\n <a\n href={`mailto:${row.email}`}\n className=\"text-fg-brand hover:underline\"\n onClick={(e: React.MouseEvent) => e.stopPropagation()}\n >\n {row.email}\n </a>\n </TableCell>\n\n <TableCell width={widths.phone}>\n <a\n href={`tel:${row.phone.replace(/\\D/g, \"\")}`}\n className=\"text-fg-brand hover:underline\"\n onClick={(e: React.MouseEvent) => e.stopPropagation()}\n >\n {row.phone}\n </a>\n </TableCell>\n\n <TableCell width={widths.status}>\n <StatusDot statusId={row.statusId} />\n </TableCell>\n\n <TableCell width={widths.category}>\n <CategoryChip categoryId={row.categoryId} />\n </TableCell>\n\n <TableCell width={widths.agent}>\n <AgentCell agentId={row.agentId} />\n </TableCell>\n\n <TableCell width={widths.value}>\n <span className=\"font-semibold tabular-nums\">{formatCurrency(row.value)}</span>\n </TableCell>\n\n <TableCell width={widths.createdAt}>\n <span className=\"text-fg-muted tabular-nums\">{formatDateShort(row.createdAt)}</span>\n </TableCell>\n\n <TableCell width={widths.lastContact}>\n <span className=\"text-fg-muted tabular-nums\">{formatDateShort(row.lastContact)}</span>\n </TableCell>\n\n <TableCell width={widths.location}>{row.location}</TableCell>\n\n <TableCell width={widths.actions} align=\"center\" className=\"!px-0 opacity-0 group-hover/row:opacity-100 transition-opacity\">\n <Button size=\"icon-xs\" variant=\"ghost\" color=\"secondary\" aria-label=\"Acoes\" onClick={(e: React.MouseEvent<HTMLButtonElement>) => e.stopPropagation()}>\n <MoreHorizontal />\n </Button>\n </TableCell>\n </TableRow>\n );\n })}\n </TableBody>\n </Table>\n );\n}\n","import {\n CLIENTS_MOCK,\n STATUSES,\n CATEGORIES,\n AGENTS,\n type ClientRow,\n} from \"../TableDoc\";\n\n/* ── Dataset 87 clientes (bate com badge do print) ─────────────── */\n\nexport const CLIENTS_87: ClientRow[] = Array.from({ length: 9 }, (_, batch) =>\n CLIENTS_MOCK.map((row, i) => ({\n ...row,\n id: `CLI-${2400 + batch * 10 + i}`,\n })),\n)\n .flat()\n .slice(0, 87);\n\n/* ── Lookups por categoria de status (column color mapping) ────── */\n\nexport const STATUS_COLOR_MAP: Record<string, string> = {\n active: \"success\",\n pending: \"warning\",\n paused: \"info\",\n inactive: \"neutral\",\n};\n\nexport const STATUS_DOT: Record<string, string> = {\n active: \"var(--color-fg-success)\",\n pending: \"var(--color-fg-warning)\",\n paused: \"var(--color-fg-info)\",\n inactive: \"var(--color-fg-muted)\",\n};\n\nexport const CATEGORY_KIND: Record<string, \"warning\" | \"info\" | \"success\"> = {\n royal: \"warning\",\n licenciado: \"info\",\n lead: \"success\",\n};\n\n/* ── Options pra filters/selects ───────────────────────────────── */\n\nexport const STATUS_OPTIONS = Object.entries(STATUSES).map(([v, m]) => ({\n value: v,\n label: m.label,\n color: STATUS_COLOR_MAP[v] ?? \"neutral\",\n}));\n\nexport const CATEGORY_OPTIONS = Object.entries(CATEGORIES).map(([v, m]) => ({\n value: v,\n label: m.label,\n color: m.kind === \"neutral\" ? \"neutral\" : m.kind,\n}));\n\nexport const AGENT_OPTIONS = Object.entries(AGENTS).map(([v, a]) => ({\n value: v,\n label: a.name,\n}));\n\n/* ── Avatar lookup pro column type \"user\" ──────────────────────── */\n\nexport const AGENTS_LOOKUP = Object.fromEntries(\n Object.entries(AGENTS).map(([id, a]) => [\n id,\n {\n name: a.name,\n initials: a.name\n .split(\" \")\n .map((s) => s[0])\n .join(\"\")\n .slice(0, 2),\n color: a.color,\n },\n ]),\n);\n\n/* ── Kanban columns (1 por status) ─────────────────────────────── */\n\nexport const KANBAN_COLUMNS = Object.entries(STATUSES).map(([id, s]) => ({\n id,\n label: s.label,\n dotColor: STATUS_DOT[id] ?? \"var(--color-fg-muted)\",\n}));\n\n/* ── Cidades pro select do drawer ──────────────────────────────── */\n\nexport const CITIES = [\n \"São Paulo, SP\",\n \"Rio de Janeiro, RJ\",\n \"Belo Horizonte, MG\",\n \"Porto Alegre, RS\",\n \"Curitiba, PR\",\n \"Recife, PE\",\n \"Salvador, BA\",\n \"Fortaleza, CE\",\n \"Brasília, DF\",\n \"Manaus, AM\",\n];\n\n/* ── Helpers de formatação ─────────────────────────────────────── */\n\nexport function formatBRL(value: number) {\n return value.toLocaleString(\"pt-BR\", {\n style: \"currency\",\n currency: \"BRL\",\n minimumFractionDigits: 2,\n });\n}\n\nexport function formatShortDate(ms: number) {\n if (!ms) return \"—\";\n const d = new Date(ms);\n const day = d.getDate().toString().padStart(2, \"0\");\n const months = [\"jan\", \"fev\", \"mar\", \"abr\", \"mai\", \"jun\", \"jul\", \"ago\", \"set\", \"out\", \"nov\", \"dez\"];\n return `${day} ${months[d.getMonth()]}`;\n}\n"],"names":[],"mappings":"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"}
@@ -0,0 +1,72 @@
1
+ "use strict";
2
+ const jsxRuntime = require("react/jsx-runtime");
3
+ const React = require("react");
4
+ const classVarianceAuthority = require("class-variance-authority");
5
+ const chipGroup = require("./chip-group-CsKBBHW2.mjs");
6
+ function _interopNamespaceDefault(e) {
7
+ const n = Object.create(null, { [Symbol.toStringTag]: { value: "Module" } });
8
+ if (e) {
9
+ for (const k in e) {
10
+ if (k !== "default") {
11
+ const d = Object.getOwnPropertyDescriptor(e, k);
12
+ Object.defineProperty(n, k, d.get ? d : {
13
+ enumerable: true,
14
+ get: () => e[k]
15
+ });
16
+ }
17
+ }
18
+ }
19
+ n.default = e;
20
+ return Object.freeze(n);
21
+ }
22
+ const React__namespace = /* @__PURE__ */ _interopNamespaceDefault(React);
23
+ const inputVariants = classVarianceAuthority.cva(
24
+ [
25
+ "flex w-full",
26
+ "bg-bg-input dark:bg-bg-muted",
27
+ "hover:bg-bg-input-hover dark:hover:bg-bg-muted-hover",
28
+ "border border-border-input rounded-radius-lg",
29
+ "px-pad-xl",
30
+ "text-[13px] text-fg-default placeholder:text-fg-muted placeholder:opacity-70",
31
+ "transition-[border-color,box-shadow,background-color] outline-none",
32
+ "disabled:cursor-not-allowed disabled:opacity-50 disabled:hover:bg-bg-input dark:disabled:hover:bg-bg-muted",
33
+ "file:inline-flex file:border-0 file:bg-transparent file:text-sm file:font-medium file:text-fg-default"
34
+ ],
35
+ {
36
+ variants: {
37
+ size: {
38
+ xxs: "min-h-form-xs rounded-radius-md",
39
+ xs: "min-h-form-sm rounded-radius-md",
40
+ sm: "min-h-form-md",
41
+ md: "min-h-form-lg"
42
+ },
43
+ state: {
44
+ default: "focus-visible:border-border-brand focus-visible:shadow-sh-ring",
45
+ error: "border-border-danger-muted focus-visible:border-border-danger-muted focus-visible:shadow-sh-ring-danger",
46
+ warning: "border-border-warning-muted focus-visible:border-border-warning-muted focus-visible:shadow-sh-ring-warning",
47
+ success: "border-border-success-muted focus-visible:border-border-success-muted focus-visible:shadow-sh-ring-success"
48
+ }
49
+ },
50
+ defaultVariants: {
51
+ size: "md",
52
+ state: "default"
53
+ }
54
+ }
55
+ );
56
+ const Input = React__namespace.forwardRef(
57
+ ({ className, type, size, state, ...props }, ref) => {
58
+ return /* @__PURE__ */ jsxRuntime.jsx(
59
+ "input",
60
+ {
61
+ type,
62
+ ref,
63
+ className: chipGroup.cn(inputVariants({ size, state }), className),
64
+ ...props
65
+ }
66
+ );
67
+ }
68
+ );
69
+ Input.displayName = "Input";
70
+ exports.Input = Input;
71
+ exports.inputVariants = inputVariants;
72
+ //# sourceMappingURL=input-374MpdBL.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"input-374MpdBL.mjs","sources":["../../src/components/shadcn/input.tsx"],"sourcesContent":["import * as React from \"react\";\nimport { cva, type VariantProps } from \"class-variance-authority\";\nimport { cn } from \"@/lib/utils\";\n\n/**\n * Input — alinhado com `.tbl-form-input` do design-and-table-v2.\n *\n * Specs base (md, default):\n * - h: 40px (form-lg), px: 12px (pad-xl), radius: 10px (radius-lg)\n * - bg-input (light) / dark:bg-bg-muted\n * - border: 1px solid border-input\n * - font: 13px, color fg-default, placeholder fg-muted\n * - focus: border + shadow-sh-ring por state\n *\n * Pra inputs com prefixo/sufixo/ícone/botão dentro → use `<InputGroup>`.\n * Este componente é puro (só o <input>) — sem wrapper, sem adornments inline.\n */\n\nexport type InputState = \"default\" | \"error\" | \"warning\" | \"success\";\n\nconst inputVariants = cva(\n [\n \"flex w-full\",\n \"bg-bg-input dark:bg-bg-muted\",\n \"hover:bg-bg-input-hover dark:hover:bg-bg-muted-hover\",\n \"border border-border-input rounded-radius-lg\",\n \"px-pad-xl\",\n \"text-[13px] text-fg-default placeholder:text-fg-muted placeholder:opacity-70\",\n \"transition-[border-color,box-shadow,background-color] outline-none\",\n \"disabled:cursor-not-allowed disabled:opacity-50 disabled:hover:bg-bg-input dark:disabled:hover:bg-bg-muted\",\n \"file:inline-flex file:border-0 file:bg-transparent file:text-sm file:font-medium file:text-fg-default\",\n ],\n {\n variants: {\n size: {\n xxs: \"min-h-form-xs rounded-radius-md\",\n xs: \"min-h-form-sm rounded-radius-md\",\n sm: \"min-h-form-md\",\n md: \"min-h-form-lg\",\n },\n state: {\n default: \"focus-visible:border-border-brand focus-visible:shadow-sh-ring\",\n error: \"border-border-danger-muted focus-visible:border-border-danger-muted focus-visible:shadow-sh-ring-danger\",\n warning: \"border-border-warning-muted focus-visible:border-border-warning-muted focus-visible:shadow-sh-ring-warning\",\n success: \"border-border-success-muted focus-visible:border-border-success-muted focus-visible:shadow-sh-ring-success\",\n },\n },\n defaultVariants: {\n size: \"md\",\n state: \"default\",\n },\n },\n);\n\nexport type InputVariantProps = VariantProps<typeof inputVariants>;\n\nexport interface InputProps\n extends Omit<React.InputHTMLAttributes<HTMLInputElement>, \"size\">,\n InputVariantProps {}\n\nconst Input = React.forwardRef<HTMLInputElement, InputProps>(\n ({ className, type, size, state, ...props }, ref) => {\n return (\n <input\n type={type}\n ref={ref}\n className={cn(inputVariants({ size, state }), className)}\n {...props}\n />\n );\n },\n);\nInput.displayName = \"Input\";\n\nexport { Input, inputVariants };\n"],"names":["cva","React","jsx","cn"],"mappings":";;;;;;;;;;;;;;;;;;;;;;AAoBA,MAAM,gBAAgBA,uBAAAA;AAAAA,EACpB;AAAA,IACE;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EAAA;AAAA,EAEF;AAAA,IACE,UAAU;AAAA,MACR,MAAM;AAAA,QACJ,KAAK;AAAA,QACL,IAAK;AAAA,QACL,IAAK;AAAA,QACL,IAAK;AAAA,MAAA;AAAA,MAEP,OAAO;AAAA,QACL,SAAS;AAAA,QACT,OAAS;AAAA,QACT,SAAS;AAAA,QACT,SAAS;AAAA,MAAA;AAAA,IACX;AAAA,IAEF,iBAAiB;AAAA,MACf,MAAM;AAAA,MACN,OAAO;AAAA,IAAA;AAAA,EACT;AAEJ;AAQA,MAAM,QAAQC,iBAAM;AAAA,EAClB,CAAC,EAAE,WAAW,MAAM,MAAM,OAAO,GAAG,MAAA,GAAS,QAAQ;AACnD,WACEC,2BAAAA;AAAAA,MAAC;AAAA,MAAA;AAAA,QACC;AAAA,QACA;AAAA,QACA,WAAWC,UAAAA,GAAG,cAAc,EAAE,MAAM,MAAA,CAAO,GAAG,SAAS;AAAA,QACtD,GAAG;AAAA,MAAA;AAAA,IAAA;AAAA,EAGV;AACF;AACA,MAAM,cAAc;;;"}
@@ -0,0 +1,56 @@
1
+ import { jsx } from "react/jsx-runtime";
2
+ import * as React from "react";
3
+ import { cva } from "class-variance-authority";
4
+ import { c as cn } from "./chip-group-D3D0i72q.mjs";
5
+ const inputVariants = cva(
6
+ [
7
+ "flex w-full",
8
+ "bg-bg-input dark:bg-bg-muted",
9
+ "hover:bg-bg-input-hover dark:hover:bg-bg-muted-hover",
10
+ "border border-border-input rounded-radius-lg",
11
+ "px-pad-xl",
12
+ "text-[13px] text-fg-default placeholder:text-fg-muted placeholder:opacity-70",
13
+ "transition-[border-color,box-shadow,background-color] outline-none",
14
+ "disabled:cursor-not-allowed disabled:opacity-50 disabled:hover:bg-bg-input dark:disabled:hover:bg-bg-muted",
15
+ "file:inline-flex file:border-0 file:bg-transparent file:text-sm file:font-medium file:text-fg-default"
16
+ ],
17
+ {
18
+ variants: {
19
+ size: {
20
+ xxs: "min-h-form-xs rounded-radius-md",
21
+ xs: "min-h-form-sm rounded-radius-md",
22
+ sm: "min-h-form-md",
23
+ md: "min-h-form-lg"
24
+ },
25
+ state: {
26
+ default: "focus-visible:border-border-brand focus-visible:shadow-sh-ring",
27
+ error: "border-border-danger-muted focus-visible:border-border-danger-muted focus-visible:shadow-sh-ring-danger",
28
+ warning: "border-border-warning-muted focus-visible:border-border-warning-muted focus-visible:shadow-sh-ring-warning",
29
+ success: "border-border-success-muted focus-visible:border-border-success-muted focus-visible:shadow-sh-ring-success"
30
+ }
31
+ },
32
+ defaultVariants: {
33
+ size: "md",
34
+ state: "default"
35
+ }
36
+ }
37
+ );
38
+ const Input = React.forwardRef(
39
+ ({ className, type, size, state, ...props }, ref) => {
40
+ return /* @__PURE__ */ jsx(
41
+ "input",
42
+ {
43
+ type,
44
+ ref,
45
+ className: cn(inputVariants({ size, state }), className),
46
+ ...props
47
+ }
48
+ );
49
+ }
50
+ );
51
+ Input.displayName = "Input";
52
+ export {
53
+ Input as I,
54
+ inputVariants as i
55
+ };
56
+ //# sourceMappingURL=input-DF4XAWmr.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"input-DF4XAWmr.mjs","sources":["../../src/components/shadcn/input.tsx"],"sourcesContent":["import * as React from \"react\";\nimport { cva, type VariantProps } from \"class-variance-authority\";\nimport { cn } from \"@/lib/utils\";\n\n/**\n * Input — alinhado com `.tbl-form-input` do design-and-table-v2.\n *\n * Specs base (md, default):\n * - h: 40px (form-lg), px: 12px (pad-xl), radius: 10px (radius-lg)\n * - bg-input (light) / dark:bg-bg-muted\n * - border: 1px solid border-input\n * - font: 13px, color fg-default, placeholder fg-muted\n * - focus: border + shadow-sh-ring por state\n *\n * Pra inputs com prefixo/sufixo/ícone/botão dentro → use `<InputGroup>`.\n * Este componente é puro (só o <input>) — sem wrapper, sem adornments inline.\n */\n\nexport type InputState = \"default\" | \"error\" | \"warning\" | \"success\";\n\nconst inputVariants = cva(\n [\n \"flex w-full\",\n \"bg-bg-input dark:bg-bg-muted\",\n \"hover:bg-bg-input-hover dark:hover:bg-bg-muted-hover\",\n \"border border-border-input rounded-radius-lg\",\n \"px-pad-xl\",\n \"text-[13px] text-fg-default placeholder:text-fg-muted placeholder:opacity-70\",\n \"transition-[border-color,box-shadow,background-color] outline-none\",\n \"disabled:cursor-not-allowed disabled:opacity-50 disabled:hover:bg-bg-input dark:disabled:hover:bg-bg-muted\",\n \"file:inline-flex file:border-0 file:bg-transparent file:text-sm file:font-medium file:text-fg-default\",\n ],\n {\n variants: {\n size: {\n xxs: \"min-h-form-xs rounded-radius-md\",\n xs: \"min-h-form-sm rounded-radius-md\",\n sm: \"min-h-form-md\",\n md: \"min-h-form-lg\",\n },\n state: {\n default: \"focus-visible:border-border-brand focus-visible:shadow-sh-ring\",\n error: \"border-border-danger-muted focus-visible:border-border-danger-muted focus-visible:shadow-sh-ring-danger\",\n warning: \"border-border-warning-muted focus-visible:border-border-warning-muted focus-visible:shadow-sh-ring-warning\",\n success: \"border-border-success-muted focus-visible:border-border-success-muted focus-visible:shadow-sh-ring-success\",\n },\n },\n defaultVariants: {\n size: \"md\",\n state: \"default\",\n },\n },\n);\n\nexport type InputVariantProps = VariantProps<typeof inputVariants>;\n\nexport interface InputProps\n extends Omit<React.InputHTMLAttributes<HTMLInputElement>, \"size\">,\n InputVariantProps {}\n\nconst Input = React.forwardRef<HTMLInputElement, InputProps>(\n ({ className, type, size, state, ...props }, ref) => {\n return (\n <input\n type={type}\n ref={ref}\n className={cn(inputVariants({ size, state }), className)}\n {...props}\n />\n );\n },\n);\nInput.displayName = \"Input\";\n\nexport { Input, inputVariants };\n"],"names":[],"mappings":";;;;AAoBA,MAAM,gBAAgB;AAAA,EACpB;AAAA,IACE;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EAAA;AAAA,EAEF;AAAA,IACE,UAAU;AAAA,MACR,MAAM;AAAA,QACJ,KAAK;AAAA,QACL,IAAK;AAAA,QACL,IAAK;AAAA,QACL,IAAK;AAAA,MAAA;AAAA,MAEP,OAAO;AAAA,QACL,SAAS;AAAA,QACT,OAAS;AAAA,QACT,SAAS;AAAA,QACT,SAAS;AAAA,MAAA;AAAA,IACX;AAAA,IAEF,iBAAiB;AAAA,MACf,MAAM;AAAA,MACN,OAAO;AAAA,IAAA;AAAA,EACT;AAEJ;AAQA,MAAM,QAAQ,MAAM;AAAA,EAClB,CAAC,EAAE,WAAW,MAAM,MAAM,OAAO,GAAG,MAAA,GAAS,QAAQ;AACnD,WACE;AAAA,MAAC;AAAA,MAAA;AAAA,QACC;AAAA,QACA;AAAA,QACA,WAAW,GAAG,cAAc,EAAE,MAAM,MAAA,CAAO,GAAG,SAAS;AAAA,QACtD,GAAG;AAAA,MAAA;AAAA,IAAA;AAAA,EAGV;AACF;AACA,MAAM,cAAc;"}
@@ -0,0 +1,75 @@
1
+ "use strict";
2
+ const jsxRuntime = require("react/jsx-runtime");
3
+ const chipGroup = require("./chip-group-CsKBBHW2.mjs");
4
+ const pageHeaderStyles = chipGroup.tv({
5
+ slots: {
6
+ root: "shrink-0 flex flex-col gap-gp-md",
7
+ topRow: "flex items-center justify-between gap-gp-2xl",
8
+ textCol: "flex flex-col gap-gp-xs min-w-0 flex-1",
9
+ titleRow: "flex items-center gap-gp-md",
10
+ title: "m-0 text-title-lg font-bold tracking-[-0.01em] text-fg-default",
11
+ description: [
12
+ "m-0 text-paragraph-sm text-fg-subtle leading-[1.5]",
13
+ "whitespace-nowrap overflow-hidden text-ellipsis"
14
+ ],
15
+ actionsRow: "flex items-center gap-gp-sm shrink-0",
16
+ extraRow: "w-full"
17
+ },
18
+ variants: {
19
+ hideTextOnMobile: {
20
+ true: { textCol: "max-md:hidden" },
21
+ false: {}
22
+ },
23
+ /**
24
+ * Mobile: actions ocupa o espaço (text hidden) + último filho vira fluid.
25
+ * Off = mantém actions square e shrink-0 (mesmo comportamento desktop).
26
+ */
27
+ mobileFluid: {
28
+ true: {
29
+ actionsRow: [
30
+ "max-md:shrink max-md:flex-1 max-md:justify-end",
31
+ "max-md:[&>:last-child]:flex-1"
32
+ ]
33
+ },
34
+ false: {}
35
+ }
36
+ },
37
+ defaultVariants: {
38
+ hideTextOnMobile: true,
39
+ mobileFluid: true
40
+ }
41
+ });
42
+ function PageHeader({
43
+ title,
44
+ description,
45
+ badge,
46
+ actions,
47
+ children,
48
+ hideTextOnMobile = true,
49
+ fluidPrimaryOnMobile = true,
50
+ className
51
+ }) {
52
+ const s = pageHeaderStyles({
53
+ hideTextOnMobile,
54
+ mobileFluid: fluidPrimaryOnMobile
55
+ });
56
+ const hasText = !!(title || description || badge);
57
+ const hasTopRow = hasText || !!actions;
58
+ return /* @__PURE__ */ jsxRuntime.jsxs("header", { className: chipGroup.cn(s.root(), className), children: [
59
+ hasTopRow && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: s.topRow(), children: [
60
+ hasText && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: s.textCol(), children: [
61
+ (title || badge) && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: s.titleRow(), children: [
62
+ title && /* @__PURE__ */ jsxRuntime.jsx("h1", { className: s.title(), children: title }),
63
+ badge
64
+ ] }),
65
+ description && /* @__PURE__ */ jsxRuntime.jsx("p", { className: s.description(), children: description })
66
+ ] }),
67
+ actions && /* @__PURE__ */ jsxRuntime.jsx("div", { className: s.actionsRow(), children: actions })
68
+ ] }),
69
+ children && /* @__PURE__ */ jsxRuntime.jsx("div", { className: s.extraRow(), children })
70
+ ] });
71
+ }
72
+ PageHeader.displayName = "PageHeader";
73
+ exports.PageHeader = PageHeader;
74
+ exports.pageHeaderStyles = pageHeaderStyles;
75
+ //# sourceMappingURL=page-header-Dw-3wqAG.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"page-header-Dw-3wqAG.mjs","sources":["../../src/components/ui/PageHeader/page-header.styles.ts","../../src/components/ui/PageHeader/page-header.tsx"],"sourcesContent":["import { tv } from \"@/utils/tv\";\n\n/**\n * PageHeader styles — bloco de título de página colocado dentro do body\n * do `<AppShell>`.\n *\n * Layout desktop:\n * ┌──────────────────────────────────────────────────────────┐\n * │ [title] [badge] [action1] [action2] [CTA] │\n * │ description │\n * ├──────────────────────────────────────────────────────────┤\n * │ {children — ex: <Tabs />} │\n * └──────────────────────────────────────────────────────────┘\n *\n * Mobile:\n * - Text section sai (hideTextOnMobile, default true)\n * - Actions ocupam toda a largura; último botão vira fluid (CTA primary)\n */\nexport const pageHeaderStyles = tv({\n slots: {\n root: \"shrink-0 flex flex-col gap-gp-md\",\n topRow: \"flex items-center justify-between gap-gp-2xl\",\n textCol: \"flex flex-col gap-gp-xs min-w-0 flex-1\",\n titleRow: \"flex items-center gap-gp-md\",\n title: \"m-0 text-title-lg font-bold tracking-[-0.01em] text-fg-default\",\n description: [\n \"m-0 text-paragraph-sm text-fg-subtle leading-[1.5]\",\n \"whitespace-nowrap overflow-hidden text-ellipsis\",\n ],\n actionsRow: \"flex items-center gap-gp-sm shrink-0\",\n extraRow: \"w-full\",\n },\n variants: {\n hideTextOnMobile: {\n true: { textCol: \"max-md:hidden\" },\n false: {},\n },\n /**\n * Mobile: actions ocupa o espaço (text hidden) + último filho vira fluid.\n * Off = mantém actions square e shrink-0 (mesmo comportamento desktop).\n */\n mobileFluid: {\n true: {\n actionsRow: [\n \"max-md:shrink max-md:flex-1 max-md:justify-end\",\n \"max-md:[&>:last-child]:flex-1\",\n ],\n },\n false: {},\n },\n },\n defaultVariants: {\n hideTextOnMobile: true,\n mobileFluid: true,\n },\n});\n","import { cn } from \"@/lib/utils\";\nimport { pageHeaderStyles } from \"./page-header.styles\";\nimport type { PageHeaderProps } from \"./page-header.types\";\n\n/**\n * PageHeader — bloco de título reutilizável colocado dentro do body do\n * `<AppShell>`. Cobre o caso comum:\n *\n * - Título (h1) + descrição (sub) + badge (chip ao lado)\n * - Slot de ações à direita (botões / dropdowns)\n * - Slot livre abaixo pra tabs, filtros ou qualquer conteúdo extra\n *\n * Mobile-ready por default:\n * - Title/description/badge somem em viewports pequenas\n * (Header global do AppShell já mostra title/breadcrumb)\n * - O último botão do `actions` vira fluid (CTA full-width)\n *\n * @example\n * ```tsx\n * <PageHeader\n * title=\"Clientes\"\n * description=\"Gerencie sua base de clientes.\"\n * badge={<Chip color=\"primary\" variant=\"soft\">87 registros</Chip>}\n * actions={\n * <>\n * <Button variant=\"outline\" size=\"icon-md\"><MoreHorizontal /></Button>\n * <Button variant=\"filled\" color=\"primary\">Novo cliente</Button>\n * </>\n * }\n * />\n * ```\n *\n * @example com tabs abaixo (slot children):\n * ```tsx\n * <PageHeader title=\"Configurações\" actions={<Button>Salvar</Button>}>\n * <Tabs ... />\n * </PageHeader>\n * ```\n */\nexport function PageHeader({\n title,\n description,\n badge,\n actions,\n children,\n hideTextOnMobile = true,\n fluidPrimaryOnMobile = true,\n className,\n}: PageHeaderProps) {\n const s = pageHeaderStyles({\n hideTextOnMobile,\n mobileFluid: fluidPrimaryOnMobile,\n });\n\n const hasText = !!(title || description || badge);\n const hasTopRow = hasText || !!actions;\n\n return (\n <header className={cn(s.root(), className)}>\n {hasTopRow && (\n <div className={s.topRow()}>\n {hasText && (\n <div className={s.textCol()}>\n {(title || badge) && (\n <div className={s.titleRow()}>\n {title && <h1 className={s.title()}>{title}</h1>}\n {badge}\n </div>\n )}\n {description && <p className={s.description()}>{description}</p>}\n </div>\n )}\n {actions && <div className={s.actionsRow()}>{actions}</div>}\n </div>\n )}\n {children && <div className={s.extraRow()}>{children}</div>}\n </header>\n );\n}\n\nPageHeader.displayName = \"PageHeader\";\n"],"names":["tv","jsxs","cn","jsx"],"mappings":";;;AAkBO,MAAM,mBAAmBA,UAAAA,GAAG;AAAA,EACjC,OAAO;AAAA,IACL,MAAM;AAAA,IACN,QAAQ;AAAA,IACR,SAAS;AAAA,IACT,UAAU;AAAA,IACV,OAAO;AAAA,IACP,aAAa;AAAA,MACX;AAAA,MACA;AAAA,IAAA;AAAA,IAEF,YAAY;AAAA,IACZ,UAAU;AAAA,EAAA;AAAA,EAEZ,UAAU;AAAA,IACR,kBAAkB;AAAA,MAChB,MAAM,EAAE,SAAS,gBAAA;AAAA,MACjB,OAAO,CAAA;AAAA,IAAC;AAAA;AAAA;AAAA;AAAA;AAAA,IAMV,aAAa;AAAA,MACX,MAAM;AAAA,QACJ,YAAY;AAAA,UACV;AAAA,UACA;AAAA,QAAA;AAAA,MACF;AAAA,MAEF,OAAO,CAAA;AAAA,IAAC;AAAA,EACV;AAAA,EAEF,iBAAiB;AAAA,IACf,kBAAkB;AAAA,IAClB,aAAa;AAAA,EAAA;AAEjB,CAAC;AChBM,SAAS,WAAW;AAAA,EACzB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,mBAAmB;AAAA,EACnB,uBAAuB;AAAA,EACvB;AACF,GAAoB;AAClB,QAAM,IAAI,iBAAiB;AAAA,IACzB;AAAA,IACA,aAAa;AAAA,EAAA,CACd;AAED,QAAM,UAAU,CAAC,EAAE,SAAS,eAAe;AAC3C,QAAM,YAAY,WAAW,CAAC,CAAC;AAE/B,SACEC,2BAAAA,KAAC,YAAO,WAAWC,UAAAA,GAAG,EAAE,KAAA,GAAQ,SAAS,GACtC,UAAA;AAAA,IAAA,aACCD,2BAAAA,KAAC,OAAA,EAAI,WAAW,EAAE,UACf,UAAA;AAAA,MAAA,WACCA,2BAAAA,KAAC,OAAA,EAAI,WAAW,EAAE,WACd,UAAA;AAAA,SAAA,SAAS,UACTA,2BAAAA,KAAC,OAAA,EAAI,WAAW,EAAE,YACf,UAAA;AAAA,UAAA,wCAAU,MAAA,EAAG,WAAW,EAAE,MAAA,GAAU,UAAA,OAAM;AAAA,UAC1C;AAAA,QAAA,GACH;AAAA,QAED,eAAeE,2BAAAA,IAAC,KAAA,EAAE,WAAW,EAAE,YAAA,GAAgB,UAAA,YAAA,CAAY;AAAA,MAAA,GAC9D;AAAA,MAED,WAAWA,2BAAAA,IAAC,OAAA,EAAI,WAAW,EAAE,WAAA,GAAe,UAAA,QAAA,CAAQ;AAAA,IAAA,GACvD;AAAA,IAED,YAAYA,2BAAAA,IAAC,OAAA,EAAI,WAAW,EAAE,SAAA,GAAa,SAAA,CAAS;AAAA,EAAA,GACvD;AAEJ;AAEA,WAAW,cAAc;;;"}
@@ -0,0 +1,76 @@
1
+ import { jsxs, jsx } from "react/jsx-runtime";
2
+ import { t as tv, c as cn } from "./chip-group-D3D0i72q.mjs";
3
+ const pageHeaderStyles = tv({
4
+ slots: {
5
+ root: "shrink-0 flex flex-col gap-gp-md",
6
+ topRow: "flex items-center justify-between gap-gp-2xl",
7
+ textCol: "flex flex-col gap-gp-xs min-w-0 flex-1",
8
+ titleRow: "flex items-center gap-gp-md",
9
+ title: "m-0 text-title-lg font-bold tracking-[-0.01em] text-fg-default",
10
+ description: [
11
+ "m-0 text-paragraph-sm text-fg-subtle leading-[1.5]",
12
+ "whitespace-nowrap overflow-hidden text-ellipsis"
13
+ ],
14
+ actionsRow: "flex items-center gap-gp-sm shrink-0",
15
+ extraRow: "w-full"
16
+ },
17
+ variants: {
18
+ hideTextOnMobile: {
19
+ true: { textCol: "max-md:hidden" },
20
+ false: {}
21
+ },
22
+ /**
23
+ * Mobile: actions ocupa o espaço (text hidden) + último filho vira fluid.
24
+ * Off = mantém actions square e shrink-0 (mesmo comportamento desktop).
25
+ */
26
+ mobileFluid: {
27
+ true: {
28
+ actionsRow: [
29
+ "max-md:shrink max-md:flex-1 max-md:justify-end",
30
+ "max-md:[&>:last-child]:flex-1"
31
+ ]
32
+ },
33
+ false: {}
34
+ }
35
+ },
36
+ defaultVariants: {
37
+ hideTextOnMobile: true,
38
+ mobileFluid: true
39
+ }
40
+ });
41
+ function PageHeader({
42
+ title,
43
+ description,
44
+ badge,
45
+ actions,
46
+ children,
47
+ hideTextOnMobile = true,
48
+ fluidPrimaryOnMobile = true,
49
+ className
50
+ }) {
51
+ const s = pageHeaderStyles({
52
+ hideTextOnMobile,
53
+ mobileFluid: fluidPrimaryOnMobile
54
+ });
55
+ const hasText = !!(title || description || badge);
56
+ const hasTopRow = hasText || !!actions;
57
+ return /* @__PURE__ */ jsxs("header", { className: cn(s.root(), className), children: [
58
+ hasTopRow && /* @__PURE__ */ jsxs("div", { className: s.topRow(), children: [
59
+ hasText && /* @__PURE__ */ jsxs("div", { className: s.textCol(), children: [
60
+ (title || badge) && /* @__PURE__ */ jsxs("div", { className: s.titleRow(), children: [
61
+ title && /* @__PURE__ */ jsx("h1", { className: s.title(), children: title }),
62
+ badge
63
+ ] }),
64
+ description && /* @__PURE__ */ jsx("p", { className: s.description(), children: description })
65
+ ] }),
66
+ actions && /* @__PURE__ */ jsx("div", { className: s.actionsRow(), children: actions })
67
+ ] }),
68
+ children && /* @__PURE__ */ jsx("div", { className: s.extraRow(), children })
69
+ ] });
70
+ }
71
+ PageHeader.displayName = "PageHeader";
72
+ export {
73
+ PageHeader as P,
74
+ pageHeaderStyles as p
75
+ };
76
+ //# sourceMappingURL=page-header-mC1gGtOI.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"page-header-mC1gGtOI.mjs","sources":["../../src/components/ui/PageHeader/page-header.styles.ts","../../src/components/ui/PageHeader/page-header.tsx"],"sourcesContent":["import { tv } from \"@/utils/tv\";\n\n/**\n * PageHeader styles — bloco de título de página colocado dentro do body\n * do `<AppShell>`.\n *\n * Layout desktop:\n * ┌──────────────────────────────────────────────────────────┐\n * │ [title] [badge] [action1] [action2] [CTA] │\n * │ description │\n * ├──────────────────────────────────────────────────────────┤\n * │ {children — ex: <Tabs />} │\n * └──────────────────────────────────────────────────────────┘\n *\n * Mobile:\n * - Text section sai (hideTextOnMobile, default true)\n * - Actions ocupam toda a largura; último botão vira fluid (CTA primary)\n */\nexport const pageHeaderStyles = tv({\n slots: {\n root: \"shrink-0 flex flex-col gap-gp-md\",\n topRow: \"flex items-center justify-between gap-gp-2xl\",\n textCol: \"flex flex-col gap-gp-xs min-w-0 flex-1\",\n titleRow: \"flex items-center gap-gp-md\",\n title: \"m-0 text-title-lg font-bold tracking-[-0.01em] text-fg-default\",\n description: [\n \"m-0 text-paragraph-sm text-fg-subtle leading-[1.5]\",\n \"whitespace-nowrap overflow-hidden text-ellipsis\",\n ],\n actionsRow: \"flex items-center gap-gp-sm shrink-0\",\n extraRow: \"w-full\",\n },\n variants: {\n hideTextOnMobile: {\n true: { textCol: \"max-md:hidden\" },\n false: {},\n },\n /**\n * Mobile: actions ocupa o espaço (text hidden) + último filho vira fluid.\n * Off = mantém actions square e shrink-0 (mesmo comportamento desktop).\n */\n mobileFluid: {\n true: {\n actionsRow: [\n \"max-md:shrink max-md:flex-1 max-md:justify-end\",\n \"max-md:[&>:last-child]:flex-1\",\n ],\n },\n false: {},\n },\n },\n defaultVariants: {\n hideTextOnMobile: true,\n mobileFluid: true,\n },\n});\n","import { cn } from \"@/lib/utils\";\nimport { pageHeaderStyles } from \"./page-header.styles\";\nimport type { PageHeaderProps } from \"./page-header.types\";\n\n/**\n * PageHeader — bloco de título reutilizável colocado dentro do body do\n * `<AppShell>`. Cobre o caso comum:\n *\n * - Título (h1) + descrição (sub) + badge (chip ao lado)\n * - Slot de ações à direita (botões / dropdowns)\n * - Slot livre abaixo pra tabs, filtros ou qualquer conteúdo extra\n *\n * Mobile-ready por default:\n * - Title/description/badge somem em viewports pequenas\n * (Header global do AppShell já mostra title/breadcrumb)\n * - O último botão do `actions` vira fluid (CTA full-width)\n *\n * @example\n * ```tsx\n * <PageHeader\n * title=\"Clientes\"\n * description=\"Gerencie sua base de clientes.\"\n * badge={<Chip color=\"primary\" variant=\"soft\">87 registros</Chip>}\n * actions={\n * <>\n * <Button variant=\"outline\" size=\"icon-md\"><MoreHorizontal /></Button>\n * <Button variant=\"filled\" color=\"primary\">Novo cliente</Button>\n * </>\n * }\n * />\n * ```\n *\n * @example com tabs abaixo (slot children):\n * ```tsx\n * <PageHeader title=\"Configurações\" actions={<Button>Salvar</Button>}>\n * <Tabs ... />\n * </PageHeader>\n * ```\n */\nexport function PageHeader({\n title,\n description,\n badge,\n actions,\n children,\n hideTextOnMobile = true,\n fluidPrimaryOnMobile = true,\n className,\n}: PageHeaderProps) {\n const s = pageHeaderStyles({\n hideTextOnMobile,\n mobileFluid: fluidPrimaryOnMobile,\n });\n\n const hasText = !!(title || description || badge);\n const hasTopRow = hasText || !!actions;\n\n return (\n <header className={cn(s.root(), className)}>\n {hasTopRow && (\n <div className={s.topRow()}>\n {hasText && (\n <div className={s.textCol()}>\n {(title || badge) && (\n <div className={s.titleRow()}>\n {title && <h1 className={s.title()}>{title}</h1>}\n {badge}\n </div>\n )}\n {description && <p className={s.description()}>{description}</p>}\n </div>\n )}\n {actions && <div className={s.actionsRow()}>{actions}</div>}\n </div>\n )}\n {children && <div className={s.extraRow()}>{children}</div>}\n </header>\n );\n}\n\nPageHeader.displayName = \"PageHeader\";\n"],"names":[],"mappings":";;AAkBO,MAAM,mBAAmB,GAAG;AAAA,EACjC,OAAO;AAAA,IACL,MAAM;AAAA,IACN,QAAQ;AAAA,IACR,SAAS;AAAA,IACT,UAAU;AAAA,IACV,OAAO;AAAA,IACP,aAAa;AAAA,MACX;AAAA,MACA;AAAA,IAAA;AAAA,IAEF,YAAY;AAAA,IACZ,UAAU;AAAA,EAAA;AAAA,EAEZ,UAAU;AAAA,IACR,kBAAkB;AAAA,MAChB,MAAM,EAAE,SAAS,gBAAA;AAAA,MACjB,OAAO,CAAA;AAAA,IAAC;AAAA;AAAA;AAAA;AAAA;AAAA,IAMV,aAAa;AAAA,MACX,MAAM;AAAA,QACJ,YAAY;AAAA,UACV;AAAA,UACA;AAAA,QAAA;AAAA,MACF;AAAA,MAEF,OAAO,CAAA;AAAA,IAAC;AAAA,EACV;AAAA,EAEF,iBAAiB;AAAA,IACf,kBAAkB;AAAA,IAClB,aAAa;AAAA,EAAA;AAEjB,CAAC;AChBM,SAAS,WAAW;AAAA,EACzB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,mBAAmB;AAAA,EACnB,uBAAuB;AAAA,EACvB;AACF,GAAoB;AAClB,QAAM,IAAI,iBAAiB;AAAA,IACzB;AAAA,IACA,aAAa;AAAA,EAAA,CACd;AAED,QAAM,UAAU,CAAC,EAAE,SAAS,eAAe;AAC3C,QAAM,YAAY,WAAW,CAAC,CAAC;AAE/B,SACE,qBAAC,YAAO,WAAW,GAAG,EAAE,KAAA,GAAQ,SAAS,GACtC,UAAA;AAAA,IAAA,aACC,qBAAC,OAAA,EAAI,WAAW,EAAE,UACf,UAAA;AAAA,MAAA,WACC,qBAAC,OAAA,EAAI,WAAW,EAAE,WACd,UAAA;AAAA,SAAA,SAAS,UACT,qBAAC,OAAA,EAAI,WAAW,EAAE,YACf,UAAA;AAAA,UAAA,6BAAU,MAAA,EAAG,WAAW,EAAE,MAAA,GAAU,UAAA,OAAM;AAAA,UAC1C;AAAA,QAAA,GACH;AAAA,QAED,eAAe,oBAAC,KAAA,EAAE,WAAW,EAAE,YAAA,GAAgB,UAAA,YAAA,CAAY;AAAA,MAAA,GAC9D;AAAA,MAED,WAAW,oBAAC,OAAA,EAAI,WAAW,EAAE,WAAA,GAAe,UAAA,QAAA,CAAQ;AAAA,IAAA,GACvD;AAAA,IAED,YAAY,oBAAC,OAAA,EAAI,WAAW,EAAE,SAAA,GAAa,SAAA,CAAS;AAAA,EAAA,GACvD;AAEJ;AAEA,WAAW,cAAc;"}