@dirstack/ui 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +67 -0
- package/dist/components/animated-number.d.ts +18 -0
- package/dist/components/animated-number.d.ts.map +1 -0
- package/dist/components/animated-number.js +29 -0
- package/dist/components/animated-number.js.map +1 -0
- package/dist/components/avatar.d.ts +8 -0
- package/dist/components/avatar.d.ts.map +1 -0
- package/dist/components/avatar.js +27 -0
- package/dist/components/avatar.js.map +1 -0
- package/dist/components/badge.d.ts +58 -0
- package/dist/components/badge.d.ts.map +1 -0
- package/dist/components/badge.js +51 -0
- package/dist/components/badge.js.map +1 -0
- package/dist/components/button.d.ts +63 -0
- package/dist/components/button.d.ts.map +1 -0
- package/dist/components/button.js +66 -0
- package/dist/components/button.js.map +1 -0
- package/dist/components/callout.d.ts +41 -0
- package/dist/components/callout.d.ts.map +1 -0
- package/dist/components/callout.js +49 -0
- package/dist/components/callout.js.map +1 -0
- package/dist/components/card.d.ts +61 -0
- package/dist/components/card.d.ts.map +1 -0
- package/dist/components/card.js +67 -0
- package/dist/components/card.js.map +1 -0
- package/dist/components/chart.d.ts +32 -0
- package/dist/components/chart.d.ts.map +1 -0
- package/dist/components/chart.js +121 -0
- package/dist/components/chart.js.map +1 -0
- package/dist/components/copy-button.d.ts +22 -0
- package/dist/components/copy-button.d.ts.map +1 -0
- package/dist/components/copy-button.js +50 -0
- package/dist/components/copy-button.js.map +1 -0
- package/dist/components/copy-input.d.ts +13 -0
- package/dist/components/copy-input.d.ts.map +1 -0
- package/dist/components/copy-input.js +28 -0
- package/dist/components/copy-input.js.map +1 -0
- package/dist/components/detail-row.d.ts +93 -0
- package/dist/components/detail-row.d.ts.map +1 -0
- package/dist/components/detail-row.js +69 -0
- package/dist/components/detail-row.js.map +1 -0
- package/dist/components/dialog.d.ts +173 -0
- package/dist/components/dialog.d.ts.map +1 -0
- package/dist/components/dialog.js +139 -0
- package/dist/components/dialog.js.map +1 -0
- package/dist/components/empty-state.d.ts +96 -0
- package/dist/components/empty-state.d.ts.map +1 -0
- package/dist/components/empty-state.js +69 -0
- package/dist/components/empty-state.js.map +1 -0
- package/dist/components/entity-avatar.d.ts +77 -0
- package/dist/components/entity-avatar.d.ts.map +1 -0
- package/dist/components/entity-avatar.js +48 -0
- package/dist/components/entity-avatar.js.map +1 -0
- package/dist/components/form-row.d.ts +35 -0
- package/dist/components/form-row.d.ts.map +1 -0
- package/dist/components/form-row.js +46 -0
- package/dist/components/form-row.js.map +1 -0
- package/dist/components/form-section.d.ts +24 -0
- package/dist/components/form-section.d.ts.map +1 -0
- package/dist/components/form-section.js +39 -0
- package/dist/components/form-section.js.map +1 -0
- package/dist/components/form.d.ts +28 -0
- package/dist/components/form.d.ts.map +1 -0
- package/dist/components/form.js +88 -0
- package/dist/components/form.js.map +1 -0
- package/dist/components/heading.d.ts +44 -0
- package/dist/components/heading.d.ts.map +1 -0
- package/dist/components/heading.js +45 -0
- package/dist/components/heading.js.map +1 -0
- package/dist/components/input.d.ts +55 -0
- package/dist/components/input.d.ts.map +1 -0
- package/dist/components/input.js +33 -0
- package/dist/components/input.js.map +1 -0
- package/dist/components/kbd.d.ts +28 -0
- package/dist/components/kbd.d.ts.map +1 -0
- package/dist/components/kbd.js +31 -0
- package/dist/components/kbd.js.map +1 -0
- package/dist/components/label.d.ts +21 -0
- package/dist/components/label.d.ts.map +1 -0
- package/dist/components/label.js +21 -0
- package/dist/components/label.js.map +1 -0
- package/dist/components/menu.d.ts +22 -0
- package/dist/components/menu.d.ts.map +1 -0
- package/dist/components/menu.js +73 -0
- package/dist/components/menu.js.map +1 -0
- package/dist/components/nav-button.d.ts +34 -0
- package/dist/components/nav-button.d.ts.map +1 -0
- package/dist/components/nav-button.js +70 -0
- package/dist/components/nav-button.js.map +1 -0
- package/dist/components/nav.d.ts +44 -0
- package/dist/components/nav.d.ts.map +1 -0
- package/dist/components/nav.js +53 -0
- package/dist/components/nav.js.map +1 -0
- package/dist/components/number-input.d.ts +18 -0
- package/dist/components/number-input.d.ts.map +1 -0
- package/dist/components/number-input.js +25 -0
- package/dist/components/number-input.js.map +1 -0
- package/dist/components/page.d.ts +24 -0
- package/dist/components/page.d.ts.map +1 -0
- package/dist/components/page.js +24 -0
- package/dist/components/page.js.map +1 -0
- package/dist/components/pagination.d.ts +17 -0
- package/dist/components/pagination.d.ts.map +1 -0
- package/dist/components/pagination.js +63 -0
- package/dist/components/pagination.js.map +1 -0
- package/dist/components/popover.d.ts +8 -0
- package/dist/components/popover.d.ts.map +1 -0
- package/dist/components/popover.js +24 -0
- package/dist/components/popover.js.map +1 -0
- package/dist/components/search-input.d.ts +14 -0
- package/dist/components/search-input.d.ts.map +1 -0
- package/dist/components/search-input.js +36 -0
- package/dist/components/search-input.js.map +1 -0
- package/dist/components/section-header.d.ts +107 -0
- package/dist/components/section-header.d.ts.map +1 -0
- package/dist/components/section-header.js +147 -0
- package/dist/components/section-header.js.map +1 -0
- package/dist/components/select.d.ts +17 -0
- package/dist/components/select.d.ts.map +1 -0
- package/dist/components/select.js +94 -0
- package/dist/components/select.js.map +1 -0
- package/dist/components/skeleton.d.ts +5 -0
- package/dist/components/skeleton.d.ts.map +1 -0
- package/dist/components/skeleton.js +13 -0
- package/dist/components/skeleton.js.map +1 -0
- package/dist/components/stack.d.ts +54 -0
- package/dist/components/stack.d.ts.map +1 -0
- package/dist/components/stack.js +46 -0
- package/dist/components/stack.js.map +1 -0
- package/dist/components/stat-strip.d.ts +38 -0
- package/dist/components/stat-strip.d.ts.map +1 -0
- package/dist/components/stat-strip.js +57 -0
- package/dist/components/stat-strip.js.map +1 -0
- package/dist/components/steps.d.ts +19 -0
- package/dist/components/steps.d.ts.map +1 -0
- package/dist/components/steps.js +29 -0
- package/dist/components/steps.js.map +1 -0
- package/dist/components/switch.d.ts +6 -0
- package/dist/components/switch.d.ts.map +1 -0
- package/dist/components/switch.js +17 -0
- package/dist/components/switch.js.map +1 -0
- package/dist/components/tabs.d.ts +62 -0
- package/dist/components/tabs.d.ts.map +1 -0
- package/dist/components/tabs.js +64 -0
- package/dist/components/tabs.js.map +1 -0
- package/dist/components/textarea.d.ts +9 -0
- package/dist/components/textarea.d.ts.map +1 -0
- package/dist/components/textarea.js +18 -0
- package/dist/components/textarea.js.map +1 -0
- package/dist/components/toaster.d.ts +6 -0
- package/dist/components/toaster.d.ts.map +1 -0
- package/dist/components/toaster.js +37 -0
- package/dist/components/toaster.js.map +1 -0
- package/dist/components/tooltip.d.ts +15 -0
- package/dist/components/tooltip.d.ts.map +1 -0
- package/dist/components/tooltip.js +41 -0
- package/dist/components/tooltip.js.map +1 -0
- package/dist/lib/animation.d.ts +12 -0
- package/dist/lib/animation.d.ts.map +1 -0
- package/dist/lib/animation.js +14 -0
- package/dist/lib/animation.js.map +1 -0
- package/dist/lib/classes.d.ts +29 -0
- package/dist/lib/classes.d.ts.map +1 -0
- package/dist/lib/classes.js +39 -0
- package/dist/lib/classes.js.map +1 -0
- package/dist/lib/icons.d.ts +21 -0
- package/dist/lib/icons.d.ts.map +1 -0
- package/dist/lib/icons.js +43 -0
- package/dist/lib/icons.js.map +1 -0
- package/dist/lib/interactive.d.ts +41 -0
- package/dist/lib/interactive.d.ts.map +1 -0
- package/dist/lib/interactive.js +30 -0
- package/dist/lib/interactive.js.map +1 -0
- package/dist/lib/slot.d.ts +12 -0
- package/dist/lib/slot.d.ts.map +1 -0
- package/dist/lib/slot.js +19 -0
- package/dist/lib/slot.js.map +1 -0
- package/dist/lib/variants.d.ts +3 -0
- package/dist/lib/variants.js +3 -0
- package/dist/styles.css +169 -0
- package/package.json +112 -0
|
@@ -0,0 +1,173 @@
|
|
|
1
|
+
import { VariantProps } from "../lib/variants.js";
|
|
2
|
+
import { Button } from "./button.js";
|
|
3
|
+
import { SectionHeader } from "./section-header.js";
|
|
4
|
+
import { ComponentProps, ReactNode } from "react";
|
|
5
|
+
import { Dialog as Dialog$1 } from "@base-ui/react/dialog";
|
|
6
|
+
//#region src/components/dialog.d.ts
|
|
7
|
+
declare const Dialog: typeof Dialog$1.Root;
|
|
8
|
+
declare const DialogTrigger: Dialog$1.Trigger;
|
|
9
|
+
declare const DialogTitle: import("react").ForwardRefExoticComponent<Omit<import("@base-ui/react").AlertDialogTitleProps, "ref"> & import("react").RefAttributes<HTMLHeadingElement>>;
|
|
10
|
+
declare const DialogDescription: import("react").ForwardRefExoticComponent<Omit<import("@base-ui/react").AlertDialogDescriptionProps, "ref"> & import("react").RefAttributes<HTMLParagraphElement>>;
|
|
11
|
+
declare const dialogContentVariants: import("tailwind-variants").TVReturnType<{
|
|
12
|
+
size: {
|
|
13
|
+
xs: "max-w-xs";
|
|
14
|
+
sm: "max-w-sm";
|
|
15
|
+
md: "max-w-md";
|
|
16
|
+
lg: "max-w-lg";
|
|
17
|
+
xl: "max-w-xl";
|
|
18
|
+
"2xl": "max-w-2xl";
|
|
19
|
+
"3xl": "max-w-3xl";
|
|
20
|
+
"4xl": "max-w-4xl";
|
|
21
|
+
"5xl": "max-w-5xl";
|
|
22
|
+
};
|
|
23
|
+
/**
|
|
24
|
+
* Pin the dialog near the top of the viewport instead of centering it, so its height can
|
|
25
|
+
* change without the whole thing jumping. A dialog stacked on top of another one
|
|
26
|
+
* (`[[role=dialog]~&]`) sits a little lower still, so both remain visible.
|
|
27
|
+
*/
|
|
28
|
+
fixed: {
|
|
29
|
+
true: "top-[10vh] max-h-[calc(90vh-2rem)] [[role=dialog]~&]:top-[15vh] [[role=dialog]~&]:max-h-[calc(85vh-2rem)]";
|
|
30
|
+
false: "top-1/2 -translate-y-1/2 max-h-[calc(100vh-2rem)]";
|
|
31
|
+
};
|
|
32
|
+
/**
|
|
33
|
+
* Drop the dialog's own padding and gap so sections can run edge to edge and draw their
|
|
34
|
+
* own borders, e.g. a bordered header over a scrolling body over a bordered footer.
|
|
35
|
+
*/
|
|
36
|
+
flush: {
|
|
37
|
+
true: "gap-0 p-0";
|
|
38
|
+
false: "gap-6 p-6";
|
|
39
|
+
};
|
|
40
|
+
}, undefined, string[], {
|
|
41
|
+
size: {
|
|
42
|
+
xs: "max-w-xs";
|
|
43
|
+
sm: "max-w-sm";
|
|
44
|
+
md: "max-w-md";
|
|
45
|
+
lg: "max-w-lg";
|
|
46
|
+
xl: "max-w-xl";
|
|
47
|
+
"2xl": "max-w-2xl";
|
|
48
|
+
"3xl": "max-w-3xl";
|
|
49
|
+
"4xl": "max-w-4xl";
|
|
50
|
+
"5xl": "max-w-5xl";
|
|
51
|
+
};
|
|
52
|
+
/**
|
|
53
|
+
* Pin the dialog near the top of the viewport instead of centering it, so its height can
|
|
54
|
+
* change without the whole thing jumping. A dialog stacked on top of another one
|
|
55
|
+
* (`[[role=dialog]~&]`) sits a little lower still, so both remain visible.
|
|
56
|
+
*/
|
|
57
|
+
fixed: {
|
|
58
|
+
true: "top-[10vh] max-h-[calc(90vh-2rem)] [[role=dialog]~&]:top-[15vh] [[role=dialog]~&]:max-h-[calc(85vh-2rem)]";
|
|
59
|
+
false: "top-1/2 -translate-y-1/2 max-h-[calc(100vh-2rem)]";
|
|
60
|
+
};
|
|
61
|
+
/**
|
|
62
|
+
* Drop the dialog's own padding and gap so sections can run edge to edge and draw their
|
|
63
|
+
* own borders, e.g. a bordered header over a scrolling body over a bordered footer.
|
|
64
|
+
*/
|
|
65
|
+
flush: {
|
|
66
|
+
true: "gap-0 p-0";
|
|
67
|
+
false: "gap-6 p-6";
|
|
68
|
+
};
|
|
69
|
+
}, undefined, import("tailwind-variants").TVReturnTypeLike<{
|
|
70
|
+
size: {
|
|
71
|
+
xs: "max-w-xs";
|
|
72
|
+
sm: "max-w-sm";
|
|
73
|
+
md: "max-w-md";
|
|
74
|
+
lg: "max-w-lg";
|
|
75
|
+
xl: "max-w-xl";
|
|
76
|
+
"2xl": "max-w-2xl";
|
|
77
|
+
"3xl": "max-w-3xl";
|
|
78
|
+
"4xl": "max-w-4xl";
|
|
79
|
+
"5xl": "max-w-5xl";
|
|
80
|
+
};
|
|
81
|
+
/**
|
|
82
|
+
* Pin the dialog near the top of the viewport instead of centering it, so its height can
|
|
83
|
+
* change without the whole thing jumping. A dialog stacked on top of another one
|
|
84
|
+
* (`[[role=dialog]~&]`) sits a little lower still, so both remain visible.
|
|
85
|
+
*/
|
|
86
|
+
fixed: {
|
|
87
|
+
true: "top-[10vh] max-h-[calc(90vh-2rem)] [[role=dialog]~&]:top-[15vh] [[role=dialog]~&]:max-h-[calc(85vh-2rem)]";
|
|
88
|
+
false: "top-1/2 -translate-y-1/2 max-h-[calc(100vh-2rem)]";
|
|
89
|
+
};
|
|
90
|
+
/**
|
|
91
|
+
* Drop the dialog's own padding and gap so sections can run edge to edge and draw their
|
|
92
|
+
* own borders, e.g. a bordered header over a scrolling body over a bordered footer.
|
|
93
|
+
*/
|
|
94
|
+
flush: {
|
|
95
|
+
true: "gap-0 p-0";
|
|
96
|
+
false: "gap-6 p-6";
|
|
97
|
+
};
|
|
98
|
+
}, undefined>>;
|
|
99
|
+
type DialogContentProps = Omit<Dialog$1.Popup.Props, "className"> & VariantProps<typeof dialogContentVariants> & {
|
|
100
|
+
className?: string;
|
|
101
|
+
/**
|
|
102
|
+
* Hide the close button in the top right corner, for a dialog that must be dismissed
|
|
103
|
+
* through one of its own actions.
|
|
104
|
+
*/
|
|
105
|
+
hideClose?: boolean;
|
|
106
|
+
};
|
|
107
|
+
declare function DialogContent({ className, children, size, fixed, flush, hideClose, ...props }: DialogContentProps): import("react").JSX.Element;
|
|
108
|
+
declare const dialogHeaderVariants: import("tailwind-variants").TVReturnType<{
|
|
109
|
+
/**
|
|
110
|
+
* Give the header its own hairline and padding, for a `flush` dialog whose body scrolls
|
|
111
|
+
* under it. The extra right padding clears the dialog's close button.
|
|
112
|
+
*/
|
|
113
|
+
bordered: {
|
|
114
|
+
true: "border-b px-6 py-5 pr-14";
|
|
115
|
+
};
|
|
116
|
+
}, undefined, undefined, {
|
|
117
|
+
/**
|
|
118
|
+
* Give the header its own hairline and padding, for a `flush` dialog whose body scrolls
|
|
119
|
+
* under it. The extra right padding clears the dialog's close button.
|
|
120
|
+
*/
|
|
121
|
+
bordered: {
|
|
122
|
+
true: "border-b px-6 py-5 pr-14";
|
|
123
|
+
};
|
|
124
|
+
}, undefined, import("tailwind-variants").TVReturnTypeLike<{
|
|
125
|
+
/**
|
|
126
|
+
* Give the header its own hairline and padding, for a `flush` dialog whose body scrolls
|
|
127
|
+
* under it. The extra right padding clears the dialog's close button.
|
|
128
|
+
*/
|
|
129
|
+
bordered: {
|
|
130
|
+
true: "border-b px-6 py-5 pr-14";
|
|
131
|
+
};
|
|
132
|
+
}, undefined>>;
|
|
133
|
+
type DialogHeaderProps = Omit<ComponentProps<typeof SectionHeader>, "title" | "description"> & VariantProps<typeof dialogHeaderVariants> & {
|
|
134
|
+
title: ReactNode;
|
|
135
|
+
description?: ReactNode;
|
|
136
|
+
};
|
|
137
|
+
/**
|
|
138
|
+
* The standard dialog heading: a card-scale `SectionHeader` whose title and description are wired to
|
|
139
|
+
* Base UI's `DialogTitle` / `DialogDescription` for accessibility. Extra children render after
|
|
140
|
+
* them.
|
|
141
|
+
*/
|
|
142
|
+
declare function DialogHeader({ title, description, bordered, className, children, ...props }: DialogHeaderProps): import("react").JSX.Element;
|
|
143
|
+
declare const dialogFooterVariants: import("tailwind-variants").TVReturnType<{
|
|
144
|
+
/**
|
|
145
|
+
* Give the footer its own hairline and padding, for a `flush` dialog where the body
|
|
146
|
+
* scrolls behind it.
|
|
147
|
+
*/
|
|
148
|
+
bordered: {
|
|
149
|
+
true: "border-t px-6 py-4";
|
|
150
|
+
};
|
|
151
|
+
}, undefined, "flex flex-col-reverse flex-wrap gap-x-2 gap-y-4 sm:flex-row sm:justify-end", {
|
|
152
|
+
/**
|
|
153
|
+
* Give the footer its own hairline and padding, for a `flush` dialog where the body
|
|
154
|
+
* scrolls behind it.
|
|
155
|
+
*/
|
|
156
|
+
bordered: {
|
|
157
|
+
true: "border-t px-6 py-4";
|
|
158
|
+
};
|
|
159
|
+
}, undefined, import("tailwind-variants").TVReturnTypeLike<{
|
|
160
|
+
/**
|
|
161
|
+
* Give the footer its own hairline and padding, for a `flush` dialog where the body
|
|
162
|
+
* scrolls behind it.
|
|
163
|
+
*/
|
|
164
|
+
bordered: {
|
|
165
|
+
true: "border-t px-6 py-4";
|
|
166
|
+
};
|
|
167
|
+
}, undefined>>;
|
|
168
|
+
type DialogFooterProps = ComponentProps<"div"> & VariantProps<typeof dialogFooterVariants>;
|
|
169
|
+
declare function DialogFooter({ className, bordered, ...props }: DialogFooterProps): import("react").JSX.Element;
|
|
170
|
+
declare function DialogClose({ ...props }: ComponentProps<typeof Button>): import("react").JSX.Element;
|
|
171
|
+
//#endregion
|
|
172
|
+
export { Dialog, DialogClose, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTitle, DialogTrigger };
|
|
173
|
+
//# sourceMappingURL=dialog.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dialog.d.ts","names":[],"sources":["../../src/components/dialog.tsx"],"mappings":";;;;;;cAcM,eAAM,SAAA;cACN,eAAa,SAAA;cACb,6BAAW,0BAAA,8BAAA,gDAAA,cAAA;cACX,mCAAiB,0BAAA,8BAAA,sDAAA,cAAA;cAiBjB,mDAAqB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;KAiDtB,qBAAqB,KAAK,SAAgB,MAAM,sBACnD,oBAAoB;EAClB;;;;;EAMA;;iBAGK,gBACP,WACA,UACA,MACA,OACA,OACA,cACG,SACF,qCAAkB,IAAA;cAsBf,kDAAoB;;;;;;;;;;;;;;;;;;;;;;;;;KAYrB,oBAAoB,KAAK,sBAAsB,2CAClD,oBAAoB;EAClB,OAAO;EACP,cAAc;;;;;;;iBAQT,eACP,OACA,aACA,UACA,WACA,aACG,SACF,oCAAiB,IAAA;cAgBd,kDAAoB;;;;;;;;;;;;;;;;;;;;;;;;;KAcrB,oBAAoB,wBAAwB,oBAAoB;iBAE5D,eAAe,WAAW,aAAa,SAAS,oCAAiB,IAAA;iBAIjE,iBAAiB,SAAS,sBAAsB,0BAAO,IAAA"}
|
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { cn, variants } from "../lib/variants.js";
|
|
3
|
+
import { XIcon } from "../lib/icons.js";
|
|
4
|
+
import { Button } from "./button.js";
|
|
5
|
+
import { SectionHeader, SectionHeaderBody, SectionHeaderDescription, SectionHeaderTitle } from "./section-header.js";
|
|
6
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
7
|
+
import { Dialog as Dialog$1 } from "@base-ui/react/dialog";
|
|
8
|
+
//#region src/components/dialog.tsx
|
|
9
|
+
const Dialog = Dialog$1.Root;
|
|
10
|
+
const DialogTrigger = Dialog$1.Trigger;
|
|
11
|
+
const DialogTitle = Dialog$1.Title;
|
|
12
|
+
const DialogDescription = Dialog$1.Description;
|
|
13
|
+
/** The dashed, blurred backdrop behind the dialog. Rendered by `DialogContent`. */
|
|
14
|
+
function DialogOverlay({ className, ...props }) {
|
|
15
|
+
return /* @__PURE__ */ jsx(Dialog$1.Backdrop, {
|
|
16
|
+
className: cn("fixed inset-0 z-50 bg-dashed backdrop-blur-xs", "data-open:animate-in data-closed:animate-out", "data-open:fade-in-0 data-closed:fade-out-0", className),
|
|
17
|
+
...props
|
|
18
|
+
});
|
|
19
|
+
}
|
|
20
|
+
const dialogContentVariants = variants({
|
|
21
|
+
base: [
|
|
22
|
+
"fixed left-1/2 z-50 grid w-[calc(100vw-2rem)] -translate-x-1/2 overflow-y-auto",
|
|
23
|
+
"border bg-card shadow-sm rounded-xl",
|
|
24
|
+
"data-open:animate-in data-closed:animate-out",
|
|
25
|
+
"data-open:fade-in-0 data-closed:fade-out-0",
|
|
26
|
+
"data-open:slide-in-from-bottom-4 data-closed:slide-out-to-bottom-4"
|
|
27
|
+
],
|
|
28
|
+
variants: {
|
|
29
|
+
size: {
|
|
30
|
+
xs: "max-w-xs",
|
|
31
|
+
sm: "max-w-sm",
|
|
32
|
+
md: "max-w-md",
|
|
33
|
+
lg: "max-w-lg",
|
|
34
|
+
xl: "max-w-xl",
|
|
35
|
+
"2xl": "max-w-2xl",
|
|
36
|
+
"3xl": "max-w-3xl",
|
|
37
|
+
"4xl": "max-w-4xl",
|
|
38
|
+
"5xl": "max-w-5xl"
|
|
39
|
+
},
|
|
40
|
+
/**
|
|
41
|
+
* Pin the dialog near the top of the viewport instead of centering it, so its height can
|
|
42
|
+
* change without the whole thing jumping. A dialog stacked on top of another one
|
|
43
|
+
* (`[[role=dialog]~&]`) sits a little lower still, so both remain visible.
|
|
44
|
+
*/
|
|
45
|
+
fixed: {
|
|
46
|
+
true: "top-[10vh] max-h-[calc(90vh-2rem)] [[role=dialog]~&]:top-[15vh] [[role=dialog]~&]:max-h-[calc(85vh-2rem)]",
|
|
47
|
+
false: "top-1/2 -translate-y-1/2 max-h-[calc(100vh-2rem)]"
|
|
48
|
+
},
|
|
49
|
+
/**
|
|
50
|
+
* Drop the dialog's own padding and gap so sections can run edge to edge and draw their
|
|
51
|
+
* own borders, e.g. a bordered header over a scrolling body over a bordered footer.
|
|
52
|
+
*/
|
|
53
|
+
flush: {
|
|
54
|
+
true: "gap-0 p-0",
|
|
55
|
+
false: "gap-6 p-6"
|
|
56
|
+
}
|
|
57
|
+
},
|
|
58
|
+
defaultVariants: {
|
|
59
|
+
size: "md",
|
|
60
|
+
fixed: true,
|
|
61
|
+
flush: false
|
|
62
|
+
}
|
|
63
|
+
});
|
|
64
|
+
function DialogContent({ className, children, size, fixed, flush, hideClose, ...props }) {
|
|
65
|
+
return /* @__PURE__ */ jsxs(Dialog$1.Portal, { children: [/* @__PURE__ */ jsx(DialogOverlay, {}), /* @__PURE__ */ jsxs(Dialog$1.Popup, {
|
|
66
|
+
className: dialogContentVariants({
|
|
67
|
+
size,
|
|
68
|
+
fixed,
|
|
69
|
+
flush,
|
|
70
|
+
className
|
|
71
|
+
}),
|
|
72
|
+
...props,
|
|
73
|
+
children: [children, !hideClose && /* @__PURE__ */ jsx(Dialog$1.Close, {
|
|
74
|
+
render: /* @__PURE__ */ jsx(Button, {
|
|
75
|
+
variant: "ghost",
|
|
76
|
+
size: "sm",
|
|
77
|
+
"aria-label": "Close",
|
|
78
|
+
prefix: /* @__PURE__ */ jsx(XIcon, {})
|
|
79
|
+
}),
|
|
80
|
+
className: "absolute top-3 right-3"
|
|
81
|
+
})]
|
|
82
|
+
})] });
|
|
83
|
+
}
|
|
84
|
+
const dialogHeaderVariants = variants({ variants: {
|
|
85
|
+
/**
|
|
86
|
+
* Give the header its own hairline and padding, for a `flush` dialog whose body scrolls
|
|
87
|
+
* under it. The extra right padding clears the dialog's close button.
|
|
88
|
+
*/
|
|
89
|
+
bordered: { true: "border-b px-6 py-5 pr-14" } } });
|
|
90
|
+
/**
|
|
91
|
+
* The standard dialog heading: a card-scale `SectionHeader` whose title and description are wired to
|
|
92
|
+
* Base UI's `DialogTitle` / `DialogDescription` for accessibility. Extra children render after
|
|
93
|
+
* them.
|
|
94
|
+
*/
|
|
95
|
+
function DialogHeader({ title, description, bordered, className, children, ...props }) {
|
|
96
|
+
return /* @__PURE__ */ jsxs(SectionHeader, {
|
|
97
|
+
size: "card",
|
|
98
|
+
className: dialogHeaderVariants({
|
|
99
|
+
bordered,
|
|
100
|
+
className
|
|
101
|
+
}),
|
|
102
|
+
...props,
|
|
103
|
+
children: [/* @__PURE__ */ jsxs(SectionHeaderBody, { children: [/* @__PURE__ */ jsx(DialogTitle, {
|
|
104
|
+
render: /* @__PURE__ */ jsx(SectionHeaderTitle, {}),
|
|
105
|
+
children: title
|
|
106
|
+
}), description && /* @__PURE__ */ jsx(DialogDescription, {
|
|
107
|
+
render: /* @__PURE__ */ jsx(SectionHeaderDescription, {}),
|
|
108
|
+
children: description
|
|
109
|
+
})] }), children]
|
|
110
|
+
});
|
|
111
|
+
}
|
|
112
|
+
const dialogFooterVariants = variants({
|
|
113
|
+
base: "flex flex-col-reverse flex-wrap gap-x-2 gap-y-4 sm:flex-row sm:justify-end",
|
|
114
|
+
variants: {
|
|
115
|
+
/**
|
|
116
|
+
* Give the footer its own hairline and padding, for a `flush` dialog where the body
|
|
117
|
+
* scrolls behind it.
|
|
118
|
+
*/
|
|
119
|
+
bordered: { true: "border-t px-6 py-4" } }
|
|
120
|
+
});
|
|
121
|
+
function DialogFooter({ className, bordered, ...props }) {
|
|
122
|
+
return /* @__PURE__ */ jsx("div", {
|
|
123
|
+
className: dialogFooterVariants({
|
|
124
|
+
bordered,
|
|
125
|
+
className
|
|
126
|
+
}),
|
|
127
|
+
...props
|
|
128
|
+
});
|
|
129
|
+
}
|
|
130
|
+
function DialogClose({ ...props }) {
|
|
131
|
+
return /* @__PURE__ */ jsx(Dialog$1.Close, { render: /* @__PURE__ */ jsx(Button, {
|
|
132
|
+
variant: "secondary",
|
|
133
|
+
...props
|
|
134
|
+
}) });
|
|
135
|
+
}
|
|
136
|
+
//#endregion
|
|
137
|
+
export { Dialog, DialogClose, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTitle, DialogTrigger };
|
|
138
|
+
|
|
139
|
+
//# sourceMappingURL=dialog.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dialog.js","names":["DialogPrimitive"],"sources":["../../src/components/dialog.tsx"],"sourcesContent":["\"use client\"\n\nimport { Dialog as DialogPrimitive } from \"@base-ui/react/dialog\"\nimport type { ComponentProps, ReactNode } from \"react\"\nimport { Button } from \"~/components/button\"\nimport {\n SectionHeader,\n SectionHeaderBody,\n SectionHeaderDescription,\n SectionHeaderTitle,\n} from \"~/components/section-header\"\nimport { XIcon } from \"~/lib/icons\"\nimport { variants, cn, type VariantProps } from \"~/lib/variants\"\n\nconst Dialog = DialogPrimitive.Root\nconst DialogTrigger = DialogPrimitive.Trigger\nconst DialogTitle = DialogPrimitive.Title\nconst DialogDescription = DialogPrimitive.Description\n\n/** The dashed, blurred backdrop behind the dialog. Rendered by `DialogContent`. */\nfunction DialogOverlay({ className, ...props }: DialogPrimitive.Backdrop.Props) {\n return (\n <DialogPrimitive.Backdrop\n className={cn(\n \"fixed inset-0 z-50 bg-dashed backdrop-blur-xs\",\n \"data-open:animate-in data-closed:animate-out\",\n \"data-open:fade-in-0 data-closed:fade-out-0\",\n className,\n )}\n {...props}\n />\n )\n}\n\nconst dialogContentVariants = variants({\n base: [\n \"fixed left-1/2 z-50 grid w-[calc(100vw-2rem)] -translate-x-1/2 overflow-y-auto\",\n \"border bg-card shadow-sm rounded-xl\",\n \"data-open:animate-in data-closed:animate-out\",\n \"data-open:fade-in-0 data-closed:fade-out-0\",\n \"data-open:slide-in-from-bottom-4 data-closed:slide-out-to-bottom-4\",\n ],\n\n variants: {\n size: {\n xs: \"max-w-xs\",\n sm: \"max-w-sm\",\n md: \"max-w-md\",\n lg: \"max-w-lg\",\n xl: \"max-w-xl\",\n \"2xl\": \"max-w-2xl\",\n \"3xl\": \"max-w-3xl\",\n \"4xl\": \"max-w-4xl\",\n \"5xl\": \"max-w-5xl\",\n },\n\n /**\n * Pin the dialog near the top of the viewport instead of centering it, so its height can\n * change without the whole thing jumping. A dialog stacked on top of another one\n * (`[[role=dialog]~&]`) sits a little lower still, so both remain visible.\n */\n fixed: {\n true: \"top-[10vh] max-h-[calc(90vh-2rem)] [[role=dialog]~&]:top-[15vh] [[role=dialog]~&]:max-h-[calc(85vh-2rem)]\",\n false: \"top-1/2 -translate-y-1/2 max-h-[calc(100vh-2rem)]\",\n },\n\n /**\n * Drop the dialog's own padding and gap so sections can run edge to edge and draw their\n * own borders, e.g. a bordered header over a scrolling body over a bordered footer.\n */\n flush: {\n true: \"gap-0 p-0\",\n false: \"gap-6 p-6\",\n },\n },\n\n defaultVariants: {\n size: \"md\",\n fixed: true,\n flush: false,\n },\n})\n\ntype DialogContentProps = Omit<DialogPrimitive.Popup.Props, \"className\"> &\n VariantProps<typeof dialogContentVariants> & {\n className?: string\n\n /**\n * Hide the close button in the top right corner, for a dialog that must be dismissed\n * through one of its own actions.\n */\n hideClose?: boolean\n }\n\nfunction DialogContent({\n className,\n children,\n size,\n fixed,\n flush,\n hideClose,\n ...props\n}: DialogContentProps) {\n return (\n <DialogPrimitive.Portal>\n <DialogOverlay />\n\n <DialogPrimitive.Popup\n className={dialogContentVariants({ size, fixed, flush, className })}\n {...props}\n >\n {children}\n\n {!hideClose && (\n <DialogPrimitive.Close\n render={<Button variant=\"ghost\" size=\"sm\" aria-label=\"Close\" prefix={<XIcon />} />}\n className=\"absolute top-3 right-3\"\n />\n )}\n </DialogPrimitive.Popup>\n </DialogPrimitive.Portal>\n )\n}\n\nconst dialogHeaderVariants = variants({\n variants: {\n /**\n * Give the header its own hairline and padding, for a `flush` dialog whose body scrolls\n * under it. The extra right padding clears the dialog's close button.\n */\n bordered: {\n true: \"border-b px-6 py-5 pr-14\",\n },\n },\n})\n\ntype DialogHeaderProps = Omit<ComponentProps<typeof SectionHeader>, \"title\" | \"description\"> &\n VariantProps<typeof dialogHeaderVariants> & {\n title: ReactNode\n description?: ReactNode\n }\n\n/**\n * The standard dialog heading: a card-scale `SectionHeader` whose title and description are wired to\n * Base UI's `DialogTitle` / `DialogDescription` for accessibility. Extra children render after\n * them.\n */\nfunction DialogHeader({\n title,\n description,\n bordered,\n className,\n children,\n ...props\n}: DialogHeaderProps) {\n return (\n <SectionHeader size=\"card\" className={dialogHeaderVariants({ bordered, className })} {...props}>\n <SectionHeaderBody>\n <DialogTitle render={<SectionHeaderTitle />}>{title}</DialogTitle>\n\n {description && (\n <DialogDescription render={<SectionHeaderDescription />}>{description}</DialogDescription>\n )}\n </SectionHeaderBody>\n\n {children}\n </SectionHeader>\n )\n}\n\nconst dialogFooterVariants = variants({\n base: \"flex flex-col-reverse flex-wrap gap-x-2 gap-y-4 sm:flex-row sm:justify-end\",\n\n variants: {\n /**\n * Give the footer its own hairline and padding, for a `flush` dialog where the body\n * scrolls behind it.\n */\n bordered: {\n true: \"border-t px-6 py-4\",\n },\n },\n})\n\ntype DialogFooterProps = ComponentProps<\"div\"> & VariantProps<typeof dialogFooterVariants>\n\nfunction DialogFooter({ className, bordered, ...props }: DialogFooterProps) {\n return <div className={dialogFooterVariants({ bordered, className })} {...props} />\n}\n\nfunction DialogClose({ ...props }: ComponentProps<typeof Button>) {\n return <DialogPrimitive.Close render={<Button variant=\"secondary\" {...props} />} />\n}\n\nexport {\n Dialog,\n DialogClose,\n DialogContent,\n DialogDescription,\n DialogFooter,\n DialogHeader,\n DialogTitle,\n DialogTrigger,\n}\n"],"mappings":";;;;;;;;AAcA,MAAM,SAASA,SAAgB;AAC/B,MAAM,gBAAgBA,SAAgB;AACtC,MAAM,cAAcA,SAAgB;AACpC,MAAM,oBAAoBA,SAAgB;;AAG1C,SAAS,cAAc,EAAE,WAAW,GAAG,SAAyC;CAC9E,OACE,oBAACA,SAAgB,UAAjB;EACE,WAAW,GACT,iDACA,gDACA,8CACA,SACF;EACA,GAAI;CACL,CAAA;AAEL;AAEA,MAAM,wBAAwB,SAAS;CACrC,MAAM;EACJ;EACA;EACA;EACA;EACA;CACF;CAEA,UAAU;EACR,MAAM;GACJ,IAAI;GACJ,IAAI;GACJ,IAAI;GACJ,IAAI;GACJ,IAAI;GACJ,OAAO;GACP,OAAO;GACP,OAAO;GACP,OAAO;EACT;;;;;;EAOA,OAAO;GACL,MAAM;GACN,OAAO;EACT;;;;;EAMA,OAAO;GACL,MAAM;GACN,OAAO;EACT;CACF;CAEA,iBAAiB;EACf,MAAM;EACN,OAAO;EACP,OAAO;CACT;AACF,CAAC;AAaD,SAAS,cAAc,EACrB,WACA,UACA,MACA,OACA,OACA,WACA,GAAG,SACkB;CACrB,OACE,qBAACA,SAAgB,QAAjB,EAAA,UAAA,CACE,oBAAC,eAAD,CAAgB,CAAA,GAEhB,qBAACA,SAAgB,OAAjB;EACE,WAAW,sBAAsB;GAAE;GAAM;GAAO;GAAO;EAAU,CAAC;EAClE,GAAI;EAFN,UAAA,CAIG,UAEA,CAAC,aACA,oBAACA,SAAgB,OAAjB;GACE,QAAQ,oBAAC,QAAD;IAAQ,SAAQ;IAAQ,MAAK;IAAK,cAAW;IAAQ,QAAQ,oBAAC,OAAD,CAAQ,CAAA;GAAI,CAAA;GACjF,WAAU;EACX,CAAA,CAEkB;CACD,CAAA,CAAA,EAAA,CAAA;AAE5B;AAEA,MAAM,uBAAuB,SAAS,EACpC,UAAU;;;;;AAKR,UAAU,EACR,MAAM,2BACR,EACF,EACF,CAAC;;;;;;AAaD,SAAS,aAAa,EACpB,OACA,aACA,UACA,WACA,UACA,GAAG,SACiB;CACpB,OACE,qBAAC,eAAD;EAAe,MAAK;EAAO,WAAW,qBAAqB;GAAE;GAAU;EAAU,CAAC;EAAG,GAAI;EAAzF,UAAA,CACE,qBAAC,mBAAD,EAAA,UAAA,CACE,oBAAC,aAAD;GAAa,QAAQ,oBAAC,oBAAD,CAAqB,CAAA;GAAI,UAAA;EAAmB,CAAA,GAEhE,eACC,oBAAC,mBAAD;GAAmB,QAAQ,oBAAC,0BAAD,CAA2B,CAAA;GAAI,UAAA;EAA+B,CAAA,CAE1E,EAAA,CAAA,GAElB,QACY;;AAEnB;AAEA,MAAM,uBAAuB,SAAS;CACpC,MAAM;CAEN,UAAU;;;;;AAKR,UAAU,EACR,MAAM,qBACR,EACF;AACF,CAAC;AAID,SAAS,aAAa,EAAE,WAAW,UAAU,GAAG,SAA4B;CAC1E,OAAO,oBAAC,OAAD;EAAK,WAAW,qBAAqB;GAAE;GAAU;EAAU,CAAC;EAAG,GAAI;CAAQ,CAAA;AACpF;AAEA,SAAS,YAAY,EAAE,GAAG,SAAwC;CAChE,OAAO,oBAACA,SAAgB,OAAjB,EAAuB,QAAQ,oBAAC,QAAD;EAAQ,SAAQ;EAAY,GAAI;CAAQ,CAAA,EAAI,CAAA;AACpF"}
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
import { VariantProps } from "../lib/variants.js";
|
|
2
|
+
import { ComponentProps, ReactNode } from "react";
|
|
3
|
+
//#region src/components/empty-state.d.ts
|
|
4
|
+
declare const emptyStateVariants: import("tailwind-variants").TVReturnType<{
|
|
5
|
+
variant: {
|
|
6
|
+
block: {
|
|
7
|
+
root: string;
|
|
8
|
+
title: string;
|
|
9
|
+
description: string;
|
|
10
|
+
action: string;
|
|
11
|
+
};
|
|
12
|
+
inline: {
|
|
13
|
+
root: string;
|
|
14
|
+
title: string;
|
|
15
|
+
action: string;
|
|
16
|
+
};
|
|
17
|
+
dashed: {
|
|
18
|
+
root: string;
|
|
19
|
+
title: string;
|
|
20
|
+
action: string;
|
|
21
|
+
};
|
|
22
|
+
};
|
|
23
|
+
}, {
|
|
24
|
+
root: string;
|
|
25
|
+
icon: string;
|
|
26
|
+
content: string;
|
|
27
|
+
title: string;
|
|
28
|
+
description: string;
|
|
29
|
+
action: string;
|
|
30
|
+
}, undefined, {
|
|
31
|
+
variant: {
|
|
32
|
+
block: {
|
|
33
|
+
root: string;
|
|
34
|
+
title: string;
|
|
35
|
+
description: string;
|
|
36
|
+
action: string;
|
|
37
|
+
};
|
|
38
|
+
inline: {
|
|
39
|
+
root: string;
|
|
40
|
+
title: string;
|
|
41
|
+
action: string;
|
|
42
|
+
};
|
|
43
|
+
dashed: {
|
|
44
|
+
root: string;
|
|
45
|
+
title: string;
|
|
46
|
+
action: string;
|
|
47
|
+
};
|
|
48
|
+
};
|
|
49
|
+
}, {
|
|
50
|
+
root: string;
|
|
51
|
+
icon: string;
|
|
52
|
+
content: string;
|
|
53
|
+
title: string;
|
|
54
|
+
description: string;
|
|
55
|
+
action: string;
|
|
56
|
+
}, import("tailwind-variants").TVReturnTypeLike<{
|
|
57
|
+
variant: {
|
|
58
|
+
block: {
|
|
59
|
+
root: string;
|
|
60
|
+
title: string;
|
|
61
|
+
description: string;
|
|
62
|
+
action: string;
|
|
63
|
+
};
|
|
64
|
+
inline: {
|
|
65
|
+
root: string;
|
|
66
|
+
title: string;
|
|
67
|
+
action: string;
|
|
68
|
+
};
|
|
69
|
+
dashed: {
|
|
70
|
+
root: string;
|
|
71
|
+
title: string;
|
|
72
|
+
action: string;
|
|
73
|
+
};
|
|
74
|
+
};
|
|
75
|
+
}, {
|
|
76
|
+
root: string;
|
|
77
|
+
icon: string;
|
|
78
|
+
content: string;
|
|
79
|
+
title: string;
|
|
80
|
+
description: string;
|
|
81
|
+
action: string;
|
|
82
|
+
}>>;
|
|
83
|
+
type EmptyStateProps = Omit<ComponentProps<"div">, "title"> & VariantProps<typeof emptyStateVariants> & {
|
|
84
|
+
icon?: ReactNode;
|
|
85
|
+
title: ReactNode;
|
|
86
|
+
description?: ReactNode;
|
|
87
|
+
action?: ReactNode;
|
|
88
|
+
};
|
|
89
|
+
/**
|
|
90
|
+
* The one empty state. `block` fills a card or list with a centered icon, title and
|
|
91
|
+
* description; `inline` is a single muted line inside a form section; `dashed` is a
|
|
92
|
+
* short dashed panel that stands in for a missing chart.
|
|
93
|
+
*/
|
|
94
|
+
export declare function EmptyState({ icon, title, description, action, variant, className, ...props }: EmptyStateProps): import("react").JSX.Element;
|
|
95
|
+
//#endregion
|
|
96
|
+
//# sourceMappingURL=empty-state.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"empty-state.d.ts","names":[],"sources":["../../src/components/empty-state.tsx"],"mappings":";;;cAIM,gDAAkB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;KAoCnB,kBAAkB,KAAK,kCAC1B,oBAAoB;EAClB,OAAO;EACP,OAAO;EACP,cAAc;EACd,SAAS;;;;;;;wBAQG,aACd,MACA,OACA,aACA,QACA,SACA,cACG,SACF,kCAAe,IAAA"}
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import { cn, variants } from "../lib/variants.js";
|
|
2
|
+
import { descriptionClasses } from "../lib/classes.js";
|
|
3
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
4
|
+
//#region src/components/empty-state.tsx
|
|
5
|
+
const emptyStateVariants = variants({
|
|
6
|
+
slots: {
|
|
7
|
+
root: "",
|
|
8
|
+
icon: "flex size-11 items-center justify-center rounded-full bg-muted text-muted-foreground [&_svg]:size-5",
|
|
9
|
+
content: "space-y-1",
|
|
10
|
+
title: "",
|
|
11
|
+
description: descriptionClasses,
|
|
12
|
+
action: ""
|
|
13
|
+
},
|
|
14
|
+
variants: { variant: {
|
|
15
|
+
block: {
|
|
16
|
+
root: "flex flex-col items-center gap-3 px-6 py-12 text-center",
|
|
17
|
+
title: "font-medium text-sm",
|
|
18
|
+
description: "mx-auto max-w-sm",
|
|
19
|
+
action: "mt-1"
|
|
20
|
+
},
|
|
21
|
+
inline: {
|
|
22
|
+
root: "py-5",
|
|
23
|
+
title: "text-muted-foreground text-sm",
|
|
24
|
+
action: "mt-2"
|
|
25
|
+
},
|
|
26
|
+
dashed: {
|
|
27
|
+
root: "bg-dashed flex h-32 items-center justify-center rounded-lg border",
|
|
28
|
+
title: "rounded-md bg-background px-3 py-1.5 text-muted-foreground text-sm",
|
|
29
|
+
action: "mt-2"
|
|
30
|
+
}
|
|
31
|
+
} },
|
|
32
|
+
defaultVariants: { variant: "block" }
|
|
33
|
+
});
|
|
34
|
+
/**
|
|
35
|
+
* The one empty state. `block` fills a card or list with a centered icon, title and
|
|
36
|
+
* description; `inline` is a single muted line inside a form section; `dashed` is a
|
|
37
|
+
* short dashed panel that stands in for a missing chart.
|
|
38
|
+
*/
|
|
39
|
+
function EmptyState({ icon, title, description, action, variant, className, ...props }) {
|
|
40
|
+
const styles = emptyStateVariants({ variant });
|
|
41
|
+
return /* @__PURE__ */ jsxs("div", {
|
|
42
|
+
className: cn(styles.root(), className),
|
|
43
|
+
...props,
|
|
44
|
+
children: [
|
|
45
|
+
icon && /* @__PURE__ */ jsx("div", {
|
|
46
|
+
className: styles.icon(),
|
|
47
|
+
children: icon
|
|
48
|
+
}),
|
|
49
|
+
/* @__PURE__ */ jsxs("div", {
|
|
50
|
+
className: styles.content(),
|
|
51
|
+
children: [/* @__PURE__ */ jsx("p", {
|
|
52
|
+
className: styles.title(),
|
|
53
|
+
children: title
|
|
54
|
+
}), description && /* @__PURE__ */ jsx("p", {
|
|
55
|
+
className: styles.description(),
|
|
56
|
+
children: description
|
|
57
|
+
})]
|
|
58
|
+
}),
|
|
59
|
+
action && /* @__PURE__ */ jsx("div", {
|
|
60
|
+
className: styles.action(),
|
|
61
|
+
children: action
|
|
62
|
+
})
|
|
63
|
+
]
|
|
64
|
+
});
|
|
65
|
+
}
|
|
66
|
+
//#endregion
|
|
67
|
+
export { EmptyState };
|
|
68
|
+
|
|
69
|
+
//# sourceMappingURL=empty-state.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"empty-state.js","names":[],"sources":["../../src/components/empty-state.tsx"],"sourcesContent":["import type { ComponentProps, ReactNode } from \"react\"\nimport { descriptionClasses } from \"~/lib/classes\"\nimport { cn, variants, type VariantProps } from \"~/lib/variants\"\n\nconst emptyStateVariants = variants({\n slots: {\n root: \"\",\n icon: \"flex size-11 items-center justify-center rounded-full bg-muted text-muted-foreground [&_svg]:size-5\",\n content: \"space-y-1\",\n title: \"\",\n description: descriptionClasses,\n action: \"\",\n },\n\n variants: {\n variant: {\n block: {\n root: \"flex flex-col items-center gap-3 px-6 py-12 text-center\",\n title: \"font-medium text-sm\",\n description: \"mx-auto max-w-sm\",\n action: \"mt-1\",\n },\n inline: {\n root: \"py-5\",\n title: \"text-muted-foreground text-sm\",\n action: \"mt-2\",\n },\n dashed: {\n root: \"bg-dashed flex h-32 items-center justify-center rounded-lg border\",\n title: \"rounded-md bg-background px-3 py-1.5 text-muted-foreground text-sm\",\n action: \"mt-2\",\n },\n },\n },\n\n defaultVariants: {\n variant: \"block\",\n },\n})\n\ntype EmptyStateProps = Omit<ComponentProps<\"div\">, \"title\"> &\n VariantProps<typeof emptyStateVariants> & {\n icon?: ReactNode\n title: ReactNode\n description?: ReactNode\n action?: ReactNode\n }\n\n/**\n * The one empty state. `block` fills a card or list with a centered icon, title and\n * description; `inline` is a single muted line inside a form section; `dashed` is a\n * short dashed panel that stands in for a missing chart.\n */\nexport function EmptyState({\n icon,\n title,\n description,\n action,\n variant,\n className,\n ...props\n}: EmptyStateProps) {\n const styles = emptyStateVariants({ variant })\n\n return (\n <div className={cn(styles.root(), className)} {...props}>\n {icon && <div className={styles.icon()}>{icon}</div>}\n\n <div className={styles.content()}>\n <p className={styles.title()}>{title}</p>\n {description && <p className={styles.description()}>{description}</p>}\n </div>\n\n {action && <div className={styles.action()}>{action}</div>}\n </div>\n )\n}\n"],"mappings":";;;;AAIA,MAAM,qBAAqB,SAAS;CAClC,OAAO;EACL,MAAM;EACN,MAAM;EACN,SAAS;EACT,OAAO;EACP,aAAa;EACb,QAAQ;CACV;CAEA,UAAU,EACR,SAAS;EACP,OAAO;GACL,MAAM;GACN,OAAO;GACP,aAAa;GACb,QAAQ;EACV;EACA,QAAQ;GACN,MAAM;GACN,OAAO;GACP,QAAQ;EACV;EACA,QAAQ;GACN,MAAM;GACN,OAAO;GACP,QAAQ;EACV;CACF,EACF;CAEA,iBAAiB,EACf,SAAS,QACX;AACF,CAAC;;;;;;AAeD,SAAgB,WAAW,EACzB,MACA,OACA,aACA,QACA,SACA,WACA,GAAG,SACe;CAClB,MAAM,SAAS,mBAAmB,EAAE,QAAQ,CAAC;CAE7C,OACE,qBAAC,OAAD;EAAK,WAAW,GAAG,OAAO,KAAK,GAAG,SAAS;EAAG,GAAI;EAAlD,UAAA;GACG,QAAQ,oBAAC,OAAD;IAAK,WAAW,OAAO,KAAK;IAAI,UAAA;GAAU,CAAA;GAEnD,qBAAC,OAAD;IAAK,WAAW,OAAO,QAAQ;IAA/B,UAAA,CACE,oBAAC,KAAD;KAAG,WAAW,OAAO,MAAM;KAAI,UAAA;IAAS,CAAA,GACvC,eAAe,oBAAC,KAAD;KAAG,WAAW,OAAO,YAAY;KAAI,UAAA;IAAe,CAAA,CACjE;;GAEJ,UAAU,oBAAC,OAAD;IAAK,WAAW,OAAO,OAAO;IAAI,UAAA;GAAY,CAAA;EACtD;;AAET"}
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import { Avatar } from "./avatar.js";
|
|
2
|
+
import { VariantProps } from "../lib/variants.js";
|
|
3
|
+
import { ComponentProps, ReactNode } from "react";
|
|
4
|
+
//#region src/components/entity-avatar.d.ts
|
|
5
|
+
declare const entityAvatar: import("tailwind-variants").TVReturnType<{
|
|
6
|
+
size: {
|
|
7
|
+
sm: {
|
|
8
|
+
root: string;
|
|
9
|
+
image: string;
|
|
10
|
+
fallback: string;
|
|
11
|
+
};
|
|
12
|
+
md: {
|
|
13
|
+
root: string;
|
|
14
|
+
};
|
|
15
|
+
lg: {
|
|
16
|
+
root: string;
|
|
17
|
+
};
|
|
18
|
+
};
|
|
19
|
+
}, {
|
|
20
|
+
root: string;
|
|
21
|
+
image: string;
|
|
22
|
+
fallback: string;
|
|
23
|
+
}, undefined, {
|
|
24
|
+
size: {
|
|
25
|
+
sm: {
|
|
26
|
+
root: string;
|
|
27
|
+
image: string;
|
|
28
|
+
fallback: string;
|
|
29
|
+
};
|
|
30
|
+
md: {
|
|
31
|
+
root: string;
|
|
32
|
+
};
|
|
33
|
+
lg: {
|
|
34
|
+
root: string;
|
|
35
|
+
};
|
|
36
|
+
};
|
|
37
|
+
}, {
|
|
38
|
+
root: string;
|
|
39
|
+
image: string;
|
|
40
|
+
fallback: string;
|
|
41
|
+
}, import("tailwind-variants").TVReturnTypeLike<{
|
|
42
|
+
size: {
|
|
43
|
+
sm: {
|
|
44
|
+
root: string;
|
|
45
|
+
image: string;
|
|
46
|
+
fallback: string;
|
|
47
|
+
};
|
|
48
|
+
md: {
|
|
49
|
+
root: string;
|
|
50
|
+
};
|
|
51
|
+
lg: {
|
|
52
|
+
root: string;
|
|
53
|
+
};
|
|
54
|
+
};
|
|
55
|
+
}, {
|
|
56
|
+
root: string;
|
|
57
|
+
image: string;
|
|
58
|
+
fallback: string;
|
|
59
|
+
}>>;
|
|
60
|
+
type EntityAvatarProps = Omit<ComponentProps<typeof Avatar>, "className"> & VariantProps<typeof entityAvatar> & {
|
|
61
|
+
className?: string;
|
|
62
|
+
/**
|
|
63
|
+
* The image source (e.g. a favicon URL). When absent, only the fallback renders.
|
|
64
|
+
*/
|
|
65
|
+
src?: string | null;
|
|
66
|
+
/**
|
|
67
|
+
* The entity's display name; its initials are the default fallback.
|
|
68
|
+
*/
|
|
69
|
+
name: string;
|
|
70
|
+
/**
|
|
71
|
+
* Overrides the initials derived from `name`.
|
|
72
|
+
*/
|
|
73
|
+
fallback?: ReactNode;
|
|
74
|
+
};
|
|
75
|
+
export declare function EntityAvatar({ src, name, fallback, size, className, ...props }: EntityAvatarProps): import("react").JSX.Element;
|
|
76
|
+
//#endregion
|
|
77
|
+
//# sourceMappingURL=entity-avatar.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"entity-avatar.d.ts","names":[],"sources":["../../src/components/entity-avatar.tsx"],"mappings":";;;;cAyBM,0CAAY;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;KAuBb,oBAAoB,KAAK,sBAAsB,wBAClD,oBAAoB;EAClB;;;;EAKA;;;;EAKA;;;;EAKA,WAAW;;wBAGC,eACd,KACA,MACA,UACA,MACA,cACG,SACF,oCAAiB,IAAA"}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import { variants } from "../lib/variants.js";
|
|
2
|
+
import { Avatar, AvatarFallback, AvatarImage } from "./avatar.js";
|
|
3
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
4
|
+
//#region src/components/entity-avatar.tsx
|
|
5
|
+
/**
|
|
6
|
+
* The initials standing in for a missing image: a name of two characters or less as it is,
|
|
7
|
+
* otherwise the first letter of each word, capped at `max` (uncapped when `max` is 0).
|
|
8
|
+
*/
|
|
9
|
+
function getInitials(name, max = 0) {
|
|
10
|
+
const value = name.trim();
|
|
11
|
+
if (value.length <= 2) return value.toUpperCase();
|
|
12
|
+
const initials = value.split(" ").filter(Boolean).map((word) => word.charAt(0).toUpperCase()).join("");
|
|
13
|
+
return max > 0 ? initials.slice(0, max) : initials;
|
|
14
|
+
}
|
|
15
|
+
const entityAvatar = variants({
|
|
16
|
+
slots: {
|
|
17
|
+
root: "rounded-md border",
|
|
18
|
+
image: "p-[7.5%]",
|
|
19
|
+
fallback: ""
|
|
20
|
+
},
|
|
21
|
+
variants: { size: {
|
|
22
|
+
sm: {
|
|
23
|
+
root: "size-5 rounded-sm border-0",
|
|
24
|
+
image: "p-0",
|
|
25
|
+
fallback: "text-[0.625rem]"
|
|
26
|
+
},
|
|
27
|
+
md: { root: "size-9" },
|
|
28
|
+
lg: { root: "size-14" }
|
|
29
|
+
} }
|
|
30
|
+
});
|
|
31
|
+
function EntityAvatar({ src, name, fallback, size, className, ...props }) {
|
|
32
|
+
const styles = entityAvatar({ size });
|
|
33
|
+
return /* @__PURE__ */ jsxs(Avatar, {
|
|
34
|
+
className: styles.root({ className }),
|
|
35
|
+
...props,
|
|
36
|
+
children: [src && /* @__PURE__ */ jsx(AvatarImage, {
|
|
37
|
+
src,
|
|
38
|
+
className: styles.image()
|
|
39
|
+
}), /* @__PURE__ */ jsx(AvatarFallback, {
|
|
40
|
+
className: styles.fallback(),
|
|
41
|
+
children: fallback ?? getInitials(name, size === "sm" ? 2 : 3)
|
|
42
|
+
})]
|
|
43
|
+
});
|
|
44
|
+
}
|
|
45
|
+
//#endregion
|
|
46
|
+
export { EntityAvatar };
|
|
47
|
+
|
|
48
|
+
//# sourceMappingURL=entity-avatar.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"entity-avatar.js","names":[],"sources":["../../src/components/entity-avatar.tsx"],"sourcesContent":["import type { ComponentProps, ReactNode } from \"react\"\nimport { Avatar, AvatarFallback, AvatarImage } from \"~/components/avatar\"\nimport { variants, type VariantProps } from \"~/lib/variants\"\n\n/**\n * The initials standing in for a missing image: a name of two characters or less as it is,\n * otherwise the first letter of each word, capped at `max` (uncapped when `max` is 0).\n */\nfunction getInitials(name: string, max = 0) {\n const value = name.trim()\n\n if (value.length <= 2) {\n return value.toUpperCase()\n }\n\n const initials = value\n .split(\" \")\n .filter(Boolean)\n .map(word => word.charAt(0).toUpperCase())\n .join(\"\")\n\n return max > 0 ? initials.slice(0, max) : initials\n}\n\n// Radius lives on the root, which clips its children.\nconst entityAvatar = variants({\n slots: {\n root: \"rounded-md border\",\n image: \"p-[7.5%]\",\n fallback: \"\",\n },\n\n variants: {\n size: {\n // 20px: the identity mark of a nav row or menu item — borderless, flush, two initials.\n sm: {\n root: \"size-5 rounded-sm border-0\",\n image: \"p-0\",\n fallback: \"text-[0.625rem]\",\n },\n // 36px: list rows and cards.\n md: { root: \"size-9\" },\n // 56px: the logo field.\n lg: { root: \"size-14\" },\n },\n },\n})\n\ntype EntityAvatarProps = Omit<ComponentProps<typeof Avatar>, \"className\"> &\n VariantProps<typeof entityAvatar> & {\n className?: string\n\n /**\n * The image source (e.g. a favicon URL). When absent, only the fallback renders.\n */\n src?: string | null\n\n /**\n * The entity's display name; its initials are the default fallback.\n */\n name: string\n\n /**\n * Overrides the initials derived from `name`.\n */\n fallback?: ReactNode\n }\n\nexport function EntityAvatar({\n src,\n name,\n fallback,\n size,\n className,\n ...props\n}: EntityAvatarProps) {\n const styles = entityAvatar({ size })\n\n return (\n <Avatar className={styles.root({ className })} {...props}>\n {src && <AvatarImage src={src} className={styles.image()} />}\n\n <AvatarFallback className={styles.fallback()}>\n {fallback ?? getInitials(name, size === \"sm\" ? 2 : 3)}\n </AvatarFallback>\n </Avatar>\n )\n}\n"],"mappings":";;;;;;;;AAQA,SAAS,YAAY,MAAc,MAAM,GAAG;CAC1C,MAAM,QAAQ,KAAK,KAAK;CAExB,IAAI,MAAM,UAAU,GAClB,OAAO,MAAM,YAAY;CAG3B,MAAM,WAAW,MACd,MAAM,GAAG,CAAC,CACV,OAAO,OAAO,CAAC,CACf,KAAI,SAAQ,KAAK,OAAO,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CACzC,KAAK,EAAE;CAEV,OAAO,MAAM,IAAI,SAAS,MAAM,GAAG,GAAG,IAAI;AAC5C;AAGA,MAAM,eAAe,SAAS;CAC5B,OAAO;EACL,MAAM;EACN,OAAO;EACP,UAAU;CACZ;CAEA,UAAU,EACR,MAAM;EAEJ,IAAI;GACF,MAAM;GACN,OAAO;GACP,UAAU;EACZ;EAEA,IAAI,EAAE,MAAM,SAAS;EAErB,IAAI,EAAE,MAAM,UAAU;CACxB,EACF;AACF,CAAC;AAsBD,SAAgB,aAAa,EAC3B,KACA,MACA,UACA,MACA,WACA,GAAG,SACiB;CACpB,MAAM,SAAS,aAAa,EAAE,KAAK,CAAC;CAEpC,OACE,qBAAC,QAAD;EAAQ,WAAW,OAAO,KAAK,EAAE,UAAU,CAAC;EAAG,GAAI;EAAnD,UAAA,CACG,OAAO,oBAAC,aAAD;GAAkB;GAAK,WAAW,OAAO,MAAM;EAAI,CAAA,GAE3D,oBAAC,gBAAD;GAAgB,WAAW,OAAO,SAAS;GACxC,UAAA,YAAY,YAAY,MAAM,SAAS,OAAO,IAAI,CAAC;EACtC,CAAA,CACV;;AAEZ"}
|