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.
Files changed (177) hide show
  1. package/CHANGELOG.md +3001 -0
  2. package/LICENSE +21 -0
  3. package/README.md +556 -0
  4. package/dist/Toast-FZUdYH1L.js +594 -0
  5. package/dist/cn.js +7 -0
  6. package/dist/components/Accordion/Accordion.d.ts +49 -0
  7. package/dist/components/Accordion/AccordionContent.d.ts +15 -0
  8. package/dist/components/Accordion/AccordionContext.d.ts +59 -0
  9. package/dist/components/Accordion/AccordionHeader.d.ts +22 -0
  10. package/dist/components/Accordion/AccordionItem.d.ts +11 -0
  11. package/dist/components/Accordion/index.d.ts +8 -0
  12. package/dist/components/Alert/Alert.d.ts +39 -0
  13. package/dist/components/Alert/index.d.ts +2 -0
  14. package/dist/components/AlertDialog/AlertDialogClose.d.ts +64 -0
  15. package/dist/components/AlertDialog/AlertDialogContent.d.ts +58 -0
  16. package/dist/components/AlertDialog/index.d.ts +14 -0
  17. package/dist/components/Avatar/Avatar.d.ts +62 -0
  18. package/dist/components/Avatar/AvatarGroup.d.ts +13 -0
  19. package/dist/components/Avatar/index.d.ts +4 -0
  20. package/dist/components/Badge/Badge.d.ts +33 -0
  21. package/dist/components/Badge/index.d.ts +2 -0
  22. package/dist/components/Breadcrumb/Breadcrumb.d.ts +14 -0
  23. package/dist/components/Breadcrumb/BreadcrumbItem.d.ts +21 -0
  24. package/dist/components/Breadcrumb/index.d.ts +4 -0
  25. package/dist/components/Button/Button.d.ts +61 -0
  26. package/dist/components/Button/IconButton.d.ts +48 -0
  27. package/dist/components/Button/index.d.ts +4 -0
  28. package/dist/components/Card/Card.d.ts +79 -0
  29. package/dist/components/Card/CardBody.d.ts +8 -0
  30. package/dist/components/Card/CardDivider.d.ts +8 -0
  31. package/dist/components/Card/CardFooter.d.ts +8 -0
  32. package/dist/components/Card/CardHeader.d.ts +8 -0
  33. package/dist/components/Card/CardImage.d.ts +15 -0
  34. package/dist/components/Card/index.d.ts +12 -0
  35. package/dist/components/Checkbox/Checkbox.d.ts +47 -0
  36. package/dist/components/Checkbox/index.d.ts +2 -0
  37. package/dist/components/Chip/Chip.d.ts +38 -0
  38. package/dist/components/Chip/index.d.ts +2 -0
  39. package/dist/components/Dialog/Dialog.d.ts +80 -0
  40. package/dist/components/Dialog/DialogBody.d.ts +8 -0
  41. package/dist/components/Dialog/DialogClose.d.ts +61 -0
  42. package/dist/components/Dialog/DialogContent.d.ts +36 -0
  43. package/dist/components/Dialog/DialogContext.d.ts +1 -0
  44. package/dist/components/Dialog/DialogFooter.d.ts +8 -0
  45. package/dist/components/Dialog/DialogHeader.d.ts +13 -0
  46. package/dist/components/Dialog/DialogTrigger.d.ts +44 -0
  47. package/dist/components/Dialog/index.d.ts +16 -0
  48. package/dist/components/Divider/Divider.d.ts +34 -0
  49. package/dist/components/Divider/index.d.ts +2 -0
  50. package/dist/components/Input/ErrorText.d.ts +13 -0
  51. package/dist/components/Input/Helper.d.ts +11 -0
  52. package/dist/components/Input/Input.d.ts +35 -0
  53. package/dist/components/Input/InputAddon.d.ts +8 -0
  54. package/dist/components/Input/InputGroup.d.ts +17 -0
  55. package/dist/components/Input/Label.d.ts +12 -0
  56. package/dist/components/Input/index.d.ts +12 -0
  57. package/dist/components/NativeSelect/NativeSelect.d.ts +41 -0
  58. package/dist/components/NativeSelect/index.d.ts +2 -0
  59. package/dist/components/Navbar/Navbar.d.ts +46 -0
  60. package/dist/components/Navbar/NavbarActions.d.ts +10 -0
  61. package/dist/components/Navbar/NavbarLink.d.ts +13 -0
  62. package/dist/components/Navbar/NavbarLogo.d.ts +22 -0
  63. package/dist/components/Navbar/NavbarMenuButton.d.ts +15 -0
  64. package/dist/components/Navbar/NavbarNav.d.ts +14 -0
  65. package/dist/components/Navbar/index.d.ts +12 -0
  66. package/dist/components/Pagination/Pagination.d.ts +77 -0
  67. package/dist/components/Pagination/index.d.ts +2 -0
  68. package/dist/components/Progress/Progress.d.ts +63 -0
  69. package/dist/components/Progress/index.d.ts +2 -0
  70. package/dist/components/Radio/Radio.d.ts +28 -0
  71. package/dist/components/Radio/index.d.ts +2 -0
  72. package/dist/components/Rating/Rating.d.ts +85 -0
  73. package/dist/components/Rating/index.d.ts +2 -0
  74. package/dist/components/Sidebar/Sidebar.d.ts +28 -0
  75. package/dist/components/Sidebar/SidebarContext.d.ts +32 -0
  76. package/dist/components/Sidebar/SidebarDivider.d.ts +8 -0
  77. package/dist/components/Sidebar/SidebarFooter.d.ts +8 -0
  78. package/dist/components/Sidebar/SidebarHeader.d.ts +13 -0
  79. package/dist/components/Sidebar/SidebarItem.d.ts +42 -0
  80. package/dist/components/Sidebar/SidebarNav.d.ts +13 -0
  81. package/dist/components/Sidebar/SidebarSection.d.ts +11 -0
  82. package/dist/components/Sidebar/SidebarToggle.d.ts +17 -0
  83. package/dist/components/Sidebar/index.d.ts +16 -0
  84. package/dist/components/Skeleton/Skeleton.d.ts +60 -0
  85. package/dist/components/Skeleton/index.d.ts +2 -0
  86. package/dist/components/Slider/Slider.d.ts +44 -0
  87. package/dist/components/Slider/index.d.ts +2 -0
  88. package/dist/components/Slot/Slot.d.ts +1 -0
  89. package/dist/components/Slot/composeEventHandlers.d.ts +1 -0
  90. package/dist/components/Slot/composeRefs.d.ts +1 -0
  91. package/dist/components/Slot/index.d.ts +3 -0
  92. package/dist/components/Spinner/Spinner.d.ts +31 -0
  93. package/dist/components/Spinner/index.d.ts +2 -0
  94. package/dist/components/Stepper/Step.d.ts +17 -0
  95. package/dist/components/Stepper/Stepper.d.ts +97 -0
  96. package/dist/components/Stepper/index.d.ts +4 -0
  97. package/dist/components/Switch/Switch.d.ts +53 -0
  98. package/dist/components/Switch/index.d.ts +2 -0
  99. package/dist/components/Table/Table.d.ts +74 -0
  100. package/dist/components/Table/index.d.ts +2 -0
  101. package/dist/components/Tabs/Tabs.d.ts +41 -0
  102. package/dist/components/Tabs/TabsContent.d.ts +15 -0
  103. package/dist/components/Tabs/TabsContext.d.ts +61 -0
  104. package/dist/components/Tabs/TabsList.d.ts +10 -0
  105. package/dist/components/Tabs/TabsTrigger.d.ts +15 -0
  106. package/dist/components/Tabs/index.d.ts +8 -0
  107. package/dist/components/Textarea/Textarea.d.ts +51 -0
  108. package/dist/components/Textarea/index.d.ts +2 -0
  109. package/dist/components/ThemeToggle/ThemeToggle.d.ts +43 -0
  110. package/dist/components/ThemeToggle/index.d.ts +2 -0
  111. package/dist/components/Timeline/Timeline.d.ts +20 -0
  112. package/dist/components/Timeline/TimelineItem.d.ts +32 -0
  113. package/dist/components/Timeline/index.d.ts +4 -0
  114. package/dist/components/Toast/Toast.d.ts +47 -0
  115. package/dist/components/Toast/ToastContext.d.ts +93 -0
  116. package/dist/components/Toast/ToastProvider.d.ts +116 -0
  117. package/dist/components/Toast/index.d.ts +6 -0
  118. package/dist/components/floating/Menu/Menu.d.ts +67 -0
  119. package/dist/components/floating/Menu/MenuContent.d.ts +60 -0
  120. package/dist/components/floating/Menu/MenuContext.d.ts +78 -0
  121. package/dist/components/floating/Menu/MenuItem.d.ts +47 -0
  122. package/dist/components/floating/Menu/MenuLabel.d.ts +6 -0
  123. package/dist/components/floating/Menu/MenuSeparator.d.ts +6 -0
  124. package/dist/components/floating/Menu/MenuTrigger.d.ts +53 -0
  125. package/dist/components/floating/Menu/index.d.ts +12 -0
  126. package/dist/components/floating/Menu/menuSelectors.d.ts +15 -0
  127. package/dist/components/floating/Tooltip/Tooltip.d.ts +194 -0
  128. package/dist/components/floating/Tooltip/index.d.ts +2 -0
  129. package/dist/components/floating/index.d.ts +3 -0
  130. package/dist/components/floating/primitives/FloatingTreeRoot.d.ts +55 -0
  131. package/dist/components/floating/primitives/index.d.ts +2 -0
  132. package/dist/components/floating/primitives/useFloatingNode.d.ts +1 -0
  133. package/dist/components/index.d.ts +38 -0
  134. package/dist/hooks/useControllableState.d.ts +152 -0
  135. package/dist/hooks/useTheme.d.ts +44 -0
  136. package/dist/index.d.ts +36 -0
  137. package/dist/index.js +1843 -0
  138. package/dist/server-safe.d.ts +69 -0
  139. package/dist/server-safe.js +47 -0
  140. package/dist/styles/igoded-base.css +1 -0
  141. package/dist/styles/igoded-components.css +1 -0
  142. package/dist/styles/igoded-design.css +1 -0
  143. package/dist/styles/igoded-fonts.css +1 -0
  144. package/dist/styles/igoded-reset.css +1 -0
  145. package/dist/styles/igoded-state-css.css +1 -0
  146. package/dist/styles/igoded-tokens.css +1 -0
  147. package/dist/styles/index.css +3 -0
  148. package/dist/styles/state/active.css +1 -0
  149. package/dist/styles/state/checked.css +1 -0
  150. package/dist/styles/state/default.css +1 -0
  151. package/dist/styles/state/disabled.css +1 -0
  152. package/dist/styles/state/empty.css +1 -0
  153. package/dist/styles/state/first-child.css +1 -0
  154. package/dist/styles/state/first-of-type.css +1 -0
  155. package/dist/styles/state/focus-visible.css +1 -0
  156. package/dist/styles/state/focus-within.css +1 -0
  157. package/dist/styles/state/focus.css +1 -0
  158. package/dist/styles/state/group-hover.css +1 -0
  159. package/dist/styles/state/hover.css +1 -0
  160. package/dist/styles/state/in-range.css +1 -0
  161. package/dist/styles/state/indeterminate.css +1 -0
  162. package/dist/styles/state/invalid.css +1 -0
  163. package/dist/styles/state/last-child.css +1 -0
  164. package/dist/styles/state/last-of-type.css +1 -0
  165. package/dist/styles/state/nth-child.css +1 -0
  166. package/dist/styles/state/only-child.css +1 -0
  167. package/dist/styles/state/optional.css +1 -0
  168. package/dist/styles/state/other.css +1 -0
  169. package/dist/styles/state/out-of-range.css +1 -0
  170. package/dist/styles/state/placeholder-shown.css +1 -0
  171. package/dist/styles/state/read-only.css +1 -0
  172. package/dist/styles/state/read-write.css +1 -0
  173. package/dist/styles/state/required.css +1 -0
  174. package/dist/styles/state/target.css +1 -0
  175. package/dist/styles/state/valid.css +1 -0
  176. package/dist/utils/cn.d.ts +11 -0
  177. package/package.json +282 -0
