@krizaka/ui 2.0.0-beta.0 → 2.0.0-beta.2
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/README.md +52 -3
- package/dist/alert.d.ts +95 -0
- package/dist/alert.js +38 -0
- package/dist/alert.js.map +1 -0
- package/dist/button-G5qY4qSY.d.ts +68 -0
- package/dist/card.d.ts +227 -0
- package/dist/card.js +108 -0
- package/dist/card.js.map +1 -0
- package/dist/checkbox.d.ts +52 -0
- package/dist/checkbox.js +42 -0
- package/dist/checkbox.js.map +1 -0
- package/dist/chip.d.ts +97 -0
- package/dist/chip.js +93 -0
- package/dist/chip.js.map +1 -0
- package/dist/chunk-5AXLA4LK.js +13 -0
- package/dist/chunk-5AXLA4LK.js.map +1 -0
- package/dist/chunk-5FRYKFTO.js +121 -0
- package/dist/chunk-5FRYKFTO.js.map +1 -0
- package/dist/{chunk-CPMZS4XA.js → chunk-FJDSLNXK.js} +1 -1
- package/dist/chunk-FJDSLNXK.js.map +1 -0
- package/dist/chunk-J3NC6ER4.js +9 -0
- package/dist/chunk-J3NC6ER4.js.map +1 -0
- package/dist/chunk-QRG5RYEI.js +49 -0
- package/dist/chunk-QRG5RYEI.js.map +1 -0
- package/dist/cn.d.ts +3 -0
- package/dist/cn.js +1 -1
- package/dist/command.d.ts +156 -0
- package/dist/command.js +111 -0
- package/dist/command.js.map +1 -0
- package/dist/confirm-button.d.ts +23 -0
- package/dist/confirm-button.js +85 -0
- package/dist/confirm-button.js.map +1 -0
- package/dist/dialog-DGBY2grk.d.ts +147 -0
- package/dist/dialog.d.ts +28 -0
- package/dist/dialog.js +93 -0
- package/dist/dialog.js.map +1 -0
- package/dist/dropdown-menu.d.ts +71 -0
- package/dist/dropdown-menu.js +66 -0
- package/dist/dropdown-menu.js.map +1 -0
- package/dist/field.js +1 -1
- package/dist/kbd.d.ts +24 -0
- package/dist/kbd.js +16 -0
- package/dist/kbd.js.map +1 -0
- package/dist/motion.css +7 -1
- package/dist/page-header.d.ts +77 -0
- package/dist/page-header.js +32 -0
- package/dist/page-header.js.map +1 -0
- package/dist/popover.d.ts +18 -0
- package/dist/popover.js +34 -0
- package/dist/popover.js.map +1 -0
- package/dist/progress.d.ts +87 -0
- package/dist/progress.js +85 -0
- package/dist/progress.js.map +1 -0
- package/dist/radio-group.d.ts +77 -0
- package/dist/radio-group.js +48 -0
- package/dist/radio-group.js.map +1 -0
- package/dist/separator.d.ts +24 -0
- package/dist/separator.js +17 -0
- package/dist/separator.js.map +1 -0
- package/dist/slider.d.ts +88 -0
- package/dist/slider.js +82 -0
- package/dist/slider.js.map +1 -0
- package/dist/stat.d.ts +75 -0
- package/dist/stat.js +42 -0
- package/dist/stat.js.map +1 -0
- package/dist/switch.d.ts +72 -0
- package/dist/switch.js +38 -0
- package/dist/switch.js.map +1 -0
- package/dist/tabs.d.ts +83 -0
- package/dist/tabs.js +60 -0
- package/dist/tabs.js.map +1 -0
- package/dist/theme.d.ts +2 -59
- package/dist/theme.js +13 -34
- package/dist/theme.js.map +1 -1
- package/dist/toast.d.ts +32 -0
- package/dist/toast.js +49 -0
- package/dist/toast.js.map +1 -0
- package/dist/tooltip.d.ts +21 -0
- package/dist/tooltip.js +44 -0
- package/dist/tooltip.js.map +1 -0
- package/package.json +291 -5
- package/dist/chunk-CPMZS4XA.js.map +0 -1
package/README.md
CHANGED
|
@@ -27,7 +27,9 @@ is one CSS file. The primitives: **React 19** and Tailwind CSS v4 with the Kriza
|
|
|
27
27
|
|
|
28
28
|
## Primitives
|
|
29
29
|
|
|
30
|
-
> 2.0 beta: the
|
|
30
|
+
> 2.0 beta: the atoms, the structure of a page and what opens over it (cards, dialogs, sheets, toasts, popovers,
|
|
31
|
+
> menus, tooltips), then navigation and input (tabs, chips, switches, sliders, checkboxes, radios, the command palette,
|
|
32
|
+
> the two-step confirm button, progress).
|
|
31
33
|
|
|
32
34
|
### Install
|
|
33
35
|
|
|
@@ -47,6 +49,9 @@ import { Button, IconButton } from "@krizaka/ui/button";
|
|
|
47
49
|
import { Badge } from "@krizaka/ui/badge";
|
|
48
50
|
import { Field, Input } from "@krizaka/ui/field";
|
|
49
51
|
import { ThemeProvider, ThemeScript, ThemeToggle } from "@krizaka/ui/theme";
|
|
52
|
+
import { Card } from "@krizaka/ui/card";
|
|
53
|
+
import { AlertDialog, Dialog } from "@krizaka/ui/dialog";
|
|
54
|
+
import { toast, Toaster } from "@krizaka/ui/toast";
|
|
50
55
|
|
|
51
56
|
<Button variant="primary" loading={saving}>{t("save")}</Button>
|
|
52
57
|
<Button asChild variant="outline"><Link href="/docs">{t("docs")}</Link></Button>
|
|
@@ -56,6 +61,27 @@ import { ThemeProvider, ThemeScript, ThemeToggle } from "@krizaka/ui/theme";
|
|
|
56
61
|
<Input id="email" invalid={!!error} aria-describedby="email-error" />
|
|
57
62
|
{error && <Field.Error id="email-error">{error}</Field.Error>}
|
|
58
63
|
</Field.Root>
|
|
64
|
+
|
|
65
|
+
<Card.Root asChild interactive reveal={index}>
|
|
66
|
+
<Link href={href}>
|
|
67
|
+
<Card.Media><Card.Image src={cover} fallback={<PlayIcon />} /></Card.Media>
|
|
68
|
+
<Card.Body><Card.Title>{title}</Card.Title></Card.Body>
|
|
69
|
+
</Link>
|
|
70
|
+
</Card.Root>
|
|
71
|
+
|
|
72
|
+
<Dialog.Root>
|
|
73
|
+
<Dialog.Trigger asChild><Button>{t("edit")}</Button></Dialog.Trigger>
|
|
74
|
+
<Dialog.Content closeLabel={t("close")} placement="bottom">
|
|
75
|
+
<Dialog.Header><Dialog.Title>{t("editTitle")}</Dialog.Title></Dialog.Header>
|
|
76
|
+
<Dialog.Body>…</Dialog.Body>
|
|
77
|
+
</Dialog.Content>
|
|
78
|
+
</Dialog.Root>
|
|
79
|
+
|
|
80
|
+
<AlertDialog tone="danger" trigger={<Button variant="danger">{t("delete")}</Button>} title={t("deleteTitle")}
|
|
81
|
+
confirmLabel={t("delete")} cancelLabel={t("cancel")} onConfirm={() => deleteVideo(id)} />
|
|
82
|
+
|
|
83
|
+
// once, in the root layout — then toast.success(t("saved")) anywhere on the client
|
|
84
|
+
<Toaster label={t("notifications")} closeLabel={t("dismiss")} />
|
|
59
85
|
```
|
|
60
86
|
|
|
61
87
|
**React 19 is required by the primitives** (`ref` is a prop, no `forwardRef`). The package keeps `react >= 18` as its
|
|
@@ -64,7 +90,8 @@ peer range, because the marks and the motion still run on React 18: one `package
|
|
|
64
90
|
|
|
65
91
|
### The component contract (12 points)
|
|
66
92
|
|
|
67
|
-
1. **Composed when there is structure** (`Field.*`, `Avatar.Group`), **flat for an atom**
|
|
93
|
+
1. **Composed when there is structure** (`Card.*`, `Dialog.*`, `Field.*`, `Avatar.Group`), **flat for an atom**
|
|
94
|
+
(`Button`, `Badge`, `Input`, `Stat`).
|
|
68
95
|
2. **Variants exported next to the component** (`buttonVariants`, `badgeVariants`): a `<Link>` or a Server Component
|
|
69
96
|
is styled without importing the component.
|
|
70
97
|
3. **`asChild`** (Radix `Slot`) rather than `as`: props, `className` and `ref` are merged into the child.
|
|
@@ -74,7 +101,8 @@ peer range, because the marks and the motion still run on React 18: one `package
|
|
|
74
101
|
6. **Controlled and uncontrolled**: `value`/`defaultValue` + `onValueChange`, `open`/`defaultOpen` + `onOpenChange`.
|
|
75
102
|
7. **State is exposed as `data-*`** (`data-tone`, `data-loading`, `data-invalid`, `data-urgent`, `data-mode`): a
|
|
76
103
|
product styles a state without a new variant.
|
|
77
|
-
8. **Server by default**: `"use client"` only on the entries with a hook or a portal (`avatar`, `theme`, `countdown
|
|
104
|
+
8. **Server by default**: `"use client"` only on the entries with a hook or a portal (`avatar`, `theme`, `countdown`,
|
|
105
|
+
`dialog`, `toast`, `popover`, `dropdown-menu`, `tooltip`).
|
|
78
106
|
One build entry per component; the directive is kept per entry.
|
|
79
107
|
9. **React 19 minimum for the primitives**; the marks stay `react >= 18`.
|
|
80
108
|
10. **Accessibility is delegated**: non-trivial interactions on Radix UI (`radix-ui`), the command palette on cmdk,
|
|
@@ -101,6 +129,26 @@ Colours are roles of the preset (`bg-surface-2`, `text-fg-secondary`, `border-bo
|
|
|
101
129
|
| `@krizaka/ui/empty-state` | `EmptyState` (`icon`, `title`, `description`, `action`) | server |
|
|
102
130
|
| `@krizaka/ui/spinner` | `Spinner` (`label`, `size`) | server |
|
|
103
131
|
| `@krizaka/ui/countdown` | `Countdown` (`target`, `label`, `units`, `size`, `urgentBelowMs`, `skewMs`), `useCountdown`, `splitDuration` | client |
|
|
132
|
+
| `@krizaka/ui/card` | `Card.Root` (`asChild`, `reveal`, `radius` md·lg·xl, `tone` default·elevated·glass, `interactive`), `Card.Media` (`aspect` video·square·portrait·auto), `Card.Image` (`fallback`), `Card.Overlay` (`corner`), `Card.Body` (`padding`), `Card.Title` (`as`), `Card.Description`, `Card.Stat` (`label`), `Card.Footer`; `card` (the slots) | server |
|
|
133
|
+
| `@krizaka/ui/dialog` | `Dialog.Root/Trigger/Content/Header/Title/Description/Body/Footer/Close` (`placement` center·bottom·right, `size` sm·md·lg, `closeLabel` required unless `hideClose`, `dismissible={false}`: no close on Escape or outside click), `Sheet` (= `placement="bottom"`), `AlertDialog` (`title`, `description`, `confirmLabel`, `cancelLabel`, `tone` danger·primary, async `onConfirm`, `trigger`) | client |
|
|
134
|
+
| `@krizaka/ui/toast` | `Toaster` (sonner styled by roles: `label`, `closeLabel`, `position`, `closeButton`; `richColors` off), `toast` (`.success/.warning/.error/.info/.custom`…) | client |
|
|
135
|
+
| `@krizaka/ui/popover` | `Popover.Root/Trigger/Anchor/Content/Close` | client |
|
|
136
|
+
| `@krizaka/ui/dropdown-menu` | `DropdownMenu.Root/Trigger/Content/Item/CheckboxItem/Label/Separator/Group` (`Item` `tone` default·danger), `menu` (the slots) | client |
|
|
137
|
+
| `@krizaka/ui/tooltip` | `Tooltip` (`content`, `delayDuration` 300, `side`, `open`/`defaultOpen`), `TooltipProvider` | client |
|
|
138
|
+
| `@krizaka/ui/stat` | `Stat` (`label`, `value`, `hint`, `trend` up·down·flat, `trendLabel`) | server |
|
|
139
|
+
| `@krizaka/ui/page-header` | `PageHeader` (`title`, `description`, `actions`, `breadcrumb`, `as` h1·h2) | server |
|
|
140
|
+
| `@krizaka/ui/alert` | `Alert` (`tone` info·success·warning·danger, `icon`, `title`, `action`; `role="alert"` for danger and warning, `status` otherwise), `alertVariants` | server |
|
|
141
|
+
| `@krizaka/ui/separator` | `Separator` (`orientation`, `decorative`, Radix), `separatorVariants` | server |
|
|
142
|
+
| `@krizaka/ui/kbd` | `Kbd` (`size` sm·md), `kbdVariants` | server |
|
|
143
|
+
| `@krizaka/ui/tabs` | `Tabs.Root/List/Trigger/Content` (`variant` underline·segmented·pills on the root, `orientation`, `value`/`defaultValue` + `onValueChange`), `tabs` (the slots) | client |
|
|
144
|
+
| `@krizaka/ui/chip` | `Chip` (`selected`/`defaultSelected` + `onSelectedChange`, `size` sm·md; `removable` + `removeLabel` + `onRemove`), `Chip.Group` (`type` single·multiple, `label`, `required` for single), `chip` (the slots) | client |
|
|
145
|
+
| `@krizaka/ui/switch` | `Switch` (`checked`/`defaultChecked` + `onCheckedChange`, `label` unless a visible label names it, `size` sm·md, `invalid`), `switchVariants` | client |
|
|
146
|
+
| `@krizaka/ui/slider` | `Slider` (`value`: a number or a `[min, max]` range, `onValueChange`, `onValueCommit`, `label`, `thumbLabels`, `formatValue` → aria-valuetext, `showLabel`, `origin`), `slider` (the slots) | client |
|
|
147
|
+
| `@krizaka/ui/checkbox` | `Checkbox` (`checked` true·false·"indeterminate" + `onCheckedChange`, `invalid`, its words as children) — sits in a `Field` | client |
|
|
148
|
+
| `@krizaka/ui/radio-group` | `RadioGroup.Root` (`label`, `orientation`, `invalid`), `RadioGroup.Item` (a dot and its words), `RadioGroup.Card` (a whole card is the radio) | client |
|
|
149
|
+
| `@krizaka/ui/command` | `Command.Root` (`label`, `shouldFilter`…) `/Input` (`placeholder`, `trailing`) `/List` (`label`) `/Empty` (`emptyLabel`) `/Loading/Group/Item/Separator/Shortcut` on cmdk; `CommandDialog` (`label`, `open`/`onOpenChange`, `footer`, `contentProps`) | client |
|
|
150
|
+
| `@krizaka/ui/confirm-button` | `ConfirmButton` (two presses: `confirmLabel`, `onConfirm`, `timeoutMs` 4000, `label` for an icon, `armedContent`; the `Button` variants), `confirmArmed` | client |
|
|
151
|
+
| `@krizaka/ui/progress` | `Progress` (`variant` bar·ring, `size` sm·md·lg, `value`/`max`, indeterminate without a value, `label`, `valueText`, a ring's centre as children) | server |
|
|
104
152
|
| `@krizaka/ui` | the marks, `MotionObserver`, `RotatingWord`, `cx` (unchanged) | client |
|
|
105
153
|
| `@krizaka/ui/native` | the marks for React Native (unchanged) | native |
|
|
106
154
|
| `@krizaka/ui/motion.css`, `@krizaka/ui/tailwind.css` | the motion signature; the `@source` of the primitives' classes | CSS |
|
|
@@ -170,6 +218,7 @@ import { MotionObserver, RotatingWord } from "@krizaka/ui";
|
|
|
170
218
|
| `kz-lift` | A card rising under the pointer |
|
|
171
219
|
| `kz-gradient-text`, `kz-marquee` | Drifting gradient text, endless bands |
|
|
172
220
|
| `kz-overlay`, `kz-dialog`, `kz-pop`, `kz-fade` | Backdrops, dialogs (from the bottom on phones), menus, views swapped in place |
|
|
221
|
+
| `kz-progress` | The indeterminate progress bar's travelling segment |
|
|
173
222
|
|
|
174
223
|
With Tailwind CSS v4, give every transition the same easing:
|
|
175
224
|
|
package/dist/alert.d.ts
ADDED
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
import * as tailwind_variants from 'tailwind-variants';
|
|
2
|
+
import { VariantProps } from 'tailwind-variants';
|
|
3
|
+
import * as React from 'react';
|
|
4
|
+
|
|
5
|
+
declare const alertVariants: tailwind_variants.TVReturnType<{
|
|
6
|
+
tone: {
|
|
7
|
+
info: {
|
|
8
|
+
root: string;
|
|
9
|
+
icon: string;
|
|
10
|
+
};
|
|
11
|
+
success: {
|
|
12
|
+
root: string;
|
|
13
|
+
icon: string;
|
|
14
|
+
};
|
|
15
|
+
warning: {
|
|
16
|
+
root: string;
|
|
17
|
+
icon: string;
|
|
18
|
+
};
|
|
19
|
+
danger: {
|
|
20
|
+
root: string;
|
|
21
|
+
icon: string;
|
|
22
|
+
};
|
|
23
|
+
};
|
|
24
|
+
}, {
|
|
25
|
+
root: string;
|
|
26
|
+
icon: string;
|
|
27
|
+
content: string;
|
|
28
|
+
title: string;
|
|
29
|
+
description: string;
|
|
30
|
+
action: string;
|
|
31
|
+
}, undefined, {
|
|
32
|
+
tone: {
|
|
33
|
+
info: {
|
|
34
|
+
root: string;
|
|
35
|
+
icon: string;
|
|
36
|
+
};
|
|
37
|
+
success: {
|
|
38
|
+
root: string;
|
|
39
|
+
icon: string;
|
|
40
|
+
};
|
|
41
|
+
warning: {
|
|
42
|
+
root: string;
|
|
43
|
+
icon: string;
|
|
44
|
+
};
|
|
45
|
+
danger: {
|
|
46
|
+
root: string;
|
|
47
|
+
icon: string;
|
|
48
|
+
};
|
|
49
|
+
};
|
|
50
|
+
}, {
|
|
51
|
+
root: string;
|
|
52
|
+
icon: string;
|
|
53
|
+
content: string;
|
|
54
|
+
title: string;
|
|
55
|
+
description: string;
|
|
56
|
+
action: string;
|
|
57
|
+
}, tailwind_variants.TVReturnTypeLike<{
|
|
58
|
+
tone: {
|
|
59
|
+
info: {
|
|
60
|
+
root: string;
|
|
61
|
+
icon: string;
|
|
62
|
+
};
|
|
63
|
+
success: {
|
|
64
|
+
root: string;
|
|
65
|
+
icon: string;
|
|
66
|
+
};
|
|
67
|
+
warning: {
|
|
68
|
+
root: string;
|
|
69
|
+
icon: string;
|
|
70
|
+
};
|
|
71
|
+
danger: {
|
|
72
|
+
root: string;
|
|
73
|
+
icon: string;
|
|
74
|
+
};
|
|
75
|
+
};
|
|
76
|
+
}, {
|
|
77
|
+
root: string;
|
|
78
|
+
icon: string;
|
|
79
|
+
content: string;
|
|
80
|
+
title: string;
|
|
81
|
+
description: string;
|
|
82
|
+
action: string;
|
|
83
|
+
}>>;
|
|
84
|
+
type AlertTone = NonNullable<VariantProps<typeof alertVariants>["tone"]>;
|
|
85
|
+
type AlertProps = Omit<React.ComponentProps<"div">, "title"> & {
|
|
86
|
+
tone?: AlertTone;
|
|
87
|
+
/** A decorative icon (hidden from assistive technology). */
|
|
88
|
+
icon?: React.ReactNode;
|
|
89
|
+
title?: React.ReactNode;
|
|
90
|
+
/** What to do: a Button, a link. */
|
|
91
|
+
action?: React.ReactNode;
|
|
92
|
+
};
|
|
93
|
+
declare function Alert({ tone, icon, title, action, className, children, ...props }: AlertProps): React.JSX.Element;
|
|
94
|
+
|
|
95
|
+
export { Alert, type AlertProps, type AlertTone, alertVariants };
|
package/dist/alert.js
ADDED
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
// src/alert/alert.tsx
|
|
2
|
+
import { tv } from "tailwind-variants";
|
|
3
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
4
|
+
var alertVariants = tv({
|
|
5
|
+
slots: {
|
|
6
|
+
root: "relative flex w-full items-start gap-3 rounded-xl border p-4 text-sm text-fg",
|
|
7
|
+
icon: "mt-0.5 flex h-5 w-5 shrink-0 items-center justify-center [&>svg]:h-5 [&>svg]:w-5",
|
|
8
|
+
content: "flex min-w-0 flex-1 flex-col gap-1",
|
|
9
|
+
title: "font-semibold text-fg",
|
|
10
|
+
description: "text-fg-secondary",
|
|
11
|
+
action: "flex shrink-0 items-center gap-2 self-center"
|
|
12
|
+
},
|
|
13
|
+
variants: {
|
|
14
|
+
tone: {
|
|
15
|
+
info: { root: "border-info/40 bg-info/10", icon: "text-info" },
|
|
16
|
+
success: { root: "border-success/40 bg-success/10", icon: "text-success" },
|
|
17
|
+
warning: { root: "border-warning/50 bg-warning/10", icon: "text-warning" },
|
|
18
|
+
danger: { root: "border-danger/50 bg-danger/10", icon: "text-danger" }
|
|
19
|
+
}
|
|
20
|
+
},
|
|
21
|
+
defaultVariants: { tone: "info" }
|
|
22
|
+
});
|
|
23
|
+
function Alert({ tone = "info", icon, title, action, className, children, ...props }) {
|
|
24
|
+
const s = alertVariants({ tone });
|
|
25
|
+
return /* @__PURE__ */ jsxs("div", { role: tone === "danger" || tone === "warning" ? "alert" : "status", "data-tone": tone, className: s.root({ className }), ...props, children: [
|
|
26
|
+
icon && /* @__PURE__ */ jsx("span", { "aria-hidden": true, className: s.icon(), children: icon }),
|
|
27
|
+
/* @__PURE__ */ jsxs("div", { className: s.content(), children: [
|
|
28
|
+
title && /* @__PURE__ */ jsx("p", { className: s.title(), children: title }),
|
|
29
|
+
children && /* @__PURE__ */ jsx("div", { className: s.description(), children })
|
|
30
|
+
] }),
|
|
31
|
+
action && /* @__PURE__ */ jsx("div", { className: s.action(), children: action })
|
|
32
|
+
] });
|
|
33
|
+
}
|
|
34
|
+
export {
|
|
35
|
+
Alert,
|
|
36
|
+
alertVariants
|
|
37
|
+
};
|
|
38
|
+
//# sourceMappingURL=alert.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/alert/alert.tsx"],"sourcesContent":["// Server-safe. A message in the flow of the page (not a toast): a tone, an icon, a title, a text, an action.\n// danger and warning are announced at once (role=\"alert\"); info and success politely (role=\"status\").\nimport type * as React from \"react\";\nimport { tv, type VariantProps } from \"tailwind-variants\";\n\n// Soft tones (a tint, a tinted border, a coloured icon): the text stays a text role — the invariant status tokens are\n// too light for small text on a light surface (WCAG AA).\nexport const alertVariants = tv({\n slots: {\n root: \"relative flex w-full items-start gap-3 rounded-xl border p-4 text-sm text-fg\",\n icon: \"mt-0.5 flex h-5 w-5 shrink-0 items-center justify-center [&>svg]:h-5 [&>svg]:w-5\",\n content: \"flex min-w-0 flex-1 flex-col gap-1\",\n title: \"font-semibold text-fg\",\n description: \"text-fg-secondary\",\n action: \"flex shrink-0 items-center gap-2 self-center\",\n },\n variants: {\n tone: {\n info: { root: \"border-info/40 bg-info/10\", icon: \"text-info\" },\n success: { root: \"border-success/40 bg-success/10\", icon: \"text-success\" },\n warning: { root: \"border-warning/50 bg-warning/10\", icon: \"text-warning\" },\n danger: { root: \"border-danger/50 bg-danger/10\", icon: \"text-danger\" },\n },\n },\n defaultVariants: { tone: \"info\" },\n});\n\nexport type AlertTone = NonNullable<VariantProps<typeof alertVariants>[\"tone\"]>;\n\nexport type AlertProps = Omit<React.ComponentProps<\"div\">, \"title\"> & {\n tone?: AlertTone;\n /** A decorative icon (hidden from assistive technology). */\n icon?: React.ReactNode;\n title?: React.ReactNode;\n /** What to do: a Button, a link. */\n action?: React.ReactNode;\n};\n\nexport function Alert({ tone = \"info\", icon, title, action, className, children, ...props }: AlertProps) {\n const s = alertVariants({ tone });\n return (\n <div role={tone === \"danger\" || tone === \"warning\" ? \"alert\" : \"status\"} data-tone={tone} className={s.root({ className })} {...props}>\n {icon && (\n <span aria-hidden className={s.icon()}>\n {icon}\n </span>\n )}\n <div className={s.content()}>\n {title && <p className={s.title()}>{title}</p>}\n {children && <div className={s.description()}>{children}</div>}\n </div>\n {action && <div className={s.action()}>{action}</div>}\n </div>\n );\n}\n"],"mappings":";AAGA,SAAS,UAA6B;AAwC9B,cAIF,YAJE;AApCD,IAAM,gBAAgB,GAAG;AAAA,EAC9B,OAAO;AAAA,IACL,MAAM;AAAA,IACN,MAAM;AAAA,IACN,SAAS;AAAA,IACT,OAAO;AAAA,IACP,aAAa;AAAA,IACb,QAAQ;AAAA,EACV;AAAA,EACA,UAAU;AAAA,IACR,MAAM;AAAA,MACJ,MAAM,EAAE,MAAM,6BAA6B,MAAM,YAAY;AAAA,MAC7D,SAAS,EAAE,MAAM,mCAAmC,MAAM,eAAe;AAAA,MACzE,SAAS,EAAE,MAAM,mCAAmC,MAAM,eAAe;AAAA,MACzE,QAAQ,EAAE,MAAM,iCAAiC,MAAM,cAAc;AAAA,IACvE;AAAA,EACF;AAAA,EACA,iBAAiB,EAAE,MAAM,OAAO;AAClC,CAAC;AAaM,SAAS,MAAM,EAAE,OAAO,QAAQ,MAAM,OAAO,QAAQ,WAAW,UAAU,GAAG,MAAM,GAAe;AACvG,QAAM,IAAI,cAAc,EAAE,KAAK,CAAC;AAChC,SACE,qBAAC,SAAI,MAAM,SAAS,YAAY,SAAS,YAAY,UAAU,UAAU,aAAW,MAAM,WAAW,EAAE,KAAK,EAAE,UAAU,CAAC,GAAI,GAAG,OAC7H;AAAA,YACC,oBAAC,UAAK,eAAW,MAAC,WAAW,EAAE,KAAK,GACjC,gBACH;AAAA,IAEF,qBAAC,SAAI,WAAW,EAAE,QAAQ,GACvB;AAAA,eAAS,oBAAC,OAAE,WAAW,EAAE,MAAM,GAAI,iBAAM;AAAA,MACzC,YAAY,oBAAC,SAAI,WAAW,EAAE,YAAY,GAAI,UAAS;AAAA,OAC1D;AAAA,IACC,UAAU,oBAAC,SAAI,WAAW,EAAE,OAAO,GAAI,kBAAO;AAAA,KACjD;AAEJ;","names":[]}
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import * as tailwind_variants from 'tailwind-variants';
|
|
2
|
+
import { VariantProps } from 'tailwind-variants';
|
|
3
|
+
import * as React from 'react';
|
|
4
|
+
|
|
5
|
+
declare const buttonVariants: tailwind_variants.TVReturnType<{
|
|
6
|
+
variant: {
|
|
7
|
+
primary: "bg-accent text-on-accent shadow-sm hover:bg-accent-hover";
|
|
8
|
+
secondary: "border border-border-default bg-surface-2 text-fg hover:border-border-strong hover:bg-surface-3";
|
|
9
|
+
outline: "border border-border-default bg-transparent text-fg hover:border-accent hover:text-accent";
|
|
10
|
+
ghost: "text-fg-secondary hover:bg-surface-2 hover:text-fg";
|
|
11
|
+
danger: "border border-danger/50 bg-danger/10 text-fg hover:border-danger hover:bg-danger/20";
|
|
12
|
+
};
|
|
13
|
+
size: {
|
|
14
|
+
sm: "h-8 px-3 text-xs";
|
|
15
|
+
md: "h-10 px-4 text-sm";
|
|
16
|
+
lg: "h-12 px-6 text-sm";
|
|
17
|
+
icon: "h-10 w-10";
|
|
18
|
+
};
|
|
19
|
+
shape: {
|
|
20
|
+
rounded: "rounded-lg";
|
|
21
|
+
pill: "rounded-full";
|
|
22
|
+
};
|
|
23
|
+
}, undefined, string, {
|
|
24
|
+
variant: {
|
|
25
|
+
primary: "bg-accent text-on-accent shadow-sm hover:bg-accent-hover";
|
|
26
|
+
secondary: "border border-border-default bg-surface-2 text-fg hover:border-border-strong hover:bg-surface-3";
|
|
27
|
+
outline: "border border-border-default bg-transparent text-fg hover:border-accent hover:text-accent";
|
|
28
|
+
ghost: "text-fg-secondary hover:bg-surface-2 hover:text-fg";
|
|
29
|
+
danger: "border border-danger/50 bg-danger/10 text-fg hover:border-danger hover:bg-danger/20";
|
|
30
|
+
};
|
|
31
|
+
size: {
|
|
32
|
+
sm: "h-8 px-3 text-xs";
|
|
33
|
+
md: "h-10 px-4 text-sm";
|
|
34
|
+
lg: "h-12 px-6 text-sm";
|
|
35
|
+
icon: "h-10 w-10";
|
|
36
|
+
};
|
|
37
|
+
shape: {
|
|
38
|
+
rounded: "rounded-lg";
|
|
39
|
+
pill: "rounded-full";
|
|
40
|
+
};
|
|
41
|
+
}, undefined, tailwind_variants.TVReturnTypeLike<{
|
|
42
|
+
variant: {
|
|
43
|
+
primary: "bg-accent text-on-accent shadow-sm hover:bg-accent-hover";
|
|
44
|
+
secondary: "border border-border-default bg-surface-2 text-fg hover:border-border-strong hover:bg-surface-3";
|
|
45
|
+
outline: "border border-border-default bg-transparent text-fg hover:border-accent hover:text-accent";
|
|
46
|
+
ghost: "text-fg-secondary hover:bg-surface-2 hover:text-fg";
|
|
47
|
+
danger: "border border-danger/50 bg-danger/10 text-fg hover:border-danger hover:bg-danger/20";
|
|
48
|
+
};
|
|
49
|
+
size: {
|
|
50
|
+
sm: "h-8 px-3 text-xs";
|
|
51
|
+
md: "h-10 px-4 text-sm";
|
|
52
|
+
lg: "h-12 px-6 text-sm";
|
|
53
|
+
icon: "h-10 w-10";
|
|
54
|
+
};
|
|
55
|
+
shape: {
|
|
56
|
+
rounded: "rounded-lg";
|
|
57
|
+
pill: "rounded-full";
|
|
58
|
+
};
|
|
59
|
+
}, undefined>>;
|
|
60
|
+
type ButtonVariants = VariantProps<typeof buttonVariants>;
|
|
61
|
+
type ButtonProps = React.ComponentProps<"button"> & ButtonVariants & {
|
|
62
|
+
/** Renders the child (e.g. a <Link>) instead of the <button>, with props, classes and ref merged. */
|
|
63
|
+
asChild?: boolean;
|
|
64
|
+
/** Disables and signals the wait (aria-busy, data-loading) — the product adds a spinner if it wants one. */
|
|
65
|
+
loading?: boolean;
|
|
66
|
+
};
|
|
67
|
+
|
|
68
|
+
export type { ButtonProps as B, ButtonVariants as a };
|
package/dist/card.d.ts
ADDED
|
@@ -0,0 +1,227 @@
|
|
|
1
|
+
import * as tailwind_variants from 'tailwind-variants';
|
|
2
|
+
import { VariantProps } from 'tailwind-variants';
|
|
3
|
+
import * as React from 'react';
|
|
4
|
+
|
|
5
|
+
declare const card: tailwind_variants.TVReturnType<{
|
|
6
|
+
radius: {
|
|
7
|
+
md: {
|
|
8
|
+
root: string;
|
|
9
|
+
};
|
|
10
|
+
lg: {
|
|
11
|
+
root: string;
|
|
12
|
+
};
|
|
13
|
+
xl: {
|
|
14
|
+
root: string;
|
|
15
|
+
};
|
|
16
|
+
};
|
|
17
|
+
tone: {
|
|
18
|
+
default: {};
|
|
19
|
+
elevated: {
|
|
20
|
+
root: string;
|
|
21
|
+
};
|
|
22
|
+
glass: {
|
|
23
|
+
root: string;
|
|
24
|
+
};
|
|
25
|
+
};
|
|
26
|
+
interactive: {
|
|
27
|
+
true: {
|
|
28
|
+
root: string;
|
|
29
|
+
};
|
|
30
|
+
};
|
|
31
|
+
padding: {
|
|
32
|
+
none: {
|
|
33
|
+
body: string;
|
|
34
|
+
};
|
|
35
|
+
sm: {
|
|
36
|
+
body: string;
|
|
37
|
+
};
|
|
38
|
+
md: {
|
|
39
|
+
body: string;
|
|
40
|
+
};
|
|
41
|
+
lg: {
|
|
42
|
+
body: string;
|
|
43
|
+
};
|
|
44
|
+
};
|
|
45
|
+
}, {
|
|
46
|
+
root: string;
|
|
47
|
+
media: string;
|
|
48
|
+
image: string;
|
|
49
|
+
fallback: string;
|
|
50
|
+
overlay: string;
|
|
51
|
+
body: string;
|
|
52
|
+
title: string;
|
|
53
|
+
description: string;
|
|
54
|
+
stat: string;
|
|
55
|
+
statLabel: string;
|
|
56
|
+
statValue: string;
|
|
57
|
+
footer: string;
|
|
58
|
+
}, undefined, {
|
|
59
|
+
radius: {
|
|
60
|
+
md: {
|
|
61
|
+
root: string;
|
|
62
|
+
};
|
|
63
|
+
lg: {
|
|
64
|
+
root: string;
|
|
65
|
+
};
|
|
66
|
+
xl: {
|
|
67
|
+
root: string;
|
|
68
|
+
};
|
|
69
|
+
};
|
|
70
|
+
tone: {
|
|
71
|
+
default: {};
|
|
72
|
+
elevated: {
|
|
73
|
+
root: string;
|
|
74
|
+
};
|
|
75
|
+
glass: {
|
|
76
|
+
root: string;
|
|
77
|
+
};
|
|
78
|
+
};
|
|
79
|
+
interactive: {
|
|
80
|
+
true: {
|
|
81
|
+
root: string;
|
|
82
|
+
};
|
|
83
|
+
};
|
|
84
|
+
padding: {
|
|
85
|
+
none: {
|
|
86
|
+
body: string;
|
|
87
|
+
};
|
|
88
|
+
sm: {
|
|
89
|
+
body: string;
|
|
90
|
+
};
|
|
91
|
+
md: {
|
|
92
|
+
body: string;
|
|
93
|
+
};
|
|
94
|
+
lg: {
|
|
95
|
+
body: string;
|
|
96
|
+
};
|
|
97
|
+
};
|
|
98
|
+
}, {
|
|
99
|
+
root: string;
|
|
100
|
+
media: string;
|
|
101
|
+
image: string;
|
|
102
|
+
fallback: string;
|
|
103
|
+
overlay: string;
|
|
104
|
+
body: string;
|
|
105
|
+
title: string;
|
|
106
|
+
description: string;
|
|
107
|
+
stat: string;
|
|
108
|
+
statLabel: string;
|
|
109
|
+
statValue: string;
|
|
110
|
+
footer: string;
|
|
111
|
+
}, tailwind_variants.TVReturnTypeLike<{
|
|
112
|
+
radius: {
|
|
113
|
+
md: {
|
|
114
|
+
root: string;
|
|
115
|
+
};
|
|
116
|
+
lg: {
|
|
117
|
+
root: string;
|
|
118
|
+
};
|
|
119
|
+
xl: {
|
|
120
|
+
root: string;
|
|
121
|
+
};
|
|
122
|
+
};
|
|
123
|
+
tone: {
|
|
124
|
+
default: {};
|
|
125
|
+
elevated: {
|
|
126
|
+
root: string;
|
|
127
|
+
};
|
|
128
|
+
glass: {
|
|
129
|
+
root: string;
|
|
130
|
+
};
|
|
131
|
+
};
|
|
132
|
+
interactive: {
|
|
133
|
+
true: {
|
|
134
|
+
root: string;
|
|
135
|
+
};
|
|
136
|
+
};
|
|
137
|
+
padding: {
|
|
138
|
+
none: {
|
|
139
|
+
body: string;
|
|
140
|
+
};
|
|
141
|
+
sm: {
|
|
142
|
+
body: string;
|
|
143
|
+
};
|
|
144
|
+
md: {
|
|
145
|
+
body: string;
|
|
146
|
+
};
|
|
147
|
+
lg: {
|
|
148
|
+
body: string;
|
|
149
|
+
};
|
|
150
|
+
};
|
|
151
|
+
}, {
|
|
152
|
+
root: string;
|
|
153
|
+
media: string;
|
|
154
|
+
image: string;
|
|
155
|
+
fallback: string;
|
|
156
|
+
overlay: string;
|
|
157
|
+
body: string;
|
|
158
|
+
title: string;
|
|
159
|
+
description: string;
|
|
160
|
+
stat: string;
|
|
161
|
+
statLabel: string;
|
|
162
|
+
statValue: string;
|
|
163
|
+
footer: string;
|
|
164
|
+
}>>;
|
|
165
|
+
type CardVariants = VariantProps<typeof card>;
|
|
166
|
+
type CardRootProps = React.ComponentProps<"div"> & Pick<CardVariants, "radius" | "tone" | "interactive"> & {
|
|
167
|
+
/** Renders the child (a link, an article) instead of the <div>, with props, classes and ref merged. */
|
|
168
|
+
asChild?: boolean;
|
|
169
|
+
/** Enters on scroll (MotionObserver): the index in the grid becomes the delay (50 ms a step, 8 steps at most). */
|
|
170
|
+
reveal?: number;
|
|
171
|
+
};
|
|
172
|
+
declare function CardRoot({ asChild, reveal, radius, tone, interactive, className, style, ...props }: CardRootProps): React.JSX.Element;
|
|
173
|
+
declare const ASPECT: {
|
|
174
|
+
readonly video: "aspect-video";
|
|
175
|
+
readonly square: "aspect-square";
|
|
176
|
+
readonly portrait: "aspect-[3/4]";
|
|
177
|
+
readonly auto: "";
|
|
178
|
+
};
|
|
179
|
+
type CardMediaProps = React.ComponentProps<"div"> & {
|
|
180
|
+
aspect?: keyof typeof ASPECT;
|
|
181
|
+
};
|
|
182
|
+
declare function CardMedia({ aspect, className, ...props }: CardMediaProps): React.JSX.Element;
|
|
183
|
+
type CardImageProps = Omit<React.ComponentProps<"img">, "src"> & {
|
|
184
|
+
src?: string | null;
|
|
185
|
+
/** Shown when there is no image: an icon, an illustration (decorative). */
|
|
186
|
+
fallback?: React.ReactNode;
|
|
187
|
+
};
|
|
188
|
+
/** The image of a media, or its `fallback` when there is none. `alt` is empty by default: the title names the card. */
|
|
189
|
+
declare function CardImage({ src, alt, fallback, className, ...props }: CardImageProps): React.JSX.Element;
|
|
190
|
+
declare const CORNER: {
|
|
191
|
+
readonly "top-left": "left-2.5 top-2.5";
|
|
192
|
+
readonly "top-right": "right-2.5 top-2.5";
|
|
193
|
+
readonly "bottom-left": "bottom-2.5 left-2.5";
|
|
194
|
+
readonly "bottom-right": "bottom-2.5 right-2.5";
|
|
195
|
+
};
|
|
196
|
+
type CardOverlayProps = React.ComponentProps<"div"> & {
|
|
197
|
+
corner?: keyof typeof CORNER;
|
|
198
|
+
};
|
|
199
|
+
/** What sits on the media (badges, a caption). `scrim` and `fg-on-media` are invariant: nothing to do for light. */
|
|
200
|
+
declare function CardOverlay({ corner, className, ...props }: CardOverlayProps): React.JSX.Element;
|
|
201
|
+
type CardBodyProps = React.ComponentProps<"div"> & Pick<CardVariants, "padding">;
|
|
202
|
+
declare function CardBody({ padding, className, ...props }: CardBodyProps): React.JSX.Element;
|
|
203
|
+
type CardTitleProps = React.ComponentProps<"h3"> & {
|
|
204
|
+
as?: "h2" | "h3" | "h4";
|
|
205
|
+
};
|
|
206
|
+
declare function CardTitle({ as: Tag, className, ...props }: CardTitleProps): React.JSX.Element;
|
|
207
|
+
declare function CardDescription({ className, ...props }: React.ComponentProps<"p">): React.JSX.Element;
|
|
208
|
+
type CardStatProps = React.ComponentProps<"div"> & {
|
|
209
|
+
label: React.ReactNode;
|
|
210
|
+
};
|
|
211
|
+
/** A figure put forward: the label in capitals, the value in tabular digits. */
|
|
212
|
+
declare function CardStat({ label, className, children, ...props }: CardStatProps): React.JSX.Element;
|
|
213
|
+
declare function CardFooter({ className, ...props }: React.ComponentProps<"div">): React.JSX.Element;
|
|
214
|
+
/** `Card.Root/Media/Image/Overlay/Body/Title/Description/Stat/Footer`. */
|
|
215
|
+
declare const Card: {
|
|
216
|
+
Root: typeof CardRoot;
|
|
217
|
+
Media: typeof CardMedia;
|
|
218
|
+
Image: typeof CardImage;
|
|
219
|
+
Overlay: typeof CardOverlay;
|
|
220
|
+
Body: typeof CardBody;
|
|
221
|
+
Title: typeof CardTitle;
|
|
222
|
+
Description: typeof CardDescription;
|
|
223
|
+
Stat: typeof CardStat;
|
|
224
|
+
Footer: typeof CardFooter;
|
|
225
|
+
};
|
|
226
|
+
|
|
227
|
+
export { Card, CardBody, type CardBodyProps, CardDescription, CardFooter, CardImage, type CardImageProps, CardMedia, type CardMediaProps, CardOverlay, type CardOverlayProps, CardRoot, type CardRootProps, CardStat, type CardStatProps, CardTitle, type CardTitleProps, card };
|
package/dist/card.js
ADDED
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
import {
|
|
2
|
+
cn
|
|
3
|
+
} from "./chunk-FJDSLNXK.js";
|
|
4
|
+
|
|
5
|
+
// src/card/card.tsx
|
|
6
|
+
import { Slot } from "radix-ui";
|
|
7
|
+
import { tv } from "tailwind-variants";
|
|
8
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
9
|
+
var card = tv({
|
|
10
|
+
slots: {
|
|
11
|
+
root: "group relative flex flex-col overflow-hidden border border-border-default bg-surface-1 text-fg transition-colors focus-visible:outline-hidden focus-visible:ring-2 focus-visible:ring-ring",
|
|
12
|
+
media: "relative overflow-hidden bg-media",
|
|
13
|
+
image: "h-full w-full object-cover transition-transform duration-500 motion-safe:group-hover:scale-105",
|
|
14
|
+
fallback: "flex h-full w-full items-center justify-center bg-linear-to-br from-accent/15 via-media to-accent-2/15 text-accent/60",
|
|
15
|
+
overlay: "absolute z-10 flex items-center gap-1.5",
|
|
16
|
+
body: "relative flex flex-1 flex-col gap-3",
|
|
17
|
+
title: "line-clamp-1 text-sm font-semibold text-fg transition-colors group-hover:text-accent",
|
|
18
|
+
description: "line-clamp-2 text-xs text-fg-secondary",
|
|
19
|
+
stat: "min-w-0",
|
|
20
|
+
statLabel: "text-[10px] font-semibold uppercase tracking-wider text-fg-secondary",
|
|
21
|
+
statValue: "font-display text-xl font-black tabular-nums text-fg",
|
|
22
|
+
footer: "relative mt-auto flex items-center gap-2 border-t border-border-subtle pt-3 text-xs text-fg-secondary"
|
|
23
|
+
},
|
|
24
|
+
variants: {
|
|
25
|
+
radius: { md: { root: "rounded-md" }, lg: { root: "rounded-lg" }, xl: { root: "rounded-xl" } },
|
|
26
|
+
tone: { default: {}, elevated: { root: "bg-surface-2 shadow-md" }, glass: { root: "bg-surface-1/70 backdrop-blur-md" } },
|
|
27
|
+
interactive: { true: { root: "kz-spotlight kz-lift hover:border-accent/50" } },
|
|
28
|
+
padding: { none: { body: "p-0" }, sm: { body: "p-3" }, md: { body: "p-4" }, lg: { body: "p-6" } }
|
|
29
|
+
},
|
|
30
|
+
defaultVariants: { radius: "xl", tone: "default", padding: "md" }
|
|
31
|
+
});
|
|
32
|
+
var slots = card();
|
|
33
|
+
function CardRoot({ asChild, reveal, radius, tone, interactive, className, style, ...props }) {
|
|
34
|
+
const Comp = asChild ? Slot.Root : "div";
|
|
35
|
+
const revealStyle = reveal === void 0 ? style : { ...style, "--kz-delay": `${Math.min(Math.max(reveal, 0), 8) * 50}ms` };
|
|
36
|
+
return /* @__PURE__ */ jsx(
|
|
37
|
+
Comp,
|
|
38
|
+
{
|
|
39
|
+
"data-reveal": reveal === void 0 ? void 0 : "",
|
|
40
|
+
"data-interactive": interactive ? "" : void 0,
|
|
41
|
+
style: revealStyle,
|
|
42
|
+
className: card({ radius, tone, interactive }).root({ className }),
|
|
43
|
+
...props
|
|
44
|
+
}
|
|
45
|
+
);
|
|
46
|
+
}
|
|
47
|
+
var ASPECT = { video: "aspect-video", square: "aspect-square", portrait: "aspect-[3/4]", auto: "" };
|
|
48
|
+
function CardMedia({ aspect = "video", className, ...props }) {
|
|
49
|
+
return /* @__PURE__ */ jsx("div", { "data-aspect": aspect, className: slots.media({ className: cn(ASPECT[aspect], className) }), ...props });
|
|
50
|
+
}
|
|
51
|
+
function CardImage({ src, alt = "", fallback, className, ...props }) {
|
|
52
|
+
if (!src) {
|
|
53
|
+
return /* @__PURE__ */ jsx("div", { "data-fallback": "", "aria-hidden": true, className: slots.fallback({ className }), children: fallback });
|
|
54
|
+
}
|
|
55
|
+
return /* @__PURE__ */ jsx("img", { src, alt, loading: "lazy", decoding: "async", className: slots.image({ className }), ...props });
|
|
56
|
+
}
|
|
57
|
+
var CORNER = {
|
|
58
|
+
"top-left": "left-2.5 top-2.5",
|
|
59
|
+
"top-right": "right-2.5 top-2.5",
|
|
60
|
+
"bottom-left": "bottom-2.5 left-2.5",
|
|
61
|
+
"bottom-right": "bottom-2.5 right-2.5"
|
|
62
|
+
};
|
|
63
|
+
function CardOverlay({ corner = "top-left", className, ...props }) {
|
|
64
|
+
return /* @__PURE__ */ jsx("div", { "data-corner": corner, className: slots.overlay({ className: cn(CORNER[corner], className) }), ...props });
|
|
65
|
+
}
|
|
66
|
+
function CardBody({ padding, className, ...props }) {
|
|
67
|
+
return /* @__PURE__ */ jsx("div", { className: card({ padding }).body({ className }), ...props });
|
|
68
|
+
}
|
|
69
|
+
function CardTitle({ as: Tag = "h3", className, ...props }) {
|
|
70
|
+
return /* @__PURE__ */ jsx(Tag, { className: slots.title({ className }), ...props });
|
|
71
|
+
}
|
|
72
|
+
function CardDescription({ className, ...props }) {
|
|
73
|
+
return /* @__PURE__ */ jsx("p", { className: slots.description({ className }), ...props });
|
|
74
|
+
}
|
|
75
|
+
function CardStat({ label, className, children, ...props }) {
|
|
76
|
+
return /* @__PURE__ */ jsxs("div", { className: slots.stat({ className }), ...props, children: [
|
|
77
|
+
/* @__PURE__ */ jsx("p", { className: slots.statLabel(), children: label }),
|
|
78
|
+
/* @__PURE__ */ jsx("p", { className: slots.statValue(), children })
|
|
79
|
+
] });
|
|
80
|
+
}
|
|
81
|
+
function CardFooter({ className, ...props }) {
|
|
82
|
+
return /* @__PURE__ */ jsx("div", { className: slots.footer({ className }), ...props });
|
|
83
|
+
}
|
|
84
|
+
var Card = {
|
|
85
|
+
Root: CardRoot,
|
|
86
|
+
Media: CardMedia,
|
|
87
|
+
Image: CardImage,
|
|
88
|
+
Overlay: CardOverlay,
|
|
89
|
+
Body: CardBody,
|
|
90
|
+
Title: CardTitle,
|
|
91
|
+
Description: CardDescription,
|
|
92
|
+
Stat: CardStat,
|
|
93
|
+
Footer: CardFooter
|
|
94
|
+
};
|
|
95
|
+
export {
|
|
96
|
+
Card,
|
|
97
|
+
CardBody,
|
|
98
|
+
CardDescription,
|
|
99
|
+
CardFooter,
|
|
100
|
+
CardImage,
|
|
101
|
+
CardMedia,
|
|
102
|
+
CardOverlay,
|
|
103
|
+
CardRoot,
|
|
104
|
+
CardStat,
|
|
105
|
+
CardTitle,
|
|
106
|
+
card
|
|
107
|
+
};
|
|
108
|
+
//# sourceMappingURL=card.js.map
|