beez-ui 0.7.0 → 0.8.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/CHANGELOG.md +21 -3
- package/README.md +290 -274
- package/dist/components/account-menu.d.ts +53 -0
- package/dist/components/account-menu.js +405 -0
- package/dist/components/animated-collapse.d.ts +19 -0
- package/dist/components/animated-collapse.js +81 -0
- package/dist/components/animated-count.d.ts +13 -0
- package/dist/components/animated-count.js +105 -0
- package/dist/components/animated-list-item.d.ts +25 -0
- package/dist/components/animated-list-item.js +132 -0
- package/dist/components/bouncing-dots-loader.d.ts +19 -0
- package/dist/components/bouncing-dots-loader.js +47 -0
- package/dist/components/confirm-delete-button.d.ts +29 -0
- package/dist/components/confirm-delete-button.js +254 -0
- package/dist/components/empty-state.d.ts +24 -0
- package/dist/components/empty-state.js +37 -0
- package/dist/components/error-state.d.ts +20 -0
- package/dist/components/error-state.js +145 -0
- package/dist/components/external-browser-handoff.d.ts +27 -0
- package/dist/components/external-browser-handoff.js +306 -0
- package/dist/components/file-upload.d.ts +78 -0
- package/dist/components/file-upload.js +678 -0
- package/dist/components/info-popover.d.ts +23 -0
- package/dist/components/info-popover.js +158 -0
- package/dist/components/month-calendar-header.d.ts +65 -0
- package/dist/components/month-calendar-header.js +337 -0
- package/dist/components/month-grid.d.ts +59 -0
- package/dist/components/month-grid.js +301 -0
- package/dist/components/notification-bell.d.ts +50 -0
- package/dist/components/notification-bell.js +338 -0
- package/dist/components/notification-panel.d.ts +56 -0
- package/dist/components/notification-panel.js +281 -0
- package/dist/components/open-in-browser-cta.d.ts +22 -0
- package/dist/components/open-in-browser-cta.js +61 -0
- package/dist/components/presence-swap.d.ts +22 -0
- package/dist/components/presence-swap.js +162 -0
- package/dist/components/progress-ring.d.ts +20 -0
- package/dist/components/progress-ring.js +53 -0
- package/dist/components/pwa-update-control.d.ts +18 -0
- package/dist/components/pwa-update-control.js +119 -0
- package/dist/components/reaction-button.d.ts +26 -0
- package/dist/components/reaction-button.js +114 -0
- package/dist/components/rich-link-editor.d.ts +25 -0
- package/dist/components/rich-link-editor.js +320 -0
- package/dist/components/rich-markdown-content.d.ts +10 -0
- package/dist/components/rich-markdown-content.js +56 -0
- package/dist/components/rich-text-content.d.ts +19 -0
- package/dist/components/rich-text-content.js +26 -0
- package/dist/emoji-picker.d.ts +27 -0
- package/dist/emoji-picker.js +283 -0
- package/dist/hooks/use-horizontal-swipe.d.ts +23 -0
- package/dist/hooks/use-horizontal-swipe.js +80 -0
- package/dist/hooks/use-is-hydrated.d.ts +6 -0
- package/dist/hooks/use-is-hydrated.js +20 -0
- package/dist/hooks/use-minute-clock.d.ts +23 -0
- package/dist/hooks/use-minute-clock.js +147 -0
- package/dist/hooks/use-month-transition-direction.d.ts +21 -0
- package/dist/hooks/use-month-transition-direction.js +110 -0
- package/dist/hooks/use-rich-link-editor.d.ts +55 -0
- package/dist/hooks/use-rich-link-editor.js +515 -0
- package/dist/hooks/use-viewer-time-zone.d.ts +6 -0
- package/dist/hooks/use-viewer-time-zone.js +20 -0
- package/dist/index.d.ts +44 -0
- package/dist/index.js +43 -0
- package/dist/lib/browser-clipboard.d.ts +13 -0
- package/dist/lib/browser-clipboard.js +48 -0
- package/dist/lib/browser-navigation.d.ts +21 -0
- package/dist/lib/browser-navigation.js +42 -0
- package/dist/lib/file-acceptance.d.ts +43 -0
- package/dist/lib/file-acceptance.js +107 -0
- package/dist/lib/format-file-size.d.ts +16 -0
- package/dist/lib/format-file-size.js +34 -0
- package/dist/lib/fuzzy-search.d.ts +17 -0
- package/dist/lib/fuzzy-search.js +183 -0
- package/dist/lib/horizontal-swipe.d.ts +23 -0
- package/dist/lib/horizontal-swipe.js +29 -0
- package/dist/lib/in-app-browser.d.ts +35 -0
- package/dist/lib/in-app-browser.js +80 -0
- package/dist/lib/month-grid.d.ts +42 -0
- package/dist/lib/month-grid.js +74 -0
- package/dist/lib/name-initials.d.ts +7 -0
- package/dist/lib/name-initials.js +11 -0
- package/dist/lib/rich-text/link-markdown-constants.d.ts +147 -0
- package/dist/lib/rich-text/link-markdown-constants.js +458 -0
- package/dist/lib/rich-text/link-markdown-types.d.ts +53 -0
- package/dist/lib/rich-text/link-markdown-types.js +1 -0
- package/dist/lib/rich-text/link-markdown.d.ts +193 -0
- package/dist/lib/rich-text/link-markdown.js +592 -0
- package/dist/lib/rich-text/rich-markdown.d.ts +41 -0
- package/dist/lib/rich-text/rich-markdown.js +105 -0
- package/dist/lib/rich-text/rich-text-editor-dom.d.ts +26 -0
- package/dist/lib/rich-text/rich-text-editor-dom.js +79 -0
- package/dist/motion/tokens.d.ts +17 -1
- package/dist/motion/tokens.js +17 -1
- package/dist/styles.css +1 -1
- package/package.json +211 -1
package/README.md
CHANGED
|
@@ -1,274 +1,290 @@
|
|
|
1
|
-
# beez-ui
|
|
2
|
-
|
|
3
|
-
Biblioteca de componentes React reutilizables, con adaptadores opcionales por framework y tema compartido. Reúne los componentes de LaTribu y las funcionalidades reutilizables de agenda-mensual.
|
|
4
|
-
|
|
5
|
-
## Storybook
|
|
6
|
-
|
|
7
|
-
```bash
|
|
8
|
-
pnpm storybook
|
|
9
|
-
```
|
|
10
|
-
|
|
11
|
-
Abre `http://localhost:6006` para explorar los componentes con controles de texto,
|
|
12
|
-
variantes, tamaños, estados y comportamiento. El selector de la barra permite
|
|
13
|
-
probar el tema claro, oscuro o del sistema. Las stories de componentes compuestos
|
|
14
|
-
incluyen sus piezas en ejemplos completos; los campos editables y selectores
|
|
15
|
-
sincronizan sus interacciones con Controls. `BeezUIProvider` configura el preview
|
|
16
|
-
y no forma parte del catálogo. Las notificaciones se exploran en `ThemedToaster`,
|
|
17
|
-
sin duplicar una story de `Toaster`; `WhatsappIcon` está en la sección `Icons`.
|
|
18
|
-
|
|
19
|
-
```bash
|
|
20
|
-
pnpm build-storybook # Genera storybook-static para servirlo o publicarlo
|
|
21
|
-
pnpm typecheck:stories # Comprueba stories y configuración con TypeScript
|
|
22
|
-
pnpm test:storybook # Build y navegación/interacciones en Chromium y WebKit
|
|
23
|
-
```
|
|
24
|
-
|
|
25
|
-
El catálogo consume los exports públicos y el CSS compilado de la librería. Los
|
|
26
|
-
scripts compilan `beez-ui` antes de arrancar; si editás sus fuentes con Storybook
|
|
27
|
-
abierto, ejecutá `pnpm build` para actualizar el paquete que muestra el preview.
|
|
28
|
-
Los cambios en las stories se actualizan durante el desarrollo. Storybook y sus
|
|
29
|
-
addons son dependencias de desarrollo y no se incluyen en el paquete publicado.
|
|
30
|
-
|
|
31
|
-
Configuración basada en [React con Vite](https://storybook.js.org/docs/get-started/frameworks/react-vite)
|
|
32
|
-
y [Controls](https://storybook.js.org/docs/essentials/controls).
|
|
33
|
-
|
|
34
|
-
## Uso del paquete
|
|
35
|
-
|
|
36
|
-
```tsx
|
|
37
|
-
import { Button, Avatar, AvatarImage, DataTable, Calendar } from "beez-ui";
|
|
38
|
-
```
|
|
39
|
-
|
|
40
|
-
Agrupar los imports de componentes desde la raíz. El paquete publica JavaScript ESM y declaraciones TypeScript en `dist`; el consumidor no necesita transpilar el código fuente de la librería. La gramática de filtros y los helpers de mes-año son independientes de React.
|
|
41
|
-
|
|
42
|
-
La utilidad `cn`, también exportada desde `beez-ui`, usa el paquete `cn` para combinar clases condicionales y resolver conflictos de Tailwind.
|
|
43
|
-
|
|
44
|
-
```css
|
|
45
|
-
@import "beez-ui/styles.css";
|
|
46
|
-
```
|
|
47
|
-
|
|
48
|
-
`beez-ui/styles.css` es CSS listo para el navegador: incluye reset, utilidades, tema claro/oscuro, radios y fuentes locales Geist, Poppins e IBM Plex Mono. No requiere Tailwind, plugins PostCSS ni declaraciones `@source` en el consumidor. Las clases se compilan en el build de la biblioteca y se publican en `dist/styles.css`; `styles.source.css` es la entrada de desarrollo y no se distribuye.
|
|
49
|
-
|
|
50
|
-
Los consumidores pueden sobrescribir tokens mediante CSS normal. Poppins se reserva para títulos grandes mediante `--font-display`; las licencias se incluyen en `assets/fonts`. Si la aplicación usa Tailwind para sus propios estilos puede mantenerlo, pero ya no necesita escanear beez-ui.
|
|
51
|
-
|
|
52
|
-
`DropdownMenuContent` toma el ancho natural de sus opciones, con un mínimo de 12 rem y un máximo limitado por el espacio disponible. No hereda el ancho del botón disparador: los menús abiertos desde un icono deben mantener sus etiquetas legibles. Para un ancho específico, usar `className` y ajustar también el mínimo cuando se necesite un menú más pequeño.
|
|
53
|
-
|
|
54
|
-
Los componentes usan por defecto los espaciados compactos de Agenda: `Select` mide 2 rem (1.75 rem en tamaño pequeño), `TabsList` horizontal mide 2 rem y `PopoverContent` usa 0.625 rem de padding. Los menús y submenús tienen un mínimo de 12 rem, con filas compactas. `Dialog` y `AlertDialog` usan 1 rem de padding y un footer con borde superior y fondo diferenciado; `Textarea` distingue el estado deshabilitado mediante su fondo. Estos valores conservan los colores y fuentes del tema compartido. Son cambios de los defaults, sin una prop adicional para activarlos; los consumidores pueden personalizarlos mediante `className`.
|
|
55
|
-
|
|
56
|
-
Los `Sheet` superiores e inferiores limitan su altura al viewport dinámico (`100dvh`) y permiten desplazar el contenido para mantener accesibles las acciones de paneles largos.
|
|
57
|
-
|
|
58
|
-
## Movimiento
|
|
59
|
-
|
|
60
|
-
Las nuevas animaciones usan la dependencia `motion`: `animate` controla la
|
|
61
|
-
reproducción, `hover` y `press` los gestos, y `AnimatePresence` / `usePresence`
|
|
62
|
-
retienen los overlays durante su salida. Los presets y tiempos viven en
|
|
63
|
-
`src/motion/`. No se usan keyframes CSS para estas animaciones.
|
|
64
|
-
|
|
65
|
-
`MotionSlot` anima el nodo original del primitive mediante refs compuestos,
|
|
66
|
-
sin agregar wrappers al DOM ni reemplazar sus handlers. Las curvas y springs
|
|
67
|
-
siguen los tokens de [beui motion](https://beui.dev/components/motion):
|
|
68
|
-
|
|
69
|
-
- `Button` se comprime con spring a 0.93 y se eleva a 1.02 al hover, solo en
|
|
70
|
-
dispositivos con hover real (`(hover: hover) and (pointer: fine)`); los ítems de
|
|
71
|
-
`Sidebar` y `Tabs` se comprimen a 0.98.
|
|
72
|
-
- `Checkbox` y `RadioGroup` se comprimen a 0.92. La marca del checkbox aparece
|
|
73
|
-
con pop y trazo (`pathLength`) y sale con blur; el punto del radio aparece con spring.
|
|
74
|
-
- El thumb de `Switch` viaja con un spring pesado y se aplasta mientras se presiona.
|
|
75
|
-
- `Input`, `Textarea`, `InputGroup` y `SelectTrigger` tiemblan al pasar a
|
|
76
|
-
`aria-invalid="true"`; `FormMessage` entra con blur.
|
|
77
|
-
- `Tooltip` entra con blur, escala y desplazamiento desde el trigger.
|
|
78
|
-
`Popover`, `HoverCard`, `DropdownMenu` y `Select` escalan desde 0.96 y se revelan
|
|
79
|
-
con un clip desde la esquina más cercana al trigger.
|
|
80
|
-
- `Dialog` y `AlertDialog` suben con spring; `Sheet` entra desde su borde con spring
|
|
81
|
-
y sale con la curva de cajón (0.24 s), sin demorar la siguiente interacción.
|
|
82
|
-
- `GlideSlot` desliza el indicador activo entre ítems como un `layoutId` compartido:
|
|
83
|
-
la pestaña activa de `Tabs` (fondo o subrayado), el ítem activo de `SidebarMenu`, la
|
|
84
|
-
página actual de `PaginationContent`, y al navegar con teclado el ítem resaltado de
|
|
85
|
-
`DropdownMenu` y `Select` y la sugerencia activa de `FilterQueryBar`. Con el puntero,
|
|
86
|
-
esos resaltados lo siguen al instante: el propio puntero ya marca la posición.
|
|
87
|
-
- Las superficies flotantes se revelan con un clip que deja 24 px libres fuera de la
|
|
88
|
-
caja, así su borde (`ring`) y su sombra se ven desde el primer frame. Una copia
|
|
89
|
-
transitoria viaja entre ítems y se elimina al llegar, devolviendo el estilo al ítem.
|
|
90
|
-
- El chevron de `SelectTrigger` gira 180° al abrir y los chevrons de `DataTable`
|
|
91
|
-
(grupos y columnas) giran en lugar de cambiar de ícono; CSS define el ángulo final.
|
|
92
|
-
- Las opciones del `Select` entran escalonadas con blur (las primeras 10; el resto
|
|
93
|
-
solo se desvanece) y los checks de ítems de `Select` y `DropdownMenu` aparecen con pop.
|
|
94
|
-
- El ícono de `AnimatedThemeToggler` cambia con blur y escala; el botón de cierre de
|
|
95
|
-
`Dialog` aparece con un pop demorado.
|
|
96
|
-
- El contenido de `Tabs` entra con un desplazamiento de 4 px y `Alert` entra con blur.
|
|
97
|
-
Cards y enlaces responden al hover; el avatar bajo el puntero de un `AvatarGroup` se
|
|
98
|
-
eleva. Un brillo recorre el `Skeleton` desde su `::after` con reproducción nativa,
|
|
99
|
-
sin trabajo por frame en JavaScript.
|
|
100
|
-
- `Calendar` desliza el mes entrante desde el lado de la navegación (invertido en RTL).
|
|
101
|
-
- `AvatarImage` se revela con blur y un zoom de 1.06 al terminar de cargar; las imágenes
|
|
102
|
-
ya cargadas al montar no se animan.
|
|
103
|
-
- El cursor de `TypingAnimation` queda fijo mientras escribe y parpadea en reposo. Las animaciones especializadas
|
|
104
|
-
existentes de Embla, Sonner y rough-notation se conservan.
|
|
105
|
-
|
|
106
|
-
El contenido que está saliendo deja de ser interactivo y accesible de inmediato.
|
|
107
|
-
Cada familia de overlays tiene un contexto de visibilidad independiente para
|
|
108
|
-
soportar composiciones anidadas; los portales sin nodo visible no bloquean el
|
|
109
|
-
cierre del padre. `Select` conserva su desmontaje nativo y usa Motion en la entrada.
|
|
110
|
-
La elección explícita de `forceMount` permanece bajo control del consumidor.
|
|
111
|
-
|
|
112
|
-
Se respeta `prefers-reduced-motion`: las nuevas animaciones se cancelan y se
|
|
113
|
-
restauran los estilos; las anotaciones se dibujan sin animación y el texto aparece
|
|
114
|
-
completo, incluidas todas las palabras de una secuencia. Los controles del carrusel
|
|
115
|
-
avanzan directamente. El CSS solo aporta el fallback de movimiento reducido para
|
|
116
|
-
los efectos heredados. `BeezUIProvider` configura `MotionConfig` con
|
|
117
|
-
`reducedMotion="user"`. El primer render conserva el contrato de SSR.
|
|
118
|
-
|
|
119
|
-
El selector aplica el tema inmediatamente y anima su icono con Motion; no depende
|
|
120
|
-
de View Transitions nativas ni de una animación para completar el cambio. Los estilos temporales se liberan al terminar
|
|
121
|
-
la reproducción. Las stories permiten probar los gestos y estados reales; el
|
|
122
|
-
selector de tema de la story y la barra de Storybook se mantienen sincronizados.
|
|
123
|
-
|
|
124
|
-
## Providers de UI
|
|
125
|
-
|
|
126
|
-
Elegir un único `BeezUIProvider` según el framework. Los componentes y `useTheme` siempre se importan desde `beez-ui`.
|
|
127
|
-
|
|
128
|
-
| Import del provider | Navegación | Imágenes de avatar |
|
|
129
|
-
| --- | --- | --- |
|
|
130
|
-
| `beez-ui` | Anclas nativas | `@unpic/react` |
|
|
131
|
-
| `beez-ui/next` | `next/link` | `next/image` |
|
|
132
|
-
| `beez-ui/tanstack` | TanStack Router | `@unpic/react` |
|
|
133
|
-
|
|
134
|
-
```tsx
|
|
135
|
-
"use client";
|
|
136
|
-
|
|
137
|
-
import type { ReactNode } from "react";
|
|
138
|
-
import { BeezUIProvider } from "beez-ui/next";
|
|
139
|
-
|
|
140
|
-
export function Providers({ children }: { children: ReactNode }) {
|
|
141
|
-
return (
|
|
142
|
-
<BeezUIProvider themeOptions={{ storageKey: "tutribu-theme", defaultTheme: "system" }}>
|
|
143
|
-
{children}
|
|
144
|
-
</BeezUIProvider>
|
|
145
|
-
);
|
|
146
|
-
}
|
|
147
|
-
```
|
|
148
|
-
|
|
149
|
-
Todos los providers usan `next-themes` con clases CSS. El consumidor configura `themeOptions` y conecta sus controles a `useTheme` desde `beez-ui`. Al migrar una aplicación, conservar su clave de almacenamiento y retirar los scripts y estados anteriores que modifiquen el tema. En Next, mantener `suppressHydrationWarning` en el elemento `html` porque el provider restaura la preferencia antes de hidratar.
|
|
150
|
-
|
|
151
|
-
El provider de Next desactiva prefetch y optimización de imágenes por defecto, como LaTribu. Se activan con `prefetch` y `optimizeImages`; para optimizar imágenes remotas hay que configurar sus hosts en la app. `Link` y los enlaces de paginación usan el adaptador del provider. El contrato común de `Link` acepta href como string y atributos de ancla, no todas las opciones exclusivas de Next.
|
|
152
|
-
|
|
153
|
-
El provider de TanStack se monta dentro del router de la aplicación. Preserva query y hash; `prefetch` activa precarga por intención. TanStack no aporta un componente Image propio: Unpic genera variantes responsivas para CDNs compatibles y conserva las URLs que no reconoce; no instala un servidor de optimización.
|
|
154
|
-
|
|
155
|
-
Next y TanStack Router son peers opcionales aislados en sus entrypoints. El provider nativo admite overrides mediante `components`. Sin provider, los componentes conservan anclas e imágenes HTML como fallback.
|
|
156
|
-
|
|
157
|
-
## Responsabilidades del consumidor
|
|
158
|
-
|
|
159
|
-
- Tema: `AnimatedThemeToggler` y `ThemedToaster` consumen el contexto compartido. Sus props explícitas de tema siguen disponibles para usos controlados.
|
|
160
|
-
- Navegación: `PaginationNext`, `PaginationPrevious` y `PaginationLink` usan anclas nativas. El prop opcional `component` admite el adaptador del router que elija la app. Sin proveedor usa el elemento nativo; con el proveedor de Next usa su navegación cliente.
|
|
161
|
-
- Sidebar: `defaultOpen` y el modo controlado conservan la semántica de LaTribu. `storageKey` activa opcionalmente persistencia local segura tras hidratar, sin cambiar la cookie pública `sidebar_state` ni sus siete días de duración.
|
|
162
|
-
- Formularios y tablas: el consumidor provee sus datos, validaciones y callbacks. No se importan servicios, modelos de negocio ni endpoints de agenda-mensual.
|
|
163
|
-
|
|
164
|
-
## Componentes incorporados desde agenda-mensual
|
|
165
|
-
|
|
166
|
-
`Alert`, `AnimatedThemeToggler`, `Calendar`, `DataTable`, `FilterQueryBar`, `Form`, `Highlighter`, `InputGroup`, `Label`, `RadioGroup`, `TypingAnimation` y `ThemedToaster`, junto con sus subcomponentes, tipos y gramática de filtros.
|
|
167
|
-
|
|
168
|
-
`FilterQueryBar` mantiene el foco en el input mientras se recorren las sugerencias con el puntero o las flechas. Enter aplica la opción activa; interactuar con el input no cierra la lista.
|
|
169
|
-
|
|
170
|
-
La tabla conserva agrupación estable, columnas configurables, memoización, exclusiones y sincronización de qualifiers por identificadores. La barra conserva navegación por teclado, autocompletado y filtros de texto, rangos, fechas, presencia y carpetas. `Calendar` usa español por defecto y acepta otra locale. Los textos y configuraciones de filtros se pueden personalizar por props.
|
|
171
|
-
|
|
172
|
-
Los componentes compartidos conservan el tema de LaTribu. Se incorporaron atributos `data-variant`/`data-size` del botón, scroll para paneles largos y persistencia opcional del sidebar. Se mantienen `Button.asChild`, estados deshabilitados y skeletons deterministas. `AvatarImage` delega carga y fallback a Base UI; conserva carga diferida y recuperación al cambiar `src`. El export original `Toaster` permanece disponible; `ThemedToaster` agrega los estilos e iconos compartidos.
|
|
173
|
-
|
|
174
|
-
##
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
pnpm test:
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
pnpm
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
pnpm
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
El
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
Los
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
1
|
+
# beez-ui
|
|
2
|
+
|
|
3
|
+
Biblioteca de componentes React reutilizables, con adaptadores opcionales por framework y tema compartido. Reúne los componentes de LaTribu y las funcionalidades reutilizables de agenda-mensual.
|
|
4
|
+
|
|
5
|
+
## Storybook
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
pnpm storybook
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
Abre `http://localhost:6006` para explorar los componentes con controles de texto,
|
|
12
|
+
variantes, tamaños, estados y comportamiento. El selector de la barra permite
|
|
13
|
+
probar el tema claro, oscuro o del sistema. Las stories de componentes compuestos
|
|
14
|
+
incluyen sus piezas en ejemplos completos; los campos editables y selectores
|
|
15
|
+
sincronizan sus interacciones con Controls. `BeezUIProvider` configura el preview
|
|
16
|
+
y no forma parte del catálogo. Las notificaciones se exploran en `ThemedToaster`,
|
|
17
|
+
sin duplicar una story de `Toaster`; `WhatsappIcon` está en la sección `Icons`.
|
|
18
|
+
|
|
19
|
+
```bash
|
|
20
|
+
pnpm build-storybook # Genera storybook-static para servirlo o publicarlo
|
|
21
|
+
pnpm typecheck:stories # Comprueba stories y configuración con TypeScript
|
|
22
|
+
pnpm test:storybook # Build y navegación/interacciones en Chromium y WebKit
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
El catálogo consume los exports públicos y el CSS compilado de la librería. Los
|
|
26
|
+
scripts compilan `beez-ui` antes de arrancar; si editás sus fuentes con Storybook
|
|
27
|
+
abierto, ejecutá `pnpm build` para actualizar el paquete que muestra el preview.
|
|
28
|
+
Los cambios en las stories se actualizan durante el desarrollo. Storybook y sus
|
|
29
|
+
addons son dependencias de desarrollo y no se incluyen en el paquete publicado.
|
|
30
|
+
|
|
31
|
+
Configuración basada en [React con Vite](https://storybook.js.org/docs/get-started/frameworks/react-vite)
|
|
32
|
+
y [Controls](https://storybook.js.org/docs/essentials/controls).
|
|
33
|
+
|
|
34
|
+
## Uso del paquete
|
|
35
|
+
|
|
36
|
+
```tsx
|
|
37
|
+
import { Button, Avatar, AvatarImage, DataTable, Calendar } from "beez-ui";
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
Agrupar los imports de componentes desde la raíz. El paquete publica JavaScript ESM y declaraciones TypeScript en `dist`; el consumidor no necesita transpilar el código fuente de la librería. La gramática de filtros y los helpers de mes-año son independientes de React.
|
|
41
|
+
|
|
42
|
+
La utilidad `cn`, también exportada desde `beez-ui`, usa el paquete `cn` para combinar clases condicionales y resolver conflictos de Tailwind.
|
|
43
|
+
|
|
44
|
+
```css
|
|
45
|
+
@import "beez-ui/styles.css";
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
`beez-ui/styles.css` es CSS listo para el navegador: incluye reset, utilidades, tema claro/oscuro, radios y fuentes locales Geist, Poppins e IBM Plex Mono. No requiere Tailwind, plugins PostCSS ni declaraciones `@source` en el consumidor. Las clases se compilan en el build de la biblioteca y se publican en `dist/styles.css`; `styles.source.css` es la entrada de desarrollo y no se distribuye.
|
|
49
|
+
|
|
50
|
+
Los consumidores pueden sobrescribir tokens mediante CSS normal. Poppins se reserva para títulos grandes mediante `--font-display`; las licencias se incluyen en `assets/fonts`. Si la aplicación usa Tailwind para sus propios estilos puede mantenerlo, pero ya no necesita escanear beez-ui.
|
|
51
|
+
|
|
52
|
+
`DropdownMenuContent` toma el ancho natural de sus opciones, con un mínimo de 12 rem y un máximo limitado por el espacio disponible. No hereda el ancho del botón disparador: los menús abiertos desde un icono deben mantener sus etiquetas legibles. Para un ancho específico, usar `className` y ajustar también el mínimo cuando se necesite un menú más pequeño.
|
|
53
|
+
|
|
54
|
+
Los componentes usan por defecto los espaciados compactos de Agenda: `Select` mide 2 rem (1.75 rem en tamaño pequeño), `TabsList` horizontal mide 2 rem y `PopoverContent` usa 0.625 rem de padding. Los menús y submenús tienen un mínimo de 12 rem, con filas compactas. `Dialog` y `AlertDialog` usan 1 rem de padding y un footer con borde superior y fondo diferenciado; `Textarea` distingue el estado deshabilitado mediante su fondo. Estos valores conservan los colores y fuentes del tema compartido. Son cambios de los defaults, sin una prop adicional para activarlos; los consumidores pueden personalizarlos mediante `className`.
|
|
55
|
+
|
|
56
|
+
Los `Sheet` superiores e inferiores limitan su altura al viewport dinámico (`100dvh`) y permiten desplazar el contenido para mantener accesibles las acciones de paneles largos.
|
|
57
|
+
|
|
58
|
+
## Movimiento
|
|
59
|
+
|
|
60
|
+
Las nuevas animaciones usan la dependencia `motion`: `animate` controla la
|
|
61
|
+
reproducción, `hover` y `press` los gestos, y `AnimatePresence` / `usePresence`
|
|
62
|
+
retienen los overlays durante su salida. Los presets y tiempos viven en
|
|
63
|
+
`src/motion/`. No se usan keyframes CSS para estas animaciones.
|
|
64
|
+
|
|
65
|
+
`MotionSlot` anima el nodo original del primitive mediante refs compuestos,
|
|
66
|
+
sin agregar wrappers al DOM ni reemplazar sus handlers. Las curvas y springs
|
|
67
|
+
siguen los tokens de [beui motion](https://beui.dev/components/motion):
|
|
68
|
+
|
|
69
|
+
- `Button` se comprime con spring a 0.93 y se eleva a 1.02 al hover, solo en
|
|
70
|
+
dispositivos con hover real (`(hover: hover) and (pointer: fine)`); los ítems de
|
|
71
|
+
`Sidebar` y `Tabs` se comprimen a 0.98.
|
|
72
|
+
- `Checkbox` y `RadioGroup` se comprimen a 0.92. La marca del checkbox aparece
|
|
73
|
+
con pop y trazo (`pathLength`) y sale con blur; el punto del radio aparece con spring.
|
|
74
|
+
- El thumb de `Switch` viaja con un spring pesado y se aplasta mientras se presiona.
|
|
75
|
+
- `Input`, `Textarea`, `InputGroup` y `SelectTrigger` tiemblan al pasar a
|
|
76
|
+
`aria-invalid="true"`; `FormMessage` entra con blur.
|
|
77
|
+
- `Tooltip` entra con blur, escala y desplazamiento desde el trigger.
|
|
78
|
+
`Popover`, `HoverCard`, `DropdownMenu` y `Select` escalan desde 0.96 y se revelan
|
|
79
|
+
con un clip desde la esquina más cercana al trigger.
|
|
80
|
+
- `Dialog` y `AlertDialog` suben con spring; `Sheet` entra desde su borde con spring
|
|
81
|
+
y sale con la curva de cajón (0.24 s), sin demorar la siguiente interacción.
|
|
82
|
+
- `GlideSlot` desliza el indicador activo entre ítems como un `layoutId` compartido:
|
|
83
|
+
la pestaña activa de `Tabs` (fondo o subrayado), el ítem activo de `SidebarMenu`, la
|
|
84
|
+
página actual de `PaginationContent`, y al navegar con teclado el ítem resaltado de
|
|
85
|
+
`DropdownMenu` y `Select` y la sugerencia activa de `FilterQueryBar`. Con el puntero,
|
|
86
|
+
esos resaltados lo siguen al instante: el propio puntero ya marca la posición.
|
|
87
|
+
- Las superficies flotantes se revelan con un clip que deja 24 px libres fuera de la
|
|
88
|
+
caja, así su borde (`ring`) y su sombra se ven desde el primer frame. Una copia
|
|
89
|
+
transitoria viaja entre ítems y se elimina al llegar, devolviendo el estilo al ítem.
|
|
90
|
+
- El chevron de `SelectTrigger` gira 180° al abrir y los chevrons de `DataTable`
|
|
91
|
+
(grupos y columnas) giran en lugar de cambiar de ícono; CSS define el ángulo final.
|
|
92
|
+
- Las opciones del `Select` entran escalonadas con blur (las primeras 10; el resto
|
|
93
|
+
solo se desvanece) y los checks de ítems de `Select` y `DropdownMenu` aparecen con pop.
|
|
94
|
+
- El ícono de `AnimatedThemeToggler` cambia con blur y escala; el botón de cierre de
|
|
95
|
+
`Dialog` aparece con un pop demorado.
|
|
96
|
+
- El contenido de `Tabs` entra con un desplazamiento de 4 px y `Alert` entra con blur.
|
|
97
|
+
Cards y enlaces responden al hover; el avatar bajo el puntero de un `AvatarGroup` se
|
|
98
|
+
eleva. Un brillo recorre el `Skeleton` desde su `::after` con reproducción nativa,
|
|
99
|
+
sin trabajo por frame en JavaScript.
|
|
100
|
+
- `Calendar` desliza el mes entrante desde el lado de la navegación (invertido en RTL).
|
|
101
|
+
- `AvatarImage` se revela con blur y un zoom de 1.06 al terminar de cargar; las imágenes
|
|
102
|
+
ya cargadas al montar no se animan.
|
|
103
|
+
- El cursor de `TypingAnimation` queda fijo mientras escribe y parpadea en reposo. Las animaciones especializadas
|
|
104
|
+
existentes de Embla, Sonner y rough-notation se conservan.
|
|
105
|
+
|
|
106
|
+
El contenido que está saliendo deja de ser interactivo y accesible de inmediato.
|
|
107
|
+
Cada familia de overlays tiene un contexto de visibilidad independiente para
|
|
108
|
+
soportar composiciones anidadas; los portales sin nodo visible no bloquean el
|
|
109
|
+
cierre del padre. `Select` conserva su desmontaje nativo y usa Motion en la entrada.
|
|
110
|
+
La elección explícita de `forceMount` permanece bajo control del consumidor.
|
|
111
|
+
|
|
112
|
+
Se respeta `prefers-reduced-motion`: las nuevas animaciones se cancelan y se
|
|
113
|
+
restauran los estilos; las anotaciones se dibujan sin animación y el texto aparece
|
|
114
|
+
completo, incluidas todas las palabras de una secuencia. Los controles del carrusel
|
|
115
|
+
avanzan directamente. El CSS solo aporta el fallback de movimiento reducido para
|
|
116
|
+
los efectos heredados. `BeezUIProvider` configura `MotionConfig` con
|
|
117
|
+
`reducedMotion="user"`. El primer render conserva el contrato de SSR.
|
|
118
|
+
|
|
119
|
+
El selector aplica el tema inmediatamente y anima su icono con Motion; no depende
|
|
120
|
+
de View Transitions nativas ni de una animación para completar el cambio. Los estilos temporales se liberan al terminar
|
|
121
|
+
la reproducción. Las stories permiten probar los gestos y estados reales; el
|
|
122
|
+
selector de tema de la story y la barra de Storybook se mantienen sincronizados.
|
|
123
|
+
|
|
124
|
+
## Providers de UI
|
|
125
|
+
|
|
126
|
+
Elegir un único `BeezUIProvider` según el framework. Los componentes y `useTheme` siempre se importan desde `beez-ui`.
|
|
127
|
+
|
|
128
|
+
| Import del provider | Navegación | Imágenes de avatar |
|
|
129
|
+
| --- | --- | --- |
|
|
130
|
+
| `beez-ui` | Anclas nativas | `@unpic/react` |
|
|
131
|
+
| `beez-ui/next` | `next/link` | `next/image` |
|
|
132
|
+
| `beez-ui/tanstack` | TanStack Router | `@unpic/react` |
|
|
133
|
+
|
|
134
|
+
```tsx
|
|
135
|
+
"use client";
|
|
136
|
+
|
|
137
|
+
import type { ReactNode } from "react";
|
|
138
|
+
import { BeezUIProvider } from "beez-ui/next";
|
|
139
|
+
|
|
140
|
+
export function Providers({ children }: { children: ReactNode }) {
|
|
141
|
+
return (
|
|
142
|
+
<BeezUIProvider themeOptions={{ storageKey: "tutribu-theme", defaultTheme: "system" }}>
|
|
143
|
+
{children}
|
|
144
|
+
</BeezUIProvider>
|
|
145
|
+
);
|
|
146
|
+
}
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
Todos los providers usan `next-themes` con clases CSS. El consumidor configura `themeOptions` y conecta sus controles a `useTheme` desde `beez-ui`. Al migrar una aplicación, conservar su clave de almacenamiento y retirar los scripts y estados anteriores que modifiquen el tema. En Next, mantener `suppressHydrationWarning` en el elemento `html` porque el provider restaura la preferencia antes de hidratar.
|
|
150
|
+
|
|
151
|
+
El provider de Next desactiva prefetch y optimización de imágenes por defecto, como LaTribu. Se activan con `prefetch` y `optimizeImages`; para optimizar imágenes remotas hay que configurar sus hosts en la app. `Link` y los enlaces de paginación usan el adaptador del provider. El contrato común de `Link` acepta href como string y atributos de ancla, no todas las opciones exclusivas de Next.
|
|
152
|
+
|
|
153
|
+
El provider de TanStack se monta dentro del router de la aplicación. Preserva query y hash; `prefetch` activa precarga por intención. TanStack no aporta un componente Image propio: Unpic genera variantes responsivas para CDNs compatibles y conserva las URLs que no reconoce; no instala un servidor de optimización.
|
|
154
|
+
|
|
155
|
+
Next y TanStack Router son peers opcionales aislados en sus entrypoints. El provider nativo admite overrides mediante `components`. Sin provider, los componentes conservan anclas e imágenes HTML como fallback.
|
|
156
|
+
|
|
157
|
+
## Responsabilidades del consumidor
|
|
158
|
+
|
|
159
|
+
- Tema: `AnimatedThemeToggler` y `ThemedToaster` consumen el contexto compartido. Sus props explícitas de tema siguen disponibles para usos controlados.
|
|
160
|
+
- Navegación: `PaginationNext`, `PaginationPrevious` y `PaginationLink` usan anclas nativas. El prop opcional `component` admite el adaptador del router que elija la app. Sin proveedor usa el elemento nativo; con el proveedor de Next usa su navegación cliente.
|
|
161
|
+
- Sidebar: `defaultOpen` y el modo controlado conservan la semántica de LaTribu. `storageKey` activa opcionalmente persistencia local segura tras hidratar, sin cambiar la cookie pública `sidebar_state` ni sus siete días de duración.
|
|
162
|
+
- Formularios y tablas: el consumidor provee sus datos, validaciones y callbacks. No se importan servicios, modelos de negocio ni endpoints de agenda-mensual.
|
|
163
|
+
|
|
164
|
+
## Componentes incorporados desde agenda-mensual
|
|
165
|
+
|
|
166
|
+
`Alert`, `AnimatedThemeToggler`, `Calendar`, `DataTable`, `FilterQueryBar`, `Form`, `Highlighter`, `InputGroup`, `Label`, `RadioGroup`, `TypingAnimation` y `ThemedToaster`, junto con sus subcomponentes, tipos y gramática de filtros.
|
|
167
|
+
|
|
168
|
+
`FilterQueryBar` mantiene el foco en el input mientras se recorren las sugerencias con el puntero o las flechas. Enter aplica la opción activa; interactuar con el input no cierra la lista.
|
|
169
|
+
|
|
170
|
+
La tabla conserva agrupación estable, columnas configurables, memoización, exclusiones y sincronización de qualifiers por identificadores. La barra conserva navegación por teclado, autocompletado y filtros de texto, rangos, fechas, presencia y carpetas. `Calendar` usa español por defecto y acepta otra locale. Los textos y configuraciones de filtros se pueden personalizar por props.
|
|
171
|
+
|
|
172
|
+
Los componentes compartidos conservan el tema de LaTribu. Se incorporaron atributos `data-variant`/`data-size` del botón, scroll para paneles largos y persistencia opcional del sidebar. Se mantienen `Button.asChild`, estados deshabilitados y skeletons deterministas. `AvatarImage` delega carga y fallback a Base UI; conserva carga diferida y recuperación al cambiar `src`. El export original `Toaster` permanece disponible; `ThemedToaster` agrega los estilos e iconos compartidos.
|
|
173
|
+
|
|
174
|
+
## Componentes de producto reutilizables
|
|
175
|
+
|
|
176
|
+
Provienen de las carpetas de producto de LaTribu y agenda-mensual y quedaron desacoplados de su dominio: reciben datos ya resueltos y textos por props, con valores por defecto en español.
|
|
177
|
+
|
|
178
|
+
- Movimiento: `PresenceSwap`, `AnimatedCount`, `AnimatedCollapse` y `AnimatedListItem`. Los tokens que usa la biblioteca se exportan desde la raíz y desde `beez-ui/motion-tokens`, así las apps animan sus superficies con las mismas curvas y springs en lugar de copiarlos.
|
|
179
|
+
- Feedback: `BouncingDotsLoader`, `ProgressRing`, `EmptyState`, `ErrorState`, `InfoPopover`, `ConfirmDeleteButton` y `ReactionButton`. El loader y la entrada del título de `MonthCalendarHeader` usan keyframes CSS porque se renderizan en el servidor; el fallback de movimiento reducido los detiene.
|
|
180
|
+
- Cuenta y sesión: `AccountMenu` (inicio de sesión mediante `signInHref` o `onSignIn`), `OpenInBrowserCta`, `ExternalBrowserHandoff` y los helpers `detectInAppBrowser` y `buildExternalBrowserUrl`.
|
|
181
|
+
- Contenido: `RichTextContent`, `RichMarkdownContent`, `RichLinkEditor` y `useRichLinkEditor`. Solo interpretan links en markdown, URLs sueltas, listas y negrita; el HTML del contenido nunca se renderiza como markup.
|
|
182
|
+
- Notificaciones: `NotificationBell` y `NotificationPanel` reciben `NotificationPanelItem` (`id`, `title`, `detail`, `sentAtLabel`, `href`, `isUnread`); la app traduce sus notificaciones a ese formato. Con `surface="responsive"` se renderizan el popover y el sheet hasta hidratar, y después solo el que corresponde al viewport.
|
|
183
|
+
- Calendario: `MonthGrid` y `MonthCalendarHeader` trabajan con claves `YYYY-MM` y `YYYY-MM-DD` sin zona horaria; la app decide en qué zona convierte cada instante en día. La navegación acepta `href` (link del router) o `onSelect`.
|
|
184
|
+
- Archivos: `FileUpload`, `FileUploadDropZone`, `FileUploadList` y `FileUploadItem` validan tipo y tamaño, pero no suben archivos: el progreso y los errores los informa la app.
|
|
185
|
+
- PWA: `PwaUpdateControl` aparece solo cuando hay un service worker en espera y le envía `{ type: "SKIP_WAITING" }` (configurable con `skipWaitingMessage`).
|
|
186
|
+
- Hooks y utilidades: `useIsHydrated`, `useMinuteClock`, `useViewerTimeZone`, `useHorizontalSwipe`, `usePrefersReducedMotion`, `formatFileSize`, `copyTextToClipboard`, `getNameInitials`, búsqueda difusa y helpers de URL.
|
|
187
|
+
|
|
188
|
+
`EmojiPicker` vive en el entrypoint opcional `beez-ui/emoji-picker` para no sumar `emoji-picker-react` a quien no lo usa. Hay que instalarlo como dependencia de la app (`pnpm add emoji-picker-react`); la librería se carga recién al abrir el selector, nunca durante el render del servidor.
|
|
189
|
+
|
|
190
|
+
## React Compiler
|
|
191
|
+
|
|
192
|
+
El build usa el port de React Compiler en Rust de [Oxc](https://oxc.rs/blog/2026-08-18-react-compiler-support), mediante `oxc-transform-react`. Esta integración sigue marcada como experimental por Oxc.
|
|
193
|
+
|
|
194
|
+
Las optimizaciones se incluyen en el JavaScript publicado: el consumidor no necesita habilitar React Compiler en Vite, Next ni otro bundler. El target es React 19 y utiliza `react/compiler-runtime`, incluido en el peer React 19.2; no se añade un runtime independiente.
|
|
195
|
+
|
|
196
|
+
TypeScript 7 valida los tipos y genera las declaraciones. Oxc recibe los fuentes originales y ejecuta React Compiler antes de eliminar TypeScript y transformar JSX. Conserva ESM, los exports y las directivas de cliente. Sólo los módulos cuyo prólogo declara `"use client"` reciben memoización automática; los módulos compatibles con Server Components se emiten sin cachés de cliente. Esto evita introducir hooks del runtime de cliente en el render servidor de Next.
|
|
197
|
+
|
|
198
|
+
La cobertura depende de las heurísticas del compilador y de las reglas de React: algunas funciones conservan su implementación sin optimizar. Las memoizaciones y comentarios del código fuente permanecen intactos. El build informa cuántos módulos incluyen memoización automática y falla ante errores fatales de transformación.
|
|
199
|
+
|
|
200
|
+
```sh
|
|
201
|
+
# Comparar el comportamiento sin memoización automática.
|
|
202
|
+
pnpm test:uncompiled
|
|
203
|
+
|
|
204
|
+
# Volver a generar la distribución optimizada.
|
|
205
|
+
pnpm build
|
|
206
|
+
```
|
|
207
|
+
|
|
208
|
+
`test:uncompiled` usa `pnpm build --no-react-compiler` y ejecuta Vitest. CI y `release:prepare` ejecutan esa comparación antes del check normal, que restaura el build optimizado. Los consumidores de prueba no habilitan un segundo compilador: ejercen el paquete generado, incluido un componente de servidor real en Next.
|
|
209
|
+
|
|
210
|
+
## Desarrollo y validación
|
|
211
|
+
|
|
212
|
+
Usar pnpm **12.3.4**. Las dependencias tienen rangos `^` y el lockfile fija las versiones verificadas.
|
|
213
|
+
|
|
214
|
+
```sh
|
|
215
|
+
pnpm install --frozen-lockfile
|
|
216
|
+
pnpm check
|
|
217
|
+
pnpm exec playwright install chromium webkit
|
|
218
|
+
pnpm test:browser
|
|
219
|
+
pnpm build
|
|
220
|
+
pnpm release:prepare
|
|
221
|
+
```
|
|
222
|
+
|
|
223
|
+
`pnpm build` genera las declaraciones con TypeScript 7, JavaScript con Oxc/React Compiler y CSS con el CLI de Tailwind. `pnpm check` ejecuta ESLint 10, los typechecks separados de código y tests con TypeScript 7, y Vitest 5. `tests/tsconfig.json` incorpora los matchers de Testing Library y los tipos de Vite sin incluirlos en el código de producción. `test:browser` verifica una app React/Vite nativa y una app Next real en Chromium y WebKit, tanto en desktop como en móvil. Los tests unitarios importan los archivos compilados. Los consumidores de navegador no instalan plugins de Tailwind, y una prueba adicional sirve el tarball por HTTP sin procesadores CSS para verificar estilos computados y carga de fuentes. Una prueba adicional instala el tarball en un consumidor aislado sin Next y verifica render, filtrado y declaraciones públicas.
|
|
224
|
+
|
|
225
|
+
Los tests resuelven `beez-ui`, `beez-ui/next`, `beez-ui/tanstack` y `beez-ui/emoji-picker` mediante rutas explícitas a las declaraciones compiladas en `tests/tsconfig.json`. Ejecutar `pnpm build` después de clonar o si falta `dist`; los comandos de validación completos ya lo hacen. Si el editor conserva diagnósticos anteriores después del build, reiniciar su servidor de TypeScript.
|
|
226
|
+
|
|
227
|
+
El compilador `tsc` es TypeScript 7. Para `typescript-eslint`, se mantiene la [API de compatibilidad oficial de TypeScript 6](https://devblogs.microsoft.com/typescript/announcing-typescript-7-0/#running-side-by-side-with-typescript-6.0) mediante un alias; no reemplaza el compilador de los typechecks.
|
|
228
|
+
|
|
229
|
+
## Crear y publicar una versión
|
|
230
|
+
|
|
231
|
+
Desde el repositorio de beez-ui, configurar `NPM_TOKEN` con permiso de publicación en el entorno o en `.env`, tomando `.env.example` como referencia. Mantener el archivo local existente si ya está configurado.
|
|
232
|
+
|
|
233
|
+
### Un solo comando: `pnpm create-version` (alias `pnpm cv`)
|
|
234
|
+
|
|
235
|
+
```sh
|
|
236
|
+
pnpm create-version # diagnóstico, plan y release interactivo
|
|
237
|
+
pnpm create-version --bump minor # patch | minor | major sin preguntar
|
|
238
|
+
pnpm create-version --set-version 0.7.0 # versión exacta
|
|
239
|
+
pnpm create-version --dry-run # solo muestra el diagnóstico y el plan
|
|
240
|
+
pnpm cv # alias de pnpm create-version
|
|
241
|
+
```
|
|
242
|
+
|
|
243
|
+
El comando hace `git fetch`, consulta npm y muestra un panel con la rama, el upstream, el working tree, `main` frente a origin, la versión local, la última versión publicada, los commits posteriores al último cambio de versión y el artefacto ya preparado. Después decide qué falta:
|
|
244
|
+
|
|
245
|
+
- **Release nuevo**: si hay commits sin publicar, sugiere `patch`, `minor` o `major` según los commits (breaking change, funcionalidades o solo arreglos) y pregunta con las flechas. Las notas salen del bloque `## [Unreleased]` de `CHANGELOG.md` (ver la sección CHANGELOG más abajo); si está vacío, invoca a Codex (`codex exec`) para completarlo desde los commits sin publicar y muestra el resultado, y si Codex no está o no escribe nada válido, el release se corta. Tras confirmar ejecuta el flujo validado completo (ver abajo).
|
|
246
|
+
- **Release a medio terminar**: si `package.json` tiene una versión que npm todavía no tiene, completa solo lo que falta: si `package.json` y `CHANGELOG.md` quedaron sin commitear los commitea primero; después prepara el artefacto (reusa automáticamente el ya preparado cuando es posterior al último cambio de código, y `release:publish` lo vuelve a verificar), pushea el commit de release si todavía no está en origin y publica (la confirmación del inicio cubre la publicación). Nunca vuelve a subir la versión.
|
|
247
|
+
- **Todo al día**: si la versión está publicada y no hay commits nuevos, no hace nada.
|
|
248
|
+
|
|
249
|
+
`--set-version` sólo acepta el siguiente patch, minor o major de la versión actual (desde `0.6.0`: `0.6.1`, `0.7.0` o `1.0.0`); rechaza versiones menores, iguales, prerelease o que salteen versiones. Los releases salen sólo desde `main` con upstream configurado. Se detiene y explica qué hacer ante otra rama, `HEAD` desacoplado, cambios sin commitear (salvo `CHANGELOG.md` en un release nuevo, que viaja en el commit de release, o `package.json` y `CHANGELOG.md` de un release a medio terminar), secciones de `[Unreleased]` fuera de las de Keep a Changelog, `main` divergida o npm sin respuesta; un bloqueo termina con código 0 porque ya está explicado en pantalla, y un paso fallido termina con código 1. Si `main` está atrás, la actualiza con fast-forward antes de versionar. Si algo falla, basta con volver a ejecutar `pnpm create-version`: retoma desde el primer paso pendiente. Las opciones de cada pregunta están numeradas: se eligen apretando su número, o con las flechas y Enter; cada versión muestra debajo qué significa patch, minor o major. Sin terminal interactiva cada pregunta toma su opción por defecto. El tiempo total que muestra al final no cuenta el tiempo que espera tus respuestas.
|
|
250
|
+
|
|
251
|
+
La lógica pura vive en `scripts/release-plan.js` y `scripts/changelog.js` (lectura y release de `[Unreleased]`), la invocación de Codex en `scripts/changelog-ai.js`, la lectura de Git y npm en `scripts/release-state.js`, la UI de terminal (cajas, colores, íconos Nerd Font, spinner y selector) en `scripts/terminal-ui.js` y el orquestador en `scripts/release.js`, sin dependencias nuevas. Los íconos requieren una Nerd Font en la terminal.
|
|
252
|
+
|
|
253
|
+
### CHANGELOG
|
|
254
|
+
|
|
255
|
+
`CHANGELOG.md` sigue [Keep a Changelog](https://keepachangelog.com/es-ES/1.1.0/). Cada cambio agrega sus entradas en el bloque `## [Unreleased]`, agrupadas en `### Added`, `### Changed`, `### Deprecated`, `### Removed`, `### Fixed` y `### Security` (solo las que apliquen). Nunca se escriben la versión ni la fecha a mano: `pnpm create-version` las agrega al publicar. Las versiones anteriores a este formato (`## 0.6.1 - 2026-09-26`) siguen siendo válidas. La regla completa está en `AGENTS.md`.
|
|
256
|
+
|
|
257
|
+
### Flujo validado de un release nuevo
|
|
258
|
+
|
|
259
|
+
1. Actualiza `package.json` y renombra `## [Unreleased]` a `## [X.Y.Z] - AAAA-MM-DD` (fecha UTC), dejando un `[Unreleased]` vacío arriba y conservando el historial (`scripts/release-version.js`). Si `[Unreleased]` no tiene cambios o usa secciones no válidas, no toca nada.
|
|
260
|
+
2. Commitea en el momento `package.json` y `CHANGELOG.md` (sólo esos dos archivos, conservando otros archivos staged), antes de las validaciones largas: si algo se corta después, queda un commit local y nunca metadata suelta.
|
|
261
|
+
3. Prepara la release: instalación congelada, tests sin React Compiler, build optimizado de JavaScript, tipos y CSS, lint, typechecks, tests unitarios y pruebas de navegador.
|
|
262
|
+
4. Genera el tarball en `releases/<version>-<sha256>/beez-ui-<version>.tgz` y valida su contenido, exports e integridad.
|
|
263
|
+
5. Pushea el commit de release a la rama upstream configurada, sólo si sigue siendo el commit actual.
|
|
264
|
+
6. Publica ese mismo artefacto en npm con acceso público y etiqueta `latest`.
|
|
265
|
+
|
|
266
|
+
La publicación usa el cliente oficial de npm para admitir su flujo interactivo de verificación en el navegador/2FA. Instalación, build y checks siguen usando pnpm 12. Ejecutar desde una terminal interactiva cuando la cuenta requiera autenticación adicional. El token se carga sólo al publicar y no se imprime. El repositorio no tiene `.npmrc`: pnpm 12 ignora las variables de entorno en credenciales controladas por el repositorio y avisaba en cada comando. `release:publish` crea un config temporal de npm fuera del repositorio que sólo referencia `${NPM_TOKEN}` (npm lo expande desde el entorno; el token no se escribe en disco ni en la línea de comandos), lo pasa con `--userconfig` y lo borra al terminar, también si la publicación falla (`scripts/npm-auth.js`).
|
|
267
|
+
|
|
268
|
+
El commit se limita a los dos archivos de metadatos, incluidos sus cambios previos; revisar el código antes de ejecutar la release. No crea tags ni hace force push. Si cambian el checkout, el upstream o los metadatos durante las validaciones, se detiene. También comprueba que los hooks de Git no hayan agregado archivos ni alterado los metadatos validados antes de pushear. Si falla una validación o el push, no publica y el commit de release queda en local: `pnpm create-version` lo detecta y retoma sólo lo que falte (preparar, pushear, publicar), sin volver a subir la versión. Si falla la publicación, comprobar primero si npm recibió la versión; si no, `pnpm create-version` reintenta sólo la publicación del mismo tarball.
|
|
269
|
+
|
|
270
|
+
Los pasos individuales siguen disponibles:
|
|
271
|
+
|
|
272
|
+
```sh
|
|
273
|
+
# Sólo validar y empaquetar la versión actual, sin publicarla.
|
|
274
|
+
pnpm release:prepare
|
|
275
|
+
|
|
276
|
+
# Publicar un artefacto ya preparado.
|
|
277
|
+
pnpm release:publish releases/<version>-<sha256>/beez-ui-<version>.tgz
|
|
278
|
+
```
|
|
279
|
+
|
|
280
|
+
`release:publish` vuelve a verificar nombre, versión, contenido y checksum antes de invocar `npm publish`. El paquete excluye fuentes privadas, tests, scripts, `.env` y `.npmrc`; incluye JavaScript, declaraciones, CSS, fuentes tipográficas y licencias. Conserva releases anteriores.
|
|
281
|
+
|
|
282
|
+
`prepack` ejecuta el build para los empaquetados manuales. `dist` y `releases` son generados e ignorados por Git. La CI verifica los checks y los tres providers en ambos motores de navegador en Linux y Windows; no publica automáticamente.
|
|
283
|
+
|
|
284
|
+
Tras publicar, los consumidores pueden instalar `pnpm add beez-ui`. También pueden instalar directamente el `.tgz` validado antes de una publicación. LaTribu consume la versión publicada en npm y fija la resolución e integridad mediante su lockfile, sin guardar tarballs locales.
|
|
285
|
+
|
|
286
|
+
Los componentes nuevos de shadcn/ui se agregan mediante su CLI en esta biblioteca y se exportan desde la raíz. No editar las copias instaladas en los consumidores.
|
|
287
|
+
|
|
288
|
+
## Procedencia
|
|
289
|
+
|
|
290
|
+
Fuentes originales: `guidomodarelli/TuTribu` (`components/ui`) y `agenda-mensual` (`src/components/ui`). Se preservan las funcionalidades y los comentarios que explican sus decisiones; la integración adapta imports, contratos y dependencias del consumidor. Consultar `LICENSE.md` para la licencia original de shadcn/ui y `assets/fonts/*-LICENSE.txt` para las fuentes. El icono de WhatsApp proviene del registry `@svgl`.
|