@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.
Files changed (77) hide show
  1. package/README.md +137 -4
  2. package/dist/alert.d.ts +95 -0
  3. package/dist/alert.js +38 -0
  4. package/dist/alert.js.map +1 -0
  5. package/dist/avatar.d.ts +98 -0
  6. package/dist/avatar.js +48 -0
  7. package/dist/avatar.js.map +1 -0
  8. package/dist/badge.d.ts +64 -0
  9. package/dist/badge.js +31 -0
  10. package/dist/badge.js.map +1 -0
  11. package/dist/button.d.ts +76 -0
  12. package/dist/button.js +46 -0
  13. package/dist/button.js.map +1 -0
  14. package/dist/card.d.ts +227 -0
  15. package/dist/card.js +108 -0
  16. package/dist/card.js.map +1 -0
  17. package/dist/chunk-CPMZS4XA.js +11 -0
  18. package/dist/chunk-CPMZS4XA.js.map +1 -0
  19. package/dist/chunk-J3NC6ER4.js +9 -0
  20. package/dist/chunk-J3NC6ER4.js.map +1 -0
  21. package/dist/chunk-QRG5RYEI.js +49 -0
  22. package/dist/chunk-QRG5RYEI.js.map +1 -0
  23. package/dist/chunk-RLOXWF2G.js +13 -0
  24. package/dist/chunk-RLOXWF2G.js.map +1 -0
  25. package/dist/cn.d.ts +10 -0
  26. package/dist/cn.js +7 -0
  27. package/dist/cn.js.map +1 -0
  28. package/dist/countdown.d.ts +46 -0
  29. package/dist/countdown.js +74 -0
  30. package/dist/countdown.js.map +1 -0
  31. package/dist/dialog.d.ts +155 -0
  32. package/dist/dialog.js +157 -0
  33. package/dist/dialog.js.map +1 -0
  34. package/dist/dropdown-menu.d.ts +71 -0
  35. package/dist/dropdown-menu.js +66 -0
  36. package/dist/dropdown-menu.js.map +1 -0
  37. package/dist/empty-state.d.ts +63 -0
  38. package/dist/empty-state.js +26 -0
  39. package/dist/empty-state.js.map +1 -0
  40. package/dist/field.d.ts +80 -0
  41. package/dist/field.js +47 -0
  42. package/dist/field.js.map +1 -0
  43. package/dist/index.d.ts +6 -6
  44. package/dist/kbd.d.ts +24 -0
  45. package/dist/kbd.js +16 -0
  46. package/dist/kbd.js.map +1 -0
  47. package/dist/page-header.d.ts +77 -0
  48. package/dist/page-header.js +32 -0
  49. package/dist/page-header.js.map +1 -0
  50. package/dist/popover.d.ts +18 -0
  51. package/dist/popover.js +34 -0
  52. package/dist/popover.js.map +1 -0
  53. package/dist/separator.d.ts +24 -0
  54. package/dist/separator.js +17 -0
  55. package/dist/separator.js.map +1 -0
  56. package/dist/skeleton.d.ts +28 -0
  57. package/dist/skeleton.js +18 -0
  58. package/dist/skeleton.js.map +1 -0
  59. package/dist/slot.d.ts +11 -0
  60. package/dist/slot.js +9 -0
  61. package/dist/slot.js.map +1 -0
  62. package/dist/spinner.d.ts +31 -0
  63. package/dist/spinner.js +31 -0
  64. package/dist/spinner.js.map +1 -0
  65. package/dist/stat.d.ts +75 -0
  66. package/dist/stat.js +42 -0
  67. package/dist/stat.js.map +1 -0
  68. package/dist/theme.d.ts +95 -0
  69. package/dist/theme.js +119 -0
  70. package/dist/theme.js.map +1 -0
  71. package/dist/toast.d.ts +32 -0
  72. package/dist/toast.js +49 -0
  73. package/dist/toast.js.map +1 -0
  74. package/dist/tooltip.d.ts +21 -0
  75. package/dist/tooltip.js +44 -0
  76. package/dist/tooltip.js.map +1 -0
  77. package/package.json +333 -7
