@wellingtonhlc/shared-ui 0.29.0 → 0.29.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (153) hide show
  1. package/README.md +25 -10
  2. package/dist/cli/check-page-actions.d.ts +9 -0
  3. package/dist/cli/check-page-actions.d.ts.map +1 -0
  4. package/dist/cli/check-page-actions.js +108 -0
  5. package/dist/components/ActionBar.d.ts +26 -0
  6. package/dist/components/ActionBar.d.ts.map +1 -0
  7. package/dist/components/ActionBar.js +29 -0
  8. package/dist/components/ActionPrimitives.d.ts +31 -0
  9. package/dist/components/ActionPrimitives.d.ts.map +1 -0
  10. package/dist/components/ActionPrimitives.js +27 -0
  11. package/dist/components/AppShell.d.ts +65 -0
  12. package/dist/components/AppShell.d.ts.map +1 -0
  13. package/dist/components/AppShell.js +50 -0
  14. package/dist/components/AppShellActions.d.ts +24 -0
  15. package/dist/components/AppShellActions.d.ts.map +1 -0
  16. package/dist/components/AppShellActions.js +15 -0
  17. package/dist/components/Badge.d.ts +16 -0
  18. package/dist/components/Badge.d.ts.map +1 -0
  19. package/dist/components/Badge.js +36 -0
  20. package/dist/components/Banner.d.ts +13 -0
  21. package/dist/components/Banner.d.ts.map +1 -0
  22. package/dist/components/Banner.js +29 -0
  23. package/dist/components/Button.d.ts +14 -0
  24. package/dist/components/Button.d.ts.map +1 -0
  25. package/dist/components/Button.js +39 -0
  26. package/dist/components/Card.d.ts +36 -0
  27. package/dist/components/Card.d.ts.map +1 -0
  28. package/dist/components/Card.js +56 -0
  29. package/dist/components/ConfirmationDialog.d.ts +74 -0
  30. package/dist/components/ConfirmationDialog.d.ts.map +1 -0
  31. package/dist/components/ConfirmationDialog.js +234 -0
  32. package/dist/components/CopyableField.d.ts +10 -0
  33. package/dist/components/CopyableField.d.ts.map +1 -0
  34. package/dist/components/CopyableField.js +60 -0
  35. package/dist/components/DateField.d.ts +20 -0
  36. package/dist/components/DateField.d.ts.map +1 -0
  37. package/dist/components/DateField.js +172 -0
  38. package/dist/components/DecimalField.d.ts +21 -0
  39. package/dist/components/DecimalField.d.ts.map +1 -0
  40. package/dist/components/DecimalField.js +137 -0
  41. package/dist/components/DismissiblePopover.d.ts +14 -0
  42. package/dist/components/DismissiblePopover.d.ts.map +1 -0
  43. package/dist/components/DismissiblePopover.js +51 -0
  44. package/dist/components/EmptyState.d.ts +15 -0
  45. package/dist/components/EmptyState.d.ts.map +1 -0
  46. package/dist/components/EmptyState.js +32 -0
  47. package/dist/components/FieldControl.d.ts +20 -0
  48. package/dist/components/FieldControl.d.ts.map +1 -0
  49. package/dist/components/FieldControl.js +73 -0
  50. package/dist/components/FieldGroup.d.ts +11 -0
  51. package/dist/components/FieldGroup.d.ts.map +1 -0
  52. package/dist/components/FieldGroup.js +11 -0
  53. package/dist/components/FieldSkeleton.d.ts +14 -0
  54. package/dist/components/FieldSkeleton.d.ts.map +1 -0
  55. package/dist/components/FieldSkeleton.js +23 -0
  56. package/dist/components/FieldValidationError.d.ts +8 -0
  57. package/dist/components/FieldValidationError.d.ts.map +1 -0
  58. package/dist/components/FieldValidationError.js +7 -0
  59. package/dist/components/Filter.d.ts +51 -0
  60. package/dist/components/Filter.d.ts.map +1 -0
  61. package/dist/components/Filter.js +68 -0
  62. package/dist/components/Loading.d.ts +17 -0
  63. package/dist/components/Loading.d.ts.map +1 -0
  64. package/dist/components/Loading.js +15 -0
  65. package/dist/components/LoadingOverlay.d.ts +11 -0
  66. package/dist/components/LoadingOverlay.d.ts.map +1 -0
  67. package/dist/components/LoadingOverlay.js +8 -0
  68. package/dist/components/Modal.d.ts +49 -0
  69. package/dist/components/Modal.d.ts.map +1 -0
  70. package/dist/components/Modal.js +108 -0
  71. package/dist/components/MultiSelectField.d.ts +22 -0
  72. package/dist/components/MultiSelectField.d.ts.map +1 -0
  73. package/dist/components/MultiSelectField.js +84 -0
  74. package/dist/components/NavCard.d.ts +15 -0
  75. package/dist/components/NavCard.d.ts.map +1 -0
  76. package/dist/components/NavCard.js +13 -0
  77. package/dist/components/Page.d.ts +89 -0
  78. package/dist/components/Page.d.ts.map +1 -0
  79. package/dist/components/Page.js +347 -0
  80. package/dist/components/PageMessage.d.ts +12 -0
  81. package/dist/components/PageMessage.d.ts.map +1 -0
  82. package/dist/components/PageMessage.js +36 -0
  83. package/dist/components/Pagination.d.ts +15 -0
  84. package/dist/components/Pagination.d.ts.map +1 -0
  85. package/dist/components/Pagination.js +57 -0
  86. package/dist/components/PasswordInput.d.ts +8 -0
  87. package/dist/components/PasswordInput.d.ts.map +1 -0
  88. package/dist/components/PasswordInput.js +17 -0
  89. package/dist/components/RadioGroup.d.ts +32 -0
  90. package/dist/components/RadioGroup.d.ts.map +1 -0
  91. package/dist/components/RadioGroup.js +86 -0
  92. package/dist/components/RenderCase.d.ts +20 -0
  93. package/dist/components/RenderCase.d.ts.map +1 -0
  94. package/dist/components/RenderCase.js +31 -0
  95. package/dist/components/RenderIf.d.ts +10 -0
  96. package/dist/components/RenderIf.d.ts.map +1 -0
  97. package/dist/components/RenderIf.js +9 -0
  98. package/dist/components/SearchField.d.ts +22 -0
  99. package/dist/components/SearchField.d.ts.map +1 -0
  100. package/dist/components/SearchField.js +43 -0
  101. package/dist/components/SelectField.d.ts +31 -0
  102. package/dist/components/SelectField.d.ts.map +1 -0
  103. package/dist/components/SelectField.js +26 -0
  104. package/dist/components/SelectionField.d.ts +39 -0
  105. package/dist/components/SelectionField.d.ts.map +1 -0
  106. package/dist/components/SelectionField.js +105 -0
  107. package/dist/components/Sidebar.d.ts +104 -0
  108. package/dist/components/Sidebar.d.ts.map +1 -0
  109. package/dist/components/Sidebar.js +146 -0
  110. package/dist/components/StatCard.d.ts +16 -0
  111. package/dist/components/StatCard.d.ts.map +1 -0
  112. package/dist/components/StatCard.js +62 -0
  113. package/dist/components/Switch.d.ts +20 -0
  114. package/dist/components/Switch.d.ts.map +1 -0
  115. package/dist/components/Switch.js +63 -0
  116. package/dist/components/Table.d.ts +65 -0
  117. package/dist/components/Table.d.ts.map +1 -0
  118. package/dist/components/Table.js +118 -0
  119. package/dist/components/TabsUnderlined.d.ts +23 -0
  120. package/dist/components/TabsUnderlined.d.ts.map +1 -0
  121. package/dist/components/TabsUnderlined.js +29 -0
  122. package/dist/components/TextField.d.ts +25 -0
  123. package/dist/components/TextField.d.ts.map +1 -0
  124. package/dist/components/TextField.js +71 -0
  125. package/dist/components/TextareaField.d.ts +14 -0
  126. package/dist/components/TextareaField.d.ts.map +1 -0
  127. package/dist/components/TextareaField.js +34 -0
  128. package/dist/components/ThemePreferencesSelector.d.ts +29 -0
  129. package/dist/components/ThemePreferencesSelector.d.ts.map +1 -0
  130. package/dist/components/ThemePreferencesSelector.js +37 -0
  131. package/dist/components/Tooltip.d.ts +13 -0
  132. package/dist/components/Tooltip.d.ts.map +1 -0
  133. package/dist/components/Tooltip.js +40 -0
  134. package/dist/components/Workspace.d.ts +22 -0
  135. package/dist/components/Workspace.d.ts.map +1 -0
  136. package/dist/components/Workspace.js +33 -0
  137. package/dist/components/WorkspaceContext.d.ts +2 -0
  138. package/dist/components/WorkspaceContext.d.ts.map +1 -0
  139. package/dist/components/WorkspaceContext.js +2 -0
  140. package/dist/components/form-control-helpers.d.ts +24 -0
  141. package/dist/components/form-control-helpers.d.ts.map +1 -0
  142. package/dist/components/form-control-helpers.js +20 -0
  143. package/dist/index.d.ts +45 -0
  144. package/dist/index.d.ts.map +1 -0
  145. package/dist/index.js +44 -0
  146. package/dist/styles.css +21 -41
  147. package/dist/tailwind-preset.d.ts +23 -0
  148. package/dist/tailwind-preset.d.ts.map +1 -0
  149. package/dist/tailwind-preset.js +22 -0
  150. package/dist/utils/cn.d.ts +2 -0
  151. package/dist/utils/cn.d.ts.map +1 -0
  152. package/dist/utils/cn.js +33 -0
  153. package/package.json +1 -1
