@astra-kit/ui 0.0.0 → 1.1.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 +14 -1
- package/README.md +14 -59
- package/dist/components/button-link.d.ts +15 -0
- package/dist/components/button-link.js +70 -0
- package/dist/components/button-recipe.d.ts +27 -0
- package/dist/components/button-recipe.js +44 -0
- package/dist/components/button.d.ts +3 -5
- package/dist/components/button.js +1 -25
- package/dist/components/dropdown-menu.d.ts +2 -1
- package/dist/components/dropdown-menu.js +28 -0
- package/dist/components/radio-group.d.ts +5 -3
- package/dist/components/radio-group.js +88 -85
- package/dist/constants/dropdown-menu.d.ts +7 -0
- package/dist/constants/dropdown-menu.js +11 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +3 -0
- package/package.json +6 -1
package/CHANGELOG.md
CHANGED
|
@@ -4,6 +4,15 @@ Todos los cambios relevantes de `@astra-kit/ui` se documentan en este archivo co
|
|
|
4
4
|
|
|
5
5
|
## [Unreleased]
|
|
6
6
|
|
|
7
|
+
## [1.1.0] - 2026-10-19
|
|
8
|
+
|
|
9
|
+
### Added
|
|
10
|
+
|
|
11
|
+
- `ButtonLink`: un link con el aspecto de `Button` (`variant` y `size`) que rutea con el adaptador del provider y sigue siendo un enlace, para navegar sin estilos propios en cada app. También se exporta `buttonClassName({ variant, size, className })`, con las mismas clases para otros elementos, como un `<label>` que abre un selector de archivos.
|
|
12
|
+
- `RadioGroup` acepta `hideLabel` (por defecto `false`), como `Select`: la leyenda sigue nombrando el grupo para lectores de pantalla pero no se ve ni ocupa espacio, para layouts que ya muestran su propio título. Ya no hace falta ocultarla con CSS propio.
|
|
13
|
+
|
|
14
|
+
## [1.0.0] - 2026-10-18
|
|
15
|
+
|
|
7
16
|
### Changed
|
|
8
17
|
|
|
9
18
|
- 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 +21,8 @@ Todos los cambios relevantes de `@astra-kit/ui` se documentan en este archivo co
|
|
|
12
21
|
|
|
13
22
|
### Removed
|
|
14
23
|
|
|
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
|
|
24
|
+
- 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).
|
|
25
|
+
|
|
26
|
+
### Fixed
|
|
27
|
+
|
|
28
|
+
- `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,16 @@ import { Avatar, Button, Calendar, DataTable } from "@astra-kit/ui";
|
|
|
47
47
|
<Avatar name="Ana Núñez" src="/ana.jpg" />;
|
|
48
48
|
```
|
|
49
49
|
|
|
50
|
-
|
|
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 `RadioGroup`, 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
|
+
|
|
52
|
+
`Button` es para acciones y no tiene `asChild`. Una navegación con aspecto de botón es un `ButtonLink`: el `Link` del provider (rutea con el adaptador configurado y sigue siendo un enlace, que se puede abrir en otra pestaña o copiar) con la receta de `Button` y sus `variant` y `size`. Para otro elemento con aspecto de botón, como un `<label>` que abre un selector de archivos, `buttonClassName({ variant, size, className })` devuelve las mismas clases. Ninguno de los dos incluye la presión ni el spinner de `Button`.
|
|
53
|
+
|
|
54
|
+
```tsx
|
|
55
|
+
import { ButtonLink, buttonClassName } from "@astra-kit/ui";
|
|
56
|
+
|
|
57
|
+
<ButtonLink href="/" variant="secondary">Volver al inicio</ButtonLink>;
|
|
58
|
+
<label className={buttonClassName({ variant: "ghost", size: "sm" })}>Adjuntar<input type="file" hidden /></label>;
|
|
59
|
+
```
|
|
51
60
|
|
|
52
61
|
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
62
|
|
|
@@ -67,32 +76,6 @@ Los componentes usan por defecto los espaciados compactos de Agenda: `Select` mi
|
|
|
67
76
|
|
|
68
77
|
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
78
|
|
|
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
79
|
## Movimiento
|
|
97
80
|
|
|
98
81
|
El movimiento sigue a [Arc](https://uiarc.dev): explica causa y efecto (qué se abrió,
|
|
@@ -293,39 +276,11 @@ El compilador `tsc` es TypeScript 7. El paquete `typescript` apunta a la [API de
|
|
|
293
276
|
|
|
294
277
|
## Crear y publicar una versión
|
|
295
278
|
|
|
296
|
-
###
|
|
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**.
|
|
279
|
+
### Cómo se publica
|
|
325
280
|
|
|
326
|
-
|
|
281
|
+
`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
282
|
|
|
328
|
-
|
|
283
|
+
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
284
|
|
|
330
285
|
### Un solo comando: `pnpm create-version` (alias `pnpm cv`)
|
|
331
286
|
|
|
@@ -374,7 +329,7 @@ pnpm release:prepare
|
|
|
374
329
|
|
|
375
330
|
El paquete excluye fuentes privadas, tests, scripts, `.env` y `.npmrc`; incluye JavaScript, declaraciones, CSS, fuentes tipográficas y licencias. Conserva releases anteriores.
|
|
376
331
|
|
|
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
|
|
332
|
+
`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
333
|
|
|
379
334
|
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
335
|
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { type ButtonSize, type ButtonVariant } from "./button-recipe.js";
|
|
2
|
+
import { type LinkProps } from "./link.js";
|
|
3
|
+
export type ButtonLinkProps = LinkProps & {
|
|
4
|
+
/** Visual weight, as in `Button`. Defaults to `primary`. */
|
|
5
|
+
variant?: ButtonVariant;
|
|
6
|
+
/** Height and padding, as in `Button`. Defaults to `md`. */
|
|
7
|
+
size?: ButtonSize;
|
|
8
|
+
};
|
|
9
|
+
/**
|
|
10
|
+
* A link styled as a button, such as "Volver al inicio" on an error page.
|
|
11
|
+
* @param props - Variant, size and every `Link` prop, including `href`, `prefetch` and `component`.
|
|
12
|
+
* @returns The link.
|
|
13
|
+
*/
|
|
14
|
+
declare function ButtonLink({ variant, size, className, ...props }: ButtonLinkProps): import("react").JSX.Element;
|
|
15
|
+
export { ButtonLink };
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { c as _c } from "react/compiler-runtime";
|
|
3
|
+
/**
|
|
4
|
+
* Navigation that looks like Arc's Button (https://uiarc.dev, MIT License, see THIRD_PARTY_NOTICES.md): the
|
|
5
|
+
* provider's `Link`, so it routes through the configured adapter, with the button recipe. A link stays a link for
|
|
6
|
+
* assistive technology and the browser (it opens in a new tab, it can be copied), which a `Button` cannot.
|
|
7
|
+
*/
|
|
8
|
+
import { cn } from "../lib/utils.js";
|
|
9
|
+
import { buttonClassName } from "./button-recipe.js";
|
|
10
|
+
import { Link } from "./link.js";
|
|
11
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
12
|
+
/**
|
|
13
|
+
* A link styled as a button, such as "Volver al inicio" on an error page.
|
|
14
|
+
* @param props - Variant, size and every `Link` prop, including `href`, `prefetch` and `component`.
|
|
15
|
+
* @returns The link.
|
|
16
|
+
*/
|
|
17
|
+
function ButtonLink(t0) {
|
|
18
|
+
const $ = _c(14);
|
|
19
|
+
let className;
|
|
20
|
+
let props;
|
|
21
|
+
let t1;
|
|
22
|
+
let t2;
|
|
23
|
+
if ($[0] !== t0) {
|
|
24
|
+
({variant: t1, size: t2, className, ...props} = t0);
|
|
25
|
+
$[0] = t0;
|
|
26
|
+
$[1] = className;
|
|
27
|
+
$[2] = props;
|
|
28
|
+
$[3] = t1;
|
|
29
|
+
$[4] = t2;
|
|
30
|
+
} else {
|
|
31
|
+
className = $[1];
|
|
32
|
+
props = $[2];
|
|
33
|
+
t1 = $[3];
|
|
34
|
+
t2 = $[4];
|
|
35
|
+
}
|
|
36
|
+
const variant = t1 === undefined ? "primary" : t1;
|
|
37
|
+
const size = t2 === undefined ? "md" : t2;
|
|
38
|
+
let t3;
|
|
39
|
+
if ($[5] !== className || $[6] !== size || $[7] !== variant) {
|
|
40
|
+
t3 = cn(buttonClassName({
|
|
41
|
+
variant,
|
|
42
|
+
size
|
|
43
|
+
}), className);
|
|
44
|
+
$[5] = className;
|
|
45
|
+
$[6] = size;
|
|
46
|
+
$[7] = variant;
|
|
47
|
+
$[8] = t3;
|
|
48
|
+
} else {
|
|
49
|
+
t3 = $[8];
|
|
50
|
+
}
|
|
51
|
+
let t4;
|
|
52
|
+
if ($[9] !== props || $[10] !== size || $[11] !== t3 || $[12] !== variant) {
|
|
53
|
+
t4 = /* @__PURE__ */ _jsx(Link, {
|
|
54
|
+
"data-slot": "button-link",
|
|
55
|
+
"data-variant": variant,
|
|
56
|
+
"data-size": size,
|
|
57
|
+
...props,
|
|
58
|
+
className: t3
|
|
59
|
+
});
|
|
60
|
+
$[9] = props;
|
|
61
|
+
$[10] = size;
|
|
62
|
+
$[11] = t3;
|
|
63
|
+
$[12] = variant;
|
|
64
|
+
$[13] = t4;
|
|
65
|
+
} else {
|
|
66
|
+
t4 = $[13];
|
|
67
|
+
}
|
|
68
|
+
return t4;
|
|
69
|
+
}
|
|
70
|
+
export { ButtonLink };
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/** Visual weight, as in Arc: one primary action per surface. */
|
|
2
|
+
export type ButtonVariant = "primary" | "secondary" | "ghost" | "danger";
|
|
3
|
+
/** Height and padding, from Arc's control heights. */
|
|
4
|
+
export type ButtonSize = "sm" | "md" | "lg";
|
|
5
|
+
/**
|
|
6
|
+
* Arc's button recipe on its tokens. Press scale is driven by Motion alone, so `transform` never gets a CSS
|
|
7
|
+
* transition, and anchors of floating layers never scale because Radix measures them on pointerdown. Keyboard focus
|
|
8
|
+
* uses the foundation's shared outline; pointer focus draws no ring.
|
|
9
|
+
*/
|
|
10
|
+
export declare const buttonVariants: (props?: ({
|
|
11
|
+
variant?: "danger" | "ghost" | "primary" | "secondary" | null | undefined;
|
|
12
|
+
size?: "lg" | "md" | "sm" | null | undefined;
|
|
13
|
+
} & import("class-variance-authority/types").ClassProp) | undefined) => string;
|
|
14
|
+
/** Options of {@link buttonClassName}. */
|
|
15
|
+
export type ButtonClassNameOptions = {
|
|
16
|
+
variant?: ButtonVariant;
|
|
17
|
+
size?: ButtonSize;
|
|
18
|
+
/** Extra classes merged after the recipe, so they win on conflicts. */
|
|
19
|
+
className?: string;
|
|
20
|
+
};
|
|
21
|
+
/**
|
|
22
|
+
* Arc's button classes for an element that is not a `Button`, such as a `<label>` that opens a file picker. Links
|
|
23
|
+
* use {@link ButtonLink} instead. The press scale and the loading label are effects of `Button` and are not included.
|
|
24
|
+
* @param options - Variant, size and extra classes. Defaults to `primary` and `md`.
|
|
25
|
+
* @returns The class list.
|
|
26
|
+
*/
|
|
27
|
+
export declare function buttonClassName({ variant, size, className }?: ButtonClassNameOptions): string;
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Arc's Button recipe (https://uiarc.dev, MIT License, see THIRD_PARTY_NOTICES.md): variants, sizes and the helper
|
|
3
|
+
* that applies them. It has no client directive, so `buttonClassName` also runs in React Server Components; the
|
|
4
|
+
* `Button` and `ButtonLink` components import it from here.
|
|
5
|
+
*/
|
|
6
|
+
import { cva } from "class-variance-authority";
|
|
7
|
+
import { cn } from "../lib/utils.js";
|
|
8
|
+
/**
|
|
9
|
+
* Arc's button recipe on its tokens. Press scale is driven by Motion alone, so `transform` never gets a CSS
|
|
10
|
+
* transition, and anchors of floating layers never scale because Radix measures them on pointerdown. Keyboard focus
|
|
11
|
+
* uses the foundation's shared outline; pointer focus draws no ring.
|
|
12
|
+
*/
|
|
13
|
+
export const buttonVariants = cva("relative inline-flex shrink-0 cursor-pointer items-center justify-center gap-2 rounded-(--radius-control) border border-transparent px-4 font-sans text-sm leading-(--leading-body) font-medium whitespace-nowrap select-none [-webkit-tap-highlight-color:transparent] transition-[color,background-color,border-color,opacity,box-shadow] duration-(--duration-fast) ease-(--ease-standard) disabled:cursor-not-allowed disabled:opacity-[.52] aria-busy:cursor-progress motion-reduce:transition-none [&:is([aria-haspopup]:not([aria-haspopup=false]),[data-state],[role=combobox])]:transform-none! [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4", {
|
|
14
|
+
variants: {
|
|
15
|
+
variant: {
|
|
16
|
+
primary: "border-foreground bg-foreground text-background hover-fine:not-disabled:opacity-[.91] hover-fine:not-disabled:shadow-(--shadow-resting) active:not-disabled:opacity-[.84]",
|
|
17
|
+
secondary: "border-border bg-surface text-foreground hover-fine:not-disabled:bg-surface-muted hover-fine:not-disabled:shadow-(--shadow-resting) active:not-disabled:bg-surface-muted disabled:bg-surface-muted disabled:text-text-muted disabled:opacity-100",
|
|
18
|
+
ghost: "bg-transparent text-text-secondary hover-fine:not-disabled:bg-surface-muted hover-fine:not-disabled:text-foreground active:not-disabled:bg-surface-muted active:not-disabled:text-foreground disabled:text-text-muted disabled:opacity-100",
|
|
19
|
+
danger: "border-border bg-surface text-danger hover-fine:not-disabled:border-danger hover-fine:not-disabled:bg-surface-muted active:not-disabled:border-danger active:not-disabled:bg-surface-muted disabled:bg-surface-muted disabled:text-[color-mix(in_oklab,var(--danger)_55%,var(--surface-muted))] disabled:opacity-100"
|
|
20
|
+
},
|
|
21
|
+
size: {
|
|
22
|
+
sm: "min-h-(--control-height-sm) px-3",
|
|
23
|
+
md: "min-h-(--control-height-md)",
|
|
24
|
+
lg: "min-h-(--control-height-lg) px-5"
|
|
25
|
+
}
|
|
26
|
+
},
|
|
27
|
+
defaultVariants: {
|
|
28
|
+
variant: "primary",
|
|
29
|
+
size: "md"
|
|
30
|
+
}
|
|
31
|
+
});
|
|
32
|
+
/**
|
|
33
|
+
* Arc's button classes for an element that is not a `Button`, such as a `<label>` that opens a file picker. Links
|
|
34
|
+
* use {@link ButtonLink} instead. The press scale and the loading label are effects of `Button` and are not included.
|
|
35
|
+
* @param options - Variant, size and extra classes. Defaults to `primary` and `md`.
|
|
36
|
+
* @returns The class list.
|
|
37
|
+
*/
|
|
38
|
+
export function buttonClassName({ variant = "primary", size = "md", className } = {}) {
|
|
39
|
+
return cn(buttonVariants({
|
|
40
|
+
variant,
|
|
41
|
+
size,
|
|
42
|
+
className
|
|
43
|
+
}));
|
|
44
|
+
}
|
|
@@ -1,13 +1,10 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Arc's Button (https://uiarc.dev, MIT License, see THIRD_PARTY_NOTICES.md): its variants, sizes, tokens and motion,
|
|
3
3
|
* with width-aware press feedback, a label that springs to its new width and a loading spinner. It renders a native
|
|
4
|
-
* button
|
|
4
|
+
* button: navigation that looks like a button is a `ButtonLink`, and other elements take `buttonClassName`. Composite components that need icon sizes use the internal `ControlButton`.
|
|
5
5
|
*/
|
|
6
6
|
import type { ComponentProps } from "react";
|
|
7
|
-
|
|
8
|
-
export type ButtonVariant = "primary" | "secondary" | "ghost" | "danger";
|
|
9
|
-
/** Height and padding, from Arc's control heights. */
|
|
10
|
-
export type ButtonSize = "sm" | "md" | "lg";
|
|
7
|
+
import { type ButtonSize, type ButtonVariant } from "./button-recipe.js";
|
|
11
8
|
export type ButtonProps = ComponentProps<"button"> & {
|
|
12
9
|
variant?: ButtonVariant;
|
|
13
10
|
size?: ButtonSize;
|
|
@@ -21,3 +18,4 @@ export type ButtonProps = ComponentProps<"button"> & {
|
|
|
21
18
|
*/
|
|
22
19
|
declare function Button({ className, variant, size, loading, type, children, ref, ...props }: ButtonProps): import("react").JSX.Element;
|
|
23
20
|
export { Button };
|
|
21
|
+
export type { ButtonSize, ButtonVariant } from "./button-recipe.js";
|
|
@@ -1,39 +1,15 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import { c as _c } from "react/compiler-runtime";
|
|
3
|
-
import { cva } from "class-variance-authority";
|
|
4
3
|
import { useIsPresent } from "motion/react";
|
|
5
4
|
import { usePrefersReducedMotion } from "../hooks/use-prefers-reduced-motion.js";
|
|
6
5
|
import { cn } from "../lib/utils.js";
|
|
6
|
+
import { buttonVariants } from "./button-recipe.js";
|
|
7
7
|
import { useArcPress } from "../motion/arc-press.js";
|
|
8
8
|
import { useAttachedElement } from "../motion/use-attached-element.js";
|
|
9
9
|
import { ButtonLabel } from "./button-label.js";
|
|
10
10
|
import { LEAVING_ATTRIBUTES, LOADING_INERT_HANDLERS } from "./button-interaction.js";
|
|
11
11
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
12
12
|
/**
|
|
13
|
-
* Arc's button recipe on its tokens. Press scale is driven by Motion alone, so `transform` never gets a CSS
|
|
14
|
-
* transition, and anchors of floating layers never scale because Radix measures them on pointerdown. Keyboard focus
|
|
15
|
-
* uses the foundation's shared outline; pointer focus draws no ring.
|
|
16
|
-
*/
|
|
17
|
-
const buttonVariants = cva("relative inline-flex shrink-0 cursor-pointer items-center justify-center gap-2 rounded-(--radius-control) border border-transparent px-4 font-sans text-sm leading-(--leading-body) font-medium whitespace-nowrap select-none [-webkit-tap-highlight-color:transparent] transition-[color,background-color,border-color,opacity,box-shadow] duration-(--duration-fast) ease-(--ease-standard) disabled:cursor-not-allowed disabled:opacity-[.52] aria-busy:cursor-progress motion-reduce:transition-none [&:is([aria-haspopup]:not([aria-haspopup=false]),[data-state],[role=combobox])]:transform-none! [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4", {
|
|
18
|
-
variants: {
|
|
19
|
-
variant: {
|
|
20
|
-
primary: "border-foreground bg-foreground text-background hover-fine:not-disabled:opacity-[.91] hover-fine:not-disabled:shadow-(--shadow-resting) active:not-disabled:opacity-[.84]",
|
|
21
|
-
secondary: "border-border bg-surface text-foreground hover-fine:not-disabled:bg-surface-muted hover-fine:not-disabled:shadow-(--shadow-resting) active:not-disabled:bg-surface-muted disabled:bg-surface-muted disabled:text-text-muted disabled:opacity-100",
|
|
22
|
-
ghost: "bg-transparent text-text-secondary hover-fine:not-disabled:bg-surface-muted hover-fine:not-disabled:text-foreground active:not-disabled:bg-surface-muted active:not-disabled:text-foreground disabled:text-text-muted disabled:opacity-100",
|
|
23
|
-
danger: "border-border bg-surface text-danger hover-fine:not-disabled:border-danger hover-fine:not-disabled:bg-surface-muted active:not-disabled:border-danger active:not-disabled:bg-surface-muted disabled:bg-surface-muted disabled:text-[color-mix(in_oklab,var(--danger)_55%,var(--surface-muted))] disabled:opacity-100"
|
|
24
|
-
},
|
|
25
|
-
size: {
|
|
26
|
-
sm: "min-h-(--control-height-sm) px-3",
|
|
27
|
-
md: "min-h-(--control-height-md)",
|
|
28
|
-
lg: "min-h-(--control-height-lg) px-5"
|
|
29
|
-
}
|
|
30
|
-
},
|
|
31
|
-
defaultVariants: {
|
|
32
|
-
variant: "primary",
|
|
33
|
-
size: "md"
|
|
34
|
-
}
|
|
35
|
-
});
|
|
36
|
-
/**
|
|
37
13
|
* A single action on a page, form or dialog. Defaults to `type="button"`, so it only submits a form when asked to.
|
|
38
14
|
* @param props - Variant, size, loading state and native button attributes, including `ref`.
|
|
39
15
|
* @returns The native button.
|
|
@@ -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;
|
|
@@ -10,8 +10,10 @@ export type RadioGroupOption = {
|
|
|
10
10
|
disabled?: boolean;
|
|
11
11
|
};
|
|
12
12
|
export type RadioGroupProps = {
|
|
13
|
-
/**
|
|
13
|
+
/** Legend of the fieldset, which names the group. */
|
|
14
14
|
label: string;
|
|
15
|
+
/** Keeps `label` for assistive technology only, for layouts that already show their own label. */
|
|
16
|
+
hideLabel?: boolean;
|
|
15
17
|
/** Rows in order. Values double as keys, so keep them unique. */
|
|
16
18
|
options: RadioGroupOption[];
|
|
17
19
|
/** Selected value when controlled. */
|
|
@@ -27,8 +29,8 @@ export type RadioGroupProps = {
|
|
|
27
29
|
};
|
|
28
30
|
/**
|
|
29
31
|
* A choice of one option from a visible set, controlled with `value` or uncontrolled with `defaultValue`.
|
|
30
|
-
* @param props - Legend, options, value, change handler, form name and classes.
|
|
32
|
+
* @param props - Legend, its visibility, options, value, change handler, form name and classes.
|
|
31
33
|
* @returns The fieldset with its legend and option rows.
|
|
32
34
|
*/
|
|
33
|
-
declare function RadioGroup({ label, options, value, defaultValue, onValueChange, name, className }: RadioGroupProps): import("react").JSX.Element;
|
|
35
|
+
declare function RadioGroup({ label, hideLabel, options, value, defaultValue, onValueChange, name, className, }: RadioGroupProps): import("react").JSX.Element;
|
|
34
36
|
export { RadioGroup };
|
|
@@ -208,12 +208,13 @@ function _temp(event) {
|
|
|
208
208
|
}
|
|
209
209
|
/**
|
|
210
210
|
* A choice of one option from a visible set, controlled with `value` or uncontrolled with `defaultValue`.
|
|
211
|
-
* @param props - Legend, options, value, change handler, form name and classes.
|
|
211
|
+
* @param props - Legend, its visibility, options, value, change handler, form name and classes.
|
|
212
212
|
* @returns The fieldset with its legend and option rows.
|
|
213
213
|
*/
|
|
214
214
|
function RadioGroup(t0) {
|
|
215
|
-
const $ = _c(
|
|
216
|
-
const { label, options, value, defaultValue, onValueChange, name, className } = t0;
|
|
215
|
+
const $ = _c(33);
|
|
216
|
+
const { label, hideLabel: t1, options, value, defaultValue, onValueChange, name, className } = t0;
|
|
217
|
+
const hideLabel = t1 === undefined ? false : t1;
|
|
217
218
|
const reduceMotion = usePrefersReducedMotion();
|
|
218
219
|
const generatedId = useId();
|
|
219
220
|
const legendId = `${generatedId}-legend`;
|
|
@@ -224,36 +225,36 @@ function RadioGroup(t0) {
|
|
|
224
225
|
const highlightRef = useRef(null);
|
|
225
226
|
const shownValue = useRef(null);
|
|
226
227
|
const placedAt = useRef("");
|
|
227
|
-
let
|
|
228
|
+
let t2;
|
|
228
229
|
if ($[0] === Symbol.for("react.memo_cache_sentinel")) {
|
|
229
|
-
|
|
230
|
-
$[0] =
|
|
230
|
+
t2 = () => optionsRef.current?.querySelector(CHECKED_OPTION_SELECTOR) ?? null;
|
|
231
|
+
$[0] = t2;
|
|
231
232
|
} else {
|
|
232
|
-
|
|
233
|
+
t2 = $[0];
|
|
233
234
|
}
|
|
234
|
-
const findCheckedRow =
|
|
235
|
-
let t2;
|
|
235
|
+
const findCheckedRow = t2;
|
|
236
236
|
let t3;
|
|
237
|
+
let t4;
|
|
237
238
|
if ($[1] !== reduceMotion || $[2] !== selectedValue) {
|
|
238
|
-
|
|
239
|
+
t3 = () => {
|
|
239
240
|
const hasChanged = shownValue.current !== null && shownValue.current !== selectedValue;
|
|
240
241
|
placeHighlight(highlightRef.current, findCheckedRow(), placedAt, hasChanged && !reduceMotion);
|
|
241
242
|
shownValue.current = selectedValue;
|
|
242
243
|
groupRef.current?.setAttribute(RADIO_GROUP_READY_ATTRIBUTE, "");
|
|
243
244
|
};
|
|
244
|
-
|
|
245
|
+
t4 = [selectedValue, reduceMotion];
|
|
245
246
|
$[1] = reduceMotion;
|
|
246
247
|
$[2] = selectedValue;
|
|
247
|
-
$[3] =
|
|
248
|
-
$[4] =
|
|
248
|
+
$[3] = t3;
|
|
249
|
+
$[4] = t4;
|
|
249
250
|
} else {
|
|
250
|
-
|
|
251
|
-
|
|
251
|
+
t3 = $[3];
|
|
252
|
+
t4 = $[4];
|
|
252
253
|
}
|
|
253
|
-
useLayoutEffect(
|
|
254
|
-
let
|
|
254
|
+
useLayoutEffect(t3, t4);
|
|
255
|
+
let t5;
|
|
255
256
|
if ($[5] === Symbol.for("react.memo_cache_sentinel")) {
|
|
256
|
-
|
|
257
|
+
t5 = () => {
|
|
257
258
|
const list = optionsRef.current;
|
|
258
259
|
if (!list || typeof ResizeObserver === "undefined") {
|
|
259
260
|
return;
|
|
@@ -263,15 +264,15 @@ function RadioGroup(t0) {
|
|
|
263
264
|
list.querySelectorAll(OPTION_SELECTOR).forEach((row) => observer.observe(row));
|
|
264
265
|
return () => observer.disconnect();
|
|
265
266
|
};
|
|
266
|
-
$[5] =
|
|
267
|
+
$[5] = t5;
|
|
267
268
|
} else {
|
|
268
|
-
|
|
269
|
+
t5 = $[5];
|
|
269
270
|
}
|
|
270
|
-
useEffect(
|
|
271
|
-
const
|
|
272
|
-
let
|
|
271
|
+
useEffect(t5);
|
|
272
|
+
const t6 = name ?? generatedId;
|
|
273
|
+
let t7;
|
|
273
274
|
if ($[6] !== onValueChange || $[7] !== value) {
|
|
274
|
-
|
|
275
|
+
t7 = (nextValue) => {
|
|
275
276
|
if (value === undefined) {
|
|
276
277
|
setUncontrolledValue(nextValue);
|
|
277
278
|
}
|
|
@@ -279,112 +280,114 @@ function RadioGroup(t0) {
|
|
|
279
280
|
};
|
|
280
281
|
$[6] = onValueChange;
|
|
281
282
|
$[7] = value;
|
|
282
|
-
$[8] =
|
|
283
|
+
$[8] = t7;
|
|
283
284
|
} else {
|
|
284
|
-
|
|
285
|
+
t7 = $[8];
|
|
285
286
|
}
|
|
286
|
-
let
|
|
287
|
+
let t8;
|
|
287
288
|
if ($[9] !== className) {
|
|
288
|
-
|
|
289
|
+
t8 = cn("m-0 grid min-w-0 border-0 p-0", className);
|
|
289
290
|
$[9] = className;
|
|
290
|
-
$[10] =
|
|
291
|
+
$[10] = t8;
|
|
291
292
|
} else {
|
|
292
|
-
|
|
293
|
+
t8 = $[10];
|
|
293
294
|
}
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
295
|
+
const t9 = hideLabel ? "sr-only" : "mb-(--space-2) p-0 text-sm font-medium text-foreground";
|
|
296
|
+
let t10;
|
|
297
|
+
if ($[11] !== label || $[12] !== legendId || $[13] !== t9) {
|
|
298
|
+
t10 = /* @__PURE__ */ _jsx("legend", {
|
|
297
299
|
id: legendId,
|
|
298
300
|
"data-slot": "radio-group-label",
|
|
299
|
-
className:
|
|
301
|
+
className: t9,
|
|
300
302
|
children: label
|
|
301
303
|
});
|
|
302
304
|
$[11] = label;
|
|
303
305
|
$[12] = legendId;
|
|
304
|
-
$[13] =
|
|
306
|
+
$[13] = t9;
|
|
307
|
+
$[14] = t10;
|
|
305
308
|
} else {
|
|
306
|
-
|
|
309
|
+
t10 = $[14];
|
|
307
310
|
}
|
|
308
|
-
let
|
|
309
|
-
if ($[
|
|
310
|
-
|
|
311
|
+
let t11;
|
|
312
|
+
if ($[15] === Symbol.for("react.memo_cache_sentinel")) {
|
|
313
|
+
t11 = /* @__PURE__ */ _jsx("span", {
|
|
311
314
|
ref: highlightRef,
|
|
312
315
|
"data-slot": "radio-group-highlight",
|
|
313
316
|
"aria-hidden": "true",
|
|
314
317
|
className: "pointer-events-none absolute top-0 left-0 z-1 box-border rounded-(--radius-control) border border-(--control-on) bg-[color-mix(in_oklab,var(--control-on)_5%,transparent)] opacity-0"
|
|
315
318
|
});
|
|
316
|
-
$[
|
|
319
|
+
$[15] = t11;
|
|
317
320
|
} else {
|
|
318
|
-
|
|
321
|
+
t11 = $[15];
|
|
319
322
|
}
|
|
320
|
-
let
|
|
321
|
-
if ($[
|
|
322
|
-
|
|
323
|
-
$[
|
|
324
|
-
$[
|
|
323
|
+
let t12;
|
|
324
|
+
if ($[16] !== options) {
|
|
325
|
+
t12 = options.map(_temp2);
|
|
326
|
+
$[16] = options;
|
|
327
|
+
$[17] = t12;
|
|
325
328
|
} else {
|
|
326
|
-
|
|
329
|
+
t12 = $[17];
|
|
327
330
|
}
|
|
328
|
-
let
|
|
329
|
-
if ($[
|
|
330
|
-
|
|
331
|
+
let t13;
|
|
332
|
+
if ($[18] !== t12) {
|
|
333
|
+
t13 = /* @__PURE__ */ _jsxs("div", {
|
|
331
334
|
ref: optionsRef,
|
|
332
335
|
"data-slot": "radio-group-options",
|
|
333
336
|
className: "relative grid w-full gap-(--space-2)",
|
|
334
|
-
children: [
|
|
337
|
+
children: [t11, t12]
|
|
335
338
|
});
|
|
336
|
-
$[
|
|
337
|
-
$[
|
|
339
|
+
$[18] = t12;
|
|
340
|
+
$[19] = t13;
|
|
338
341
|
} else {
|
|
339
|
-
|
|
342
|
+
t13 = $[19];
|
|
340
343
|
}
|
|
341
|
-
let
|
|
342
|
-
if ($[
|
|
343
|
-
|
|
344
|
+
let t14;
|
|
345
|
+
if ($[20] !== legendId || $[21] !== t10 || $[22] !== t13 || $[23] !== t8) {
|
|
346
|
+
t14 = /* @__PURE__ */ _jsxs("fieldset", {
|
|
344
347
|
ref: groupRef,
|
|
345
348
|
"data-slot": "radio-group",
|
|
346
349
|
"aria-labelledby": legendId,
|
|
347
|
-
className:
|
|
348
|
-
children: [
|
|
350
|
+
className: t8,
|
|
351
|
+
children: [t10, t13]
|
|
349
352
|
});
|
|
350
|
-
$[
|
|
351
|
-
$[
|
|
352
|
-
$[
|
|
353
|
-
$[
|
|
354
|
-
$[
|
|
353
|
+
$[20] = legendId;
|
|
354
|
+
$[21] = t10;
|
|
355
|
+
$[22] = t13;
|
|
356
|
+
$[23] = t8;
|
|
357
|
+
$[24] = t14;
|
|
355
358
|
} else {
|
|
356
|
-
|
|
359
|
+
t14 = $[24];
|
|
357
360
|
}
|
|
358
|
-
let
|
|
359
|
-
if ($[
|
|
360
|
-
|
|
361
|
+
let t15;
|
|
362
|
+
if ($[25] !== selectedValue || $[26] !== t14 || $[27] !== t6 || $[28] !== t7) {
|
|
363
|
+
t15 = /* @__PURE__ */ _jsx(RadioGroupPrimitive.Root, {
|
|
361
364
|
asChild: true,
|
|
362
|
-
name:
|
|
365
|
+
name: t6,
|
|
363
366
|
value: selectedValue,
|
|
364
|
-
onValueChange:
|
|
365
|
-
children:
|
|
367
|
+
onValueChange: t7,
|
|
368
|
+
children: t14
|
|
366
369
|
});
|
|
367
|
-
$[
|
|
368
|
-
$[
|
|
369
|
-
$[26] = t5;
|
|
370
|
+
$[25] = selectedValue;
|
|
371
|
+
$[26] = t14;
|
|
370
372
|
$[27] = t6;
|
|
371
|
-
$[28] =
|
|
373
|
+
$[28] = t7;
|
|
374
|
+
$[29] = t15;
|
|
372
375
|
} else {
|
|
373
|
-
|
|
376
|
+
t15 = $[29];
|
|
374
377
|
}
|
|
375
|
-
let
|
|
376
|
-
if ($[
|
|
377
|
-
|
|
378
|
+
let t16;
|
|
379
|
+
if ($[30] !== selectedValue || $[31] !== t15) {
|
|
380
|
+
t16 = /* @__PURE__ */ _jsx(RadioGroupValueContext.Provider, {
|
|
378
381
|
value: selectedValue,
|
|
379
|
-
children:
|
|
382
|
+
children: t15
|
|
380
383
|
});
|
|
381
|
-
$[
|
|
382
|
-
$[
|
|
383
|
-
$[
|
|
384
|
+
$[30] = selectedValue;
|
|
385
|
+
$[31] = t15;
|
|
386
|
+
$[32] = t16;
|
|
384
387
|
} else {
|
|
385
|
-
|
|
388
|
+
t16 = $[32];
|
|
386
389
|
}
|
|
387
|
-
return
|
|
390
|
+
return t16;
|
|
388
391
|
}
|
|
389
392
|
function _temp2(option) {
|
|
390
393
|
return /* @__PURE__ */ _jsx(RadioGroupOptionRow, { ...option }, option.value);
|
|
@@ -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/dist/index.d.ts
CHANGED
|
@@ -7,6 +7,8 @@ export * from "./components/action-button.js";
|
|
|
7
7
|
export * from "./components/avatar.js";
|
|
8
8
|
export * from "./components/badge.js";
|
|
9
9
|
export * from "./components/button.js";
|
|
10
|
+
export { buttonClassName, type ButtonClassNameOptions } from "./components/button-recipe.js";
|
|
11
|
+
export * from "./components/button-link.js";
|
|
10
12
|
export * from "./components/card.js";
|
|
11
13
|
export * from "./components/carousel.js";
|
|
12
14
|
export * from "./components/checkbox.js";
|
package/dist/index.js
CHANGED
|
@@ -6,6 +6,9 @@ export * from "./components/action-button.js";
|
|
|
6
6
|
export * from "./components/avatar.js";
|
|
7
7
|
export * from "./components/badge.js";
|
|
8
8
|
export * from "./components/button.js";
|
|
9
|
+
// From the recipe module, which has no client directive, so it also runs in Server Components.
|
|
10
|
+
export { buttonClassName } from "./components/button-recipe.js";
|
|
11
|
+
export * from "./components/button-link.js";
|
|
9
12
|
export * from "./components/card.js";
|
|
10
13
|
export * from "./components/carousel.js";
|
|
11
14
|
export * from "./components/checkbox.js";
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@astra-kit/ui",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "1.1.0",
|
|
4
4
|
"description": "Shared UI components with the customizations extracted from TuTribu.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"sideEffects": [
|
|
@@ -38,6 +38,11 @@
|
|
|
38
38
|
"import": "./dist/components/button.js",
|
|
39
39
|
"default": "./dist/components/button.js"
|
|
40
40
|
},
|
|
41
|
+
"./button-link": {
|
|
42
|
+
"types": "./dist/components/button-link.d.ts",
|
|
43
|
+
"import": "./dist/components/button-link.js",
|
|
44
|
+
"default": "./dist/components/button-link.js"
|
|
45
|
+
},
|
|
41
46
|
"./card": {
|
|
42
47
|
"types": "./dist/components/card.d.ts",
|
|
43
48
|
"import": "./dist/components/card.js",
|