@@ -0,0 +1,74 @@
1
+ "use client";
2
+
3
+ // src/countdown/core.ts
4
+ import { useSyncExternalStore } from "react";
5
+ var listeners = /* @__PURE__ */ new Set();
6
+ var timer = null;
7
+ function subscribe(listener) {
8
+ listeners.add(listener);
9
+ timer ??= setInterval(() => listeners.forEach((l) => l()), 1e3);
10
+ return () => {
11
+ listeners.delete(listener);
12
+ if (listeners.size === 0 && timer) {
13
+ clearInterval(timer);
14
+ timer = null;
15
+ }
16
+ };
17
+ }
18
+ var nowSecond = () => Math.floor(Date.now() / 1e3) * 1e3;
19
+ function useCountdown(target, skewMs = 0) {
20
+ const now = useSyncExternalStore(subscribe, nowSecond, nowSecond);
21
+ return Math.max(0, new Date(target).getTime() - (now + skewMs));
22
+ }
23
+ function splitDuration(ms) {
24
+ const total = Math.max(0, Math.floor(ms / 1e3));
25
+ return { d: Math.floor(total / 86400), h: Math.floor(total % 86400 / 3600), m: Math.floor(total % 3600 / 60), s: total % 60 };
26
+ }
27
+ function countdownParts(ms, units) {
28
+ const { d, h, m, s } = splitDuration(ms);
29
+ return d > 0 ? [[d, units.d], [h, units.h], [m, units.m]] : [[h, units.h], [m, units.m], [s, units.s]];
30
+ }
31
+
32
+ // src/countdown/countdown.tsx
33
+ import { tv } from "tailwind-variants";
34
+ import { jsx, jsxs } from "react/jsx-runtime";
35
+ var countdown = tv({
36
+ slots: {
37
+ root: "inline-flex items-baseline gap-1.5 font-display font-black tabular-nums tracking-tight text-fg",
38
+ segment: "inline-flex items-baseline",
39
+ unit: "ml-0.5 text-[0.5em] font-bold uppercase text-fg-secondary"
40
+ },
41
+ variants: {
42
+ size: { sm: { root: "text-sm" }, md: { root: "text-xl" }, lg: { root: "text-3xl sm:text-4xl" } },
43
+ urgent: { true: { root: "text-danger" } }
44
+ },
45
+ defaultVariants: { size: "md" }
46
+ });
47
+ function Countdown({ target, skewMs = 0, units, urgentBelowMs = 6e4, size = "md", label, className }) {
48
+ const ms = useCountdown(target, skewMs);
49
+ const urgent = ms > 0 && ms < urgentBelowMs;
50
+ const parts = countdownParts(ms, units);
51
+ const s = countdown({ size, urgent });
52
+ return /* @__PURE__ */ jsx(
53
+ "span",
54
+ {
55
+ role: "timer",
56
+ "aria-label": label,
57
+ "data-urgent": urgent ? "" : void 0,
58
+ "data-ended": ms === 0 ? "" : void 0,
59
+ suppressHydrationWarning: true,
60
+ className: s.root({ className }),
61
+ children: parts.map(([value, unit], i) => /* @__PURE__ */ jsxs("span", { className: s.segment({ className: urgent && i === parts.length - 1 ? "motion-safe:animate-pulse" : void 0 }), children: [
62
+ String(value).padStart(2, "0"),
63
+ /* @__PURE__ */ jsx("span", { className: s.unit(), children: unit })
64
+ ] }, unit))
65
+ }
66
+ );
67
+ }
68
+ export {
69
+ Countdown,
70
+ countdownParts,
71
+ splitDuration,
72
+ useCountdown
73
+ };
74
+ //# sourceMappingURL=countdown.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/countdown/core.ts","../src/countdown/countdown.tsx"],"sourcesContent":["// The countdown's clock, shared by the web (`@krizaka/ui/countdown`) and native renders: no DOM import.\nimport { useSyncExternalStore } from \"react\";\n\n// One clock for every countdown on the page: it ticks each second while someone listens.\nconst listeners = new Set<() => void>();\nlet timer: ReturnType<typeof setInterval> | null = null;\n\nfunction subscribe(listener: () => void) {\n listeners.add(listener);\n timer ??= setInterval(() => listeners.forEach((l) => l()), 1000);\n return () => {\n listeners.delete(listener);\n if (listeners.size === 0 && timer) {\n clearInterval(timer);\n timer = null;\n }\n };\n}\n\nconst nowSecond = () => Math.floor(Date.now() / 1000) * 1000;\n\n/** Milliseconds left until `target` (never negative), ticking every second. `skewMs` = server clock − this clock. */\nexport function useCountdown(target: Date | string | number, skewMs = 0): number {\n const now = useSyncExternalStore(subscribe, nowSecond, nowSecond);\n return Math.max(0, new Date(target).getTime() - (now + skewMs));\n}\n\n/** Splits a duration into days, hours, minutes and seconds. */\nexport function splitDuration(ms: number): { d: number; h: number; m: number; s: number } {\n const total = Math.max(0, Math.floor(ms / 1000));\n return { d: Math.floor(total / 86400), h: Math.floor((total % 86400) / 3600), m: Math.floor((total % 3600) / 60), s: total % 60 };\n}\n\n/** The short unit labels, passed translated (e.g. `{ d: \"d\", h: \"h\", m: \"m\", s: \"s\" }`). */\nexport type CountdownUnits = { d: string; h: string; m: string; s: string };\n\n/** The three segments shown: days, hours, minutes when there are days; else hours, minutes, seconds. */\nexport function countdownParts(ms: number, units: CountdownUnits): [number, string][] {\n const { d, h, m, s } = splitDuration(ms);\n return d > 0 ? [[d, units.d], [h, units.h], [m, units.m]] : [[h, units.h], [m, units.m], [s, units.s]];\n}\n","// Client: the clock is a hook.\nimport { tv } from \"tailwind-variants\";\n\nimport { countdownParts, type CountdownUnits, useCountdown } from \"./core\";\n\nconst countdown = tv({\n slots: {\n root: \"inline-flex items-baseline gap-1.5 font-display font-black tabular-nums tracking-tight text-fg\",\n segment: \"inline-flex items-baseline\",\n unit: \"ml-0.5 text-[0.5em] font-bold uppercase text-fg-secondary\",\n },\n variants: {\n size: { sm: { root: \"text-sm\" }, md: { root: \"text-xl\" }, lg: { root: \"text-3xl sm:text-4xl\" } },\n urgent: { true: { root: \"text-danger\" } },\n },\n defaultVariants: { size: \"md\" },\n});\n\nexport type CountdownProps = {\n target: Date | string | number;\n /** Server clock − this clock, in milliseconds. */\n skewMs?: number;\n /** The short unit labels, passed translated. */\n units: CountdownUnits;\n /** Below this many milliseconds it turns urgent (`text-danger`, the last segment pulses). Default 60 s. */\n urgentBelowMs?: number;\n size?: \"sm\" | \"md\" | \"lg\";\n /** Accessible name, e.g. \"Ends in\". */\n label: string;\n className?: string;\n};\n\n/**\n * Time left until a moment, as segments (2d 04h 13m 09s — days only when there are some) in tabular figures. Under\n * `urgentBelowMs` it turns to the danger role and its last segment pulses (no motion under prefers-reduced-motion).\n * Words come from the app: `units` are the short unit labels. `role=\"timer\"` without live announcements — the app\n * announces what matters. State: `data-urgent`, `data-ended`.\n *\n * The danger role is large-text safe (≥ 3:1) from `size=\"md\"`; at `size=\"sm\"` an urgent countdown in light mode is\n * under the 4.5:1 of small text.\n */\nexport function Countdown({ target, skewMs = 0, units, urgentBelowMs = 60_000, size = \"md\", label, className }: CountdownProps) {\n const ms = useCountdown(target, skewMs);\n const urgent = ms > 0 && ms < urgentBelowMs;\n const parts = countdownParts(ms, units);\n const s = countdown({ size, urgent });\n return (\n <span\n role=\"timer\"\n aria-label={label}\n data-urgent={urgent ? \"\" : undefined}\n data-ended={ms === 0 ? \"\" : undefined}\n suppressHydrationWarning\n className={s.root({ className })}\n >\n {parts.map(([value, unit], i) => (\n <span key={unit} className={s.segment({ className: urgent && i === parts.length - 1 ? \"motion-safe:animate-pulse\" : undefined })}>\n {String(value).padStart(2, \"0\")}\n <span className={s.unit()}>{unit}</span>\n </span>\n ))}\n </span>\n );\n}\n"],"mappings":";;;AACA,SAAS,4BAA4B;AAGrC,IAAM,YAAY,oBAAI,IAAgB;AACtC,IAAI,QAA+C;AAEnD,SAAS,UAAU,UAAsB;AACvC,YAAU,IAAI,QAAQ;AACtB,YAAU,YAAY,MAAM,UAAU,QAAQ,CAAC,MAAM,EAAE,CAAC,GAAG,GAAI;AAC/D,SAAO,MAAM;AACX,cAAU,OAAO,QAAQ;AACzB,QAAI,UAAU,SAAS,KAAK,OAAO;AACjC,oBAAc,KAAK;AACnB,cAAQ;AAAA,IACV;AAAA,EACF;AACF;AAEA,IAAM,YAAY,MAAM,KAAK,MAAM,KAAK,IAAI,IAAI,GAAI,IAAI;AAGjD,SAAS,aAAa,QAAgC,SAAS,GAAW;AAC/E,QAAM,MAAM,qBAAqB,WAAW,WAAW,SAAS;AAChE,SAAO,KAAK,IAAI,GAAG,IAAI,KAAK,MAAM,EAAE,QAAQ,KAAK,MAAM,OAAO;AAChE;AAGO,SAAS,cAAc,IAA4D;AACxF,QAAM,QAAQ,KAAK,IAAI,GAAG,KAAK,MAAM,KAAK,GAAI,CAAC;AAC/C,SAAO,EAAE,GAAG,KAAK,MAAM,QAAQ,KAAK,GAAG,GAAG,KAAK,MAAO,QAAQ,QAAS,IAAI,GAAG,GAAG,KAAK,MAAO,QAAQ,OAAQ,EAAE,GAAG,GAAG,QAAQ,GAAG;AAClI;AAMO,SAAS,eAAe,IAAY,OAA2C;AACpF,QAAM,EAAE,GAAG,GAAG,GAAG,EAAE,IAAI,cAAc,EAAE;AACvC,SAAO,IAAI,IAAI,CAAC,CAAC,GAAG,MAAM,CAAC,GAAG,CAAC,GAAG,MAAM,CAAC,GAAG,CAAC,GAAG,MAAM,CAAC,CAAC,IAAI,CAAC,CAAC,GAAG,MAAM,CAAC,GAAG,CAAC,GAAG,MAAM,CAAC,GAAG,CAAC,GAAG,MAAM,CAAC,CAAC;AACvG;;;ACvCA,SAAS,UAAU;AAuDX,SAEE,KAFF;AAnDR,IAAM,YAAY,GAAG;AAAA,EACnB,OAAO;AAAA,IACL,MAAM;AAAA,IACN,SAAS;AAAA,IACT,MAAM;AAAA,EACR;AAAA,EACA,UAAU;AAAA,IACR,MAAM,EAAE,IAAI,EAAE,MAAM,UAAU,GAAG,IAAI,EAAE,MAAM,UAAU,GAAG,IAAI,EAAE,MAAM,uBAAuB,EAAE;AAAA,IAC/F,QAAQ,EAAE,MAAM,EAAE,MAAM,cAAc,EAAE;AAAA,EAC1C;AAAA,EACA,iBAAiB,EAAE,MAAM,KAAK;AAChC,CAAC;AAyBM,SAAS,UAAU,EAAE,QAAQ,SAAS,GAAG,OAAO,gBAAgB,KAAQ,OAAO,MAAM,OAAO,UAAU,GAAmB;AAC9H,QAAM,KAAK,aAAa,QAAQ,MAAM;AACtC,QAAM,SAAS,KAAK,KAAK,KAAK;AAC9B,QAAM,QAAQ,eAAe,IAAI,KAAK;AACtC,QAAM,IAAI,UAAU,EAAE,MAAM,OAAO,CAAC;AACpC,SACE;AAAA,IAAC;AAAA;AAAA,MACC,MAAK;AAAA,MACL,cAAY;AAAA,MACZ,eAAa,SAAS,KAAK;AAAA,MAC3B,cAAY,OAAO,IAAI,KAAK;AAAA,MAC5B,0BAAwB;AAAA,MACxB,WAAW,EAAE,KAAK,EAAE,UAAU,CAAC;AAAA,MAE9B,gBAAM,IAAI,CAAC,CAAC,OAAO,IAAI,GAAG,MACzB,qBAAC,UAAgB,WAAW,EAAE,QAAQ,EAAE,WAAW,UAAU,MAAM,MAAM,SAAS,IAAI,8BAA8B,OAAU,CAAC,GAC5H;AAAA,eAAO,KAAK,EAAE,SAAS,GAAG,GAAG;AAAA,QAC9B,oBAAC,UAAK,WAAW,EAAE,KAAK,GAAI,gBAAK;AAAA,WAFxB,IAGX,CACD;AAAA;AAAA,EACH;AAEJ;","names":[]}
@@ -0,0 +1,155 @@
1
+ import * as React from 'react';
2
+ import * as tailwind_variants from 'tailwind-variants';
3
+ import { VariantProps } from 'tailwind-variants';
4
+ import { Dialog as Dialog$1 } from 'radix-ui';
5
+
6
+ type AlertDialogProps = {
7
+ open?: boolean;
8
+ defaultOpen?: boolean;
9
+ onOpenChange?: (open: boolean) => void;
10
+ /** The element that opens the dialog (rendered as is, `asChild`): a Button, an IconButton. */
11
+ trigger?: React.ReactNode;
12
+ title: React.ReactNode;
13
+ description?: React.ReactNode;
14
+ /** More content between the description and the actions. */
15
+ children?: React.ReactNode;
16
+ confirmLabel: string;
17
+ cancelLabel: string;
18
+ /** `danger` for a destructive action (delete, leave, cancel a payment). */
19
+ tone?: "danger" | "primary";
20
+ /** Runs on confirm. A promise keeps the dialog open and the button loading until it settles. */
21
+ onConfirm: () => void | Promise<unknown>;
22
+ /** The element the portal renders into (default: document.body). */
23
+ container?: HTMLElement | null;
24
+ className?: string;
25
+ };
26
+ declare function AlertDialog({ open: openProp, defaultOpen, onOpenChange, trigger, title, description, children, confirmLabel, cancelLabel, tone, onConfirm, container, className, }: AlertDialogProps): React.JSX.Element;
27
+
28
+ declare const dialog: tailwind_variants.TVReturnType<{
29
+ placement: {
30
+ center: {
31
+ content: string;
32
+ };
33
+ bottom: {
34
+ content: string;
35
+ };
36
+ right: {
37
+ content: string;
38
+ };
39
+ };
40
+ size: {
41
+ sm: {
42
+ content: string;
43
+ };
44
+ md: {
45
+ content: string;
46
+ };
47
+ lg: {
48
+ content: string;
49
+ };
50
+ };
51
+ }, {
52
+ overlay: string;
53
+ content: string;
54
+ close: string;
55
+ header: string;
56
+ title: string;
57
+ description: string;
58
+ body: string;
59
+ footer: string;
60
+ }, undefined, {
61
+ placement: {
62
+ center: {
63
+ content: string;
64
+ };
65
+ bottom: {
66
+ content: string;
67
+ };
68
+ right: {
69
+ content: string;
70
+ };
71
+ };
72
+ size: {
73
+ sm: {
74
+ content: string;
75
+ };
76
+ md: {
77
+ content: string;
78
+ };
79
+ lg: {
80
+ content: string;
81
+ };
82
+ };
83
+ }, {
84
+ overlay: string;
85
+ content: string;
86
+ close: string;
87
+ header: string;
88
+ title: string;
89
+ description: string;
90
+ body: string;
91
+ footer: string;
92
+ }, tailwind_variants.TVReturnTypeLike<{
93
+ placement: {
94
+ center: {
95
+ content: string;
96
+ };
97
+ bottom: {
98
+ content: string;
99
+ };
100
+ right: {
101
+ content: string;
102
+ };
103
+ };
104
+ size: {
105
+ sm: {
106
+ content: string;
107
+ };
108
+ md: {
109
+ content: string;
110
+ };
111
+ lg: {
112
+ content: string;
113
+ };
114
+ };
115
+ }, {
116
+ overlay: string;
117
+ content: string;
118
+ close: string;
119
+ header: string;
120
+ title: string;
121
+ description: string;
122
+ body: string;
123
+ footer: string;
124
+ }>>;
125
+ type DialogVariants = VariantProps<typeof dialog>;
126
+ type DialogContentProps = React.ComponentProps<typeof Dialog$1.Content> & DialogVariants & {
127
+ /** The accessible name of the close button — passed translated. */
128
+ closeLabel: string;
129
+ /** The element the portal renders into (default: document.body). */
130
+ container?: HTMLElement | null;
131
+ };
132
+ /** The dialog itself, portalled over a dimmed overlay, with a close button. Give it a `Dialog.Title`. */
133
+ declare function DialogContent({ placement, size, closeLabel, container, className, children, ...props }: DialogContentProps): React.JSX.Element;
134
+ declare function DialogHeader({ className, ...props }: React.ComponentProps<"div">): React.JSX.Element;
135
+ declare function DialogTitle({ className, ...props }: React.ComponentProps<typeof Dialog$1.Title>): React.JSX.Element;
136
+ declare function DialogDescription({ className, ...props }: React.ComponentProps<typeof Dialog$1.Description>): React.JSX.Element;
137
+ declare function DialogBody({ className, ...props }: React.ComponentProps<"div">): React.JSX.Element;
138
+ declare function DialogFooter({ className, ...props }: React.ComponentProps<"div">): React.JSX.Element;
139
+ /** `Dialog.Root/Trigger/Content/Header/Title/Description/Body/Footer/Close`. `open`/`defaultOpen` + `onOpenChange`. */
140
+ declare const Dialog: {
141
+ Root: React.FC<Dialog$1.DialogProps>;
142
+ Trigger: React.ForwardRefExoticComponent<Dialog$1.DialogTriggerProps & React.RefAttributes<HTMLButtonElement>>;
143
+ Close: React.ForwardRefExoticComponent<Dialog$1.DialogCloseProps & React.RefAttributes<HTMLButtonElement>>;
144
+ Content: typeof DialogContent;
145
+ Header: typeof DialogHeader;
146
+ Title: typeof DialogTitle;
147
+ Description: typeof DialogDescription;
148
+ Body: typeof DialogBody;
149
+ Footer: typeof DialogFooter;
150
+ };
151
+ type SheetProps = Omit<DialogContentProps, "placement">;
152
+ /** A sheet is a dialog anchored at the bottom (centred from `sm` up): `Dialog.Content placement="bottom"`. */
153
+ declare function Sheet(props: SheetProps): React.JSX.Element;
154
+
155
+ export { AlertDialog, type AlertDialogProps, Dialog, DialogBody, DialogContent, type DialogContentProps, DialogDescription, DialogFooter, DialogHeader, DialogTitle, type DialogVariants, Sheet, type SheetProps, dialog };
package/dist/dialog.js ADDED
@@ -0,0 +1,157 @@
1
+ "use client";
2
+ import {
3
+ Button,
4
+ IconButton
5
+ } from "./chunk-QRG5RYEI.js";
6
+
7
+ // src/dialog/alert-dialog.tsx
8
+ import { AlertDialog as AlertDialogPrimitive } from "radix-ui";
9
+ import * as React from "react";
10
+
11
+ // src/dialog/dialog.tsx
12
+ import { Dialog as DialogPrimitive } from "radix-ui";
13
+ import { tv } from "tailwind-variants";
14
+ import { jsx, jsxs } from "react/jsx-runtime";
15
+ var dialog = tv({
16
+ slots: {
17
+ overlay: "kz-overlay fixed inset-0 z-50 bg-overlay backdrop-blur-xs",
18
+ content: "kz-dialog fixed z-50 flex flex-col overflow-hidden border border-border-default bg-surface-1 text-fg shadow-lg focus:outline-hidden",
19
+ close: "absolute right-3 top-3 h-9 w-9",
20
+ header: "flex flex-col gap-1 px-5 pb-2 pr-14 pt-5",
21
+ title: "text-base font-bold text-fg",
22
+ description: "text-sm text-fg-secondary",
23
+ body: "min-h-0 flex-1 overflow-y-auto px-5 pb-5",
24
+ footer: "flex flex-wrap items-center justify-end gap-2 border-t border-border-subtle px-5 py-4 pb-[max(1rem,env(safe-area-inset-bottom))]"
25
+ },
26
+ variants: {
27
+ placement: {
28
+ center: { content: "left-1/2 top-1/2 max-h-[85dvh] w-[calc(100%-2rem)] -translate-x-1/2 -translate-y-1/2 rounded-xl" },
29
+ /* A sheet: anchored at the bottom on a phone, centred from `sm` up. */
30
+ bottom: {
31
+ content: "inset-x-0 bottom-0 max-h-[92dvh] rounded-t-[1.75rem] sm:bottom-auto sm:left-1/2 sm:top-1/2 sm:w-full sm:-translate-x-1/2 sm:-translate-y-1/2 sm:rounded-[1.75rem]"
32
+ },
33
+ right: { content: "inset-y-0 right-0 h-full w-full max-w-md rounded-none border-y-0 border-r-0" }
34
+ },
35
+ size: { sm: { content: "sm:max-w-sm" }, md: { content: "sm:max-w-md" }, lg: { content: "sm:max-w-2xl" } }
36
+ },
37
+ defaultVariants: { placement: "center", size: "md" }
38
+ });
39
+ var s = dialog();
40
+ function CloseIcon() {
41
+ return /* @__PURE__ */ jsx("svg", { viewBox: "0 0 24 24", className: "h-4 w-4", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", "aria-hidden": true, children: /* @__PURE__ */ jsx("path", { d: "M18 6 6 18M6 6l12 12" }) });
42
+ }
43
+ function DialogContent({ placement, size, closeLabel, container, className, children, ...props }) {
44
+ const v = dialog({ placement, size });
45
+ return /* @__PURE__ */ jsxs(DialogPrimitive.Portal, { container, children: [
46
+ /* @__PURE__ */ jsx(DialogPrimitive.Overlay, { className: v.overlay() }),
47
+ /* @__PURE__ */ jsxs(DialogPrimitive.Content, { "data-placement": placement ?? "center", className: v.content({ className }), ...props, children: [
48
+ children,
49
+ /* @__PURE__ */ jsx(DialogPrimitive.Close, { asChild: true, children: /* @__PURE__ */ jsx(IconButton, { label: closeLabel, variant: "ghost", shape: "pill", className: v.close(), children: /* @__PURE__ */ jsx(CloseIcon, {}) }) })
50
+ ] })
51
+ ] });
52
+ }
53
+ function DialogHeader({ className, ...props }) {
54
+ return /* @__PURE__ */ jsx("div", { className: s.header({ className }), ...props });
55
+ }
56
+ function DialogTitle({ className, ...props }) {
57
+ return /* @__PURE__ */ jsx(DialogPrimitive.Title, { className: s.title({ className }), ...props });
58
+ }
59
+ function DialogDescription({ className, ...props }) {
60
+ return /* @__PURE__ */ jsx(DialogPrimitive.Description, { className: s.description({ className }), ...props });
61
+ }
62
+ function DialogBody({ className, ...props }) {
63
+ return /* @__PURE__ */ jsx("div", { className: s.body({ className }), ...props });
64
+ }
65
+ function DialogFooter({ className, ...props }) {
66
+ return /* @__PURE__ */ jsx("div", { className: s.footer({ className }), ...props });
67
+ }
68
+ var Dialog = {
69
+ Root: DialogPrimitive.Root,
70
+ Trigger: DialogPrimitive.Trigger,
71
+ Close: DialogPrimitive.Close,
72
+ Content: DialogContent,
73
+ Header: DialogHeader,
74
+ Title: DialogTitle,
75
+ Description: DialogDescription,
76
+ Body: DialogBody,
77
+ Footer: DialogFooter
78
+ };
79
+ function Sheet(props) {
80
+ return /* @__PURE__ */ jsx(DialogContent, { placement: "bottom", ...props });
81
+ }
82
+
83
+ // src/dialog/alert-dialog.tsx
84
+ import { jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
85
+ var s2 = dialog({ placement: "center", size: "sm" });
86
+ function AlertDialog({
87
+ open: openProp,
88
+ defaultOpen = false,
89
+ onOpenChange,
90
+ trigger,
91
+ title,
92
+ description,
93
+ children,
94
+ confirmLabel,
95
+ cancelLabel,
96
+ tone = "primary",
97
+ onConfirm,
98
+ container,
99
+ className
100
+ }) {
101
+ const [openState, setOpenState] = React.useState(defaultOpen);
102
+ const [pending, setPending] = React.useState(false);
103
+ const open = openProp ?? openState;
104
+ const setOpen = (next) => {
105
+ if (openProp === void 0) setOpenState(next);
106
+ onOpenChange?.(next);
107
+ };
108
+ const confirm = async () => {
109
+ setPending(true);
110
+ try {
111
+ await onConfirm();
112
+ setOpen(false);
113
+ } catch {
114
+ } finally {
115
+ setPending(false);
116
+ }
117
+ };
118
+ return /* @__PURE__ */ jsxs2(AlertDialogPrimitive.Root, { open, onOpenChange: (next) => pending ? void 0 : setOpen(next), children: [
119
+ trigger && /* @__PURE__ */ jsx2(AlertDialogPrimitive.Trigger, { asChild: true, children: trigger }),
120
+ /* @__PURE__ */ jsxs2(AlertDialogPrimitive.Portal, { container, children: [
121
+ /* @__PURE__ */ jsx2(AlertDialogPrimitive.Overlay, { className: s2.overlay() }),
122
+ /* @__PURE__ */ jsxs2(
123
+ AlertDialogPrimitive.Content,
124
+ {
125
+ "data-tone": tone,
126
+ "aria-busy": pending || void 0,
127
+ className: s2.content({ className }),
128
+ onEscapeKeyDown: (event) => pending && event.preventDefault(),
129
+ children: [
130
+ /* @__PURE__ */ jsxs2("div", { className: s2.header({ className: "pr-5" }), children: [
131
+ /* @__PURE__ */ jsx2(AlertDialogPrimitive.Title, { className: s2.title(), children: title }),
132
+ description && /* @__PURE__ */ jsx2(AlertDialogPrimitive.Description, { className: s2.description(), children: description })
133
+ ] }),
134
+ children && /* @__PURE__ */ jsx2("div", { className: s2.body(), children }),
135
+ /* @__PURE__ */ jsxs2("div", { className: s2.footer(), children: [
136
+ /* @__PURE__ */ jsx2(AlertDialogPrimitive.Cancel, { asChild: true, children: /* @__PURE__ */ jsx2(Button, { variant: "ghost", disabled: pending, children: cancelLabel }) }),
137
+ /* @__PURE__ */ jsx2(Button, { variant: tone === "danger" ? "danger" : "primary", loading: pending, onClick: confirm, children: confirmLabel })
138
+ ] })
139
+ ]
140
+ }
141
+ )
142
+ ] })
143
+ ] });
144
+ }
145
+ export {
146
+ AlertDialog,
147
+ Dialog,
148
+ DialogBody,
149
+ DialogContent,
150
+ DialogDescription,
151
+ DialogFooter,
152
+ DialogHeader,
153
+ DialogTitle,
154
+ Sheet,
155
+ dialog
156
+ };
157
+ //# sourceMappingURL=dialog.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/dialog/alert-dialog.tsx","../src/dialog/dialog.tsx"],"sourcesContent":["// Client. A confirmation that interrupts: Radix AlertDialog (role=\"alertdialog\", no outside click, focus on Cancel).\n// `onConfirm` may be async: the dialog stays open with the confirm button loading until it settles, closes when it\n// resolves, and stays open when it rejects (the product shows the error).\nimport { AlertDialog as AlertDialogPrimitive } from \"radix-ui\";\nimport * as React from \"react\";\n\nimport { Button } from \"../button/button\";\nimport { dialog } from \"./dialog\";\n\nconst s = dialog({ placement: \"center\", size: \"sm\" });\n\nexport type AlertDialogProps = {\n open?: boolean;\n defaultOpen?: boolean;\n onOpenChange?: (open: boolean) => void;\n /** The element that opens the dialog (rendered as is, `asChild`): a Button, an IconButton. */\n trigger?: React.ReactNode;\n title: React.ReactNode;\n description?: React.ReactNode;\n /** More content between the description and the actions. */\n children?: React.ReactNode;\n confirmLabel: string;\n cancelLabel: string;\n /** `danger` for a destructive action (delete, leave, cancel a payment). */\n tone?: \"danger\" | \"primary\";\n /** Runs on confirm. A promise keeps the dialog open and the button loading until it settles. */\n onConfirm: () => void | Promise<unknown>;\n /** The element the portal renders into (default: document.body). */\n container?: HTMLElement | null;\n className?: string;\n};\n\nexport function AlertDialog({\n open: openProp,\n defaultOpen = false,\n onOpenChange,\n trigger,\n title,\n description,\n children,\n confirmLabel,\n cancelLabel,\n tone = \"primary\",\n onConfirm,\n container,\n className,\n}: AlertDialogProps) {\n const [openState, setOpenState] = React.useState(defaultOpen);\n const [pending, setPending] = React.useState(false);\n const open = openProp ?? openState;\n\n const setOpen = (next: boolean) => {\n if (openProp === undefined) setOpenState(next);\n onOpenChange?.(next);\n };\n\n const confirm = async () => {\n setPending(true);\n try {\n await onConfirm();\n setOpen(false);\n } catch {\n // Stays open: the product reports the failure (a toast, an inline error) and the person may retry.\n } finally {\n setPending(false);\n }\n };\n\n return (\n <AlertDialogPrimitive.Root open={open} onOpenChange={(next) => (pending ? undefined : setOpen(next))}>\n {trigger && <AlertDialogPrimitive.Trigger asChild>{trigger}</AlertDialogPrimitive.Trigger>}\n <AlertDialogPrimitive.Portal container={container}>\n <AlertDialogPrimitive.Overlay className={s.overlay()} />\n <AlertDialogPrimitive.Content\n data-tone={tone}\n aria-busy={pending || undefined}\n className={s.content({ className })}\n onEscapeKeyDown={(event) => pending && event.preventDefault()}\n >\n <div className={s.header({ className: \"pr-5\" })}>\n <AlertDialogPrimitive.Title className={s.title()}>{title}</AlertDialogPrimitive.Title>\n {description && <AlertDialogPrimitive.Description className={s.description()}>{description}</AlertDialogPrimitive.Description>}\n </div>\n {children && <div className={s.body()}>{children}</div>}\n <div className={s.footer()}>\n <AlertDialogPrimitive.Cancel asChild>\n <Button variant=\"ghost\" disabled={pending}>\n {cancelLabel}\n </Button>\n </AlertDialogPrimitive.Cancel>\n <Button variant={tone === \"danger\" ? \"danger\" : \"primary\"} loading={pending} onClick={confirm}>\n {confirmLabel}\n </Button>\n </div>\n </AlertDialogPrimitive.Content>\n </AlertDialogPrimitive.Portal>\n </AlertDialogPrimitive.Root>\n );\n}\n","// Client (a portal). Radix does the focus trap, the scroll lock, Escape, the outside click, aria-modal, the\n// aria-labelledby / aria-describedby wiring and the focus return: this file only holds the shape.\nimport { Dialog as DialogPrimitive } from \"radix-ui\";\nimport type * as React from \"react\";\nimport { tv, type VariantProps } from \"tailwind-variants\";\n\nimport { IconButton } from \"../button/button\";\n\nexport const dialog = tv({\n slots: {\n overlay: \"kz-overlay fixed inset-0 z-50 bg-overlay backdrop-blur-xs\",\n content:\n \"kz-dialog fixed z-50 flex flex-col overflow-hidden border border-border-default bg-surface-1 text-fg shadow-lg focus:outline-hidden\",\n close: \"absolute right-3 top-3 h-9 w-9\",\n header: \"flex flex-col gap-1 px-5 pb-2 pr-14 pt-5\",\n title: \"text-base font-bold text-fg\",\n description: \"text-sm text-fg-secondary\",\n body: \"min-h-0 flex-1 overflow-y-auto px-5 pb-5\",\n footer:\n \"flex flex-wrap items-center justify-end gap-2 border-t border-border-subtle px-5 py-4 pb-[max(1rem,env(safe-area-inset-bottom))]\",\n },\n variants: {\n placement: {\n center: { content: \"left-1/2 top-1/2 max-h-[85dvh] w-[calc(100%-2rem)] -translate-x-1/2 -translate-y-1/2 rounded-xl\" },\n /* A sheet: anchored at the bottom on a phone, centred from `sm` up. */\n bottom: {\n content:\n \"inset-x-0 bottom-0 max-h-[92dvh] rounded-t-[1.75rem] sm:bottom-auto sm:left-1/2 sm:top-1/2 sm:w-full \" +\n \"sm:-translate-x-1/2 sm:-translate-y-1/2 sm:rounded-[1.75rem]\",\n },\n right: { content: \"inset-y-0 right-0 h-full w-full max-w-md rounded-none border-y-0 border-r-0\" },\n },\n size: { sm: { content: \"sm:max-w-sm\" }, md: { content: \"sm:max-w-md\" }, lg: { content: \"sm:max-w-2xl\" } },\n },\n defaultVariants: { placement: \"center\", size: \"md\" },\n});\nconst s = dialog();\n\nexport type DialogVariants = VariantProps<typeof dialog>;\n\nfunction CloseIcon() {\n return (\n <svg viewBox=\"0 0 24 24\" className=\"h-4 w-4\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" aria-hidden>\n <path d=\"M18 6 6 18M6 6l12 12\" />\n </svg>\n );\n}\n\nexport type DialogContentProps = React.ComponentProps<typeof DialogPrimitive.Content> &\n DialogVariants & {\n /** The accessible name of the close button — passed translated. */\n closeLabel: string;\n /** The element the portal renders into (default: document.body). */\n container?: HTMLElement | null;\n };\n\n/** The dialog itself, portalled over a dimmed overlay, with a close button. Give it a `Dialog.Title`. */\nexport function DialogContent({ placement, size, closeLabel, container, className, children, ...props }: DialogContentProps) {\n const v = dialog({ placement, size });\n return (\n <DialogPrimitive.Portal container={container}>\n <DialogPrimitive.Overlay className={v.overlay()} />\n <DialogPrimitive.Content data-placement={placement ?? \"center\"} className={v.content({ className })} {...props}>\n {children}\n <DialogPrimitive.Close asChild>\n <IconButton label={closeLabel} variant=\"ghost\" shape=\"pill\" className={v.close()}>\n <CloseIcon />\n </IconButton>\n </DialogPrimitive.Close>\n </DialogPrimitive.Content>\n </DialogPrimitive.Portal>\n );\n}\n\nexport function DialogHeader({ className, ...props }: React.ComponentProps<\"div\">) {\n return <div className={s.header({ className })} {...props} />;\n}\n\nexport function DialogTitle({ className, ...props }: React.ComponentProps<typeof DialogPrimitive.Title>) {\n return <DialogPrimitive.Title className={s.title({ className })} {...props} />;\n}\n\nexport function DialogDescription({ className, ...props }: React.ComponentProps<typeof DialogPrimitive.Description>) {\n return <DialogPrimitive.Description className={s.description({ className })} {...props} />;\n}\n\nexport function DialogBody({ className, ...props }: React.ComponentProps<\"div\">) {\n return <div className={s.body({ className })} {...props} />;\n}\n\nexport function DialogFooter({ className, ...props }: React.ComponentProps<\"div\">) {\n return <div className={s.footer({ className })} {...props} />;\n}\n\n/** `Dialog.Root/Trigger/Content/Header/Title/Description/Body/Footer/Close`. `open`/`defaultOpen` + `onOpenChange`. */\nexport const Dialog = {\n Root: DialogPrimitive.Root,\n Trigger: DialogPrimitive.Trigger,\n Close: DialogPrimitive.Close,\n Content: DialogContent,\n Header: DialogHeader,\n Title: DialogTitle,\n Description: DialogDescription,\n Body: DialogBody,\n Footer: DialogFooter,\n};\n\nexport type SheetProps = Omit<DialogContentProps, \"placement\">;\n\n/** A sheet is a dialog anchored at the bottom (centred from `sm` up): `Dialog.Content placement=\"bottom\"`. */\nexport function Sheet(props: SheetProps) {\n return <DialogContent placement=\"bottom\" {...props} />;\n}\n"],"mappings":"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","names":["jsx","jsxs","s"]}
@@ -0,0 +1,71 @@
1
+ import * as tailwind_variants from 'tailwind-variants';
2
+ import { DropdownMenu as DropdownMenu$1 } from 'radix-ui';
3
+ import * as React from 'react';
4
+
5
+ declare const menu: tailwind_variants.TVReturnType<{
6
+ tone: {
7
+ default: {};
8
+ danger: {
9
+ item: string;
10
+ };
11
+ };
12
+ }, {
13
+ content: string;
14
+ item: string;
15
+ indicator: string;
16
+ label: string;
17
+ separator: string;
18
+ }, undefined, {
19
+ tone: {
20
+ default: {};
21
+ danger: {
22
+ item: string;
23
+ };
24
+ };
25
+ }, {
26
+ content: string;
27
+ item: string;
28
+ indicator: string;
29
+ label: string;
30
+ separator: string;
31
+ }, tailwind_variants.TVReturnTypeLike<{
32
+ tone: {
33
+ default: {};
34
+ danger: {
35
+ item: string;
36
+ };
37
+ };
38
+ }, {
39
+ content: string;
40
+ item: string;
41
+ indicator: string;
42
+ label: string;
43
+ separator: string;
44
+ }>>;
45
+ type DropdownMenuContentProps = React.ComponentProps<typeof DropdownMenu$1.Content> & {
46
+ /** The element the portal renders into (default: document.body). */
47
+ container?: HTMLElement | null;
48
+ };
49
+ declare function DropdownMenuContent({ sideOffset, align, collisionPadding, container, className, ...props }: DropdownMenuContentProps): React.JSX.Element;
50
+ type DropdownMenuItemProps = React.ComponentProps<typeof DropdownMenu$1.Item> & {
51
+ tone?: "default" | "danger";
52
+ };
53
+ /** An action. `tone="danger"` for a destructive one; `onSelect` runs it (the menu closes). */
54
+ declare function DropdownMenuItem({ tone, className, ...props }: DropdownMenuItemProps): React.JSX.Element;
55
+ /** A toggled option: `checked` + `onCheckedChange`. */
56
+ declare function DropdownMenuCheckboxItem({ className, children, ...props }: React.ComponentProps<typeof DropdownMenu$1.CheckboxItem>): React.JSX.Element;
57
+ declare function DropdownMenuLabel({ className, ...props }: React.ComponentProps<typeof DropdownMenu$1.Label>): React.JSX.Element;
58
+ declare function DropdownMenuSeparator({ className, ...props }: React.ComponentProps<typeof DropdownMenu$1.Separator>): React.JSX.Element;
59
+ /** `DropdownMenu.Root/Trigger/Content/Item/CheckboxItem/Label/Separator/Group`. `open`/`defaultOpen` + `onOpenChange`. */
60
+ declare const DropdownMenu: {
61
+ Root: React.FC<DropdownMenu$1.DropdownMenuProps>;
62
+ Trigger: React.ForwardRefExoticComponent<DropdownMenu$1.DropdownMenuTriggerProps & React.RefAttributes<HTMLButtonElement>>;
63
+ Content: typeof DropdownMenuContent;
64
+ Item: typeof DropdownMenuItem;
65
+ CheckboxItem: typeof DropdownMenuCheckboxItem;
66
+ Label: typeof DropdownMenuLabel;
67
+ Separator: typeof DropdownMenuSeparator;
68
+ Group: React.ForwardRefExoticComponent<DropdownMenu$1.DropdownMenuGroupProps & React.RefAttributes<HTMLDivElement>>;
69
+ };
70
+
71
+ export { DropdownMenu, DropdownMenuCheckboxItem, DropdownMenuContent, type DropdownMenuContentProps, DropdownMenuItem, type DropdownMenuItemProps, DropdownMenuLabel, DropdownMenuSeparator, menu };
@@ -0,0 +1,66 @@
1
+ "use client";
2
+ import {
3
+ floating
4
+ } from "./chunk-J3NC6ER4.js";
5
+ import {
6
+ cn
7
+ } from "./chunk-RLOXWF2G.js";
8
+
9
+ // src/dropdown-menu/dropdown-menu.tsx
10
+ import { DropdownMenu as MenuPrimitive } from "radix-ui";
11
+ import { tv } from "tailwind-variants";
12
+ import { jsx, jsxs } from "react/jsx-runtime";
13
+ var menu = tv({
14
+ slots: {
15
+ content: cn(floating, "min-w-48 max-h-(--radix-dropdown-menu-content-available-height) overflow-y-auto p-1 origin-(--radix-dropdown-menu-content-transform-origin)"),
16
+ item: "relative flex cursor-pointer select-none items-center gap-2 rounded-md px-2.5 py-2 text-sm text-fg outline-hidden transition-colors data-highlighted:bg-surface-3 data-disabled:pointer-events-none data-disabled:opacity-40 [&>svg]:h-4 [&>svg]:w-4 [&>svg]:shrink-0 [&>svg]:text-fg-secondary",
17
+ indicator: "ml-auto flex h-4 w-4 items-center justify-center text-accent",
18
+ label: "px-2.5 pb-1 pt-2 text-[11px] font-semibold uppercase tracking-wider text-fg-secondary",
19
+ separator: "-mx-1 my-1 h-px bg-border-subtle"
20
+ },
21
+ variants: {
22
+ // The danger token is too light for small text on a light surface: the label stays a text role, the icon and the
23
+ // highlight carry the danger.
24
+ tone: { default: {}, danger: { item: "data-highlighted:bg-danger/15 [&>svg]:text-danger" } }
25
+ },
26
+ defaultVariants: { tone: "default" }
27
+ });
28
+ var s = menu();
29
+ function DropdownMenuContent({ sideOffset = 6, align = "end", collisionPadding = 8, container, className, ...props }) {
30
+ return /* @__PURE__ */ jsx(MenuPrimitive.Portal, { container, children: /* @__PURE__ */ jsx(MenuPrimitive.Content, { sideOffset, align, collisionPadding, className: s.content({ className }), ...props }) });
31
+ }
32
+ function DropdownMenuItem({ tone, className, ...props }) {
33
+ return /* @__PURE__ */ jsx(MenuPrimitive.Item, { "data-tone": tone ?? "default", className: menu({ tone }).item({ className }), ...props });
34
+ }
35
+ function DropdownMenuCheckboxItem({ className, children, ...props }) {
36
+ return /* @__PURE__ */ jsxs(MenuPrimitive.CheckboxItem, { className: s.item({ className }), ...props, children: [
37
+ children,
38
+ /* @__PURE__ */ jsx(MenuPrimitive.ItemIndicator, { className: s.indicator(), children: /* @__PURE__ */ jsx("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2.5", strokeLinecap: "round", strokeLinejoin: "round", "aria-hidden": true, children: /* @__PURE__ */ jsx("path", { d: "M20 6 9 17l-5-5" }) }) })
39
+ ] });
40
+ }
41
+ function DropdownMenuLabel({ className, ...props }) {
42
+ return /* @__PURE__ */ jsx(MenuPrimitive.Label, { className: s.label({ className }), ...props });
43
+ }
44
+ function DropdownMenuSeparator({ className, ...props }) {
45
+ return /* @__PURE__ */ jsx(MenuPrimitive.Separator, { className: s.separator({ className }), ...props });
46
+ }
47
+ var DropdownMenu = {
48
+ Root: MenuPrimitive.Root,
49
+ Trigger: MenuPrimitive.Trigger,
50
+ Content: DropdownMenuContent,
51
+ Item: DropdownMenuItem,
52
+ CheckboxItem: DropdownMenuCheckboxItem,
53
+ Label: DropdownMenuLabel,
54
+ Separator: DropdownMenuSeparator,
55
+ Group: MenuPrimitive.Group
56
+ };
57
+ export {
58
+ DropdownMenu,
59
+ DropdownMenuCheckboxItem,
60
+ DropdownMenuContent,
61
+ DropdownMenuItem,
62
+ DropdownMenuLabel,
63
+ DropdownMenuSeparator,
64
+ menu
65
+ };
66
+ //# sourceMappingURL=dropdown-menu.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/dropdown-menu/dropdown-menu.tsx"],"sourcesContent":["// Client (a portal). Radix does the roving focus, the arrows, Home/End, typeahead, Escape and the focus return.\nimport { DropdownMenu as MenuPrimitive } from \"radix-ui\";\nimport type * as React from \"react\";\nimport { tv } from \"tailwind-variants\";\n\nimport { cn } from \"../cn\";\nimport { floating } from \"../floating\";\n\nexport const menu = tv({\n slots: {\n content: cn(floating, \"min-w-48 max-h-(--radix-dropdown-menu-content-available-height) overflow-y-auto p-1 origin-(--radix-dropdown-menu-content-transform-origin)\"),\n item:\n \"relative flex cursor-pointer select-none items-center gap-2 rounded-md px-2.5 py-2 text-sm text-fg outline-hidden transition-colors \" +\n \"data-highlighted:bg-surface-3 data-disabled:pointer-events-none data-disabled:opacity-40 [&>svg]:h-4 [&>svg]:w-4 [&>svg]:shrink-0 \" +\n \"[&>svg]:text-fg-secondary\",\n indicator: \"ml-auto flex h-4 w-4 items-center justify-center text-accent\",\n label: \"px-2.5 pb-1 pt-2 text-[11px] font-semibold uppercase tracking-wider text-fg-secondary\",\n separator: \"-mx-1 my-1 h-px bg-border-subtle\",\n },\n variants: {\n // The danger token is too light for small text on a light surface: the label stays a text role, the icon and the\n // highlight carry the danger.\n tone: { default: {}, danger: { item: \"data-highlighted:bg-danger/15 [&>svg]:text-danger\" } },\n },\n defaultVariants: { tone: \"default\" },\n});\nconst s = menu();\n\nexport type DropdownMenuContentProps = React.ComponentProps<typeof MenuPrimitive.Content> & {\n /** The element the portal renders into (default: document.body). */\n container?: HTMLElement | null;\n};\n\nexport function DropdownMenuContent({ sideOffset = 6, align = \"end\", collisionPadding = 8, container, className, ...props }: DropdownMenuContentProps) {\n return (\n <MenuPrimitive.Portal container={container}>\n <MenuPrimitive.Content sideOffset={sideOffset} align={align} collisionPadding={collisionPadding} className={s.content({ className })} {...props} />\n </MenuPrimitive.Portal>\n );\n}\n\nexport type DropdownMenuItemProps = React.ComponentProps<typeof MenuPrimitive.Item> & { tone?: \"default\" | \"danger\" };\n\n/** An action. `tone=\"danger\"` for a destructive one; `onSelect` runs it (the menu closes). */\nexport function DropdownMenuItem({ tone, className, ...props }: DropdownMenuItemProps) {\n return <MenuPrimitive.Item data-tone={tone ?? \"default\"} className={menu({ tone }).item({ className })} {...props} />;\n}\n\n/** A toggled option: `checked` + `onCheckedChange`. */\nexport function DropdownMenuCheckboxItem({ className, children, ...props }: React.ComponentProps<typeof MenuPrimitive.CheckboxItem>) {\n return (\n <MenuPrimitive.CheckboxItem className={s.item({ className })} {...props}>\n {children}\n <MenuPrimitive.ItemIndicator className={s.indicator()}>\n <svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2.5\" strokeLinecap=\"round\" strokeLinejoin=\"round\" aria-hidden>\n <path d=\"M20 6 9 17l-5-5\" />\n </svg>\n </MenuPrimitive.ItemIndicator>\n </MenuPrimitive.CheckboxItem>\n );\n}\n\nexport function DropdownMenuLabel({ className, ...props }: React.ComponentProps<typeof MenuPrimitive.Label>) {\n return <MenuPrimitive.Label className={s.label({ className })} {...props} />;\n}\n\nexport function DropdownMenuSeparator({ className, ...props }: React.ComponentProps<typeof MenuPrimitive.Separator>) {\n return <MenuPrimitive.Separator className={s.separator({ className })} {...props} />;\n}\n\n/** `DropdownMenu.Root/Trigger/Content/Item/CheckboxItem/Label/Separator/Group`. `open`/`defaultOpen` + `onOpenChange`. */\nexport const DropdownMenu = {\n Root: MenuPrimitive.Root,\n Trigger: MenuPrimitive.Trigger,\n Content: DropdownMenuContent,\n Item: DropdownMenuItem,\n CheckboxItem: DropdownMenuCheckboxItem,\n Label: DropdownMenuLabel,\n Separator: DropdownMenuSeparator,\n Group: MenuPrimitive.Group,\n};\n"],"mappings":";;;;;;;;;AACA,SAAS,gBAAgB,qBAAqB;AAE9C,SAAS,UAAU;AAiCb,cAeF,YAfE;AA5BC,IAAM,OAAO,GAAG;AAAA,EACrB,OAAO;AAAA,IACL,SAAS,GAAG,UAAU,6IAA6I;AAAA,IACnK,MACE;AAAA,IAGF,WAAW;AAAA,IACX,OAAO;AAAA,IACP,WAAW;AAAA,EACb;AAAA,EACA,UAAU;AAAA;AAAA;AAAA,IAGR,MAAM,EAAE,SAAS,CAAC,GAAG,QAAQ,EAAE,MAAM,oDAAoD,EAAE;AAAA,EAC7F;AAAA,EACA,iBAAiB,EAAE,MAAM,UAAU;AACrC,CAAC;AACD,IAAM,IAAI,KAAK;AAOR,SAAS,oBAAoB,EAAE,aAAa,GAAG,QAAQ,OAAO,mBAAmB,GAAG,WAAW,WAAW,GAAG,MAAM,GAA6B;AACrJ,SACE,oBAAC,cAAc,QAAd,EAAqB,WACpB,8BAAC,cAAc,SAAd,EAAsB,YAAwB,OAAc,kBAAoC,WAAW,EAAE,QAAQ,EAAE,UAAU,CAAC,GAAI,GAAG,OAAO,GACnJ;AAEJ;AAKO,SAAS,iBAAiB,EAAE,MAAM,WAAW,GAAG,MAAM,GAA0B;AACrF,SAAO,oBAAC,cAAc,MAAd,EAAmB,aAAW,QAAQ,WAAW,WAAW,KAAK,EAAE,KAAK,CAAC,EAAE,KAAK,EAAE,UAAU,CAAC,GAAI,GAAG,OAAO;AACrH;AAGO,SAAS,yBAAyB,EAAE,WAAW,UAAU,GAAG,MAAM,GAA4D;AACnI,SACE,qBAAC,cAAc,cAAd,EAA2B,WAAW,EAAE,KAAK,EAAE,UAAU,CAAC,GAAI,GAAG,OAC/D;AAAA;AAAA,IACD,oBAAC,cAAc,eAAd,EAA4B,WAAW,EAAE,UAAU,GAClD,8BAAC,SAAI,SAAQ,aAAY,MAAK,QAAO,QAAO,gBAAe,aAAY,OAAM,eAAc,SAAQ,gBAAe,SAAQ,eAAW,MACnI,8BAAC,UAAK,GAAE,mBAAkB,GAC5B,GACF;AAAA,KACF;AAEJ;AAEO,SAAS,kBAAkB,EAAE,WAAW,GAAG,MAAM,GAAqD;AAC3G,SAAO,oBAAC,cAAc,OAAd,EAAoB,WAAW,EAAE,MAAM,EAAE,UAAU,CAAC,GAAI,GAAG,OAAO;AAC5E;AAEO,SAAS,sBAAsB,EAAE,WAAW,GAAG,MAAM,GAAyD;AACnH,SAAO,oBAAC,cAAc,WAAd,EAAwB,WAAW,EAAE,UAAU,EAAE,UAAU,CAAC,GAAI,GAAG,OAAO;AACpF;AAGO,IAAM,eAAe;AAAA,EAC1B,MAAM,cAAc;AAAA,EACpB,SAAS,cAAc;AAAA,EACvB,SAAS;AAAA,EACT,MAAM;AAAA,EACN,cAAc;AAAA,EACd,OAAO;AAAA,EACP,WAAW;AAAA,EACX,OAAO,cAAc;AACvB;","names":[]}
@@ -0,0 +1,63 @@
1
+ import * as tailwind_variants from 'tailwind-variants';
2
+ import * as React from 'react';
3
+
4
+ declare const emptyState: tailwind_variants.TVReturnType<{
5
+ [key: string]: {
6
+ [key: string]: tailwind_variants.ClassValue | {
7
+ root?: tailwind_variants.ClassValue;
8
+ icon?: tailwind_variants.ClassValue;
9
+ title?: tailwind_variants.ClassValue;
10
+ description?: tailwind_variants.ClassValue;
11
+ action?: tailwind_variants.ClassValue;
12
+ };
13
+ };
14
+ } | {
15
+ [x: string]: {
16
+ [x: string]: tailwind_variants.ClassValue | {
17
+ root?: tailwind_variants.ClassValue;
18
+ icon?: tailwind_variants.ClassValue;
19
+ title?: tailwind_variants.ClassValue;
20
+ description?: tailwind_variants.ClassValue;
21
+ action?: tailwind_variants.ClassValue;
22
+ };
23
+ };
24
+ } | {}, {
25
+ root: string;
26
+ icon: string;
27
+ title: string;
28
+ description: string;
29
+ action: string;
30
+ }, undefined, {
31
+ [key: string]: {
32
+ [key: string]: tailwind_variants.ClassValue | {
33
+ root?: tailwind_variants.ClassValue;
34
+ icon?: tailwind_variants.ClassValue;
35
+ title?: tailwind_variants.ClassValue;
36
+ description?: tailwind_variants.ClassValue;
37
+ action?: tailwind_variants.ClassValue;
38
+ };
39
+ };
40
+ } | {}, {
41
+ root: string;
42
+ icon: string;
43
+ title: string;
44
+ description: string;
45
+ action: string;
46
+ }, tailwind_variants.TVReturnTypeLike<unknown, {
47
+ root: string;
48
+ icon: string;
49
+ title: string;
50
+ description: string;
51
+ action: string;
52
+ }>>;
53
+ type EmptyStateProps = Omit<React.ComponentProps<"div">, "title"> & {
54
+ /** A decorative icon (hidden from assistive technology). */
55
+ icon?: React.ReactNode;
56
+ title: React.ReactNode;
57
+ description?: React.ReactNode;
58
+ /** What to do next: a Button, a link. */
59
+ action?: React.ReactNode;
60
+ };
61
+ declare function EmptyState({ icon, title, description, action, className, ...props }: EmptyStateProps): React.JSX.Element;
62
+
63
+ export { EmptyState, type EmptyStateProps, emptyState };