package/README.md CHANGED
@@ -187,6 +187,12 @@ O Storybook documenta as escalas em `Foundations` e organiza os exemplos públic
187
187
  `Components`, por função. Consumidores podem sobrescrever tokens de tema, mas componentes
188
188
  não devem introduzir hexadecimais, sombras ou escalas paralelas.
189
189
 
190
+ O tema padrão usa azul como identidade de marca (`--brand`/`--primary`). No tema claro,
191
+ Sidebar e Top Bar usam `--surface`; no tema escuro, usam `--background-secondary`, a mesma
192
+ superfície de `Page.Actions`. `TabsUnderlined` possui um token próprio (`--tabs-background`)
193
+ para manter contraste entre abas selecionadas e não selecionadas mesmo quando as superfícies
194
+ do consumidor possuem a mesma cor.
195
+
190
196
  Preset Tailwind:
191
197
 
192
198
  ```ts
@@ -265,13 +271,22 @@ primitivos de acao, mas aplica o tamanho esperado para a topbar.
265
271
  import { AppShell } from '@wellingtonhlc/shared-ui';
266
272
  import { Bell, Settings } from 'lucide-react';
267
273
 
268
- <AppShell.Actions>
269
- <AppShell.Topbar.Button icon={<Bell />} tooltip="Notificacoes" />
270
- <AppShell.Topbar.Button icon={<Settings />} tooltip="Configuracoes" />
271
- </AppShell.Actions>
272
- ```
273
-
274
- ## TabsUnderlined
274
+ <AppShell.Actions>
275
+ <AppShell.Topbar.Button icon={<Bell />} tooltip="Notificacoes" />
276
+ <AppShell.Topbar.Button icon={<Settings />} tooltip="Configuracoes" />
277
+ </AppShell.Actions>
278
+ ```
279
+
280
+ ## Sidebar
281
+
282
+ Use `Sidebar.ActionButton`, `Sidebar.SubActionButton` e `Sidebar.NavGroup` para navegação.
283
+ Não use variantes de `Button` para simular itens do menu. O botão sanduíche é fornecido por
284
+ `Sidebar.ToggleButton` e compartilha os mesmos estados de hover e foco dos itens principais.
285
+
286
+ No modo compacto, o Sidebar reserva um slot estável para cada ícone. Labels e chevrons são
287
+ revelados durante a expansão sem deslocar o ícone ou provocar layout shift.
288
+
289
+ ## TabsUnderlined
275
290
 
276
291
  `TabsUnderlined` renderiza abas sublinhadas com conteudo controlado ou nao controlado.
277
292
  As abas ja possuem tamanho minimo padrao e padding horizontal para comportar labels
@@ -303,15 +318,15 @@ Contrato minimo:
303
318
  ```tsx
304
319
  import { ThemePreferencesSelector, type ThemePreferencesValue } from '@wellingtonhlc/shared-ui';
305
320
 