@@ -0,0 +1,53 @@
1
+ import { ButtonHTMLAttributes, Ref } from 'react';
2
+ export interface MenuTriggerProps extends ButtonHTMLAttributes<HTMLButtonElement> {
3
+ ref?: Ref<HTMLButtonElement> | undefined;
4
+ /**
5
+ * Slot pattern (D14 Bloque D beta.27): si `true`, clona el child del
6
+ * consumer y le aplica trigger semantics (id, aria-haspopup, aria-expanded
7
+ * via `useRole`, aria-controls, click + keyboard handlers de FUI) sin
8
+ * renderizar un `<button>` propio ni aplicar `ig-menu-trigger`.
9
+ *
10
+ * Permite usar cualquier elemento como trigger (`<Button>` del DS,
11
+ * `<a>`, custom component) preservando su tipo, styling y eventos.
12
+ *
13
+ * Sin `asChild`, MenuTrigger renderiza un `<button>` plano con clase
14
+ * `ig-menu-trigger` (comportamiento backwards-compat con 1.0.0-beta.26).
15
+ *
16
+ * @example
17
+ * // Slot pattern (recomendado con Button del DS):
18
+ * <MenuTrigger asChild>
19
+ * <Button variant="brand">Abrir menú</Button>
20
+ * </MenuTrigger>
21
+ *
22
+ * @example
23
+ * // Default (backwards-compat):
24
+ * <MenuTrigger>Opciones</MenuTrigger>
25
+ */
26
+ asChild?: boolean | undefined;
27
+ }
28
+ /**
29
+ * MenuTrigger — botón que abre/cierra el menú. Dos modos de render:
30
+ *
31
+ * - **Default** (`asChild=false`): renderiza un `<button class="ig-menu-trigger">`
32
+ * plano. Comportamiento idéntico al de 1.0.0-beta.26.
33
+ *
34
+ * - **Slot pattern** (`asChild=true`, D14 Bloque D): clona el child del
35
+ * consumer y le aplica id + ARIA + handlers FUI. El child es
36
+ * renderizado directamente (no wrapper). Patrón canónico Radix/shadcn.
37
+ *
38
+ * **C-03 (RC1)**: internals via `@floating-ui/react`. `useClick` ya
39
+ * cubre toggle por click + Space/Enter (estándar `<button>`).
40
+ * `useListNavigation` con `focusItemOnOpen: "auto"` foca primer/último
41
+ * item según la tecla que abrió el menú.
42
+ *
43
+ * ARIA inyectada por `useRole({ role: "menu" })`:
44
+ * - `aria-haspopup="menu"`
45
+ * - `aria-expanded={open}`
46
+ *
47
+ * `aria-controls={menuId}` se inyecta explícitamente para enlace al
48
+ * MenuContent (no lo cubre useRole por defecto).
49
+ *
50
+ * Es client-component (`"use client"`) porque consume `MenuContext` via
51
+ * hook — NO marcado server-safe.
52
+ */
53
+ export declare function MenuTrigger({ asChild, className, children, type, ref, ...rest }: MenuTriggerProps): import("react").JSX.Element;
@@ -0,0 +1,12 @@
1
+ export { Menu } from './Menu.js';
2
+ export type { MenuProps, MenuAlign, MenuDirection, } from './Menu.js';
3
+ export { MenuTrigger } from './MenuTrigger.js';
4
+ export type { MenuTriggerProps } from './MenuTrigger.js';
5
+ export { MenuContent } from './MenuContent.js';
6
+ export type { MenuContentProps } from './MenuContent.js';
7
+ export { MenuItem } from './MenuItem.js';
8
+ export type { MenuItemProps } from './MenuItem.js';
9
+ export { MenuSeparator } from './MenuSeparator.js';
10
+ export type { MenuSeparatorProps } from './MenuSeparator.js';
11
+ export { MenuLabel } from './MenuLabel.js';
12
+ export type { MenuLabelProps } from './MenuLabel.js';
@@ -0,0 +1,15 @@
1
+ /**
2
+ * Selector compartido por MenuTrigger y MenuItem para localizar
3
+ * los items navegables del menú.
4
+ *
5
+ * Excluye:
6
+ * - `[disabled]` — los <button> nativos disabled no son focuseables.
7
+ * - `[aria-disabled="true"]` — los <a> y custom items que se marcan
8
+ * deshabilitados por ARIA pero NO por el atributo HTML `disabled`.
9
+ *
10
+ * Tener UN solo selector evita que trigger e item se desincronicen
11
+ * (el bug histórico era que ↓ desde trigger saltaba a un item con
12
+ * aria-disabled, y luego ArrowDown desde ahí lo saltaba — comportamiento
13
+ * inconsistente).
14
+ */
15
+ export declare const NAVIGABLE_ITEM_SELECTOR = "[role=\"menuitem\"]:not([disabled]):not([aria-disabled=\"true\"])";
@@ -0,0 +1,194 @@
1
+ import { HTMLProps, ReactElement, ReactNode } from 'react';
2
+ export type TooltipPlacement = "top" | "top-start" | "top-end" | "right" | "right-start" | "right-end" | "bottom" | "bottom-start" | "bottom-end" | "left" | "left-start" | "left-end";
3
+ export type TooltipVariant = "brand" | "secondary" | "success" | "warning" | "danger" | "info";
4
+ export interface TooltipProps {
5
+ /**
6
+ * Contenido del tooltip. Acepta `string` (recomendado para a11y) o
7
+ * `ReactNode` para casos con formatting (negrita, links, fragmentos).
8
+ *
9
+ * **A11y — preferir string**: el SR-only `<span role="tooltip">` que
10
+ * contiene este valor es el referente de `aria-describedby` del child.
11
+ * Los SR (NVDA, VoiceOver, JAWS) leen el contenido del elemento. Con
12
+ * `string` el comportamiento está garantizado. Con `ReactNode`
13
+ * (`<strong>`, `<a>`, fragments) los SR pueden saltar nodos o leer
14
+ * en orden inesperado dependiendo del rol semántico — el consumer
15
+ * es responsable de que el contenido sea announce-friendly.
16
+ *
17
+ * Si necesitas formatting rich con interacción (links clickables,
18
+ * botones), considera `Popover` (1.1.0+) en lugar de Tooltip.
19
+ *
20
+ * C-01 (gate review): pre-RC1 era `string` puro. Ampliado a
21
+ * `string | ReactNode` para alinear con `Popover.content` y
22
+ * `HoverCard.content` futuros (evitar dos APIs hermanas con tipos
23
+ * incompatibles para conceptos similares).
24
+ */
25
+ text: string | ReactNode;
26
+ /** Posición preferida relativa al child. Por defecto `"top"`. */
27
+ placement?: TooltipPlacement | undefined;
28
+ /** Color del tooltip. */
29
+ variant?: TooltipVariant | undefined;
30
+ /**
31
+ * Elemento envuelto (típicamente un `<button>` o `<a>`). Debe ser
32
+ * un único `ReactElement` HTML — no string, fragment, array ni
33
+ * `ReactNode` arbitrario. El componente inyecta refs / handlers /
34
+ * `aria-describedby` vía `cloneElement`, lo que requiere un nodo
35
+ * elemento concreto.
36
+ *
37
+ * H-18 (gate review): el tipo previo `ReactNode` permitía
38
+ * `<Tooltip text="x">texto</Tooltip>` o arrays/fragments en
39
+ * tiempo de tipos, pero el control no quedaba asociado al SR.
40
+ * `ReactElement<HTMLProps<HTMLElement>>` rechaza ese caso en
41
+ * compile-time.
42
+ *
43
+ * D-01 / M-05 (gate review, RC1): el child se renderiza directo
44
+ * (Slot pattern) — no envuelto en un `<span>`. Tooltip era pre-RC1
45
+ * un wrapper `<span class="ig-tooltip-wrapper">` que rompía
46
+ * block-level layouts y obligaba a CSS extra. La eliminación es
47
+ * **breaking** (consumer con reglas dirigidas a `.ig-tooltip-wrapper`
48
+ * pierden el target) y se refleja en CHANGELOG.
49
+ */
50
+ children: ReactElement<HTMLProps<HTMLElement>>;
51
+ /** Delay en ms antes de mostrar al hover. Por defecto `0`. */
52
+ openDelay?: number | undefined;
53
+ /** Delay en ms antes de ocultar al desactivar. Por defecto `0`. */
54
+ closeDelay?: number | undefined;
55
+ /**
56
+ * Contenedor donde se monta el portal del tooltip. Por defecto
57
+ * `document.body`. También aplica para CSS containment / shadow roots.
58
+ *
59
+ * **Caso típico — Tooltip dentro de Dialog**: `<Dialog>` usa
60
+ * `<dialog>.showModal()` que crea un top-layer del browser. Si el
61
+ * portal del tooltip queda en `document.body`, aparece *detrás* del
62
+ * backdrop del dialog (invisible al usuario). Pasar el ref del
63
+ * dialog como container hace que el portal viva dentro del top-layer
64
+ * y se renderice por encima del backdrop.
65
+ *
66
+ * Patrón canónico (decisión C-02 documentada en
67
+ * `docs/decisions/C-02-modal-tooltip-portal.md`):
68
+ *
69
+ * ```tsx
70
+ * function MiPantalla() {
71
+ * const dialogRef = useRef<HTMLDialogElement>(null);
72
+ * return (
73
+ * <Dialog ref={dialogRef} open onClose={...}>
74
+ * <DialogBody>
75
+ * <Tooltip text="Eliminar" container={dialogRef}>
76
+ * <Button>×</Button>
77
+ * </Tooltip>
78
+ * </DialogBody>
79
+ * </Dialog>
80
+ * );
81
+ * }
82
+ * ```
83
+ *
84
+ * Acepta `HTMLElement` directo o un `RefObject` (Floating UI
85
+ * resuelve ambos).
86
+ */
87
+ container?: HTMLElement | React.RefObject<HTMLElement | null> | null | undefined;
88
+ /**
89
+ * Cualquier prop adicional (event handlers, `ref`, aria-*, data-*,
90
+ * etc.) que el consumer pase a Tooltip se forwardea al elemento child
91
+ * final via el `<Slot>` primitive (D14 Bloque C beta.27).
92
+ *
93
+ * Habilita el patrón **nested asChild** crítico para el refactor Slot
94
+ * DS-wide:
95
+ *
96
+ * ```tsx
97
+ * <DialogClose asChild>
98
+ * <Tooltip text="Cancela y cierra">
99
+ * <Button variant="danger">×</Button>
100
+ * </Tooltip>
101
+ * </DialogClose>
102
+ * ```
103
+ *
104
+ * El outer Slot de DialogClose pasa props al `<Tooltip>` (close
105
+ * onClick, ref); Tooltip los recibe en este index signature y los
106
+ * forwardea al `<Button>` final via su Slot interno. Resultado: el
107
+ * click en el botón cierra el dialog Y el botón sigue siendo el
108
+ * anchor del tooltip. Pre-D14 Bloque C: Tooltip dropeaba props del
109
+ * outer Slot (codex P2 round 2 sobre #109).
110
+ */
111
+ [key: string]: unknown;
112
+ }
113
+ /**
114
+ * Tooltip — wrapper que muestra un texto contextual al hacer hover/focus
115
+ * sobre el child. Usa **Floating UI** (`@floating-ui/react`) para
116
+ * positioning robusto:
117
+ *
118
+ * - **Portal-out**: el tooltip vive en un `<FloatingPortal>` al final
119
+ * de `<body>`, escapando overflow:hidden de cualquier ancestor.
120
+ * - **`flip` + `shift`**: si no cabe en el placement preferido, salta
121
+ * al opuesto o se desplaza para mantenerse visible en el viewport.
122
+ * - **`offset(8px)`**: separación entre el child y el tooltip.
123
+ * - **`autoUpdate`**: reposicionamiento al scroll/resize/transform.
124
+ *
125
+ * **A11y**:
126
+ * - El child recibe `aria-describedby` apuntando al span sr-only que
127
+ * contiene el `text`. Los lectores de pantalla siempre tienen
128
+ * acceso al texto (incluso cuando el portal no está montado).
129
+ * - El portal flotante usa `role="tooltip"` (gestionado por `useRole`).
130
+ * - `useDismiss` cierra con Escape. `outsidePress` desactivado: un
131
+ * tooltip hover/focus-only no puede dejarse "abierto" por error —
132
+ * sale del hover/focus ya cierra. Sin esto, FUI montaría un listener
133
+ * global de pointerdown sobre `document` mientras open, ruido sin
134
+ * beneficio. Si en el futuro hay un Tooltip click-trigger (poco
135
+ * probable; usa Popover para eso), reabrir como prop opt-in.
136
+ *
137
+ * **D-01 / M-05 / B-03 / H-01 (RC1)**: refactor a Slot pattern +
138
+ * primitives layer. El Tooltip ya **no renderiza wrapper span**:
139
+ * devuelve el child clonado + un sr-only span sibling + el portal.
140
+ * Esto cierra:
141
+ * - **D-01 / M-05**: rompía block-level layouts del consumer porque
142
+ * todo se envolvía en `<span class="ig-tooltip-wrapper">`.
143
+ * - **H-01 / B-03**: cascade dismiss vía `<FloatingTreeRoot>` +
144
+ * `useFloatingNode()` + `<FloatingNode>`. Sin tree, sigue
145
+ * funcionando independiente.
146
+ *
147
+ * **Migración desde CSS-only (pre-1.0.0-rc.1)**: la API pública
148
+ * (props text/placement/variant) NO cambia. Las clases
149
+ * `ig-tooltip-place-*` y `ig-tooltip-*` ahora se aplican al
150
+ * elemento del portal en lugar del wrapper. Si tenías reglas CSS
151
+ * dirigidas al wrapper `.ig-tooltip-wrapper` o ref / className en el
152
+ * `<Tooltip>`, ese wrapper ya no existe: aplica los estilos directo
153
+ * al child o envuélvelo manualmente.
154
+ *
155
+ * **Caveat — Tooltip sobre `<button disabled>` en Firefox** (L-03
156
+ * gate review): Firefox NO dispara `mouseenter` / `pointerenter` /
157
+ * `focus` sobre `<button disabled>` (Chrome/Safari sí). El SR-only
158
+ * span con `aria-describedby` sigue funcionando para lectores de
159
+ * pantalla, pero el portal visual no aparece al hover. Workaround
160
+ * canónico: envolver el botón en un `<span>` y aplicar
161
+ * `pointer-events: none` al botón disabled (el span recibe los
162
+ * eventos):
163
+ *
164
+ * ```tsx
165
+ * <Tooltip text="Acción no disponible">
166
+ * <span style={{ display: "inline-block" }}>
167
+ * <Button disabled style={{ pointerEvents: "none" }}>X</Button>
168
+ * </span>
169
+ * </Tooltip>
170
+ * ```
171
+ *
172
+ * El DS no aplica este wrapper automáticamente (Slot pattern: cero
173
+ * elementos extras silenciosos).
174
+ *
175
+ * @example
176
+ * <Tooltip text="Eliminar" placement="top">
177
+ * <Button icon aria-label="Eliminar">×</Button>
178
+ * </Tooltip>
179
+ *
180
+ * @example // overflow:hidden ya NO recorta el tooltip (portal-out)
181
+ * <div style={{ overflow: "hidden", width: 100 }}>
182
+ * <Tooltip text="Texto largo que escapa">
183
+ * <Button>Hover</Button>
184
+ * </Tooltip>
185
+ * </div>
186
+ *
187
+ * @example // cascade dismiss con FloatingTreeRoot
188
+ * <FloatingTreeRoot>
189
+ * <Popover content={<Tooltip text="..."><Button>Y</Button></Tooltip>}>
190
+ * <Button>X</Button>
191
+ * </Popover>
192
+ * </FloatingTreeRoot>
193
+ */
194
+ export declare function Tooltip({ text, placement, variant, children, openDelay, closeDelay, container, ...outerSlotProps }: TooltipProps): import("react").JSX.Element;
@@ -0,0 +1,2 @@
1
+ export { Tooltip } from './Tooltip.js';
2
+ export type { TooltipProps, TooltipPlacement, TooltipVariant, } from './Tooltip.js';
@@ -0,0 +1,3 @@
1
+ export * from './primitives/index.js';
2
+ export * from './Tooltip/index.js';
3
+ export * from './Menu/index.js';
@@ -0,0 +1,55 @@
1
+ import { ReactNode } from 'react';
2
+ export interface FloatingTreeRootProps {
3
+ children: ReactNode;
4
+ }
5
+ /**
6
+ * FloatingTreeRoot — habilita el cascade dismiss entre `Tooltip`,
7
+ * `Popover`, `Dropdown` (FUI) y similares cuando se anidan.
8
+ *
9
+ * **Comportamiento sin el root**: cada float funciona independiente —
10
+ * un `Escape` cierra solo el float más interno. Si el consumer abre un
11
+ * Popover dentro de un Dialog y un Tooltip dentro del Popover, cada
12
+ * Escape requiere acción separada y los floats no comparten estado de
13
+ * dismiss.
14
+ *
15
+ * **Comportamiento con el root**: los floats se registran en el árbol
16
+ * de `@floating-ui/react` y comparten el ciclo de dismiss. Un `Escape`
17
+ * cierra todos los floats abiertos en cascada (más interno → más
18
+ * externo). `outsidePress` también respeta la jerarquía: clicar dentro
19
+ * de un float anidado no cierra al ancestro.
20
+ *
21
+ * **Cuándo usarlo**: opt-in por consumer. Si tu app no anida floats
22
+ * (típico en formularios planos / dashboards simples), no lo necesitas
23
+ * y pagas un context extra sin beneficio. Si tienes Dialog con
24
+ * Tooltips/Popovers, o menús contextuales con sub-menús, envuelve la
25
+ * raíz de la app.
26
+ *
27
+ * @example
28
+ * ```tsx
29
+ * import { FloatingTreeRoot } from "reactigoded";
30
+ *
31
+ * function App() {
32
+ * return (
33
+ * <FloatingTreeRoot>
34
+ * <RouterProvider router={router} />
35
+ * </FloatingTreeRoot>
36
+ * );
37
+ * }
38
+ * ```
39
+ *
40
+ * H-01 / B-03 (gate review): pre-RC1 los floats no se registraban en
41
+ * tree, lo que dejaba un bug latente: anidación profunda no cerraba
42
+ * en cascada. Este wrapper expone la primitiva de FUI sin acoplar al
43
+ * design system al import específico de `@floating-ui/react` desde el
44
+ * consumer (le ofrecemos un nombre estable del DS).
45
+ *
46
+ * D11 (beta.24 gate review): `FloatingTreeRoot` queda como símbolo
47
+ * canónico para anidación de floats del DS. El hook subyacente
48
+ * `useFloatingNode` permanece internal (consumido sólo por Tooltip
49
+ * / Menu / Popover roadmap del DS via path directo). Si en el
50
+ * futuro abrimos hooks custom de floats al consumer, este símbolo
51
+ * sigue siendo el entrypoint.
52
+ *
53
+ * @public
54
+ */
55
+ export declare function FloatingTreeRoot({ children }: FloatingTreeRootProps): import("react").JSX.Element;
@@ -0,0 +1,2 @@
1
+ export { FloatingTreeRoot } from './FloatingTreeRoot.js';
2
+ export type { FloatingTreeRootProps } from './FloatingTreeRoot.js';
@@ -0,0 +1,38 @@
1
+ /**
2
+ * Barrel de componentes del design system.
3
+ *
4
+ * Cada componente exporta su tipo de props y el componente en sí desde
5
+ * `./<Componente>/index.ts`.
6
+ */
7
+ export * from './Accordion/index.js';
8
+ export * from './Alert/index.js';
9
+ export * from './AlertDialog/index.js';
10
+ export * from './Avatar/index.js';
11
+ export * from './Badge/index.js';
12
+ export * from './Breadcrumb/index.js';
13
+ export * from './Button/index.js';
14
+ export * from './Card/index.js';
15
+ export * from './Checkbox/index.js';
16
+ export * from './Chip/index.js';
17
+ export * from './Divider/index.js';
18
+ export * from './Input/index.js';
19
+ export * from './Dialog/index.js';
20
+ export * from './Navbar/index.js';
21
+ export * from './Pagination/index.js';
22
+ export * from './Progress/index.js';
23
+ export * from './Radio/index.js';
24
+ export * from './Rating/index.js';
25
+ export * from './NativeSelect/index.js';
26
+ export * from './Sidebar/index.js';
27
+ export * from './Skeleton/index.js';
28
+ export * from './Slider/index.js';
29
+ export * from './Spinner/index.js';
30
+ export * from './Stepper/index.js';
31
+ export * from './Switch/index.js';
32
+ export * from './Table/index.js';
33
+ export * from './Tabs/index.js';
34
+ export * from './Textarea/index.js';
35
+ export * from './ThemeToggle/index.js';
36
+ export * from './Timeline/index.js';
37
+ export * from './Toast/index.js';
38
+ export * from './floating/index.js';
@@ -0,0 +1,152 @@
1
+ export type UseControllableStateBaseOptions<T> = {
2
+ /**
3
+ * Valor controlado. Si está definido (≠ undefined), el componente es
4
+ * controlled — el valor externo manda y `setValue` solo dispara
5
+ * `onChange`.
6
+ */
7
+ value?: T | undefined;
8
+ /** Callback al cambiar el valor. Disparado en ambos modos. */
9
+ onChange?: ((value: T) => void) | undefined;
10
+ } & {};
11
+ export interface UseControllableStateInternalOptions<T> extends UseControllableStateBaseOptions<T> {
12
+ /** Valor inicial uncontrolled. Ignorado si `value` está definido. */
13
+ defaultValue?: T | undefined;
14
+ derive?: never;
15
+ setDerivedValue?: never;
16
+ }
17
+ export interface UseControllableStateDerivedOptions<T> extends UseControllableStateBaseOptions<T> {
18
+ /**
19
+ * Valor uncontrolled derivado en cada render desde fuentes externas
20
+ * (storage, MediaQueryList, otro hook). Debe ser **puro**: no
21
+ * escribas storage, DOM ni estado dentro.
22
+ */
23
+ derive: () => T;
24
+ /**
25
+ * Setter de la fuente local React que alimenta `derive()`.
26
+ *
27
+ * IMPORTANTE: debe actualizar una fuente React/local que `derive()`
28
+ * lea. No debe escribir únicamente en una fuente externa como
29
+ * `localStorage`, porque `useSyncExternalStore` no notifica cambios
30
+ * same-tab en browsers reales y la UI no se actualizaría tras una
31
+ * interacción del usuario.
32
+ *
33
+ * Ejemplo correcto en ThemeSwitch:
34
+ *
35
+ * ```ts
36
+ * const [override, setOverride] = useState<Theme | null>(null);
37
+ *
38
+ * useControllableState({
39
+ * derive: () => override ?? stored ?? defaultTheme ?? "dark",
40
+ * setDerivedValue: setOverride,
41
+ * });
42
+ * ```
43
+ */
44
+ setDerivedValue: (next: T) => void;
45
+ defaultValue?: never;
46
+ }
47
+ /**
48
+ * Opciones de `useControllableState`.
49
+ *
50
+ * Dos modos mutuamente excluyentes garantizados por unión discriminada:
51
+ *
52
+ * **Modo interno clásico** — para componentes con state interno simple.
53
+ *
54
+ * ```ts
55
+ * useControllableState({
56
+ * value,
57
+ * defaultValue,
58
+ * onChange,
59
+ * });
60
+ * ```
61
+ *
62
+ * **Modo derivado** — para componentes cuyo valor uncontrolled deriva de
63
+ * fuentes externas o compuestas.
64
+ *
65
+ * ```ts
66
+ * useControllableState({
67
+ * value,
68
+ * derive: () => override ?? stored ?? defaultValue ?? "fallback",
69
+ * setDerivedValue: setOverride,
70
+ * onChange,
71
+ * });
72
+ * ```
73
+ *
74
+ * En modo derivado NO pases `defaultValue`; mete el fallback dentro de
75
+ * `derive()`. TypeScript impide la combinación inválida vía `never`.
76
+ */
77
+ export type UseControllableStateOptions<T> = UseControllableStateInternalOptions<T> | UseControllableStateDerivedOptions<T>;
78
+ export interface SetValueOptions {
79
+ /**
80
+ * Si `true`, NO se invoca `onChange`. Útil para auto-selects internos
81
+ * y rehidrataciones desde storage que NO son acción del usuario.
82
+ */
83
+ silent?: boolean | undefined;
84
+ }
85
+ /**
86
+ * Acción aceptada por `setValue`: un valor directo `T` o una función
87
+ * updater `(prev: T) => T` (M-06, RC1) — mismo patrón que `useState`
88
+ * de React. La updater function recibe el `value` actual del hook
89
+ * (controlled, derivado o internal según el modo) y debe retornar el
90
+ * siguiente valor sin mutar el anterior.
91
+ *
92
+ * Útil para updates que no dependen del closure del callback:
93
+ *
94
+ * ```tsx
95
+ * <button onClick={() => setValue((prev) => !prev)}>Toggle</button>
96
+ * ```
97
+ *
98
+ * vs. el equivalente con valor directo (depende del closure):
99
+ *
100
+ * ```tsx
101
+ * <button onClick={() => setValue(!value)}>Toggle</button>
102
+ * ```
103
+ */
104
+ export type SetValueAction<T> = T | ((prev: T) => T);
105
+ export interface UseControllableStateReturn<T> {
106
+ /** Valor actual (controlled, derivado o internal). */
107
+ value: T;
108
+ /**
109
+ * Setter que respeta el modo. En controlled solo dispara `onChange`.
110
+ * Pasa `{ silent: true }` para no notificar al consumer.
111
+ *
112
+ * Acepta valor directo `T` o updater function `(prev: T) => T`
113
+ * (M-06, RC1) — mismo patrón que `useState`.
114
+ */
115
+ setValue: (action: SetValueAction<T>, options?: SetValueOptions) => void;
116
+ /** True si el componente está en modo controlled. */
117
+ isControlled: boolean;
118
+ }
119
+ /**
120
+ * Hook para componentes con patrón controlled/uncontrolled.
121
+ *
122
+ * Dos modos:
123
+ * - **Internal** (default): `useState(defaultValue)` para uncontrolled.
124
+ * - **Derived** (opt-in): `derive()` se computa en render desde una
125
+ * fuente externa (storage, MediaQueryList…) y `setDerivedValue` la
126
+ * actualiza. Útil cuando el origen del valor uncontrolled es un
127
+ * sistema externo y no queremos un `useState` espejo que se
128
+ * desincronice.
129
+ *
130
+ * `setValue` mantiene identidad estable entre renders (útil para
131
+ * pasarlo a contextos sin invalidar consumers). `onChange` y el modo
132
+ * se sincronizan vía refs.
133
+ *
134
+ * @example // Modo internal (la mayoría de componentes)
135
+ * const { value, setValue } = useControllableState({
136
+ * value: checked,
137
+ * defaultValue: defaultChecked ?? false,
138
+ * onChange: onCheckedChange,
139
+ * });
140
+ *
141
+ * @example // Modo derive (ThemeSwitch con useStoredTheme)
142
+ * const stored = useStoredTheme(storageKey);
143
+ * const { value, setValue } = useControllableState<Theme>({
144
+ * value: themeProp,
145
+ * derive: () => stored ?? defaultTheme ?? "dark",
146
+ * setDerivedValue: (next) => writeStoredTheme(storageKey, next),
147
+ * onChange: onValueChange,
148
+ * });
149
+ *
150
+ * @public
151
+ */
152
+ export declare function useControllableState<T>(options: UseControllableStateOptions<T>): UseControllableStateReturn<T>;
@@ -0,0 +1,44 @@
1
+ export type Theme = "light" | "dark";
2
+ export interface UseThemeReturn {
3
+ theme: Theme;
4
+ setTheme: (theme: Theme) => void;
5
+ toggleTheme: () => void;
6
+ }
7
+ /**
8
+ * Hook para manejar el tema (light/dark).
9
+ *
10
+ * El atributo `data-theme` de `<html>` es la única fuente de verdad: el
11
+ * hook lo observa con un `MutationObserver` vía `useSyncExternalStore`
12
+ * y se mantiene sincronizado con cualquier escritor (otro `useTheme`,
13
+ * `<ThemeSwitch>`, el script anti-flash del README o código del
14
+ * consumer). `setTheme` escribe el atributo y deja que el observer
15
+ * propague el cambio.
16
+ *
17
+ * **SSR**: en el servidor devuelve `dark` (default dark-first del DS
18
+ * desde `1.0.0-beta.3`). Hidrata en cliente leyendo el atributo. Para
19
+ * evitar el flash inicial, inyecta el script anti-flash documentado en
20
+ * el README §"Tema light/dark".
21
+ *
22
+ * @example
23
+ * function ThemeToggle() {
24
+ * const { theme, toggleTheme } = useTheme();
25
+ * return (
26
+ * <button type="button" onClick={toggleTheme} aria-label={`Tema actual: ${theme}`}>
27
+ * {theme === "dark" ? "☀" : "🌙"}
28
+ * </button>
29
+ * );
30
+ * }
31
+ *
32
+ * @example
33
+ * // Forzar tema desde una preferencia de usuario.
34
+ * function SettingsPanel({ pref }: { pref: "light" | "dark" | "auto" }) {
35
+ * const { setTheme } = useTheme();
36
+ * useEffect(() => {
37
+ * if (pref !== "auto") setTheme(pref);
38
+ * }, [pref, setTheme]);
39
+ * return null;
40
+ * }
41
+ *
42
+ * @public
43
+ */
44
+ export declare function useTheme(): UseThemeReturn;
@@ -0,0 +1,36 @@
1
+ /**
2
+ * Igoded Design System — entry point del paquete.
3
+ *
4
+ * Arquitectura CSS modular (estable desde `1.0.0-beta.3`):
5
+ *
6
+ * tokens.css solo variables --ig-* + keyframes + @font-face
7
+ * (cero selectores globales, ~98 KB).
8
+ * base.css globales mínimos: box-sizing + html + scrollbars +
9
+ * ::selection + prefers-reduced-motion / contrast /
10
+ * forced-colors. Garantías a11y. Requiere tokens.
11
+ * components.css utilities + componentes (clases .ig-*). Requiere
12
+ * tokens + base.
13
+ * design.css meta: @import de tokens + base + components.
14
+ *
15
+ * reset.css estilos por defecto para HTML nativo (h1-h6, p, a,
16
+ * button, input, table…). Opt-in.
17
+ * state.css utilities pseudo-class (hover:, focus:). ~6.5 MB sin gzip / ~700 KB gzipped. Opt-in.
18
+ * all.css atajo: design + reset + state.
19
+ *
20
+ * USO POR ESCENARIO:
21
+ *
22
+ * import "reactigoded/styles/design.css"; // DS completo
23
+ *
24
+ * import "reactigoded/styles/design.css";
25
+ * import "reactigoded/styles/reset.css"; // DS + HTML nativo
26
+ *
27
+ * import "reactigoded/styles/tokens.css"; // solo tokens
28
+ *
29
+ * import "reactigoded/styles/tokens.css";
30
+ * import "reactigoded/styles/base.css"; // tokens + a11y
31
+ * // baseline
32
+ */
33
+ export * from './components/index.js';
34
+ export { useTheme, type Theme, type UseThemeReturn } from './hooks/useTheme.js';
35
+ export { useControllableState, type SetValueOptions, type UseControllableStateOptions, type UseControllableStateReturn, } from './hooks/useControllableState.js';
36
+ export { cn } from './utils/cn.js';