@astra-kit/ui 0.0.0 → 1.0.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 CHANGED
@@ -4,6 +4,8 @@ Todos los cambios relevantes de `@astra-kit/ui` se documentan en este archivo co
4
4
 
5
5
  ## [Unreleased]
6
6
 
7
+ ## [1.0.0] - 2026-10-18
8
+
7
9
  ### Changed
8
10
 
9
11
  - El paquete pasa a llamarse `@astra-kit/ui` y reinicia la numeración: reemplazá la dependencia `beez-ui` por `@astra-kit/ui` y todos los imports, incluidos los subpaths y el CSS (`@astra-kit/ui/next`, `@astra-kit/ui/styles.css`, …). El repositorio ahora es `guidomodarelli/astra-ui`.
@@ -12,4 +14,8 @@ Todos los cambios relevantes de `@astra-kit/ui` se documentan en este archivo co
12
14
 
13
15
  ### Removed
14
16
 
15
- - No se aceptan los nombres anteriores (`BeezUIProvider`, `BeezLinkProps`, `BeezImageProps`, `useBeezUIComponents`, `Beez Inter`/`Geist`/`Mono`, `--beez-reaction-active-color`, `data-beez-theme-menu`): hay que migrar todo de una vez. El historial de `beez-ui` 0.8.1–4.0.1 queda en `docs/history/beez-ui-changelog.md`.
17
+ - No se aceptan los nombres anteriores (`BeezUIProvider`, `BeezLinkProps`, `BeezImageProps`, `useBeezUIComponents`, `Beez Inter`/`Geist`/`Mono`, `--beez-reaction-active-color`, `data-beez-theme-menu`): hay que migrar todo de una vez. El historial de `beez-ui` 0.8.1–4.0.1 queda en [`docs/history/beez-ui-changelog.md`](https://github.com/guidomodarelli/astra-ui/blob/main/docs/history/beez-ui-changelog.md).
18
+
19
+ ### Fixed
20
+
21
+ - `DropdownMenu` con un `trigger` propio no disponible ya no abre el menú: ni con click o toque cuando el botón está deshabilitado (por su `disabled`, por un `<fieldset disabled>` o por estado interno del componente), ni con Enter, Espacio o flecha abajo cuando tiene `aria-disabled="true"`, como un `Button` en `loading`. Antes se abría porque el navegador igual entrega el `pointerdown` al botón deshabilitado.
package/README.md CHANGED
@@ -47,7 +47,7 @@ import { Avatar, Button, Calendar, DataTable } from "@astra-kit/ui";
47
47
  <Avatar name="Ana Núñez" src="/ana.jpg" />;
48
48
  ```
49
49
 
50
- Desde 3.0.0 los componentes adoptados de [Arc](https://uiarc.dev) usan la API pública de Arc: `Switch`, `Checkbox`, `RadioGroup`, `Badge`, `Avatar`, `AvatarGroup`, `Skeleton`, `Card`, `Alert`, `Tooltip`, `HoverCard`, `DropdownMenu`, `Select`, `Pagination`, `Calendar` y `Carousel` son componentes cerrados que se configuran por props (`items`, `options`, `members`, `content`, `title`); `Dialog` (`Dialog`, `DialogTrigger`, `DialogContent` con `title` y `description`, `DialogClose`), `Popover` y `Tabs` conservan las partes de Arc. Cada uno suma solo las extensiones que Arc no cubre, con copy en español por defecto, por ejemplo `getHref` en `Pagination`, `trigger` e ítems con `href` en `DropdownMenu`, `onOpenChange` en `HoverCard`, `footer` y el modo `alert` en `Dialog` (reemplaza a `AlertDialog`), `hideLabel` en `Select` y `onSettle` en `Carousel`. La tabla de migración desde 2.x está en [Migración a 3.0.0](#migración-a-300).
50
+ Los componentes adoptados de [Arc](https://uiarc.dev) usan la API pública de Arc: `Switch`, `Checkbox`, `RadioGroup`, `Badge`, `Avatar`, `AvatarGroup`, `Skeleton`, `Card`, `Alert`, `Tooltip`, `HoverCard`, `DropdownMenu`, `Select`, `Pagination`, `Calendar` y `Carousel` son componentes cerrados que se configuran por props (`items`, `options`, `members`, `content`, `title`); `Dialog` (`Dialog`, `DialogTrigger`, `DialogContent` con `title` y `description`, `DialogClose`), `Popover` y `Tabs` conservan las partes de Arc. Cada uno suma solo las extensiones que Arc no cubre, con copy en español por defecto, por ejemplo `getHref` en `Pagination`, `trigger` e ítems con `href` en `DropdownMenu`, `onOpenChange` en `HoverCard`, `footer` y el modo `alert` en `Dialog` (reemplaza a `AlertDialog`), `hideLabel` en `Select` y `onSettle` en `Carousel`. La tabla de migración desde `beez-ui` 2.x está en [`docs/history/beez-ui-changelog.md`](https://github.com/guidomodarelli/astra-ui/blob/main/docs/history/beez-ui-changelog.md).
51
51
 
52
52
  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.
53
53
 
@@ -67,32 +67,6 @@ Los componentes usan por defecto los espaciados compactos de Agenda: `Select` mi
67
67
 
68
68
  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.
69
69
 
70
- ## Migración a 3.0.0
71
-
72
- | Componente | 2.x | 3.0.0 |
73
- | --- | --- | --- |
74
- | `Switch` | `size="sm"` | Un solo tamaño, sin `size` |
75
- | `RadioGroup` | `RadioGroup` + `RadioGroupItem` | `<RadioGroup label options={[{ value, label, description }]} value onValueChange />` |
76
- | `Badge` | `variant` (`default`, `secondary`, `outline`, `ghost`, `link`, `destructive`) | `tone` (`neutral`, `success`, `info`, `warning`, `danger`); `destructive` pasa a `danger`, el resto a `neutral` |
77
- | `Avatar` | `Avatar` + `AvatarImage` + `AvatarFallback` (+ `AvatarBadge`) | `<Avatar name src size fallback badge />`; `size="default"` pasa a `md` |
78
- | `AvatarGroup` | `AvatarGroup` con `Avatar` hijos + `AvatarGroupCount` | `<AvatarGroup members={[{ name, src, status }]} max label />`; con una vista previa de los integrantes, `total` hace que el chip +N cuente contra el total |
79
- | `Skeleton` | `<Skeleton className="h-4 w-24" />` | `<Skeleton lines={1} className />`, `avatar`, `label`, o `loading` con hijos |
80
- | `Card` | `CardHeader`, `CardTitle`, `CardDescription`, `CardAction`, `CardContent`, `CardFooter`, `CardMedia` | `title`, `description`, `action`, `children`, `footer`, `media` |
81
- | `Alert` | `AlertTitle`, `AlertDescription`, `AlertAction`, `variant="destructive"` | `<Alert title tone="danger" action>detalle</Alert>` |
82
- | `Tooltip` | `TooltipProvider` + `Tooltip` + `TooltipTrigger asChild` + `TooltipContent` | `<Tooltip content side align>{trigger}</Tooltip>`, sin provider |
83
- | `Popover` | `PopoverAnchor`, `PopoverHeader`, `PopoverTitle`, `PopoverDescription`; `align` centrado por defecto | Solo `Popover`, `PopoverTrigger`, `PopoverContent`, `PopoverClose`; `align="start"` por defecto |
84
- | `HoverCard` | `HoverCard` + `HoverCardTrigger asChild` + `HoverCardContent` | `<HoverCard content onOpenChange className>{trigger}</HoverCard>` |
85
- | `DropdownMenu` | `DropdownMenuTrigger asChild`, `Content`, `Item`, `Separator`, `RadioGroup`, `RadioItem`, `CheckboxItem`, `Shortcut`, `Sub*` | `<DropdownMenu label trigger items={[{ label, icon, onSelect, href, destructive, separatorBefore, checked, trailing }]} selection />`; sin submenús. El click dentro del menú no sube por el árbol de React hasta los contenedores que lo envuelven |
86
- | `Select` | `SelectTrigger`, `SelectValue placeholder`, `SelectContent`, `SelectItem` | `<Select label hideLabel placeholder options={[{ value, label, disabled }]} value onValueChange triggerClassName />`; `aria-describedby` del trigger pasa a `Select` y `options` acepta listas `as const` |
87
- | `Tabs` | `TabsList variant="line"`, `tabsListVariants` | Solo la lista segmentada |
88
- | `Pagination` | `PaginationContent`, `PaginationItem`, `PaginationLink`, `PaginationPrevious`, `PaginationNext`, `PaginationEllipsis` | `<Pagination page pageCount onPageChange getHref label />`; sin `pageCount`, `hasNextPage` dibuja solo Anterior y Siguiente. `onPageChange(page, event)` recibe el click: con `getHref`, `event.preventDefault()` pagina en el lugar sin navegar |
89
- | `Dialog` | `DialogHeader`, `DialogTitle`, `DialogDescription`, `DialogFooter`, `DialogPortal`, `DialogOverlay` | `<DialogContent title description footer hideTitle>`; el cierre se llama "Cerrar diálogo". Lo que acompañaba al título dentro de `DialogHeader` (etiquetas, estado) pasa a `headerContent`, y el ref del cierre a `closeButtonRef` |
90
- | `AlertDialog` | `AlertDialog`, `AlertDialogContent`, `AlertDialogAction`, `AlertDialogCancel`… y `@astra-kit/ui/alert-dialog` | `<Dialog alert>` con `DialogContent` y `DialogClose asChild` para cancelar y confirmar |
91
- | `Calendar` | `mode`, `selected`, `onSelect`, `disabled`, `defaultMonth`, `components`, `classNames` | `<Calendar value onChange month onMonthChange minDate maxDate disabledDates locale showToday />`; solo selección simple |
92
- | `Carousel` | `CarouselContent`, `CarouselItem`, `CarouselPrevious`, `CarouselNext`, `CarouselIndicators`, `opts`, `setApi`, `CarouselApi` | `<Carousel label loop defaultIndex onIndexChange onSettle slideSize>{slides}</Carousel>`; `reInit` ya no hace falta. Las clases de `CarouselContent` y de su pista pasan a `viewportClassName` y `trackClassName` |
93
- | `AccountMenu` | `children` con `DropdownMenuItem` | `items` con los ítems de `DropdownMenu` |
94
- | `DataTable` | `columnVisibilityMenuExtraContent` | `columnVisibilityMenuExtraItems` |
95
-
96
70
  ## Movimiento
97
71
 
98
72
  El movimiento sigue a [Arc](https://uiarc.dev): explica causa y efecto (qué se abrió,
@@ -293,39 +267,11 @@ El compilador `tsc` es TypeScript 7. El paquete `typescript` apunta a la [API de
293
267
 
294
268
  ## Crear y publicar una versión
295
269
 
296
- ### Desde GitHub Actions
297
-
298
- El workflow **Release** se ejecuta automáticamente con cada push o merge a `main`,
299
- incluidos los cambios de `package.json`. También se puede iniciar en GitHub desde
300
- **Actions → Release → Run workflow**, seleccionando `main`.
301
- El workflow usa `pnpm create-version --accept-suggested`: astra-rp calcula la versión
302
- y verifica que `[Unreleased]` tenga entradas escritas a mano, cierra esa sección con la versión, prepara y valida el tarball, crea y sube
303
- el commit y el tag y publica en npm con trusted publishing (OIDC).
304
-
305
- El disparador también incluye los pushes que cambian `package.json`, pero
306
- astra-rp no retoma una versión editada a mano en un commit común: necesita
307
- su commit de versión y tag de release. Para el flujo automático, dejar que
308
- astra-rp aumente la versión según los commits.
309
-
310
- No necesita secrets manuales: pasa `GITHUB_TOKEN` como `NPM_TOKEN`, con
311
- `contents: write` para subir el release y `packages: write` para publicar.
312
- El token se entrega solo al paso de release. El workflow conserva el historial
313
- completo de Git, instala Chromium y WebKit para las validaciones y serializa
314
- los releases sin cancelar uno que ya esté en curso. Solo permite ejecutarlos
315
- sobre `main`.
316
-
317
- Si el paquete ya existe, este repositorio debe tener acceso de escritura en
318
- **Package settings → Manage Actions access**. Si una regla de protección de
319
- `main` impide pushes del token del workflow, debe ajustarse para permitir el
320
- flujo de release antes de ejecutarlo. No ejecutar un release local mientras
321
- esté corriendo el de Actions. Los pushes hechos con `GITHUB_TOKEN` no disparan
322
- otros workflows, incluido **Release**, por lo que el commit de versión no crea un
323
- bucle de publicaciones. La preparación del release ejecuta las validaciones completas.
324
- Para retomar una publicación fallida después del push, volver a ejecutar **Release**.
270
+ ### Cómo se publica
325
271
 
326
- ### Desde una terminal local
272
+ `pnpm create-version` (alias `pnpm cv`) corre en tu máquina: diagnostica el repositorio, crea el commit `X.Y.Z` y el tag anotado `vX.Y.Z`, los pushea y despacha el workflow **Release** (`.github/workflows/release.yml`) con `version`, `tag` y `sha`. El workflow verifica que el tag apunte a ese commit y que esté en `main`, prepara y valida el tarball y lo publica en npm con [trusted publishing](https://docs.npmjs.com/trusted-publishers) (OIDC, `id-token: write`), sin tokens de npm ni secrets en el repositorio.
327
273
 
328
- Desde este repositorio, configurar `NPM_TOKEN` con un token personal de GitHub **clásico** con `write:packages` en el entorno o en `.env`, tomando `.env.example` como referencia. Si el valor existente es un token de npm, reemplazarlo localmente por el de GitHub. No pegarlo en el chat ni agregar credenciales al `.npmrc` del proyecto: astra-rp rechaza esas credenciales. El campo `repository` del manifest vincula el paquete con este repositorio.
274
+ Como la publicación usa OIDC, solo puede correr en GitHub Actions: `--local` no publica este paquete. Si el workflow falla después del push, corré `pnpm cv --retry-ci vX.Y.Z` para reintentarlo sobre el mismo tag.
329
275
 
330
276
  ### Un solo comando: `pnpm create-version` (alias `pnpm cv`)
331
277
 
@@ -374,7 +320,7 @@ pnpm release:prepare
374
320
 
375
321
  El paquete excluye fuentes privadas, tests, scripts, `.env` y `.npmrc`; incluye JavaScript, declaraciones, CSS, fuentes tipográficas y licencias. Conserva releases anteriores.
376
322
 
377
- `prepack` ejecuta el build para los empaquetados manuales. `dist` y `releases` son generados e ignorados por Git. La CI verifica los checks, los tres providers y el catálogo de Storybook (`pnpm test:storybook`) en ambos motores de navegador en Linux y Windows. La publicación se ejecuta desde el workflow **Release**, que recibe la versión, el tag y el commit creados por `pnpm create-version`.
323
+ `prepack` ejecuta el build para los empaquetados manuales. `dist` y `releases` son generados e ignorados por Git. La CI verifica los checks, los tres providers y el catálogo de Storybook (`pnpm test:storybook`) en ambos motores de navegador (Chromium y WebKit) en Linux. La publicación se ejecuta desde el workflow **Release**, que recibe la versión, el tag y el commit creados por `pnpm create-version`.
378
324
 
379
325
  Tras publicar, los consumidores pueden instalar `pnpm add @astra-kit/ui`. También pueden instalar directamente el `.tgz` validado antes de una publicación.
380
326
 
@@ -23,7 +23,8 @@ export type DropdownMenuProps = {
23
23
  icon?: ReactNode;
24
24
  /**
25
25
  * Your own trigger, rendered with `asChild` instead of Arc's labelled button, such as an icon button with its own
26
- * `aria-label`. It must accept a ref and be focusable.
26
+ * `aria-label`. It must accept a ref and be focusable. While the rendered trigger is disabled (its own `disabled`, an
27
+ * ancestor `<fieldset disabled>`) or has `aria-disabled="true"`, the menu does not open.
27
28
  */
28
29
  trigger?: ReactElement;
29
30
  /** Single selection: rows with a `value` render as radio items checked against `selection.value`. */
@@ -1,12 +1,38 @@
1
1
  "use client";
2
2
  import { c as _c } from "react/compiler-runtime";
3
3
  import { ChevronDownIcon } from "lucide-react";
4
+ import { DROPDOWN_MENU_OPEN_KEYS, DROPDOWN_MENU_UNAVAILABLE_TRIGGER_SELECTOR } from "../constants/dropdown-menu.js";
4
5
  import { cn } from "../lib/utils.js";
5
6
  import { Button } from "./button.js";
6
7
  import { DropdownMenu as DropdownMenuRoot, DropdownMenuContent, DropdownMenuTrigger } from "./primitives/dropdown-menu.js";
7
8
  import { DropdownMenuItems } from "./primitives/dropdown-menu-items.js";
8
9
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
9
10
  /**
11
+ * Tells whether the rendered trigger is unavailable, however it got there: its own `disabled`, an ancestor
12
+ * `<fieldset disabled>`, state derived inside a custom component, or `aria-disabled="true"`.
13
+ * @param trigger - Element the event reached.
14
+ * @returns Whether the menu must stay closed.
15
+ */
16
+ function isUnavailableTrigger(trigger) {
17
+ return trigger.matches(DROPDOWN_MENU_UNAVAILABLE_TRIGGER_SELECTOR);
18
+ }
19
+ /**
20
+ * Keeps an unavailable trigger from opening the menu on press. The engine still delivers `pointerdown` to a disabled
21
+ * button, and Radix opens on it unless the event is already default-prevented.
22
+ * @param event - Pointer event on the trigger.
23
+ */
24
+ function preventPointerOpenWhileUnavailable(event) {
25
+ if (isUnavailableTrigger(event.currentTarget)) event.preventDefault();
26
+ }
27
+ /**
28
+ * Keeps an `aria-disabled` trigger, which stays focusable, from opening the menu with Enter, Space or ArrowDown. Other
29
+ * keys, such as Tab, keep their default so focus can leave it.
30
+ * @param event - Keyboard event on the trigger.
31
+ */
32
+ function preventKeyboardOpenWhileUnavailable(event) {
33
+ if (DROPDOWN_MENU_OPEN_KEYS.includes(event.key) && isUnavailableTrigger(event.currentTarget)) event.preventDefault();
34
+ }
35
+ /**
10
36
  * A focused list of actions anchored to a trigger.
11
37
  * @param props - The label, the items and optional trigger, selection, placement and open state.
12
38
  * @returns The trigger with its menu.
@@ -44,6 +70,8 @@ function DropdownMenu(t0) {
44
70
  if ($[5] !== t1) {
45
71
  t2 = /* @__PURE__ */ _jsx(DropdownMenuTrigger, {
46
72
  asChild: true,
73
+ onPointerDown: preventPointerOpenWhileUnavailable,
74
+ onKeyDown: preventKeyboardOpenWhileUnavailable,
47
75
  children: t1
48
76
  });
49
77
  $[5] = t1;
@@ -1,4 +1,11 @@
1
1
  import type { ArcFloatingMotion } from "../motion/arc-floating-slot.js";
2
+ /**
3
+ * Rendered trigger states that must not open the menu: natively disabled (its own prop, an ancestor
4
+ * `<fieldset disabled>` or state derived inside a custom component) or marked unavailable with `aria-disabled`.
5
+ */
6
+ export declare const DROPDOWN_MENU_UNAVAILABLE_TRIGGER_SELECTOR = ":disabled, [aria-disabled=\"true\"]";
7
+ /** Keys that open the menu from its focused trigger, as Radix handles them; any other key keeps its default. */
8
+ export declare const DROPDOWN_MENU_OPEN_KEYS: readonly string[];
2
9
  /** Gap, in pixels, between the trigger and the menu. */
3
10
  export declare const DROPDOWN_MENU_SIDE_OFFSET_PX = 6;
4
11
  /** Minimum distance, in pixels, a menu keeps from the viewport edges. */
@@ -1,4 +1,15 @@
1
1
  import { ARC_DURATION, ARC_EASE, ARC_SPRING_CSS } from "../motion/arc-tokens.js";
2
+ /**
3
+ * Rendered trigger states that must not open the menu: natively disabled (its own prop, an ancestor
4
+ * `<fieldset disabled>` or state derived inside a custom component) or marked unavailable with `aria-disabled`.
5
+ */
6
+ export const DROPDOWN_MENU_UNAVAILABLE_TRIGGER_SELECTOR = ":disabled, [aria-disabled=\"true\"]";
7
+ /** Keys that open the menu from its focused trigger, as Radix handles them; any other key keeps its default. */
8
+ export const DROPDOWN_MENU_OPEN_KEYS = [
9
+ "Enter",
10
+ " ",
11
+ "ArrowDown"
12
+ ];
2
13
  /** Gap, in pixels, between the trigger and the menu. */
3
14
  export const DROPDOWN_MENU_SIDE_OFFSET_PX = 6;
4
15
  /** Minimum distance, in pixels, a menu keeps from the viewport edges. */
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@astra-kit/ui",
3
- "version": "0.0.0",
3
+ "version": "1.0.0",
4
4
  "description": "Shared UI components with the customizations extracted from TuTribu.",
5
5
  "type": "module",
6
6
  "sideEffects": [