reactigoded 1.0.0-beta.26
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/CHANGELOG.md +3001 -0
- package/LICENSE +21 -0
- package/README.md +556 -0
- package/dist/Toast-FZUdYH1L.js +594 -0
- package/dist/cn.js +7 -0
- package/dist/components/Accordion/Accordion.d.ts +49 -0
- package/dist/components/Accordion/AccordionContent.d.ts +15 -0
- package/dist/components/Accordion/AccordionContext.d.ts +59 -0
- package/dist/components/Accordion/AccordionHeader.d.ts +22 -0
- package/dist/components/Accordion/AccordionItem.d.ts +11 -0
- package/dist/components/Accordion/index.d.ts +8 -0
- package/dist/components/Alert/Alert.d.ts +39 -0
- package/dist/components/Alert/index.d.ts +2 -0
- package/dist/components/AlertDialog/AlertDialogClose.d.ts +64 -0
- package/dist/components/AlertDialog/AlertDialogContent.d.ts +58 -0
- package/dist/components/AlertDialog/index.d.ts +14 -0
- package/dist/components/Avatar/Avatar.d.ts +62 -0
- package/dist/components/Avatar/AvatarGroup.d.ts +13 -0
- package/dist/components/Avatar/index.d.ts +4 -0
- package/dist/components/Badge/Badge.d.ts +33 -0
- package/dist/components/Badge/index.d.ts +2 -0
- package/dist/components/Breadcrumb/Breadcrumb.d.ts +14 -0
- package/dist/components/Breadcrumb/BreadcrumbItem.d.ts +21 -0
- package/dist/components/Breadcrumb/index.d.ts +4 -0
- package/dist/components/Button/Button.d.ts +61 -0
- package/dist/components/Button/IconButton.d.ts +48 -0
- package/dist/components/Button/index.d.ts +4 -0
- package/dist/components/Card/Card.d.ts +79 -0
- package/dist/components/Card/CardBody.d.ts +8 -0
- package/dist/components/Card/CardDivider.d.ts +8 -0
- package/dist/components/Card/CardFooter.d.ts +8 -0
- package/dist/components/Card/CardHeader.d.ts +8 -0
- package/dist/components/Card/CardImage.d.ts +15 -0
- package/dist/components/Card/index.d.ts +12 -0
- package/dist/components/Checkbox/Checkbox.d.ts +47 -0
- package/dist/components/Checkbox/index.d.ts +2 -0
- package/dist/components/Chip/Chip.d.ts +38 -0
- package/dist/components/Chip/index.d.ts +2 -0
- package/dist/components/Dialog/Dialog.d.ts +80 -0
- package/dist/components/Dialog/DialogBody.d.ts +8 -0
- package/dist/components/Dialog/DialogClose.d.ts +61 -0
- package/dist/components/Dialog/DialogContent.d.ts +36 -0
- package/dist/components/Dialog/DialogContext.d.ts +1 -0
- package/dist/components/Dialog/DialogFooter.d.ts +8 -0
- package/dist/components/Dialog/DialogHeader.d.ts +13 -0
- package/dist/components/Dialog/DialogTrigger.d.ts +44 -0
- package/dist/components/Dialog/index.d.ts +16 -0
- package/dist/components/Divider/Divider.d.ts +34 -0
- package/dist/components/Divider/index.d.ts +2 -0
- package/dist/components/Input/ErrorText.d.ts +13 -0
- package/dist/components/Input/Helper.d.ts +11 -0
- package/dist/components/Input/Input.d.ts +35 -0
- package/dist/components/Input/InputAddon.d.ts +8 -0
- package/dist/components/Input/InputGroup.d.ts +17 -0
- package/dist/components/Input/Label.d.ts +12 -0
- package/dist/components/Input/index.d.ts +12 -0
- package/dist/components/NativeSelect/NativeSelect.d.ts +41 -0
- package/dist/components/NativeSelect/index.d.ts +2 -0
- package/dist/components/Navbar/Navbar.d.ts +46 -0
- package/dist/components/Navbar/NavbarActions.d.ts +10 -0
- package/dist/components/Navbar/NavbarLink.d.ts +13 -0
- package/dist/components/Navbar/NavbarLogo.d.ts +22 -0
- package/dist/components/Navbar/NavbarMenuButton.d.ts +15 -0
- package/dist/components/Navbar/NavbarNav.d.ts +14 -0
- package/dist/components/Navbar/index.d.ts +12 -0
- package/dist/components/Pagination/Pagination.d.ts +77 -0
- package/dist/components/Pagination/index.d.ts +2 -0
- package/dist/components/Progress/Progress.d.ts +63 -0
- package/dist/components/Progress/index.d.ts +2 -0
- package/dist/components/Radio/Radio.d.ts +28 -0
- package/dist/components/Radio/index.d.ts +2 -0
- package/dist/components/Rating/Rating.d.ts +85 -0
- package/dist/components/Rating/index.d.ts +2 -0
- package/dist/components/Sidebar/Sidebar.d.ts +28 -0
- package/dist/components/Sidebar/SidebarContext.d.ts +32 -0
- package/dist/components/Sidebar/SidebarDivider.d.ts +8 -0
- package/dist/components/Sidebar/SidebarFooter.d.ts +8 -0
- package/dist/components/Sidebar/SidebarHeader.d.ts +13 -0
- package/dist/components/Sidebar/SidebarItem.d.ts +42 -0
- package/dist/components/Sidebar/SidebarNav.d.ts +13 -0
- package/dist/components/Sidebar/SidebarSection.d.ts +11 -0
- package/dist/components/Sidebar/SidebarToggle.d.ts +17 -0
- package/dist/components/Sidebar/index.d.ts +16 -0
- package/dist/components/Skeleton/Skeleton.d.ts +60 -0
- package/dist/components/Skeleton/index.d.ts +2 -0
- package/dist/components/Slider/Slider.d.ts +44 -0
- package/dist/components/Slider/index.d.ts +2 -0
- package/dist/components/Slot/Slot.d.ts +1 -0
- package/dist/components/Slot/composeEventHandlers.d.ts +1 -0
- package/dist/components/Slot/composeRefs.d.ts +1 -0
- package/dist/components/Slot/index.d.ts +3 -0
- package/dist/components/Spinner/Spinner.d.ts +31 -0
- package/dist/components/Spinner/index.d.ts +2 -0
- package/dist/components/Stepper/Step.d.ts +17 -0
- package/dist/components/Stepper/Stepper.d.ts +97 -0
- package/dist/components/Stepper/index.d.ts +4 -0
- package/dist/components/Switch/Switch.d.ts +53 -0
- package/dist/components/Switch/index.d.ts +2 -0
- package/dist/components/Table/Table.d.ts +74 -0
- package/dist/components/Table/index.d.ts +2 -0
- package/dist/components/Tabs/Tabs.d.ts +41 -0
- package/dist/components/Tabs/TabsContent.d.ts +15 -0
- package/dist/components/Tabs/TabsContext.d.ts +61 -0
- package/dist/components/Tabs/TabsList.d.ts +10 -0
- package/dist/components/Tabs/TabsTrigger.d.ts +15 -0
- package/dist/components/Tabs/index.d.ts +8 -0
- package/dist/components/Textarea/Textarea.d.ts +51 -0
- package/dist/components/Textarea/index.d.ts +2 -0
- package/dist/components/ThemeToggle/ThemeToggle.d.ts +43 -0
- package/dist/components/ThemeToggle/index.d.ts +2 -0
- package/dist/components/Timeline/Timeline.d.ts +20 -0
- package/dist/components/Timeline/TimelineItem.d.ts +32 -0
- package/dist/components/Timeline/index.d.ts +4 -0
- package/dist/components/Toast/Toast.d.ts +47 -0
- package/dist/components/Toast/ToastContext.d.ts +93 -0
- package/dist/components/Toast/ToastProvider.d.ts +116 -0
- package/dist/components/Toast/index.d.ts +6 -0
- package/dist/components/floating/Menu/Menu.d.ts +67 -0
- package/dist/components/floating/Menu/MenuContent.d.ts +60 -0
- package/dist/components/floating/Menu/MenuContext.d.ts +78 -0
- package/dist/components/floating/Menu/MenuItem.d.ts +47 -0
- package/dist/components/floating/Menu/MenuLabel.d.ts +6 -0
- package/dist/components/floating/Menu/MenuSeparator.d.ts +6 -0
- package/dist/components/floating/Menu/MenuTrigger.d.ts +53 -0
- package/dist/components/floating/Menu/index.d.ts +12 -0
- package/dist/components/floating/Menu/menuSelectors.d.ts +15 -0
- package/dist/components/floating/Tooltip/Tooltip.d.ts +194 -0
- package/dist/components/floating/Tooltip/index.d.ts +2 -0
- package/dist/components/floating/index.d.ts +3 -0
- package/dist/components/floating/primitives/FloatingTreeRoot.d.ts +55 -0
- package/dist/components/floating/primitives/index.d.ts +2 -0
- package/dist/components/floating/primitives/useFloatingNode.d.ts +1 -0
- package/dist/components/index.d.ts +38 -0
- package/dist/hooks/useControllableState.d.ts +152 -0
- package/dist/hooks/useTheme.d.ts +44 -0
- package/dist/index.d.ts +36 -0
- package/dist/index.js +1843 -0
- package/dist/server-safe.d.ts +69 -0
- package/dist/server-safe.js +47 -0
- package/dist/styles/igoded-base.css +1 -0
- package/dist/styles/igoded-components.css +1 -0
- package/dist/styles/igoded-design.css +1 -0
- package/dist/styles/igoded-fonts.css +1 -0
- package/dist/styles/igoded-reset.css +1 -0
- package/dist/styles/igoded-state-css.css +1 -0
- package/dist/styles/igoded-tokens.css +1 -0
- package/dist/styles/index.css +3 -0
- package/dist/styles/state/active.css +1 -0
- package/dist/styles/state/checked.css +1 -0
- package/dist/styles/state/default.css +1 -0
- package/dist/styles/state/disabled.css +1 -0
- package/dist/styles/state/empty.css +1 -0
- package/dist/styles/state/first-child.css +1 -0
- package/dist/styles/state/first-of-type.css +1 -0
- package/dist/styles/state/focus-visible.css +1 -0
- package/dist/styles/state/focus-within.css +1 -0
- package/dist/styles/state/focus.css +1 -0
- package/dist/styles/state/group-hover.css +1 -0
- package/dist/styles/state/hover.css +1 -0
- package/dist/styles/state/in-range.css +1 -0
- package/dist/styles/state/indeterminate.css +1 -0
- package/dist/styles/state/invalid.css +1 -0
- package/dist/styles/state/last-child.css +1 -0
- package/dist/styles/state/last-of-type.css +1 -0
- package/dist/styles/state/nth-child.css +1 -0
- package/dist/styles/state/only-child.css +1 -0
- package/dist/styles/state/optional.css +1 -0
- package/dist/styles/state/other.css +1 -0
- package/dist/styles/state/out-of-range.css +1 -0
- package/dist/styles/state/placeholder-shown.css +1 -0
- package/dist/styles/state/read-only.css +1 -0
- package/dist/styles/state/read-write.css +1 -0
- package/dist/styles/state/required.css +1 -0
- package/dist/styles/state/target.css +1 -0
- package/dist/styles/state/valid.css +1 -0
- package/dist/utils/cn.d.ts +11 -0
- package/package.json +282 -0
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { Ref } from 'react';
|
|
2
|
+
import { SwitchProps } from '../Switch/index.js';
|
|
3
|
+
import { Theme } from '../../hooks/useTheme.js';
|
|
4
|
+
export interface ThemeToggleProps extends Omit<SwitchProps, "checked" | "defaultChecked" | "onChange" | "ref"> {
|
|
5
|
+
/** Tema actual (modo controlado). */
|
|
6
|
+
theme?: Theme | undefined;
|
|
7
|
+
/** Tema inicial (modo no controlado). Si se omite, se intenta leer storage. */
|
|
8
|
+
defaultTheme?: Theme | undefined;
|
|
9
|
+
/** Callback al cambiar de tema. */
|
|
10
|
+
onThemeChange?: ((theme: Theme) => void) | undefined;
|
|
11
|
+
/** Clave de localStorage donde se persiste el tema. `null` desactiva la persistencia. */
|
|
12
|
+
storageKey?: string | null | undefined;
|
|
13
|
+
/**
|
|
14
|
+
* Atributo donde se aplica el tema. Por defecto `data-theme` en `<html>`.
|
|
15
|
+
* Pasar `null` para no aplicar el tema al DOM (sólo dispara onThemeChange).
|
|
16
|
+
*/
|
|
17
|
+
attribute?: string | null | undefined;
|
|
18
|
+
/**
|
|
19
|
+
* Etiqueta del switch. Por defecto muestra "Dark" / "Light" según el modo.
|
|
20
|
+
* Si se proporciona como string fija, se usa siempre; si es función, recibe
|
|
21
|
+
* el tema actual y devuelve el nodo a renderizar.
|
|
22
|
+
*/
|
|
23
|
+
label?: React.ReactNode | ((theme: Theme) => React.ReactNode) | undefined;
|
|
24
|
+
ref?: Ref<HTMLInputElement> | undefined;
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* ThemeToggle — toggle de tema light/dark sobre el `Switch` del design system.
|
|
28
|
+
*
|
|
29
|
+
* SSR-safe: en el servidor renderiza el tema por defecto y en el cliente
|
|
30
|
+
* hidrata el valor desde `localStorage` (vía `useSyncExternalStore`). Persiste
|
|
31
|
+
* en `localStorage` bajo `storageKey` (default `"theme"`) y aplica el atributo
|
|
32
|
+
* `data-theme` a `<html>`. Soporta controlled (`theme` + `onThemeChange`) o
|
|
33
|
+
* uncontrolled (`defaultTheme`).
|
|
34
|
+
*
|
|
35
|
+
* Si la app necesita evitar el flash de tema incorrecto durante hidratación,
|
|
36
|
+
* inyecta en el `<head>` un script que aplique `data-theme` antes del paint.
|
|
37
|
+
*
|
|
38
|
+
* @example
|
|
39
|
+
* <ThemeToggle />
|
|
40
|
+
* <ThemeToggle defaultTheme="dark" label={(t) => t === "dark" ? "🌙" : "☀️"} />
|
|
41
|
+
* <ThemeToggle theme={theme} onThemeChange={setTheme} storageKey={null} />
|
|
42
|
+
*/
|
|
43
|
+
export declare function ThemeToggle({ theme: themeProp, defaultTheme, onThemeChange, storageKey, attribute, label, ref, ...rest }: ThemeToggleProps): import("react").JSX.Element;
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { HTMLAttributes, Ref } from 'react';
|
|
2
|
+
export interface TimelineProps extends HTMLAttributes<HTMLDivElement> {
|
|
3
|
+
ref?: Ref<HTMLDivElement> | undefined;
|
|
4
|
+
}
|
|
5
|
+
/**
|
|
6
|
+
* Timeline — lista vertical de eventos cronológicos.
|
|
7
|
+
*
|
|
8
|
+
* Compón con `TimelineItem`. Renderiza un contenedor con `role="list"` para
|
|
9
|
+
* que los lectores de pantalla anuncien la cantidad de elementos. Pasa
|
|
10
|
+
* `aria-label` para etiquetar la lista (i18n vía atributo HTML estándar).
|
|
11
|
+
*
|
|
12
|
+
* @example
|
|
13
|
+
* <Timeline aria-label="Historial">
|
|
14
|
+
* <TimelineItem date="15 Nov 2024" title="Lanzamiento" />
|
|
15
|
+
* <TimelineItem date="20 Dic 2024" title="Update" dotVariant="success" />
|
|
16
|
+
* </Timeline>
|
|
17
|
+
*
|
|
18
|
+
* @server-safe
|
|
19
|
+
*/
|
|
20
|
+
export declare function Timeline({ className, children, ref, ...rest }: TimelineProps): import("react").JSX.Element;
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { HTMLAttributes, ReactNode, Ref } from 'react';
|
|
2
|
+
export type TimelineDotVariant = "default" | "brand" | "secondary" | "success" | "warning" | "danger" | "info";
|
|
3
|
+
export interface TimelineItemProps extends Omit<HTMLAttributes<HTMLDivElement>, "title"> {
|
|
4
|
+
/** Fecha o etiqueta temporal del evento. */
|
|
5
|
+
date?: ReactNode | undefined;
|
|
6
|
+
/** Título del evento. */
|
|
7
|
+
title?: ReactNode | undefined;
|
|
8
|
+
/** Descripción del evento. */
|
|
9
|
+
description?: ReactNode | undefined;
|
|
10
|
+
/** Variante de color del punto del timeline. */
|
|
11
|
+
dotVariant?: TimelineDotVariant | undefined;
|
|
12
|
+
/**
|
|
13
|
+
* Contenido custom del punto (icono, número, etc.).
|
|
14
|
+
* Si se proporciona reemplaza el punto por defecto.
|
|
15
|
+
*/
|
|
16
|
+
dotContent?: ReactNode | undefined;
|
|
17
|
+
/**
|
|
18
|
+
* Si se proporciona, sustituye el contenido renderizado por defecto
|
|
19
|
+
* (date/title/description). Útil para layouts ricos.
|
|
20
|
+
*/
|
|
21
|
+
children?: ReactNode | undefined;
|
|
22
|
+
ref?: Ref<HTMLDivElement> | undefined;
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* TimelineItem — un evento dentro de un Timeline.
|
|
26
|
+
*
|
|
27
|
+
* Por defecto renderiza el patrón `date` + `title` + `description`. Si se
|
|
28
|
+
* pasan children, se usan en lugar del contenido por defecto.
|
|
29
|
+
*
|
|
30
|
+
* @server-safe
|
|
31
|
+
*/
|
|
32
|
+
export declare function TimelineItem({ className, date, title, description, dotVariant, dotContent, children, ref, ...rest }: TimelineItemProps): import("react").JSX.Element;
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { HTMLAttributes, ReactNode, Ref } from 'react';
|
|
2
|
+
export type ToastVariant = "neutral" | "success" | "warning" | "danger" | "info" | "brand" | "secondary";
|
|
3
|
+
export interface ToastProps extends Omit<HTMLAttributes<HTMLDivElement>, "title"> {
|
|
4
|
+
/** Color/semántica del toast. Por defecto `"neutral"` (sin border-left coloreado). */
|
|
5
|
+
variant?: ToastVariant | undefined;
|
|
6
|
+
/** Título destacado en la parte superior. */
|
|
7
|
+
title?: ReactNode | undefined;
|
|
8
|
+
/** Mensaje secundario (también acepta `children`). */
|
|
9
|
+
message?: ReactNode | undefined;
|
|
10
|
+
/**
|
|
11
|
+
* Icono al inicio. `undefined` muestra el icono por defecto del variant
|
|
12
|
+
* (excepto "neutral", que no tiene). Pasa `false` para ocultarlo o un nodo
|
|
13
|
+
* propio para sustituirlo.
|
|
14
|
+
*/
|
|
15
|
+
icon?: ReactNode | false | undefined;
|
|
16
|
+
/** Si se muestra el botón "×". Alias estandarizado con `Alert`. */
|
|
17
|
+
dismissible?: boolean | undefined;
|
|
18
|
+
/** Callback al pulsar el botón "×". */
|
|
19
|
+
onClose?: (() => void) | undefined;
|
|
20
|
+
/** Texto a11y para el botón de cerrar. Por defecto `"Cerrar"`. */
|
|
21
|
+
closeLabel?: string | undefined;
|
|
22
|
+
ref?: Ref<HTMLDivElement> | undefined;
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Toast — notificación efímera presentational.
|
|
26
|
+
*
|
|
27
|
+
* Variants `danger`/`warning` se anuncian con `role="alert"` (assertive); el
|
|
28
|
+
* resto con `role="status"` + `aria-live="polite"`. Para el patrón habitual
|
|
29
|
+
* (cola de toasts con auto-dismiss) usa `ToastProvider` + `useToast()`.
|
|
30
|
+
*
|
|
31
|
+
* @example
|
|
32
|
+
* <ToastProvider position="bottom-right">
|
|
33
|
+
* <App />
|
|
34
|
+
* </ToastProvider>
|
|
35
|
+
*
|
|
36
|
+
* function SaveButton() {
|
|
37
|
+
* const { toast } = useToast();
|
|
38
|
+
* return (
|
|
39
|
+
* <Button onClick={() => toast({ variant: "success", title: "Guardado" })}>
|
|
40
|
+
* Guardar
|
|
41
|
+
* </Button>
|
|
42
|
+
* );
|
|
43
|
+
* }
|
|
44
|
+
*
|
|
45
|
+
* @server-safe
|
|
46
|
+
*/
|
|
47
|
+
export declare function Toast({ variant, title, message, icon, dismissible, onClose, closeLabel, className, children, ref, ...rest }: ToastProps): import("react").JSX.Element;
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
import { ReactNode } from 'react';
|
|
2
|
+
import { ToastVariant } from './Toast.js';
|
|
3
|
+
export interface ToastOptions {
|
|
4
|
+
/** Título del toast. */
|
|
5
|
+
title?: ReactNode | undefined;
|
|
6
|
+
/** Mensaje secundario. */
|
|
7
|
+
message?: ReactNode | undefined;
|
|
8
|
+
/** Variant semántico. Por defecto `"neutral"`. */
|
|
9
|
+
variant?: ToastVariant | undefined;
|
|
10
|
+
/**
|
|
11
|
+
* Tiempo en ms hasta auto-dismiss. `0` desactiva el auto-dismiss (queda
|
|
12
|
+
* hasta que se cierre manualmente). Por defecto `5000`.
|
|
13
|
+
*/
|
|
14
|
+
duration?: number | undefined;
|
|
15
|
+
/** Override del icono del toast. `false` lo oculta. */
|
|
16
|
+
icon?: ReactNode | false | undefined;
|
|
17
|
+
/** Si el toast muestra botón "×". Por defecto `true`. */
|
|
18
|
+
dismissible?: boolean | undefined;
|
|
19
|
+
/** Callback al cerrar (manual o auto). */
|
|
20
|
+
onDismiss?: (() => void) | undefined;
|
|
21
|
+
}
|
|
22
|
+
export interface ToastEntry extends ToastOptions {
|
|
23
|
+
id: string;
|
|
24
|
+
}
|
|
25
|
+
export interface ToastContextValue {
|
|
26
|
+
/** Crea un toast y devuelve su id. */
|
|
27
|
+
toast: (options: ToastOptions) => string;
|
|
28
|
+
/** Cierra un toast por id. */
|
|
29
|
+
dismiss: (id: string) => void;
|
|
30
|
+
/** Cierra todos los toasts. */
|
|
31
|
+
dismissAll: () => void;
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* D11 (beta.24 gate review): alias canónico del return de
|
|
35
|
+
* `useToast()`. Convención DS-wide `Use{Name}Return` (cf.
|
|
36
|
+
* `UseThemeReturn`, `UseControllableStateReturn`). El interfaz
|
|
37
|
+
* underlying `ToastContextValue` queda exportado para consumers que
|
|
38
|
+
* necesitan tipar el shape del Provider en mocks o adapters, pero
|
|
39
|
+
* el nombre que el consumer tipea al destructurar `useToast()` es
|
|
40
|
+
* `UseToastReturn`.
|
|
41
|
+
*
|
|
42
|
+
* @public
|
|
43
|
+
*/
|
|
44
|
+
export type UseToastReturn = ToastContextValue;
|
|
45
|
+
export declare const ToastContext: import('react').Context<ToastContextValue | null>;
|
|
46
|
+
/**
|
|
47
|
+
* Hook para disparar toasts desde cualquier componente envuelto en un
|
|
48
|
+
* `<ToastProvider>`. Lanza error si se llama fuera del Provider — no
|
|
49
|
+
* intentes hacer try/catch del hook, monta el Provider en la raíz de tu
|
|
50
|
+
* app (igual que `<QueryClientProvider>` o similares).
|
|
51
|
+
*
|
|
52
|
+
* @example
|
|
53
|
+
* // En la raíz de tu app:
|
|
54
|
+
* <ToastProvider position="top-right" defaultDuration={5000}>
|
|
55
|
+
* <App />
|
|
56
|
+
* </ToastProvider>
|
|
57
|
+
*
|
|
58
|
+
* // En un componente hijo:
|
|
59
|
+
* function SaveButton() {
|
|
60
|
+
* const { toast } = useToast();
|
|
61
|
+
* return (
|
|
62
|
+
* <Button
|
|
63
|
+
* onClick={async () => {
|
|
64
|
+
* try {
|
|
65
|
+
* await save();
|
|
66
|
+
* toast({ variant: "success", title: "Guardado" });
|
|
67
|
+
* } catch (err) {
|
|
68
|
+
* toast({ variant: "danger", title: "Error", message: String(err) });
|
|
69
|
+
* }
|
|
70
|
+
* }}
|
|
71
|
+
* >
|
|
72
|
+
* Guardar
|
|
73
|
+
* </Button>
|
|
74
|
+
* );
|
|
75
|
+
* }
|
|
76
|
+
*
|
|
77
|
+
* @example
|
|
78
|
+
* // Dismiss programático (devuelve un id):
|
|
79
|
+
* function NotificationOnFlight() {
|
|
80
|
+
* const { toast, dismiss } = useToast();
|
|
81
|
+
* useEffect(() => {
|
|
82
|
+
* const id = toast({ variant: "info", title: "Subiendo…", duration: 0 });
|
|
83
|
+
* uploadFile().finally(() => { dismiss(id); });
|
|
84
|
+
* }, [toast, dismiss]);
|
|
85
|
+
* return null;
|
|
86
|
+
* }
|
|
87
|
+
*
|
|
88
|
+
* @returns `{ toast, dismiss, dismissAll }` — todas estables (memoizadas).
|
|
89
|
+
* @throws Error si se llama fuera de `<ToastProvider>`.
|
|
90
|
+
*
|
|
91
|
+
* @public
|
|
92
|
+
*/
|
|
93
|
+
export declare function useToast(): UseToastReturn;
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
import { ReactNode } from 'react';
|
|
2
|
+
import { ToastOptions } from './ToastContext.js';
|
|
3
|
+
export type ToastPosition = "top-right" | "top-left" | "bottom-right" | "bottom-left" | "top-center" | "bottom-center";
|
|
4
|
+
export interface ToastProviderProps {
|
|
5
|
+
/** Posición del contenedor. Por defecto `"top-right"`. */
|
|
6
|
+
position?: ToastPosition | undefined;
|
|
7
|
+
/** Duración por defecto en ms. Toasts individuales pueden sobrescribirla. Por defecto `5000`. */
|
|
8
|
+
defaultDuration?: number | undefined;
|
|
9
|
+
/**
|
|
10
|
+
* Target HTMLElement para `createPortal`. Default `document.body`.
|
|
11
|
+
* Pasa `null` para renderizar inline (útil en SSR o en tests sin
|
|
12
|
+
* portal).
|
|
13
|
+
*
|
|
14
|
+
* **Caso típico — Toast dentro de Dialog**: `<Dialog>` usa
|
|
15
|
+
* `<dialog>.showModal()` que crea un top-layer del browser. Si el
|
|
16
|
+
* portal del ToastProvider queda en `document.body`, los toasts
|
|
17
|
+
* aparecen *detrás* del backdrop del dialog (invisibles al usuario).
|
|
18
|
+
* Pasar el ref del dialog como container ancla el portal al top-layer
|
|
19
|
+
* y los toasts se renderizan visibles sobre el backdrop. Patrón
|
|
20
|
+
* canónico idéntico al de `Tooltip` y `MenuContent` (gate review H-04,
|
|
21
|
+
* decision C-02).
|
|
22
|
+
*
|
|
23
|
+
* Tipo más restrictivo que `Tooltip`/`MenuContent` (`HTMLElement` solo,
|
|
24
|
+
* no `RefObject`): `createPortal` de react-dom necesita el HTMLElement
|
|
25
|
+
* resuelto. El consumer pasa `ref.current` post-mount o usa
|
|
26
|
+
* `useLayoutEffect` para capturar el nodo. Floating UI (Tooltip/Menu)
|
|
27
|
+
* resuelve refs internamente; react-dom no.
|
|
28
|
+
*
|
|
29
|
+
* @example
|
|
30
|
+
* ```tsx
|
|
31
|
+
* function ConfirmDialog() {
|
|
32
|
+
* const dialogRef = useRef<HTMLDialogElement>(null);
|
|
33
|
+
* return (
|
|
34
|
+
* <Dialog ref={dialogRef} open onClose={...}>
|
|
35
|
+
* <DialogBody>
|
|
36
|
+
* <ToastProvider container={dialogRef.current}>
|
|
37
|
+
* <ConfirmFlow />
|
|
38
|
+
* </ToastProvider>
|
|
39
|
+
* </DialogBody>
|
|
40
|
+
* </Dialog>
|
|
41
|
+
* );
|
|
42
|
+
* }
|
|
43
|
+
* ```
|
|
44
|
+
*
|
|
45
|
+
* Ver `docs/decisions/C-02-modal-tooltip-portal.md` para el rationale
|
|
46
|
+
* completo del patrón manual (vs context-based) y los triggers de
|
|
47
|
+
* re-evaluación post-rc.1.
|
|
48
|
+
*/
|
|
49
|
+
container?: HTMLElement | null | undefined;
|
|
50
|
+
/**
|
|
51
|
+
* Número máximo de toasts visibles a la vez. Cuando se excede, el más
|
|
52
|
+
* antiguo se desmonta automáticamente (FIFO eviction) y se dispara su
|
|
53
|
+
* `onDismiss`. Por defecto sin límite (M-11 gate review). Útil para
|
|
54
|
+
* evitar spam visual en bucles de errores de red, validación masiva,
|
|
55
|
+
* etc.
|
|
56
|
+
*/
|
|
57
|
+
maxToasts?: number | undefined;
|
|
58
|
+
/**
|
|
59
|
+
* Función opcional que extrae una clave de identidad del toast. Si la
|
|
60
|
+
* clave de un toast nuevo coincide con una en cola, el nuevo se ignora
|
|
61
|
+
* y `toast()` devuelve el id del existente (M-11 gate review).
|
|
62
|
+
*
|
|
63
|
+
* Por defecto sin dedupe (cada llamada crea un toast nuevo). Patrón
|
|
64
|
+
* típico:
|
|
65
|
+
*
|
|
66
|
+
* ```tsx
|
|
67
|
+
* <ToastProvider dedupeBy={(t) => `${t.variant}:${t.title}`}>
|
|
68
|
+
* ```
|
|
69
|
+
*
|
|
70
|
+
* Aplica solo en el momento de la inserción — toasts ya en cola no se
|
|
71
|
+
* fusionan retroactivamente si `dedupeBy` cambia.
|
|
72
|
+
*/
|
|
73
|
+
dedupeBy?: ((toast: ToastOptions) => string) | undefined;
|
|
74
|
+
children?: ReactNode | undefined;
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* ToastProvider — pone `useToast()` a disposición y renderiza la cola de
|
|
78
|
+
* toasts en un portal fixed con la posición elegida. Cada toast se
|
|
79
|
+
* auto-dismisea a los `duration` ms (o `defaultDuration` del provider).
|
|
80
|
+
*
|
|
81
|
+
* **Patrón canónico (single-instance global)**: un solo provider en la
|
|
82
|
+
* raíz de la app, una sola posición, una sola cola. Patrón recomendado
|
|
83
|
+
* para el 95% de los casos:
|
|
84
|
+
*
|
|
85
|
+
* ```tsx
|
|
86
|
+
* <ToastProvider position="top-right">
|
|
87
|
+
* <Routes />
|
|
88
|
+
* </ToastProvider>
|
|
89
|
+
* ```
|
|
90
|
+
*
|
|
91
|
+
* **Multi-instance (workaround C-06 gate review)**: si necesitas emitir
|
|
92
|
+
* a posiciones distintas según el sub-árbol (ej: errores críticos en
|
|
93
|
+
* `bottom-center`, notificaciones en `top-right`), anida providers con
|
|
94
|
+
* scopes geográficos. `useToast()` siempre se conecta al ancestro
|
|
95
|
+
* `ToastProvider` más cercano vía Context — el provider más interno
|
|
96
|
+
* sobreescribe al externo dentro de su sub-árbol.
|
|
97
|
+
*
|
|
98
|
+
* ```tsx
|
|
99
|
+
* <ToastProvider position="top-right"> // Notifications scope
|
|
100
|
+
* <Routes>
|
|
101
|
+
* <Route path="/critical-flow" element={
|
|
102
|
+
* <ToastProvider position="bottom-center"> // Errors scope
|
|
103
|
+
* <CriticalFlow />
|
|
104
|
+
* </ToastProvider>
|
|
105
|
+
* } />
|
|
106
|
+
* </Routes>
|
|
107
|
+
* </ToastProvider>
|
|
108
|
+
* ```
|
|
109
|
+
*
|
|
110
|
+
* Limitación conocida: dentro de un sub-árbol gana un solo provider.
|
|
111
|
+
* Para mezclar tipos (errores + notificaciones) en el mismo sub-árbol
|
|
112
|
+
* hay que refactorizar el layout. API con `scope` nombrado evaluada
|
|
113
|
+
* para 1.1.0+ si emerge demanda real. Ver
|
|
114
|
+
* `docs/decisions/C-06-toast-multi-instance.md`.
|
|
115
|
+
*/
|
|
116
|
+
export declare function ToastProvider({ position, defaultDuration, container, maxToasts, dedupeBy, children, }: ToastProviderProps): import("react").JSX.Element;
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
export { Toast } from './Toast.js';
|
|
2
|
+
export type { ToastProps, ToastVariant } from './Toast.js';
|
|
3
|
+
export { ToastProvider } from './ToastProvider.js';
|
|
4
|
+
export type { ToastProviderProps, ToastPosition } from './ToastProvider.js';
|
|
5
|
+
export { useToast } from './ToastContext.js';
|
|
6
|
+
export type { ToastOptions, ToastEntry, ToastContextValue, UseToastReturn, } from './ToastContext.js';
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import { HTMLAttributes, Ref } from 'react';
|
|
2
|
+
export type MenuAlign = "left" | "right";
|
|
3
|
+
export type MenuDirection = "down" | "up";
|
|
4
|
+
export interface MenuProps extends HTMLAttributes<HTMLDivElement> {
|
|
5
|
+
/** Estado abierto (modo controlado). Si se omite, el componente gestiona su propio estado. */
|
|
6
|
+
open?: boolean | undefined;
|
|
7
|
+
/** Estado inicial (modo no controlado). Por defecto `false`. */
|
|
8
|
+
defaultOpen?: boolean | undefined;
|
|
9
|
+
/** Callback al abrir/cerrar. Disparado en ambos modos. */
|
|
10
|
+
onOpenChange?: ((open: boolean) => void) | undefined;
|
|
11
|
+
/** Alineación horizontal del menu. Por defecto `"left"`. */
|
|
12
|
+
placement?: MenuAlign | undefined;
|
|
13
|
+
/** Hacia dónde abre verticalmente. Por defecto `"down"`. */
|
|
14
|
+
direction?: MenuDirection | undefined;
|
|
15
|
+
/** Si los `MenuItem` cierran el menu al activarse. Por defecto `true`. */
|
|
16
|
+
closeOnSelect?: boolean | undefined;
|
|
17
|
+
ref?: Ref<HTMLDivElement> | undefined;
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Menu — menú desplegable accesible.
|
|
21
|
+
*
|
|
22
|
+
* Compón con `MenuTrigger`, `MenuContent`, `MenuItem`,
|
|
23
|
+
* `MenuSeparator`, `MenuLabel`. Cierra con ESC y al hacer click fuera;
|
|
24
|
+
* soporta navegación con ↑/↓/Home/End/Enter/Espacio + typeahead (foco
|
|
25
|
+
* por primera letra) siguiendo el patrón WAI-ARIA APG menu-button.
|
|
26
|
+
*
|
|
27
|
+
* **C-03 (RC1)**: migración a `@floating-ui/react` sobre la capa
|
|
28
|
+
* `floating/primitives/` (compartida con Tooltip + futuros Popover/
|
|
29
|
+
* HoverCard). Reemplaza ~600 LOC hand-rolled de outside-click/escape/
|
|
30
|
+
* arrow-keys por hooks composables FUI con APG menu pattern completo:
|
|
31
|
+
*
|
|
32
|
+
* - `useListNavigation`: flechas + Home/End + loop.
|
|
33
|
+
* - `useTypeahead`: focus por primera letra (APG menu).
|
|
34
|
+
* - `useDismiss({ bubbles.escapeKey: true })`: cascade dismiss vía
|
|
35
|
+
* `<FloatingTreeRoot>` opt-in (cierra ancestros registrados).
|
|
36
|
+
* - `useFloatingNode`: registro en el tree para anidación.
|
|
37
|
+
* - `<FloatingFocusManager>`: focus trap + return al trigger al cerrar.
|
|
38
|
+
*
|
|
39
|
+
* **Positioning**: FUI completo desde D2/beta.24. `MenuContent` se monta
|
|
40
|
+
* en `<FloatingPortal>` y aplica `floatingStyles` inline con
|
|
41
|
+
* `flip`/`shift`/`offset`; además expone `data-side`/`data-align` para
|
|
42
|
+
* hooks CSS de animación o edge styling. El wrapper `.ig-menu` conserva
|
|
43
|
+
* solo el trigger/contexto, no posiciona ni muestra el content.
|
|
44
|
+
*
|
|
45
|
+
* Modo controlado: pasa `open` + `onOpenChange`. Modo no controlado: omite `open`.
|
|
46
|
+
*
|
|
47
|
+
* @example
|
|
48
|
+
* <Menu>
|
|
49
|
+
* <MenuTrigger>Acciones ▼</MenuTrigger>
|
|
50
|
+
* <MenuContent>
|
|
51
|
+
* <MenuItem onClick={editar}>Editar</MenuItem>
|
|
52
|
+
* <MenuSeparator />
|
|
53
|
+
* <MenuItem danger onClick={borrar}>Eliminar</MenuItem>
|
|
54
|
+
* </MenuContent>
|
|
55
|
+
* </Menu>
|
|
56
|
+
*
|
|
57
|
+
* @example // cascade dismiss con FloatingTreeRoot (Menu dentro de Dialog)
|
|
58
|
+
* <FloatingTreeRoot>
|
|
59
|
+
* <Dialog open>
|
|
60
|
+
* <Menu>
|
|
61
|
+
* <MenuTrigger>...</MenuTrigger>
|
|
62
|
+
* <MenuContent>...</MenuContent>
|
|
63
|
+
* </Menu>
|
|
64
|
+
* </Dialog>
|
|
65
|
+
* </FloatingTreeRoot>
|
|
66
|
+
*/
|
|
67
|
+
export declare function Menu({ open: openProp, defaultOpen, onOpenChange, placement, direction, closeOnSelect, className, children, ref, ...rest }: MenuProps): import("react").JSX.Element;
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import { HTMLAttributes, Ref, RefObject } from 'react';
|
|
2
|
+
export interface MenuContentProps extends HTMLAttributes<HTMLDivElement> {
|
|
3
|
+
ref?: Ref<HTMLDivElement> | undefined;
|
|
4
|
+
/**
|
|
5
|
+
* **D2 + H-04 paralelo (RC1 gate review beta.24)**: target HTMLElement
|
|
6
|
+
* para el `<FloatingPortal>`. Default `document.body`.
|
|
7
|
+
*
|
|
8
|
+
* **Caso típico — Menu dentro de Dialog**: `<Dialog>` usa
|
|
9
|
+
* `<dialog>.showModal()` que crea un top-layer del browser. Si el
|
|
10
|
+
* portal del Menu queda en `document.body`, aparece *detrás* del
|
|
11
|
+
* backdrop del dialog (invisible al usuario). Pasar el ref del
|
|
12
|
+
* dialog como container ancla el portal al top-layer del dialog y
|
|
13
|
+
* el menu se renderiza visible sobre el backdrop. Patrón canónico
|
|
14
|
+
* idéntico al de Tooltip (gate review H-04, decision C-02).
|
|
15
|
+
*
|
|
16
|
+
* Acepta `HTMLElement` directo o un `RefObject` (Floating UI resuelve
|
|
17
|
+
* ambos).
|
|
18
|
+
*/
|
|
19
|
+
container?: HTMLElement | RefObject<HTMLElement | null> | null | undefined;
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* MenuContent — contenedor `role="menu"` para los items, renderizado
|
|
23
|
+
* en `<FloatingPortal>` con positioning automático via FUI flip+shift+offset.
|
|
24
|
+
*
|
|
25
|
+
* **D2 (RC1 gate review beta.24)**: full FUI portal real. Pre-D2 (C-03):
|
|
26
|
+
* MenuContent renderizaba inline en árbol Menu padre + CSS-driven
|
|
27
|
+
* positioning via `.ig-menu-up`/`.ig-menu-right` modifier classes. flip
|
|
28
|
+
* middleware corría pero su output (placement resuelto) se descartaba.
|
|
29
|
+
* Resultado: overflow:hidden ancestor clipaba el menu + sin re-flip
|
|
30
|
+
* cuando estaba cerca del viewport edge.
|
|
31
|
+
*
|
|
32
|
+
* Post-D2:
|
|
33
|
+
* - `<FloatingPortal>` mueve MenuContent a `document.body` → escapa
|
|
34
|
+
* ancestor overflow:hidden.
|
|
35
|
+
* - `floatingStyles` inline (top/left/position) aplicados → flip/shift
|
|
36
|
+
* real visible.
|
|
37
|
+
* - `data-side="top|bottom|left|right"` + `data-align="start|end|center"`
|
|
38
|
+
* atributos expuestos para CSS hooks (animation origin, edge styles,
|
|
39
|
+
* etc.) — split Radix-style, no composite `data-placement`.
|
|
40
|
+
* - `data-state="open"` para CSS transitions / animation-in.
|
|
41
|
+
* - Unmount-on-close (return null cuando !open) — pre-D2 mantenía DOM
|
|
42
|
+
* con visibility:hidden + `:focus-within` JS-less fallback. Patrón
|
|
43
|
+
* eliminado: Menu pasa a JS-required (alineado con Tooltip/Dialog/
|
|
44
|
+
* Accordion). No mas CSS-only fallback.
|
|
45
|
+
*
|
|
46
|
+
* `<FloatingFocusManager modal={false} initialFocus={-1} returnFocus>`:
|
|
47
|
+
* - Trap inicial: `useListNavigation focusItemOnOpen:"auto"` foca primer/
|
|
48
|
+
* último item según tecla que abrió.
|
|
49
|
+
* - Return: al cerrar (Escape / outside click / Tab fuera), foco vuelve
|
|
50
|
+
* al trigger automáticamente.
|
|
51
|
+
*
|
|
52
|
+
* `<FloatingNode id={nodeId}>` wraps OUTSIDE portal (en el React tree)
|
|
53
|
+
* para que descendants registrados en FloatingTree propaguen cascade
|
|
54
|
+
* dismiss correctamente — el portal mueve DOM, no tree React.
|
|
55
|
+
*
|
|
56
|
+
* ARIA inyectada por `useRole({ role: "menu" })`:
|
|
57
|
+
* - `role="menu"`
|
|
58
|
+
* - `aria-labelledby={triggerId}` (vinculado al MenuTrigger)
|
|
59
|
+
*/
|
|
60
|
+
export declare function MenuContent({ className, children, ref, container, style: consumerStyle, ...rest }: MenuContentProps): import("react").JSX.Element | null;
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
import { CSSProperties, RefObject } from 'react';
|
|
2
|
+
import { FloatingContext, useFloating, useInteractions } from '@floating-ui/react';
|
|
3
|
+
export interface MenuContextValue {
|
|
4
|
+
/** Si el menú está visible. */
|
|
5
|
+
open: boolean;
|
|
6
|
+
/** Cambia visibilidad y dispara `onOpenChange`. */
|
|
7
|
+
setOpen: (next: boolean) => void;
|
|
8
|
+
/** ID del trigger (para `aria-labelledby` del menu). */
|
|
9
|
+
triggerId: string;
|
|
10
|
+
/** ID del menu (para `aria-controls` del trigger). */
|
|
11
|
+
menuId: string;
|
|
12
|
+
/** Si los items deben cerrar el menu al activarse. */
|
|
13
|
+
closeOnSelect: boolean;
|
|
14
|
+
/**
|
|
15
|
+
* Helpers de @floating-ui/react para inyectar handlers/refs/aria.
|
|
16
|
+
* `MenuTrigger`, `MenuContent` y `MenuItem` los consumen para
|
|
17
|
+
* mergear listeners del consumer con los de FUI sin pisarlos.
|
|
18
|
+
*
|
|
19
|
+
* C-03 (RC1): migración a Floating UI internals sobre la capa
|
|
20
|
+
* `floating/primitives/`. La API pública del Menu no cambia; este
|
|
21
|
+
* shape de context sí es nuevo y se considera **interno** (no se
|
|
22
|
+
* exporta desde el barrel del DS — B-04 confirmó).
|
|
23
|
+
*/
|
|
24
|
+
getReferenceProps: ReturnType<typeof useInteractions>["getReferenceProps"];
|
|
25
|
+
getFloatingProps: ReturnType<typeof useInteractions>["getFloatingProps"];
|
|
26
|
+
getItemProps: ReturnType<typeof useInteractions>["getItemProps"];
|
|
27
|
+
/** Refs de los items visibles, registrados por orden por `MenuItem`. */
|
|
28
|
+
listRef: RefObject<Array<HTMLElement | null>>;
|
|
29
|
+
/** Labels (texto plano) de los items para `useTypeahead`. */
|
|
30
|
+
labelsRef: RefObject<Array<string | null>>;
|
|
31
|
+
/** Index del item con focus virtual (roving). */
|
|
32
|
+
activeIndex: number | null;
|
|
33
|
+
/** Setter del index activo. */
|
|
34
|
+
setActiveIndex: (index: number | null) => void;
|
|
35
|
+
/** `setReference` para que `MenuTrigger` registre su elemento. */
|
|
36
|
+
setReference: ReturnType<typeof useFloating>["refs"]["setReference"];
|
|
37
|
+
/** `setFloating` para que `MenuContent` registre su elemento. */
|
|
38
|
+
setFloating: ReturnType<typeof useFloating>["refs"]["setFloating"];
|
|
39
|
+
/** Context FUI para `<FloatingFocusManager>` en MenuContent. */
|
|
40
|
+
context: FloatingContext;
|
|
41
|
+
/**
|
|
42
|
+
* D2 (RC1 gate review beta.24): `floatingStyles` inline (top/left/
|
|
43
|
+
* position) computado por `useFloating` con middleware flip+shift+offset
|
|
44
|
+
* aplicado. MenuContent los aplica via `style={floatingStyles}` en lugar
|
|
45
|
+
* de descartarlos como en C-03 (donde positioning era CSS-driven via
|
|
46
|
+
* `.ig-menu-up`/`.ig-menu-right` modifier classes). Combinado con
|
|
47
|
+
* data-side/data-align attributes, el consumer puede hookear estilos
|
|
48
|
+
* visuales (transform-origin, border-radius edge cases) por placement
|
|
49
|
+
* sin tocar geometría.
|
|
50
|
+
*/
|
|
51
|
+
floatingStyles: CSSProperties;
|
|
52
|
+
/** nodeId para envolver el content en `<FloatingNode>` (cascade dismiss). */
|
|
53
|
+
nodeId: string | undefined;
|
|
54
|
+
}
|
|
55
|
+
export declare const MenuContext: import('react').Context<MenuContextValue | null>;
|
|
56
|
+
/**
|
|
57
|
+
* Hook que expone el contexto de un `<Menu>` (open, setOpen, ids para
|
|
58
|
+
* `aria-controls`/`aria-labelledby`, closeOnSelect, y los `getReferenceProps`/
|
|
59
|
+
* `getFloatingProps`/`getItemProps` de Floating UI). Lo usan internamente
|
|
60
|
+
* `MenuTrigger`, `MenuContent` y `MenuItem`.
|
|
61
|
+
*
|
|
62
|
+
* También útil si construyes tu propio item custom o quieres cerrar el
|
|
63
|
+
* menu desde código en respuesta a algún evento externo.
|
|
64
|
+
*
|
|
65
|
+
* @example
|
|
66
|
+
* function CustomItem() {
|
|
67
|
+
* const { setOpen } = useMenu();
|
|
68
|
+
* const router = useRouter();
|
|
69
|
+
* return (
|
|
70
|
+
* <MenuItem onClick={() => { router.push("/perfil"); setOpen(false); }}>
|
|
71
|
+
* Ir a perfil
|
|
72
|
+
* </MenuItem>
|
|
73
|
+
* );
|
|
74
|
+
* }
|
|
75
|
+
*
|
|
76
|
+
* @throws Error si se usa fuera de `<Menu>`.
|
|
77
|
+
*/
|
|
78
|
+
export declare function useMenu(): MenuContextValue;
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { AnchorHTMLAttributes, ButtonHTMLAttributes, KeyboardEvent, MouseEvent, Ref } from 'react';
|
|
2
|
+
interface CommonProps {
|
|
3
|
+
/** Marca el item como acción destructiva (color malum). */
|
|
4
|
+
danger?: boolean | undefined;
|
|
5
|
+
/** Marca el item como seleccionado actualmente. */
|
|
6
|
+
active?: boolean | undefined;
|
|
7
|
+
}
|
|
8
|
+
type ItemMouseHandler = (e: MouseEvent<HTMLElement>) => void;
|
|
9
|
+
type ItemKeyboardHandler = (e: KeyboardEvent<HTMLElement>) => void;
|
|
10
|
+
type ButtonItemProps = CommonProps & Omit<ButtonHTMLAttributes<HTMLButtonElement>, "onClick" | "onKeyDown"> & {
|
|
11
|
+
href?: undefined;
|
|
12
|
+
onClick?: ItemMouseHandler | undefined;
|
|
13
|
+
onKeyDown?: ItemKeyboardHandler | undefined;
|
|
14
|
+
ref?: Ref<HTMLButtonElement> | undefined;
|
|
15
|
+
};
|
|
16
|
+
type AnchorItemProps = CommonProps & Omit<AnchorHTMLAttributes<HTMLAnchorElement>, "onClick" | "onKeyDown"> & {
|
|
17
|
+
href: string;
|
|
18
|
+
onClick?: ItemMouseHandler | undefined;
|
|
19
|
+
onKeyDown?: ItemKeyboardHandler | undefined;
|
|
20
|
+
ref?: Ref<HTMLAnchorElement> | undefined;
|
|
21
|
+
};
|
|
22
|
+
export type MenuItemProps = ButtonItemProps | AnchorItemProps;
|
|
23
|
+
/**
|
|
24
|
+
* MenuItem — entrada del menú con `role="menuitem"`.
|
|
25
|
+
*
|
|
26
|
+
* Si recibe `href` renderiza un `<a>`, si no un `<button>`. Cierra el menu
|
|
27
|
+
* al activarse cuando `Menu.closeOnSelect` está activo (por defecto).
|
|
28
|
+
*
|
|
29
|
+
* **C-03 (RC1)**: navegación delegada a `useListNavigation` + `useTypeahead`
|
|
30
|
+
* de Floating UI sobre el primitive layer.
|
|
31
|
+
*
|
|
32
|
+
* **A11y APG menu**:
|
|
33
|
+
* - `role="menuitem"`.
|
|
34
|
+
* - `aria-disabled="true"` salta el item en flechas Y bloquea clicks.
|
|
35
|
+
* - Roving tabindex: `tabIndex={-1}` para todos.
|
|
36
|
+
*
|
|
37
|
+
* **H-19**: `<a>` sintetiza click en Space (Enter ya dispara click nativo).
|
|
38
|
+
*
|
|
39
|
+
* **Tipo de callbacks**: `onClick`/`onKeyDown` tipan `MouseEvent<HTMLElement>`
|
|
40
|
+
* / `KeyboardEvent<HTMLElement>` (no element-specific). Razón: alineación
|
|
41
|
+
* con la firma genuinamente común de ambos branches (`<a>` y `<button>`).
|
|
42
|
+
* Audit pre-RC1 verificó 0 consumers accediendo a `e.currentTarget.{href,
|
|
43
|
+
* disabled,...}` desde callbacks de MenuItem. Si un consumer hipotético lo
|
|
44
|
+
* necesita: narrowing manual con `instanceof`.
|
|
45
|
+
*/
|
|
46
|
+
export declare function MenuItem({ ref, ...props }: MenuItemProps): import("react").JSX.Element;
|
|
47
|
+
export type { ButtonItemProps, AnchorItemProps };
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { HTMLAttributes, Ref } from 'react';
|
|
2
|
+
export interface MenuLabelProps extends HTMLAttributes<HTMLDivElement> {
|
|
3
|
+
ref?: Ref<HTMLDivElement> | undefined;
|
|
4
|
+
}
|
|
5
|
+
/** MenuLabel — cabecera tipo etiqueta para agrupar items. */
|
|
6
|
+
export declare function MenuLabel({ className, children, ref, ...rest }: MenuLabelProps): import("react").JSX.Element;
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { HTMLAttributes, Ref } from 'react';
|
|
2
|
+
export interface MenuSeparatorProps extends HTMLAttributes<HTMLDivElement> {
|
|
3
|
+
ref?: Ref<HTMLDivElement> | undefined;
|
|
4
|
+
}
|
|
5
|
+
/** MenuSeparator — separador horizontal entre grupos de items. */
|
|
6
|
+
export declare function MenuSeparator({ className, ref, ...rest }: MenuSeparatorProps): import("react").JSX.Element;
|