@wellingtonhlc/shared-ui 0.27.1 → 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.
- package/README.md +45 -14
- package/dist/components/ActionBar.js +3 -3
- package/dist/components/ActionPrimitives.js +5 -5
- package/dist/components/AppShell.js +5 -5
- package/dist/components/Badge.js +4 -4
- package/dist/components/Banner.js +5 -5
- package/dist/components/Button.d.ts +1 -1
- package/dist/components/Button.d.ts.map +1 -1
- package/dist/components/Button.js +11 -13
- package/dist/components/Card.js +3 -3
- package/dist/components/ConfirmationDialog.js +12 -12
- package/dist/components/CopyableField.js +1 -1
- package/dist/components/DateField.d.ts +1 -0
- package/dist/components/DateField.d.ts.map +1 -1
- package/dist/components/DateField.js +2 -2
- package/dist/components/FieldControl.js +2 -2
- package/dist/components/FieldValidationError.js +1 -1
- package/dist/components/LoadingOverlay.js +1 -1
- package/dist/components/Modal.js +2 -2
- package/dist/components/MultiSelectField.js +3 -3
- package/dist/components/NavCard.js +1 -1
- package/dist/components/Page.js +4 -4
- package/dist/components/Pagination.js +7 -7
- package/dist/components/RadioGroup.js +2 -2
- package/dist/components/SelectionField.js +1 -1
- package/dist/components/Sidebar.d.ts.map +1 -1
- package/dist/components/Sidebar.js +17 -17
- package/dist/components/Switch.js +1 -1
- package/dist/components/Table.d.ts.map +1 -1
- package/dist/components/Table.js +6 -8
- package/dist/components/TabsUnderlined.d.ts.map +1 -1
- package/dist/components/TabsUnderlined.js +5 -5
- package/dist/components/ThemePreferencesSelector.js +4 -4
- package/dist/components/Tooltip.js +1 -1
- package/dist/components/form-control-helpers.js +1 -1
- package/dist/styles.css +606 -745
- package/package.json +14 -2
package/README.md
CHANGED
|
@@ -168,10 +168,32 @@ import { cn } from '@wellingtonhlc/shared-ui/utils/cn';
|
|
|
168
168
|
Estilos:
|
|
169
169
|
|
|
170
170
|
```tsx
|
|
171
|
-
import '@wellingtonhlc/shared-ui/styles.css';
|
|
172
|
-
```
|
|
173
|
-
|
|
174
|
-
|
|
171
|
+
import '@wellingtonhlc/shared-ui/styles.css';
|
|
172
|
+
```
|
|
173
|
+
|
|
174
|
+
### Foundations e tokens
|
|
175
|
+
|
|
176
|
+
`styles.css` define os tokens semânticos consumidos pelos componentes. Prefira sempre
|
|
177
|
+
esses tokens a valores locais:
|
|
178
|
+
|
|
179
|
+
- cores de superfície, texto, borda, marca e estados (`--background`, `--surface`,
|
|
180
|
+
`--brand`, `--status-*-*`);
|
|
181
|
+
- tipografia (`--font-family-*`, `--font-size-*`, `--line-height-*`);
|
|
182
|
+
- espaçamento (`--space-*`);
|
|
183
|
+
- forma e elevação (`--radius-*`, `--shadow-*`);
|
|
184
|
+
- movimento (`--duration-*`).
|
|
185
|
+
|
|
186
|
+
O Storybook documenta as escalas em `Foundations` e organiza os exemplos públicos em
|
|
187
|
+
`Components`, por função. Consumidores podem sobrescrever tokens de tema, mas componentes
|
|
188
|
+
não devem introduzir hexadecimais, sombras ou escalas paralelas.
|
|
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
|
+
|
|
196
|
+
Preset Tailwind:
|
|
175
197
|
|
|
176
198
|
```ts
|
|
177
199
|
import sharedUiPreset from '@wellingtonhlc/shared-ui/tailwind-preset';
|
|
@@ -249,13 +271,22 @@ primitivos de acao, mas aplica o tamanho esperado para a topbar.
|
|
|
249
271
|
import { AppShell } from '@wellingtonhlc/shared-ui';
|
|
250
272
|
import { Bell, Settings } from 'lucide-react';
|
|
251
273
|
|
|
252
|
-
<AppShell.Actions>
|
|
253
|
-
<AppShell.Topbar.Button icon={<Bell />} tooltip="Notificacoes" />
|
|
254
|
-
<AppShell.Topbar.Button icon={<Settings />} tooltip="Configuracoes" />
|
|
255
|
-
</AppShell.Actions>
|
|
256
|
-
```
|
|
257
|
-
|
|
258
|
-
##
|
|
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
|
|
259
290
|
|
|
260
291
|
`TabsUnderlined` renderiza abas sublinhadas com conteudo controlado ou nao controlado.
|
|
261
292
|
As abas ja possuem tamanho minimo padrao e padding horizontal para comportar labels
|
|
@@ -287,15 +318,15 @@ Contrato minimo:
|
|
|
287
318
|
```tsx
|
|
288
319
|
import { ThemePreferencesSelector, type ThemePreferencesValue } from '@wellingtonhlc/shared-ui';
|
|
289
320
|
|
|
290
|
-
const value: ThemePreferencesValue = {
|
|
291
|
-
color: '
|
|
321
|
+
const value: ThemePreferencesValue = {
|
|
322
|
+
color: 'ocean',
|
|
292
323
|
appearance: 'system',
|
|
293
324
|
};
|
|
294
325
|
|
|
295
326
|
<ThemePreferencesSelector
|
|
296
327
|
value={value}
|
|
297
328
|
options={[
|
|
298
|
-
{ key: '
|
|
329
|
+
{ key: 'ocean', label: 'Ocean', primary: '#2563eb' },
|
|
299
330
|
{ key: 'emerald', label: 'Emerald', primary: '#059669' },
|
|
300
331
|
]}
|
|
301
332
|
onChange={setValue}
|
|
@@ -9,8 +9,8 @@ function Separator({ className }) {
|
|
|
9
9
|
}
|
|
10
10
|
const variantClasses = {
|
|
11
11
|
default: 'text-foreground-muted hover:bg-background hover:text-foreground data-[state=open]:bg-background data-[state=open]:text-foreground',
|
|
12
|
-
primary: 'text-
|
|
13
|
-
danger: 'text-
|
|
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
14
|
};
|
|
15
15
|
const shapeClasses = {
|
|
16
16
|
icon: 'size-8 p-0',
|
|
@@ -19,7 +19,7 @@ const shapeClasses = {
|
|
|
19
19
|
const Button = forwardRef(({ className, disabled = false, highlight = false, icon, label, loading = false, tooltip, type = 'button', variant = 'default', ...props }, ref) => {
|
|
20
20
|
const resolvedVariant = highlight ? 'primary' : variant;
|
|
21
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-
|
|
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
23
|
});
|
|
24
24
|
Button.displayName = 'ActionBar.Button';
|
|
25
25
|
export const ActionBar = {
|
|
@@ -8,19 +8,19 @@ export function ActionSeparatorPrimitive({ className }) {
|
|
|
8
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
9
|
}
|
|
10
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-[
|
|
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-[
|
|
13
|
-
danger: 'border-[var(--status-danger-border
|
|
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
14
|
};
|
|
15
15
|
export const ActionButtonPrimitive = forwardRef(({ children, className, disabled, highlight = false, icon, label, loading = false, tooltip, type = 'button', variant = 'default', ...props }, ref) => {
|
|
16
16
|
const content = label ?? children;
|
|
17
17
|
const hasText = Boolean(content);
|
|
18
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-
|
|
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
20
|
// Forma visual consistente: cantos arredondados (rounded-md) com e sem texto.
|
|
21
21
|
// Botoes so-icone (IconButtonPrimitive) ficam quadrados; botoes com texto
|
|
22
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-[
|
|
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
24
|
});
|
|
25
25
|
ActionButtonPrimitive.displayName = 'ActionButtonPrimitive';
|
|
26
26
|
export const IconButtonPrimitive = forwardRef(({ 'aria-label': ariaLabel, tooltip, ...props }, ref) => (_jsx(ActionButtonPrimitive, { ref: ref, "aria-label": ariaLabel, tooltip: tooltip ?? ariaLabel, ...props })));
|
|
@@ -4,9 +4,9 @@ import { cn } from '../utils/cn';
|
|
|
4
4
|
import { AppShellActionButton, AppShellActions, AppShellActionsSeparator, } from './AppShellActions';
|
|
5
5
|
const AppShellOverlayContext = createContext('default');
|
|
6
6
|
const overlayVariantClasses = {
|
|
7
|
-
default: 'bg-
|
|
8
|
-
soft: 'bg-
|
|
9
|
-
strong: 'bg-
|
|
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
10
|
};
|
|
11
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
12
|
Root.displayName = 'AppShell.Root';
|
|
@@ -17,7 +17,7 @@ const Overlay = forwardRef(({ className, label = 'Fechar menu lateral', onClick,
|
|
|
17
17
|
const resolvedVariant = variant ?? inheritedVariant;
|
|
18
18
|
if (!visible)
|
|
19
19
|
return null;
|
|
20
|
-
return (_jsx("button", { ref: ref, type: "button", "aria-label": label, className: cn('fixed inset-0 z-[
|
|
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
21
|
});
|
|
22
22
|
Overlay.displayName = 'AppShell.Overlay';
|
|
23
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 })));
|
|
@@ -26,7 +26,7 @@ const WorkArea = forwardRef(({ children, className }, ref) => (_jsx("div", { ref
|
|
|
26
26
|
WorkArea.displayName = 'AppShell.WorkArea';
|
|
27
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
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-background
|
|
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
30
|
TopbarRoot.displayName = 'AppShell.Topbar';
|
|
31
31
|
export const Topbar = Object.assign(TopbarRoot, {
|
|
32
32
|
Button: TopbarButton,
|
package/dist/components/Badge.js
CHANGED
|
@@ -13,10 +13,10 @@ const variantAlias = {
|
|
|
13
13
|
const variantClasses = {
|
|
14
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
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
|
|
17
|
-
warning: 'border-[var(--status-warning-border
|
|
18
|
-
info: 'border-[var(--status-info-border
|
|
19
|
-
danger: 'border-[var(--status-danger-border
|
|
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
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
21
|
};
|
|
22
22
|
const sizeClasses = {
|
|
@@ -4,10 +4,10 @@ import { X } from 'lucide-react';
|
|
|
4
4
|
import { Button } from './Button';
|
|
5
5
|
import { cn } from '../utils/cn';
|
|
6
6
|
const variantStyles = {
|
|
7
|
-
info: 'border-[
|
|
8
|
-
warning: 'border-[
|
|
9
|
-
critical: 'border-[
|
|
10
|
-
success: 'border-[
|
|
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
11
|
};
|
|
12
12
|
const sizeStyles = {
|
|
13
13
|
sm: 'min-h-10 px-3 py-2 text-sm',
|
|
@@ -25,5 +25,5 @@ export function Banner({ variant = 'info', size = 'md', closable = true, onClose
|
|
|
25
25
|
}
|
|
26
26
|
if (!visible)
|
|
27
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-
|
|
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
29
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { type ButtonHTMLAttributes } from 'react';
|
|
2
|
-
export type ButtonVariant = 'primary' | 'secondary' | 'ghost' | 'outline' | '
|
|
2
|
+
export type ButtonVariant = 'primary' | 'secondary' | 'ghost' | 'outline' | 'success' | 'warning' | 'danger' | 'destructive';
|
|
3
3
|
export type ButtonSize = 'xs' | 'sm' | 'md' | 'lg' | 'wide';
|
|
4
4
|
export interface ButtonProps extends ButtonHTMLAttributes<HTMLButtonElement> {
|
|
5
5
|
variant?: ButtonVariant;
|
|
@@ -1 +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,
|
|
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"}
|
|
@@ -2,26 +2,24 @@ import { jsx as _jsx } from "react/jsx-runtime";
|
|
|
2
2
|
import { forwardRef } from 'react';
|
|
3
3
|
import { cn } from '../utils/cn';
|
|
4
4
|
const variantClasses = {
|
|
5
|
-
primary: 'border-transparent bg-[var(--brand)] text-[var(--primary-foreground
|
|
6
|
-
secondary: 'border-[
|
|
7
|
-
ghost: 'border-transparent bg-transparent text-foreground-muted hover:bg-[
|
|
8
|
-
outline: 'border-app-border bg-transparent text-foreground hover:border-[color-mix(in_srgb,var(--brand)_46%,var(--app-border))] hover:bg-[
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
destructive: 'border-transparent bg-[#dc2626] text-white hover:bg-[#b91c1c]',
|
|
14
|
-
sidebar: 'border-transparent bg-transparent text-foreground-muted hover:bg-[color-mix(in_srgb,var(--brand)_10%,transparent)] hover:text-[var(--brand)]',
|
|
5
|
+
primary: 'border-transparent bg-[var(--brand)] text-[var(--primary-foreground)] shadow-[var(--shadow-brand)] hover:bg-[var(--brand-hover)] hover:shadow-[var(--shadow-brand-hover)]',
|
|
6
|
+
secondary: 'border-[var(--status-info-border)] bg-[var(--status-info-bg)] text-[var(--status-info-text)] shadow-[inset_0_0_0_1px_color-mix(in_srgb,var(--status-info-border)_18%,transparent)] hover:bg-[color-mix(in_srgb,var(--status-info-bg)_78%,var(--status-info-border))]',
|
|
7
|
+
ghost: 'border-transparent bg-transparent text-foreground-muted hover:bg-[var(--brand-surface-hover)] hover:text-[color-mix(in_srgb,var(--brand)_86%,var(--foreground))] dark:hover:text-[color-mix(in_srgb,var(--brand)_78%,var(--on-solid))]',
|
|
8
|
+
outline: 'border-app-border bg-transparent text-foreground hover:border-[color-mix(in_srgb,var(--brand)_46%,var(--app-border))] hover:bg-[var(--brand-surface-subtle)] hover:text-[color-mix(in_srgb,var(--brand)_86%,var(--foreground))] dark:hover:border-[color-mix(in_srgb,var(--brand)_54%,var(--app-border))] dark:hover:text-[color-mix(in_srgb,var(--brand)_78%,var(--on-solid))]',
|
|
9
|
+
success: 'border-[var(--status-success-border)] bg-[var(--status-success-bg)] text-[var(--status-success-text)] shadow-[inset_0_0_0_1px_color-mix(in_srgb,var(--status-success-border)_18%,transparent)] hover:bg-[color-mix(in_srgb,var(--status-success-bg)_78%,var(--status-success-border))]',
|
|
10
|
+
warning: 'border-[var(--status-warning-border)] bg-[var(--status-warning-bg)] text-[var(--status-warning-text)] shadow-[inset_0_0_0_1px_color-mix(in_srgb,var(--status-warning-border)_18%,transparent)] hover:bg-[color-mix(in_srgb,var(--status-warning-bg)_78%,var(--status-warning-border))]',
|
|
11
|
+
danger: 'border-[var(--status-danger-border)] bg-[var(--status-danger-bg)] text-[var(--status-danger-text)] shadow-[inset_0_0_0_1px_color-mix(in_srgb,var(--status-danger-border)_18%,transparent)] hover:bg-[color-mix(in_srgb,var(--status-danger-bg)_78%,var(--status-danger-border))]',
|
|
12
|
+
destructive: 'border-transparent bg-[var(--destructive)] text-[var(--on-solid)] hover:bg-[var(--destructive-hover)]',
|
|
15
13
|
};
|
|
16
14
|
const sizeClasses = {
|
|
17
|
-
xs: 'min-h-7 min-w-7 px-1.5 py-1 text-[
|
|
15
|
+
xs: 'min-h-7 min-w-7 px-1.5 py-1 text-[length:var(--font-size-2xs)]',
|
|
18
16
|
sm: 'min-h-9 min-w-9 px-2.5 py-2 text-xs',
|
|
19
17
|
md: 'min-h-11 min-w-20 px-4 py-2.5 text-sm',
|
|
20
18
|
lg: 'min-h-13 min-w-24 px-6 py-3 text-base',
|
|
21
19
|
wide: 'min-h-11 min-w-20 w-full px-4 py-2.5 text-sm',
|
|
22
20
|
};
|
|
23
21
|
const roundedSizeClasses = {
|
|
24
|
-
xs: 'size-7 min-h-7 min-w-7 p-1 text-[
|
|
22
|
+
xs: 'size-7 min-h-7 min-w-7 p-1 text-[length:var(--font-size-2xs)]',
|
|
25
23
|
sm: 'size-9 min-h-9 min-w-9 p-1.5 text-xs',
|
|
26
24
|
md: 'size-12 min-h-12 min-w-12 p-2 text-sm',
|
|
27
25
|
lg: 'size-14 min-h-14 min-w-14 p-3 text-base',
|
|
@@ -31,7 +29,7 @@ export const Button = forwardRef(({ children, className, disabled, isLoading = f
|
|
|
31
29
|
const busy = isLoading || isSubmitting;
|
|
32
30
|
const resolvedSize = rounded ? roundedSizeClasses[size] : sizeClasses[size];
|
|
33
31
|
const ariaBusy = props['aria-busy'] ?? (busy ? true : undefined);
|
|
34
|
-
return (_jsx("button", { ref: ref, className: cn('inline-flex cursor-pointer items-center justify-center gap-2 rounded-[var(--radius)] border font-semibold leading-none no-underline transition-[background-color,border-color,color,opacity,box-shadow] duration-
|
|
32
|
+
return (_jsx("button", { ref: ref, className: cn('inline-flex cursor-pointer items-center justify-center gap-2 rounded-[var(--radius)] border font-semibold leading-none no-underline transition-[background-color,border-color,color,opacity,box-shadow] duration-[var(--duration-fast)] focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-brand/30 disabled:cursor-not-allowed disabled:opacity-55 disabled:saturate-50', variantClasses[variant], resolvedSize, rounded && 'rounded-full', busy && 'cursor-wait opacity-90', className), disabled: disabled || busy, style: {
|
|
35
33
|
...style,
|
|
36
34
|
...(minWidth !== undefined
|
|
37
35
|
? { minWidth: typeof minWidth === 'number' ? `${minWidth}px` : minWidth }
|
package/dist/components/Card.js
CHANGED
|
@@ -5,10 +5,10 @@ function getCardVariantClass(variant) {
|
|
|
5
5
|
return 'bg-[color-mix(in_srgb,var(--foreground-muted)_5%,var(--surface))] shadow-none';
|
|
6
6
|
}
|
|
7
7
|
if (variant === 'surface') {
|
|
8
|
-
return 'bg-surface shadow-[inset_0_1px_0_color-mix(in_srgb
|
|
8
|
+
return 'bg-surface shadow-[inset_0_1px_0_color-mix(in_srgb,var(--on-solid)_40%,transparent)]';
|
|
9
9
|
}
|
|
10
10
|
if (variant === 'elevated') {
|
|
11
|
-
return 'bg-surface shadow-[
|
|
11
|
+
return 'bg-surface shadow-[var(--shadow-lg)]';
|
|
12
12
|
}
|
|
13
13
|
return 'bg-background-secondary shadow-sm';
|
|
14
14
|
}
|
|
@@ -21,7 +21,7 @@ function getContentDensityClass(density) {
|
|
|
21
21
|
}
|
|
22
22
|
function CardRoot({ className, children, highlight = false, variant = 'default', ...props }) {
|
|
23
23
|
return (_jsx("div", { className: cn('border-app-border rounded-xl border', highlight
|
|
24
|
-
&& 'bg-[linear-gradient(135deg,color-mix(in_srgb,var(--
|
|
24
|
+
&& 'bg-[linear-gradient(135deg,color-mix(in_srgb,var(--surface)_92%,var(--brand)_8%),var(--surface))] shadow-[var(--shadow-md)]', !highlight && getCardVariantClass(variant), className), ...props, children: children }));
|
|
25
25
|
}
|
|
26
26
|
function CardHeader({ className, children, ...props }) {
|
|
27
27
|
return (_jsx("div", { className: cn('border-app-border flex flex-col gap-1 border-b p-4', '[&>h2]:h-auto [&>h2]:rounded-none [&>h2]:border-0 [&>h2]:p-0', className), ...props, children: children }));
|
|
@@ -11,23 +11,23 @@ function resolveVariant(variant) {
|
|
|
11
11
|
const dialogVariantStyles = {
|
|
12
12
|
information: {
|
|
13
13
|
icon: InfoIcon,
|
|
14
|
-
iconClassName: 'text-[
|
|
15
|
-
titleClassName: 'text-[
|
|
14
|
+
iconClassName: 'text-[var(--status-info-icon)]',
|
|
15
|
+
titleClassName: 'text-[var(--status-info-text)]',
|
|
16
16
|
},
|
|
17
17
|
question: {
|
|
18
18
|
icon: HelpCircleIcon,
|
|
19
|
-
iconClassName: 'text-
|
|
20
|
-
titleClassName: 'text-
|
|
19
|
+
iconClassName: 'text-foreground-muted',
|
|
20
|
+
titleClassName: 'text-foreground',
|
|
21
21
|
},
|
|
22
22
|
warning: {
|
|
23
23
|
icon: AlertTriangleIcon,
|
|
24
|
-
iconClassName: 'text-[
|
|
25
|
-
titleClassName: 'text-[
|
|
24
|
+
iconClassName: 'text-[var(--status-warning-icon)]',
|
|
25
|
+
titleClassName: 'text-[var(--status-warning-text)]',
|
|
26
26
|
},
|
|
27
27
|
destructive: {
|
|
28
28
|
icon: AlertCircleIcon,
|
|
29
|
-
iconClassName: 'text-[
|
|
30
|
-
titleClassName: 'text-[
|
|
29
|
+
iconClassName: 'text-[var(--status-danger-icon)]',
|
|
30
|
+
titleClassName: 'text-[var(--status-danger-text)]',
|
|
31
31
|
},
|
|
32
32
|
};
|
|
33
33
|
const buttonVariantDefaults = {
|
|
@@ -37,8 +37,8 @@ const buttonVariantDefaults = {
|
|
|
37
37
|
success: { label: 'Sim', buttonVariant: 'primary' },
|
|
38
38
|
};
|
|
39
39
|
const confirmButtonVariantByDialog = {
|
|
40
|
-
information: '
|
|
41
|
-
question: '
|
|
40
|
+
information: 'secondary',
|
|
41
|
+
question: 'outline',
|
|
42
42
|
warning: 'warning',
|
|
43
43
|
destructive: 'destructive',
|
|
44
44
|
};
|
|
@@ -150,7 +150,7 @@ function Root({ children, className, closeOnEscape = true, onOpenChange, open, o
|
|
|
150
150
|
if (!open) {
|
|
151
151
|
return null;
|
|
152
152
|
}
|
|
153
|
-
return createPortal(_jsx(ConfirmationDialogContext.Provider, { value: value, children: _jsx("div", { className: cn('fixed inset-0 z-[
|
|
153
|
+
return createPortal(_jsx(ConfirmationDialogContext.Provider, { value: value, children: _jsx("div", { className: cn('fixed inset-0 z-[var(--z-critical-dialog)] flex items-center justify-center bg-[var(--overlay-scrim)] p-4 backdrop-blur-[var(--backdrop-blur-sm)]', overlayClassName), role: "presentation", children: _jsxs("section", { "aria-describedby": descriptionId, "aria-labelledby": titleId, "aria-modal": "true", className: cn('border-app-border bg-background-secondary text-foreground relative grid gap-4 rounded-xl border p-6 shadow-[var(--shadow-overlay)]', className), role: "alertdialog", style: { width: 'min(29rem, calc(100vw - 2rem))' }, children: [_jsx("button", { "aria-label": "Fechar", className: cn('text-foreground-muted hover:bg-background hover:text-foreground absolute right-4 top-4 inline-flex size-7 cursor-pointer items-center justify-center rounded-md opacity-60 transition disabled:cursor-not-allowed disabled:opacity-30'), disabled: isBusy, onClick: close, type: "button", children: _jsx(XIcon, { className: "size-3.5" }) }), children] }) }) }), document.body);
|
|
154
154
|
}
|
|
155
155
|
function Icon({ className }) {
|
|
156
156
|
const { variant } = useConfirmationDialog();
|
|
@@ -198,7 +198,7 @@ function Button({ children, closeOnSuccess = true, disabled, label, minWidth = 1
|
|
|
198
198
|
...style,
|
|
199
199
|
...(isFocused
|
|
200
200
|
? {
|
|
201
|
-
boxShadow: '
|
|
201
|
+
boxShadow: 'var(--shadow-warning-focus)',
|
|
202
202
|
}
|
|
203
203
|
: {}),
|
|
204
204
|
}, children: children ?? label ?? defaults.label }));
|
|
@@ -55,6 +55,6 @@ export const CopyableField = React.forwardRef(function CopyableField({ asChild =
|
|
|
55
55
|
}
|
|
56
56
|
}
|
|
57
57
|
return (_jsx(Component, { ref: ref, role: canCopy ? "button" : undefined, tabIndex: canCopy ? 0 : -1, title: canCopy ? title : undefined, "aria-disabled": !canCopy, "aria-label": canCopy && copied ? "Copiado" : undefined, "data-copied": copied ? "true" : undefined, className: cn(canCopy &&
|
|
58
|
-
"group/copyable relative cursor-pointer rounded-md border border-transparent focus-visible:outline-none", className), onClick: handleClick, onKeyDown: handleKeyDown, ...props, children: asChild ? (children) : (_jsxs(_Fragment, { children: [children, canCopy ? (_jsx("span", { "aria-hidden": "true", className: cn("border-app-border bg-[color-mix(in_srgb,var(--foreground-muted)_3%,var(--background-secondary))] text-foreground-muted pointer-events-none absolute top-1/2 right-0 inline-flex size-6 translate-x-[calc(100%+0.25rem)] -translate-y-1/2 items-center justify-center rounded-md border opacity-0 shadow-sm transition-[opacity,color,border-color,background-color] duration-
|
|
58
|
+
"group/copyable relative cursor-pointer rounded-md border border-transparent focus-visible:outline-none", className), onClick: handleClick, onKeyDown: handleKeyDown, ...props, children: asChild ? (children) : (_jsxs(_Fragment, { children: [children, canCopy ? (_jsx("span", { "aria-hidden": "true", className: cn("border-app-border bg-[color-mix(in_srgb,var(--foreground-muted)_3%,var(--background-secondary))] text-foreground-muted pointer-events-none absolute top-1/2 right-0 inline-flex size-6 translate-x-[calc(100%+0.25rem)] -translate-y-1/2 items-center justify-center rounded-md border opacity-0 shadow-sm transition-[opacity,color,border-color,background-color] duration-[var(--duration-fast)] group-hover/copyable:opacity-100 group-focus-visible/copyable:opacity-100", copied &&
|
|
59
59
|
"bg-[color-mix(in_srgb,var(--brand)_9%,var(--background-secondary))] text-brand opacity-100"), children: copied ? (_jsx(ClipboardCheckIcon, { className: "size-3.5" })) : (_jsx(ClipboardIcon, { className: "size-3.5" })) })) : null] })) }));
|
|
60
60
|
});
|
|
@@ -14,6 +14,7 @@ export interface DateFieldProps extends Omit<React.InputHTMLAttributes<HTMLInput
|
|
|
14
14
|
enableTime?: boolean;
|
|
15
15
|
timeIntervals?: number;
|
|
16
16
|
noPortal?: boolean;
|
|
17
|
+
calendarClassName?: string;
|
|
17
18
|
}
|
|
18
19
|
export declare const DateField: React.ForwardRefExoticComponent<DateFieldProps & React.RefAttributes<HTMLInputElement>>;
|
|
19
20
|
//# sourceMappingURL=DateField.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"DateField.d.ts","sourceRoot":"","sources":["../../src/components/DateField.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAY1B,MAAM,MAAM,aAAa,GAAG,MAAM,GAAG,UAAU,GAAG,MAAM,CAAC;AA6FzD,MAAM,WAAW,cAAe,SAAQ,IAAI,CAAC,KAAK,CAAC,mBAAmB,CAAC,gBAAgB,CAAC,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,GAAG,UAAU,CAAC;IAC/H,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,GAAG,IAAI,CAAC;IAC7B,QAAQ,CAAC,EAAE,CAAC,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC,GAAG,KAAK,CAAC,kBAAkB,CAAC,gBAAgB,CAAC,CAAC;IAClF,QAAQ,CAAC,EAAE,KAAK,CAAC,GAAG,CAAC,gBAAgB,CAAC,CAAC;IACvC,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,IAAI,CAAC,EAAE,IAAI,GAAG,IAAI,GAAG,IAAI,CAAC;IAC1B,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,IAAI,CAAC,EAAE,aAAa,CAAC;IACrB,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,EAAE,OAAO,CAAC;
|
|
1
|
+
{"version":3,"file":"DateField.d.ts","sourceRoot":"","sources":["../../src/components/DateField.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAY1B,MAAM,MAAM,aAAa,GAAG,MAAM,GAAG,UAAU,GAAG,MAAM,CAAC;AA6FzD,MAAM,WAAW,cAAe,SAAQ,IAAI,CAAC,KAAK,CAAC,mBAAmB,CAAC,gBAAgB,CAAC,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,GAAG,UAAU,CAAC;IAC/H,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,GAAG,IAAI,CAAC;IAC7B,QAAQ,CAAC,EAAE,CAAC,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC,GAAG,KAAK,CAAC,kBAAkB,CAAC,gBAAgB,CAAC,CAAC;IAClF,QAAQ,CAAC,EAAE,KAAK,CAAC,GAAG,CAAC,gBAAgB,CAAC,CAAC;IACvC,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,IAAI,CAAC,EAAE,IAAI,GAAG,IAAI,GAAG,IAAI,CAAC;IAC1B,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,IAAI,CAAC,EAAE,aAAa,CAAC;IACrB,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,iBAAiB,CAAC,EAAE,MAAM,CAAC;CAC5B;AAED,eAAO,MAAM,SAAS,yFA8IrB,CAAC"}
|
|
@@ -102,7 +102,7 @@ function assignRef(ref, value) {
|
|
|
102
102
|
}
|
|
103
103
|
ref.current = value;
|
|
104
104
|
}
|
|
105
|
-
export const DateField = React.forwardRef(({ label, onChange, onBlur, inputRef, disabled, errorMessage, id, className, wrapperClassName, labelClassName, size = 'sm', roundedFull = false, noPortal = false, mode, enableTime = false, timeIntervals = 5, value, name, placeholder, min, max, autoComplete = 'off', autoFocus, }, ref) => {
|
|
105
|
+
export const DateField = React.forwardRef(({ label, onChange, onBlur, inputRef, disabled, errorMessage, id, className, wrapperClassName, labelClassName, size = 'sm', roundedFull = false, noPortal = false, calendarClassName, mode, enableTime = false, timeIntervals = 5, value, name, placeholder, min, max, autoComplete = 'off', autoFocus, }, ref) => {
|
|
106
106
|
const sizeMap = {
|
|
107
107
|
sm: 'h-9 text-sm px-3 rounded-md',
|
|
108
108
|
md: 'h-12 text-sm px-4 rounded-md',
|
|
@@ -163,7 +163,7 @@ export const DateField = React.forwardRef(({ label, onChange, onBlur, inputRef,
|
|
|
163
163
|
? { showTimeSelect: true, showTimeSelectOnly: true, timeIntervals, dateFormat: 'HH:mm', timeFormat: 'HH:mm', timeCaption: 'Hora' }
|
|
164
164
|
: isDateTime
|
|
165
165
|
? { showTimeSelect: true, timeIntervals, dateFormat: 'dd/MM/yyyy HH:mm', timeFormat: 'HH:mm', timeCaption: 'Hora' }
|
|
166
|
-
: { dateFormat: 'dd/MM/yyyy', minDate: toOptionalDate(min), maxDate: toOptionalDate(max) }), locale: "pt-BR", placeholderText: placeholder ?? label, disabled: controlDisabled, showPopperArrow: false, popperClassName: "app-datepicker-popper", calendarClassName:
|
|
166
|
+
: { dateFormat: 'dd/MM/yyyy', minDate: toOptionalDate(min), maxDate: toOptionalDate(max) }), locale: "pt-BR", placeholderText: placeholder ?? label, disabled: controlDisabled, showPopperArrow: false, popperClassName: "app-datepicker-popper", calendarClassName: cn('app-datepicker', calendarClassName), wrapperClassName: "w-full", formatWeekDay: (day) => day.slice(0, 3), ariaDescribedBy: describedBy, ariaInvalid: controlError ? 'true' : undefined, autoComplete: autoComplete, autoFocus: autoFocus, className: controlClasses({
|
|
167
167
|
errorMessage: controlError,
|
|
168
168
|
disabled: controlDisabled,
|
|
169
169
|
extra: cn(className, 'w-full cursor-pointer pr-10', sizeClass),
|
|
@@ -12,7 +12,7 @@ export const FieldControl = ({ label, id, wrapperClassName, labelClassName = '',
|
|
|
12
12
|
const roundedClass = roundedFull ? 'fc-rounded-full' : '';
|
|
13
13
|
const isHorizontal = labelPosition === 'left' || labelPosition === 'right';
|
|
14
14
|
const labelSizeClassMap = {
|
|
15
|
-
xs: 'text-[
|
|
15
|
+
xs: 'text-[length:var(--font-size-2xs)]',
|
|
16
16
|
sm: 'text-xs',
|
|
17
17
|
md: 'text-sm',
|
|
18
18
|
lg: 'text-base',
|
|
@@ -64,7 +64,7 @@ export const FieldControl = ({ label, id, wrapperClassName, labelClassName = '',
|
|
|
64
64
|
.dark .${scopeClass} textarea::-webkit-input-placeholder { color: var(--muted-foreground); opacity: 0.50; }
|
|
65
65
|
.${roundedClass} input,
|
|
66
66
|
.${roundedClass} textarea,
|
|
67
|
-
.${roundedClass} select { border-radius:
|
|
67
|
+
.${roundedClass} select { border-radius: var(--radius-full); padding: var(--space-1-5) var(--space-4); min-height: var(--space-8); }
|
|
68
68
|
.${roundedClass} input::placeholder,
|
|
69
69
|
.${roundedClass} textarea::placeholder,
|
|
70
70
|
.${roundedClass} select::placeholder { opacity: 0.5; }
|
|
@@ -3,5 +3,5 @@ import { cn } from '../utils/cn';
|
|
|
3
3
|
export function FieldValidationError({ id, message, hasValidation = false }) {
|
|
4
4
|
if (!hasValidation && !message)
|
|
5
5
|
return null;
|
|
6
|
-
return (_jsx("p", { id: id, className: cn('mt-px text-left text-[
|
|
6
|
+
return (_jsx("p", { id: id, className: cn('mt-px text-left text-[length:var(--font-size-2xs)] leading-[var(--line-height-2xs)] transition-opacity duration-[var(--duration-normal)] select-none', hasValidation ? 'min-h-[14px]' : 'min-h-0', message ? 'text-red-600 opacity-100 dark:text-red-400' : 'opacity-0'), "aria-live": "polite", "aria-atomic": "true", role: message ? 'alert' : undefined, children: message ?? '' }));
|
|
7
7
|
}
|
|
@@ -4,5 +4,5 @@ import { cn } from '../utils/cn';
|
|
|
4
4
|
export function LoadingOverlay({ open = false, variant = 'solid', size = 'lg', label = 'Carregando', className, }) {
|
|
5
5
|
if (!open)
|
|
6
6
|
return null;
|
|
7
|
-
return (_jsx("div", { className: cn('fixed inset-0 z-[
|
|
7
|
+
return (_jsx("div", { className: cn('fixed inset-0 z-[var(--z-loading-overlay)] flex items-center justify-center', variant === 'solid' ? 'bg-background' : 'bg-[var(--overlay-loading)] backdrop-blur-[var(--backdrop-blur-md)]', className), role: "status", "aria-label": label, "aria-live": "polite", children: _jsx(Loading, { size: size, "aria-label": label }) }));
|
|
8
8
|
}
|
package/dist/components/Modal.js
CHANGED
|
@@ -73,11 +73,11 @@ function ModalRoot({ allowExternalFocus = false, centered = false, children, cla
|
|
|
73
73
|
onOpenChange?.(nextOpen);
|
|
74
74
|
}
|
|
75
75
|
const hasFooter = React.Children.toArray(children).some((child) => React.isValidElement(child) && child.type === ModalFooter);
|
|
76
|
-
return (_jsx(DialogPrimitive.Root, { ...props, modal: !allowExternalFocus, open: open, onOpenChange: handleOpenChange, children: _jsxs(DialogPrimitive.Portal, { children: [_jsx(DialogPrimitive.Overlay, { style: { zIndex: overlayZIndex }, className: cn('fixed inset-0 z-[
|
|
76
|
+
return (_jsx(DialogPrimitive.Root, { ...props, modal: !allowExternalFocus, open: open, onOpenChange: handleOpenChange, children: _jsxs(DialogPrimitive.Portal, { children: [_jsx(DialogPrimitive.Overlay, { style: { zIndex: overlayZIndex }, className: cn('fixed inset-0 z-[var(--z-modal-overlay)] bg-[var(--overlay-scrim)] backdrop-blur-[var(--backdrop-blur-sm)]', allowExternalFocus && 'pointer-events-none', overlayClassName) }), _jsxs(DialogPrimitive.Content, { style: {
|
|
77
77
|
zIndex: contentZIndex,
|
|
78
78
|
width: widthVariants[size],
|
|
79
79
|
...(!centered && offset ? { top: `${offset}px` } : {}),
|
|
80
|
-
}, className: cn('fixed z-[
|
|
80
|
+
}, className: cn('fixed z-[var(--z-modal)] grid max-h-[95vh]', hasFooter ? 'grid-rows-[auto_minmax(0,1fr)_auto]' : 'grid-rows-[auto_minmax(0,1fr)]', 'rounded-xl', density === 'default' && 'p-6', density === 'compact' && 'p-4', variant === 'default' && 'border-app-border bg-background-secondary text-foreground border shadow-[var(--shadow-lg)]', variant === 'elevated' && 'border-app-border bg-surface text-foreground border shadow-[var(--shadow-overlay)]', centered ? 'left-[50%] top-[50%] -translate-x-1/2 -translate-y-1/2' : 'left-[50%] top-[2.5%] -translate-x-1/2', sizeVariants[size], minHeightVariants[size], className), children: [children, showCloseButton ? (_jsxs(DialogPrimitive.Close, { className: cn('absolute right-4 top-4 inline-flex h-8 w-8 items-center justify-center rounded-md', 'text-foreground-muted hover:bg-background hover:text-foreground cursor-pointer transition-colors', 'focus:ring-brand/50 focus:ring-2 focus:ring-offset-2 focus:outline-none disabled:pointer-events-none'), children: [_jsx(XIcon, { className: "size-4" }), _jsx("span", { className: "sr-only", children: "Fechar" })] })) : null] })] }) }));
|
|
81
81
|
}
|
|
82
82
|
function ModalHeader({ className, density = 'default', separated = false, ...props }) {
|
|
83
83
|
return (_jsx("div", { "data-slot": "modal-header", className: cn('flex flex-col text-center sm:text-left', density === 'default' && 'gap-1.5 [&_[data-slot=modal-description]]:text-sm [&_[data-slot=modal-title]]:text-lg', density === 'compact' && 'gap-0.5 [&_[data-slot=modal-description]]:text-xs [&_[data-slot=modal-title]]:text-base', separated && density === 'default' && 'border-app-border border-b pb-4', separated && density === 'compact' && 'border-app-border border-b pb-2', className), ...props }));
|
|
@@ -19,7 +19,7 @@ function OptionListItem({ option, isSelected, isDisabledByMax, onToggle, }) {
|
|
|
19
19
|
return;
|
|
20
20
|
onToggle(option.value);
|
|
21
21
|
}
|
|
22
|
-
return (_jsxs("li", { role: "option", "aria-selected": isSelected, className: cn('hover:bg-background flex cursor-pointer items-center gap-2 px-3 py-2 text-sm transition-colors', disabled && 'cursor-not-allowed opacity-50'), onClick: handleClick, children: [_jsx("span", { className: cn('border-app-border flex size-4 shrink-0 items-center justify-center rounded border', isSelected && 'bg-brand border-brand'), children: _jsx(RenderIf, { when: isSelected, children: _jsx(Check, { className: "size-3 text-
|
|
22
|
+
return (_jsxs("li", { role: "option", "aria-selected": isSelected, className: cn('hover:bg-background flex cursor-pointer items-center gap-2 px-3 py-2 text-sm transition-colors', disabled && 'cursor-not-allowed opacity-50'), onClick: handleClick, children: [_jsx("span", { className: cn('border-app-border flex size-4 shrink-0 items-center justify-center rounded border', isSelected && 'bg-brand border-brand'), children: _jsx(RenderIf, { when: isSelected, children: _jsx(Check, { className: "size-3 text-[var(--on-solid)]" }) }) }), option.label] }));
|
|
23
23
|
}
|
|
24
24
|
export function MultiSelectField({ label, value, options, onChange, placeholder = 'Selecione...', errorMessage, disabled = false, maxSelected, wrapperClassName, size = 'sm', labelPosition = 'top', }) {
|
|
25
25
|
const [open, setOpen] = useState(false);
|
|
@@ -73,8 +73,8 @@ export function MultiSelectField({ label, value, options, onChange, placeholder
|
|
|
73
73
|
md: 'min-h-12 text-sm px-4',
|
|
74
74
|
lg: 'min-h-14 text-base px-6',
|
|
75
75
|
};
|
|
76
|
-
const triggerClass = cn('bg-surface border-app-border text-foreground w-full rounded-md border transition-colors duration-
|
|
77
|
-
const dropdownClass = cn('bg-surface border-app-border text-foreground absolute left-0 z-
|
|
76
|
+
const triggerClass = cn('bg-surface border-app-border text-foreground w-full rounded-md border transition-colors duration-[var(--duration-normal)]', 'relative flex cursor-pointer select-none flex-wrap items-center gap-1 py-1.5 pr-8', sizeClassMap[size], !disabled && 'hover:border-brand focus:outline-none focus:ring-2 focus:ring-brand/50', errorMessage && 'border-red-500 focus:ring-red-200', disabled && 'bg-input-bg cursor-not-allowed opacity-60');
|
|
77
|
+
const dropdownClass = cn('bg-surface border-app-border text-foreground absolute left-0 z-[var(--z-popover)] w-full rounded-md border shadow-[var(--shadow-md)]', direction === 'down' ? 'top-full mt-1' : 'bottom-full mb-1');
|
|
78
78
|
const selectedOptions = options.filter((option) => value.includes(option.value));
|
|
79
79
|
return (_jsx(FieldControl, { label: label, wrapperClassName: wrapperClassName, errorMessage: errorMessage, disabled: disabled, size: size, labelPosition: labelPosition, children: _jsxs("div", { ref: containerRef, className: "relative", children: [_jsxs("div", { role: "combobox", "aria-expanded": open, "aria-haspopup": "listbox", tabIndex: disabled ? -1 : 0, className: triggerClass, onClick: handleOpen, onKeyDown: handleComboboxKeyDown, children: [_jsxs(RenderCase.Root, { children: [_jsx(RenderCase.If, { when: selectedOptions.length === 0, children: _jsx("span", { className: "text-foreground-muted/50 text-sm", children: placeholder }) }), _jsx(RenderCase.Else, { children: selectedOptions.map((option) => (_jsx(ChipItem, { option: option, disabled: disabled, onRemove: handleRemoveChip }, String(option.value)))) })] }), _jsx("div", { className: "pointer-events-none absolute top-1/2 right-3 -translate-y-1/2", children: _jsx(ChevronDown, { className: cn('text-foreground-muted/90 size-4 transition-transform', open && 'rotate-180') }) })] }), _jsx(RenderIf, { when: open, children: _jsx("div", { className: dropdownClass, children: _jsx("ul", { role: "listbox", "aria-multiselectable": "true", className: "max-h-52 overflow-y-auto py-1", children: options.map((option) => {
|
|
80
80
|
const isSelected = value.includes(option.value);
|
|
@@ -8,6 +8,6 @@ import { cn } from '../utils/cn';
|
|
|
8
8
|
* itens de listas navegaveis e acessos rapidos.
|
|
9
9
|
*/
|
|
10
10
|
export const NavCard = forwardRef(({ className, description, hideArrow = false, icon, title, type = 'button', ...props }, ref) => {
|
|
11
|
-
return (_jsxs("button", { ref: ref, type: type, className: cn('group border-app-border bg-surface flex w-full cursor-pointer items-center gap-3 rounded-lg border px-3 py-3 text-left transition-[background-color,border-color,box-shadow]', 'hover:border-[color-mix(in_srgb,var(--brand)_44%,var(--app-border))] hover:bg-[color-mix(in_srgb,var(--brand)_7%,var(--surface))] hover:shadow-[
|
|
11
|
+
return (_jsxs("button", { ref: ref, type: type, className: cn('group border-app-border bg-surface flex w-full cursor-pointer items-center gap-3 rounded-lg border px-3 py-3 text-left transition-[background-color,border-color,box-shadow]', 'hover:border-[color-mix(in_srgb,var(--brand)_44%,var(--app-border))] hover:bg-[color-mix(in_srgb,var(--brand)_7%,var(--surface))] hover:shadow-[var(--shadow-action)]', 'focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-[color-mix(in_srgb,var(--brand)_36%,transparent)] focus-visible:outline-none', className), ...props, children: [icon && (_jsx("span", { className: "text-[color-mix(in_srgb,var(--brand)_68%,var(--foreground-muted))] group-hover:text-brand inline-flex shrink-0 items-center justify-center transition-colors [&_svg]:size-5", children: icon })), _jsxs("span", { className: "flex min-w-0 flex-1 flex-col gap-0.5", children: [_jsx("span", { className: "text-foreground line-clamp-2 text-sm leading-snug font-medium", children: title }), description && (_jsx("span", { className: "text-foreground-muted truncate text-xs", children: description }))] }), !hideArrow && (_jsx(ArrowRightIcon, { "aria-hidden": "true", className: "text-foreground-muted/50 group-hover:text-brand size-4 shrink-0 transition-transform duration-[var(--duration-fast)] group-hover:translate-x-0.5" }))] }));
|
|
12
12
|
});
|
|
13
13
|
NavCard.displayName = 'NavCard';
|
package/dist/components/Page.js
CHANGED
|
@@ -258,7 +258,7 @@ function Actions({ align = 'start', __fromSlot = false, children, className, def
|
|
|
258
258
|
const verticalMetaJustification = getVerticalMetaJustification(effectivePosition);
|
|
259
259
|
const helpButton = helpVisible ? (_jsx("div", { className: cn('flex shrink-0', isVertical && 'w-full', isVertical && verticalMetaJustification), children: _jsx(Tooltip, { className: cn('max-w-[22rem] px-3 py-2', helpClassName), content: helpContent, delayDuration: 120, openOnClick: true, side: getHelpSide(effectivePosition), children: _jsx(ActionButtonPrimitive, { "aria-label": helpLabel, icon: _jsx(CircleHelpIcon, { "aria-hidden": "true" }), tooltip: helpLabel }) }) })) : null;
|
|
260
260
|
const labelToggleButton = canToggleLabels ? (_jsx(ActionButtonPrimitive, { "aria-pressed": effectiveShowLabels, "aria-label": effectiveShowLabels ? 'Ocultar labels das acoes' : 'Mostrar labels das acoes', icon: effectiveShowLabels ? _jsx(CaptionsOffIcon, { "aria-hidden": "true" }) : _jsx(CaptionsIcon, { "aria-hidden": "true" }), tooltip: effectiveShowLabels ? 'Ocultar labels das acoes' : 'Mostrar labels das acoes', onClick: handleToggleLabels })) : null;
|
|
261
|
-
const moveButton = canMove ? (_jsxs("div", { className: cn('relative flex shrink-0', isVertical && 'w-full', isVertical && verticalMetaJustification), children: [_jsx(ActionButtonPrimitive, { "aria-haspopup": "menu", "aria-label": "Mover barra de acoes", "aria-expanded": isMenuOpen, className: cn('touch-none [&]:cursor-grab [&_*]:cursor-grab active:[&]:cursor-grabbing active:[&_*]:cursor-grabbing', isDragging && '[&]:cursor-grabbing [&_*]:cursor-grabbing'), icon: _jsx(GripVerticalIcon, { "aria-hidden": "true" }), tooltip: "Mover barra de acoes", onClick: handleMoveMenuToggle, onKeyDown: handleMoveKeyDown, onPointerCancel: handleMovePointerCancel, onPointerDown: handleMovePointerDown, onPointerMove: handleMovePointerMove, onPointerUp: handleMovePointerUp }), isMenuOpen ? (_jsx("div", { role: "menu", className: cn('border-app-border bg-surface text-foreground absolute z-
|
|
261
|
+
const moveButton = canMove ? (_jsxs("div", { className: cn('relative flex shrink-0', isVertical && 'w-full', isVertical && verticalMetaJustification), children: [_jsx(ActionButtonPrimitive, { "aria-haspopup": "menu", "aria-label": "Mover barra de acoes", "aria-expanded": isMenuOpen, className: cn('touch-none [&]:cursor-grab [&_*]:cursor-grab active:[&]:cursor-grabbing active:[&_*]:cursor-grabbing', isDragging && '[&]:cursor-grabbing [&_*]:cursor-grabbing'), icon: _jsx(GripVerticalIcon, { "aria-hidden": "true" }), tooltip: "Mover barra de acoes", onClick: handleMoveMenuToggle, onKeyDown: handleMoveKeyDown, onPointerCancel: handleMovePointerCancel, onPointerDown: handleMovePointerDown, onPointerMove: handleMovePointerMove, onPointerUp: handleMovePointerUp }), isMenuOpen ? (_jsx("div", { role: "menu", className: cn('border-app-border bg-surface text-foreground absolute z-[var(--z-popover)] min-w-36 rounded-md border p-1 text-xs shadow-[var(--shadow-md)]', isVertical && effectivePosition === 'left' && 'left-full top-0 ml-2', isVertical && effectivePosition === 'right' && 'right-full top-0 mr-2', !isVertical && 'right-0 top-full mt-2'), children: effectiveAllowedPositions.map((nextPosition) => (_jsx(PageActionsMoveOption, { active: nextPosition === effectivePosition, label: positionLabels[nextPosition], onSelect: handleSelectPosition, position: nextPosition }, nextPosition))) })) : null] })) : null;
|
|
262
262
|
const actions = (_jsxs("div", { className: cn('flex min-h-0 min-w-0 gap-2', isVertical ? 'h-full w-full flex-col' : 'w-full items-center'), children: [_jsx(PageActionsRenderContext.Provider, { value: { showLabels: effectiveShowLabels }, children: _jsx(ActionGroupPrimitive, { align: align, size: size, className: cn('min-w-0 flex-1', isVertical
|
|
263
263
|
? cn('min-h-0 flex-col content-start [&>[data-action-separator=true]]:h-px [&>[data-action-separator=true]]:min-h-0 [&>[data-action-separator=true]]:w-full [&>[data-action-separator=true]]:self-auto', effectiveShowLabels
|
|
264
264
|
? 'w-full items-stretch [&>button]:w-full [&>button]:justify-start [&>div]:w-full [&>div>button]:w-full [&>div>button]:justify-start'
|
|
@@ -267,7 +267,7 @@ function Actions({ align = 'start', __fromSlot = false, children, className, def
|
|
|
267
267
|
return (_jsxs("div", { className: cn('flex min-w-0', positionClasses[effectivePosition], isVertical ? 'flex-col' : 'items-center', className), children: [actions, isDragging ? _jsx(PageActionsDropZones, { activePosition: dragTarget ?? effectivePosition, allowedPositions: effectiveAllowedPositions }) : null] }));
|
|
268
268
|
}
|
|
269
269
|
function PageActionsDropZones({ activePosition, allowedPositions }) {
|
|
270
|
-
return (_jsx("div", { "aria-hidden": "true", className: "pointer-events-none absolute inset-0 z-
|
|
270
|
+
return (_jsx("div", { "aria-hidden": "true", className: "pointer-events-none absolute inset-0 z-[var(--z-popover)]", children: allPositions.map((position) => {
|
|
271
271
|
if (!allowedPositions.includes(position))
|
|
272
272
|
return null;
|
|
273
273
|
return (_jsx("div", { className: cn('absolute border-2 border-dashed border-brand/50 bg-brand/10 transition-colors', position === 'left' && 'left-2 top-2 h-[calc(100%-1rem)] w-20 rounded-md', position === 'right' && 'right-2 top-2 h-[calc(100%-1rem)] w-20 rounded-md', position === 'top' && 'left-2 top-2 h-14 w-[calc(100%-1rem)] rounded-md', position === 'bottom' && 'bottom-2 left-2 h-14 w-[calc(100%-1rem)] rounded-md', activePosition === position && 'border-brand bg-brand/20 shadow-[0_0_0_4px_color-mix(in_srgb,var(--brand)_18%,transparent)]') }, position));
|
|
@@ -324,14 +324,14 @@ function ActionsSlot({ className, position }) {
|
|
|
324
324
|
return (_jsx("div", { className: cn('flex min-w-0 flex-none', (position === 'top' || position === 'bottom') && 'w-full', (position === 'left' || position === 'right') && 'min-h-0 self-stretch', className), children: cloneElement(actions, { __fromSlot: true }) }));
|
|
325
325
|
}
|
|
326
326
|
function Title({ children, className, ...props }) {
|
|
327
|
-
return (_jsx("h1", { className: cn('text-xl font-semibold tracking-[-
|
|
327
|
+
return (_jsx("h1", { className: cn('text-xl font-semibold tracking-[var(--letter-spacing-tight)] text-foreground', className), ...props, children: children }));
|
|
328
328
|
}
|
|
329
329
|
function Description({ children, className, ...props }) {
|
|
330
330
|
return (_jsx("p", { className: cn('text-sm leading-6 text-foreground-muted', className), ...props, children: children }));
|
|
331
331
|
}
|
|
332
332
|
function Header({ actions, description, eyebrow, title }) {
|
|
333
333
|
const hasLeft = eyebrow || title || description;
|
|
334
|
-
return (_jsxs("div", { className: "mb-3 flex items-start justify-between gap-3", children: [hasLeft && (_jsxs("div", { children: [eyebrow && _jsx("span", { className: "text-xs font-semibold uppercase tracking-[
|
|
334
|
+
return (_jsxs("div", { className: "mb-3 flex items-start justify-between gap-3", children: [hasLeft && (_jsxs("div", { children: [eyebrow && _jsx("span", { className: "text-xs font-semibold uppercase tracking-[var(--letter-spacing-caps)] text-foreground-muted", children: eyebrow }), title && _jsx(Title, { children: title }), description && _jsx(Description, { children: description })] })), actions && _jsx("div", { className: "flex min-w-0 justify-end", children: actions })] }));
|
|
335
335
|
}
|
|
336
336
|
export const Page = {
|
|
337
337
|
Root,
|