@aurea-uds/react 0.30.0 → 0.32.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +26 -0
- package/dist/actions.d.ts +33 -6
- package/dist/actions.js +38 -26
- package/dist/agents.js +1 -1
- package/dist/calendar.d.ts +38 -1
- package/dist/calendar.js +115 -2
- package/dist/code-client.d.ts +3 -1
- package/dist/code-client.js +23 -1
- package/dist/color.d.ts +92 -0
- package/dist/color.js +293 -0
- package/dist/disclosure.d.ts +19 -9
- package/dist/disclosure.js +8 -1
- package/dist/feedback-client.d.ts +11 -5
- package/dist/feedback-client.js +26 -15
- package/dist/graph-geometria.d.ts +84 -0
- package/dist/graph-geometria.js +437 -0
- package/dist/graph-worker.d.ts +1 -0
- package/dist/graph-worker.js +17 -0
- package/dist/graph.d.ts +72 -4
- package/dist/graph.js +1059 -166
- package/dist/icon-names.d.ts +7 -1
- package/dist/icon-names.js +2 -0
- package/dist/index.d.ts +1 -1
- package/dist/index.js +1 -1
- package/dist/inputs-client.d.ts +215 -2
- package/dist/inputs-client.js +504 -8
- package/dist/inputs.d.ts +1 -1
- package/dist/internal.d.ts +1 -0
- package/dist/internal.js +4 -0
- package/dist/layout-client.d.ts +14 -2
- package/dist/layout-client.js +2 -2
- package/dist/markup.d.ts +89 -9
- package/dist/markup.js +48 -11
- package/dist/navigation-client.d.ts +31 -7
- package/dist/navigation-client.js +60 -16
- package/dist/overlays.d.ts +20 -6
- package/dist/overlays.js +65 -10
- package/dist/pure.d.ts +42 -0
- package/dist/pure.js +2 -2
- package/dist/system.d.ts +5 -2
- package/dist/system.js +17 -9
- package/package.json +13 -3
package/dist/layout-client.js
CHANGED
|
@@ -146,7 +146,7 @@ function useLargura(query) {
|
|
|
146
146
|
return () => mq.removeEventListener?.("change", avisar);
|
|
147
147
|
}, () => typeof window !== "undefined" && typeof window.matchMedia === "function" && window.matchMedia(query).matches, () => false);
|
|
148
148
|
}
|
|
149
|
-
export function AppShell({ brand, navigation, navItems, currentNavId, navLabel, topbar, topbarVariant = "floating", topbarDivider, sidebarVariant, sidebarCollapsed, sidebarCollapsible, defaultSidebarCollapsed, onSidebarCollapsedChange, contentVariant = "surface", children, className, ...props }) {
|
|
149
|
+
export function AppShell({ brand, navigation, navItems, currentNavId, navLabel, topbar, topbarVariant = "floating", topbarDivider, sidebarVariant, sidebarScrollbar, sidebarCollapsed, sidebarCollapsible, defaultSidebarCollapsed, onSidebarCollapsedChange, contentVariant = "surface", aside, asideLabel, asideVariant, children, className, ...props }) {
|
|
150
150
|
const s = useAureaStrings();
|
|
151
151
|
useGavetaFechaNoDesktop();
|
|
152
152
|
const controlado = sidebarCollapsed !== undefined;
|
|
@@ -180,7 +180,7 @@ export function AppShell({ brand, navigation, navItems, currentNavId, navLabel,
|
|
|
180
180
|
// A condição vai escrita no `icon=` do botão, e não numa variável: é ali que o check 46 lê os
|
|
181
181
|
// ícones que o shell desenha.
|
|
182
182
|
const paraOComeco = !efetiva, direita = useDirection() === "rtl";
|
|
183
|
-
return _jsxs("div", { className: cx("app-shell", topbarVariant === "flush" && "app-shell-flush", sidebarCollapsible && "app-shell-collapsible", className), ...props, children: [_jsx("a", { className: "skip-link", href: `#${SHELL_MAIN_ID}`, children: s.skipToContent }), _jsx(Header, { variant: topbarVariant, divider: topbarDivider, brand: _jsxs(_Fragment, { children: [_jsx(IconButton, { className: "nav-toggle", icon: "list", label: s.navigationToggle, popoverTarget: SHELL_NAV_ID }), brand] }), children: topbar }), sidebarCollapsible && _jsx("div", { className: "sidebar-toggle-slot", children: _jsx(Tooltip, { content: rotulo, side: "right", children: _jsx(IconButton, { className: "sidebar-toggle", size: "xs", icon: paraOComeco === direita ? "caret-right" : "caret-left", label: rotulo, "aria-expanded": !efetiva, "aria-controls": SHELL_NAV_ID, onClick: alternar }) }) }), _jsx(Sidebar, { id: SHELL_NAV_ID, popover: "auto", variant: sidebarVariant, collapsed: efetiva, items: navItems, current: currentNavId, label: navLabel, onToggle: focoDaGaveta, children: navigation }), _jsx("main", { id: SHELL_MAIN_ID, tabIndex: -1, className: cx("content", contentVariant === "plain" && "content-plain"), children: children })] });
|
|
183
|
+
return _jsxs("div", { className: cx("app-shell", topbarVariant === "flush" && "app-shell-flush", sidebarCollapsible && "app-shell-collapsible", aside != null && "app-shell-with-aside", className), ...props, children: [_jsx("a", { className: "skip-link", href: `#${SHELL_MAIN_ID}`, children: s.skipToContent }), _jsx(Header, { variant: topbarVariant, divider: topbarDivider, brand: _jsxs(_Fragment, { children: [_jsx(IconButton, { className: "nav-toggle", icon: "list", label: s.navigationToggle, popoverTarget: SHELL_NAV_ID }), brand] }), children: topbar }), sidebarCollapsible && _jsx("div", { className: "sidebar-toggle-slot", children: _jsx(Tooltip, { content: rotulo, side: "right", children: _jsx(IconButton, { className: "sidebar-toggle", size: "xs", icon: paraOComeco === direita ? "caret-right" : "caret-left", label: rotulo, "aria-expanded": !efetiva, "aria-controls": SHELL_NAV_ID, onClick: alternar }) }) }), _jsx(Sidebar, { id: SHELL_NAV_ID, popover: "auto", variant: sidebarVariant, scrollbar: sidebarScrollbar, collapsed: efetiva, items: navItems, current: currentNavId, label: navLabel, onToggle: focoDaGaveta, children: navigation }), _jsx("main", { id: SHELL_MAIN_ID, tabIndex: -1, className: cx("content", contentVariant === "plain" && "content-plain"), children: children }), aside != null && _jsx(Sidebar, { placement: "right", variant: asideVariant ?? sidebarVariant, className: "app-shell-aside", "aria-label": asideLabel ?? s.tocLabel, children: aside })] });
|
|
184
184
|
}
|
|
185
185
|
export function Separator({ orientation, spacing = "none", className, ...props }) {
|
|
186
186
|
const ancora = useRef(null);
|
package/dist/markup.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import React, { type HTMLAttributes, type InputHTMLAttributes, type ReactElement, type ReactNode, type RefAttributes, type TextareaHTMLAttributes } from "react";
|
|
1
|
+
import React, { type AnchorHTMLAttributes, type HTMLAttributes, type InputHTMLAttributes, type ReactElement, type ReactNode, type RefAttributes, type TextareaHTMLAttributes } from "react";
|
|
2
2
|
import { type Responsive } from "./pure.js";
|
|
3
3
|
import type { ComponentSize } from "./actions.js";
|
|
4
4
|
import type { SidebarItem } from "./navigation-client.js";
|
|
@@ -15,7 +15,7 @@ type CardBase = HTMLAttributes<HTMLDivElement> & RefAttributes<HTMLDivElement> &
|
|
|
15
15
|
accent?: CardAccent;
|
|
16
16
|
};
|
|
17
17
|
export type CardProps = CardBase & ({
|
|
18
|
-
variant?: "base" | "raised" | "inset" | "selected" | "danger" | "contrast";
|
|
18
|
+
variant?: "base" | "raised" | "inset" | "outline" | "selected" | "danger" | "contrast";
|
|
19
19
|
render?: ReactElement;
|
|
20
20
|
} | {
|
|
21
21
|
variant: "interactive";
|
|
@@ -182,9 +182,14 @@ export type TypographyWeight = "normal" | "medium" | "semibold" | "bold" | "extr
|
|
|
182
182
|
export type TypographyAlign = "start" | "center" | "end" | "justify";
|
|
183
183
|
export type HeadingLevel = 1 | 2 | 3 | 4 | 5 | 6;
|
|
184
184
|
export type ParagraphSize = "base" | "sm" | "xs";
|
|
185
|
+
/** A cor do texto com o NOME do nativo (DOC-11, os mesmos nomes na web e no nativo). `link` é o amarelo
|
|
186
|
+
* de ESCREVER (legível nos dois temas); `primary` é o de PREENCHER, e no tema claro quase some — como no
|
|
187
|
+
* nativo. As cores de estado são o par `-400` (ADR-0061). Vence o `color` quando os dois vêm. */
|
|
188
|
+
export type TypographyTone = "default" | "muted" | "subtle" | "primary" | "link" | "danger" | "success" | "warning" | "info";
|
|
185
189
|
interface TypographyBase {
|
|
186
190
|
align?: TypographyAlign;
|
|
187
191
|
color?: TypographyColor;
|
|
192
|
+
tone?: TypographyTone;
|
|
188
193
|
weight?: TypographyWeight;
|
|
189
194
|
truncate?: boolean;
|
|
190
195
|
/** GAR-16 (0.28.0): algarismos da mesma largura — para número que alinha em coluna (preço, ano,
|
|
@@ -194,18 +199,18 @@ interface TypographyBase {
|
|
|
194
199
|
export interface TextProps extends Omit<HTMLAttributes<HTMLSpanElement>, "color">, RefAttributes<HTMLSpanElement>, TypographyBase {
|
|
195
200
|
type?: TypographyType;
|
|
196
201
|
}
|
|
197
|
-
export declare function Text({ type, align, color, weight, truncate, numeric, className, ...props }: TextProps): React.JSX.Element;
|
|
202
|
+
export declare function Text({ type, align, color, tone, weight, truncate, numeric, className, ...props }: TextProps): React.JSX.Element;
|
|
198
203
|
export interface HeadingProps extends Omit<HTMLAttributes<HTMLHeadingElement>, "color">, RefAttributes<HTMLHeadingElement>, TypographyBase {
|
|
199
204
|
level?: HeadingLevel;
|
|
200
205
|
}
|
|
201
|
-
export declare function Heading({ level, align, color, weight, truncate, numeric, className, ...props }: HeadingProps): React.JSX.Element;
|
|
206
|
+
export declare function Heading({ level, align, color, tone, weight, truncate, numeric, className, ...props }: HeadingProps): React.JSX.Element;
|
|
202
207
|
export interface ParagraphProps extends Omit<HTMLAttributes<HTMLParagraphElement>, "color">, RefAttributes<HTMLParagraphElement>, TypographyBase {
|
|
203
208
|
size?: ParagraphSize;
|
|
204
209
|
}
|
|
205
|
-
export declare function Paragraph({ size, align, color, weight, truncate, numeric, className, ...props }: ParagraphProps): React.JSX.Element;
|
|
210
|
+
export declare function Paragraph({ size, align, color, tone, weight, truncate, numeric, className, ...props }: ParagraphProps): React.JSX.Element;
|
|
206
211
|
export interface CodeProps extends Omit<HTMLAttributes<HTMLElement>, "color">, RefAttributes<HTMLElement>, TypographyBase {
|
|
207
212
|
}
|
|
208
|
-
export declare function Code({ align, color, weight, truncate, className, ...props }: CodeProps): React.JSX.Element;
|
|
213
|
+
export declare function Code({ align, color, tone, weight, truncate, className, ...props }: CodeProps): React.JSX.Element;
|
|
209
214
|
export type BadgeEmphasis = "soft" | "solid" | "outline";
|
|
210
215
|
export type BadgeSize = "xs" | "sm" | "md" | "lg";
|
|
211
216
|
export type BadgePlacement = "top-end" | "top-start" | "bottom-end" | "bottom-start";
|
|
@@ -213,6 +218,9 @@ export type BadgeFit = "auto" | "content";
|
|
|
213
218
|
export declare function formatBadgeCount(count: number, max?: number): string;
|
|
214
219
|
export interface BadgeProps extends HTMLAttributes<HTMLSpanElement>, RefAttributes<HTMLSpanElement> {
|
|
215
220
|
variant?: BadgeVariant;
|
|
221
|
+
/** A cor, com o NOME do nativo (DOC-11, 0.32.0: os mesmos nomes na web e no nativo). É o mesmo
|
|
222
|
+
* eixo do `variant`, e vence quando os dois vêm. */
|
|
223
|
+
tone?: BadgeVariant;
|
|
216
224
|
/** `soft` é o tom de sempre; `solid` preenche com o acento; `outline` é só contorno. */
|
|
217
225
|
emphasis?: BadgeEmphasis;
|
|
218
226
|
size?: BadgeSize;
|
|
@@ -239,7 +247,7 @@ export interface BadgeProps extends HTMLAttributes<HTMLSpanElement>, RefAttribut
|
|
|
239
247
|
* Chama-se assim, e não `content`, porque este colide com o atributo HTML de mesmo nome. */
|
|
240
248
|
badgeContent?: ReactNode;
|
|
241
249
|
}
|
|
242
|
-
export declare function Badge({ variant, emphasis, size, dot, leading, trailing, image, imageAlt, count, max, showZero, fit, anchor, anchorShape, invisible, badgeContent, children, className, ...props }: BadgeProps): React.JSX.Element;
|
|
250
|
+
export declare function Badge({ variant: variantProp, tone, emphasis, size, dot, leading, trailing, image, imageAlt, count, max, showZero, fit, anchor, anchorShape, invisible, badgeContent, children, className, ...props }: BadgeProps): React.JSX.Element;
|
|
243
251
|
/** O tom da barra: a mesma lista fechada do `ButtonTone`. Pausado é `neutral`; falha é `danger`. */
|
|
244
252
|
export type ProgressTone = "brand" | "neutral" | "success" | "warning" | "danger" | "info";
|
|
245
253
|
export interface ProgressProps {
|
|
@@ -252,10 +260,21 @@ export interface ProgressProps {
|
|
|
252
260
|
* que falta, bytes. Em texto, vai junto no `aria-valuetext`. */
|
|
253
261
|
detail?: ReactNode;
|
|
254
262
|
tone?: ProgressTone;
|
|
263
|
+
/** 0.32.0: o rótulo À MOSTRA, no alto à esquerda (o da barra da referência). Sem ele, o `label` só
|
|
264
|
+
* nomeia a barra para o leitor de tela, como sempre. */
|
|
265
|
+
showLabel?: boolean;
|
|
266
|
+
/** 0.32.0: o valor ("60%") no alto à direita, quando não há `detail`. */
|
|
267
|
+
showValue?: boolean;
|
|
268
|
+
/** A espessura do trilho: sm 4, md 8, lg 12 — os da referência. */
|
|
269
|
+
size?: ProgressSize;
|
|
255
270
|
className?: string;
|
|
256
271
|
}
|
|
257
|
-
export
|
|
258
|
-
export declare function
|
|
272
|
+
export type ProgressSize = "sm" | "md" | "lg";
|
|
273
|
+
export declare function Progress({ value, label, detail, tone, showLabel, showValue, size, className }: ProgressProps): React.JSX.Element;
|
|
274
|
+
export type SkeletonAnimation = "pulse" | "none";
|
|
275
|
+
export declare function Skeleton({ animation, className, ...props }: HTMLAttributes<HTMLDivElement> & RefAttributes<HTMLDivElement> & {
|
|
276
|
+
animation?: SkeletonAnimation;
|
|
277
|
+
}): React.JSX.Element;
|
|
259
278
|
export declare function AvatarGroup({ children, max, total, label, size, className }: {
|
|
260
279
|
children: ReactNode;
|
|
261
280
|
max?: number;
|
|
@@ -303,6 +322,8 @@ export declare function Topbar(props: HeaderProps): React.JSX.Element;
|
|
|
303
322
|
export declare function Kbd({ children, className, ...props }: HTMLAttributes<HTMLElement> & RefAttributes<HTMLElement>): React.JSX.Element;
|
|
304
323
|
export interface TextareaProps extends TextareaHTMLAttributes<HTMLTextAreaElement>, RefAttributes<HTMLTextAreaElement> {
|
|
305
324
|
size?: Responsive<FieldSize>;
|
|
325
|
+
/** 0.32.0, a da referência: `secondary` é o fundo neutro, para o campo dentro de um cartão. */
|
|
326
|
+
variant?: FieldVariant;
|
|
306
327
|
}
|
|
307
328
|
export declare const Textarea: React.ForwardRefExoticComponent<Omit<TextareaProps, "ref"> & RefAttributes<HTMLTextAreaElement>>;
|
|
308
329
|
export declare function Checkbox({ label, labelHidden, description, size, className, ...props }: Omit<InputHTMLAttributes<HTMLInputElement>, "size"> & RefAttributes<HTMLInputElement> & {
|
|
@@ -324,6 +345,7 @@ export declare function Range({ orientation, className, ...props }: InputHTMLAtt
|
|
|
324
345
|
orientation?: Responsive<RangeOrientation>;
|
|
325
346
|
}): React.JSX.Element;
|
|
326
347
|
export type FieldSize = Extract<ComponentSize, "sm" | "md" | "lg">;
|
|
348
|
+
export type FieldVariant = "primary" | "secondary";
|
|
327
349
|
export declare function Label({ htmlFor, className, children, ...props }: HTMLAttributes<HTMLLabelElement> & RefAttributes<HTMLLabelElement> & {
|
|
328
350
|
htmlFor?: string;
|
|
329
351
|
}): React.JSX.Element;
|
|
@@ -339,4 +361,62 @@ export declare function InputGroupAddon({ side, layout, className, children, ...
|
|
|
339
361
|
export declare function AspectRatio({ ratio, className, style, ...props }: HTMLAttributes<HTMLDivElement> & RefAttributes<HTMLDivElement> & {
|
|
340
362
|
ratio?: number;
|
|
341
363
|
}): React.JSX.Element;
|
|
364
|
+
export interface LinkProps extends AnchorHTMLAttributes<HTMLAnchorElement>, RefAttributes<HTMLAnchorElement> {
|
|
365
|
+
/** Abre noutra aba e mostra a seta. */
|
|
366
|
+
external?: boolean;
|
|
367
|
+
/** Não navega: sai sem `href` e com `aria-disabled`. */
|
|
368
|
+
disabled?: boolean;
|
|
369
|
+
}
|
|
370
|
+
export declare function Link({ external, disabled, href, target, rel, className, children, ...props }: LinkProps): React.JSX.Element;
|
|
371
|
+
export type ColorSwatchSize = "xs" | "sm" | "md" | "lg" | "xl";
|
|
372
|
+
export interface ColorSwatchProps extends HTMLAttributes<HTMLSpanElement>, RefAttributes<HTMLSpanElement> {
|
|
373
|
+
/** Qualquer cor do CSS: `#f0c200`, `oklch(…)`, `var(--primary)`. */
|
|
374
|
+
color: string;
|
|
375
|
+
size?: ColorSwatchSize;
|
|
376
|
+
/** O nome que o leitor de tela anuncia ("Amarelo Aurea"). Sem ele, o valor da cor. */
|
|
377
|
+
label?: string;
|
|
378
|
+
}
|
|
379
|
+
export interface ColorSwatchOption {
|
|
380
|
+
color: string;
|
|
381
|
+
label?: string;
|
|
382
|
+
/** Esta cor não se escolhe (as outras sim). */
|
|
383
|
+
disabled?: boolean;
|
|
384
|
+
}
|
|
385
|
+
/** O que as duas formas têm em comum: a escala. (É a base que o leitor da API segue em `base & (a | b)`.) */
|
|
386
|
+
export interface ColorSwatchBase {
|
|
387
|
+
size?: ColorSwatchSize;
|
|
388
|
+
}
|
|
389
|
+
export interface ColorSwatchPickerProps {
|
|
390
|
+
/** As cores para escolher — `"#0485f7"` ou `{color, label}`. É o que faz da amostra um grupo de escolha. */
|
|
391
|
+
options: readonly (string | ColorSwatchOption)[];
|
|
392
|
+
/** O nome do grupo no formulário, e o que faz das amostras UM grupo (as setas andam entre elas). */
|
|
393
|
+
name: string;
|
|
394
|
+
/** O nome do grupo para o leitor de tela ("Cor de destaque"). */
|
|
395
|
+
label: string;
|
|
396
|
+
value?: string;
|
|
397
|
+
defaultValue?: string;
|
|
398
|
+
/** O evento do navegador, como no `Radio`: `event.target.value` é a cor escolhida. */
|
|
399
|
+
onChange?: React.ChangeEventHandler<HTMLInputElement>;
|
|
400
|
+
/** `"grid"` (o padrão: em linha, quebrando) ou `"stack"` (em coluna), como na referência. */
|
|
401
|
+
layout?: "grid" | "stack";
|
|
402
|
+
/** A marca da escolhida, no lugar do "visto" (um `<Icon>`, por exemplo). Ela ganha a tinta que contrasta. */
|
|
403
|
+
indicator?: ReactNode;
|
|
404
|
+
size?: ColorSwatchSize;
|
|
405
|
+
disabled?: boolean;
|
|
406
|
+
id?: string;
|
|
407
|
+
className?: string;
|
|
408
|
+
}
|
|
409
|
+
export declare function ColorSwatch(props: ColorSwatchBase & (ColorSwatchProps | ColorSwatchPickerProps)): React.JSX.Element;
|
|
410
|
+
export type ProgressCircleSize = "sm" | "md" | "lg";
|
|
411
|
+
export interface ProgressCircleProps extends HTMLAttributes<HTMLDivElement>, RefAttributes<HTMLDivElement> {
|
|
412
|
+
/** De `min` a `max`. Sem ele, o círculo gira. */
|
|
413
|
+
value?: number;
|
|
414
|
+
min?: number;
|
|
415
|
+
max?: number;
|
|
416
|
+
size?: ProgressCircleSize;
|
|
417
|
+
tone?: ProgressTone;
|
|
418
|
+
/** O nome que o leitor de tela anuncia ("Enviando o arquivo"). */
|
|
419
|
+
label: string;
|
|
420
|
+
}
|
|
421
|
+
export declare function ProgressCircle({ value, min, max, size, tone, label, className, ...props }: ProgressCircleProps): React.JSX.Element;
|
|
342
422
|
export {};
|
package/dist/markup.js
CHANGED
|
@@ -37,6 +37,8 @@ import { Fragment as _Fragment, jsx as _jsx, jsxs as _jsxs } from "react/jsx-run
|
|
|
37
37
|
// tocar motor. Na dúvida, ele NÃO entra — cliente a mais é lento, servidor a mais é quebrado.
|
|
38
38
|
import React, { forwardRef } from "react";
|
|
39
39
|
import { cx, fundirRender, peleDoEixo } from "./pure.js";
|
|
40
|
+
// As contas de cor são funções puras, sem estado e sem navegador (ADR-0069): o `ColorSwatch` usa a do contraste.
|
|
41
|
+
import { contrastingInk, hsbToRgb, parseColor } from "./color.js";
|
|
40
42
|
export function Card({ variant = "base", padding = "normal", orientation = "vertical", accent, className, render, ...props }) {
|
|
41
43
|
return fundirRender(render, { className: cx("card", variant !== "base" && `card-${variant}`, accent && `card-accent card-accent-${accent}`, padding === "none" && "card-flush", orientation === "horizontal" && "card-horizontal", className), ...(variant === "contrast" ? { "data-theme": "dark" } : null), ...props });
|
|
42
44
|
}
|
|
@@ -104,16 +106,17 @@ export function Timeline({ items }) { return _jsx("ol", { className: "timeline",
|
|
|
104
106
|
// `dangerouslySetInnerHTML` tem de SANITIZAR antes. A Aurea desenha o texto; ela não pode decidir
|
|
105
107
|
// o que é seguro renderizar. Está dito na ficha, em voz alta.
|
|
106
108
|
export function Prose({ className, ...props }) { return _jsx("div", { className: cx("prose", className), ...props }); }
|
|
107
|
-
const tipografia = (tipo, { align, color, weight, truncate, numeric }, className) => cx("typography", `typography-${tipo}`, color === "muted" && "typography-muted", weight && `typography-weight-${weight}`, align && `typography-align-${align}`, truncate && "typography-truncate", numeric && "typography-numeric", className);
|
|
108
|
-
export function Text({ type = "body", align, color, weight, truncate, numeric, className, ...props }) { return _jsx("span", { className: tipografia(type, { align, color, weight, truncate, numeric }, className), ...props }); }
|
|
109
|
+
const tipografia = (tipo, { align, color, tone, weight, truncate, numeric }, className) => cx("typography", `typography-${tipo}`, (tone ?? color) === "muted" && "typography-muted", tone && tone !== "default" && tone !== "muted" && `typography-tone-${tone}`, weight && `typography-weight-${weight}`, align && `typography-align-${align}`, truncate && "typography-truncate", numeric && "typography-numeric", className);
|
|
110
|
+
export function Text({ type = "body", align, color, tone, weight, truncate, numeric, className, ...props }) { return _jsx("span", { className: tipografia(type, { align, color, tone, weight, truncate, numeric }, className), ...props }); }
|
|
109
111
|
// O nível decide o elemento E o tamanho, como na referência: um `h2` tem a cara de título 2.
|
|
110
|
-
export function Heading({ level = 1, align, color, weight, truncate, numeric, className, ...props }) { const Tag = `h${level}`; return _jsx(Tag, { className: tipografia(`h${level}`, { align, color, weight, truncate, numeric }, className), ...props }); }
|
|
111
|
-
export function Paragraph({ size = "base", align, color, weight, truncate, numeric, className, ...props }) { return _jsx("p", { className: tipografia(size === "base" ? "body" : `body-${size}`, { align, color, weight, truncate, numeric }, className), ...props }); }
|
|
112
|
-
export function Code({ align, color, weight, truncate, className, ...props }) { return _jsx("code", { className: tipografia("code", { align, color, weight, truncate }, className), ...props }); }
|
|
112
|
+
export function Heading({ level = 1, align, color, tone, weight, truncate, numeric, className, ...props }) { const Tag = `h${level}`; return _jsx(Tag, { className: tipografia(`h${level}`, { align, color, tone, weight, truncate, numeric }, className), ...props }); }
|
|
113
|
+
export function Paragraph({ size = "base", align, color, tone, weight, truncate, numeric, className, ...props }) { return _jsx("p", { className: tipografia(size === "base" ? "body" : `body-${size}`, { align, color, tone, weight, truncate, numeric }, className), ...props }); }
|
|
114
|
+
export function Code({ align, color, tone, weight, truncate, className, ...props }) { return _jsx("code", { className: tipografia("code", { align, color, tone, weight, truncate }, className), ...props }); }
|
|
113
115
|
// `max` com `+` é o idioma universal do contador (três das referências o usam). Exportada porque quem
|
|
114
116
|
// escreve o nome acessível precisa do MESMO texto — "99+ unread" tem de bater com o que se vê.
|
|
115
117
|
export function formatBadgeCount(count, max = 99) { return count > max ? `${max}+` : String(count); }
|
|
116
|
-
export function Badge({ variant = "neutral", emphasis = "soft", size = "md", dot, leading, trailing, image, imageAlt, count, max = 99, showZero, fit = "auto", anchor, anchorShape = "square", invisible, badgeContent, children, className, ...props }) {
|
|
118
|
+
export function Badge({ variant: variantProp = "neutral", tone, emphasis = "soft", size = "md", dot, leading, trailing, image, imageAlt, count, max = 99, showZero, fit = "auto", anchor, anchorShape = "square", invisible, badgeContent, children, className, ...props }) {
|
|
119
|
+
const variant = tone ?? variantProp;
|
|
117
120
|
const numero = count != null ? formatBadgeCount(count, max) : undefined;
|
|
118
121
|
const miolo = anchor ? (numero ?? badgeContent) : (numero ?? children);
|
|
119
122
|
// Ponto puro: `dot` sem nada para mostrar. Aí o badge não tem conteúdo, e ganha medida própria.
|
|
@@ -131,7 +134,7 @@ export function Badge({ variant = "neutral", emphasis = "soft", size = "md", dot
|
|
|
131
134
|
// AN-07 (03/10/2026). Tudo novo é acréscimo: com `value` e sem `detail` nem `tone`, a marcação é a
|
|
132
135
|
// de antes, mais a classe da caixa de fora. A anatomia é a da barra de progresso da referência: a
|
|
133
136
|
// saída no alto à direita, o trilho embaixo, e sem `aria-valuenow` quando não há total.
|
|
134
|
-
export function Progress({ value, label, detail, tone = "brand", className }) {
|
|
137
|
+
export function Progress({ value, label, detail, tone = "brand", showLabel, showValue, size = "md", className }) {
|
|
135
138
|
const semTotal = value == null || Number.isNaN(value);
|
|
136
139
|
const pct = semTotal ? undefined : Math.max(0, Math.min(100, value));
|
|
137
140
|
const temApoio = detail != null && detail !== false && detail !== "";
|
|
@@ -139,9 +142,14 @@ export function Progress({ value, label, detail, tone = "brand", className }) {
|
|
|
139
142
|
// vezes. Apoio que não é texto (um ícone, um link) fica onde está, para o leitor achar sozinho.
|
|
140
143
|
const emTexto = temApoio && (typeof detail === "string" || typeof detail === "number") ? String(detail) : undefined;
|
|
141
144
|
const valuetext = emTexto == null ? undefined : pct == null ? emTexto : `${pct}%, ${emTexto}`;
|
|
142
|
-
|
|
145
|
+
// O rótulo à mostra sai do leitor de tela (`aria-hidden`): quem nomeia a barra continua o `aria-label`,
|
|
146
|
+
// com o mesmo texto — sem isso, o leitor o leria duas vezes. (Este arquivo não usa hook, então nada de
|
|
147
|
+
// id gerado para `aria-labelledby`.)
|
|
148
|
+
const rotuloVisivel = !!showLabel && !!label;
|
|
149
|
+
const valor = !temApoio && showValue && pct != null ? `${Math.round(pct)}%` : undefined;
|
|
150
|
+
return _jsxs("div", { className: cx("progress-field", className), children: [rotuloVisivel && _jsx("span", { className: "progress-label", "aria-hidden": "true", children: label }), temApoio && _jsx("div", { className: "progress-detail", "aria-hidden": emTexto != null || undefined, children: detail }), valor && _jsx("div", { className: "progress-detail", "aria-hidden": "true", children: valor }), _jsx("div", { className: cx("progress", semTotal && "progress-indeterminate", tone !== "brand" && `progress-tone-${tone}`, size !== "md" && `progress-${size}`), role: "progressbar", "aria-label": label, "aria-valuemin": 0, "aria-valuemax": 100, "aria-valuenow": pct, "aria-valuetext": valuetext, children: _jsx("span", { style: pct == null ? undefined : { width: `${pct}%` } }) })] });
|
|
143
151
|
}
|
|
144
|
-
export function Skeleton({ className, ...props }) { return _jsx("div", { className: cx("skeleton", className), "aria-hidden": "true", ...props }); }
|
|
152
|
+
export function Skeleton({ animation = "pulse", className, ...props }) { return _jsx("div", { className: cx("skeleton", animation === "none" && "skeleton-static", className), "aria-hidden": "true", ...props }); }
|
|
145
153
|
// ── Identity ─────────────────────────────────────────────────────────────────────────────────
|
|
146
154
|
// `React.Children` não é hook — é utilitário de leitura de `children`, e roda no servidor.
|
|
147
155
|
export function AvatarGroup({ children, max, total, label, size, className }) {
|
|
@@ -180,8 +188,12 @@ export function Topbar(props) { return _jsx(Header, { ...props }); }
|
|
|
180
188
|
// Kbd — representação de tecla/atalho. <kbd> é o elemento HTML certo; a pele é nossa. Ele já
|
|
181
189
|
// morava fora da casa dele (no `internal.tsx`, por causa do `Button`); agora mora aqui, pelo
|
|
182
190
|
// mesmo motivo elevado a regra.
|
|
183
|
-
|
|
184
|
-
|
|
191
|
+
// 0.32.0: uma tecla de UM caractere ("K", "⌘", "/") sai redonda (`kbd-single`), e uma palavra
|
|
192
|
+
// ("Esc", "Enter") em cápsula — o canto da Aurea sobre a medida da referência. Conta-se o que a
|
|
193
|
+
// pessoa vê (`Array.from` não parte um emoji ao meio); conteúdo que não é texto fica em cápsula.
|
|
194
|
+
const umCaractere = (c) => (typeof c === "string" || typeof c === "number") && Array.from(String(c).trim()).length === 1;
|
|
195
|
+
export function Kbd({ children, className, ...props }) { return _jsx("kbd", { className: cx("kbd", umCaractere(children) && "kbd-single", className), ...props, children: children }); }
|
|
196
|
+
export const Textarea = forwardRef(function Textarea({ className, size, variant, ...props }, ref) { return _jsx("textarea", { ref: ref, className: cx("textarea", peleDoEixo("textarea", size), variant === "secondary" && "textarea-secondary", className), ...props }); });
|
|
185
197
|
// `size` nos três marcáveis pela mesma razão do campo: uma linha de formulário com um campo `sm`
|
|
186
198
|
// e um checkbox de tamanho fixo ao lado desalinha. O degrau vai na MARCA, não no rótulo.
|
|
187
199
|
export function Checkbox({ label, labelHidden, description, size, className, ...props }) { return _jsxs("label", { className: cx("checkbox", labelHidden && "checkbox-bare", className), children: [_jsx("input", { type: "checkbox", ...props }), _jsx("span", { className: cx("control-mark", peleDoEixo("control-mark", size)) }), _jsxs("span", { className: labelHidden ? "sr-only" : undefined, children: [_jsx("strong", { children: label }), description && _jsxs(_Fragment, { children: [_jsx("br", {}), _jsx("span", { className: "muted", children: description })] })] })] }); }
|
|
@@ -228,3 +240,28 @@ export function InputGroupAddon({ side = "start", layout = "inline", className,
|
|
|
228
240
|
// escreve o `padding-top: 56.25%` de 2015, ou esquece o `min-width: 0` que impede a caixa de
|
|
229
241
|
// estourar dentro de um grid.
|
|
230
242
|
export function AspectRatio({ ratio = 1, className, style, ...props }) { return _jsx("div", { className: cx("aspect-ratio", className), style: { aspectRatio: ratio, ...style }, ...props }); }
|
|
243
|
+
export function Link({ external, disabled, href, target, rel, className, children, ...props }) {
|
|
244
|
+
return _jsxs("a", { className: cx("link", className), href: disabled ? undefined : href, "aria-disabled": disabled || undefined, target: external ? target ?? "_blank" : target, rel: external ? rel ?? "noopener noreferrer" : rel, ...props, children: [children, external && _jsx("span", { className: "link-external", "aria-hidden": "true" })] });
|
|
245
|
+
}
|
|
246
|
+
// Transparente quando o texto diz alfa abaixo de 1 (hex de 4 ou 8 dígitos, `rgba()`, `hsla()`…). Cor de token ou
|
|
247
|
+
// `oklch()` a marcação não lê: fica sem xadrez.
|
|
248
|
+
const transparente = (cor) => { const c = parseColor(cor); return c !== null && c.a < 1; };
|
|
249
|
+
export function ColorSwatch(props) {
|
|
250
|
+
if ("options" in props) {
|
|
251
|
+
const { options, name, label, value, defaultValue, onChange, layout = "grid", indicator, size = "md", disabled, id, className } = props;
|
|
252
|
+
// O `onChange` é o do CONSUMIDOR, repassado, como no `Checkbox` e no `Radio` desta casa: nenhum manipulador nosso
|
|
253
|
+
// é escrito aqui (a marcação continua de servidor). Vai por espalhamento, como lá.
|
|
254
|
+
return _jsx("div", { role: "radiogroup", "aria-label": label, id: id, "aria-disabled": disabled || undefined, className: cx("color-swatch-picker", size !== "md" && `color-swatch-picker-${size}`, layout === "stack" && "color-swatch-picker-stack", className), children: options.map((o) => {
|
|
255
|
+
const op = typeof o === "string" ? { color: o } : o;
|
|
256
|
+
const cor = parseColor(op.color), rgb = cor && hsbToRgb(cor);
|
|
257
|
+
return _jsxs("label", { className: cx("color-swatch-option", rgb && contrastingInk(rgb) === "dark" && "color-swatch-option-dark"), style: { ["--color-swatch-current"]: op.color }, children: [_jsx("input", { type: "radio", className: "color-swatch-input", name: name, value: op.color, "aria-label": op.label ?? op.color, checked: value === undefined ? undefined : value === op.color, defaultChecked: value === undefined ? defaultValue === op.color : undefined, disabled: disabled || op.disabled, ...(onChange ? { onChange } : {}) }), _jsx("span", { className: cx("color-swatch", cor && cor.a < 1 && "color-swatch-alpha"), "aria-hidden": "true" }), indicator != null && _jsx("span", { className: "color-swatch-indicator", "aria-hidden": "true", children: indicator })] }, op.color);
|
|
258
|
+
}) });
|
|
259
|
+
}
|
|
260
|
+
const { color, size = "md", label, className, style, ...resto } = props;
|
|
261
|
+
return _jsx("span", { role: "img", "aria-label": label ?? color, className: cx("color-swatch", size !== "md" && `color-swatch-${size}`, transparente(color) && "color-swatch-alpha", className), style: { ...style, ["--color-swatch-current"]: color }, ...resto });
|
|
262
|
+
}
|
|
263
|
+
export function ProgressCircle({ value, min = 0, max = 100, size = "md", tone = "brand", label, className, ...props }) {
|
|
264
|
+
const semTotal = value == null || Number.isNaN(value);
|
|
265
|
+
const pct = semTotal ? 25 : Math.max(0, Math.min(100, (value - min) / (max - min) * 100));
|
|
266
|
+
return _jsx("div", { role: "progressbar", "aria-label": label, "aria-valuemin": semTotal ? undefined : min, "aria-valuemax": semTotal ? undefined : max, "aria-valuenow": semTotal ? undefined : value, className: cx("progress-circle", size !== "md" && `progress-circle-${size}`, tone !== "brand" && `progress-circle-${tone}`, semTotal && "progress-circle-indeterminate", className), ...props, children: _jsxs("svg", { viewBox: "0 0 36 36", "aria-hidden": "true", children: [_jsx("circle", { className: "progress-circle-track", cx: "18", cy: "18", r: "16" }), _jsx("circle", { className: "progress-circle-fill", cx: "18", cy: "18", r: "16", pathLength: 100, strokeDasharray: "100", strokeDashoffset: 100 - pct })] }) });
|
|
267
|
+
}
|
|
@@ -24,7 +24,8 @@ export declare function Breadcrumb({ items, label }: {
|
|
|
24
24
|
}): React.JSX.Element;
|
|
25
25
|
export type TabsOrientation = "horizontal" | "vertical";
|
|
26
26
|
export type TabsPanel = "card" | "plain";
|
|
27
|
-
export
|
|
27
|
+
export type TabsVariant = "primary" | "secondary";
|
|
28
|
+
export declare function Tabs({ tabs, value, onChange, label, orientation, activateOnFocus, loopFocus, panel, variant }: {
|
|
28
29
|
tabs: Array<{
|
|
29
30
|
id: string;
|
|
30
31
|
label: ReactNode;
|
|
@@ -37,12 +38,26 @@ export declare function Tabs({ tabs, value, onChange, label, orientation, activa
|
|
|
37
38
|
activateOnFocus?: boolean;
|
|
38
39
|
loopFocus?: boolean;
|
|
39
40
|
panel?: TabsPanel;
|
|
41
|
+
variant?: TabsVariant;
|
|
40
42
|
}): React.JSX.Element;
|
|
41
|
-
export
|
|
43
|
+
export type PaginationVariant = "numbers" | "simple" | "compact";
|
|
44
|
+
export interface PaginationProps {
|
|
42
45
|
page: number;
|
|
43
46
|
total: number;
|
|
44
|
-
onPageChange
|
|
45
|
-
|
|
47
|
+
onPageChange?: (p: number) => void;
|
|
48
|
+
variant?: PaginationVariant;
|
|
49
|
+
/** O resumo à esquerda — "1 a 5 de 50 pedidos". */
|
|
50
|
+
summary?: ReactNode;
|
|
51
|
+
/** O endereço de cada página. Com ele, as páginas são links. */
|
|
52
|
+
href?: (page: number) => string;
|
|
53
|
+
/** Quantas páginas aparecem de cada lado da atual. Padrão: 1. */
|
|
54
|
+
siblings?: number;
|
|
55
|
+
/** O nome do marco de navegação. Padrão: a frase `paginationLabel`. Com duas paginações na mesma
|
|
56
|
+
* página, cada uma diz de quê ("Páginas dos pedidos"), senão o leitor de tela ouve dois marcos iguais. */
|
|
57
|
+
label?: string;
|
|
58
|
+
className?: string;
|
|
59
|
+
}
|
|
60
|
+
export declare function Pagination({ page, total, onPageChange, variant, summary, href, siblings, label, className }: PaginationProps): React.JSX.Element;
|
|
46
61
|
export interface TocItem {
|
|
47
62
|
id: string;
|
|
48
63
|
label: string;
|
|
@@ -80,12 +95,16 @@ export interface SidebarItem {
|
|
|
80
95
|
/** O link do roteador do app (M-01): `<Link href="/relatorios" />`. Recebe a pele, o estado de página atual e o conteúdo do item. */
|
|
81
96
|
render?: ReactElement;
|
|
82
97
|
}
|
|
83
|
-
export type SidebarVariant = "floating" | "flush";
|
|
84
|
-
export
|
|
98
|
+
export type SidebarVariant = "floating" | "flush" | "plain";
|
|
99
|
+
export type SidebarScrollbar = "hover" | "visible";
|
|
100
|
+
export type SidebarPlacement = "left" | "right";
|
|
101
|
+
export declare function Sidebar({ items, current, collapsed, variant, placement, scrollbar, label, children, className, onClick, ...props }: HTMLAttributes<HTMLElement> & RefAttributes<HTMLElement> & {
|
|
85
102
|
items?: SidebarItem[];
|
|
86
103
|
current?: string;
|
|
87
104
|
collapsed?: boolean;
|
|
88
105
|
variant?: SidebarVariant;
|
|
106
|
+
placement?: SidebarPlacement;
|
|
107
|
+
scrollbar?: SidebarScrollbar;
|
|
89
108
|
label?: string;
|
|
90
109
|
}): React.JSX.Element;
|
|
91
110
|
export type BottomNavVariant = "floating" | "edge";
|
|
@@ -135,13 +154,18 @@ export interface CommandItem {
|
|
|
135
154
|
icon?: IconName;
|
|
136
155
|
kbd?: string;
|
|
137
156
|
run: () => void;
|
|
157
|
+
/** 0.32.0 (DOC-06): o grupo do item ("Componentes", "Páginas"). Itens com o mesmo grupo saem juntos,
|
|
158
|
+
* sob o título dele, na ordem em que o grupo aparece primeiro. */
|
|
159
|
+
group?: string;
|
|
138
160
|
}
|
|
139
|
-
export declare function CommandPalette({ open, onClose, items, placeholder, label }: {
|
|
161
|
+
export declare function CommandPalette({ open, onClose, items, placeholder, label, shortcuts }: {
|
|
140
162
|
open: boolean;
|
|
141
163
|
onClose: () => void;
|
|
142
164
|
items: CommandItem[];
|
|
143
165
|
placeholder?: string;
|
|
144
166
|
label?: string;
|
|
167
|
+
/** 0.32.0 (DOC-07): a linha que ensina as teclas, embaixo — ↑ ↓ mover, Enter abrir, Esc fechar. */
|
|
168
|
+
shortcuts?: boolean;
|
|
145
169
|
}): React.JSX.Element | null;
|
|
146
170
|
export declare function CommandPaletteShell({ open, query, onQueryChange, children }: {
|
|
147
171
|
open: boolean;
|
|
@@ -8,7 +8,7 @@ import { Tabs as BaseTabs } from "@base-ui/react/tabs";
|
|
|
8
8
|
import { useDirection } from "@base-ui/react/direction-provider";
|
|
9
9
|
import { Autocomplete as BaseAutocomplete } from "@base-ui/react/autocomplete";
|
|
10
10
|
import { useValorResponsivo } from "./responsivo-runtime.js";
|
|
11
|
-
import { cx, fundirRender, useAureaStrings
|
|
11
|
+
import { cx, fundirRender, useAureaStrings } from "./internal.js";
|
|
12
12
|
import { Kbd } from "./markup.js";
|
|
13
13
|
import { Icon } from "./system.js";
|
|
14
14
|
import { Button } from "./actions.js";
|
|
@@ -29,8 +29,37 @@ export function Stepper({ items, label, className }) {
|
|
|
29
29
|
}) });
|
|
30
30
|
}
|
|
31
31
|
export function Breadcrumb({ items, label }) { const s = useAureaStrings(); return _jsx("nav", { className: "breadcrumb", "aria-label": label ?? s.breadcrumbLabel, children: items.map((i, n) => _jsxs(React.Fragment, { children: [n > 0 && _jsx(Icon, { name: "caret-right", size: "sm" }), " ", i.render ? fundirRender(i.render, { children: i.label }, "a") : i.href ? _jsx("a", { href: i.href, children: i.label }) : _jsx("strong", { "aria-current": "page", children: i.label })] }, n)) }); }
|
|
32
|
-
export function Tabs({ tabs, value, onChange, label, orientation, activateOnFocus = true, loopFocus, panel = "card" }) { const s = useAureaStrings(); const ancora = useRef(null); const resolvida = useValorResponsivo(orientation, "horizontal", ancora); return _jsxs(BaseTabs.Root, { ref: ancora, value: value, onValueChange: v => onChange(String(v)), orientation: resolvida, className: "tabs-root", children: [_jsx(BaseTabs.List, { className: "tabs", "aria-label": label ?? s.tabsLabel, activateOnFocus: activateOnFocus, loopFocus: loopFocus, children: tabs.map(t => _jsx(BaseTabs.Tab, { value: t.id, className: "tab", children: t.label }, t.id)) }), tabs.map(t => _jsx(BaseTabs.Panel, { value: t.id, className: panel === "plain" ? "tabs-panel" : "card card-inset", tabIndex: 0, children: t.content }, t.id))] }); }
|
|
33
|
-
|
|
32
|
+
export function Tabs({ tabs, value, onChange, label, orientation, activateOnFocus = true, loopFocus, panel = "card", variant = "primary" }) { const s = useAureaStrings(); const ancora = useRef(null); const resolvida = useValorResponsivo(orientation, "horizontal", ancora); return _jsxs(BaseTabs.Root, { ref: ancora, value: value, onValueChange: v => onChange(String(v)), orientation: resolvida, className: "tabs-root", children: [_jsx(BaseTabs.List, { className: cx("tabs", variant === "secondary" && "tabs-secondary"), "aria-label": label ?? s.tabsLabel, activateOnFocus: activateOnFocus, loopFocus: loopFocus, children: tabs.map(t => _jsx(BaseTabs.Tab, { value: t.id, className: "tab", children: t.label }, t.id)) }), tabs.map(t => _jsx(BaseTabs.Panel, { value: t.id, className: panel === "plain" ? "tabs-panel" : "card card-inset", tabIndex: 0, children: t.content }, t.id))] }); }
|
|
33
|
+
function paginasVisiveis(page, total, siblings) {
|
|
34
|
+
if (total <= 5 + siblings * 2)
|
|
35
|
+
return Array.from({ length: total }, (_, i) => i + 1);
|
|
36
|
+
const ini = Math.max(2, page - siblings), fim = Math.min(total - 1, page + siblings);
|
|
37
|
+
const meio = Array.from({ length: fim - ini + 1 }, (_, i) => ini + i);
|
|
38
|
+
return [1, ...(ini > 2 ? ["..."] : []), ...meio, ...(fim < total - 1 ? ["..."] : []), total];
|
|
39
|
+
}
|
|
40
|
+
export function Pagination({ page, total, onPageChange, variant = "numbers", summary, href, siblings = 1, label, className }) {
|
|
41
|
+
const s = useAureaStrings();
|
|
42
|
+
if (variant === "compact")
|
|
43
|
+
return _jsxs("nav", { className: cx("pagination", className), "aria-label": label ?? s.paginationLabel, children: [_jsx(Button, { variant: "ghost", size: "sm", disabled: page <= 1, onClick: () => onPageChange?.(page - 1), children: s.previous }), _jsxs(Badge, { variant: "primary", children: [page, " / ", total] }), _jsx(Button, { variant: "ghost", size: "sm", disabled: page >= total, onClick: () => onPageChange?.(page + 1), children: s.next })] });
|
|
44
|
+
// Um item: link (com `href`) ou botão. Desligado (a primeira página no "anterior"), sem endereço.
|
|
45
|
+
const item = (alvo, conteudo, { atual = false, nav, rotulo } = {}) => {
|
|
46
|
+
const fora = alvo < 1 || alvo > total;
|
|
47
|
+
const cls = cx("pagination-link", nav && "pagination-link-nav", atual && "active");
|
|
48
|
+
const comuns = { className: cls, "aria-label": rotulo, "aria-current": atual ? "page" : undefined };
|
|
49
|
+
if (href)
|
|
50
|
+
return fora ? _jsx("a", { ...comuns, "aria-disabled": "true", children: conteudo })
|
|
51
|
+
: _jsx("a", { ...comuns, href: href(alvo), onClick: onPageChange ? (e) => { if (!e.metaKey && !e.ctrlKey && !e.shiftKey && e.button === 0) {
|
|
52
|
+
e.preventDefault();
|
|
53
|
+
onPageChange(alvo);
|
|
54
|
+
} } : undefined, children: conteudo });
|
|
55
|
+
return _jsx("button", { type: "button", ...comuns, disabled: fora, onClick: () => onPageChange?.(alvo), children: conteudo });
|
|
56
|
+
};
|
|
57
|
+
const anterior = item(page - 1, _jsxs(_Fragment, { children: [_jsx(Icon, { name: "caret-left", className: "pagination-nav-icon" }), _jsx("span", { children: s.previous })] }), { nav: "prev" });
|
|
58
|
+
const proxima = item(page + 1, _jsxs(_Fragment, { children: [_jsx("span", { children: s.next }), _jsx(Icon, { name: "caret-right", className: "pagination-nav-icon" })] }), { nav: "next" });
|
|
59
|
+
return _jsxs("nav", { className: cx("pagination", className), "aria-label": label ?? s.paginationLabel, children: [summary != null && _jsx("span", { className: "pagination-summary", children: summary }), _jsxs("ul", { className: "pagination-content", children: [_jsx("li", { children: anterior }), variant === "numbers" && paginasVisiveis(page, total, siblings).map((p, i) => p === "..."
|
|
60
|
+
? _jsx("li", { children: _jsx("span", { className: "pagination-ellipsis", "aria-hidden": "true", children: "\u2026" }) }, `e${i}`)
|
|
61
|
+
: _jsx("li", { children: item(p, p, { atual: p === page, rotulo: `${s.paginationPage} ${p}` }) }, p)), _jsx("li", { children: proxima })] })] });
|
|
62
|
+
}
|
|
34
63
|
export function TableOfContents({ items, current, label, className, ...props }) {
|
|
35
64
|
const s = useAureaStrings();
|
|
36
65
|
const meu = React.useRef(null);
|
|
@@ -43,7 +72,7 @@ export function TableOfContents({ items, current, label, className, ...props })
|
|
|
43
72
|
return _jsxs("nav", { ref: n => { meu.current = n; if (typeof refDele === "function")
|
|
44
73
|
refDele(n);
|
|
45
74
|
else if (refDele)
|
|
46
|
-
refDele.current = n; }, className: cx("toc", className), "aria-label": label ?? s.tocLabel, ...resto, children: [
|
|
75
|
+
refDele.current = n; }, className: cx("toc", className), "aria-label": label ?? s.tocLabel, ...resto, children: [_jsxs("p", { className: "toc-label", children: [_jsx("span", { className: "toc-label-icon", "aria-hidden": "true" }), label ?? s.tocLabel] }), items.map(i => _jsx("a", { href: `#${i.id}`, className: cx(i.sub && "toc-sub"), ...(i.id === atual ? { "aria-current": "true" } : {}), children: i.label }, i.id))] });
|
|
47
76
|
}
|
|
48
77
|
/** Qual dos `items` está na faixa de leitura, observando o documento. Devolve `undefined` até o
|
|
49
78
|
* primeiro cálculo — e em SSR, onde não há documento para observar.
|
|
@@ -235,10 +264,10 @@ function fecharGavetaAoEscolher(e) {
|
|
|
235
264
|
}
|
|
236
265
|
catch { /* motor sem popover: não há gaveta */ }
|
|
237
266
|
}
|
|
238
|
-
export function Sidebar({ items, current, collapsed, variant = "floating", label, children, className, onClick, ...props }) {
|
|
267
|
+
export function Sidebar({ items, current, collapsed, variant = "floating", placement = "left", scrollbar = "hover", label, children, className, onClick, ...props }) {
|
|
239
268
|
const s = useAureaStrings();
|
|
240
269
|
const baseId = React.useId();
|
|
241
|
-
return _jsxs("aside", { className: cx("sidebar", variant !== "floating" && `sidebar-${variant}`, collapsed && "sidebar-collapsed", className), onClick: e => { onClick?.(e); fecharGavetaAoEscolher(e); }, ...props, children: [items && items.length > 0 && _jsx("nav", { className: "sidebar-nav", "aria-label": label ?? s.sidebarLabel, children: sidebarList(items, { baseId, current, collapsed }) }), children] });
|
|
270
|
+
return _jsxs("aside", { className: cx("sidebar", variant !== "floating" && `sidebar-${variant}`, collapsed && "sidebar-collapsed", placement === "right" && "sidebar-right", scrollbar === "visible" && "sidebar-scrollbar-visible", className), "data-placement": placement, onClick: e => { onClick?.(e); fecharGavetaAoEscolher(e); }, ...props, children: [items && items.length > 0 && _jsx("nav", { className: "sidebar-nav", "aria-label": label ?? s.sidebarLabel, children: sidebarList(items, { baseId, current, collapsed }) }), children] });
|
|
242
271
|
}
|
|
243
272
|
const LEGADO = {
|
|
244
273
|
flat: ["edge", "none"], surface: ["floating", "circle"], pill: ["floating", "pill"], dock: ["floating", "circle"]
|
|
@@ -282,24 +311,39 @@ export function NavList({ items, className, ...props }) {
|
|
|
282
311
|
: _jsx("button", { type: "button", className: "nav-list-row", "aria-disabled": it.disabled || undefined, onClick: it.disabled ? undefined : it.onClick, children: miolo }) }, it.id);
|
|
283
312
|
}) });
|
|
284
313
|
}
|
|
285
|
-
export function CommandPalette({ open, onClose, items, placeholder, label }) {
|
|
314
|
+
export function CommandPalette({ open, onClose, items, placeholder, label, shortcuts = true }) {
|
|
286
315
|
const s = useAureaStrings();
|
|
287
|
-
const
|
|
316
|
+
const idAtalhos = React.useId();
|
|
317
|
+
// GRUPOS (0.32.0, DOC-06). Em 13/08/2026 a Aurea ficou SEM grupo, e a medição decidiu: dar a cada
|
|
318
|
+
// `Group` a sua fatia de itens passava POR CIMA do filtro do motor (digitar "the" devolvia os três).
|
|
319
|
+
// O caminho certo é o da documentação do motor (1.6.0, a paleta de exemplo dele): `items` agrupados
|
|
320
|
+
// (`{value, items}`), e a lista recebe os grupos JÁ FILTRADOS. Sem `group` em nenhum item, a lista é
|
|
321
|
+
// a de sempre.
|
|
322
|
+
const grupos = React.useMemo(() => {
|
|
323
|
+
if (!items.some(i => i.group))
|
|
324
|
+
return null;
|
|
325
|
+
const mapa = new Map();
|
|
326
|
+
for (const i of items) {
|
|
327
|
+
const g = i.group ?? "";
|
|
328
|
+
if (!mapa.has(g))
|
|
329
|
+
mapa.set(g, []);
|
|
330
|
+
mapa.get(g).push(i);
|
|
331
|
+
}
|
|
332
|
+
return [...mapa].map(([value, itens]) => ({ value, items: itens }));
|
|
333
|
+
}, [items]);
|
|
288
334
|
if (!open)
|
|
289
335
|
return null;
|
|
290
|
-
// SEM AGRUPAMENTO na v1, e a medição é que decidiu (13/08/2026). O `Autocomplete.Root` não
|
|
291
|
-
// consome a estrutura agrupada como o `Combobox.Root` consome — e o caminho alternativo, dar a
|
|
292
|
-
// cada `Group` a sua fatia de itens, PASSA POR CIMA do filtro do motor: digitar "the" devolvia
|
|
293
|
-
// os três comandos. Entre agrupar e filtrar, filtrar é o ponto de uma paleta de comandos.
|
|
294
|
-
// Fica registrado como limite, não como esquecimento: quando alguém precisar de grupo aqui, o
|
|
295
|
-
// caminho é o `Combobox.Root`, e isso é troca de motor, não ajuste.
|
|
296
336
|
const executa = (item) => { onClose(); item.run(); };
|
|
297
337
|
const linha = (item) => _jsxs(BaseAutocomplete.Item, { value: item, className: "menu-item command-item", onClick: () => executa(item), children: [item.icon && _jsx(Icon, { name: item.icon }), _jsx("span", { className: "command-item-label", children: item.label }), item.kbd && _jsx(Kbd, { children: item.kbd })] }, item.id);
|
|
298
338
|
// Escape fecha, e é o teclado que a pessoa tenta primeiro. O motor não fecha sozinho porque
|
|
299
339
|
// quem é dono do `open` é o consumidor — mesma regra do Dialog e do Drawer daqui.
|
|
300
340
|
return _jsx("div", { className: "command-overlay", onKeyDown: e => { if (e.key === "Escape")
|
|
301
|
-
onClose(); }, children:
|
|
302
|
-
|
|
341
|
+
onClose(); }, children: _jsxs("div", { className: "command-palette", role: "dialog", "aria-label": label ?? s.commandLabel, children: [_jsxs(BaseAutocomplete.Root, { items: (grupos ?? items), itemToStringValue: (i) => i.label, mode: "list", open: true, inline: true, autoHighlight: "always", keepHighlight: true, children: [_jsx(BaseAutocomplete.Input, { autoFocus: true, className: "input", onKeyDown: e => { if (e.key === "Escape") {
|
|
342
|
+
e.stopPropagation();
|
|
343
|
+
onClose();
|
|
344
|
+
} }, "aria-label": placeholder ?? s.commandPlaceholder, placeholder: placeholder ?? s.commandPlaceholder, "aria-expanded": true, "aria-describedby": shortcuts ? idAtalhos : undefined }), _jsxs("div", { className: "menu command-list", children: [_jsx(BaseAutocomplete.Empty, { className: "combobox-empty", children: s.comboboxEmpty }), _jsx(BaseAutocomplete.List, { children: grupos
|
|
345
|
+
? (g) => _jsxs(BaseAutocomplete.Group, { items: g.items, className: "command-group", children: [g.value && _jsx(BaseAutocomplete.GroupLabel, { className: "command-group-label", children: g.value }), _jsx(BaseAutocomplete.Collection, { children: linha })] }, g.value)
|
|
346
|
+
: _jsx(BaseAutocomplete.Collection, { children: linha }) })] })] }), shortcuts && _jsxs("p", { className: "command-shortcuts", id: idAtalhos, children: [_jsxs("span", { children: [_jsx(Kbd, { children: "\u2191" }), _jsx(Kbd, { children: "\u2193" }), " ", s.commandHintMove] }), _jsxs("span", { children: [_jsx(Kbd, { children: "Enter" }), " ", s.commandHintSelect] }), _jsxs("span", { children: [_jsx(Kbd, { children: "Esc" }), " ", s.commandHintClose] })] })] }) });
|
|
303
347
|
}
|
|
304
348
|
export function CommandPaletteShell({ open, query, onQueryChange, children }) { const s = useAureaStrings(); if (!open)
|
|
305
349
|
return null; return _jsx("div", { className: "command-overlay", children: _jsxs("div", { className: "command-palette", role: "dialog", "aria-label": s.commandLabel, children: [_jsx(SearchField, { autoFocus: true, "aria-label": s.commandPlaceholder, value: query, onChange: e => onQueryChange(e.target.value), placeholder: s.commandPlaceholder }), children] }) }); }
|
package/dist/overlays.d.ts
CHANGED
|
@@ -2,7 +2,9 @@ import React, { type ReactNode, type ReactElement } from "react";
|
|
|
2
2
|
import { type Responsive } from "./pure.js";
|
|
3
3
|
import { type IconName } from "./system.js";
|
|
4
4
|
export type DialogSize = "xs" | "sm" | "md" | "lg" | "xl" | "full";
|
|
5
|
-
export
|
|
5
|
+
export type DialogPlacement = "auto" | "center" | "top" | "bottom";
|
|
6
|
+
export type DialogIconTone = "neutral" | "brand" | "info" | "success" | "warning" | "danger";
|
|
7
|
+
export declare function Dialog({ open, title, children, footer, onClose, size, dismissible, icon, iconTone, placement }: {
|
|
6
8
|
open: boolean;
|
|
7
9
|
title: ReactNode;
|
|
8
10
|
children: ReactNode;
|
|
@@ -10,8 +12,11 @@ export declare function Dialog({ open, title, children, footer, onClose, size, d
|
|
|
10
12
|
onClose: () => void;
|
|
11
13
|
size?: DialogSize;
|
|
12
14
|
dismissible?: boolean;
|
|
15
|
+
icon?: IconName;
|
|
16
|
+
iconTone?: DialogIconTone;
|
|
17
|
+
placement?: DialogPlacement;
|
|
13
18
|
}): React.JSX.Element;
|
|
14
|
-
export declare function ConfirmDialog({ open, title, description, confirmLabel, cancelLabel, destructive, onConfirm, onCancel }: {
|
|
19
|
+
export declare function ConfirmDialog({ open, title, description, confirmLabel, cancelLabel, destructive, onConfirm, onCancel, icon, iconTone, placement }: {
|
|
15
20
|
open: boolean;
|
|
16
21
|
title: ReactNode;
|
|
17
22
|
description: ReactNode;
|
|
@@ -20,13 +25,18 @@ export declare function ConfirmDialog({ open, title, description, confirmLabel,
|
|
|
20
25
|
destructive?: boolean;
|
|
21
26
|
onConfirm: () => void;
|
|
22
27
|
onCancel: () => void;
|
|
28
|
+
icon?: IconName;
|
|
29
|
+
iconTone?: DialogIconTone;
|
|
30
|
+
placement?: DialogPlacement;
|
|
23
31
|
}): React.JSX.Element;
|
|
24
|
-
export
|
|
32
|
+
export type DrawerSide = "left" | "right" | "top" | "bottom";
|
|
33
|
+
export declare function Drawer({ open, title, children, footer, onClose, side }: {
|
|
25
34
|
open: boolean;
|
|
26
35
|
title: ReactNode;
|
|
27
36
|
children: ReactNode;
|
|
37
|
+
footer?: ReactNode;
|
|
28
38
|
onClose: () => void;
|
|
29
|
-
side?:
|
|
39
|
+
side?: DrawerSide;
|
|
30
40
|
}): React.JSX.Element;
|
|
31
41
|
export type AccessGateProps = {
|
|
32
42
|
allowed: boolean;
|
|
@@ -42,16 +52,20 @@ export type AccessGateProps = {
|
|
|
42
52
|
});
|
|
43
53
|
export declare function AccessGate({ allowed, children, ...resto }: AccessGateProps): React.JSX.Element;
|
|
44
54
|
export type OverlaySide = "top" | "right" | "bottom" | "left";
|
|
45
|
-
export declare function Tooltip({ children, content, side }: {
|
|
55
|
+
export declare function Tooltip({ children, content, side, arrow, delay, closeDelay }: {
|
|
46
56
|
children: ReactElement;
|
|
47
57
|
content: ReactNode;
|
|
48
58
|
side?: OverlaySide;
|
|
59
|
+
arrow?: boolean;
|
|
60
|
+
delay?: number;
|
|
61
|
+
closeDelay?: number;
|
|
49
62
|
}): React.JSX.Element;
|
|
50
|
-
export declare function Popover({ trigger, title, children, side }: {
|
|
63
|
+
export declare function Popover({ trigger, title, children, side, arrow }: {
|
|
51
64
|
trigger: ReactElement;
|
|
52
65
|
title?: ReactNode;
|
|
53
66
|
children: ReactNode;
|
|
54
67
|
side?: OverlaySide;
|
|
68
|
+
arrow?: boolean;
|
|
55
69
|
}): React.JSX.Element;
|
|
56
70
|
export declare function HoverCard({ trigger, children, side }: {
|
|
57
71
|
trigger: ReactElement;
|