@krizaka/ui 1.3.0 → 2.0.0-beta.1
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 +137 -4
- package/dist/alert.d.ts +95 -0
- package/dist/alert.js +38 -0
- package/dist/alert.js.map +1 -0
- package/dist/avatar.d.ts +98 -0
- package/dist/avatar.js +48 -0
- package/dist/avatar.js.map +1 -0
- package/dist/badge.d.ts +64 -0
- package/dist/badge.js +31 -0
- package/dist/badge.js.map +1 -0
- package/dist/button.d.ts +76 -0
- package/dist/button.js +46 -0
- package/dist/button.js.map +1 -0
- package/dist/card.d.ts +227 -0
- package/dist/card.js +108 -0
- package/dist/card.js.map +1 -0
- package/dist/chunk-CPMZS4XA.js +11 -0
- package/dist/chunk-CPMZS4XA.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/chunk-RLOXWF2G.js +13 -0
- package/dist/chunk-RLOXWF2G.js.map +1 -0
- package/dist/cn.d.ts +10 -0
- package/dist/cn.js +7 -0
- package/dist/cn.js.map +1 -0
- package/dist/countdown.d.ts +46 -0
- package/dist/countdown.js +74 -0
- package/dist/countdown.js.map +1 -0
- package/dist/dialog.d.ts +155 -0
- package/dist/dialog.js +157 -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/empty-state.d.ts +63 -0
- package/dist/empty-state.js +26 -0
- package/dist/empty-state.js.map +1 -0
- package/dist/field.d.ts +80 -0
- package/dist/field.js +47 -0
- package/dist/field.js.map +1 -0
- package/dist/index.d.ts +6 -6
- package/dist/kbd.d.ts +24 -0
- package/dist/kbd.js +16 -0
- package/dist/kbd.js.map +1 -0
- 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/separator.d.ts +24 -0
- package/dist/separator.js +17 -0
- package/dist/separator.js.map +1 -0
- package/dist/skeleton.d.ts +28 -0
- package/dist/skeleton.js +18 -0
- package/dist/skeleton.js.map +1 -0
- package/dist/slot.d.ts +11 -0
- package/dist/slot.js +9 -0
- package/dist/slot.js.map +1 -0
- package/dist/spinner.d.ts +31 -0
- package/dist/spinner.js +31 -0
- package/dist/spinner.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/theme.d.ts +95 -0
- package/dist/theme.js +119 -0
- package/dist/theme.js.map +1 -0
- 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 +333 -7
package/dist/button.js
ADDED
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
// src/button/button.tsx
|
|
2
|
+
import { Slot } from "radix-ui";
|
|
3
|
+
import { tv } from "tailwind-variants";
|
|
4
|
+
import { jsx } from "react/jsx-runtime";
|
|
5
|
+
var buttonVariants = tv({
|
|
6
|
+
base: "inline-flex shrink-0 select-none items-center justify-center gap-2 whitespace-nowrap font-semibold transition-all focus-visible:outline-hidden focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 focus-visible:ring-offset-surface-0 disabled:pointer-events-none disabled:opacity-40 data-loading:cursor-progress active:scale-[0.98]",
|
|
7
|
+
variants: {
|
|
8
|
+
variant: {
|
|
9
|
+
primary: "bg-accent text-on-accent shadow-sm hover:bg-accent-hover",
|
|
10
|
+
secondary: "border border-border-default bg-surface-2 text-fg hover:border-border-strong hover:bg-surface-3",
|
|
11
|
+
outline: "border border-border-default bg-transparent text-fg hover:border-accent hover:text-accent",
|
|
12
|
+
ghost: "text-fg-secondary hover:bg-surface-2 hover:text-fg",
|
|
13
|
+
// The danger token is invariant and too light for small text on a light surface (3.6:1): the label stays a
|
|
14
|
+
// text role, the border and the tint carry the danger.
|
|
15
|
+
danger: "border border-danger/50 bg-danger/10 text-fg hover:border-danger hover:bg-danger/20"
|
|
16
|
+
},
|
|
17
|
+
size: { sm: "h-8 px-3 text-xs", md: "h-10 px-4 text-sm", lg: "h-12 px-6 text-sm", icon: "h-10 w-10" },
|
|
18
|
+
shape: { rounded: "rounded-lg", pill: "rounded-full" }
|
|
19
|
+
},
|
|
20
|
+
defaultVariants: { variant: "secondary", size: "md", shape: "rounded" }
|
|
21
|
+
});
|
|
22
|
+
function Button({ asChild, loading, variant, size, shape, className, disabled, ...props }) {
|
|
23
|
+
const Comp = asChild ? Slot.Root : "button";
|
|
24
|
+
return /* @__PURE__ */ jsx(
|
|
25
|
+
Comp,
|
|
26
|
+
{
|
|
27
|
+
type: asChild ? void 0 : "button",
|
|
28
|
+
"aria-busy": loading || void 0,
|
|
29
|
+
"data-loading": loading ? "" : void 0,
|
|
30
|
+
"data-variant": variant ?? "secondary",
|
|
31
|
+
disabled: asChild ? void 0 : disabled || loading,
|
|
32
|
+
"aria-disabled": asChild && (disabled || loading) ? true : void 0,
|
|
33
|
+
className: buttonVariants({ variant, size, shape, className }),
|
|
34
|
+
...props
|
|
35
|
+
}
|
|
36
|
+
);
|
|
37
|
+
}
|
|
38
|
+
function IconButton({ label, size = "icon", ...props }) {
|
|
39
|
+
return /* @__PURE__ */ jsx(Button, { "aria-label": label, title: label, size, ...props });
|
|
40
|
+
}
|
|
41
|
+
export {
|
|
42
|
+
Button,
|
|
43
|
+
IconButton,
|
|
44
|
+
buttonVariants
|
|
45
|
+
};
|
|
46
|
+
//# sourceMappingURL=button.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/button/button.tsx"],"sourcesContent":["// Server-safe: no hook, no context. `buttonVariants` styles a <Link> or a Server Component without the component.\nimport { Slot } from \"radix-ui\";\nimport type * as React from \"react\";\nimport { tv, type VariantProps } from \"tailwind-variants\";\n\nexport const buttonVariants = tv({\n base:\n \"inline-flex shrink-0 select-none items-center justify-center gap-2 whitespace-nowrap font-semibold transition-all \" +\n \"focus-visible:outline-hidden focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 focus-visible:ring-offset-surface-0 \" +\n \"disabled:pointer-events-none disabled:opacity-40 data-loading:cursor-progress active:scale-[0.98]\",\n variants: {\n variant: {\n primary: \"bg-accent text-on-accent shadow-sm hover:bg-accent-hover\",\n secondary: \"border border-border-default bg-surface-2 text-fg hover:border-border-strong hover:bg-surface-3\",\n outline: \"border border-border-default bg-transparent text-fg hover:border-accent hover:text-accent\",\n ghost: \"text-fg-secondary hover:bg-surface-2 hover:text-fg\",\n // The danger token is invariant and too light for small text on a light surface (3.6:1): the label stays a\n // text role, the border and the tint carry the danger.\n danger: \"border border-danger/50 bg-danger/10 text-fg hover:border-danger hover:bg-danger/20\",\n },\n size: { sm: \"h-8 px-3 text-xs\", md: \"h-10 px-4 text-sm\", lg: \"h-12 px-6 text-sm\", icon: \"h-10 w-10\" },\n shape: { rounded: \"rounded-lg\", pill: \"rounded-full\" },\n },\n defaultVariants: { variant: \"secondary\", size: \"md\", shape: \"rounded\" },\n});\n\nexport type ButtonVariants = VariantProps<typeof buttonVariants>;\n\nexport type ButtonProps = React.ComponentProps<\"button\"> &\n ButtonVariants & {\n /** Renders the child (e.g. a <Link>) instead of the <button>, with props, classes and ref merged. */\n asChild?: boolean;\n /** Disables and signals the wait (aria-busy, data-loading) — the product adds a spinner if it wants one. */\n loading?: boolean;\n };\n\nexport function Button({ asChild, loading, variant, size, shape, className, disabled, ...props }: ButtonProps) {\n const Comp = asChild ? Slot.Root : \"button\";\n return (\n <Comp\n type={asChild ? undefined : \"button\"}\n aria-busy={loading || undefined}\n data-loading={loading ? \"\" : undefined}\n data-variant={variant ?? \"secondary\"}\n disabled={asChild ? undefined : disabled || loading}\n aria-disabled={asChild && (disabled || loading) ? true : undefined}\n className={buttonVariants({ variant, size, shape, className })}\n {...props}\n />\n );\n}\n\nexport type IconButtonProps = Omit<ButtonProps, \"size\"> & {\n /** The accessible name (and tooltip) of the button — required, passed translated. */\n label: string;\n size?: ButtonProps[\"size\"];\n};\n\n/** An icon-only button: `label` is required, it is its accessible name. */\nexport function IconButton({ label, size = \"icon\", ...props }: IconButtonProps) {\n return <Button aria-label={label} title={label} size={size} {...props} />;\n}\n"],"mappings":";AACA,SAAS,YAAY;AAErB,SAAS,UAA6B;AAoClC;AAlCG,IAAM,iBAAiB,GAAG;AAAA,EAC/B,MACE;AAAA,EAGF,UAAU;AAAA,IACR,SAAS;AAAA,MACP,SAAS;AAAA,MACT,WAAW;AAAA,MACX,SAAS;AAAA,MACT,OAAO;AAAA;AAAA;AAAA,MAGP,QAAQ;AAAA,IACV;AAAA,IACA,MAAM,EAAE,IAAI,oBAAoB,IAAI,qBAAqB,IAAI,qBAAqB,MAAM,YAAY;AAAA,IACpG,OAAO,EAAE,SAAS,cAAc,MAAM,eAAe;AAAA,EACvD;AAAA,EACA,iBAAiB,EAAE,SAAS,aAAa,MAAM,MAAM,OAAO,UAAU;AACxE,CAAC;AAYM,SAAS,OAAO,EAAE,SAAS,SAAS,SAAS,MAAM,OAAO,WAAW,UAAU,GAAG,MAAM,GAAgB;AAC7G,QAAM,OAAO,UAAU,KAAK,OAAO;AACnC,SACE;AAAA,IAAC;AAAA;AAAA,MACC,MAAM,UAAU,SAAY;AAAA,MAC5B,aAAW,WAAW;AAAA,MACtB,gBAAc,UAAU,KAAK;AAAA,MAC7B,gBAAc,WAAW;AAAA,MACzB,UAAU,UAAU,SAAY,YAAY;AAAA,MAC5C,iBAAe,YAAY,YAAY,WAAW,OAAO;AAAA,MACzD,WAAW,eAAe,EAAE,SAAS,MAAM,OAAO,UAAU,CAAC;AAAA,MAC5D,GAAG;AAAA;AAAA,EACN;AAEJ;AASO,SAAS,WAAW,EAAE,OAAO,OAAO,QAAQ,GAAG,MAAM,GAAoB;AAC9E,SAAO,oBAAC,UAAO,cAAY,OAAO,OAAO,OAAO,MAAa,GAAG,OAAO;AACzE;","names":[]}
|
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-CPMZS4XA.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
|
package/dist/card.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/card/card.tsx"],"sourcesContent":["// Server-safe: no hook, no context. One `tv` definition with slots: each part takes its slot, and a product overrides\n// any part through `className` (merged last by tailwind-merge).\nimport { Slot } from \"radix-ui\";\nimport type * as React from \"react\";\nimport { tv, type VariantProps } from \"tailwind-variants\";\n\nimport { cn } from \"../cn\";\n\nexport const card = tv({\n slots: {\n root:\n \"group relative flex flex-col overflow-hidden border border-border-default bg-surface-1 text-fg transition-colors \" +\n \"focus-visible:outline-hidden focus-visible:ring-2 focus-visible:ring-ring\",\n media: \"relative overflow-hidden bg-media\",\n image: \"h-full w-full object-cover transition-transform duration-500 motion-safe:group-hover:scale-105\",\n 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\",\n overlay: \"absolute z-10 flex items-center gap-1.5\",\n body: \"relative flex flex-1 flex-col gap-3\",\n title: \"line-clamp-1 text-sm font-semibold text-fg transition-colors group-hover:text-accent\",\n description: \"line-clamp-2 text-xs text-fg-secondary\",\n stat: \"min-w-0\",\n statLabel: \"text-[10px] font-semibold uppercase tracking-wider text-fg-secondary\",\n statValue: \"font-display text-xl font-black tabular-nums text-fg\",\n footer: \"relative mt-auto flex items-center gap-2 border-t border-border-subtle pt-3 text-xs text-fg-secondary\",\n },\n variants: {\n radius: { md: { root: \"rounded-md\" }, lg: { root: \"rounded-lg\" }, xl: { root: \"rounded-xl\" } },\n tone: { default: {}, elevated: { root: \"bg-surface-2 shadow-md\" }, glass: { root: \"bg-surface-1/70 backdrop-blur-md\" } },\n interactive: { true: { root: \"kz-spotlight kz-lift hover:border-accent/50\" } },\n padding: { none: { body: \"p-0\" }, sm: { body: \"p-3\" }, md: { body: \"p-4\" }, lg: { body: \"p-6\" } },\n },\n defaultVariants: { radius: \"xl\", tone: \"default\", padding: \"md\" },\n});\n\ntype CardVariants = VariantProps<typeof card>;\n/** The parts without a variant read the default slots: no context, so server-safe. */\nconst slots = card();\n\nexport type CardRootProps = React.ComponentProps<\"div\"> &\n Pick<CardVariants, \"radius\" | \"tone\" | \"interactive\"> & {\n /** Renders the child (a link, an article) instead of the <div>, with props, classes and ref merged. */\n asChild?: boolean;\n /** Enters on scroll (MotionObserver): the index in the grid becomes the delay (50 ms a step, 8 steps at most). */\n reveal?: number;\n };\n\nexport function CardRoot({ asChild, reveal, radius, tone, interactive, className, style, ...props }: CardRootProps) {\n const Comp = asChild ? Slot.Root : \"div\";\n const revealStyle =\n reveal === undefined ? style : ({ ...style, \"--kz-delay\": `${Math.min(Math.max(reveal, 0), 8) * 50}ms` } as React.CSSProperties);\n return (\n <Comp\n data-reveal={reveal === undefined ? undefined : \"\"}\n data-interactive={interactive ? \"\" : undefined}\n style={revealStyle}\n className={card({ radius, tone, interactive }).root({ className })}\n {...props}\n />\n );\n}\n\nconst ASPECT = { video: \"aspect-video\", square: \"aspect-square\", portrait: \"aspect-[3/4]\", auto: \"\" } as const;\nexport type CardMediaProps = React.ComponentProps<\"div\"> & { aspect?: keyof typeof ASPECT };\n\nexport function CardMedia({ aspect = \"video\", className, ...props }: CardMediaProps) {\n return <div data-aspect={aspect} className={slots.media({ className: cn(ASPECT[aspect], className) })} {...props} />;\n}\n\nexport type CardImageProps = Omit<React.ComponentProps<\"img\">, \"src\"> & {\n src?: string | null;\n /** Shown when there is no image: an icon, an illustration (decorative). */\n fallback?: React.ReactNode;\n};\n\n/** The image of a media, or its `fallback` when there is none. `alt` is empty by default: the title names the card. */\nexport function CardImage({ src, alt = \"\", fallback, className, ...props }: CardImageProps) {\n if (!src) {\n return (\n <div data-fallback=\"\" aria-hidden className={slots.fallback({ className })}>\n {fallback}\n </div>\n );\n }\n return <img src={src} alt={alt} loading=\"lazy\" decoding=\"async\" className={slots.image({ className })} {...props} />;\n}\n\nconst CORNER = {\n \"top-left\": \"left-2.5 top-2.5\",\n \"top-right\": \"right-2.5 top-2.5\",\n \"bottom-left\": \"bottom-2.5 left-2.5\",\n \"bottom-right\": \"bottom-2.5 right-2.5\",\n} as const;\nexport type CardOverlayProps = React.ComponentProps<\"div\"> & { corner?: keyof typeof CORNER };\n\n/** What sits on the media (badges, a caption). `scrim` and `fg-on-media` are invariant: nothing to do for light. */\nexport function CardOverlay({ corner = \"top-left\", className, ...props }: CardOverlayProps) {\n return <div data-corner={corner} className={slots.overlay({ className: cn(CORNER[corner], className) })} {...props} />;\n}\n\nexport type CardBodyProps = React.ComponentProps<\"div\"> & Pick<CardVariants, \"padding\">;\n\nexport function CardBody({ padding, className, ...props }: CardBodyProps) {\n return <div className={card({ padding }).body({ className })} {...props} />;\n}\n\nexport type CardTitleProps = React.ComponentProps<\"h3\"> & { as?: \"h2\" | \"h3\" | \"h4\" };\n\nexport function CardTitle({ as: Tag = \"h3\", className, ...props }: CardTitleProps) {\n return <Tag className={slots.title({ className })} {...props} />;\n}\n\nexport function CardDescription({ className, ...props }: React.ComponentProps<\"p\">) {\n return <p className={slots.description({ className })} {...props} />;\n}\n\nexport type CardStatProps = React.ComponentProps<\"div\"> & { label: React.ReactNode };\n\n/** A figure put forward: the label in capitals, the value in tabular digits. */\nexport function CardStat({ label, className, children, ...props }: CardStatProps) {\n return (\n <div className={slots.stat({ className })} {...props}>\n <p className={slots.statLabel()}>{label}</p>\n <p className={slots.statValue()}>{children}</p>\n </div>\n );\n}\n\nexport function CardFooter({ className, ...props }: React.ComponentProps<\"div\">) {\n return <div className={slots.footer({ className })} {...props} />;\n}\n\n/** `Card.Root/Media/Image/Overlay/Body/Title/Description/Stat/Footer`. */\nexport const Card = {\n Root: CardRoot,\n Media: CardMedia,\n Image: CardImage,\n Overlay: CardOverlay,\n Body: CardBody,\n Title: CardTitle,\n Description: CardDescription,\n Stat: CardStat,\n Footer: CardFooter,\n};\n"],"mappings":"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","names":[]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/cn.ts"],"sourcesContent":["import { type ClassValue, clsx } from \"clsx\";\nimport { cn as merge } from \"tailwind-variants\";\n\nexport type { ClassValue };\n\n/**\n * Merges Tailwind classes: the last one wins — a product's `className` overrides the primitive's. The merge engine is\n * tailwind-merge as tailwind-variants ships it (the one `tv` uses), so the platform carries a single copy of it.\n */\nexport function cn(...inputs: ClassValue[]): string {\n return merge(clsx(inputs)) ?? \"\";\n}\n"],"mappings":";AAAA,SAA0B,YAAY;AACtC,SAAS,MAAM,aAAa;AAQrB,SAAS,MAAM,QAA8B;AAClD,SAAO,MAAM,KAAK,MAAM,CAAC,KAAK;AAChC;","names":[]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/floating.ts"],"sourcesContent":["// The one surface of everything that floats next to its trigger (popover, menu, tooltip): a raised surface, a border,\n// the large shadow and the `kz-pop` entrance from the side Radix measured (`--radix-*-transform-origin`).\nexport const floating =\n \"kz-pop z-50 rounded-lg border border-border-default bg-surface-2 text-fg shadow-lg outline-hidden\";\n"],"mappings":";;;AAEO,IAAM,WACX;","names":[]}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
// src/button/button.tsx
|
|
4
|
+
import { Slot } from "radix-ui";
|
|
5
|
+
import { tv } from "tailwind-variants";
|
|
6
|
+
import { jsx } from "react/jsx-runtime";
|
|
7
|
+
var buttonVariants = tv({
|
|
8
|
+
base: "inline-flex shrink-0 select-none items-center justify-center gap-2 whitespace-nowrap font-semibold transition-all focus-visible:outline-hidden focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 focus-visible:ring-offset-surface-0 disabled:pointer-events-none disabled:opacity-40 data-loading:cursor-progress active:scale-[0.98]",
|
|
9
|
+
variants: {
|
|
10
|
+
variant: {
|
|
11
|
+
primary: "bg-accent text-on-accent shadow-sm hover:bg-accent-hover",
|
|
12
|
+
secondary: "border border-border-default bg-surface-2 text-fg hover:border-border-strong hover:bg-surface-3",
|
|
13
|
+
outline: "border border-border-default bg-transparent text-fg hover:border-accent hover:text-accent",
|
|
14
|
+
ghost: "text-fg-secondary hover:bg-surface-2 hover:text-fg",
|
|
15
|
+
// The danger token is invariant and too light for small text on a light surface (3.6:1): the label stays a
|
|
16
|
+
// text role, the border and the tint carry the danger.
|
|
17
|
+
danger: "border border-danger/50 bg-danger/10 text-fg hover:border-danger hover:bg-danger/20"
|
|
18
|
+
},
|
|
19
|
+
size: { sm: "h-8 px-3 text-xs", md: "h-10 px-4 text-sm", lg: "h-12 px-6 text-sm", icon: "h-10 w-10" },
|
|
20
|
+
shape: { rounded: "rounded-lg", pill: "rounded-full" }
|
|
21
|
+
},
|
|
22
|
+
defaultVariants: { variant: "secondary", size: "md", shape: "rounded" }
|
|
23
|
+
});
|
|
24
|
+
function Button({ asChild, loading, variant, size, shape, className, disabled, ...props }) {
|
|
25
|
+
const Comp = asChild ? Slot.Root : "button";
|
|
26
|
+
return /* @__PURE__ */ jsx(
|
|
27
|
+
Comp,
|
|
28
|
+
{
|
|
29
|
+
type: asChild ? void 0 : "button",
|
|
30
|
+
"aria-busy": loading || void 0,
|
|
31
|
+
"data-loading": loading ? "" : void 0,
|
|
32
|
+
"data-variant": variant ?? "secondary",
|
|
33
|
+
disabled: asChild ? void 0 : disabled || loading,
|
|
34
|
+
"aria-disabled": asChild && (disabled || loading) ? true : void 0,
|
|
35
|
+
className: buttonVariants({ variant, size, shape, className }),
|
|
36
|
+
...props
|
|
37
|
+
}
|
|
38
|
+
);
|
|
39
|
+
}
|
|
40
|
+
function IconButton({ label, size = "icon", ...props }) {
|
|
41
|
+
return /* @__PURE__ */ jsx(Button, { "aria-label": label, title: label, size, ...props });
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
export {
|
|
45
|
+
buttonVariants,
|
|
46
|
+
Button,
|
|
47
|
+
IconButton
|
|
48
|
+
};
|
|
49
|
+
//# sourceMappingURL=chunk-QRG5RYEI.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/button/button.tsx"],"sourcesContent":["// Server-safe: no hook, no context. `buttonVariants` styles a <Link> or a Server Component without the component.\nimport { Slot } from \"radix-ui\";\nimport type * as React from \"react\";\nimport { tv, type VariantProps } from \"tailwind-variants\";\n\nexport const buttonVariants = tv({\n base:\n \"inline-flex shrink-0 select-none items-center justify-center gap-2 whitespace-nowrap font-semibold transition-all \" +\n \"focus-visible:outline-hidden focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 focus-visible:ring-offset-surface-0 \" +\n \"disabled:pointer-events-none disabled:opacity-40 data-loading:cursor-progress active:scale-[0.98]\",\n variants: {\n variant: {\n primary: \"bg-accent text-on-accent shadow-sm hover:bg-accent-hover\",\n secondary: \"border border-border-default bg-surface-2 text-fg hover:border-border-strong hover:bg-surface-3\",\n outline: \"border border-border-default bg-transparent text-fg hover:border-accent hover:text-accent\",\n ghost: \"text-fg-secondary hover:bg-surface-2 hover:text-fg\",\n // The danger token is invariant and too light for small text on a light surface (3.6:1): the label stays a\n // text role, the border and the tint carry the danger.\n danger: \"border border-danger/50 bg-danger/10 text-fg hover:border-danger hover:bg-danger/20\",\n },\n size: { sm: \"h-8 px-3 text-xs\", md: \"h-10 px-4 text-sm\", lg: \"h-12 px-6 text-sm\", icon: \"h-10 w-10\" },\n shape: { rounded: \"rounded-lg\", pill: \"rounded-full\" },\n },\n defaultVariants: { variant: \"secondary\", size: \"md\", shape: \"rounded\" },\n});\n\nexport type ButtonVariants = VariantProps<typeof buttonVariants>;\n\nexport type ButtonProps = React.ComponentProps<\"button\"> &\n ButtonVariants & {\n /** Renders the child (e.g. a <Link>) instead of the <button>, with props, classes and ref merged. */\n asChild?: boolean;\n /** Disables and signals the wait (aria-busy, data-loading) — the product adds a spinner if it wants one. */\n loading?: boolean;\n };\n\nexport function Button({ asChild, loading, variant, size, shape, className, disabled, ...props }: ButtonProps) {\n const Comp = asChild ? Slot.Root : \"button\";\n return (\n <Comp\n type={asChild ? undefined : \"button\"}\n aria-busy={loading || undefined}\n data-loading={loading ? \"\" : undefined}\n data-variant={variant ?? \"secondary\"}\n disabled={asChild ? undefined : disabled || loading}\n aria-disabled={asChild && (disabled || loading) ? true : undefined}\n className={buttonVariants({ variant, size, shape, className })}\n {...props}\n />\n );\n}\n\nexport type IconButtonProps = Omit<ButtonProps, \"size\"> & {\n /** The accessible name (and tooltip) of the button — required, passed translated. */\n label: string;\n size?: ButtonProps[\"size\"];\n};\n\n/** An icon-only button: `label` is required, it is its accessible name. */\nexport function IconButton({ label, size = \"icon\", ...props }: IconButtonProps) {\n return <Button aria-label={label} title={label} size={size} {...props} />;\n}\n"],"mappings":";;;AACA,SAAS,YAAY;AAErB,SAAS,UAA6B;AAoClC;AAlCG,IAAM,iBAAiB,GAAG;AAAA,EAC/B,MACE;AAAA,EAGF,UAAU;AAAA,IACR,SAAS;AAAA,MACP,SAAS;AAAA,MACT,WAAW;AAAA,MACX,SAAS;AAAA,MACT,OAAO;AAAA;AAAA;AAAA,MAGP,QAAQ;AAAA,IACV;AAAA,IACA,MAAM,EAAE,IAAI,oBAAoB,IAAI,qBAAqB,IAAI,qBAAqB,MAAM,YAAY;AAAA,IACpG,OAAO,EAAE,SAAS,cAAc,MAAM,eAAe;AAAA,EACvD;AAAA,EACA,iBAAiB,EAAE,SAAS,aAAa,MAAM,MAAM,OAAO,UAAU;AACxE,CAAC;AAYM,SAAS,OAAO,EAAE,SAAS,SAAS,SAAS,MAAM,OAAO,WAAW,UAAU,GAAG,MAAM,GAAgB;AAC7G,QAAM,OAAO,UAAU,KAAK,OAAO;AACnC,SACE;AAAA,IAAC;AAAA;AAAA,MACC,MAAM,UAAU,SAAY;AAAA,MAC5B,aAAW,WAAW;AAAA,MACtB,gBAAc,UAAU,KAAK;AAAA,MAC7B,gBAAc,WAAW;AAAA,MACzB,UAAU,UAAU,SAAY,YAAY;AAAA,MAC5C,iBAAe,YAAY,YAAY,WAAW,OAAO;AAAA,MACzD,WAAW,eAAe,EAAE,SAAS,MAAM,OAAO,UAAU,CAAC;AAAA,MAC5D,GAAG;AAAA;AAAA,EACN;AAEJ;AASO,SAAS,WAAW,EAAE,OAAO,OAAO,QAAQ,GAAG,MAAM,GAAoB;AAC9E,SAAO,oBAAC,UAAO,cAAY,OAAO,OAAO,OAAO,MAAa,GAAG,OAAO;AACzE;","names":[]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/cn.ts"],"sourcesContent":["import { type ClassValue, clsx } from \"clsx\";\nimport { cn as merge } from \"tailwind-variants\";\n\nexport type { ClassValue };\n\n/**\n * Merges Tailwind classes: the last one wins — a product's `className` overrides the primitive's. The merge engine is\n * tailwind-merge as tailwind-variants ships it (the one `tv` uses), so the platform carries a single copy of it.\n */\nexport function cn(...inputs: ClassValue[]): string {\n return merge(clsx(inputs)) ?? \"\";\n}\n"],"mappings":";;;AAAA,SAA0B,YAAY;AACtC,SAAS,MAAM,aAAa;AAQrB,SAAS,MAAM,QAA8B;AAClD,SAAO,MAAM,KAAK,MAAM,CAAC,KAAK;AAChC;","names":[]}
|
package/dist/cn.d.ts
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { ClassValue } from 'clsx';
|
|
2
|
+
export { ClassValue } from 'clsx';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Merges Tailwind classes: the last one wins — a product's `className` overrides the primitive's. The merge engine is
|
|
6
|
+
* tailwind-merge as tailwind-variants ships it (the one `tv` uses), so the platform carries a single copy of it.
|
|
7
|
+
*/
|
|
8
|
+
declare function cn(...inputs: ClassValue[]): string;
|
|
9
|
+
|
|
10
|
+
export { cn };
|
package/dist/cn.js
ADDED
package/dist/cn.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
|
|
3
|
+
/** Milliseconds left until `target` (never negative), ticking every second. `skewMs` = server clock − this clock. */
|
|
4
|
+
declare function useCountdown(target: Date | string | number, skewMs?: number): number;
|
|
5
|
+
/** Splits a duration into days, hours, minutes and seconds. */
|
|
6
|
+
declare function splitDuration(ms: number): {
|
|
7
|
+
d: number;
|
|
8
|
+
h: number;
|
|
9
|
+
m: number;
|
|
10
|
+
s: number;
|
|
11
|
+
};
|
|
12
|
+
/** The short unit labels, passed translated (e.g. `{ d: "d", h: "h", m: "m", s: "s" }`). */
|
|
13
|
+
type CountdownUnits = {
|
|
14
|
+
d: string;
|
|
15
|
+
h: string;
|
|
16
|
+
m: string;
|
|
17
|
+
s: string;
|
|
18
|
+
};
|
|
19
|
+
/** The three segments shown: days, hours, minutes when there are days; else hours, minutes, seconds. */
|
|
20
|
+
declare function countdownParts(ms: number, units: CountdownUnits): [number, string][];
|
|
21
|
+
|
|
22
|
+
type CountdownProps = {
|
|
23
|
+
target: Date | string | number;
|
|
24
|
+
/** Server clock − this clock, in milliseconds. */
|
|
25
|
+
skewMs?: number;
|
|
26
|
+
/** The short unit labels, passed translated. */
|
|
27
|
+
units: CountdownUnits;
|
|
28
|
+
/** Below this many milliseconds it turns urgent (`text-danger`, the last segment pulses). Default 60 s. */
|
|
29
|
+
urgentBelowMs?: number;
|
|
30
|
+
size?: "sm" | "md" | "lg";
|
|
31
|
+
/** Accessible name, e.g. "Ends in". */
|
|
32
|
+
label: string;
|
|
33
|
+
className?: string;
|
|
34
|
+
};
|
|
35
|
+
/**
|
|
36
|
+
* Time left until a moment, as segments (2d 04h 13m 09s — days only when there are some) in tabular figures. Under
|
|
37
|
+
* `urgentBelowMs` it turns to the danger role and its last segment pulses (no motion under prefers-reduced-motion).
|
|
38
|
+
* Words come from the app: `units` are the short unit labels. `role="timer"` without live announcements — the app
|
|
39
|
+
* announces what matters. State: `data-urgent`, `data-ended`.
|
|
40
|
+
*
|
|
41
|
+
* The danger role is large-text safe (≥ 3:1) from `size="md"`; at `size="sm"` an urgent countdown in light mode is
|
|
42
|
+
* under the 4.5:1 of small text.
|
|
43
|
+
*/
|
|
44
|
+
declare function Countdown({ target, skewMs, units, urgentBelowMs, size, label, className }: CountdownProps): React.JSX.Element;
|
|
45
|
+
|
|
46
|
+
export { Countdown, type CountdownProps, type CountdownUnits, countdownParts, splitDuration, useCountdown };
|