306
- const value: ThemePreferencesValue = {
307
- color: 'indigo',
321
+ const value: ThemePreferencesValue = {
322
+ color: 'ocean',
308
323
  appearance: 'system',
309
324
  };
310
325
 
311
326
  <ThemePreferencesSelector
312
327
  value={value}
313
328
  options={[
314
- { key: 'indigo', label: 'Indigo', primary: '#5b5cff' },
329
+ { key: 'ocean', label: 'Ocean', primary: '#2563eb' },
315
330
  { key: 'emerald', label: 'Emerald', primary: '#059669' },
316
331
  ]}
317
332
  onChange={setValue}
@@ -0,0 +1,9 @@
1
+ #!/usr/bin/env node
2
+ export interface PageActionsCheckResult {
3
+ errors: string[];
4
+ scannedFiles: number;
5
+ sourceRoot: string;
6
+ }
7
+ export declare function checkPageActionsContract(rootDir?: string): PageActionsCheckResult;
8
+ export declare function runPageActionsContractCli(args?: string[]): PageActionsCheckResult;
9
+ //# sourceMappingURL=check-page-actions.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"check-page-actions.d.ts","sourceRoot":"","sources":["../../src/cli/check-page-actions.ts"],"names":[],"mappings":";AAQA,MAAM,WAAW,sBAAsB;IACrC,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,YAAY,EAAE,MAAM,CAAC;IACrB,UAAU,EAAE,MAAM,CAAC;CACpB;AAoFD,wBAAgB,wBAAwB,CAAC,OAAO,SAAgB,GAAG,sBAAsB,CA2DxF;AAED,wBAAgB,yBAAyB,CAAC,IAAI,WAAwB,0BAerE"}
@@ -0,0 +1,108 @@
1
+ #!/usr/bin/env node
2
+ import fs from 'node:fs';
3
+ import path from 'node:path';
4
+ import { fileURLToPath } from 'node:url';
5
+ const extensions = new Set(['.ts', '.tsx']);
6
+ const ignoredDirectories = new Set(['node_modules', 'dist', 'build', 'coverage']);
7
+ function normalizePath(root, filePath) {
8
+ return path.relative(root, filePath).split(path.sep).join('/');
9
+ }
10
+ function* walk(directory) {
11
+ if (!fs.existsSync(directory))
12
+ return;
13
+ for (const entry of fs.readdirSync(directory, { withFileTypes: true })) {
14
+ if (ignoredDirectories.has(entry.name))
15
+ continue;
16
+ const fullPath = path.join(directory, entry.name);
17
+ if (entry.isDirectory()) {
18
+ yield* walk(fullPath);
19
+ continue;
20
+ }
21
+ if (extensions.has(path.extname(entry.name))) {
22
+ yield fullPath;
23
+ }
24
+ }
25
+ }
26
+ function collectMatches(text, pattern, message, root, filePath, errors) {
27
+ for (const match of text.matchAll(pattern)) {
28
+ const before = text.slice(0, match.index);
29
+ const line = before.split(/\r?\n/).length;
30
+ errors.push(`${normalizePath(root, filePath)}:${line}: ${message}`);
31
+ }
32
+ }
33
+ function collectPageActionButtonsWithoutLabel(root, filePath, text, errors) {
34
+ const tagStart = '<Page.ActionButton';
35
+ let searchIndex = 0;
36
+ while (searchIndex < text.length) {
37
+ const startIndex = text.indexOf(tagStart, searchIndex);
38
+ if (startIndex === -1)
39
+ return;
40
+ let cursor = startIndex + tagStart.length;
41
+ let expressionDepth = 0;
42
+ let quote = null;
43
+ while (cursor < text.length) {
44
+ const char = text[cursor];
45
+ const previousChar = cursor > 0 ? text[cursor - 1] : '';
46
+ if (quote) {
47
+ if (char === quote && previousChar !== '\\')
48
+ quote = null;
49
+ cursor += 1;
50
+ continue;
51
+ }
52
+ if (char === '"' || char === "'" || char === '`') {
53
+ quote = char;
54
+ cursor += 1;
55
+ continue;
56
+ }
57
+ if (char === '{')
58
+ expressionDepth += 1;
59
+ if (char === '}')
60
+ expressionDepth = Math.max(0, expressionDepth - 1);
61
+ if (char === '>' && expressionDepth === 0)
62
+ break;
63
+ cursor += 1;
64
+ }
65
+ const tag = text.slice(startIndex, cursor + 1);
66
+ if (!/\blabel\s*=/.test(tag)) {
67
+ const before = text.slice(0, startIndex);
68
+ const line = before.split(/\r?\n/).length;
69
+ errors.push(`${normalizePath(root, filePath)}:${line}: Page.ActionButton deve declarar label`);
70
+ }
71
+ searchIndex = cursor + 1;
72
+ }
73
+ }
74
+ export function checkPageActionsContract(rootDir = process.cwd()) {
75
+ const root = path.resolve(rootDir);
76
+ const sourceRoot = fs.existsSync(path.join(root, 'src')) ? path.join(root, 'src') : root;
77
+ const errors = [];
78
+ let scannedFiles = 0;
79
+ for (const filePath of walk(sourceRoot)) {
80
+ scannedFiles += 1;
81
+ const text = fs.readFileSync(filePath, 'utf8');
82
+ collectMatches(text, /ActionBar\./g, 'use Page.Actions, Page.ActionButton e Page.ActionsSeparator no lugar de ActionBar.*', root, filePath, errors);
83
+ collectMatches(text, /<AppLayout\b[\s\S]*?<Page\.Root\b[^>]*\bactions\s*=/g, 'nao aninhe Page.Root actions dentro de AppLayout; use AppLayout.actions com Page.Actions', root, filePath, errors);
84
+ collectMatches(text, /<AppLayout\b[\s\S]*?\bactions\s*=\s*{\s*<>/g, 'AppLayout.actions nao deve receber Fragment como root; use Page.Actions ou componente *Actions', root, filePath, errors);
85
+ collectMatches(text, /<AppLayout\b[\s\S]*?\bactions\s*=\s*{\s*<div\b/g, 'AppLayout.actions nao deve receber div como root; use Page.Actions ou componente *Actions', root, filePath, errors);
86
+ collectMatches(text, /<AppLayout\b[\s\S]*?\bactions\s*=\s*{\s*<Page\.ActionButton\b/g, 'AppLayout.actions nao deve receber Page.ActionButton solto; envolva em Page.Actions', root, filePath, errors);
87
+ collectPageActionButtonsWithoutLabel(root, filePath, text, errors);
88
+ }
89
+ return { errors, scannedFiles, sourceRoot };
90
+ }
91
+ export function runPageActionsContractCli(args = process.argv.slice(2)) {
92
+ const rootDir = args[0] ?? process.cwd();
93
+ const result = checkPageActionsContract(rootDir);
94
+ if (result.errors.length > 0) {
95
+ console.error('Falha na verificacao de Page Actions:');
96
+ for (const error of result.errors)
97
+ console.error('- ' + error);
98
+ process.exitCode = 1;
99
+ return result;
100
+ }
101
+ console.log(`Page Actions OK: ${result.scannedFiles} arquivo(s) verificado(s); AppLayout.actions usa Page.Actions direta ou indiretamente.`);
102
+ return result;
103
+ }
104
+ const currentFilePath = fileURLToPath(import.meta.url);
105
+ const entryFilePath = process.argv[1] ? path.resolve(process.argv[1]) : '';
106
+ if (entryFilePath === currentFilePath) {
107
+ runPageActionsContractCli();
108
+ }
@@ -0,0 +1,26 @@
1
+ import { type ButtonHTMLAttributes, type ReactNode } from 'react';
2
+ export type ActionBarVariant = 'default' | 'primary' | 'danger';
3
+ export interface ActionBarRootProps {
4
+ children: ReactNode;
5
+ className?: string;
6
+ }
7
+ declare function Root({ children, className }: ActionBarRootProps): import("react").JSX.Element;
8
+ export interface ActionBarSeparatorProps {
9
+ className?: string;
10
+ }
11
+ declare function Separator({ className }: ActionBarSeparatorProps): import("react").JSX.Element;
12
+ export interface ActionBarButtonProps extends Omit<ButtonHTMLAttributes<HTMLButtonElement>, 'children'> {
13
+ highlight?: boolean;
14
+ icon: ReactNode;
15
+ label?: string;
16
+ loading?: boolean;
17
+ tooltip?: string;
18
+ variant?: ActionBarVariant;
19
+ }
20
+ export declare const ActionBar: {
21
+ Root: typeof Root;
22
+ Button: import("react").ForwardRefExoticComponent<ActionBarButtonProps & import("react").RefAttributes<HTMLButtonElement>>;
23
+ Separator: typeof Separator;
24
+ };
25
+ export {};
26
+ //# sourceMappingURL=ActionBar.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ActionBar.d.ts","sourceRoot":"","sources":["../../src/components/ActionBar.tsx"],"names":[],"mappings":"AAAA,OAAO,EAEL,KAAK,oBAAoB,EACzB,KAAK,SAAS,EACf,MAAM,OAAO,CAAC;AAIf,MAAM,MAAM,gBAAgB,GAAG,SAAS,GAAG,SAAS,GAAG,QAAQ,CAAC;AAEhE,MAAM,WAAW,kBAAkB;IACjC,QAAQ,EAAE,SAAS,CAAC;IACpB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,iBAAS,IAAI,CAAC,EAAE,QAAQ,EAAE,SAAS,EAAE,EAAE,kBAAkB,+BAWxD;AAED,MAAM,WAAW,uBAAuB;IACtC,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,iBAAS,SAAS,CAAC,EAAE,SAAS,EAAE,EAAE,uBAAuB,+BAQxD;AAED,MAAM,WAAW,oBACf,SAAQ,IAAI,CAAC,oBAAoB,CAAC,iBAAiB,CAAC,EAAE,UAAU,CAAC;IACjE,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,IAAI,EAAE,SAAS,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,OAAO,CAAC,EAAE,gBAAgB,CAAC;CAC5B;AA2DD,eAAO,MAAM,SAAS;;;;CAIrB,CAAC"}
@@ -0,0 +1,29 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { forwardRef, } from 'react';
3
+ import { cn } from '../utils/cn';
4
+ function Root({ children, className }) {
5
+ return (_jsx("div", { className: cn('border-app-border bg-background-secondary flex min-w-0 items-center gap-1.5 overflow-x-auto overflow-y-hidden border-b px-2 py-1.5', className), children: children }));
6
+ }
7
+ function Separator({ className }) {
8
+ return (_jsx("div", { role: "separator", "aria-orientation": "vertical", className: cn('bg-app-border mx-1 h-5 w-px shrink-0 rounded-full', className) }));
9
+ }
10
+ const variantClasses = {
11
+ default: 'text-foreground-muted hover:bg-background hover:text-foreground data-[state=open]:bg-background data-[state=open]:text-foreground',
12
+ primary: 'text-[var(--status-warning-icon)] hover:bg-[var(--status-warning-bg)] hover:text-[var(--status-warning-text)] data-[state=open]:bg-[var(--status-warning-bg)] data-[state=open]:text-[var(--status-warning-text)]',
13
+ danger: 'text-[var(--status-danger-icon)] hover:bg-[var(--status-danger-bg)] hover:text-[var(--status-danger-text)] data-[state=open]:bg-[var(--status-danger-bg)] data-[state=open]:text-[var(--status-danger-text)]',
14
+ };
15
+ const shapeClasses = {
16
+ icon: 'size-8 p-0',
17
+ labeled: 'min-h-8 gap-1.5 px-2 text-xs max-sm:px-1.5',
18
+ };
19
+ const Button = forwardRef(({ className, disabled = false, highlight = false, icon, label, loading = false, tooltip, type = 'button', variant = 'default', ...props }, ref) => {
20
+ const resolvedVariant = highlight ? 'primary' : variant;
21
+ const tooltipText = tooltip ?? label ?? props['aria-label'];
22
+ return (_jsxs("button", { ref: ref, ...props, type: type, disabled: disabled || loading, "aria-label": props['aria-label'] ?? tooltipText, title: tooltipText, className: cn('inline-flex shrink-0 cursor-pointer select-none items-center justify-center rounded-md border-0 bg-transparent font-semibold transition-[background-color,color,box-shadow,opacity] duration-[var(--duration-fast)] focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-brand/30 disabled:cursor-not-allowed disabled:opacity-45', label ? shapeClasses.labeled : shapeClasses.icon, variantClasses[resolvedVariant], loading && 'cursor-wait opacity-75', className), children: [_jsx("span", { className: "inline-flex size-4 shrink-0 items-center justify-center [&>svg]:size-4", children: icon }), label && _jsx("span", { className: "max-w-30 overflow-hidden text-ellipsis whitespace-nowrap max-sm:hidden", children: label })] }));
23
+ });
24
+ Button.displayName = 'ActionBar.Button';
25
+ export const ActionBar = {
26
+ Root,
27
+ Button,
28
+ Separator,
29
+ };
@@ -0,0 +1,31 @@
1
+ import { type ButtonHTMLAttributes, type ReactNode } from 'react';
2
+ export type ActionGroupAlign = 'start' | 'end';
3
+ export type ActionGroupSize = 'sm' | 'md' | 'lg';
4
+ export type ActionButtonVariant = 'default' | 'primary' | 'danger';
5
+ export interface ActionGroupPrimitiveProps {
6
+ children: ReactNode;
7
+ className?: string;
8
+ align?: ActionGroupAlign;
9
+ size?: ActionGroupSize;
10
+ }
11
+ export interface ActionSeparatorPrimitiveProps {
12
+ className?: string;
13
+ }
14
+ export interface ActionButtonPrimitiveProps extends Omit<ButtonHTMLAttributes<HTMLButtonElement>, 'children'> {
15
+ children?: ReactNode;
16
+ highlight?: boolean;
17
+ icon?: ReactNode;
18
+ label?: ReactNode;
19
+ loading?: boolean;
20
+ tooltip?: string;
21
+ variant?: ActionButtonVariant;
22
+ }
23
+ export interface IconButtonPrimitiveProps extends Omit<ActionButtonPrimitiveProps, 'children' | 'label'> {
24
+ 'aria-label': string;
25
+ icon: ReactNode;
26
+ }
27
+ export declare function ActionGroupPrimitive({ align, children, className, size }: ActionGroupPrimitiveProps): import("react").JSX.Element;
28
+ export declare function ActionSeparatorPrimitive({ className }: ActionSeparatorPrimitiveProps): import("react").JSX.Element;
29
+ export declare const ActionButtonPrimitive: import("react").ForwardRefExoticComponent<ActionButtonPrimitiveProps & import("react").RefAttributes<HTMLButtonElement>>;
30
+ export declare const IconButtonPrimitive: import("react").ForwardRefExoticComponent<IconButtonPrimitiveProps & import("react").RefAttributes<HTMLButtonElement>>;
31
+ //# sourceMappingURL=ActionPrimitives.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ActionPrimitives.d.ts","sourceRoot":"","sources":["../../src/components/ActionPrimitives.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAc,KAAK,oBAAoB,EAAE,KAAK,SAAS,EAAE,MAAM,OAAO,CAAC;AAG9E,MAAM,MAAM,gBAAgB,GAAG,OAAO,GAAG,KAAK,CAAC;AAC/C,MAAM,MAAM,eAAe,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,CAAC;AACjD,MAAM,MAAM,mBAAmB,GAAG,SAAS,GAAG,SAAS,GAAG,QAAQ,CAAC;AAEnE,MAAM,WAAW,yBAAyB;IACxC,QAAQ,EAAE,SAAS,CAAC;IACpB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE,gBAAgB,CAAC;IACzB,IAAI,CAAC,EAAE,eAAe,CAAC;CACxB;AAED,MAAM,WAAW,6BAA6B;IAC5C,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,0BAA2B,SAAQ,IAAI,CAAC,oBAAoB,CAAC,iBAAiB,CAAC,EAAE,UAAU,CAAC;IAC3G,QAAQ,CAAC,EAAE,SAAS,CAAC;IACrB,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,IAAI,CAAC,EAAE,SAAS,CAAC;IACjB,KAAK,CAAC,EAAE,SAAS,CAAC;IAClB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,OAAO,CAAC,EAAE,mBAAmB,CAAC;CAC/B;AAED,MAAM,WAAW,wBAAyB,SAAQ,IAAI,CAAC,0BAA0B,EAAE,UAAU,GAAG,OAAO,CAAC;IACtG,YAAY,EAAE,MAAM,CAAC;IACrB,IAAI,EAAE,SAAS,CAAC;CACjB;AAED,wBAAgB,oBAAoB,CAAC,EAAE,KAAe,EAAE,QAAQ,EAAE,SAAS,EAAE,IAAW,EAAE,EAAE,yBAAyB,+BAapH;AAED,wBAAgB,wBAAwB,CAAC,EAAE,SAAS,EAAE,EAAE,6BAA6B,+BAQpF;AAQD,eAAO,MAAM,qBAAqB,0HAiDjC,CAAC;AAIF,eAAO,MAAM,mBAAmB,wHAI/B,CAAC"}
@@ -0,0 +1,27 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { forwardRef } from 'react';
3
+ import { cn } from '../utils/cn';
4
+ export function ActionGroupPrimitive({ align = 'start', children, className, size = 'md' }) {
5
+ return (_jsx("div", { className: cn('flex flex-wrap items-center', align === 'start' ? 'justify-start' : 'justify-end', size === 'sm' ? 'gap-1.5' : size === 'lg' ? 'gap-2.5' : 'gap-2', className), children: children }));
6
+ }
7
+ export function ActionSeparatorPrimitive({ className }) {
8
+ return (_jsx("span", { "aria-hidden": "true", "data-action-separator": "true", className: cn('bg-app-border min-h-7 w-px shrink-0 self-stretch rounded-full', className) }));
9
+ }
10
+ const variantClasses = {
11
+ default: 'border-app-border bg-surface text-foreground-muted hover:border-[color-mix(in_srgb,var(--brand)_44%,var(--app-border))] hover:bg-[color-mix(in_srgb,var(--brand)_10%,var(--surface))] hover:text-brand hover:shadow-[var(--shadow-action)]',
12
+ primary: 'border-[color-mix(in_srgb,var(--brand)_44%,var(--app-border))] bg-[color-mix(in_srgb,var(--brand)_10%,var(--surface))] text-brand shadow-[var(--shadow-action)] hover:bg-[color-mix(in_srgb,var(--brand)_16%,var(--surface))] hover:text-brand',
13
+ danger: 'border-[var(--status-danger-border)] bg-[var(--status-danger-bg)] text-[var(--status-danger-text)] hover:border-[var(--destructive)] hover:bg-destructive hover:text-[var(--on-solid)]',
14
+ };
15
+ export const ActionButtonPrimitive = forwardRef(({ children, className, disabled, highlight = false, icon, label, loading = false, tooltip, type = 'button', variant = 'default', ...props }, ref) => {
16
+ const content = label ?? children;
17
+ const hasText = Boolean(content);
18
+ const isDisabled = disabled || loading;
19
+ return (_jsxs("button", { ref: ref, type: type, "aria-label": tooltip, title: tooltip, disabled: isDisabled, className: cn('inline-flex min-w-0 cursor-pointer select-none items-center justify-center border font-semibold transition-[background-color,border-color,color,box-shadow,transform,opacity] duration-[var(--duration-fast)] active:translate-y-px disabled:translate-y-0 focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-[color-mix(in_srgb,var(--brand)_36%,transparent)] disabled:cursor-not-allowed disabled:opacity-60', variantClasses[variant],
20
+ // Forma visual consistente: cantos arredondados (rounded-md) com e sem texto.
21
+ // Botoes so-icone (IconButtonPrimitive) ficam quadrados; botoes com texto
22
+ // recebem padding horizontal. A forma vem do pacote, nao do consumidor.
23
+ 'rounded-md', hasText ? 'min-h-8 max-w-44 gap-1.5 px-3 text-[length:var(--font-size-compact)]' : 'size-8 p-0', highlight && variant === 'default' && 'font-bold text-[color-mix(in_srgb,var(--brand)_86%,var(--foreground))] [&_svg]:stroke-[2.6]', highlight && variant === 'primary' && 'font-bold text-[color-mix(in_srgb,var(--brand)_72%,var(--foreground))] [&_svg]:stroke-[2.6]', highlight && variant === 'danger' && 'font-bold text-[color-mix(in_srgb,var(--destructive)_86%,var(--foreground))] [&_svg]:stroke-[2.6]', loading && 'cursor-wait opacity-75', className), ...props, children: [icon && _jsx("span", { className: "inline-flex shrink-0 items-center justify-center [&_svg]:size-4", children: icon }), hasText && _jsx("span", { className: "min-w-0 max-w-full truncate", children: content })] }));
24
+ });
25
+ ActionButtonPrimitive.displayName = 'ActionButtonPrimitive';
26
+ export const IconButtonPrimitive = forwardRef(({ 'aria-label': ariaLabel, tooltip, ...props }, ref) => (_jsx(ActionButtonPrimitive, { ref: ref, "aria-label": ariaLabel, tooltip: tooltip ?? ariaLabel, ...props })));
27
+ IconButtonPrimitive.displayName = 'IconButtonPrimitive';
@@ -0,0 +1,65 @@
1
+ import { type ReactNode } from 'react';
2
+ import { AppShellActions, AppShellActionsSeparator, type AppShellActionButtonProps } from './AppShellActions';
3
+ export type AppShellContentMode = 'default' | 'fluid' | 'fullscreen';
4
+ export type AppShellOverlayVariant = 'default' | 'soft' | 'strong';
5
+ export interface AppShellRootProps {
6
+ bannerSlot?: ReactNode;
7
+ children: ReactNode;
8
+ className?: string;
9
+ overlayVariant?: AppShellOverlayVariant;
10
+ }
11
+ export interface AppShellBodyProps {
12
+ children: ReactNode;
13
+ className?: string;
14
+ sidebar?: ReactNode;
15
+ }
16
+ export interface AppShellOverlayProps {
17
+ className?: string;
18
+ label?: string;
19
+ onClick: () => void;
20
+ variant?: AppShellOverlayVariant;
21
+ visible: boolean;
22
+ }
23
+ interface AppShellSlotProps {
24
+ children: ReactNode;
25
+ className?: string;
26
+ }
27
+ export interface AppShellTopbarButtonProps extends AppShellActionButtonProps {
28
+ }
29
+ export interface AppShellTopbarProps {
30
+ actions?: ReactNode;
31
+ actionsClassName?: string;
32
+ children?: ReactNode;
33
+ className?: string;
34
+ icon?: ReactNode;
35
+ mobileToggle?: ReactNode;
36
+ pageTitle: ReactNode;
37
+ titleContainerClassName?: string;
38
+ }
39
+ export declare const Topbar: import("react").ForwardRefExoticComponent<AppShellTopbarProps & import("react").RefAttributes<HTMLElement>> & {
40
+ Button: import("react").ForwardRefExoticComponent<AppShellTopbarButtonProps & import("react").RefAttributes<HTMLButtonElement>>;
41
+ };
42
+ export interface AppShellMainProps {
43
+ children: ReactNode;
44
+ className?: string;
45
+ contentPaddingClassName?: string;
46
+ contentMode?: AppShellContentMode;
47
+ disableContentPadding?: boolean;
48
+ scrollable?: boolean;
49
+ }
50
+ export declare const AppShell: {
51
+ Root: import("react").ForwardRefExoticComponent<AppShellRootProps & import("react").RefAttributes<HTMLDivElement>>;
52
+ Body: import("react").ForwardRefExoticComponent<AppShellBodyProps & import("react").RefAttributes<HTMLDivElement>>;
53
+ Overlay: import("react").ForwardRefExoticComponent<AppShellOverlayProps & import("react").RefAttributes<HTMLButtonElement>>;
54
+ Actions: typeof AppShellActions;
55
+ ActionButton: import("react").ForwardRefExoticComponent<import("./ActionPrimitives").ActionButtonPrimitiveProps & import("react").RefAttributes<HTMLButtonElement>>;
56
+ ActionsSeparator: typeof AppShellActionsSeparator;
57
+ ContentColumn: import("react").ForwardRefExoticComponent<AppShellSlotProps & import("react").RefAttributes<HTMLDivElement>>;
58
+ WorkArea: import("react").ForwardRefExoticComponent<AppShellSlotProps & import("react").RefAttributes<HTMLDivElement>>;
59
+ Topbar: import("react").ForwardRefExoticComponent<AppShellTopbarProps & import("react").RefAttributes<HTMLElement>> & {
60
+ Button: import("react").ForwardRefExoticComponent<AppShellTopbarButtonProps & import("react").RefAttributes<HTMLButtonElement>>;
61
+ };
62
+ Main: import("react").ForwardRefExoticComponent<AppShellMainProps & import("react").RefAttributes<HTMLElement>>;
63
+ };
64
+ export {};
65
+ //# sourceMappingURL=AppShell.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"AppShell.d.ts","sourceRoot":"","sources":["../../src/components/AppShell.tsx"],"names":[],"mappings":"AAAA,OAAO,EAIL,KAAK,SAAS,EACf,MAAM,OAAO,CAAC;AAGf,OAAO,EAEL,eAAe,EACf,wBAAwB,EACxB,KAAK,yBAAyB,EAC/B,MAAM,mBAAmB,CAAC;AAE3B,MAAM,MAAM,mBAAmB,GAAG,SAAS,GAAG,OAAO,GAAG,YAAY,CAAC;AACrE,MAAM,MAAM,sBAAsB,GAAG,SAAS,GAAG,MAAM,GAAG,QAAQ,CAAC;AAUnE,MAAM,WAAW,iBAAiB;IAChC,UAAU,CAAC,EAAE,SAAS,CAAC;IACvB,QAAQ,EAAE,SAAS,CAAC;IACpB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,cAAc,CAAC,EAAE,sBAAsB,CAAC;CACzC;AAcD,MAAM,WAAW,iBAAiB;IAChC,QAAQ,EAAE,SAAS,CAAC;IACpB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,OAAO,CAAC,EAAE,SAAS,CAAC;CACrB;AAeD,MAAM,WAAW,oBAAoB;IACnC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,IAAI,CAAC;IACpB,OAAO,CAAC,EAAE,sBAAsB,CAAC;IACjC,OAAO,EAAE,OAAO,CAAC;CAClB;AAsBD,UAAU,iBAAiB;IACzB,QAAQ,EAAE,SAAS,CAAC;IACpB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AA0BD,MAAM,WAAW,yBAA0B,SAAQ,yBAAyB;CAAG;AAa/E,MAAM,WAAW,mBAAmB;IAClC,OAAO,CAAC,EAAE,SAAS,CAAC;IACpB,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,EAAE,SAAS,CAAC;IACrB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,IAAI,CAAC,EAAE,SAAS,CAAC;IACjB,YAAY,CAAC,EAAE,SAAS,CAAC;IACzB,SAAS,EAAE,SAAS,CAAC;IACrB,uBAAuB,CAAC,EAAE,MAAM,CAAC;CAClC;AAqCD,eAAO,MAAM,MAAM;;CAEjB,CAAC;AAEH,MAAM,WAAW,iBAAiB;IAChC,QAAQ,EAAE,SAAS,CAAC;IACpB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,uBAAuB,CAAC,EAAE,MAAM,CAAC;IACjC,WAAW,CAAC,EAAE,mBAAmB,CAAC;IAClC,qBAAqB,CAAC,EAAE,OAAO,CAAC;IAChC,UAAU,CAAC,EAAE,OAAO,CAAC;CACtB;AAqCD,eAAO,MAAM,QAAQ;;;;;;;;;;;;;CAWpB,CAAC"}
@@ -0,0 +1,50 @@
1
+ import { jsxs as _jsxs, jsx as _jsx } from "react/jsx-runtime";
2
+ import { createContext, forwardRef, useContext, } from 'react';
3
+ import { cn } from '../utils/cn';
4
+ import { AppShellActionButton, AppShellActions, AppShellActionsSeparator, } from './AppShellActions';
5
+ const AppShellOverlayContext = createContext('default');
6
+ const overlayVariantClasses = {
7
+ default: 'bg-[var(--overlay-navigation)] backdrop-blur-[var(--backdrop-blur-sm)]',
8
+ soft: 'bg-[var(--overlay-navigation-soft)] backdrop-blur-[var(--backdrop-blur-xs)]',
9
+ strong: 'bg-[var(--overlay-navigation-strong)] backdrop-blur-[var(--backdrop-blur-md)]',
10
+ };
11
+ const Root = forwardRef(({ bannerSlot, children, className, overlayVariant = 'default' }, ref) => (_jsx(AppShellOverlayContext.Provider, { value: overlayVariant, children: _jsxs("div", { ref: ref, className: cn('flex h-screen flex-col', className), children: [bannerSlot, children] }) })));
12
+ Root.displayName = 'AppShell.Root';
13
+ const Body = forwardRef(({ children, className, sidebar }, ref) => (_jsxs("div", { ref: ref, className: cn('flex min-h-0 min-w-0 flex-1 overflow-hidden', className), children: [sidebar, children] })));
14
+ Body.displayName = 'AppShell.Body';
15
+ const Overlay = forwardRef(({ className, label = 'Fechar menu lateral', onClick, variant, visible }, ref) => {
16
+ const inheritedVariant = useContext(AppShellOverlayContext);
17
+ const resolvedVariant = variant ?? inheritedVariant;
18
+ if (!visible)
19
+ return null;
20
+ return (_jsx("button", { ref: ref, type: "button", "aria-label": label, className: cn('fixed inset-0 z-[var(--z-navigation-overlay)] cursor-pointer border-0', overlayVariantClasses[resolvedVariant], className), onClick: onClick }));
21
+ });
22
+ Overlay.displayName = 'AppShell.Overlay';
23
+ const ContentColumn = forwardRef(({ children, className }, ref) => (_jsx("div", { ref: ref, className: cn('flex min-h-0 min-w-0 flex-1 flex-col overflow-hidden', className), children: children })));
24
+ ContentColumn.displayName = 'AppShell.ContentColumn';
25
+ const WorkArea = forwardRef(({ children, className }, ref) => (_jsx("div", { ref: ref, className: cn('flex min-h-0 min-w-0 flex-1 flex-col-reverse overflow-hidden md:flex-col', className), children: children })));
26
+ WorkArea.displayName = 'AppShell.WorkArea';
27
+ const TopbarButton = forwardRef(({ className, ...props }, ref) => (_jsx(AppShellActionButton, { ref: ref, className: cn('relative size-10 min-h-10 min-w-10 !rounded-full', className), ...props })));
28
+ TopbarButton.displayName = 'AppShell.Topbar.Button';
29
+ const TopbarRoot = forwardRef(({ actions, actionsClassName, children, className, icon, mobileToggle, pageTitle, titleContainerClassName, }, ref) => (_jsxs("header", { ref: ref, className: cn('border-app-border bg-[var(--topbar-background)] flex min-h-16 items-center justify-between border-b px-4 pr-4 shadow-[var(--shadow-topbar)] max-md:pl-0', className), role: "banner", children: [_jsxs("div", { className: cn('flex min-w-0 items-center gap-2.5 max-md:gap-3', titleContainerClassName), children: [mobileToggle, icon && _jsx("span", { className: "shrink-0 text-foreground-muted", "aria-hidden": "true", children: icon }), _jsx("span", { className: "min-w-0 overflow-hidden text-ellipsis whitespace-nowrap text-lg font-semibold leading-7 tracking-[var(--letter-spacing-title)] text-foreground-muted", children: pageTitle })] }), (children || actions) && (_jsxs("div", { className: cn('flex shrink-0 items-center gap-4', actionsClassName), children: [children, actions] }))] })));
30
+ TopbarRoot.displayName = 'AppShell.Topbar';
31
+ export const Topbar = Object.assign(TopbarRoot, {
32
+ Button: TopbarButton,
33
+ });
34
+ const Main = forwardRef(({ children, className, contentPaddingClassName = 'p-3', contentMode = 'default', disableContentPadding = false, scrollable = true, }, ref) => {
35
+ const isFullscreen = contentMode === 'fullscreen';
36
+ return (_jsx("main", { ref: ref, className: cn('flex h-full min-h-0 w-full flex-1 flex-col bg-background', !isFullscreen && 'overflow-x-hidden', contentMode === 'default' && 'flex flex-col gap-3', contentMode === 'fluid' && 'flex flex-col gap-3 overflow-y-hidden', contentMode === 'fullscreen' && 'overflow-hidden p-0', !isFullscreen && !disableContentPadding && contentPaddingClassName, !isFullscreen && (scrollable ? 'overflow-y-auto' : 'overflow-y-hidden'), className), children: children }));
37
+ });
38
+ Main.displayName = 'AppShell.Main';
39
+ export const AppShell = {
40
+ Root,
41
+ Body,
42
+ Overlay,
43
+ Actions: AppShellActions,
44
+ ActionButton: AppShellActionButton,
45
+ ActionsSeparator: AppShellActionsSeparator,
46
+ ContentColumn,
47
+ WorkArea,
48
+ Topbar,
49
+ Main,
50
+ };
@@ -0,0 +1,24 @@
1
+ import { type ReactNode } from 'react';
2
+ import { type ActionButtonPrimitiveProps, type ActionButtonVariant, type ActionGroupAlign, type ActionGroupSize, type ActionSeparatorPrimitiveProps } from './ActionPrimitives';
3
+ export type AppShellActionsRegion = 'left' | 'top' | 'bottom' | 'right';
4
+ export type AppShellActionsAlign = ActionGroupAlign;
5
+ export type AppShellActionsSize = ActionGroupSize;
6
+ export type AppShellActionButtonVariant = ActionButtonVariant;
7
+ export interface AppShellActionsProps {
8
+ children: ReactNode;
9
+ className?: string;
10
+ region?: AppShellActionsRegion;
11
+ align?: AppShellActionsAlign;
12
+ size?: AppShellActionsSize;
13
+ }
14
+ export type AppShellActionsSeparatorProps = ActionSeparatorPrimitiveProps;
15
+ export type AppShellActionButtonProps = ActionButtonPrimitiveProps;
16
+ export declare function AppShellActions({ align, children, className, region, size }: AppShellActionsProps): import("react").JSX.Element;
17
+ export declare function AppShellActionsSeparator(props: AppShellActionsSeparatorProps): import("react").JSX.Element;
18
+ export declare const AppShellActionButton: import("react").ForwardRefExoticComponent<ActionButtonPrimitiveProps & import("react").RefAttributes<HTMLButtonElement>>;
19
+ export declare const AppShellActionsApi: {
20
+ Root: typeof AppShellActions;
21
+ Button: import("react").ForwardRefExoticComponent<ActionButtonPrimitiveProps & import("react").RefAttributes<HTMLButtonElement>>;
22
+ Separator: typeof AppShellActionsSeparator;
23
+ };
24
+ //# sourceMappingURL=AppShellActions.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"AppShellActions.d.ts","sourceRoot":"","sources":["../../src/components/AppShellActions.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,SAAS,EAAE,MAAM,OAAO,CAAC;AACvC,OAAO,EAIL,KAAK,0BAA0B,EAC/B,KAAK,mBAAmB,EACxB,KAAK,gBAAgB,EACrB,KAAK,eAAe,EACpB,KAAK,6BAA6B,EACnC,MAAM,oBAAoB,CAAC;AAG5B,MAAM,MAAM,qBAAqB,GAAG,MAAM,GAAG,KAAK,GAAG,QAAQ,GAAG,OAAO,CAAC;AACxE,MAAM,MAAM,oBAAoB,GAAG,gBAAgB,CAAC;AACpD,MAAM,MAAM,mBAAmB,GAAG,eAAe,CAAC;AAClD,MAAM,MAAM,2BAA2B,GAAG,mBAAmB,CAAC;AAE9D,MAAM,WAAW,oBAAoB;IACnC,QAAQ,EAAE,SAAS,CAAC;IACpB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,MAAM,CAAC,EAAE,qBAAqB,CAAC;IAC/B,KAAK,CAAC,EAAE,oBAAoB,CAAC;IAC7B,IAAI,CAAC,EAAE,mBAAmB,CAAC;CAC5B;AAED,MAAM,MAAM,6BAA6B,GAAG,6BAA6B,CAAC;AAC1E,MAAM,MAAM,yBAAyB,GAAG,0BAA0B,CAAC;AAEnE,wBAAgB,eAAe,CAAC,EAAE,KAAe,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAc,EAAE,IAAW,EAAE,EAAE,oBAAoB,+BAgB1H;AAED,wBAAgB,wBAAwB,CAAC,KAAK,EAAE,6BAA6B,+BAE5E;AAED,eAAO,MAAM,oBAAoB,0HAAwB,CAAC;AAE1D,eAAO,MAAM,kBAAkB;;;;CAI9B,CAAC"}
@@ -0,0 +1,15 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { ActionButtonPrimitive, ActionGroupPrimitive, ActionSeparatorPrimitive, } from './ActionPrimitives';
3
+ import { cn } from '../utils/cn';
4
+ export function AppShellActions({ align = 'start', children, className, region = 'top', size = 'md' }) {
5
+ return (_jsx(ActionGroupPrimitive, { align: align, size: size, className: cn('min-w-0', region === 'top' && 'h-full overflow-x-auto overflow-y-hidden', region === 'bottom' && 'border-app-border bg-background-secondary w-full border-t p-2', (region === 'left' || region === 'right') && 'flex-col items-stretch', className), children: children }));
6
+ }
7
+ export function AppShellActionsSeparator(props) {
8
+ return _jsx(ActionSeparatorPrimitive, { ...props });
9
+ }
10
+ export const AppShellActionButton = ActionButtonPrimitive;
11
+ export const AppShellActionsApi = {
12
+ Root: AppShellActions,
13
+ Button: AppShellActionButton,
14
+ Separator: AppShellActionsSeparator,
15
+ };
@@ -0,0 +1,16 @@
1
+ import { type HTMLAttributes } from 'react';
2
+ export type BadgeVariant = 'default' | 'primary' | 'success' | 'warning' | 'info' | 'danger' | 'muted';
3
+ export type BadgeSize = 'xs' | 'sm' | 'md';
4
+ export interface BadgeProps extends HTMLAttributes<HTMLSpanElement> {
5
+ variant?: BadgeVariant | string;
6
+ size?: BadgeSize;
7
+ /**
8
+ * Permite que o conteudo quebre em multiplas linhas quando nao couber na largura
9
+ * disponivel. Por padrao o badge fica em linha unica (`inline-flex` + `whitespace-nowrap`),
10
+ * adequado a status curtos; com `wrap` vira `inline-block` e quebra palavras longas,
11
+ * util para valores longos (ex.: auditoria).
12
+ */
13
+ wrap?: boolean;
14
+ }
15
+ export declare const Badge: import("react").ForwardRefExoticComponent<BadgeProps & import("react").RefAttributes<HTMLSpanElement>>;
16
+ //# sourceMappingURL=Badge.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Badge.d.ts","sourceRoot":"","sources":["../../src/components/Badge.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAc,KAAK,cAAc,EAAE,MAAM,OAAO,CAAC;AAIxD,MAAM,MAAM,YAAY,GACpB,SAAS,GACT,SAAS,GACT,SAAS,GACT,SAAS,GACT,MAAM,GACN,QAAQ,GACR,OAAO,CAAC;AAEZ,MAAM,MAAM,SAAS,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,CAAC;AAE3C,MAAM,WAAW,UAAW,SAAQ,cAAc,CAAC,eAAe,CAAC;IACjE,OAAO,CAAC,EAAE,YAAY,GAAG,MAAM,CAAC;IAChC,IAAI,CAAC,EAAE,SAAS,CAAC;IACjB;;;;;OAKG;IACH,IAAI,CAAC,EAAE,OAAO,CAAC;CAChB;AA+BD,eAAO,MAAM,KAAK,wGAuBjB,CAAC"}
@@ -0,0 +1,36 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { forwardRef } from 'react';
3
+ import { cn } from '../utils/cn';
4
+ const variantAlias = {
5
+ active: 'success',
6
+ paid: 'success',
7
+ pending: 'warning',
8
+ sent: 'warning',
9
+ error: 'danger',
10
+ 'status-success': 'success',
11
+ 'status-danger': 'danger',
12
+ };
13
+ const variantClasses = {
14
+ default: 'border-[color-mix(in_srgb,var(--foreground-muted)_42%,var(--app-border))] bg-[color-mix(in_srgb,var(--foreground-muted)_14%,var(--surface))] text-foreground',
15
+ primary: 'border-[color-mix(in_srgb,var(--brand)_40%,transparent)] bg-[color-mix(in_srgb,var(--brand)_14%,var(--surface))] text-[var(--brand)]',
16
+ success: 'border-[var(--status-success-border)] bg-[var(--status-success-bg)] text-[var(--status-success-text)]',
17
+ warning: 'border-[var(--status-warning-border)] bg-[var(--status-warning-bg)] text-[var(--status-warning-text)]',
18
+ info: 'border-[var(--status-info-border)] bg-[var(--status-info-bg)] text-[var(--status-info-text)]',
19
+ danger: 'border-[var(--status-danger-border)] bg-[var(--status-danger-bg)] text-[var(--status-danger-text)]',
20
+ muted: 'border-[color-mix(in_srgb,var(--foreground-muted)_24%,transparent)] bg-[color-mix(in_srgb,var(--foreground-muted)_8%,var(--surface))] text-foreground-muted',
21
+ };
22
+ const sizeClasses = {
23
+ xs: 'px-2 py-0.5 text-xs',
24
+ sm: 'px-2.5 py-1 text-sm',
25
+ md: 'px-3 py-1 text-base',
26
+ };
27
+ export const Badge = forwardRef(({ className, size = 'xs', variant = 'default', wrap = false, ...props }, ref) => {
28
+ const normalizedVariant = variant.toLowerCase();
29
+ const normalizedAlias = variantAlias[normalizedVariant] ?? normalizedVariant;
30
+ const knownVariant = normalizedAlias;
31
+ const variantClass = variantClasses[knownVariant] ?? normalizedVariant;
32
+ return (_jsx("span", { ref: ref, className: cn('rounded-full border font-medium', wrap
33
+ ? 'inline-block whitespace-normal break-words [overflow-wrap:anywhere] leading-snug'
34
+ : 'inline-flex items-center gap-1.5 whitespace-nowrap leading-none', variantClass, sizeClasses[size], className), ...props }));
35
+ });
36
+ Badge.displayName = 'Badge';
@@ -0,0 +1,13 @@
1
+ import { type ReactNode } from 'react';
2
+ export type BannerVariant = 'info' | 'warning' | 'critical' | 'success';
3
+ export type BannerSize = 'sm' | 'md' | 'lg';
4
+ export interface BannerProps {
5
+ variant?: BannerVariant;
6
+ size?: BannerSize;
7
+ closable?: boolean;
8
+ onClose?: () => void;
9
+ className?: string;
10
+ children: ReactNode;
11
+ }
12
+ export declare function Banner({ variant, size, closable, onClose, className, children, }: BannerProps): import("react").JSX.Element | null;
13
+ //# sourceMappingURL=Banner.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Banner.d.ts","sourceRoot":"","sources":["../../src/components/Banner.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAY,KAAK,SAAS,EAAE,MAAM,OAAO,CAAC;AAMjD,MAAM,MAAM,aAAa,GAAG,MAAM,GAAG,SAAS,GAAG,UAAU,GAAG,SAAS,CAAC;AACxE,MAAM,MAAM,UAAU,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,CAAC;AAE5C,MAAM,WAAW,WAAW;IAC1B,OAAO,CAAC,EAAE,aAAa,CAAC;IACxB,IAAI,CAAC,EAAE,UAAU,CAAC;IAClB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;IACrB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,SAAS,CAAC;CACrB;AAeD,wBAAgB,MAAM,CAAC,EACrB,OAAgB,EAChB,IAAW,EACX,QAAe,EACf,OAAO,EACP,SAAS,EACT,QAAQ,GACT,EAAE,WAAW,sCAwCb"}
@@ -0,0 +1,29 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { useState } from 'react';
3
+ import { X } from 'lucide-react';
4
+ import { Button } from './Button';
5
+ import { cn } from '../utils/cn';
6
+ const variantStyles = {
7
+ info: 'border-[var(--status-info-border)] bg-[var(--status-info-bg)] text-[var(--status-info-text)]',
8
+ warning: 'border-[var(--status-warning-border)] bg-[var(--status-warning-bg)] text-[var(--status-warning-text)]',
9
+ critical: 'border-[var(--status-danger-border)] bg-[var(--status-danger-bg)] text-[var(--status-danger-text)]',
10
+ success: 'border-[var(--status-success-border)] bg-[var(--status-success-bg)] text-[var(--status-success-text)]',
11
+ };
12
+ const sizeStyles = {
13
+ sm: 'min-h-10 px-3 py-2 text-sm',
14
+ md: 'min-h-11 px-4 py-2.5 text-sm',
15
+ lg: 'min-h-12 px-4 py-3 text-base',
16
+ };
17
+ export function Banner({ variant = 'info', size = 'md', closable = true, onClose, className, children, }) {
18
+ const [visible, setVisible] = useState(true);
19
+ function handleClose() {
20
+ if (onClose) {
21
+ onClose();
22
+ return;
23
+ }
24
+ setVisible(false);
25
+ }
26
+ if (!visible)
27
+ return null;
28
+ return (_jsxs("div", { className: cn('relative flex w-full items-center border shadow-sm', variantStyles[variant], sizeStyles[size], className), children: [_jsx("div", { className: "flex min-w-0 flex-1 items-center justify-center gap-2 text-center", children: children }), closable ? (_jsx(Button, { variant: "ghost", size: "xs", rounded: true, "aria-label": "Fechar banner", className: "absolute top-1/2 right-2 -translate-y-1/2 text-current hover:bg-[var(--contrast-hover)]", onClick: handleClose, children: _jsx(X, { className: "size-4" }) })) : null] }));
29
+ }
@@ -0,0 +1,14 @@
1
+ import { type ButtonHTMLAttributes } from 'react';
2
+ export type ButtonVariant = 'primary' | 'secondary' | 'ghost' | 'outline' | 'success' | 'warning' | 'danger' | 'destructive';
3
+ export type ButtonSize = 'xs' | 'sm' | 'md' | 'lg' | 'wide';
4
+ export interface ButtonProps extends ButtonHTMLAttributes<HTMLButtonElement> {
5
+ variant?: ButtonVariant;
6
+ size?: ButtonSize;
7
+ isLoading?: boolean;
8
+ isSubmitting?: boolean;
9
+ minWidth?: number | string;
10
+ rounded?: boolean;
11
+ tooltip?: string;
12
+ }
13
+ export declare const Button: import("react").ForwardRefExoticComponent<ButtonProps & import("react").RefAttributes<HTMLButtonElement>>;
14
+ //# sourceMappingURL=Button.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Button.d.ts","sourceRoot":"","sources":["../../src/components/Button.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAc,KAAK,oBAAoB,EAAE,MAAM,OAAO,CAAC;AAI9D,MAAM,MAAM,aAAa,GACrB,SAAS,GACT,WAAW,GACX,OAAO,GACP,SAAS,GACT,SAAS,GACT,SAAS,GACT,QAAQ,GACR,aAAa,CAAC;AAClB,MAAM,MAAM,UAAU,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,GAAG,MAAM,CAAC;AAE5D,MAAM,WAAW,WAAY,SAAQ,oBAAoB,CAAC,iBAAiB,CAAC;IAC1E,OAAO,CAAC,EAAE,aAAa,CAAC;IACxB,IAAI,CAAC,EAAE,UAAU,CAAC;IAClB,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,QAAQ,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IAC3B,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAqCD,eAAO,MAAM,MAAM,2GAmDlB,CAAC"}