ruler-components 0.1.1 → 0.1.3
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/dist/index.d.mts +458 -0
- package/dist/index.d.ts +458 -0
- package/dist/index.js +3618 -0
- package/dist/index.js.map +1 -0
- package/dist/index.mjs +3467 -0
- package/dist/index.mjs.map +1 -0
- package/package.json +21 -2
- package/AGENTS.md +0 -9
- package/CLAUDE.md +0 -1
- package/app/docs/[slug]/page.tsx +0 -147
- package/app/docs/layout.tsx +0 -26
- package/app/docs/page.tsx +0 -148
- package/app/favicon.ico +0 -0
- package/app/globals.css +0 -168
- package/app/icon.png +0 -0
- package/app/layout.tsx +0 -90
- package/app/opengraph-image.tsx +0 -10
- package/app/page.tsx +0 -34
- package/app/twitter-image.tsx +0 -10
- package/components/docs/accordion-doc-page.tsx +0 -352
- package/components/docs/alert-doc-page.tsx +0 -293
- package/components/docs/allinput-doc-page.tsx +0 -183
- package/components/docs/avatar-doc-page.tsx +0 -424
- package/components/docs/badge-doc-page.tsx +0 -363
- package/components/docs/button-doc-page.tsx +0 -406
- package/components/docs/card-doc-page.tsx +0 -364
- package/components/docs/checkbox-doc-page.tsx +0 -277
- package/components/docs/colors-doc-page.tsx +0 -430
- package/components/docs/dialog-doc-page.tsx +0 -364
- package/components/docs/docs-footer.tsx +0 -11
- package/components/docs/docs-mobile-menu-bar.tsx +0 -22
- package/components/docs/docs-mobile-nav-context.tsx +0 -27
- package/components/docs/docs-page.tsx +0 -263
- package/components/docs/docs-search.tsx +0 -303
- package/components/docs/docs-sidebar.tsx +0 -165
- package/components/docs/docs-topbar.tsx +0 -32
- package/components/docs/dropdown-doc-page.tsx +0 -522
- package/components/docs/getting-started-doc-page.tsx +0 -205
- package/components/docs/label-doc-page.tsx +0 -173
- package/components/docs/loaders-doc-page.tsx +0 -244
- package/components/docs/menu-doc-page.tsx +0 -373
- package/components/docs/modal-doc-page.tsx +0 -436
- package/components/docs/next-steps.tsx +0 -53
- package/components/docs/pagination-doc-page.tsx +0 -316
- package/components/docs/progress-doc-page.tsx +0 -387
- package/components/docs/radio-doc-page.tsx +0 -270
- package/components/docs/skeleton-doc-page.tsx +0 -230
- package/components/docs/stepper-doc-page.tsx +0 -309
- package/components/docs/switch-doc-page.tsx +0 -264
- package/components/docs/table-doc-page.tsx +0 -689
- package/components/docs/tabs-doc-page.tsx +0 -359
- package/components/docs/theming-doc-page.tsx +0 -243
- package/components/docs/tooltip-doc-page.tsx +0 -357
- package/components/docs/usage-section.tsx +0 -21
- package/components/icons/discord.tsx +0 -9
- package/components/icons/github.tsx +0 -9
- package/components/icons/x.tsx +0 -9
- package/components/installation-section.tsx +0 -34
- package/components/landing/feature-highlights.tsx +0 -105
- package/components/landing/footer-strip.tsx +0 -45
- package/components/landing/hero-card.tsx +0 -14
- package/components/landing/hero-spotlight.tsx +0 -126
- package/components/landing/hero.tsx +0 -64
- package/components/landing/navbar.tsx +0 -44
- package/components/landing/quick-start-section.tsx +0 -59
- package/components/landing/site-footer.tsx +0 -55
- package/components/theme-provider.tsx +0 -60
- package/components/ui/accordion.tsx +0 -174
- package/components/ui/alert.tsx +0 -103
- package/components/ui/allinput.tsx +0 -210
- package/components/ui/avatar.tsx +0 -179
- package/components/ui/badge.tsx +0 -52
- package/components/ui/button.tsx +0 -75
- package/components/ui/card.tsx +0 -105
- package/components/ui/checkbox.tsx +0 -130
- package/components/ui/code-block.tsx +0 -60
- package/components/ui/data-table.tsx +0 -235
- package/components/ui/dialog.tsx +0 -173
- package/components/ui/dropdown.tsx +0 -78
- package/components/ui/feature-card.tsx +0 -38
- package/components/ui/input.tsx +0 -44
- package/components/ui/label.tsx +0 -110
- package/components/ui/loaders.tsx +0 -139
- package/components/ui/menu.tsx +0 -118
- package/components/ui/modal.tsx +0 -399
- package/components/ui/package-manager-tabs.tsx +0 -40
- package/components/ui/pagination.tsx +0 -200
- package/components/ui/progress.tsx +0 -134
- package/components/ui/radio.tsx +0 -262
- package/components/ui/skeleton.tsx +0 -102
- package/components/ui/steppers.tsx +0 -309
- package/components/ui/switch.tsx +0 -153
- package/components/ui/table.tsx +0 -58
- package/components/ui/tabs.tsx +0 -166
- package/components/ui/theme-toggle.tsx +0 -60
- package/components/ui/tooltip.tsx +0 -238
- package/data/color-palette.ts +0 -35
- package/data/docs-nav.ts +0 -84
- package/eslint.config.mjs +0 -18
- package/index.ts +0 -8
- package/lib/cn.ts +0 -4
- package/lib/color.ts +0 -85
- package/lib/og-image.tsx +0 -138
- package/lib/theme.ts +0 -33
- package/next.config.ts +0 -7
- package/postcss.config.mjs +0 -7
- package/public/dark.png +0 -0
- package/public/dark1.png +0 -0
- package/public/dark2.png +0 -0
- package/public/file.svg +0 -1
- package/public/globe.svg +0 -1
- package/public/light.png +0 -0
- package/public/light1.png +0 -0
- package/public/next.svg +0 -1
- package/public/vercel.svg +0 -1
- package/public/video/hero-demo.mp4 +0 -0
- package/public/window.svg +0 -1
- package/tsconfig.json +0 -34
package/dist/index.js
ADDED
|
@@ -0,0 +1,3618 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
"use strict";
|
|
3
|
+
var __create = Object.create;
|
|
4
|
+
var __defProp = Object.defineProperty;
|
|
5
|
+
var __defProps = Object.defineProperties;
|
|
6
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
7
|
+
var __getOwnPropDescs = Object.getOwnPropertyDescriptors;
|
|
8
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
9
|
+
var __getOwnPropSymbols = Object.getOwnPropertySymbols;
|
|
10
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
11
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
12
|
+
var __propIsEnum = Object.prototype.propertyIsEnumerable;
|
|
13
|
+
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
14
|
+
var __spreadValues = (a, b) => {
|
|
15
|
+
for (var prop in b || (b = {}))
|
|
16
|
+
if (__hasOwnProp.call(b, prop))
|
|
17
|
+
__defNormalProp(a, prop, b[prop]);
|
|
18
|
+
if (__getOwnPropSymbols)
|
|
19
|
+
for (var prop of __getOwnPropSymbols(b)) {
|
|
20
|
+
if (__propIsEnum.call(b, prop))
|
|
21
|
+
__defNormalProp(a, prop, b[prop]);
|
|
22
|
+
}
|
|
23
|
+
return a;
|
|
24
|
+
};
|
|
25
|
+
var __spreadProps = (a, b) => __defProps(a, __getOwnPropDescs(b));
|
|
26
|
+
var __objRest = (source, exclude) => {
|
|
27
|
+
var target = {};
|
|
28
|
+
for (var prop in source)
|
|
29
|
+
if (__hasOwnProp.call(source, prop) && exclude.indexOf(prop) < 0)
|
|
30
|
+
target[prop] = source[prop];
|
|
31
|
+
if (source != null && __getOwnPropSymbols)
|
|
32
|
+
for (var prop of __getOwnPropSymbols(source)) {
|
|
33
|
+
if (exclude.indexOf(prop) < 0 && __propIsEnum.call(source, prop))
|
|
34
|
+
target[prop] = source[prop];
|
|
35
|
+
}
|
|
36
|
+
return target;
|
|
37
|
+
};
|
|
38
|
+
var __export = (target, all) => {
|
|
39
|
+
for (var name in all)
|
|
40
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
41
|
+
};
|
|
42
|
+
var __copyProps = (to, from, except, desc) => {
|
|
43
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
44
|
+
for (let key of __getOwnPropNames(from))
|
|
45
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
46
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
47
|
+
}
|
|
48
|
+
return to;
|
|
49
|
+
};
|
|
50
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
51
|
+
// If the importer is in node compatibility mode or this is not an ESM
|
|
52
|
+
// file that has been converted to a CommonJS file using a Babel-
|
|
53
|
+
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
54
|
+
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
55
|
+
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
56
|
+
mod
|
|
57
|
+
));
|
|
58
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
59
|
+
|
|
60
|
+
// index.ts
|
|
61
|
+
var index_exports = {};
|
|
62
|
+
__export(index_exports, {
|
|
63
|
+
AILoader: () => AILoader,
|
|
64
|
+
Accordion: () => Accordion,
|
|
65
|
+
AccordionItem: () => AccordionItem,
|
|
66
|
+
AccordionLink: () => AccordionLink,
|
|
67
|
+
AccordionNested: () => AccordionNested,
|
|
68
|
+
AccordionSkeletonChevron: () => AccordionSkeletonChevron,
|
|
69
|
+
AccordionSkeletonPlus: () => AccordionSkeletonPlus,
|
|
70
|
+
Alert: () => Alert,
|
|
71
|
+
Avatar: () => Avatar,
|
|
72
|
+
AvatarGroup: () => AvatarGroup,
|
|
73
|
+
Badge: () => Badge,
|
|
74
|
+
BlurReveal: () => BlurReveal,
|
|
75
|
+
BreadcrumbStepper: () => BreadcrumbStepper,
|
|
76
|
+
Button: () => Button,
|
|
77
|
+
Card: () => Card,
|
|
78
|
+
CardContent: () => CardContent,
|
|
79
|
+
CardDescription: () => CardDescription,
|
|
80
|
+
CardFooter: () => CardFooter,
|
|
81
|
+
CardHeader: () => CardHeader,
|
|
82
|
+
CardSkeletonGrid: () => CardSkeletonGrid,
|
|
83
|
+
CardTitle: () => CardTitle,
|
|
84
|
+
Checkbox: () => Checkbox,
|
|
85
|
+
CodeBlock: () => CodeBlock,
|
|
86
|
+
DataTable: () => DataTable,
|
|
87
|
+
Dialog: () => Dialog,
|
|
88
|
+
DialogAction: () => DialogAction,
|
|
89
|
+
DialogContent: () => DialogContent,
|
|
90
|
+
DialogFooter: () => DialogFooter,
|
|
91
|
+
DialogHeader: () => DialogHeader,
|
|
92
|
+
DialogItem: () => DialogItem,
|
|
93
|
+
DialogTrigger: () => DialogTrigger,
|
|
94
|
+
DotStepper: () => DotStepper,
|
|
95
|
+
DotWave: () => DotWave,
|
|
96
|
+
Dropdown: () => Dropdown,
|
|
97
|
+
DropdownContent: () => DropdownContent,
|
|
98
|
+
DropdownDivider: () => DropdownDivider,
|
|
99
|
+
DropdownItem: () => DropdownItem,
|
|
100
|
+
DropdownLabel: () => DropdownLabel,
|
|
101
|
+
DropdownTrigger: () => DropdownTrigger,
|
|
102
|
+
ExpandableRow: () => ExpandableRow,
|
|
103
|
+
FeatureCard: () => FeatureCard,
|
|
104
|
+
Field: () => Field,
|
|
105
|
+
HalfCircles: () => HalfCircles,
|
|
106
|
+
HorizontalStepper: () => HorizontalStepper,
|
|
107
|
+
Input: () => Input,
|
|
108
|
+
InputAddon: () => InputAddon,
|
|
109
|
+
InputAutocomplete: () => InputAutocomplete,
|
|
110
|
+
InputFilled: () => InputFilled,
|
|
111
|
+
InputFloating: () => InputFloating,
|
|
112
|
+
InputIcon: () => InputIcon,
|
|
113
|
+
InputOTP: () => InputOTP,
|
|
114
|
+
InputPassword: () => InputPassword,
|
|
115
|
+
InputSearch: () => InputSearch,
|
|
116
|
+
InputStandard: () => InputStandard,
|
|
117
|
+
InputUnderline: () => InputUnderline,
|
|
118
|
+
InteractiveStepper: () => InteractiveStepper,
|
|
119
|
+
Label: () => Label,
|
|
120
|
+
ListSkeleton: () => ListSkeleton,
|
|
121
|
+
LoadBar: () => LoadBar,
|
|
122
|
+
Menu: () => Menu,
|
|
123
|
+
MenuDivider: () => MenuDivider,
|
|
124
|
+
MenuItem: () => MenuItem,
|
|
125
|
+
MenuLabel: () => MenuLabel,
|
|
126
|
+
Modal: () => Modal,
|
|
127
|
+
ModalBody: () => ModalBody,
|
|
128
|
+
ModalClose: () => ModalClose,
|
|
129
|
+
ModalContent: () => ModalContent,
|
|
130
|
+
ModalDescription: () => ModalDescription,
|
|
131
|
+
ModalFooter: () => ModalFooter,
|
|
132
|
+
ModalHeader: () => ModalHeader,
|
|
133
|
+
ModalOption: () => ModalOption,
|
|
134
|
+
ModalTitle: () => ModalTitle,
|
|
135
|
+
ModalTrigger: () => ModalTrigger,
|
|
136
|
+
MorphingLoader: () => MorphingLoader,
|
|
137
|
+
OrbitLoader: () => OrbitLoader,
|
|
138
|
+
Pagination: () => Pagination,
|
|
139
|
+
Progress: () => Progress,
|
|
140
|
+
ProgressBar: () => ProgressBar,
|
|
141
|
+
ProgressRing: () => ProgressRing,
|
|
142
|
+
ProgressStepper: () => ProgressStepper,
|
|
143
|
+
PulseLoader: () => PulseLoader,
|
|
144
|
+
Radio: () => Radio,
|
|
145
|
+
RadioGroup: () => RadioGroup,
|
|
146
|
+
SegmentedStepper: () => SegmentedStepper,
|
|
147
|
+
SkeletonShimmer: () => SkeletonShimmer,
|
|
148
|
+
SpinnerDots: () => SpinnerDots,
|
|
149
|
+
SpinnerGradient: () => SpinnerGradient,
|
|
150
|
+
SquaresLoader: () => SquaresLoader,
|
|
151
|
+
Switch: () => Switch,
|
|
152
|
+
Table: () => Table,
|
|
153
|
+
TableBody: () => TableBody,
|
|
154
|
+
TableCell: () => TableCell,
|
|
155
|
+
TableHead: () => TableHead,
|
|
156
|
+
TableHeader: () => TableHeader,
|
|
157
|
+
TableRow: () => TableRow,
|
|
158
|
+
TableSkeleton: () => TableSkeleton,
|
|
159
|
+
Tabs: () => Tabs,
|
|
160
|
+
TabsContent: () => TabsContent,
|
|
161
|
+
TabsList: () => TabsList,
|
|
162
|
+
TabsTrigger: () => TabsTrigger,
|
|
163
|
+
ThreeDots: () => ThreeDots,
|
|
164
|
+
TimelineStepper: () => TimelineStepper,
|
|
165
|
+
Tooltip: () => Tooltip,
|
|
166
|
+
TypingIndicator: () => TypingIndicator,
|
|
167
|
+
VerticalStepper: () => VerticalStepper,
|
|
168
|
+
avatarVariants: () => avatarVariants,
|
|
169
|
+
badgeVariants: () => badgeVariants,
|
|
170
|
+
buttonVariants: () => buttonVariants,
|
|
171
|
+
checkboxControlVariants: () => checkboxControlVariants,
|
|
172
|
+
getGradientFromName: () => getGradientFromName,
|
|
173
|
+
getInitials: () => getInitials,
|
|
174
|
+
inputVariants: () => inputVariants,
|
|
175
|
+
labelVariants: () => labelVariants,
|
|
176
|
+
menuItemVariants: () => menuItemVariants,
|
|
177
|
+
menuVariants: () => menuVariants,
|
|
178
|
+
modalContentVariants: () => modalContentVariants,
|
|
179
|
+
overlayVariants: () => overlayVariants,
|
|
180
|
+
radioControlVariants: () => radioControlVariants
|
|
181
|
+
});
|
|
182
|
+
module.exports = __toCommonJS(index_exports);
|
|
183
|
+
|
|
184
|
+
// components/ui/accordion.tsx
|
|
185
|
+
var import_react = require("react");
|
|
186
|
+
var import_lucide_react = require("lucide-react");
|
|
187
|
+
|
|
188
|
+
// lib/cn.ts
|
|
189
|
+
var import_clsx = require("clsx");
|
|
190
|
+
var import_tailwind_merge = require("tailwind-merge");
|
|
191
|
+
var cn = (...inputs) => (0, import_tailwind_merge.twMerge)((0, import_clsx.clsx)(inputs));
|
|
192
|
+
|
|
193
|
+
// components/ui/accordion.tsx
|
|
194
|
+
var import_jsx_runtime = require("react/jsx-runtime");
|
|
195
|
+
var AccordionContext = (0, import_react.createContext)(null);
|
|
196
|
+
function useAccordionContext() {
|
|
197
|
+
const ctx = (0, import_react.useContext)(AccordionContext);
|
|
198
|
+
if (!ctx) throw new Error("Accordion components must be used inside Accordion");
|
|
199
|
+
return ctx;
|
|
200
|
+
}
|
|
201
|
+
var EASE = { transitionTimingFunction: "cubic-bezier(0.16,1,0.3,1)" };
|
|
202
|
+
function Accordion({ children, defaultValue = null, className = "" }) {
|
|
203
|
+
const [openValue, setOpenValue] = (0, import_react.useState)(defaultValue);
|
|
204
|
+
const toggle = (value) => setOpenValue((current) => current === value ? null : value);
|
|
205
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(AccordionContext.Provider, { value: { openValue, toggle }, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className, children }) });
|
|
206
|
+
}
|
|
207
|
+
function AccordionItem({ value, title, children, variant = "plus" }) {
|
|
208
|
+
const { openValue, toggle } = useAccordionContext();
|
|
209
|
+
const isOpen = openValue === value;
|
|
210
|
+
const contentRef = (0, import_react.useRef)(null);
|
|
211
|
+
const [height, setHeight] = (0, import_react.useState)(0);
|
|
212
|
+
const panelId = (0, import_react.useId)();
|
|
213
|
+
(0, import_react.useLayoutEffect)(() => {
|
|
214
|
+
if (!contentRef.current) return;
|
|
215
|
+
setHeight(isOpen ? contentRef.current.scrollHeight : 0);
|
|
216
|
+
}, [isOpen]);
|
|
217
|
+
if (variant === "chevron") {
|
|
218
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "border-b border-zinc-200 dark:border-zinc-800 last:border-0", children: [
|
|
219
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
|
|
220
|
+
"button",
|
|
221
|
+
{
|
|
222
|
+
type: "button",
|
|
223
|
+
onClick: () => toggle(value),
|
|
224
|
+
"aria-expanded": isOpen,
|
|
225
|
+
"aria-controls": panelId,
|
|
226
|
+
className: "group flex w-full items-center justify-between rounded-lg py-5 text-left outline-none transition-colors duration-200 hover:bg-zinc-50 focus-visible:ring-2 focus-visible:ring-zinc-900/15 dark:hover:bg-zinc-900/40 dark:focus-visible:ring-white/20",
|
|
227
|
+
children: [
|
|
228
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
229
|
+
"span",
|
|
230
|
+
{
|
|
231
|
+
className: cn(
|
|
232
|
+
"text-[15px] font-medium transition-colors duration-200",
|
|
233
|
+
isOpen ? "text-zinc-900 dark:text-white" : "text-zinc-600 group-hover:text-zinc-900 dark:text-zinc-400 dark:group-hover:text-zinc-200"
|
|
234
|
+
),
|
|
235
|
+
children: title
|
|
236
|
+
}
|
|
237
|
+
),
|
|
238
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
239
|
+
import_lucide_react.ChevronDown,
|
|
240
|
+
{
|
|
241
|
+
size: 18,
|
|
242
|
+
style: EASE,
|
|
243
|
+
className: cn(
|
|
244
|
+
"shrink-0 text-zinc-400 transition-transform duration-300 group-hover:text-zinc-600 dark:group-hover:text-zinc-300",
|
|
245
|
+
isOpen && "rotate-180 text-zinc-900 dark:text-white"
|
|
246
|
+
)
|
|
247
|
+
}
|
|
248
|
+
)
|
|
249
|
+
]
|
|
250
|
+
}
|
|
251
|
+
),
|
|
252
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: __spreadProps(__spreadValues({}, EASE), { height }), className: "overflow-hidden transition-[height] duration-300", children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { id: panelId, ref: contentRef, className: "pb-5 text-sm leading-relaxed text-zinc-500 dark:text-zinc-400", children }) })
|
|
253
|
+
] });
|
|
254
|
+
}
|
|
255
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "border-b border-zinc-200 dark:border-zinc-800 last:border-0", children: [
|
|
256
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
|
|
257
|
+
"button",
|
|
258
|
+
{
|
|
259
|
+
type: "button",
|
|
260
|
+
onClick: () => toggle(value),
|
|
261
|
+
"aria-expanded": isOpen,
|
|
262
|
+
"aria-controls": panelId,
|
|
263
|
+
className: "group flex w-full items-center gap-3 rounded-lg py-4 text-left outline-none transition-colors duration-200 hover:bg-zinc-50 focus-visible:ring-2 focus-visible:ring-zinc-900/15 dark:hover:bg-zinc-900/40 dark:focus-visible:ring-white/20",
|
|
264
|
+
children: [
|
|
265
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
266
|
+
"span",
|
|
267
|
+
{
|
|
268
|
+
style: EASE,
|
|
269
|
+
className: cn(
|
|
270
|
+
"flex h-6 w-6 shrink-0 items-center justify-center rounded-full border transition-all duration-300",
|
|
271
|
+
isOpen ? "border-zinc-900 bg-zinc-900 text-white shadow-sm dark:border-zinc-100 dark:bg-zinc-100 dark:text-zinc-900" : "border-zinc-300 text-zinc-400 group-hover:border-zinc-400 group-hover:text-zinc-500 dark:border-zinc-700 dark:group-hover:border-zinc-600"
|
|
272
|
+
),
|
|
273
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_lucide_react.Plus, { size: 12, style: EASE, className: cn("transition-transform duration-300", isOpen && "rotate-45") })
|
|
274
|
+
}
|
|
275
|
+
),
|
|
276
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
277
|
+
"span",
|
|
278
|
+
{
|
|
279
|
+
className: cn(
|
|
280
|
+
"text-[15px] font-medium transition-colors duration-200",
|
|
281
|
+
isOpen ? "text-zinc-900 dark:text-zinc-100" : "text-zinc-600 group-hover:text-zinc-900 dark:text-zinc-400 dark:group-hover:text-zinc-200"
|
|
282
|
+
),
|
|
283
|
+
children: title
|
|
284
|
+
}
|
|
285
|
+
)
|
|
286
|
+
]
|
|
287
|
+
}
|
|
288
|
+
),
|
|
289
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: __spreadProps(__spreadValues({}, EASE), { height }), className: "overflow-hidden transition-[height] duration-300", children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { id: panelId, ref: contentRef, className: "pb-4 pl-9 text-sm leading-relaxed text-zinc-500 dark:text-zinc-400", children }) })
|
|
290
|
+
] });
|
|
291
|
+
}
|
|
292
|
+
function AccordionNested({ title, children, level = 0 }) {
|
|
293
|
+
const [isOpen, setIsOpen] = (0, import_react.useState)(false);
|
|
294
|
+
const contentRef = (0, import_react.useRef)(null);
|
|
295
|
+
const [height, setHeight] = (0, import_react.useState)(0);
|
|
296
|
+
const panelId = (0, import_react.useId)();
|
|
297
|
+
(0, import_react.useLayoutEffect)(() => {
|
|
298
|
+
if (!contentRef.current) return;
|
|
299
|
+
setHeight(isOpen ? contentRef.current.scrollHeight : 0);
|
|
300
|
+
}, [isOpen, children]);
|
|
301
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "border-b border-zinc-100 dark:border-zinc-800 last:border-0", children: [
|
|
302
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
|
|
303
|
+
"button",
|
|
304
|
+
{
|
|
305
|
+
type: "button",
|
|
306
|
+
onClick: () => setIsOpen(!isOpen),
|
|
307
|
+
"aria-expanded": isOpen,
|
|
308
|
+
"aria-controls": panelId,
|
|
309
|
+
className: "group flex w-full items-center gap-2.5 rounded-lg py-3.5 text-left outline-none transition-colors duration-200 hover:bg-zinc-50 focus-visible:ring-2 focus-visible:ring-zinc-900/15 dark:hover:bg-zinc-900/40 dark:focus-visible:ring-white/20",
|
|
310
|
+
style: { paddingLeft: `${level * 1.5}rem` },
|
|
311
|
+
children: [
|
|
312
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
313
|
+
import_lucide_react.ChevronRight,
|
|
314
|
+
{
|
|
315
|
+
size: 15,
|
|
316
|
+
style: EASE,
|
|
317
|
+
className: cn(
|
|
318
|
+
"shrink-0 text-zinc-400 transition-transform duration-300 group-hover:text-zinc-600 dark:group-hover:text-zinc-300",
|
|
319
|
+
isOpen && "rotate-90 text-zinc-600 dark:text-zinc-300"
|
|
320
|
+
)
|
|
321
|
+
}
|
|
322
|
+
),
|
|
323
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "text-[15px] font-medium text-zinc-900 dark:text-zinc-100", children: title })
|
|
324
|
+
]
|
|
325
|
+
}
|
|
326
|
+
),
|
|
327
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: __spreadProps(__spreadValues({}, EASE), { height }), className: "overflow-hidden transition-[height] duration-300", children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { id: panelId, ref: contentRef, className: "flex flex-col", children }) })
|
|
328
|
+
] });
|
|
329
|
+
}
|
|
330
|
+
function AccordionLink({ title, level = 0 }) {
|
|
331
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "border-b border-zinc-100 dark:border-zinc-800 last:border-0", children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
332
|
+
"div",
|
|
333
|
+
{
|
|
334
|
+
className: "cursor-pointer rounded-lg py-3.5 text-[15px] font-medium text-zinc-600 transition-colors duration-200 hover:bg-zinc-50 hover:text-zinc-900 dark:text-zinc-400 dark:hover:bg-zinc-900/40 dark:hover:text-zinc-100",
|
|
335
|
+
style: { paddingLeft: `${level * 1.5 + 1.5625}rem` },
|
|
336
|
+
children: title
|
|
337
|
+
}
|
|
338
|
+
) });
|
|
339
|
+
}
|
|
340
|
+
|
|
341
|
+
// components/ui/alert.tsx
|
|
342
|
+
var import_react2 = __toESM(require("react"));
|
|
343
|
+
var import_lucide_react2 = require("lucide-react");
|
|
344
|
+
var import_jsx_runtime2 = require("react/jsx-runtime");
|
|
345
|
+
var Alert = import_react2.default.forwardRef(
|
|
346
|
+
(_a, ref) => {
|
|
347
|
+
var _b = _a, { className = "", variant = "info", title, description, dismissible, onDismiss, action, children } = _b, props = __objRest(_b, ["className", "variant", "title", "description", "dismissible", "onDismiss", "action", "children"]);
|
|
348
|
+
const configs = {
|
|
349
|
+
info: {
|
|
350
|
+
bar: "bg-[#0070BA]",
|
|
351
|
+
icon: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_lucide_react2.Info, { className: "h-5 w-5 text-[#0070BA] shrink-0" })
|
|
352
|
+
},
|
|
353
|
+
success: {
|
|
354
|
+
bar: "bg-[#28A745]",
|
|
355
|
+
icon: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_lucide_react2.CheckCircle2, { className: "h-5 w-5 text-[#28A745] shrink-0" })
|
|
356
|
+
},
|
|
357
|
+
warning: {
|
|
358
|
+
bar: "bg-[#E58E00]",
|
|
359
|
+
icon: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_lucide_react2.TriangleAlert, { className: "h-5 w-5 text-[#E58E00] shrink-0" })
|
|
360
|
+
},
|
|
361
|
+
error: {
|
|
362
|
+
bar: "bg-[#D93025]",
|
|
363
|
+
icon: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_lucide_react2.XCircle, { className: "h-5 w-5 text-[#D93025] shrink-0" })
|
|
364
|
+
}
|
|
365
|
+
};
|
|
366
|
+
const current = configs[variant];
|
|
367
|
+
return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
|
|
368
|
+
"div",
|
|
369
|
+
__spreadProps(__spreadValues({
|
|
370
|
+
ref,
|
|
371
|
+
className: `relative flex w-full min-h-[64px] items-center gap-2.5 rounded-lg border border-gray-200 bg-white px-3 py-2.5 shadow-[0_3px_12px_rgba(0,0,0,0.03)] dark:border-zinc-800 dark:bg-zinc-900 dark:shadow-none ${className}`
|
|
372
|
+
}, props), {
|
|
373
|
+
children: [
|
|
374
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
375
|
+
"div",
|
|
376
|
+
{
|
|
377
|
+
className: `absolute left-0 top-0 w-16 h-1 ${current.bar} rounded-tl-lg`,
|
|
378
|
+
style: {
|
|
379
|
+
clipPath: "polygon(0 0, 100% 0, 92% 100%, 0 100%)"
|
|
380
|
+
}
|
|
381
|
+
}
|
|
382
|
+
),
|
|
383
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: "shrink-0 flex items-center justify-center", children: current.icon }),
|
|
384
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "flex-1 min-w-0", children: [
|
|
385
|
+
title && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("h5", { className: "text-[13px] font-semibold tracking-tight text-zinc-900 dark:text-white leading-tight", children: title }),
|
|
386
|
+
description && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("p", { className: "mt-0.5 text-[11px] font-medium text-zinc-500 dark:text-zinc-300 leading-tight", children: description }),
|
|
387
|
+
children
|
|
388
|
+
] }),
|
|
389
|
+
action && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: `shrink-0 ml-auto ${dismissible || onDismiss ? "mr-5" : ""}`, children: action }),
|
|
390
|
+
(dismissible || onDismiss) && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
391
|
+
"button",
|
|
392
|
+
{
|
|
393
|
+
onClick: onDismiss,
|
|
394
|
+
className: "absolute right-2.5 top-1/2 -translate-y-1/2 text-zinc-400 hover:text-zinc-600 dark:text-zinc-500 dark:hover:text-zinc-200 transition-colors",
|
|
395
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_lucide_react2.X, { className: "h-3.5 w-3.5 stroke-[3]" })
|
|
396
|
+
}
|
|
397
|
+
)
|
|
398
|
+
]
|
|
399
|
+
})
|
|
400
|
+
);
|
|
401
|
+
}
|
|
402
|
+
);
|
|
403
|
+
Alert.displayName = "Alert";
|
|
404
|
+
|
|
405
|
+
// components/ui/allinput.tsx
|
|
406
|
+
var import_react3 = require("react");
|
|
407
|
+
var import_lucide_react3 = require("lucide-react");
|
|
408
|
+
var import_jsx_runtime3 = require("react/jsx-runtime");
|
|
409
|
+
var fieldText = "text-sm text-zinc-900 outline-none transition-all duration-150 placeholder:text-zinc-400 dark:text-zinc-100 dark:placeholder:text-zinc-500";
|
|
410
|
+
var fieldSurface = "border-zinc-200 hover:border-zinc-300 focus:border-zinc-900 focus:ring-4 focus:ring-zinc-900/5 dark:border-zinc-800 dark:hover:border-zinc-700 dark:focus:border-zinc-400 dark:focus:ring-zinc-300/10";
|
|
411
|
+
var InputStandard = (_a) => {
|
|
412
|
+
var _b = _a, { className } = _b, props = __objRest(_b, ["className"]);
|
|
413
|
+
return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
414
|
+
"input",
|
|
415
|
+
__spreadProps(__spreadValues({}, props), {
|
|
416
|
+
className: cn("w-full rounded-xl border bg-white px-4 py-2.5 dark:bg-zinc-900", fieldText, fieldSurface, className)
|
|
417
|
+
})
|
|
418
|
+
);
|
|
419
|
+
};
|
|
420
|
+
var InputFilled = (_a) => {
|
|
421
|
+
var _b = _a, { className } = _b, props = __objRest(_b, ["className"]);
|
|
422
|
+
return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
423
|
+
"input",
|
|
424
|
+
__spreadProps(__spreadValues({}, props), {
|
|
425
|
+
className: cn(
|
|
426
|
+
"w-full rounded-xl border border-transparent bg-zinc-100 px-4 py-3 hover:bg-zinc-200/70 focus:border-zinc-900 focus:bg-white focus:ring-4 focus:ring-zinc-900/5 dark:bg-zinc-800 dark:hover:bg-zinc-700/70 dark:focus:border-zinc-400 dark:focus:bg-zinc-900 dark:focus:ring-zinc-300/10",
|
|
427
|
+
fieldText,
|
|
428
|
+
className
|
|
429
|
+
)
|
|
430
|
+
})
|
|
431
|
+
);
|
|
432
|
+
};
|
|
433
|
+
var InputUnderline = (_a) => {
|
|
434
|
+
var _b = _a, { className } = _b, props = __objRest(_b, ["className"]);
|
|
435
|
+
return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "group relative", children: [
|
|
436
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
437
|
+
"input",
|
|
438
|
+
__spreadProps(__spreadValues({}, props), {
|
|
439
|
+
className: cn(
|
|
440
|
+
"w-full border-b border-zinc-200 bg-transparent py-2 focus:border-zinc-900 dark:border-zinc-700 dark:focus:border-white",
|
|
441
|
+
fieldText,
|
|
442
|
+
className
|
|
443
|
+
)
|
|
444
|
+
})
|
|
445
|
+
),
|
|
446
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { className: "absolute bottom-0 left-0 h-[2px] w-0 bg-zinc-900 transition-all duration-300 group-focus-within:w-full dark:bg-white" })
|
|
447
|
+
] });
|
|
448
|
+
};
|
|
449
|
+
var InputFloating = (_a) => {
|
|
450
|
+
var _b = _a, {
|
|
451
|
+
label,
|
|
452
|
+
className
|
|
453
|
+
} = _b, props = __objRest(_b, [
|
|
454
|
+
"label",
|
|
455
|
+
"className"
|
|
456
|
+
]);
|
|
457
|
+
const [value, setValue] = (0, import_react3.useState)("");
|
|
458
|
+
const filled = Boolean(value || props.defaultValue);
|
|
459
|
+
return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "relative pt-4", children: [
|
|
460
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
461
|
+
"input",
|
|
462
|
+
__spreadProps(__spreadValues({}, props), {
|
|
463
|
+
onChange: (e) => {
|
|
464
|
+
var _a2;
|
|
465
|
+
setValue(e.target.value);
|
|
466
|
+
(_a2 = props.onChange) == null ? void 0 : _a2.call(props, e);
|
|
467
|
+
},
|
|
468
|
+
className: cn(
|
|
469
|
+
"peer w-full border-b-2 border-zinc-200 bg-transparent py-2 focus:border-zinc-900 dark:border-zinc-700 dark:focus:border-white",
|
|
470
|
+
fieldText,
|
|
471
|
+
className
|
|
472
|
+
)
|
|
473
|
+
})
|
|
474
|
+
),
|
|
475
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
476
|
+
"label",
|
|
477
|
+
{
|
|
478
|
+
className: cn(
|
|
479
|
+
"absolute left-0 transition-all duration-200",
|
|
480
|
+
filled ? "-top-1 text-xs font-bold text-zinc-900 dark:text-white" : "top-5 text-sm text-zinc-400 peer-focus:-top-1 peer-focus:text-xs peer-focus:font-bold peer-focus:text-zinc-900 dark:peer-focus:text-white"
|
|
481
|
+
),
|
|
482
|
+
children: label
|
|
483
|
+
}
|
|
484
|
+
)
|
|
485
|
+
] });
|
|
486
|
+
};
|
|
487
|
+
var InputSearch = (_a) => {
|
|
488
|
+
var _b = _a, { className } = _b, props = __objRest(_b, ["className"]);
|
|
489
|
+
return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "group relative", children: [
|
|
490
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
491
|
+
import_lucide_react3.Search,
|
|
492
|
+
{
|
|
493
|
+
size: 16,
|
|
494
|
+
className: "absolute left-4 top-1/2 -translate-y-1/2 text-zinc-400 transition-colors group-focus-within:text-zinc-900 dark:group-focus-within:text-white"
|
|
495
|
+
}
|
|
496
|
+
),
|
|
497
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
498
|
+
"input",
|
|
499
|
+
__spreadProps(__spreadValues({}, props), {
|
|
500
|
+
type: "text",
|
|
501
|
+
className: cn(
|
|
502
|
+
"w-full rounded-full border bg-zinc-50 py-2.5 pl-11 pr-4 focus:bg-white dark:bg-zinc-900 dark:focus:bg-zinc-950",
|
|
503
|
+
fieldText,
|
|
504
|
+
fieldSurface,
|
|
505
|
+
className
|
|
506
|
+
)
|
|
507
|
+
})
|
|
508
|
+
)
|
|
509
|
+
] });
|
|
510
|
+
};
|
|
511
|
+
var InputPassword = (_a) => {
|
|
512
|
+
var _b = _a, { className } = _b, props = __objRest(_b, ["className"]);
|
|
513
|
+
const [show, setShow] = (0, import_react3.useState)(false);
|
|
514
|
+
return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "relative", children: [
|
|
515
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
516
|
+
"input",
|
|
517
|
+
__spreadProps(__spreadValues({}, props), {
|
|
518
|
+
type: show ? "text" : "password",
|
|
519
|
+
className: cn("w-full rounded-xl border bg-white px-4 py-2.5 pr-11 dark:bg-zinc-900", fieldText, fieldSurface, className)
|
|
520
|
+
})
|
|
521
|
+
),
|
|
522
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
523
|
+
"button",
|
|
524
|
+
{
|
|
525
|
+
type: "button",
|
|
526
|
+
onClick: () => setShow(!show),
|
|
527
|
+
"aria-label": show ? "Hide password" : "Show password",
|
|
528
|
+
className: "absolute right-3 top-1/2 -translate-y-1/2 text-zinc-400 transition-colors hover:text-zinc-900 dark:hover:text-white",
|
|
529
|
+
children: show ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_lucide_react3.EyeOff, { size: 18 }) : /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_lucide_react3.Eye, { size: 18 })
|
|
530
|
+
}
|
|
531
|
+
)
|
|
532
|
+
] });
|
|
533
|
+
};
|
|
534
|
+
var InputAddon = (_a) => {
|
|
535
|
+
var _b = _a, {
|
|
536
|
+
prefix,
|
|
537
|
+
suffix,
|
|
538
|
+
className
|
|
539
|
+
} = _b, props = __objRest(_b, [
|
|
540
|
+
"prefix",
|
|
541
|
+
"suffix",
|
|
542
|
+
"className"
|
|
543
|
+
]);
|
|
544
|
+
return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
|
|
545
|
+
"div",
|
|
546
|
+
{
|
|
547
|
+
className: cn(
|
|
548
|
+
"flex w-full overflow-hidden rounded-xl border border-zinc-200 bg-white transition-all focus-within:border-zinc-900 focus-within:ring-4 focus-within:ring-zinc-900/5 dark:border-zinc-800 dark:bg-zinc-900 dark:focus-within:border-zinc-400 dark:focus-within:ring-zinc-300/10",
|
|
549
|
+
className
|
|
550
|
+
),
|
|
551
|
+
children: [
|
|
552
|
+
prefix && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { className: "flex items-center border-r border-zinc-200 bg-zinc-50 px-3 text-sm font-medium text-zinc-500 dark:border-zinc-800 dark:bg-zinc-800 dark:text-zinc-400", children: prefix }),
|
|
553
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("input", __spreadProps(__spreadValues({}, props), { className: cn("flex-1 bg-transparent px-4 py-2.5", fieldText) })),
|
|
554
|
+
suffix && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { className: "flex items-center border-l border-zinc-200 bg-zinc-50 px-3 text-sm font-medium text-zinc-500 dark:border-zinc-800 dark:bg-zinc-800 dark:text-zinc-400", children: suffix })
|
|
555
|
+
]
|
|
556
|
+
}
|
|
557
|
+
);
|
|
558
|
+
};
|
|
559
|
+
var InputIcon = (_a) => {
|
|
560
|
+
var _b = _a, {
|
|
561
|
+
icon: Icon,
|
|
562
|
+
position = "left",
|
|
563
|
+
className
|
|
564
|
+
} = _b, props = __objRest(_b, [
|
|
565
|
+
"icon",
|
|
566
|
+
"position",
|
|
567
|
+
"className"
|
|
568
|
+
]);
|
|
569
|
+
return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "relative", children: [
|
|
570
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
571
|
+
"div",
|
|
572
|
+
{
|
|
573
|
+
className: cn(
|
|
574
|
+
"pointer-events-none absolute top-1/2 -translate-y-1/2 text-zinc-400",
|
|
575
|
+
position === "left" ? "left-3.5" : "right-3.5"
|
|
576
|
+
),
|
|
577
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(Icon, { size: 18, strokeWidth: 1.5 })
|
|
578
|
+
}
|
|
579
|
+
),
|
|
580
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
581
|
+
"input",
|
|
582
|
+
__spreadProps(__spreadValues({}, props), {
|
|
583
|
+
className: cn(
|
|
584
|
+
"w-full rounded-xl border bg-white py-2.5 shadow-sm dark:bg-zinc-900",
|
|
585
|
+
position === "left" ? "pl-10 pr-4" : "pl-4 pr-10",
|
|
586
|
+
fieldText,
|
|
587
|
+
fieldSurface,
|
|
588
|
+
className
|
|
589
|
+
)
|
|
590
|
+
})
|
|
591
|
+
)
|
|
592
|
+
] });
|
|
593
|
+
};
|
|
594
|
+
var InputOTP = () => /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { className: "flex gap-2.5", children: [1, 2, 3, 4].map((i) => /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
595
|
+
"input",
|
|
596
|
+
{
|
|
597
|
+
maxLength: 1,
|
|
598
|
+
"aria-label": `Digit ${i}`,
|
|
599
|
+
className: "h-12 w-12 rounded-xl border-2 border-zinc-200 bg-white text-center text-lg font-bold text-zinc-900 outline-none transition-all focus:border-zinc-900 focus:ring-4 focus:ring-zinc-900/5 dark:border-zinc-800 dark:bg-zinc-900 dark:text-white dark:focus:border-zinc-400 dark:focus:ring-zinc-300/10"
|
|
600
|
+
},
|
|
601
|
+
i
|
|
602
|
+
)) });
|
|
603
|
+
var InputAutocomplete = (_a) => {
|
|
604
|
+
var _b = _a, {
|
|
605
|
+
suggestions,
|
|
606
|
+
className
|
|
607
|
+
} = _b, props = __objRest(_b, [
|
|
608
|
+
"suggestions",
|
|
609
|
+
"className"
|
|
610
|
+
]);
|
|
611
|
+
return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "relative", children: [
|
|
612
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
613
|
+
"input",
|
|
614
|
+
__spreadProps(__spreadValues({}, props), {
|
|
615
|
+
className: cn("w-full rounded-xl border bg-white px-4 py-2.5 dark:bg-zinc-900", fieldText, fieldSurface, className)
|
|
616
|
+
})
|
|
617
|
+
),
|
|
618
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { className: "absolute top-[calc(100%+0.5rem)] z-50 w-full rounded-xl border border-zinc-200 bg-white p-1 shadow-xl dark:border-zinc-800 dark:bg-zinc-900", children: suggestions.map((s) => /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
|
|
619
|
+
"div",
|
|
620
|
+
{
|
|
621
|
+
className: "flex cursor-pointer items-center justify-between rounded-lg px-3 py-2 text-sm text-zinc-700 hover:bg-zinc-50 dark:text-zinc-200 dark:hover:bg-zinc-800",
|
|
622
|
+
children: [
|
|
623
|
+
s,
|
|
624
|
+
" ",
|
|
625
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_lucide_react3.Check, { size: 14, className: "text-zinc-400" })
|
|
626
|
+
]
|
|
627
|
+
},
|
|
628
|
+
s
|
|
629
|
+
)) })
|
|
630
|
+
] });
|
|
631
|
+
};
|
|
632
|
+
|
|
633
|
+
// components/ui/avatar.tsx
|
|
634
|
+
var React4 = __toESM(require("react"));
|
|
635
|
+
var import_class_variance_authority = require("class-variance-authority");
|
|
636
|
+
var import_jsx_runtime4 = require("react/jsx-runtime");
|
|
637
|
+
var AVATAR_GRADIENTS = [
|
|
638
|
+
"from-violet-500 to-indigo-600",
|
|
639
|
+
"from-sky-500 to-blue-600",
|
|
640
|
+
"from-emerald-500 to-teal-600",
|
|
641
|
+
"from-amber-500 to-orange-500",
|
|
642
|
+
"from-rose-500 to-pink-600",
|
|
643
|
+
"from-fuchsia-500 to-purple-600",
|
|
644
|
+
"from-cyan-500 to-blue-500",
|
|
645
|
+
"from-lime-500 to-emerald-600"
|
|
646
|
+
];
|
|
647
|
+
var avatarVariants = (0, import_class_variance_authority.cva)(
|
|
648
|
+
[
|
|
649
|
+
"relative inline-flex shrink-0 select-none items-center justify-center overflow-hidden rounded-full",
|
|
650
|
+
"ring-1 ring-zinc-900/5 shadow-sm shadow-zinc-900/10",
|
|
651
|
+
"dark:ring-white/10 dark:shadow-black/30"
|
|
652
|
+
],
|
|
653
|
+
{
|
|
654
|
+
variants: {
|
|
655
|
+
size: {
|
|
656
|
+
sm: "h-8 w-8 text-[10px]",
|
|
657
|
+
md: "h-10 w-10 text-xs",
|
|
658
|
+
lg: "h-12 w-12 text-sm",
|
|
659
|
+
xl: "h-16 w-16 text-base"
|
|
660
|
+
},
|
|
661
|
+
variant: {
|
|
662
|
+
default: "",
|
|
663
|
+
outline: "ring-2 ring-white dark:ring-zinc-950"
|
|
664
|
+
}
|
|
665
|
+
},
|
|
666
|
+
defaultVariants: {
|
|
667
|
+
size: "md",
|
|
668
|
+
variant: "default"
|
|
669
|
+
}
|
|
670
|
+
}
|
|
671
|
+
);
|
|
672
|
+
var statusVariants = (0, import_class_variance_authority.cva)(
|
|
673
|
+
[
|
|
674
|
+
"absolute rounded-full ring-2 ring-white dark:ring-zinc-950",
|
|
675
|
+
"shadow-sm"
|
|
676
|
+
],
|
|
677
|
+
{
|
|
678
|
+
variants: {
|
|
679
|
+
status: {
|
|
680
|
+
online: "bg-emerald-500",
|
|
681
|
+
offline: "bg-zinc-400 dark:bg-zinc-500",
|
|
682
|
+
busy: "bg-amber-500"
|
|
683
|
+
},
|
|
684
|
+
size: {
|
|
685
|
+
sm: "bottom-0 right-0 h-2 w-2",
|
|
686
|
+
md: "bottom-0 right-0 h-2.5 w-2.5",
|
|
687
|
+
lg: "bottom-0.5 right-0.5 h-2.5 w-2.5",
|
|
688
|
+
xl: "bottom-1 right-1 h-3 w-3"
|
|
689
|
+
}
|
|
690
|
+
}
|
|
691
|
+
}
|
|
692
|
+
);
|
|
693
|
+
function getInitials(name) {
|
|
694
|
+
const parts = name.trim().split(/\s+/).filter(Boolean);
|
|
695
|
+
if (parts.length === 0) return "?";
|
|
696
|
+
if (parts.length === 1) return parts[0].slice(0, 2).toUpperCase();
|
|
697
|
+
return `${parts[0][0]}${parts[parts.length - 1][0]}`.toUpperCase();
|
|
698
|
+
}
|
|
699
|
+
function getGradientFromName(name) {
|
|
700
|
+
let hash = 0;
|
|
701
|
+
for (let i = 0; i < name.length; i += 1) {
|
|
702
|
+
hash = name.charCodeAt(i) + ((hash << 5) - hash);
|
|
703
|
+
}
|
|
704
|
+
return AVATAR_GRADIENTS[Math.abs(hash) % AVATAR_GRADIENTS.length];
|
|
705
|
+
}
|
|
706
|
+
var Avatar = React4.forwardRef(
|
|
707
|
+
(_a, ref) => {
|
|
708
|
+
var _b = _a, { className, size, variant, src, alt, name, status, children } = _b, props = __objRest(_b, ["className", "size", "variant", "src", "alt", "name", "status", "children"]);
|
|
709
|
+
var _a2;
|
|
710
|
+
const [imageError, setImageError] = React4.useState(false);
|
|
711
|
+
const showImage = src && !imageError;
|
|
712
|
+
const fallbackText = name ? getInitials(name) : children;
|
|
713
|
+
const gradient = name ? getGradientFromName(name) : "from-zinc-400 to-zinc-500";
|
|
714
|
+
return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
|
|
715
|
+
"span",
|
|
716
|
+
__spreadProps(__spreadValues({
|
|
717
|
+
ref,
|
|
718
|
+
className: cn(avatarVariants({ size, variant }), className)
|
|
719
|
+
}, props), {
|
|
720
|
+
children: [
|
|
721
|
+
showImage ? (
|
|
722
|
+
// eslint-disable-next-line @next/next/no-img-element
|
|
723
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
724
|
+
"img",
|
|
725
|
+
{
|
|
726
|
+
src,
|
|
727
|
+
alt: (_a2 = alt != null ? alt : name) != null ? _a2 : "Avatar",
|
|
728
|
+
className: "h-full w-full object-cover",
|
|
729
|
+
onError: () => setImageError(true)
|
|
730
|
+
}
|
|
731
|
+
)
|
|
732
|
+
) : /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
733
|
+
"span",
|
|
734
|
+
{
|
|
735
|
+
className: cn(
|
|
736
|
+
"flex h-full w-full items-center justify-center bg-gradient-to-br font-semibold uppercase tracking-tight text-white",
|
|
737
|
+
gradient
|
|
738
|
+
),
|
|
739
|
+
children: fallbackText != null ? fallbackText : "?"
|
|
740
|
+
}
|
|
741
|
+
),
|
|
742
|
+
status && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
743
|
+
"span",
|
|
744
|
+
{
|
|
745
|
+
className: cn(statusVariants({ status, size })),
|
|
746
|
+
"aria-hidden": true
|
|
747
|
+
}
|
|
748
|
+
)
|
|
749
|
+
]
|
|
750
|
+
})
|
|
751
|
+
);
|
|
752
|
+
}
|
|
753
|
+
);
|
|
754
|
+
Avatar.displayName = "Avatar";
|
|
755
|
+
function AvatarGroup(_a) {
|
|
756
|
+
var _b = _a, {
|
|
757
|
+
className,
|
|
758
|
+
max = 5,
|
|
759
|
+
size = "md",
|
|
760
|
+
children
|
|
761
|
+
} = _b, props = __objRest(_b, [
|
|
762
|
+
"className",
|
|
763
|
+
"max",
|
|
764
|
+
"size",
|
|
765
|
+
"children"
|
|
766
|
+
]);
|
|
767
|
+
const avatars = React4.Children.toArray(children).filter(React4.isValidElement);
|
|
768
|
+
const visible = avatars.slice(0, max);
|
|
769
|
+
const remaining = avatars.length - visible.length;
|
|
770
|
+
return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", __spreadProps(__spreadValues({ className: cn("flex items-center", className) }, props), { children: [
|
|
771
|
+
visible.map((child, index) => /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
772
|
+
"div",
|
|
773
|
+
{
|
|
774
|
+
className: cn(
|
|
775
|
+
"relative transition-transform duration-200 hover:z-10 hover:scale-110",
|
|
776
|
+
index > 0 && "-ml-3"
|
|
777
|
+
),
|
|
778
|
+
children: child
|
|
779
|
+
},
|
|
780
|
+
index
|
|
781
|
+
)),
|
|
782
|
+
remaining > 0 && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
783
|
+
"span",
|
|
784
|
+
{
|
|
785
|
+
className: cn(
|
|
786
|
+
"-ml-3",
|
|
787
|
+
avatarVariants({ variant: "outline", size }),
|
|
788
|
+
"bg-zinc-100 text-zinc-600 ring-2 ring-white dark:bg-zinc-800 dark:text-zinc-200 dark:ring-zinc-950"
|
|
789
|
+
),
|
|
790
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("span", { className: "flex h-full w-full items-center justify-center text-[10px] font-semibold", children: [
|
|
791
|
+
"+",
|
|
792
|
+
remaining
|
|
793
|
+
] })
|
|
794
|
+
}
|
|
795
|
+
)
|
|
796
|
+
] }));
|
|
797
|
+
}
|
|
798
|
+
|
|
799
|
+
// components/ui/badge.tsx
|
|
800
|
+
var React5 = __toESM(require("react"));
|
|
801
|
+
var import_class_variance_authority2 = require("class-variance-authority");
|
|
802
|
+
var import_jsx_runtime5 = require("react/jsx-runtime");
|
|
803
|
+
var badgeVariants = (0, import_class_variance_authority2.cva)(
|
|
804
|
+
"inline-flex items-center gap-1 rounded-md font-medium transition-colors",
|
|
805
|
+
{
|
|
806
|
+
variants: {
|
|
807
|
+
variant: {
|
|
808
|
+
default: "bg-zinc-100 text-zinc-700 dark:bg-zinc-800 dark:text-zinc-200",
|
|
809
|
+
info: "bg-[#0070BA]/10 text-[#0070BA] dark:bg-[#0070BA]/20 dark:text-[#4DA3E0]",
|
|
810
|
+
success: "bg-[#28A745]/10 text-[#28A745] dark:bg-[#28A745]/20 dark:text-[#5CC975]",
|
|
811
|
+
warning: "bg-[#E58E00]/10 text-[#E58E00] dark:bg-[#E58E00]/20 dark:text-[#F5B84A]",
|
|
812
|
+
error: "bg-[#D93025]/10 text-[#D93025] dark:bg-[#D93025]/20 dark:text-[#F06B62]",
|
|
813
|
+
outline: "border border-zinc-200 bg-transparent text-zinc-700 dark:border-zinc-700 dark:text-zinc-300"
|
|
814
|
+
},
|
|
815
|
+
size: {
|
|
816
|
+
sm: "px-1.5 py-0.5 text-[10px]",
|
|
817
|
+
md: "px-2 py-0.5 text-[11px]",
|
|
818
|
+
lg: "px-2.5 py-1 text-xs"
|
|
819
|
+
}
|
|
820
|
+
},
|
|
821
|
+
defaultVariants: {
|
|
822
|
+
variant: "default",
|
|
823
|
+
size: "md"
|
|
824
|
+
}
|
|
825
|
+
}
|
|
826
|
+
);
|
|
827
|
+
var Badge = React5.forwardRef(
|
|
828
|
+
(_a, ref) => {
|
|
829
|
+
var _b = _a, { className, variant, size } = _b, props = __objRest(_b, ["className", "variant", "size"]);
|
|
830
|
+
return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
831
|
+
"span",
|
|
832
|
+
__spreadValues({
|
|
833
|
+
ref,
|
|
834
|
+
className: cn(badgeVariants({ variant, size }), className)
|
|
835
|
+
}, props)
|
|
836
|
+
);
|
|
837
|
+
}
|
|
838
|
+
);
|
|
839
|
+
Badge.displayName = "Badge";
|
|
840
|
+
|
|
841
|
+
// components/ui/button.tsx
|
|
842
|
+
var React6 = __toESM(require("react"));
|
|
843
|
+
var import_class_variance_authority3 = require("class-variance-authority");
|
|
844
|
+
var import_jsx_runtime6 = require("react/jsx-runtime");
|
|
845
|
+
var buttonVariants = (0, import_class_variance_authority3.cva)(
|
|
846
|
+
[
|
|
847
|
+
"inline-flex cursor-pointer items-center justify-center gap-2 whitespace-nowrap rounded-xl",
|
|
848
|
+
"text-sm font-medium tracking-tight",
|
|
849
|
+
"transition-[color,background-color,border-color,box-shadow,transform] duration-200 ease-[cubic-bezier(0.16,1,0.3,1)]",
|
|
850
|
+
"focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-zinc-900/15 focus-visible:ring-offset-2 focus-visible:ring-offset-white",
|
|
851
|
+
"active:scale-[0.97] active:transition-[transform] active:duration-100",
|
|
852
|
+
"disabled:pointer-events-none disabled:opacity-40 disabled:shadow-none disabled:active:scale-100",
|
|
853
|
+
"dark:focus-visible:ring-white/20 dark:focus-visible:ring-offset-zinc-950",
|
|
854
|
+
"select-none"
|
|
855
|
+
],
|
|
856
|
+
{
|
|
857
|
+
variants: {
|
|
858
|
+
variant: {
|
|
859
|
+
primary: [
|
|
860
|
+
"bg-zinc-900 text-white",
|
|
861
|
+
"shadow-[0_1px_2px_rgba(0,0,0,0.06),0_4px_12px_rgba(0,0,0,0.08)]",
|
|
862
|
+
"hover:bg-zinc-800 hover:-translate-y-0.5",
|
|
863
|
+
"hover:shadow-[0_2px_4px_rgba(0,0,0,0.06),0_8px_20px_rgba(0,0,0,0.12)]",
|
|
864
|
+
"dark:bg-zinc-100 dark:text-zinc-900",
|
|
865
|
+
"dark:shadow-[0_1px_2px_rgba(255,255,255,0.06),0_4px_16px_rgba(0,0,0,0.35)]",
|
|
866
|
+
"dark:hover:bg-white dark:hover:shadow-[0_2px_8px_rgba(0,0,0,0.25),0_8px_24px_rgba(0,0,0,0.2)]"
|
|
867
|
+
],
|
|
868
|
+
white: [
|
|
869
|
+
"border border-zinc-200/80 bg-white text-zinc-900",
|
|
870
|
+
"shadow-[0_1px_2px_rgba(0,0,0,0.04),0_4px_12px_rgba(0,0,0,0.06)]",
|
|
871
|
+
"hover:border-zinc-300 hover:bg-zinc-50 hover:-translate-y-0.5",
|
|
872
|
+
"hover:shadow-[0_2px_4px_rgba(0,0,0,0.04),0_8px_20px_rgba(0,0,0,0.1)]"
|
|
873
|
+
],
|
|
874
|
+
outline: [
|
|
875
|
+
"border border-zinc-200 bg-white/70 text-zinc-700 backdrop-blur-sm",
|
|
876
|
+
"shadow-[0_1px_2px_rgba(0,0,0,0.03)]",
|
|
877
|
+
"hover:border-zinc-300 hover:bg-white hover:text-zinc-900 hover:-translate-y-0.5",
|
|
878
|
+
"hover:shadow-[0_2px_8px_rgba(0,0,0,0.06)]",
|
|
879
|
+
"dark:border-zinc-700 dark:bg-zinc-900/40 dark:text-zinc-200 dark:shadow-none",
|
|
880
|
+
"dark:hover:border-zinc-500 dark:hover:bg-zinc-800/80 dark:hover:text-white"
|
|
881
|
+
],
|
|
882
|
+
ghost: [
|
|
883
|
+
"text-zinc-600",
|
|
884
|
+
"hover:bg-zinc-100/90 hover:text-zinc-900",
|
|
885
|
+
"dark:text-zinc-400 dark:hover:bg-zinc-800/70 dark:hover:text-zinc-100"
|
|
886
|
+
]
|
|
887
|
+
},
|
|
888
|
+
size: {
|
|
889
|
+
sm: "h-8 gap-1.5 rounded-lg px-3.5 text-xs",
|
|
890
|
+
md: "h-10 px-4",
|
|
891
|
+
lg: "h-11 px-5 text-[15px]"
|
|
892
|
+
}
|
|
893
|
+
},
|
|
894
|
+
defaultVariants: { variant: "primary", size: "md" }
|
|
895
|
+
}
|
|
896
|
+
);
|
|
897
|
+
var Button = React6.forwardRef(
|
|
898
|
+
(_a, ref) => {
|
|
899
|
+
var _b = _a, { className, variant, size } = _b, props = __objRest(_b, ["className", "variant", "size"]);
|
|
900
|
+
return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
|
|
901
|
+
"button",
|
|
902
|
+
__spreadValues({
|
|
903
|
+
ref,
|
|
904
|
+
className: cn(buttonVariants({ variant, size }), className)
|
|
905
|
+
}, props)
|
|
906
|
+
);
|
|
907
|
+
}
|
|
908
|
+
);
|
|
909
|
+
Button.displayName = "Button";
|
|
910
|
+
|
|
911
|
+
// components/ui/card.tsx
|
|
912
|
+
var React7 = __toESM(require("react"));
|
|
913
|
+
var import_class_variance_authority4 = require("class-variance-authority");
|
|
914
|
+
var import_jsx_runtime7 = require("react/jsx-runtime");
|
|
915
|
+
var cardVariants = (0, import_class_variance_authority4.cva)(
|
|
916
|
+
"rounded-2xl border bg-white text-zinc-900 transition-all duration-200 dark:bg-zinc-900 dark:text-zinc-100",
|
|
917
|
+
{
|
|
918
|
+
variants: {
|
|
919
|
+
variant: {
|
|
920
|
+
default: "border-zinc-200/70 shadow-[0_2px_8px_rgba(0,0,0,0.06)] dark:border-zinc-800/80 dark:shadow-[0_2px_8px_rgba(0,0,0,0.25)]",
|
|
921
|
+
outline: "border-zinc-200 shadow-none dark:border-zinc-800",
|
|
922
|
+
elevated: "border-zinc-200 shadow-[0_8px_30px_rgba(0,0,0,0.08)] dark:border-zinc-800 dark:shadow-[0_8px_30px_rgba(0,0,0,0.35)]",
|
|
923
|
+
interactive: "cursor-pointer border-zinc-200/70 shadow-[0_2px_8px_rgba(0,0,0,0.06)] hover:-translate-y-0.5 hover:border-zinc-300 hover:shadow-[0_8px_24px_rgba(0,0,0,0.1)] dark:border-zinc-800/80 dark:shadow-[0_2px_8px_rgba(0,0,0,0.25)] dark:hover:border-zinc-700 dark:hover:shadow-[0_8px_24px_rgba(0,0,0,0.4)]"
|
|
924
|
+
}
|
|
925
|
+
},
|
|
926
|
+
defaultVariants: { variant: "default" }
|
|
927
|
+
}
|
|
928
|
+
);
|
|
929
|
+
var Card = React7.forwardRef(
|
|
930
|
+
(_a, ref) => {
|
|
931
|
+
var _b = _a, { className, variant } = _b, props = __objRest(_b, ["className", "variant"]);
|
|
932
|
+
return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
933
|
+
"div",
|
|
934
|
+
__spreadValues({
|
|
935
|
+
ref,
|
|
936
|
+
className: cn(cardVariants({ variant }), className)
|
|
937
|
+
}, props)
|
|
938
|
+
);
|
|
939
|
+
}
|
|
940
|
+
);
|
|
941
|
+
Card.displayName = "Card";
|
|
942
|
+
var CardHeader = React7.forwardRef((_a, ref) => {
|
|
943
|
+
var _b = _a, { className } = _b, props = __objRest(_b, ["className"]);
|
|
944
|
+
return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
945
|
+
"div",
|
|
946
|
+
__spreadValues({
|
|
947
|
+
ref,
|
|
948
|
+
className: cn("flex flex-col gap-1.5 p-6", className)
|
|
949
|
+
}, props)
|
|
950
|
+
);
|
|
951
|
+
});
|
|
952
|
+
CardHeader.displayName = "CardHeader";
|
|
953
|
+
var CardTitle = React7.forwardRef((_a, ref) => {
|
|
954
|
+
var _b = _a, { className } = _b, props = __objRest(_b, ["className"]);
|
|
955
|
+
return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
956
|
+
"h3",
|
|
957
|
+
__spreadValues({
|
|
958
|
+
ref,
|
|
959
|
+
className: cn("text-base font-semibold leading-none tracking-tight text-zinc-900 dark:text-white", className)
|
|
960
|
+
}, props)
|
|
961
|
+
);
|
|
962
|
+
});
|
|
963
|
+
CardTitle.displayName = "CardTitle";
|
|
964
|
+
var CardDescription = React7.forwardRef((_a, ref) => {
|
|
965
|
+
var _b = _a, { className } = _b, props = __objRest(_b, ["className"]);
|
|
966
|
+
return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
967
|
+
"p",
|
|
968
|
+
__spreadValues({
|
|
969
|
+
ref,
|
|
970
|
+
className: cn("text-sm leading-relaxed text-zinc-500 dark:text-zinc-400", className)
|
|
971
|
+
}, props)
|
|
972
|
+
);
|
|
973
|
+
});
|
|
974
|
+
CardDescription.displayName = "CardDescription";
|
|
975
|
+
var CardContent = React7.forwardRef((_a, ref) => {
|
|
976
|
+
var _b = _a, { className } = _b, props = __objRest(_b, ["className"]);
|
|
977
|
+
return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", __spreadValues({ ref, className: cn("px-6 pb-6 pt-0", className) }, props));
|
|
978
|
+
});
|
|
979
|
+
CardContent.displayName = "CardContent";
|
|
980
|
+
var CardFooter = React7.forwardRef((_a, ref) => {
|
|
981
|
+
var _b = _a, { className } = _b, props = __objRest(_b, ["className"]);
|
|
982
|
+
return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
983
|
+
"div",
|
|
984
|
+
__spreadValues({
|
|
985
|
+
ref,
|
|
986
|
+
className: cn(
|
|
987
|
+
"flex items-center gap-2 border-t border-zinc-100 bg-zinc-50/60 px-6 py-4 dark:border-zinc-800 dark:bg-zinc-800/30",
|
|
988
|
+
className
|
|
989
|
+
)
|
|
990
|
+
}, props)
|
|
991
|
+
);
|
|
992
|
+
});
|
|
993
|
+
CardFooter.displayName = "CardFooter";
|
|
994
|
+
|
|
995
|
+
// components/ui/checkbox.tsx
|
|
996
|
+
var React8 = __toESM(require("react"));
|
|
997
|
+
var import_lucide_react4 = require("lucide-react");
|
|
998
|
+
var import_class_variance_authority5 = require("class-variance-authority");
|
|
999
|
+
var import_jsx_runtime8 = require("react/jsx-runtime");
|
|
1000
|
+
var checkboxControlVariants = (0, import_class_variance_authority5.cva)(
|
|
1001
|
+
[
|
|
1002
|
+
"pointer-events-none relative flex shrink-0 items-center justify-center rounded-[3px] border-2 bg-white transition-all duration-200",
|
|
1003
|
+
"border-zinc-500 group-hover:border-zinc-700",
|
|
1004
|
+
"peer-checked:border-zinc-900 peer-checked:bg-zinc-900",
|
|
1005
|
+
"peer-focus-visible:outline-none peer-focus-visible:ring-2 peer-focus-visible:ring-zinc-900/30 peer-focus-visible:ring-offset-2",
|
|
1006
|
+
"peer-disabled:border-zinc-300 peer-disabled:bg-zinc-100",
|
|
1007
|
+
"peer-disabled:peer-checked:border-zinc-300 peer-disabled:peer-checked:bg-zinc-300",
|
|
1008
|
+
"dark:border-zinc-500 dark:bg-zinc-900 dark:group-hover:border-zinc-400",
|
|
1009
|
+
"dark:peer-checked:border-zinc-100 dark:peer-checked:bg-zinc-100",
|
|
1010
|
+
"dark:peer-disabled:border-zinc-700 dark:peer-disabled:bg-zinc-800",
|
|
1011
|
+
"dark:peer-disabled:peer-checked:border-zinc-600 dark:peer-disabled:peer-checked:bg-zinc-600",
|
|
1012
|
+
"peer-checked:[&_svg]:scale-100 peer-checked:[&_svg]:opacity-100"
|
|
1013
|
+
],
|
|
1014
|
+
{
|
|
1015
|
+
variants: {
|
|
1016
|
+
size: {
|
|
1017
|
+
sm: "h-4 w-4 [&_svg]:h-2.5 [&_svg]:w-2.5",
|
|
1018
|
+
md: "h-[18px] w-[18px] [&_svg]:h-3 [&_svg]:w-3",
|
|
1019
|
+
lg: "h-5 w-5 [&_svg]:h-3.5 [&_svg]:w-3.5"
|
|
1020
|
+
}
|
|
1021
|
+
},
|
|
1022
|
+
defaultVariants: { size: "md" }
|
|
1023
|
+
}
|
|
1024
|
+
);
|
|
1025
|
+
var checkboxWrapperVariants = (0, import_class_variance_authority5.cva)("group flex w-full transition-colors duration-150", {
|
|
1026
|
+
variants: {
|
|
1027
|
+
variant: {
|
|
1028
|
+
inline: "gap-3",
|
|
1029
|
+
card: [
|
|
1030
|
+
"gap-3 rounded-lg border border-zinc-200 bg-white px-3.5 py-3",
|
|
1031
|
+
"hover:border-zinc-300 hover:bg-zinc-50/80",
|
|
1032
|
+
"has-[:checked]:border-zinc-900",
|
|
1033
|
+
"dark:border-zinc-800 dark:bg-zinc-900 dark:hover:border-zinc-700 dark:hover:bg-zinc-900/50",
|
|
1034
|
+
"dark:has-[:checked]:border-zinc-500"
|
|
1035
|
+
]
|
|
1036
|
+
}
|
|
1037
|
+
},
|
|
1038
|
+
defaultVariants: { variant: "inline" }
|
|
1039
|
+
});
|
|
1040
|
+
var Checkbox = React8.forwardRef(
|
|
1041
|
+
(_a, ref) => {
|
|
1042
|
+
var _b = _a, {
|
|
1043
|
+
className,
|
|
1044
|
+
size,
|
|
1045
|
+
variant = "inline",
|
|
1046
|
+
label,
|
|
1047
|
+
description,
|
|
1048
|
+
disabled,
|
|
1049
|
+
id
|
|
1050
|
+
} = _b, props = __objRest(_b, [
|
|
1051
|
+
"className",
|
|
1052
|
+
"size",
|
|
1053
|
+
"variant",
|
|
1054
|
+
"label",
|
|
1055
|
+
"description",
|
|
1056
|
+
"disabled",
|
|
1057
|
+
"id"
|
|
1058
|
+
]);
|
|
1059
|
+
const generatedId = React8.useId();
|
|
1060
|
+
const inputId = id != null ? id : generatedId;
|
|
1061
|
+
const resolvedVariant = variant === "card" || description ? "card" : "inline";
|
|
1062
|
+
const alignStart = resolvedVariant === "card" || Boolean(description);
|
|
1063
|
+
return /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(
|
|
1064
|
+
"label",
|
|
1065
|
+
{
|
|
1066
|
+
htmlFor: inputId,
|
|
1067
|
+
className: cn(
|
|
1068
|
+
checkboxWrapperVariants({ variant: resolvedVariant }),
|
|
1069
|
+
alignStart ? "items-start" : "items-center",
|
|
1070
|
+
disabled ? "cursor-not-allowed opacity-50" : "cursor-pointer",
|
|
1071
|
+
className
|
|
1072
|
+
),
|
|
1073
|
+
children: [
|
|
1074
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(
|
|
1075
|
+
"span",
|
|
1076
|
+
{
|
|
1077
|
+
className: cn(
|
|
1078
|
+
"relative flex shrink-0 items-center justify-center p-2.5 -m-2.5",
|
|
1079
|
+
alignStart ? "mt-0.5" : void 0
|
|
1080
|
+
),
|
|
1081
|
+
children: [
|
|
1082
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
1083
|
+
"input",
|
|
1084
|
+
__spreadValues({
|
|
1085
|
+
ref,
|
|
1086
|
+
id: inputId,
|
|
1087
|
+
type: "checkbox",
|
|
1088
|
+
disabled,
|
|
1089
|
+
className: "peer absolute inset-0 z-10 cursor-pointer opacity-0 disabled:cursor-not-allowed"
|
|
1090
|
+
}, props)
|
|
1091
|
+
),
|
|
1092
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
1093
|
+
"span",
|
|
1094
|
+
{
|
|
1095
|
+
"aria-hidden": true,
|
|
1096
|
+
className: "pointer-events-none absolute inset-0 rounded-full bg-zinc-900/0 transition-colors duration-200 group-hover:bg-zinc-900/[0.08] group-active:bg-zinc-900/[0.12] peer-disabled:group-hover:bg-transparent dark:group-hover:bg-white/[0.08] dark:group-active:bg-white/[0.12]"
|
|
1097
|
+
}
|
|
1098
|
+
),
|
|
1099
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("span", { className: checkboxControlVariants({ size }), children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
1100
|
+
import_lucide_react4.Check,
|
|
1101
|
+
{
|
|
1102
|
+
className: "text-white opacity-0 transition-all duration-200 dark:text-zinc-900",
|
|
1103
|
+
strokeWidth: 3
|
|
1104
|
+
}
|
|
1105
|
+
) })
|
|
1106
|
+
]
|
|
1107
|
+
}
|
|
1108
|
+
),
|
|
1109
|
+
(label || description) && /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("span", { className: "flex min-w-0 flex-1 flex-col gap-0.5", children: [
|
|
1110
|
+
label && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("span", { className: "text-sm leading-snug text-zinc-800 dark:text-zinc-100", children: label }),
|
|
1111
|
+
description && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("span", { className: "text-xs leading-relaxed text-zinc-500 dark:text-zinc-400", children: description })
|
|
1112
|
+
] })
|
|
1113
|
+
]
|
|
1114
|
+
}
|
|
1115
|
+
);
|
|
1116
|
+
}
|
|
1117
|
+
);
|
|
1118
|
+
Checkbox.displayName = "Checkbox";
|
|
1119
|
+
|
|
1120
|
+
// components/ui/code-block.tsx
|
|
1121
|
+
var import_react4 = require("react");
|
|
1122
|
+
var import_lucide_react5 = require("lucide-react");
|
|
1123
|
+
var import_jsx_runtime9 = require("react/jsx-runtime");
|
|
1124
|
+
function CodeBlock({
|
|
1125
|
+
code,
|
|
1126
|
+
filename,
|
|
1127
|
+
className
|
|
1128
|
+
}) {
|
|
1129
|
+
const [copied, setCopied] = (0, import_react4.useState)(false);
|
|
1130
|
+
const onCopy = async () => {
|
|
1131
|
+
await navigator.clipboard.writeText(code);
|
|
1132
|
+
setCopied(true);
|
|
1133
|
+
setTimeout(() => setCopied(false), 1500);
|
|
1134
|
+
};
|
|
1135
|
+
const copyButton = /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
|
|
1136
|
+
"button",
|
|
1137
|
+
{
|
|
1138
|
+
type: "button",
|
|
1139
|
+
onClick: onCopy,
|
|
1140
|
+
"aria-label": "Copy code",
|
|
1141
|
+
className: "flex h-7 w-7 items-center justify-center rounded-md text-zinc-500 transition-colors hover:bg-white/10 hover:text-zinc-200",
|
|
1142
|
+
children: copied ? /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(import_lucide_react5.Check, { className: "h-3.5 w-3.5 text-white" }) : /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(import_lucide_react5.Copy, { className: "h-3.5 w-3.5" })
|
|
1143
|
+
}
|
|
1144
|
+
);
|
|
1145
|
+
return /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(
|
|
1146
|
+
"div",
|
|
1147
|
+
{
|
|
1148
|
+
className: cn(
|
|
1149
|
+
"group relative overflow-x-auto rounded-xl bg-zinc-900 ring-1 ring-white/10",
|
|
1150
|
+
className
|
|
1151
|
+
),
|
|
1152
|
+
children: [
|
|
1153
|
+
filename ? /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { className: "flex items-center justify-between border-b border-white/10 px-4 py-2.5", children: [
|
|
1154
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)("span", { className: "font-mono text-xs text-zinc-500", children: filename }),
|
|
1155
|
+
copyButton
|
|
1156
|
+
] }) : null,
|
|
1157
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)("pre", { className: cn("max-w-full overflow-x-auto px-4 py-3.5 text-[13px] leading-relaxed text-zinc-100", !filename && "pr-12"), children: /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("code", { className: "font-mono", children: code }) }),
|
|
1158
|
+
filename ? null : /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("div", { className: "absolute right-3 top-3", children: copyButton })
|
|
1159
|
+
]
|
|
1160
|
+
}
|
|
1161
|
+
);
|
|
1162
|
+
}
|
|
1163
|
+
|
|
1164
|
+
// components/ui/data-table.tsx
|
|
1165
|
+
var import_react7 = require("react");
|
|
1166
|
+
var import_lucide_react9 = require("lucide-react");
|
|
1167
|
+
|
|
1168
|
+
// components/ui/input.tsx
|
|
1169
|
+
var React9 = __toESM(require("react"));
|
|
1170
|
+
var import_class_variance_authority6 = require("class-variance-authority");
|
|
1171
|
+
var import_jsx_runtime10 = require("react/jsx-runtime");
|
|
1172
|
+
var inputVariants = (0, import_class_variance_authority6.cva)(
|
|
1173
|
+
"flex w-full rounded-xl border bg-white px-3.5 text-sm text-zinc-900 outline-none transition-all duration-150 placeholder:text-zinc-400 disabled:cursor-not-allowed disabled:opacity-50 dark:bg-zinc-900 dark:text-zinc-100 dark:placeholder:text-zinc-500",
|
|
1174
|
+
{
|
|
1175
|
+
variants: {
|
|
1176
|
+
size: {
|
|
1177
|
+
sm: "h-8 text-xs",
|
|
1178
|
+
md: "h-10 text-sm",
|
|
1179
|
+
lg: "h-11 text-base"
|
|
1180
|
+
},
|
|
1181
|
+
state: {
|
|
1182
|
+
default: "border-zinc-200 hover:border-zinc-300 focus:border-zinc-900 focus:ring-2 focus:ring-zinc-900/10 dark:border-zinc-800 dark:hover:border-zinc-700 dark:focus:border-zinc-400 dark:focus:ring-zinc-400/15",
|
|
1183
|
+
error: "border-red-400 focus:border-red-500 focus:ring-2 focus:ring-red-500/15 dark:border-red-500/60 dark:focus:border-red-400"
|
|
1184
|
+
}
|
|
1185
|
+
},
|
|
1186
|
+
defaultVariants: {
|
|
1187
|
+
size: "md",
|
|
1188
|
+
state: "default"
|
|
1189
|
+
}
|
|
1190
|
+
}
|
|
1191
|
+
);
|
|
1192
|
+
var Input = React9.forwardRef(
|
|
1193
|
+
(_a, ref) => {
|
|
1194
|
+
var _b = _a, { className, size, state, type = "text" } = _b, props = __objRest(_b, ["className", "size", "state", "type"]);
|
|
1195
|
+
return /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
|
|
1196
|
+
"input",
|
|
1197
|
+
__spreadValues({
|
|
1198
|
+
ref,
|
|
1199
|
+
type,
|
|
1200
|
+
className: cn(inputVariants({ size, state }), className)
|
|
1201
|
+
}, props)
|
|
1202
|
+
);
|
|
1203
|
+
}
|
|
1204
|
+
);
|
|
1205
|
+
Input.displayName = "Input";
|
|
1206
|
+
|
|
1207
|
+
// components/ui/pagination.tsx
|
|
1208
|
+
var React10 = __toESM(require("react"));
|
|
1209
|
+
var import_lucide_react6 = require("lucide-react");
|
|
1210
|
+
var import_jsx_runtime11 = require("react/jsx-runtime");
|
|
1211
|
+
function getPageList(current, total, siblingCount) {
|
|
1212
|
+
const totalSlots = siblingCount * 2 + 5;
|
|
1213
|
+
if (total <= totalSlots) return Array.from({ length: total }, (_, i) => i + 1);
|
|
1214
|
+
const left = Math.max(current - siblingCount, 1);
|
|
1215
|
+
const right = Math.min(current + siblingCount, total);
|
|
1216
|
+
const pages = [1];
|
|
1217
|
+
if (left > 2) pages.push("...");
|
|
1218
|
+
for (let p = Math.max(left, 2); p <= Math.min(right, total - 1); p++) pages.push(p);
|
|
1219
|
+
if (right < total - 1) pages.push("...");
|
|
1220
|
+
if (total > 1) pages.push(total);
|
|
1221
|
+
return pages;
|
|
1222
|
+
}
|
|
1223
|
+
var navTransition = "transition-[color,background-color,border-color,box-shadow,transform,opacity,width] duration-200 ease-[cubic-bezier(0.16,1,0.3,1)]";
|
|
1224
|
+
var popIn = "animate-[pagination-pop_220ms_cubic-bezier(0.16,1,0.3,1)]";
|
|
1225
|
+
var focusRing = "focus-visible:ring-offset-white dark:focus-visible:ring-offset-zinc-900";
|
|
1226
|
+
var WIDTH_CLASSES = {
|
|
1227
|
+
small: "w-max max-w-full",
|
|
1228
|
+
half: "w-full min-w-0 sm:w-1/2 sm:min-w-max sm:max-w-full",
|
|
1229
|
+
full: "w-full min-w-0"
|
|
1230
|
+
};
|
|
1231
|
+
var BUTTON_SIZE = 32;
|
|
1232
|
+
var GAP = 4;
|
|
1233
|
+
function Pagination({
|
|
1234
|
+
page,
|
|
1235
|
+
totalPages,
|
|
1236
|
+
onPageChange,
|
|
1237
|
+
siblingCount = 1,
|
|
1238
|
+
variant = "default",
|
|
1239
|
+
size = "small",
|
|
1240
|
+
className
|
|
1241
|
+
}) {
|
|
1242
|
+
const clampedTotal = Math.max(1, totalPages);
|
|
1243
|
+
const current = Math.min(Math.max(page, 1), clampedTotal);
|
|
1244
|
+
const goTo = (p) => onPageChange(Math.min(Math.max(p, 1), clampedTotal));
|
|
1245
|
+
const pages = React10.useMemo(
|
|
1246
|
+
() => getPageList(current, clampedTotal, siblingCount),
|
|
1247
|
+
[current, clampedTotal, siblingCount]
|
|
1248
|
+
);
|
|
1249
|
+
const maxSlots = Math.min(clampedTotal, siblingCount * 2 + 5);
|
|
1250
|
+
const trackMinWidth = maxSlots * BUTTON_SIZE + (maxSlots - 1) * GAP;
|
|
1251
|
+
const trackRef = React10.useRef(null);
|
|
1252
|
+
const prevRectsRef = React10.useRef(/* @__PURE__ */ new Map());
|
|
1253
|
+
React10.useLayoutEffect(() => {
|
|
1254
|
+
const track = trackRef.current;
|
|
1255
|
+
if (!track) return;
|
|
1256
|
+
const prevRects = prevRectsRef.current;
|
|
1257
|
+
const nextRects = /* @__PURE__ */ new Map();
|
|
1258
|
+
track.querySelectorAll("[data-flip-key]").forEach((el) => {
|
|
1259
|
+
const key = el.dataset.flipKey;
|
|
1260
|
+
const rect = el.getBoundingClientRect();
|
|
1261
|
+
nextRects.set(key, rect);
|
|
1262
|
+
const prev = prevRects.get(key);
|
|
1263
|
+
if (!prev) return;
|
|
1264
|
+
const dx = prev.left - rect.left;
|
|
1265
|
+
if (Math.abs(dx) < 0.5) return;
|
|
1266
|
+
el.style.transition = "none";
|
|
1267
|
+
el.style.transform = `translateX(${dx}px)`;
|
|
1268
|
+
el.getBoundingClientRect();
|
|
1269
|
+
requestAnimationFrame(() => {
|
|
1270
|
+
el.style.transition = "transform 220ms cubic-bezier(0.16,1,0.3,1)";
|
|
1271
|
+
el.style.transform = "";
|
|
1272
|
+
});
|
|
1273
|
+
});
|
|
1274
|
+
prevRectsRef.current = nextRects;
|
|
1275
|
+
}, [pages]);
|
|
1276
|
+
if (variant === "simple") {
|
|
1277
|
+
return /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(
|
|
1278
|
+
"nav",
|
|
1279
|
+
{
|
|
1280
|
+
"aria-label": "Pagination",
|
|
1281
|
+
className: cn(
|
|
1282
|
+
"flex items-center justify-between gap-2 overflow-x-auto rounded-full border border-zinc-200/70 bg-white p-1.5 shadow-[0_2px_8px_rgba(0,0,0,0.06)] transition-[width] duration-300 ease-[cubic-bezier(0.16,1,0.3,1)] dark:border-zinc-800/80 dark:bg-zinc-900 dark:shadow-[0_2px_8px_rgba(0,0,0,0.25)]",
|
|
1283
|
+
WIDTH_CLASSES[size],
|
|
1284
|
+
className
|
|
1285
|
+
),
|
|
1286
|
+
children: [
|
|
1287
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(Button, { variant: "ghost", size: "sm", className: cn("rounded-full", navTransition, focusRing), disabled: current <= 1, onClick: () => goTo(current - 1), children: [
|
|
1288
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)(import_lucide_react6.ChevronLeft, { size: 15 }),
|
|
1289
|
+
"Previous"
|
|
1290
|
+
] }),
|
|
1291
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("p", { className: "min-w-[6.5rem] text-center text-xs tabular-nums text-zinc-500 dark:text-zinc-400", children: [
|
|
1292
|
+
"Page ",
|
|
1293
|
+
current,
|
|
1294
|
+
" of ",
|
|
1295
|
+
clampedTotal
|
|
1296
|
+
] }),
|
|
1297
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(Button, { variant: "ghost", size: "sm", className: cn("rounded-full", navTransition, focusRing), disabled: current >= clampedTotal, onClick: () => goTo(current + 1), children: [
|
|
1298
|
+
"Next",
|
|
1299
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)(import_lucide_react6.ChevronRight, { size: 15 })
|
|
1300
|
+
] })
|
|
1301
|
+
]
|
|
1302
|
+
}
|
|
1303
|
+
);
|
|
1304
|
+
}
|
|
1305
|
+
return /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(
|
|
1306
|
+
"nav",
|
|
1307
|
+
{
|
|
1308
|
+
"aria-label": "Pagination",
|
|
1309
|
+
className: cn(
|
|
1310
|
+
"flex items-center gap-1 overflow-x-auto rounded-full border border-zinc-200/70 bg-white p-1 shadow-[0_2px_8px_rgba(0,0,0,0.06)] transition-[width] duration-300 ease-[cubic-bezier(0.16,1,0.3,1)] dark:border-zinc-800/80 dark:bg-zinc-900 dark:shadow-[0_2px_8px_rgba(0,0,0,0.25)]",
|
|
1311
|
+
WIDTH_CLASSES[size],
|
|
1312
|
+
className
|
|
1313
|
+
),
|
|
1314
|
+
children: [
|
|
1315
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
|
|
1316
|
+
Button,
|
|
1317
|
+
{
|
|
1318
|
+
variant: "ghost",
|
|
1319
|
+
size: "sm",
|
|
1320
|
+
className: cn("h-8 w-8 shrink-0 rounded-full p-0", navTransition, focusRing),
|
|
1321
|
+
disabled: current <= 1,
|
|
1322
|
+
onClick: () => goTo(current - 1),
|
|
1323
|
+
"aria-label": "Previous page",
|
|
1324
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(import_lucide_react6.ChevronLeft, { size: 15 })
|
|
1325
|
+
}
|
|
1326
|
+
),
|
|
1327
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
|
|
1328
|
+
"div",
|
|
1329
|
+
{
|
|
1330
|
+
ref: trackRef,
|
|
1331
|
+
className: "flex min-w-0 flex-1 items-center justify-center gap-1",
|
|
1332
|
+
style: size === "small" ? { minWidth: trackMinWidth } : void 0,
|
|
1333
|
+
children: pages.map(
|
|
1334
|
+
(p, i) => p === "..." ? /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
|
|
1335
|
+
"span",
|
|
1336
|
+
{
|
|
1337
|
+
"data-flip-key": `e-${i}`,
|
|
1338
|
+
className: cn("flex h-8 w-8 shrink-0 items-center justify-center text-zinc-400", popIn),
|
|
1339
|
+
"aria-hidden": "true",
|
|
1340
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(import_lucide_react6.MoreHorizontal, { size: 15 })
|
|
1341
|
+
},
|
|
1342
|
+
`ellipsis-${i}`
|
|
1343
|
+
) : /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
|
|
1344
|
+
"button",
|
|
1345
|
+
{
|
|
1346
|
+
type: "button",
|
|
1347
|
+
"data-flip-key": `p-${p}`,
|
|
1348
|
+
onClick: () => goTo(p),
|
|
1349
|
+
"aria-current": current === p ? "page" : void 0,
|
|
1350
|
+
"aria-label": `Page ${p}`,
|
|
1351
|
+
className: cn(
|
|
1352
|
+
"h-8 w-8 shrink-0 cursor-pointer rounded-full text-sm font-medium tabular-nums outline-none",
|
|
1353
|
+
"focus-visible:ring-2 focus-visible:ring-zinc-900/15 focus-visible:ring-offset-2 dark:focus-visible:ring-white/20",
|
|
1354
|
+
"active:scale-90 active:transition-transform active:duration-100",
|
|
1355
|
+
navTransition,
|
|
1356
|
+
popIn,
|
|
1357
|
+
focusRing,
|
|
1358
|
+
current === p ? "bg-zinc-900 text-white shadow-[0_2px_6px_rgba(0,0,0,0.3)] dark:bg-white dark:text-zinc-900 dark:shadow-[0_2px_6px_rgba(0,0,0,0.5)]" : "text-zinc-500 hover:bg-zinc-100 hover:text-zinc-900 dark:text-zinc-400 dark:hover:bg-zinc-800 dark:hover:text-zinc-100"
|
|
1359
|
+
),
|
|
1360
|
+
children: p
|
|
1361
|
+
},
|
|
1362
|
+
p
|
|
1363
|
+
)
|
|
1364
|
+
)
|
|
1365
|
+
}
|
|
1366
|
+
),
|
|
1367
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
|
|
1368
|
+
Button,
|
|
1369
|
+
{
|
|
1370
|
+
variant: "ghost",
|
|
1371
|
+
size: "sm",
|
|
1372
|
+
className: cn("h-8 w-8 shrink-0 rounded-full p-0", navTransition, focusRing),
|
|
1373
|
+
disabled: current >= clampedTotal,
|
|
1374
|
+
onClick: () => goTo(current + 1),
|
|
1375
|
+
"aria-label": "Next page",
|
|
1376
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(import_lucide_react6.ChevronRight, { size: 15 })
|
|
1377
|
+
}
|
|
1378
|
+
)
|
|
1379
|
+
]
|
|
1380
|
+
}
|
|
1381
|
+
);
|
|
1382
|
+
}
|
|
1383
|
+
|
|
1384
|
+
// components/ui/table.tsx
|
|
1385
|
+
var import_react5 = require("react");
|
|
1386
|
+
var import_lucide_react7 = require("lucide-react");
|
|
1387
|
+
var import_jsx_runtime12 = require("react/jsx-runtime");
|
|
1388
|
+
function Table(_a) {
|
|
1389
|
+
var _b = _a, { children, className = "" } = _b, props = __objRest(_b, ["children", "className"]);
|
|
1390
|
+
return /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("div", { className: "w-full overflow-auto", children: /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("table", __spreadProps(__spreadValues({ className: `w-full caption-bottom text-sm ${className}` }, props), { children })) });
|
|
1391
|
+
}
|
|
1392
|
+
function TableHeader(_a) {
|
|
1393
|
+
var _b = _a, { children, className = "" } = _b, props = __objRest(_b, ["children", "className"]);
|
|
1394
|
+
return /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("thead", __spreadProps(__spreadValues({ className: `border-b border-zinc-200 bg-zinc-50/50 dark:border-zinc-800 dark:bg-zinc-900/50 ${className}` }, props), { children }));
|
|
1395
|
+
}
|
|
1396
|
+
function TableBody(_a) {
|
|
1397
|
+
var _b = _a, { children, className = "" } = _b, props = __objRest(_b, ["children", "className"]);
|
|
1398
|
+
return /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("tbody", __spreadProps(__spreadValues({ className: `divide-y divide-zinc-200 dark:divide-zinc-800 ${className}` }, props), { children }));
|
|
1399
|
+
}
|
|
1400
|
+
function TableRow(_a) {
|
|
1401
|
+
var _b = _a, { children, className = "" } = _b, props = __objRest(_b, ["children", "className"]);
|
|
1402
|
+
return /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("tr", __spreadProps(__spreadValues({ className: `transition-colors hover:bg-zinc-50/50 dark:hover:bg-zinc-900/50 ${className}` }, props), { children }));
|
|
1403
|
+
}
|
|
1404
|
+
function TableHead(_a) {
|
|
1405
|
+
var _b = _a, { children, className = "" } = _b, props = __objRest(_b, ["children", "className"]);
|
|
1406
|
+
return /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("th", __spreadProps(__spreadValues({ className: `h-12 px-4 text-left align-middle font-semibold text-zinc-500 dark:text-zinc-400 uppercase text-[11px] tracking-wider ${className}` }, props), { children }));
|
|
1407
|
+
}
|
|
1408
|
+
function TableCell(_a) {
|
|
1409
|
+
var _b = _a, { children, className = "" } = _b, props = __objRest(_b, ["children", "className"]);
|
|
1410
|
+
return /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("td", __spreadProps(__spreadValues({ className: `p-4 align-middle text-zinc-700 dark:text-zinc-300 ${className}` }, props), { children }));
|
|
1411
|
+
}
|
|
1412
|
+
function ExpandableRow({ title, details, children, colSpan = 10 }) {
|
|
1413
|
+
const [isExpanded, setIsExpanded] = (0, import_react5.useState)(false);
|
|
1414
|
+
return /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(import_jsx_runtime12.Fragment, { children: [
|
|
1415
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(TableRow, { className: "cursor-pointer", onClick: () => setIsExpanded(!isExpanded), children: [
|
|
1416
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)(TableCell, { className: "w-10 text-zinc-400", children: isExpanded ? /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(import_lucide_react7.ChevronUp, { size: 16 }) : /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(import_lucide_react7.ChevronDown, { size: 16 }) }),
|
|
1417
|
+
children
|
|
1418
|
+
] }),
|
|
1419
|
+
isExpanded && /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("tr", { className: "bg-zinc-50/30 dark:bg-zinc-900/30", children: /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(TableCell, { colSpan, className: "p-6 border-l-2 border-zinc-900 dark:border-white", children: details }) })
|
|
1420
|
+
] });
|
|
1421
|
+
}
|
|
1422
|
+
|
|
1423
|
+
// components/ui/dropdown.tsx
|
|
1424
|
+
var import_react6 = __toESM(require("react"));
|
|
1425
|
+
var import_lucide_react8 = require("lucide-react");
|
|
1426
|
+
var import_jsx_runtime13 = require("react/jsx-runtime");
|
|
1427
|
+
function Dropdown({ children }) {
|
|
1428
|
+
const [isOpen, setIsOpen] = (0, import_react6.useState)(false);
|
|
1429
|
+
const containerRef = (0, import_react6.useRef)(null);
|
|
1430
|
+
(0, import_react6.useEffect)(() => {
|
|
1431
|
+
const handleClickOutside = (e) => {
|
|
1432
|
+
if (containerRef.current && !containerRef.current.contains(e.target)) setIsOpen(false);
|
|
1433
|
+
};
|
|
1434
|
+
document.addEventListener("mousedown", handleClickOutside);
|
|
1435
|
+
return () => document.removeEventListener("mousedown", handleClickOutside);
|
|
1436
|
+
}, []);
|
|
1437
|
+
(0, import_react6.useEffect)(() => {
|
|
1438
|
+
if (!isOpen) return;
|
|
1439
|
+
const handleKeyDown = (e) => {
|
|
1440
|
+
if (e.key === "Escape") setIsOpen(false);
|
|
1441
|
+
};
|
|
1442
|
+
document.addEventListener("keydown", handleKeyDown);
|
|
1443
|
+
return () => document.removeEventListener("keydown", handleKeyDown);
|
|
1444
|
+
}, [isOpen]);
|
|
1445
|
+
return /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("div", { className: "relative inline-block text-left", ref: containerRef, children: import_react6.default.Children.map(children, (child) => {
|
|
1446
|
+
if (import_react6.default.isValidElement(child)) {
|
|
1447
|
+
return import_react6.default.cloneElement(child, { isOpen, setIsOpen });
|
|
1448
|
+
}
|
|
1449
|
+
return child;
|
|
1450
|
+
}) });
|
|
1451
|
+
}
|
|
1452
|
+
function DropdownTrigger({ children, isOpen, setIsOpen }) {
|
|
1453
|
+
return import_react6.default.cloneElement(children, {
|
|
1454
|
+
onClick: () => setIsOpen(!isOpen),
|
|
1455
|
+
"aria-haspopup": "menu",
|
|
1456
|
+
"aria-expanded": isOpen,
|
|
1457
|
+
className: `${children.props.className} ${isOpen ? "ring-2 ring-zinc-200 dark:ring-zinc-800" : ""}`
|
|
1458
|
+
});
|
|
1459
|
+
}
|
|
1460
|
+
function DropdownContent({ children, isOpen, className = "", align = "left" }) {
|
|
1461
|
+
if (!isOpen) return null;
|
|
1462
|
+
const alignClass = align === "right" ? "right-0" : "left-0";
|
|
1463
|
+
return /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("div", { role: "menu", className: `absolute ${alignClass} z-50 mt-2 w-56 origin-top-right rounded-lg border border-zinc-200 bg-white p-1 shadow-xl outline-none dark:border-zinc-800 dark:bg-zinc-950 ${className} animate-in fade-in zoom-in-95 duration-200`, children });
|
|
1464
|
+
}
|
|
1465
|
+
function DropdownItem({ label, icon: Icon, selected, onClick, className = "", variant = "default" }) {
|
|
1466
|
+
const baseClass = "flex w-full items-center gap-2 rounded-md px-3 py-2 text-left text-sm transition-colors outline-none cursor-pointer";
|
|
1467
|
+
const variantClass = variant === "destructive" ? "text-red-600 hover:bg-red-50 dark:hover:bg-red-950/30" : "text-zinc-700 hover:bg-zinc-100 dark:text-zinc-300 dark:hover:bg-zinc-900";
|
|
1468
|
+
return /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("button", { type: "button", role: "menuitem", className: `${baseClass} ${variantClass} ${className}`, onClick, children: [
|
|
1469
|
+
Icon && /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(Icon, { size: 16, className: "opacity-70" }),
|
|
1470
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsx)("span", { className: "flex-1", children: label }),
|
|
1471
|
+
selected && /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(import_lucide_react8.Check, { size: 14, className: "text-zinc-900 dark:text-white" })
|
|
1472
|
+
] });
|
|
1473
|
+
}
|
|
1474
|
+
function DropdownLabel({ children }) {
|
|
1475
|
+
return /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("div", { className: "px-3 py-2 text-[11px] font-bold uppercase tracking-wider text-zinc-400", children });
|
|
1476
|
+
}
|
|
1477
|
+
function DropdownDivider() {
|
|
1478
|
+
return /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("div", { role: "separator", className: "my-1 h-px bg-zinc-100 dark:bg-zinc-800" });
|
|
1479
|
+
}
|
|
1480
|
+
|
|
1481
|
+
// components/ui/data-table.tsx
|
|
1482
|
+
var import_jsx_runtime14 = require("react/jsx-runtime");
|
|
1483
|
+
function DataTable({
|
|
1484
|
+
data,
|
|
1485
|
+
columns,
|
|
1486
|
+
searchPlaceholder = "Search...",
|
|
1487
|
+
pageSize = 5,
|
|
1488
|
+
className
|
|
1489
|
+
}) {
|
|
1490
|
+
const [search, setSearch] = (0, import_react7.useState)("");
|
|
1491
|
+
const [sortKey, setSortKey] = (0, import_react7.useState)(null);
|
|
1492
|
+
const [sortDir, setSortDir] = (0, import_react7.useState)(null);
|
|
1493
|
+
const [activeFilters, setActiveFilters] = (0, import_react7.useState)({});
|
|
1494
|
+
const [page, setPage] = (0, import_react7.useState)(1);
|
|
1495
|
+
const getValue = (row, col) => col.accessor ? col.accessor(row) : row[col.key];
|
|
1496
|
+
const filterableColumns = columns.filter((c) => {
|
|
1497
|
+
var _a;
|
|
1498
|
+
return (_a = c.filterOptions) == null ? void 0 : _a.length;
|
|
1499
|
+
});
|
|
1500
|
+
const activeFilterCount = Object.values(activeFilters).filter(Boolean).length;
|
|
1501
|
+
const filtered = (0, import_react7.useMemo)(() => {
|
|
1502
|
+
let rows = data;
|
|
1503
|
+
if (search.trim()) {
|
|
1504
|
+
const q = search.trim().toLowerCase();
|
|
1505
|
+
rows = rows.filter((row) => columns.some((col) => {
|
|
1506
|
+
var _a;
|
|
1507
|
+
return String((_a = getValue(row, col)) != null ? _a : "").toLowerCase().includes(q);
|
|
1508
|
+
}));
|
|
1509
|
+
}
|
|
1510
|
+
Object.entries(activeFilters).forEach(([key, value]) => {
|
|
1511
|
+
if (!value) return;
|
|
1512
|
+
const col = columns.find((c) => c.key === key);
|
|
1513
|
+
if (!col) return;
|
|
1514
|
+
rows = rows.filter((row) => String(getValue(row, col)) === value);
|
|
1515
|
+
});
|
|
1516
|
+
return rows;
|
|
1517
|
+
}, [data, search, activeFilters]);
|
|
1518
|
+
const sorted = (0, import_react7.useMemo)(() => {
|
|
1519
|
+
if (!sortKey || !sortDir) return filtered;
|
|
1520
|
+
const col = columns.find((c) => c.key === sortKey);
|
|
1521
|
+
if (!col) return filtered;
|
|
1522
|
+
return [...filtered].sort((a, b) => {
|
|
1523
|
+
const av = getValue(a, col);
|
|
1524
|
+
const bv = getValue(b, col);
|
|
1525
|
+
if (typeof av === "number" && typeof bv === "number") return sortDir === "asc" ? av - bv : bv - av;
|
|
1526
|
+
return sortDir === "asc" ? String(av).localeCompare(String(bv)) : String(bv).localeCompare(String(av));
|
|
1527
|
+
});
|
|
1528
|
+
}, [filtered, sortKey, sortDir]);
|
|
1529
|
+
const totalPages = Math.max(1, Math.ceil(sorted.length / pageSize));
|
|
1530
|
+
const currentPage = Math.min(page, totalPages);
|
|
1531
|
+
const paged = sorted.slice((currentPage - 1) * pageSize, currentPage * pageSize);
|
|
1532
|
+
const handleSort = (col) => {
|
|
1533
|
+
if (!col.sortable) return;
|
|
1534
|
+
if (sortKey !== col.key) {
|
|
1535
|
+
setSortKey(col.key);
|
|
1536
|
+
setSortDir("asc");
|
|
1537
|
+
} else if (sortDir === "asc") {
|
|
1538
|
+
setSortDir("desc");
|
|
1539
|
+
} else {
|
|
1540
|
+
setSortKey(null);
|
|
1541
|
+
setSortDir(null);
|
|
1542
|
+
}
|
|
1543
|
+
setPage(1);
|
|
1544
|
+
};
|
|
1545
|
+
const clearAll = () => {
|
|
1546
|
+
setSearch("");
|
|
1547
|
+
setActiveFilters({});
|
|
1548
|
+
setPage(1);
|
|
1549
|
+
};
|
|
1550
|
+
return /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("div", { className: cn("w-full", className), children: [
|
|
1551
|
+
/* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("div", { className: "flex flex-col gap-3 pb-4 sm:flex-row sm:items-center sm:justify-between", children: [
|
|
1552
|
+
/* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("div", { className: "relative w-full sm:max-w-xs", children: [
|
|
1553
|
+
/* @__PURE__ */ (0, import_jsx_runtime14.jsx)(import_lucide_react9.Search, { size: 15, className: "pointer-events-none absolute left-3 top-1/2 -translate-y-1/2 text-zinc-400" }),
|
|
1554
|
+
/* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
|
|
1555
|
+
Input,
|
|
1556
|
+
{
|
|
1557
|
+
value: search,
|
|
1558
|
+
onChange: (e) => {
|
|
1559
|
+
setSearch(e.target.value);
|
|
1560
|
+
setPage(1);
|
|
1561
|
+
},
|
|
1562
|
+
placeholder: searchPlaceholder,
|
|
1563
|
+
className: "pl-9"
|
|
1564
|
+
}
|
|
1565
|
+
)
|
|
1566
|
+
] }),
|
|
1567
|
+
(filterableColumns.length > 0 || activeFilterCount > 0) && /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("div", { className: "flex flex-wrap items-center gap-2", children: [
|
|
1568
|
+
filterableColumns.map((col) => /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)(Dropdown, { children: [
|
|
1569
|
+
/* @__PURE__ */ (0, import_jsx_runtime14.jsx)(DropdownTrigger, { children: /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)(
|
|
1570
|
+
Button,
|
|
1571
|
+
{
|
|
1572
|
+
variant: "outline",
|
|
1573
|
+
size: "sm",
|
|
1574
|
+
className: cn(activeFilters[col.key] && "border-zinc-900 text-zinc-900 dark:border-zinc-100 dark:text-white"),
|
|
1575
|
+
children: [
|
|
1576
|
+
/* @__PURE__ */ (0, import_jsx_runtime14.jsx)(import_lucide_react9.Filter, { size: 13 }),
|
|
1577
|
+
activeFilters[col.key] || col.header
|
|
1578
|
+
]
|
|
1579
|
+
}
|
|
1580
|
+
) }),
|
|
1581
|
+
/* @__PURE__ */ (0, import_jsx_runtime14.jsxs)(DropdownContent, { align: "right", children: [
|
|
1582
|
+
/* @__PURE__ */ (0, import_jsx_runtime14.jsxs)(DropdownLabel, { children: [
|
|
1583
|
+
"Filter by ",
|
|
1584
|
+
col.header
|
|
1585
|
+
] }),
|
|
1586
|
+
/* @__PURE__ */ (0, import_jsx_runtime14.jsx)(DropdownItem, { label: "All", selected: !activeFilters[col.key], onClick: () => setActiveFilters((f) => __spreadProps(__spreadValues({}, f), { [col.key]: "" })) }),
|
|
1587
|
+
/* @__PURE__ */ (0, import_jsx_runtime14.jsx)(DropdownDivider, {}),
|
|
1588
|
+
col.filterOptions.map((opt) => /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
|
|
1589
|
+
DropdownItem,
|
|
1590
|
+
{
|
|
1591
|
+
label: opt,
|
|
1592
|
+
selected: activeFilters[col.key] === opt,
|
|
1593
|
+
onClick: () => {
|
|
1594
|
+
setActiveFilters((f) => __spreadProps(__spreadValues({}, f), { [col.key]: opt }));
|
|
1595
|
+
setPage(1);
|
|
1596
|
+
}
|
|
1597
|
+
},
|
|
1598
|
+
opt
|
|
1599
|
+
))
|
|
1600
|
+
] })
|
|
1601
|
+
] }, col.key)),
|
|
1602
|
+
(activeFilterCount > 0 || search) && /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)(Button, { variant: "ghost", size: "sm", onClick: clearAll, children: [
|
|
1603
|
+
/* @__PURE__ */ (0, import_jsx_runtime14.jsx)(import_lucide_react9.X, { size: 13 }),
|
|
1604
|
+
"Clear"
|
|
1605
|
+
] })
|
|
1606
|
+
] })
|
|
1607
|
+
] }),
|
|
1608
|
+
/* @__PURE__ */ (0, import_jsx_runtime14.jsx)("div", { className: "overflow-hidden rounded-xl border border-zinc-200 dark:border-zinc-800", children: /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)(Table, { children: [
|
|
1609
|
+
/* @__PURE__ */ (0, import_jsx_runtime14.jsx)(TableHeader, { children: /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(TableRow, { children: columns.map((col) => /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
|
|
1610
|
+
TableHead,
|
|
1611
|
+
{
|
|
1612
|
+
onClick: () => handleSort(col),
|
|
1613
|
+
className: cn(
|
|
1614
|
+
col.align === "right" && "text-right",
|
|
1615
|
+
col.align === "center" && "text-center",
|
|
1616
|
+
col.sortable && "cursor-pointer select-none hover:text-zinc-700 dark:hover:text-zinc-200",
|
|
1617
|
+
col.className
|
|
1618
|
+
),
|
|
1619
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)(
|
|
1620
|
+
"span",
|
|
1621
|
+
{
|
|
1622
|
+
className: cn(
|
|
1623
|
+
"inline-flex items-center gap-1",
|
|
1624
|
+
col.align === "right" && "flex-row-reverse",
|
|
1625
|
+
col.align === "center" && "justify-center"
|
|
1626
|
+
),
|
|
1627
|
+
children: [
|
|
1628
|
+
col.header,
|
|
1629
|
+
col.sortable && (sortKey === col.key ? sortDir === "asc" ? /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(import_lucide_react9.ArrowUp, { size: 12 }) : /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(import_lucide_react9.ArrowDown, { size: 12 }) : /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(import_lucide_react9.ArrowUpDown, { size: 12, className: "opacity-30" }))
|
|
1630
|
+
]
|
|
1631
|
+
}
|
|
1632
|
+
)
|
|
1633
|
+
},
|
|
1634
|
+
col.key
|
|
1635
|
+
)) }) }),
|
|
1636
|
+
/* @__PURE__ */ (0, import_jsx_runtime14.jsx)(TableBody, { children: paged.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(TableRow, { className: "hover:bg-transparent", children: /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(TableCell, { colSpan: columns.length, className: "py-10 text-center text-zinc-400", children: "No results found." }) }) : paged.map((row, i) => /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(TableRow, { children: columns.map((col) => {
|
|
1637
|
+
var _a;
|
|
1638
|
+
return /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(TableCell, { className: cn(col.align === "right" && "text-right", col.align === "center" && "text-center", col.className), children: col.render ? col.render(row) : String((_a = getValue(row, col)) != null ? _a : "") }, col.key);
|
|
1639
|
+
}) }, i)) })
|
|
1640
|
+
] }) }),
|
|
1641
|
+
/* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("div", { className: "flex flex-col-reverse items-center justify-between gap-3 pt-4 sm:flex-row", children: [
|
|
1642
|
+
/* @__PURE__ */ (0, import_jsx_runtime14.jsx)("p", { className: "text-xs text-zinc-500 dark:text-zinc-400", children: sorted.length === 0 ? "0 results" : `Showing ${(currentPage - 1) * pageSize + 1}\u2013${Math.min(currentPage * pageSize, sorted.length)} of ${sorted.length}` }),
|
|
1643
|
+
/* @__PURE__ */ (0, import_jsx_runtime14.jsx)(Pagination, { page: currentPage, totalPages, onPageChange: setPage })
|
|
1644
|
+
] })
|
|
1645
|
+
] });
|
|
1646
|
+
}
|
|
1647
|
+
|
|
1648
|
+
// components/ui/dialog.tsx
|
|
1649
|
+
var import_react8 = __toESM(require("react"));
|
|
1650
|
+
var import_react_dom = require("react-dom");
|
|
1651
|
+
var import_lucide_react10 = require("lucide-react");
|
|
1652
|
+
var import_jsx_runtime15 = require("react/jsx-runtime");
|
|
1653
|
+
var DialogContext = (0, import_react8.createContext)(null);
|
|
1654
|
+
function Dialog({ children, open, onOpenChange }) {
|
|
1655
|
+
const [isOpenState, setIsOpenState] = (0, import_react8.useState)(false);
|
|
1656
|
+
const isOpen = open !== void 0 ? open : isOpenState;
|
|
1657
|
+
const setIsOpen = onOpenChange || setIsOpenState;
|
|
1658
|
+
(0, import_react8.useEffect)(() => {
|
|
1659
|
+
if (isOpen) document.body.style.overflow = "hidden";
|
|
1660
|
+
else document.body.style.overflow = "unset";
|
|
1661
|
+
return () => {
|
|
1662
|
+
document.body.style.overflow = "unset";
|
|
1663
|
+
};
|
|
1664
|
+
}, [isOpen]);
|
|
1665
|
+
return /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(DialogContext.Provider, { value: { isOpen, setIsOpen }, children });
|
|
1666
|
+
}
|
|
1667
|
+
function DialogTrigger({ children }) {
|
|
1668
|
+
const { setIsOpen } = (0, import_react8.useContext)(DialogContext);
|
|
1669
|
+
return import_react8.default.cloneElement(children, {
|
|
1670
|
+
onClick: (e) => {
|
|
1671
|
+
var _a;
|
|
1672
|
+
if ((_a = children.props) == null ? void 0 : _a.onClick) children.props.onClick(e);
|
|
1673
|
+
setIsOpen(true);
|
|
1674
|
+
}
|
|
1675
|
+
});
|
|
1676
|
+
}
|
|
1677
|
+
function DialogContent({ children, className = "" }) {
|
|
1678
|
+
const { isOpen, setIsOpen } = (0, import_react8.useContext)(DialogContext);
|
|
1679
|
+
const [visible, setVisible] = (0, import_react8.useState)(false);
|
|
1680
|
+
(0, import_react8.useEffect)(() => {
|
|
1681
|
+
if (!isOpen) {
|
|
1682
|
+
setVisible(false);
|
|
1683
|
+
return;
|
|
1684
|
+
}
|
|
1685
|
+
const frame = requestAnimationFrame(() => setVisible(true));
|
|
1686
|
+
return () => cancelAnimationFrame(frame);
|
|
1687
|
+
}, [isOpen]);
|
|
1688
|
+
(0, import_react8.useEffect)(() => {
|
|
1689
|
+
if (!isOpen) return;
|
|
1690
|
+
const handleKeyDown = (e) => {
|
|
1691
|
+
if (e.key === "Escape") setIsOpen(false);
|
|
1692
|
+
};
|
|
1693
|
+
window.addEventListener("keydown", handleKeyDown);
|
|
1694
|
+
return () => window.removeEventListener("keydown", handleKeyDown);
|
|
1695
|
+
}, [isOpen, setIsOpen]);
|
|
1696
|
+
if (!isOpen) return null;
|
|
1697
|
+
return (0, import_react_dom.createPortal)(
|
|
1698
|
+
/* @__PURE__ */ (0, import_jsx_runtime15.jsxs)("div", { className: "fixed inset-0 z-50 flex items-center justify-center p-4", children: [
|
|
1699
|
+
/* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
|
|
1700
|
+
"div",
|
|
1701
|
+
{
|
|
1702
|
+
className: cn(
|
|
1703
|
+
"fixed inset-0 bg-zinc-900/45 backdrop-blur-[2px] transition-opacity duration-200 ease-out dark:bg-black/65",
|
|
1704
|
+
visible ? "opacity-100" : "opacity-0"
|
|
1705
|
+
),
|
|
1706
|
+
onClick: () => setIsOpen(false),
|
|
1707
|
+
"aria-hidden": true
|
|
1708
|
+
}
|
|
1709
|
+
),
|
|
1710
|
+
/* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
|
|
1711
|
+
"div",
|
|
1712
|
+
{
|
|
1713
|
+
role: "dialog",
|
|
1714
|
+
"aria-modal": "true",
|
|
1715
|
+
onClick: (e) => e.stopPropagation(),
|
|
1716
|
+
className: cn(
|
|
1717
|
+
"relative z-10 w-full max-w-md rounded-2xl border border-zinc-200/90 bg-white p-6 text-zinc-900",
|
|
1718
|
+
"shadow-[0_20px_60px_rgba(0,0,0,0.12),0_0_0_1px_rgba(0,0,0,0.04)]",
|
|
1719
|
+
"dark:border-zinc-800 dark:bg-zinc-950 dark:text-zinc-100",
|
|
1720
|
+
"dark:shadow-[0_20px_60px_rgba(0,0,0,0.5),0_0_0_1px_rgba(255,255,255,0.06)]",
|
|
1721
|
+
"transition-[opacity,transform] duration-200 ease-out",
|
|
1722
|
+
visible ? "translate-y-0 scale-100 opacity-100" : "translate-y-1 scale-[0.97] opacity-0",
|
|
1723
|
+
className
|
|
1724
|
+
),
|
|
1725
|
+
children
|
|
1726
|
+
}
|
|
1727
|
+
)
|
|
1728
|
+
] }),
|
|
1729
|
+
document.body
|
|
1730
|
+
);
|
|
1731
|
+
}
|
|
1732
|
+
function DialogHeader({ title, description }) {
|
|
1733
|
+
return /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)("div", { className: "mb-5", children: [
|
|
1734
|
+
title && /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("h2", { className: "text-[17px] font-semibold leading-snug tracking-tight text-zinc-900 dark:text-white", children: title }),
|
|
1735
|
+
description && /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("p", { className: "mt-2 text-[14px] leading-relaxed text-zinc-500 dark:text-zinc-400", children: description })
|
|
1736
|
+
] });
|
|
1737
|
+
}
|
|
1738
|
+
function DialogFooter({ children }) {
|
|
1739
|
+
return /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("div", { className: "mt-6 flex items-center justify-end gap-1", children });
|
|
1740
|
+
}
|
|
1741
|
+
function DialogAction({ label, onClick, variant = "primary" }) {
|
|
1742
|
+
const { setIsOpen } = (0, import_react8.useContext)(DialogContext);
|
|
1743
|
+
const handleClick = () => {
|
|
1744
|
+
if (onClick) onClick();
|
|
1745
|
+
setIsOpen(false);
|
|
1746
|
+
};
|
|
1747
|
+
const colorClass = variant === "destructive" ? "text-red-600 hover:bg-red-50 dark:text-red-400 dark:hover:bg-red-500/10" : "text-zinc-700 hover:bg-zinc-100 dark:text-zinc-200 dark:hover:bg-zinc-800";
|
|
1748
|
+
return /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
|
|
1749
|
+
"button",
|
|
1750
|
+
{
|
|
1751
|
+
onClick: handleClick,
|
|
1752
|
+
className: cn(
|
|
1753
|
+
"rounded-lg px-3.5 py-2 text-[13px] font-semibold tracking-tight outline-none transition-colors duration-150",
|
|
1754
|
+
"focus-visible:ring-2 focus-visible:ring-zinc-900/15 dark:focus-visible:ring-white/20",
|
|
1755
|
+
colorClass
|
|
1756
|
+
),
|
|
1757
|
+
children: label
|
|
1758
|
+
}
|
|
1759
|
+
);
|
|
1760
|
+
}
|
|
1761
|
+
function DialogItem({
|
|
1762
|
+
label,
|
|
1763
|
+
icon,
|
|
1764
|
+
onClick,
|
|
1765
|
+
variant = "account"
|
|
1766
|
+
}) {
|
|
1767
|
+
const { setIsOpen } = (0, import_react8.useContext)(DialogContext);
|
|
1768
|
+
const handleClick = () => {
|
|
1769
|
+
if (onClick) onClick();
|
|
1770
|
+
setIsOpen(false);
|
|
1771
|
+
};
|
|
1772
|
+
const iconBg = variant === "account" ? "bg-[#0070BA]/10 dark:bg-[#0070BA]/20" : "bg-zinc-100 dark:bg-zinc-800";
|
|
1773
|
+
const iconColor = variant === "account" ? "text-[#0070BA] dark:text-[#4DA3E0]" : "text-zinc-500 dark:text-zinc-400";
|
|
1774
|
+
return /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)(
|
|
1775
|
+
"button",
|
|
1776
|
+
{
|
|
1777
|
+
onClick: handleClick,
|
|
1778
|
+
className: "flex w-full items-center gap-3 rounded-lg px-3 py-2.5 text-left outline-none transition-colors duration-150 hover:bg-zinc-50 dark:hover:bg-zinc-900/60",
|
|
1779
|
+
children: [
|
|
1780
|
+
/* @__PURE__ */ (0, import_jsx_runtime15.jsx)("div", { className: cn("flex h-9 w-9 shrink-0 items-center justify-center rounded-full", iconBg, iconColor), children: icon || (variant === "account" ? /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(import_lucide_react10.User, { size: 18 }) : /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(import_lucide_react10.Plus, { size: 18 })) }),
|
|
1781
|
+
/* @__PURE__ */ (0, import_jsx_runtime15.jsx)("span", { className: "text-[14px] font-medium text-zinc-900 dark:text-white", children: label })
|
|
1782
|
+
]
|
|
1783
|
+
}
|
|
1784
|
+
);
|
|
1785
|
+
}
|
|
1786
|
+
|
|
1787
|
+
// components/ui/feature-card.tsx
|
|
1788
|
+
var import_jsx_runtime16 = require("react/jsx-runtime");
|
|
1789
|
+
function FeatureCard({
|
|
1790
|
+
icon: Icon,
|
|
1791
|
+
title,
|
|
1792
|
+
description,
|
|
1793
|
+
variant = "plain"
|
|
1794
|
+
}) {
|
|
1795
|
+
return /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)(
|
|
1796
|
+
"div",
|
|
1797
|
+
{
|
|
1798
|
+
className: cn(
|
|
1799
|
+
variant === "bordered" && "rounded-xl border border-zinc-200 p-5 dark:border-zinc-800"
|
|
1800
|
+
),
|
|
1801
|
+
children: [
|
|
1802
|
+
/* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
|
|
1803
|
+
"div",
|
|
1804
|
+
{
|
|
1805
|
+
className: cn(
|
|
1806
|
+
"mb-4 flex h-11 w-11 items-center justify-center rounded-2xl border",
|
|
1807
|
+
variant === "bordered" ? "border-zinc-200 bg-zinc-50 text-zinc-900 dark:border-white/10 dark:bg-white/[0.06] dark:text-zinc-100" : "border-zinc-800 bg-zinc-900 text-white dark:border-zinc-200 dark:bg-white dark:text-zinc-900"
|
|
1808
|
+
),
|
|
1809
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(Icon, { className: "h-5 w-5" })
|
|
1810
|
+
}
|
|
1811
|
+
),
|
|
1812
|
+
/* @__PURE__ */ (0, import_jsx_runtime16.jsx)("h3", { className: "text-base font-semibold text-zinc-900 dark:text-zinc-50", children: title }),
|
|
1813
|
+
/* @__PURE__ */ (0, import_jsx_runtime16.jsx)("p", { className: "mt-1 text-sm text-zinc-500 dark:text-zinc-400", children: description })
|
|
1814
|
+
]
|
|
1815
|
+
}
|
|
1816
|
+
);
|
|
1817
|
+
}
|
|
1818
|
+
|
|
1819
|
+
// components/ui/label.tsx
|
|
1820
|
+
var React15 = __toESM(require("react"));
|
|
1821
|
+
var import_class_variance_authority7 = require("class-variance-authority");
|
|
1822
|
+
var import_jsx_runtime17 = require("react/jsx-runtime");
|
|
1823
|
+
var labelVariants = (0, import_class_variance_authority7.cva)(
|
|
1824
|
+
"inline-flex items-center gap-1 font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-50",
|
|
1825
|
+
{
|
|
1826
|
+
variants: {
|
|
1827
|
+
variant: {
|
|
1828
|
+
default: "text-zinc-800 dark:text-zinc-100",
|
|
1829
|
+
muted: "text-zinc-500 dark:text-zinc-400"
|
|
1830
|
+
},
|
|
1831
|
+
size: {
|
|
1832
|
+
sm: "text-xs",
|
|
1833
|
+
md: "text-sm",
|
|
1834
|
+
lg: "text-[15px]"
|
|
1835
|
+
}
|
|
1836
|
+
},
|
|
1837
|
+
defaultVariants: {
|
|
1838
|
+
variant: "default",
|
|
1839
|
+
size: "md"
|
|
1840
|
+
}
|
|
1841
|
+
}
|
|
1842
|
+
);
|
|
1843
|
+
var Label = React15.forwardRef(
|
|
1844
|
+
(_a, ref) => {
|
|
1845
|
+
var _b = _a, { className, variant, size, required, optional, hint, error, children } = _b, props = __objRest(_b, ["className", "variant", "size", "required", "optional", "hint", "error", "children"]);
|
|
1846
|
+
return /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)("div", { className: "flex w-full flex-col gap-1.5", children: [
|
|
1847
|
+
/* @__PURE__ */ (0, import_jsx_runtime17.jsxs)("div", { className: "flex items-center justify-between gap-2", children: [
|
|
1848
|
+
/* @__PURE__ */ (0, import_jsx_runtime17.jsxs)(
|
|
1849
|
+
"label",
|
|
1850
|
+
__spreadProps(__spreadValues({
|
|
1851
|
+
ref,
|
|
1852
|
+
className: cn(labelVariants({ variant, size }), className)
|
|
1853
|
+
}, props), {
|
|
1854
|
+
children: [
|
|
1855
|
+
children,
|
|
1856
|
+
required && /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("span", { className: "text-red-500", "aria-label": "required", children: "*" })
|
|
1857
|
+
]
|
|
1858
|
+
})
|
|
1859
|
+
),
|
|
1860
|
+
optional && /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("span", { className: "text-xs text-zinc-400 dark:text-zinc-500", children: "Optional" })
|
|
1861
|
+
] }),
|
|
1862
|
+
hint && !error && /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("p", { className: "text-xs leading-relaxed text-zinc-500 dark:text-zinc-400", children: hint }),
|
|
1863
|
+
error && /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("p", { className: "text-xs leading-relaxed text-red-500 dark:text-red-400", role: "alert", children: error })
|
|
1864
|
+
] });
|
|
1865
|
+
}
|
|
1866
|
+
);
|
|
1867
|
+
Label.displayName = "Label";
|
|
1868
|
+
function Field(_a) {
|
|
1869
|
+
var _b = _a, {
|
|
1870
|
+
className,
|
|
1871
|
+
label,
|
|
1872
|
+
htmlFor,
|
|
1873
|
+
required,
|
|
1874
|
+
optional,
|
|
1875
|
+
hint,
|
|
1876
|
+
error,
|
|
1877
|
+
labelSize = "md",
|
|
1878
|
+
children
|
|
1879
|
+
} = _b, props = __objRest(_b, [
|
|
1880
|
+
"className",
|
|
1881
|
+
"label",
|
|
1882
|
+
"htmlFor",
|
|
1883
|
+
"required",
|
|
1884
|
+
"optional",
|
|
1885
|
+
"hint",
|
|
1886
|
+
"error",
|
|
1887
|
+
"labelSize",
|
|
1888
|
+
"children"
|
|
1889
|
+
]);
|
|
1890
|
+
return /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)("div", __spreadProps(__spreadValues({ className: cn("flex w-full flex-col gap-2", className) }, props), { children: [
|
|
1891
|
+
/* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
|
|
1892
|
+
Label,
|
|
1893
|
+
{
|
|
1894
|
+
htmlFor,
|
|
1895
|
+
required,
|
|
1896
|
+
optional,
|
|
1897
|
+
hint,
|
|
1898
|
+
error,
|
|
1899
|
+
size: labelSize,
|
|
1900
|
+
children: label
|
|
1901
|
+
}
|
|
1902
|
+
),
|
|
1903
|
+
children
|
|
1904
|
+
] }));
|
|
1905
|
+
}
|
|
1906
|
+
|
|
1907
|
+
// components/ui/loaders.tsx
|
|
1908
|
+
var import_lucide_react11 = require("lucide-react");
|
|
1909
|
+
var import_jsx_runtime18 = require("react/jsx-runtime");
|
|
1910
|
+
var LoaderStyles = () => /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("style", { dangerouslySetInnerHTML: { __html: `
|
|
1911
|
+
@keyframes shimmer { 100% { transform: translateX(100%); } }
|
|
1912
|
+
@keyframes progressLoad { 0% { transform: scaleX(0); } 50% { transform: scaleX(0.5); } 100% { transform: scaleX(1); } }
|
|
1913
|
+
@keyframes morphShape { 0%, 100% { border-radius: 8px; transform: rotate(0deg); } 50% { border-radius: 50%; transform: rotate(180deg); } }
|
|
1914
|
+
@keyframes blurReveal { 0% { filter: blur(10px); opacity: 0; transform: translateY(10px); } 100% { filter: blur(0); opacity: 1; transform: translateY(0); } }
|
|
1915
|
+
@keyframes spinDots { 0%, 100% { opacity: 0.2; } 50% { opacity: 1; } }
|
|
1916
|
+
@keyframes squareMove { 0%, 100% { transform: scale(1); opacity: 1; } 50% { transform: scale(0.6); opacity: 0.4; } }
|
|
1917
|
+
@keyframes loadBarMove { 0% { left: -100%; } 100% { left: 100%; } }
|
|
1918
|
+
` } });
|
|
1919
|
+
var SkeletonShimmer = ({ className }) => /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)("div", { className: cn("relative overflow-hidden rounded-md bg-zinc-100 dark:bg-zinc-800", className), children: [
|
|
1920
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsx)(LoaderStyles, {}),
|
|
1921
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsx)("div", { className: "absolute inset-0 -translate-x-full bg-gradient-to-r from-transparent via-white/40 to-transparent dark:via-white/5", style: { animation: "shimmer 2s infinite" } })
|
|
1922
|
+
] });
|
|
1923
|
+
var ProgressRing = () => /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)("svg", { className: "h-10 w-10 animate-spin text-zinc-900 dark:text-white", viewBox: "0 0 32 32", children: [
|
|
1924
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsx)("circle", { className: "opacity-10", cx: "16", cy: "16", r: "14", stroke: "currentColor", strokeWidth: "3", fill: "none" }),
|
|
1925
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsx)("path", { className: "opacity-100", fill: "none", stroke: "currentColor", strokeWidth: "3", strokeLinecap: "round", d: "M16 2 A14 14 0 0 1 30 16" })
|
|
1926
|
+
] });
|
|
1927
|
+
var SpinnerGradient = () => /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("div", { className: "h-10 w-10 rounded-full border-4 border-zinc-100 dark:border-zinc-800 border-t-zinc-900 dark:border-t-white animate-spin" });
|
|
1928
|
+
var SpinnerDots = () => /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("div", { className: "relative h-10 w-10", children: [...Array(8)].map((_, i) => /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("div", { className: "absolute top-0 left-0 w-full h-full", style: { transform: `rotate(${i * 45}deg)` }, children: /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("div", { className: "h-2 w-2 rounded-full bg-zinc-900 dark:bg-white", style: { animation: "spinDots 1s linear infinite", animationDelay: `${i * 0.12}s` } }) }, i)) });
|
|
1929
|
+
var HalfCircles = () => /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("div", { className: "relative h-10 w-10 border-4 border-transparent border-t-zinc-900 dark:border-t-white rounded-full animate-spin", children: /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("div", { className: "absolute inset-0 border-4 border-transparent border-b-zinc-400 rounded-full opacity-50" }) });
|
|
1930
|
+
var SquaresLoader = () => /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)("div", { className: "flex gap-1.5", children: [
|
|
1931
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsx)("div", { className: "h-4 w-4 bg-zinc-900 dark:bg-white", style: { animation: "squareMove 1s ease-in-out infinite" } }),
|
|
1932
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsx)("div", { className: "h-4 w-4 bg-zinc-300 dark:bg-zinc-700", style: { animation: "squareMove 1s ease-in-out infinite", animationDelay: "0.2s" } })
|
|
1933
|
+
] });
|
|
1934
|
+
var LoadBar = () => /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("div", { className: "relative h-4 w-12 overflow-hidden rounded-full bg-zinc-100 dark:bg-zinc-800", children: /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("div", { className: "absolute top-0 h-full w-6 rounded-full bg-zinc-900 dark:bg-white", style: { animation: "loadBarMove 1.5s linear infinite" } }) });
|
|
1935
|
+
var PulseLoader = () => /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)("div", { className: "relative h-10 w-10 flex items-center justify-center", children: [
|
|
1936
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsx)("div", { className: "absolute h-full w-full animate-ping rounded-full bg-zinc-900/20 dark:bg-white/20" }),
|
|
1937
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsx)("div", { className: "h-4 w-4 rounded-full bg-zinc-900 dark:bg-white" })
|
|
1938
|
+
] });
|
|
1939
|
+
var DotWave = () => /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("div", { className: "flex gap-1.5", children: [0, 1, 2].map((i) => /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("div", { className: "h-2 w-2 animate-bounce rounded-full bg-zinc-900 dark:bg-white", style: { animationDelay: `${i * 0.15}s` } }, i)) });
|
|
1940
|
+
var ThreeDots = () => /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("div", { className: "flex gap-1", children: [0, 1, 2].map((i) => /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("div", { className: "h-1.5 w-1.5 rounded-full bg-zinc-400 animate-pulse", style: { animationDelay: `${i * 0.2}s` } }, i)) });
|
|
1941
|
+
var TypingIndicator = () => /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("div", { className: "flex items-center gap-1.5 px-4 py-2 bg-zinc-100 dark:bg-zinc-800 rounded-2xl w-fit", children: [0, 1, 2].map((i) => /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("div", { className: "h-1.5 w-1.5 animate-pulse rounded-full bg-zinc-400", style: { animationDelay: `${i * 0.2}s` } }, i)) });
|
|
1942
|
+
var ProgressBar = () => /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)("div", { className: "h-1.5 w-full max-w-[200px] overflow-hidden rounded-full bg-zinc-100 dark:bg-zinc-800", children: [
|
|
1943
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsx)(LoaderStyles, {}),
|
|
1944
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsx)("div", { className: "h-full w-full origin-left bg-zinc-900 dark:bg-white", style: { animation: "progressLoad 1.5s ease-in-out infinite" } })
|
|
1945
|
+
] });
|
|
1946
|
+
var MorphingLoader = () => /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("div", { className: "h-10 w-10 bg-zinc-900 dark:bg-white", style: { animation: "morphShape 3s linear infinite" } });
|
|
1947
|
+
var OrbitLoader = () => /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)("div", { className: "relative flex h-12 w-12 items-center justify-center", children: [
|
|
1948
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsx)("div", { className: "h-2 w-2 rounded-full bg-zinc-900 dark:bg-white" }),
|
|
1949
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsx)("div", { className: "absolute h-full w-full animate-spin", children: /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("div", { className: "h-2 w-2 rounded-full bg-zinc-400" }) })
|
|
1950
|
+
] });
|
|
1951
|
+
var BlurReveal = ({ children }) => /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("div", { style: { animation: "blurReveal 1s ease-out forwards" }, children });
|
|
1952
|
+
var AILoader = ({ text = "Thinking..." }) => /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)("div", { className: "flex flex-col items-center gap-4", children: [
|
|
1953
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsxs)("div", { className: "relative flex h-12 w-12 items-center justify-center", children: [
|
|
1954
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsx)("div", { className: "absolute h-full w-full animate-spin rounded-full border-2 border-zinc-200 border-t-zinc-900 dark:border-zinc-800 dark:border-t-white" }),
|
|
1955
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsx)(import_lucide_react11.Sparkles, { className: "h-5 w-5 animate-pulse text-zinc-900 dark:text-white" })
|
|
1956
|
+
] }),
|
|
1957
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsx)("span", { className: "text-[10px] font-bold uppercase tracking-widest text-zinc-400 animate-pulse", children: text })
|
|
1958
|
+
] });
|
|
1959
|
+
|
|
1960
|
+
// components/ui/menu.tsx
|
|
1961
|
+
var React16 = __toESM(require("react"));
|
|
1962
|
+
var import_lucide_react12 = require("lucide-react");
|
|
1963
|
+
var import_class_variance_authority8 = require("class-variance-authority");
|
|
1964
|
+
var import_jsx_runtime19 = require("react/jsx-runtime");
|
|
1965
|
+
var menuVariants = (0, import_class_variance_authority8.cva)(
|
|
1966
|
+
"w-56 rounded-lg p-1 outline-none",
|
|
1967
|
+
{
|
|
1968
|
+
variants: {
|
|
1969
|
+
variant: {
|
|
1970
|
+
default: "border border-zinc-200 bg-white shadow-xl dark:border-zinc-800 dark:bg-zinc-950",
|
|
1971
|
+
ghost: "bg-transparent"
|
|
1972
|
+
}
|
|
1973
|
+
},
|
|
1974
|
+
defaultVariants: { variant: "default" }
|
|
1975
|
+
}
|
|
1976
|
+
);
|
|
1977
|
+
var Menu = React16.forwardRef(
|
|
1978
|
+
(_a, ref) => {
|
|
1979
|
+
var _b = _a, { className, variant } = _b, props = __objRest(_b, ["className", "variant"]);
|
|
1980
|
+
return /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
|
|
1981
|
+
"div",
|
|
1982
|
+
__spreadValues({
|
|
1983
|
+
ref,
|
|
1984
|
+
role: "menu",
|
|
1985
|
+
className: cn(menuVariants({ variant }), className)
|
|
1986
|
+
}, props)
|
|
1987
|
+
);
|
|
1988
|
+
}
|
|
1989
|
+
);
|
|
1990
|
+
Menu.displayName = "Menu";
|
|
1991
|
+
var menuItemVariants = (0, import_class_variance_authority8.cva)(
|
|
1992
|
+
[
|
|
1993
|
+
"flex w-full cursor-pointer items-center gap-2 rounded-md px-3 py-2 text-left text-sm outline-none transition-colors",
|
|
1994
|
+
"focus-visible:bg-zinc-100 dark:focus-visible:bg-zinc-900",
|
|
1995
|
+
"disabled:pointer-events-none disabled:opacity-40"
|
|
1996
|
+
],
|
|
1997
|
+
{
|
|
1998
|
+
variants: {
|
|
1999
|
+
variant: {
|
|
2000
|
+
default: "text-zinc-700 hover:bg-zinc-100 dark:text-zinc-300 dark:hover:bg-zinc-900",
|
|
2001
|
+
destructive: "text-red-600 hover:bg-red-50 dark:text-red-400 dark:hover:bg-red-950/30"
|
|
2002
|
+
}
|
|
2003
|
+
},
|
|
2004
|
+
defaultVariants: { variant: "default" }
|
|
2005
|
+
}
|
|
2006
|
+
);
|
|
2007
|
+
var MenuItem = React16.forwardRef(
|
|
2008
|
+
(_a, ref) => {
|
|
2009
|
+
var _b = _a, { className, variant, label, icon: Icon, shortcut, selected, disabled } = _b, props = __objRest(_b, ["className", "variant", "label", "icon", "shortcut", "selected", "disabled"]);
|
|
2010
|
+
return /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)(
|
|
2011
|
+
"button",
|
|
2012
|
+
__spreadProps(__spreadValues({
|
|
2013
|
+
ref,
|
|
2014
|
+
type: "button",
|
|
2015
|
+
role: "menuitem",
|
|
2016
|
+
disabled,
|
|
2017
|
+
className: cn(menuItemVariants({ variant }), className)
|
|
2018
|
+
}, props), {
|
|
2019
|
+
children: [
|
|
2020
|
+
Icon && /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(Icon, { className: "h-4 w-4 shrink-0 opacity-70" }),
|
|
2021
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)("span", { className: "flex-1 truncate", children: label }),
|
|
2022
|
+
shortcut && /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("span", { className: "shrink-0 text-xs tracking-wide text-zinc-400 dark:text-zinc-500", children: shortcut }),
|
|
2023
|
+
selected && /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(import_lucide_react12.Check, { className: "h-3.5 w-3.5 shrink-0 text-zinc-900 dark:text-white" })
|
|
2024
|
+
]
|
|
2025
|
+
})
|
|
2026
|
+
);
|
|
2027
|
+
}
|
|
2028
|
+
);
|
|
2029
|
+
MenuItem.displayName = "MenuItem";
|
|
2030
|
+
var MenuLabel = React16.forwardRef((_a, ref) => {
|
|
2031
|
+
var _b = _a, { className } = _b, props = __objRest(_b, ["className"]);
|
|
2032
|
+
return /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
|
|
2033
|
+
"div",
|
|
2034
|
+
__spreadValues({
|
|
2035
|
+
ref,
|
|
2036
|
+
className: cn(
|
|
2037
|
+
"px-3 py-2 text-[11px] font-bold uppercase tracking-wider text-zinc-400 dark:text-zinc-500",
|
|
2038
|
+
className
|
|
2039
|
+
)
|
|
2040
|
+
}, props)
|
|
2041
|
+
);
|
|
2042
|
+
});
|
|
2043
|
+
MenuLabel.displayName = "MenuLabel";
|
|
2044
|
+
var MenuDivider = React16.forwardRef((_a, ref) => {
|
|
2045
|
+
var _b = _a, { className } = _b, props = __objRest(_b, ["className"]);
|
|
2046
|
+
return /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
|
|
2047
|
+
"div",
|
|
2048
|
+
__spreadValues({
|
|
2049
|
+
ref,
|
|
2050
|
+
role: "separator",
|
|
2051
|
+
className: cn("my-1 h-px bg-zinc-100 dark:bg-zinc-800", className)
|
|
2052
|
+
}, props)
|
|
2053
|
+
);
|
|
2054
|
+
});
|
|
2055
|
+
MenuDivider.displayName = "MenuDivider";
|
|
2056
|
+
|
|
2057
|
+
// components/ui/modal.tsx
|
|
2058
|
+
var React17 = __toESM(require("react"));
|
|
2059
|
+
var import_react_dom2 = require("react-dom");
|
|
2060
|
+
var import_class_variance_authority9 = require("class-variance-authority");
|
|
2061
|
+
var import_lucide_react13 = require("lucide-react");
|
|
2062
|
+
var import_jsx_runtime20 = require("react/jsx-runtime");
|
|
2063
|
+
var modalContentVariants = (0, import_class_variance_authority9.cva)(
|
|
2064
|
+
[
|
|
2065
|
+
"relative z-10 flex w-full flex-col overflow-hidden rounded-2xl",
|
|
2066
|
+
"border border-zinc-200/90 bg-white text-zinc-900",
|
|
2067
|
+
"shadow-[0_20px_60px_rgba(0,0,0,0.12),0_0_0_1px_rgba(0,0,0,0.04)]",
|
|
2068
|
+
"dark:border-zinc-800 dark:bg-zinc-950 dark:text-zinc-100",
|
|
2069
|
+
"dark:shadow-[0_20px_60px_rgba(0,0,0,0.45),0_0_0_1px_rgba(255,255,255,0.06)]",
|
|
2070
|
+
"transition-[opacity,transform] duration-200 ease-out"
|
|
2071
|
+
],
|
|
2072
|
+
{
|
|
2073
|
+
variants: {
|
|
2074
|
+
size: {
|
|
2075
|
+
sm: "max-w-[400px]",
|
|
2076
|
+
md: "max-w-[440px]",
|
|
2077
|
+
lg: "max-w-lg",
|
|
2078
|
+
xl: "max-w-xl"
|
|
2079
|
+
},
|
|
2080
|
+
visible: {
|
|
2081
|
+
true: "opacity-100 scale-100",
|
|
2082
|
+
false: "opacity-0 scale-[0.97]"
|
|
2083
|
+
}
|
|
2084
|
+
},
|
|
2085
|
+
defaultVariants: { size: "md", visible: false }
|
|
2086
|
+
}
|
|
2087
|
+
);
|
|
2088
|
+
var overlayVariants = (0, import_class_variance_authority9.cva)(
|
|
2089
|
+
[
|
|
2090
|
+
"absolute inset-0 bg-zinc-900/45",
|
|
2091
|
+
"transition-opacity duration-200 ease-out",
|
|
2092
|
+
"dark:bg-black/65"
|
|
2093
|
+
],
|
|
2094
|
+
{
|
|
2095
|
+
variants: {
|
|
2096
|
+
visible: {
|
|
2097
|
+
true: "opacity-100",
|
|
2098
|
+
false: "opacity-0"
|
|
2099
|
+
}
|
|
2100
|
+
},
|
|
2101
|
+
defaultVariants: { visible: false }
|
|
2102
|
+
}
|
|
2103
|
+
);
|
|
2104
|
+
var ModalContext = React17.createContext(null);
|
|
2105
|
+
var ModalContentContext = React17.createContext(null);
|
|
2106
|
+
function useModalContext() {
|
|
2107
|
+
const context = React17.useContext(ModalContext);
|
|
2108
|
+
if (!context) {
|
|
2109
|
+
throw new Error("Modal components must be used within Modal");
|
|
2110
|
+
}
|
|
2111
|
+
return context;
|
|
2112
|
+
}
|
|
2113
|
+
function useModalContentContext() {
|
|
2114
|
+
const context = React17.useContext(ModalContentContext);
|
|
2115
|
+
if (!context) {
|
|
2116
|
+
throw new Error("Modal subcomponents must be used within ModalContent");
|
|
2117
|
+
}
|
|
2118
|
+
return context;
|
|
2119
|
+
}
|
|
2120
|
+
function Modal({
|
|
2121
|
+
open: controlledOpen,
|
|
2122
|
+
onOpenChange,
|
|
2123
|
+
defaultOpen = false,
|
|
2124
|
+
children
|
|
2125
|
+
}) {
|
|
2126
|
+
const [uncontrolledOpen, setUncontrolledOpen] = React17.useState(defaultOpen);
|
|
2127
|
+
const open = controlledOpen != null ? controlledOpen : uncontrolledOpen;
|
|
2128
|
+
const handleOpenChange = React17.useCallback(
|
|
2129
|
+
(next) => {
|
|
2130
|
+
if (controlledOpen === void 0) {
|
|
2131
|
+
setUncontrolledOpen(next);
|
|
2132
|
+
}
|
|
2133
|
+
onOpenChange == null ? void 0 : onOpenChange(next);
|
|
2134
|
+
},
|
|
2135
|
+
[controlledOpen, onOpenChange]
|
|
2136
|
+
);
|
|
2137
|
+
return /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(ModalContext.Provider, { value: { open, onOpenChange: handleOpenChange }, children });
|
|
2138
|
+
}
|
|
2139
|
+
function ModalTrigger(_a) {
|
|
2140
|
+
var _b = _a, { asChild, children, onClick } = _b, props = __objRest(_b, ["asChild", "children", "onClick"]);
|
|
2141
|
+
const { onOpenChange } = useModalContext();
|
|
2142
|
+
const handleOpen = (event) => {
|
|
2143
|
+
onClick == null ? void 0 : onClick(event);
|
|
2144
|
+
if (!event.defaultPrevented) {
|
|
2145
|
+
onOpenChange(true);
|
|
2146
|
+
}
|
|
2147
|
+
};
|
|
2148
|
+
if (asChild && React17.isValidElement(children)) {
|
|
2149
|
+
const child = children;
|
|
2150
|
+
return React17.cloneElement(child, {
|
|
2151
|
+
onClick: (event) => {
|
|
2152
|
+
var _a2, _b2;
|
|
2153
|
+
(_b2 = (_a2 = child.props).onClick) == null ? void 0 : _b2.call(_a2, event);
|
|
2154
|
+
if (!event.defaultPrevented) {
|
|
2155
|
+
onOpenChange(true);
|
|
2156
|
+
}
|
|
2157
|
+
}
|
|
2158
|
+
});
|
|
2159
|
+
}
|
|
2160
|
+
return /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("button", __spreadProps(__spreadValues({ type: "button", onClick: handleOpen }, props), { children }));
|
|
2161
|
+
}
|
|
2162
|
+
function ModalContent(_a) {
|
|
2163
|
+
var _b = _a, {
|
|
2164
|
+
className,
|
|
2165
|
+
size,
|
|
2166
|
+
showCloseButton = true,
|
|
2167
|
+
onClose,
|
|
2168
|
+
children
|
|
2169
|
+
} = _b, props = __objRest(_b, [
|
|
2170
|
+
"className",
|
|
2171
|
+
"size",
|
|
2172
|
+
"showCloseButton",
|
|
2173
|
+
"onClose",
|
|
2174
|
+
"children"
|
|
2175
|
+
]);
|
|
2176
|
+
const { open, onOpenChange } = useModalContext();
|
|
2177
|
+
const [mounted, setMounted] = React17.useState(false);
|
|
2178
|
+
const [visible, setVisible] = React17.useState(false);
|
|
2179
|
+
const contentRef = React17.useRef(null);
|
|
2180
|
+
const titleId = React17.useId();
|
|
2181
|
+
const descriptionId = React17.useId();
|
|
2182
|
+
React17.useEffect(() => setMounted(true), []);
|
|
2183
|
+
React17.useEffect(() => {
|
|
2184
|
+
if (!open) {
|
|
2185
|
+
setVisible(false);
|
|
2186
|
+
document.body.style.overflow = "";
|
|
2187
|
+
return;
|
|
2188
|
+
}
|
|
2189
|
+
document.body.style.overflow = "hidden";
|
|
2190
|
+
const frame = requestAnimationFrame(() => setVisible(true));
|
|
2191
|
+
return () => {
|
|
2192
|
+
cancelAnimationFrame(frame);
|
|
2193
|
+
document.body.style.overflow = "";
|
|
2194
|
+
};
|
|
2195
|
+
}, [open]);
|
|
2196
|
+
const close = React17.useCallback(() => {
|
|
2197
|
+
onClose == null ? void 0 : onClose();
|
|
2198
|
+
onOpenChange(false);
|
|
2199
|
+
}, [onClose, onOpenChange]);
|
|
2200
|
+
React17.useEffect(() => {
|
|
2201
|
+
if (!open) return;
|
|
2202
|
+
const handleKeyDown = (event) => {
|
|
2203
|
+
if (event.key === "Escape") close();
|
|
2204
|
+
};
|
|
2205
|
+
window.addEventListener("keydown", handleKeyDown);
|
|
2206
|
+
return () => window.removeEventListener("keydown", handleKeyDown);
|
|
2207
|
+
}, [open, close]);
|
|
2208
|
+
React17.useEffect(() => {
|
|
2209
|
+
if (!open || !contentRef.current) return;
|
|
2210
|
+
const focusable = contentRef.current.querySelector(
|
|
2211
|
+
"button, [href], input, select, textarea, [tabindex]:not([tabindex='-1'])"
|
|
2212
|
+
);
|
|
2213
|
+
focusable == null ? void 0 : focusable.focus();
|
|
2214
|
+
}, [open, visible]);
|
|
2215
|
+
if (!mounted || !open) return null;
|
|
2216
|
+
const node = /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)("div", { className: "fixed inset-0 z-[100] isolate flex items-center justify-center p-4 sm:p-6", children: [
|
|
2217
|
+
/* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
|
|
2218
|
+
"div",
|
|
2219
|
+
{
|
|
2220
|
+
className: overlayVariants({ visible }),
|
|
2221
|
+
onClick: close,
|
|
2222
|
+
"aria-hidden": true
|
|
2223
|
+
}
|
|
2224
|
+
),
|
|
2225
|
+
/* @__PURE__ */ (0, import_jsx_runtime20.jsxs)(
|
|
2226
|
+
"div",
|
|
2227
|
+
__spreadProps(__spreadValues({
|
|
2228
|
+
ref: contentRef,
|
|
2229
|
+
role: "dialog",
|
|
2230
|
+
"aria-modal": "true",
|
|
2231
|
+
"aria-labelledby": titleId,
|
|
2232
|
+
"aria-describedby": descriptionId,
|
|
2233
|
+
className: cn(modalContentVariants({ size, visible }), className),
|
|
2234
|
+
onClick: (e) => e.stopPropagation()
|
|
2235
|
+
}, props), {
|
|
2236
|
+
children: [
|
|
2237
|
+
showCloseButton && /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
|
|
2238
|
+
"button",
|
|
2239
|
+
{
|
|
2240
|
+
type: "button",
|
|
2241
|
+
onClick: close,
|
|
2242
|
+
className: "absolute right-4 top-4 z-10 inline-flex h-8 w-8 items-center justify-center rounded-lg text-zinc-400 transition-colors hover:bg-zinc-100 hover:text-zinc-700 dark:hover:bg-zinc-800 dark:hover:text-zinc-200",
|
|
2243
|
+
"aria-label": "Close",
|
|
2244
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(import_lucide_react13.X, { className: "h-4 w-4", strokeWidth: 2 })
|
|
2245
|
+
}
|
|
2246
|
+
),
|
|
2247
|
+
/* @__PURE__ */ (0, import_jsx_runtime20.jsx)(ModalContentContext.Provider, { value: { titleId, descriptionId, close }, children })
|
|
2248
|
+
]
|
|
2249
|
+
})
|
|
2250
|
+
)
|
|
2251
|
+
] });
|
|
2252
|
+
return (0, import_react_dom2.createPortal)(node, document.body);
|
|
2253
|
+
}
|
|
2254
|
+
function ModalHeader(_a) {
|
|
2255
|
+
var _b = _a, {
|
|
2256
|
+
className
|
|
2257
|
+
} = _b, props = __objRest(_b, [
|
|
2258
|
+
"className"
|
|
2259
|
+
]);
|
|
2260
|
+
return /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
|
|
2261
|
+
"div",
|
|
2262
|
+
__spreadValues({
|
|
2263
|
+
className: cn("space-y-1 px-6 pt-6 pr-12", className)
|
|
2264
|
+
}, props)
|
|
2265
|
+
);
|
|
2266
|
+
}
|
|
2267
|
+
function ModalTitle(_a) {
|
|
2268
|
+
var _b = _a, {
|
|
2269
|
+
className
|
|
2270
|
+
} = _b, props = __objRest(_b, [
|
|
2271
|
+
"className"
|
|
2272
|
+
]);
|
|
2273
|
+
const { titleId } = useModalContentContext();
|
|
2274
|
+
return /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
|
|
2275
|
+
"h2",
|
|
2276
|
+
__spreadValues({
|
|
2277
|
+
id: titleId,
|
|
2278
|
+
className: cn(
|
|
2279
|
+
"text-[15px] font-semibold leading-snug tracking-tight text-zinc-900 dark:text-white",
|
|
2280
|
+
className
|
|
2281
|
+
)
|
|
2282
|
+
}, props)
|
|
2283
|
+
);
|
|
2284
|
+
}
|
|
2285
|
+
function ModalDescription(_a) {
|
|
2286
|
+
var _b = _a, {
|
|
2287
|
+
className
|
|
2288
|
+
} = _b, props = __objRest(_b, [
|
|
2289
|
+
"className"
|
|
2290
|
+
]);
|
|
2291
|
+
const { descriptionId } = useModalContentContext();
|
|
2292
|
+
return /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
|
|
2293
|
+
"p",
|
|
2294
|
+
__spreadValues({
|
|
2295
|
+
id: descriptionId,
|
|
2296
|
+
className: cn(
|
|
2297
|
+
"text-[13px] leading-relaxed text-zinc-500 dark:text-zinc-400",
|
|
2298
|
+
className
|
|
2299
|
+
)
|
|
2300
|
+
}, props)
|
|
2301
|
+
);
|
|
2302
|
+
}
|
|
2303
|
+
function ModalBody(_a) {
|
|
2304
|
+
var _b = _a, {
|
|
2305
|
+
className
|
|
2306
|
+
} = _b, props = __objRest(_b, [
|
|
2307
|
+
"className"
|
|
2308
|
+
]);
|
|
2309
|
+
return /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
|
|
2310
|
+
"div",
|
|
2311
|
+
__spreadValues({
|
|
2312
|
+
className: cn("space-y-4 px-6 pt-5 pb-6", className)
|
|
2313
|
+
}, props)
|
|
2314
|
+
);
|
|
2315
|
+
}
|
|
2316
|
+
function ModalFooter(_a) {
|
|
2317
|
+
var _b = _a, {
|
|
2318
|
+
className
|
|
2319
|
+
} = _b, props = __objRest(_b, [
|
|
2320
|
+
"className"
|
|
2321
|
+
]);
|
|
2322
|
+
return /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
|
|
2323
|
+
"div",
|
|
2324
|
+
__spreadValues({
|
|
2325
|
+
className: cn(
|
|
2326
|
+
"flex items-center justify-end gap-2 border-t border-zinc-200/90 px-6 py-4 dark:border-zinc-800",
|
|
2327
|
+
className
|
|
2328
|
+
)
|
|
2329
|
+
}, props)
|
|
2330
|
+
);
|
|
2331
|
+
}
|
|
2332
|
+
function ModalOption(_a) {
|
|
2333
|
+
var _b = _a, {
|
|
2334
|
+
className,
|
|
2335
|
+
icon,
|
|
2336
|
+
title,
|
|
2337
|
+
description
|
|
2338
|
+
} = _b, props = __objRest(_b, [
|
|
2339
|
+
"className",
|
|
2340
|
+
"icon",
|
|
2341
|
+
"title",
|
|
2342
|
+
"description"
|
|
2343
|
+
]);
|
|
2344
|
+
return /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)(
|
|
2345
|
+
"div",
|
|
2346
|
+
__spreadProps(__spreadValues({
|
|
2347
|
+
className: cn(
|
|
2348
|
+
"flex gap-3 rounded-xl border border-zinc-200 bg-zinc-50/70 p-3.5",
|
|
2349
|
+
"dark:border-zinc-800 dark:bg-zinc-900/60",
|
|
2350
|
+
className
|
|
2351
|
+
)
|
|
2352
|
+
}, props), {
|
|
2353
|
+
children: [
|
|
2354
|
+
icon && /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
|
|
2355
|
+
"div",
|
|
2356
|
+
{
|
|
2357
|
+
className: "flex h-9 w-9 shrink-0 items-center justify-center rounded-lg bg-white text-zinc-500 shadow-sm ring-1 ring-zinc-200/80 dark:bg-zinc-950 dark:text-zinc-400 dark:ring-zinc-700",
|
|
2358
|
+
children: icon
|
|
2359
|
+
}
|
|
2360
|
+
),
|
|
2361
|
+
/* @__PURE__ */ (0, import_jsx_runtime20.jsxs)("div", { className: "min-w-0", children: [
|
|
2362
|
+
/* @__PURE__ */ (0, import_jsx_runtime20.jsx)("p", { className: "text-sm font-medium text-zinc-900 dark:text-white", children: title }),
|
|
2363
|
+
description && /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("p", { className: "mt-0.5 text-xs leading-relaxed text-zinc-500 dark:text-zinc-400", children: description })
|
|
2364
|
+
] })
|
|
2365
|
+
]
|
|
2366
|
+
})
|
|
2367
|
+
);
|
|
2368
|
+
}
|
|
2369
|
+
function ModalClose(_a) {
|
|
2370
|
+
var _b = _a, { asChild, children, onClick } = _b, props = __objRest(_b, ["asChild", "children", "onClick"]);
|
|
2371
|
+
const { close } = useModalContentContext();
|
|
2372
|
+
if (asChild && React17.isValidElement(children)) {
|
|
2373
|
+
return React17.cloneElement(
|
|
2374
|
+
children,
|
|
2375
|
+
{
|
|
2376
|
+
onClick: (event) => {
|
|
2377
|
+
var _a2, _b2;
|
|
2378
|
+
(_b2 = (_a2 = children.props).onClick) == null ? void 0 : _b2.call(
|
|
2379
|
+
_a2,
|
|
2380
|
+
event
|
|
2381
|
+
);
|
|
2382
|
+
close();
|
|
2383
|
+
}
|
|
2384
|
+
}
|
|
2385
|
+
);
|
|
2386
|
+
}
|
|
2387
|
+
return /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
|
|
2388
|
+
"button",
|
|
2389
|
+
__spreadProps(__spreadValues({
|
|
2390
|
+
type: "button",
|
|
2391
|
+
onClick: (e) => {
|
|
2392
|
+
onClick == null ? void 0 : onClick(e);
|
|
2393
|
+
close();
|
|
2394
|
+
}
|
|
2395
|
+
}, props), {
|
|
2396
|
+
children
|
|
2397
|
+
})
|
|
2398
|
+
);
|
|
2399
|
+
}
|
|
2400
|
+
|
|
2401
|
+
// components/ui/progress.tsx
|
|
2402
|
+
var React18 = __toESM(require("react"));
|
|
2403
|
+
var import_class_variance_authority10 = require("class-variance-authority");
|
|
2404
|
+
var import_jsx_runtime21 = require("react/jsx-runtime");
|
|
2405
|
+
var progressTrackVariants = (0, import_class_variance_authority10.cva)(
|
|
2406
|
+
"relative w-full overflow-hidden rounded-full bg-zinc-100 dark:bg-zinc-800/70",
|
|
2407
|
+
{
|
|
2408
|
+
variants: {
|
|
2409
|
+
size: {
|
|
2410
|
+
sm: "h-1",
|
|
2411
|
+
md: "h-1.5",
|
|
2412
|
+
lg: "h-2"
|
|
2413
|
+
}
|
|
2414
|
+
},
|
|
2415
|
+
defaultVariants: { size: "md" }
|
|
2416
|
+
}
|
|
2417
|
+
);
|
|
2418
|
+
var progressIndicatorVariants = (0, import_class_variance_authority10.cva)(
|
|
2419
|
+
"h-full rounded-full transition-[width] duration-500 ease-[cubic-bezier(0.4,0,0.2,1)]",
|
|
2420
|
+
{
|
|
2421
|
+
variants: {
|
|
2422
|
+
variant: {
|
|
2423
|
+
default: "bg-zinc-900 dark:bg-zinc-100",
|
|
2424
|
+
success: "bg-[#28A745] dark:bg-[#5CC975]",
|
|
2425
|
+
warning: "bg-[#E58E00] dark:bg-[#F5B84A]",
|
|
2426
|
+
error: "bg-[#D93025] dark:bg-[#F06B62]"
|
|
2427
|
+
}
|
|
2428
|
+
},
|
|
2429
|
+
defaultVariants: { variant: "default" }
|
|
2430
|
+
}
|
|
2431
|
+
);
|
|
2432
|
+
var valuePillVariants = (0, import_class_variance_authority10.cva)(
|
|
2433
|
+
"inline-flex min-w-[2.25rem] items-center justify-end text-[11px] font-medium tabular-nums text-zinc-400 dark:text-zinc-500",
|
|
2434
|
+
{
|
|
2435
|
+
variants: {
|
|
2436
|
+
variant: {
|
|
2437
|
+
default: "",
|
|
2438
|
+
success: "",
|
|
2439
|
+
warning: "",
|
|
2440
|
+
error: ""
|
|
2441
|
+
}
|
|
2442
|
+
},
|
|
2443
|
+
defaultVariants: { variant: "default" }
|
|
2444
|
+
}
|
|
2445
|
+
);
|
|
2446
|
+
var Progress = React18.forwardRef(
|
|
2447
|
+
(_a, ref) => {
|
|
2448
|
+
var _b = _a, {
|
|
2449
|
+
className,
|
|
2450
|
+
value = 0,
|
|
2451
|
+
max = 100,
|
|
2452
|
+
variant,
|
|
2453
|
+
size,
|
|
2454
|
+
label,
|
|
2455
|
+
showValue = false,
|
|
2456
|
+
indeterminate = false,
|
|
2457
|
+
disabled = false
|
|
2458
|
+
} = _b, props = __objRest(_b, [
|
|
2459
|
+
"className",
|
|
2460
|
+
"value",
|
|
2461
|
+
"max",
|
|
2462
|
+
"variant",
|
|
2463
|
+
"size",
|
|
2464
|
+
"label",
|
|
2465
|
+
"showValue",
|
|
2466
|
+
"indeterminate",
|
|
2467
|
+
"disabled"
|
|
2468
|
+
]);
|
|
2469
|
+
const clamped = Math.min(max, Math.max(0, value));
|
|
2470
|
+
const percentage = max > 0 ? Math.round(clamped / max * 100) : 0;
|
|
2471
|
+
return /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(
|
|
2472
|
+
"div",
|
|
2473
|
+
{
|
|
2474
|
+
className: cn(
|
|
2475
|
+
"flex w-full flex-col gap-2.5",
|
|
2476
|
+
disabled && "pointer-events-none opacity-50",
|
|
2477
|
+
className
|
|
2478
|
+
),
|
|
2479
|
+
children: [
|
|
2480
|
+
(label || showValue) && /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { className: "flex items-center justify-between gap-3", children: [
|
|
2481
|
+
label && /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("span", { className: "text-sm text-zinc-600 dark:text-zinc-300", children: label }),
|
|
2482
|
+
showValue && !indeterminate && /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("span", { className: cn(valuePillVariants({ variant })), children: [
|
|
2483
|
+
percentage,
|
|
2484
|
+
"%"
|
|
2485
|
+
] })
|
|
2486
|
+
] }),
|
|
2487
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
|
|
2488
|
+
"div",
|
|
2489
|
+
__spreadProps(__spreadValues({
|
|
2490
|
+
ref,
|
|
2491
|
+
role: "progressbar",
|
|
2492
|
+
"aria-valuemin": 0,
|
|
2493
|
+
"aria-valuemax": max,
|
|
2494
|
+
"aria-valuenow": indeterminate || disabled ? void 0 : clamped,
|
|
2495
|
+
"aria-label": label,
|
|
2496
|
+
"aria-valuetext": indeterminate ? "Loading" : `${percentage}%`,
|
|
2497
|
+
"aria-disabled": disabled || void 0,
|
|
2498
|
+
className: cn(progressTrackVariants({ size }))
|
|
2499
|
+
}, props), {
|
|
2500
|
+
children: indeterminate ? /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
|
|
2501
|
+
"div",
|
|
2502
|
+
{
|
|
2503
|
+
className: cn(
|
|
2504
|
+
progressIndicatorVariants({ variant }),
|
|
2505
|
+
"w-[40%] animate-[progress-indeterminate_1.5s_ease-in-out_infinite]"
|
|
2506
|
+
)
|
|
2507
|
+
}
|
|
2508
|
+
) : /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
|
|
2509
|
+
"div",
|
|
2510
|
+
{
|
|
2511
|
+
className: cn(progressIndicatorVariants({ variant })),
|
|
2512
|
+
style: { width: `${percentage}%` }
|
|
2513
|
+
}
|
|
2514
|
+
)
|
|
2515
|
+
})
|
|
2516
|
+
)
|
|
2517
|
+
]
|
|
2518
|
+
}
|
|
2519
|
+
);
|
|
2520
|
+
}
|
|
2521
|
+
);
|
|
2522
|
+
Progress.displayName = "Progress";
|
|
2523
|
+
|
|
2524
|
+
// components/ui/radio.tsx
|
|
2525
|
+
var React19 = __toESM(require("react"));
|
|
2526
|
+
var import_class_variance_authority11 = require("class-variance-authority");
|
|
2527
|
+
var import_jsx_runtime22 = require("react/jsx-runtime");
|
|
2528
|
+
var radioControlVariants = (0, import_class_variance_authority11.cva)(
|
|
2529
|
+
[
|
|
2530
|
+
"pointer-events-none relative flex shrink-0 items-center justify-center rounded-full border-2 bg-transparent transition-all duration-200",
|
|
2531
|
+
"border-zinc-500 group-hover:border-zinc-700",
|
|
2532
|
+
"peer-checked:border-zinc-900",
|
|
2533
|
+
"peer-focus-visible:outline-none peer-focus-visible:ring-2 peer-focus-visible:ring-zinc-900/30 peer-focus-visible:ring-offset-2",
|
|
2534
|
+
"peer-disabled:border-zinc-300",
|
|
2535
|
+
"peer-disabled:peer-checked:border-zinc-300",
|
|
2536
|
+
"dark:border-zinc-500 dark:group-hover:border-zinc-400",
|
|
2537
|
+
"dark:peer-checked:border-zinc-100",
|
|
2538
|
+
"dark:peer-disabled:border-zinc-600 dark:peer-disabled:peer-checked:border-zinc-600",
|
|
2539
|
+
"peer-checked:[&_.radio-dot]:scale-100 peer-checked:[&_.radio-dot]:opacity-100",
|
|
2540
|
+
"peer-disabled:peer-checked:[&_.radio-dot]:bg-zinc-300",
|
|
2541
|
+
"dark:peer-disabled:peer-checked:[&_.radio-dot]:bg-zinc-600"
|
|
2542
|
+
],
|
|
2543
|
+
{
|
|
2544
|
+
variants: {
|
|
2545
|
+
size: {
|
|
2546
|
+
sm: "h-4 w-4 [&_.radio-dot]:h-1.5 [&_.radio-dot]:w-1.5",
|
|
2547
|
+
md: "h-5 w-5 [&_.radio-dot]:h-2.5 [&_.radio-dot]:w-2.5",
|
|
2548
|
+
lg: "h-6 w-6 [&_.radio-dot]:h-3 [&_.radio-dot]:w-3"
|
|
2549
|
+
}
|
|
2550
|
+
},
|
|
2551
|
+
defaultVariants: { size: "md" }
|
|
2552
|
+
}
|
|
2553
|
+
);
|
|
2554
|
+
var radioWrapperVariants = (0, import_class_variance_authority11.cva)("group relative flex w-full transition-colors duration-150", {
|
|
2555
|
+
variants: {
|
|
2556
|
+
variant: {
|
|
2557
|
+
inline: "gap-3",
|
|
2558
|
+
card: [
|
|
2559
|
+
"gap-3.5 rounded-lg border border-zinc-200 bg-white px-4 py-3.5",
|
|
2560
|
+
"hover:border-zinc-300 hover:bg-zinc-50/80",
|
|
2561
|
+
"has-[:checked]:border-zinc-900",
|
|
2562
|
+
"dark:border-zinc-800 dark:bg-zinc-900 dark:hover:border-zinc-700",
|
|
2563
|
+
"dark:has-[:checked]:border-zinc-500"
|
|
2564
|
+
]
|
|
2565
|
+
}
|
|
2566
|
+
},
|
|
2567
|
+
defaultVariants: { variant: "inline" }
|
|
2568
|
+
});
|
|
2569
|
+
var RadioGroupContext = React19.createContext(
|
|
2570
|
+
null
|
|
2571
|
+
);
|
|
2572
|
+
var RadioGroup = React19.forwardRef(
|
|
2573
|
+
(_a, ref) => {
|
|
2574
|
+
var _b = _a, {
|
|
2575
|
+
className,
|
|
2576
|
+
name,
|
|
2577
|
+
value: controlledValue,
|
|
2578
|
+
defaultValue,
|
|
2579
|
+
onValueChange,
|
|
2580
|
+
size = "md",
|
|
2581
|
+
variant = "inline",
|
|
2582
|
+
appearance = "default",
|
|
2583
|
+
disabled,
|
|
2584
|
+
orientation = "vertical",
|
|
2585
|
+
children
|
|
2586
|
+
} = _b, props = __objRest(_b, [
|
|
2587
|
+
"className",
|
|
2588
|
+
"name",
|
|
2589
|
+
"value",
|
|
2590
|
+
"defaultValue",
|
|
2591
|
+
"onValueChange",
|
|
2592
|
+
"size",
|
|
2593
|
+
"variant",
|
|
2594
|
+
"appearance",
|
|
2595
|
+
"disabled",
|
|
2596
|
+
"orientation",
|
|
2597
|
+
"children"
|
|
2598
|
+
]);
|
|
2599
|
+
const [uncontrolledValue, setUncontrolledValue] = React19.useState(
|
|
2600
|
+
defaultValue != null ? defaultValue : ""
|
|
2601
|
+
);
|
|
2602
|
+
const value = controlledValue != null ? controlledValue : uncontrolledValue;
|
|
2603
|
+
const handleValueChange = (next) => {
|
|
2604
|
+
if (controlledValue === void 0) {
|
|
2605
|
+
setUncontrolledValue(next);
|
|
2606
|
+
}
|
|
2607
|
+
onValueChange == null ? void 0 : onValueChange(next);
|
|
2608
|
+
};
|
|
2609
|
+
return /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
|
|
2610
|
+
RadioGroupContext.Provider,
|
|
2611
|
+
{
|
|
2612
|
+
value: { name, value, onValueChange: handleValueChange, size, variant, appearance, disabled },
|
|
2613
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
|
|
2614
|
+
"div",
|
|
2615
|
+
__spreadProps(__spreadValues({
|
|
2616
|
+
ref,
|
|
2617
|
+
role: "radiogroup",
|
|
2618
|
+
className: cn(
|
|
2619
|
+
"flex",
|
|
2620
|
+
appearance === "segmented" ? "inline-flex w-fit gap-0.5 rounded-lg border border-zinc-200 p-0.5 dark:border-zinc-800" : variant === "card" ? "gap-2.5" : "gap-2.5",
|
|
2621
|
+
orientation === "vertical" ? "flex-col" : "flex-row flex-wrap",
|
|
2622
|
+
className
|
|
2623
|
+
)
|
|
2624
|
+
}, props), {
|
|
2625
|
+
children
|
|
2626
|
+
})
|
|
2627
|
+
)
|
|
2628
|
+
}
|
|
2629
|
+
);
|
|
2630
|
+
}
|
|
2631
|
+
);
|
|
2632
|
+
RadioGroup.displayName = "RadioGroup";
|
|
2633
|
+
var Radio = React19.forwardRef(
|
|
2634
|
+
(_a, ref) => {
|
|
2635
|
+
var _b = _a, {
|
|
2636
|
+
className,
|
|
2637
|
+
size: sizeProp,
|
|
2638
|
+
variant: variantProp,
|
|
2639
|
+
value,
|
|
2640
|
+
label,
|
|
2641
|
+
description,
|
|
2642
|
+
disabled: disabledProp,
|
|
2643
|
+
id,
|
|
2644
|
+
onChange,
|
|
2645
|
+
checked: checkedProp
|
|
2646
|
+
} = _b, inputProps = __objRest(_b, [
|
|
2647
|
+
"className",
|
|
2648
|
+
"size",
|
|
2649
|
+
"variant",
|
|
2650
|
+
"value",
|
|
2651
|
+
"label",
|
|
2652
|
+
"description",
|
|
2653
|
+
"disabled",
|
|
2654
|
+
"id",
|
|
2655
|
+
"onChange",
|
|
2656
|
+
"checked"
|
|
2657
|
+
]);
|
|
2658
|
+
var _a2, _b2, _c;
|
|
2659
|
+
const context = React19.useContext(RadioGroupContext);
|
|
2660
|
+
const generatedId = React19.useId();
|
|
2661
|
+
const inputId = id != null ? id : generatedId;
|
|
2662
|
+
const size = (_a2 = sizeProp != null ? sizeProp : context == null ? void 0 : context.size) != null ? _a2 : "md";
|
|
2663
|
+
const groupVariant = (_b2 = variantProp != null ? variantProp : context == null ? void 0 : context.variant) != null ? _b2 : "inline";
|
|
2664
|
+
const appearance = (_c = context == null ? void 0 : context.appearance) != null ? _c : "default";
|
|
2665
|
+
const resolvedVariant = appearance === "segmented" ? "inline" : groupVariant === "card" || description ? "card" : "inline";
|
|
2666
|
+
const disabled = disabledProp != null ? disabledProp : context == null ? void 0 : context.disabled;
|
|
2667
|
+
const isControlled = context !== null || checkedProp !== void 0;
|
|
2668
|
+
const checked = context ? context.value === value : checkedProp;
|
|
2669
|
+
const alignStart = resolvedVariant === "card" || Boolean(description);
|
|
2670
|
+
const input = /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
|
|
2671
|
+
"input",
|
|
2672
|
+
__spreadProps(__spreadValues({}, inputProps), {
|
|
2673
|
+
ref,
|
|
2674
|
+
id: inputId,
|
|
2675
|
+
type: "radio",
|
|
2676
|
+
name: context == null ? void 0 : context.name,
|
|
2677
|
+
value,
|
|
2678
|
+
disabled,
|
|
2679
|
+
checked: isControlled ? checked : void 0,
|
|
2680
|
+
defaultChecked: !isControlled ? checkedProp : void 0,
|
|
2681
|
+
onChange: (event) => {
|
|
2682
|
+
var _a3;
|
|
2683
|
+
onChange == null ? void 0 : onChange(event);
|
|
2684
|
+
if (event.target.checked) {
|
|
2685
|
+
(_a3 = context == null ? void 0 : context.onValueChange) == null ? void 0 : _a3.call(context, value);
|
|
2686
|
+
}
|
|
2687
|
+
},
|
|
2688
|
+
className: "peer absolute inset-0 z-10 cursor-pointer opacity-0 disabled:cursor-not-allowed"
|
|
2689
|
+
})
|
|
2690
|
+
);
|
|
2691
|
+
return /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)(
|
|
2692
|
+
"label",
|
|
2693
|
+
{
|
|
2694
|
+
htmlFor: inputId,
|
|
2695
|
+
className: cn(
|
|
2696
|
+
appearance === "segmented" ? "relative inline-flex items-center rounded-md px-3 py-1.5 text-sm font-medium text-zinc-600 transition-colors duration-150 has-[:checked]:bg-zinc-900 has-[:checked]:text-white dark:text-zinc-400 dark:has-[:checked]:bg-zinc-100 dark:has-[:checked]:text-zinc-900" : radioWrapperVariants({ variant: resolvedVariant }),
|
|
2697
|
+
appearance === "segmented" ? "items-center" : alignStart ? "items-start" : "items-center",
|
|
2698
|
+
disabled ? "cursor-not-allowed opacity-50" : "cursor-pointer",
|
|
2699
|
+
className
|
|
2700
|
+
),
|
|
2701
|
+
children: [
|
|
2702
|
+
appearance === "segmented" ? input : /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)(
|
|
2703
|
+
"span",
|
|
2704
|
+
{
|
|
2705
|
+
className: cn(
|
|
2706
|
+
"relative flex shrink-0 items-center justify-center p-2.5 -m-2.5",
|
|
2707
|
+
alignStart ? "-mt-[3px]" : void 0
|
|
2708
|
+
),
|
|
2709
|
+
children: [
|
|
2710
|
+
input,
|
|
2711
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
|
|
2712
|
+
"span",
|
|
2713
|
+
{
|
|
2714
|
+
"aria-hidden": true,
|
|
2715
|
+
className: "pointer-events-none absolute inset-0 rounded-full bg-zinc-900/0 transition-colors duration-200 group-hover:bg-zinc-900/[0.08] group-active:bg-zinc-900/[0.12] peer-disabled:group-hover:bg-transparent dark:group-hover:bg-white/[0.08] dark:group-active:bg-white/[0.12]"
|
|
2716
|
+
}
|
|
2717
|
+
),
|
|
2718
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)("span", { className: radioControlVariants({ size }), children: /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("span", { className: "radio-dot scale-0 rounded-full bg-zinc-900 opacity-0 transition-all duration-200 dark:bg-zinc-100" }) })
|
|
2719
|
+
]
|
|
2720
|
+
}
|
|
2721
|
+
),
|
|
2722
|
+
(label || description) && /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)(
|
|
2723
|
+
"span",
|
|
2724
|
+
{
|
|
2725
|
+
className: cn(
|
|
2726
|
+
"flex min-w-0 flex-col",
|
|
2727
|
+
appearance === "segmented" ? "gap-0" : "flex-1 gap-0.5"
|
|
2728
|
+
),
|
|
2729
|
+
children: [
|
|
2730
|
+
label && /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
|
|
2731
|
+
"span",
|
|
2732
|
+
{
|
|
2733
|
+
className: cn(
|
|
2734
|
+
appearance === "segmented" ? "leading-none" : cn(
|
|
2735
|
+
"text-sm leading-snug text-zinc-800 dark:text-zinc-100",
|
|
2736
|
+
size === "sm" && "text-xs",
|
|
2737
|
+
size === "md" && "text-sm",
|
|
2738
|
+
size === "lg" && "text-base"
|
|
2739
|
+
)
|
|
2740
|
+
),
|
|
2741
|
+
children: label
|
|
2742
|
+
}
|
|
2743
|
+
),
|
|
2744
|
+
description && /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("span", { className: "text-xs leading-relaxed text-zinc-500 dark:text-zinc-400", children: description })
|
|
2745
|
+
]
|
|
2746
|
+
}
|
|
2747
|
+
)
|
|
2748
|
+
]
|
|
2749
|
+
}
|
|
2750
|
+
);
|
|
2751
|
+
}
|
|
2752
|
+
);
|
|
2753
|
+
Radio.displayName = "Radio";
|
|
2754
|
+
|
|
2755
|
+
// components/ui/skeleton.tsx
|
|
2756
|
+
var import_jsx_runtime23 = require("react/jsx-runtime");
|
|
2757
|
+
var SkeletonBar = ({ className }) => /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("div", { className: `animate-pulse rounded bg-zinc-200 dark:bg-zinc-800 ${className}` });
|
|
2758
|
+
function AccordionSkeletonPlus({ count = 3 }) {
|
|
2759
|
+
return /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("div", { className: "w-full", children: Array.from({ length: count }).map((_, i) => /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("div", { className: "flex items-center gap-3 py-4 border-b border-zinc-100 dark:border-zinc-800 last:border-0", children: [
|
|
2760
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsx)(SkeletonBar, { className: "h-5 w-5 rounded-full shrink-0" }),
|
|
2761
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsx)(SkeletonBar, { className: "h-4 w-2/3" })
|
|
2762
|
+
] }, i)) });
|
|
2763
|
+
}
|
|
2764
|
+
function AccordionSkeletonChevron({ count = 3 }) {
|
|
2765
|
+
return /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("div", { className: "w-full", children: Array.from({ length: count }).map((_, i) => /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("div", { className: "flex items-center justify-between py-5 border-b border-zinc-100 dark:border-zinc-800 last:border-0", children: [
|
|
2766
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsx)(SkeletonBar, { className: "h-4 w-1/2" }),
|
|
2767
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsx)(SkeletonBar, { className: "h-4 w-4 rounded-sm shrink-0" })
|
|
2768
|
+
] }, i)) });
|
|
2769
|
+
}
|
|
2770
|
+
function CardSkeletonGrid({ count = 3 }) {
|
|
2771
|
+
return /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("div", { className: "grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-4 w-full", children: Array.from({ length: count }).map((_, i) => /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("div", { className: "flex flex-col gap-3", children: [
|
|
2772
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsx)(SkeletonBar, { className: "aspect-video w-full rounded-md" }),
|
|
2773
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsx)(SkeletonBar, { className: "h-4 w-full" }),
|
|
2774
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsx)(SkeletonBar, { className: "h-4 w-[60%]" })
|
|
2775
|
+
] }, i)) });
|
|
2776
|
+
}
|
|
2777
|
+
function ListSkeleton({ count = 3 }) {
|
|
2778
|
+
return /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("div", { className: "w-full space-y-4", children: Array.from({ length: count }).map((_, i) => /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("div", { className: "flex flex-col gap-4 p-4 border border-zinc-100 dark:border-zinc-800 rounded-lg bg-white dark:bg-zinc-900/50", children: [
|
|
2779
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("div", { className: "flex items-center gap-3", children: [
|
|
2780
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsx)(SkeletonBar, { className: "h-10 w-10 rounded-full shrink-0" }),
|
|
2781
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("div", { className: "flex flex-col gap-2", children: [
|
|
2782
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsx)(SkeletonBar, { className: "h-3 w-24" }),
|
|
2783
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsx)(SkeletonBar, { className: "h-3 w-40" })
|
|
2784
|
+
] })
|
|
2785
|
+
] }),
|
|
2786
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("div", { className: "flex flex-col gap-2 mt-1", children: [
|
|
2787
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsx)(SkeletonBar, { className: "h-3 w-full" }),
|
|
2788
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsx)(SkeletonBar, { className: "h-3 w-[92%]" })
|
|
2789
|
+
] })
|
|
2790
|
+
] }, i)) });
|
|
2791
|
+
}
|
|
2792
|
+
function TableSkeleton({ count = 5 }) {
|
|
2793
|
+
return /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("div", { className: "w-full overflow-hidden rounded-lg border border-zinc-100 dark:border-zinc-800", children: /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("div", { className: "overflow-x-auto", children: /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("table", { className: "w-full text-sm text-left", children: [
|
|
2794
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsx)("thead", { className: "bg-zinc-50/50 dark:bg-zinc-900/50 border-b border-zinc-100 dark:border-zinc-800 text-zinc-500", children: /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("tr", { children: [
|
|
2795
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsx)("th", { className: "px-4 py-3 font-medium", children: "Id" }),
|
|
2796
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsx)("th", { className: "px-4 py-3 font-medium", children: "Image" }),
|
|
2797
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsx)("th", { className: "px-4 py-3 font-medium", children: "Name" }),
|
|
2798
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsx)("th", { className: "px-4 py-3 font-medium", children: "Category" }),
|
|
2799
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsx)("th", { className: "px-4 py-3 font-medium", children: "Price" }),
|
|
2800
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsx)("th", { className: "px-4 py-3 font-medium", children: "Stock" }),
|
|
2801
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsx)("th", { className: "px-4 py-3 font-medium", children: "Description" })
|
|
2802
|
+
] }) }),
|
|
2803
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsx)("tbody", { className: "divide-y divide-zinc-100 dark:divide-zinc-800", children: Array.from({ length: count }).map((_, i) => /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("tr", { children: [
|
|
2804
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsx)("td", { className: "px-4 py-4", children: /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(SkeletonBar, { className: "h-4 w-8" }) }),
|
|
2805
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsx)("td", { className: "px-4 py-4", children: /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(SkeletonBar, { className: "h-8 w-12 rounded" }) }),
|
|
2806
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsx)("td", { className: "px-4 py-4", children: /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(SkeletonBar, { className: "h-4 w-24" }) }),
|
|
2807
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsx)("td", { className: "px-4 py-4", children: /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(SkeletonBar, { className: "h-4 w-20" }) }),
|
|
2808
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsx)("td", { className: "px-4 py-4", children: /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(SkeletonBar, { className: "h-4 w-12" }) }),
|
|
2809
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsx)("td", { className: "px-4 py-4", children: /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(SkeletonBar, { className: "h-4 w-12" }) }),
|
|
2810
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsx)("td", { className: "px-4 py-4", children: /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(SkeletonBar, { className: "h-4 w-48" }) })
|
|
2811
|
+
] }, i)) })
|
|
2812
|
+
] }) }) });
|
|
2813
|
+
}
|
|
2814
|
+
|
|
2815
|
+
// components/ui/steppers.tsx
|
|
2816
|
+
var import_react9 = __toESM(require("react"));
|
|
2817
|
+
var import_framer_motion = require("framer-motion");
|
|
2818
|
+
var import_lucide_react14 = require("lucide-react");
|
|
2819
|
+
var import_jsx_runtime24 = require("react/jsx-runtime");
|
|
2820
|
+
function getTone(i, currentStep) {
|
|
2821
|
+
if (i < currentStep) return "done";
|
|
2822
|
+
if (i === currentStep) return "current";
|
|
2823
|
+
return "upcoming";
|
|
2824
|
+
}
|
|
2825
|
+
var NODE_TONE = {
|
|
2826
|
+
done: "border-zinc-900 bg-zinc-900 text-white dark:bg-white dark:text-zinc-900 dark:border-white",
|
|
2827
|
+
current: "border-zinc-900 bg-zinc-900 text-white dark:border-white dark:bg-white dark:text-zinc-900",
|
|
2828
|
+
upcoming: "border-zinc-200 bg-white text-zinc-400 dark:border-zinc-800 dark:bg-zinc-950 dark:text-zinc-600"
|
|
2829
|
+
};
|
|
2830
|
+
var TEXT_TONE = {
|
|
2831
|
+
done: "text-zinc-900 dark:text-zinc-100",
|
|
2832
|
+
current: "text-zinc-900 dark:text-white",
|
|
2833
|
+
upcoming: "text-zinc-400 dark:text-zinc-600"
|
|
2834
|
+
};
|
|
2835
|
+
function HorizontalStepper({ steps, currentStep, className }) {
|
|
2836
|
+
return /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("nav", { "aria-label": "Progress", className: cn("flex w-full items-start pb-8", className), children: steps.map((step, i) => {
|
|
2837
|
+
const tone = getTone(i, currentStep);
|
|
2838
|
+
return /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)(import_react9.default.Fragment, { children: [
|
|
2839
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("div", { className: "relative flex flex-col items-center", children: [
|
|
2840
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
|
|
2841
|
+
"div",
|
|
2842
|
+
{
|
|
2843
|
+
"aria-current": tone === "current" ? "step" : void 0,
|
|
2844
|
+
className: cn(
|
|
2845
|
+
"z-10 flex h-10 w-10 items-center justify-center rounded-full border-2 text-sm font-bold shadow-sm transition-all duration-300",
|
|
2846
|
+
NODE_TONE[tone]
|
|
2847
|
+
),
|
|
2848
|
+
children: tone === "done" ? /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(import_lucide_react14.Check, { size: 18, strokeWidth: 3 }) : /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("span", { children: i + 1 })
|
|
2849
|
+
}
|
|
2850
|
+
),
|
|
2851
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)("div", { className: "absolute top-12 w-24 text-center", children: /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("span", { className: cn("text-[10px] font-black uppercase tracking-tighter transition-colors duration-300", TEXT_TONE[tone]), children: step.title }) })
|
|
2852
|
+
] }),
|
|
2853
|
+
i < steps.length - 1 && /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("div", { className: "relative mx-2 mt-5 h-0.5 flex-1 shrink-0 rounded-full bg-zinc-100 dark:bg-zinc-800", children: /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
|
|
2854
|
+
import_framer_motion.motion.div,
|
|
2855
|
+
{
|
|
2856
|
+
initial: false,
|
|
2857
|
+
animate: { width: i < currentStep ? "100%" : "0%" },
|
|
2858
|
+
className: "absolute h-full rounded-full bg-zinc-900 dark:bg-white",
|
|
2859
|
+
transition: { duration: 0.5, ease: "easeInOut" }
|
|
2860
|
+
}
|
|
2861
|
+
) })
|
|
2862
|
+
] }, i);
|
|
2863
|
+
}) });
|
|
2864
|
+
}
|
|
2865
|
+
function VerticalStepper({ steps, currentStep, className }) {
|
|
2866
|
+
return /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("nav", { "aria-label": "Progress", className: cn("space-y-0", className), children: steps.map((step, i) => {
|
|
2867
|
+
const tone = getTone(i, currentStep);
|
|
2868
|
+
return /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("div", { className: "relative pl-10 pb-10 last:pb-0", children: [
|
|
2869
|
+
i < steps.length - 1 && /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("div", { className: "absolute left-[15px] top-8 bottom-0 w-0.5 rounded-full bg-zinc-100 dark:bg-zinc-800", children: /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
|
|
2870
|
+
import_framer_motion.motion.div,
|
|
2871
|
+
{
|
|
2872
|
+
initial: false,
|
|
2873
|
+
animate: { height: i < currentStep ? "100%" : "0%" },
|
|
2874
|
+
className: "w-full rounded-full bg-zinc-900 dark:bg-white",
|
|
2875
|
+
transition: { duration: 0.4 }
|
|
2876
|
+
}
|
|
2877
|
+
) }),
|
|
2878
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
|
|
2879
|
+
import_framer_motion.motion.div,
|
|
2880
|
+
{
|
|
2881
|
+
"aria-current": tone === "current" ? "step" : void 0,
|
|
2882
|
+
animate: { scale: tone === "current" ? 1.15 : 1 },
|
|
2883
|
+
className: cn(
|
|
2884
|
+
"absolute left-0 top-0 z-10 flex h-8 w-8 items-center justify-center rounded-full border-2 transition-all duration-300",
|
|
2885
|
+
tone === "done" || tone === "current" ? "border-zinc-900 bg-zinc-900 dark:border-white dark:bg-white" : "border-zinc-200 bg-white dark:border-zinc-800 dark:bg-zinc-950"
|
|
2886
|
+
),
|
|
2887
|
+
children: tone === "done" ? /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(import_lucide_react14.Check, { size: 14, strokeWidth: 3, className: "text-white dark:text-zinc-900" }) : /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("div", { className: cn("h-1.5 w-1.5 rounded-full", tone === "current" ? "bg-white dark:bg-zinc-900" : "bg-zinc-300 dark:bg-zinc-700") })
|
|
2888
|
+
}
|
|
2889
|
+
),
|
|
2890
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("div", { className: "flex flex-col", children: [
|
|
2891
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)("h6", { className: cn("text-sm font-bold tracking-tight transition-colors duration-300", TEXT_TONE[tone]), children: step.title }),
|
|
2892
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)("p", { className: "mt-1 text-xs leading-tight text-zinc-500 dark:text-zinc-400", children: step.description })
|
|
2893
|
+
] })
|
|
2894
|
+
] }, i);
|
|
2895
|
+
}) });
|
|
2896
|
+
}
|
|
2897
|
+
function ProgressStepper({ steps, currentStep }) {
|
|
2898
|
+
const progress = (currentStep + 1) / steps.length * 100;
|
|
2899
|
+
return /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("div", { className: "w-full space-y-4", children: [
|
|
2900
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("div", { className: "flex items-end justify-between", children: [
|
|
2901
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)("div", { className: "flex items-baseline gap-2", children: /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("span", { className: "text-lg font-black tracking-tighter text-zinc-900 dark:text-white", children: [
|
|
2902
|
+
Math.round(progress),
|
|
2903
|
+
"%"
|
|
2904
|
+
] }) }),
|
|
2905
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)("div", { className: "flex gap-1", children: steps.map((_, i) => /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
|
|
2906
|
+
import_framer_motion.motion.div,
|
|
2907
|
+
{
|
|
2908
|
+
animate: { opacity: i <= currentStep ? 1 : 0.2 },
|
|
2909
|
+
className: "h-1 w-4 rounded-full bg-zinc-900 dark:bg-white"
|
|
2910
|
+
},
|
|
2911
|
+
i
|
|
2912
|
+
)) })
|
|
2913
|
+
] }),
|
|
2914
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)("div", { className: "h-3 w-full overflow-hidden rounded-full bg-zinc-100 p-1 dark:bg-zinc-800", children: /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
|
|
2915
|
+
import_framer_motion.motion.div,
|
|
2916
|
+
{
|
|
2917
|
+
initial: false,
|
|
2918
|
+
animate: { width: `${progress}%` },
|
|
2919
|
+
className: "h-full rounded-full bg-zinc-900 dark:bg-white",
|
|
2920
|
+
transition: { type: "spring", bounce: 0, duration: 0.8 }
|
|
2921
|
+
}
|
|
2922
|
+
) })
|
|
2923
|
+
] });
|
|
2924
|
+
}
|
|
2925
|
+
function DotStepper({ steps, currentStep }) {
|
|
2926
|
+
return /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("div", { className: "flex items-center gap-3 rounded-full border border-zinc-200 bg-white p-4 dark:border-zinc-800 dark:bg-zinc-950", children: steps.map((_, i) => {
|
|
2927
|
+
const tone = getTone(i, currentStep);
|
|
2928
|
+
return /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
|
|
2929
|
+
import_framer_motion.motion.div,
|
|
2930
|
+
{
|
|
2931
|
+
animate: { width: tone === "current" ? 40 : 12 },
|
|
2932
|
+
className: cn(
|
|
2933
|
+
"h-3 rounded-full transition-colors duration-300",
|
|
2934
|
+
tone === "done" || tone === "current" ? "bg-zinc-900 dark:bg-white" : "bg-zinc-200 dark:bg-zinc-800"
|
|
2935
|
+
),
|
|
2936
|
+
transition: { type: "spring", stiffness: 300, damping: 20 }
|
|
2937
|
+
},
|
|
2938
|
+
i
|
|
2939
|
+
);
|
|
2940
|
+
}) });
|
|
2941
|
+
}
|
|
2942
|
+
function SegmentedStepper({ steps, currentStep }) {
|
|
2943
|
+
return /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("div", { className: "flex w-full gap-1", children: steps.map((_, i) => /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("div", { className: "h-2 flex-1 overflow-hidden rounded-sm bg-zinc-100 dark:bg-zinc-800", children: /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
|
|
2944
|
+
import_framer_motion.motion.div,
|
|
2945
|
+
{
|
|
2946
|
+
initial: false,
|
|
2947
|
+
animate: { x: i <= currentStep ? "0%" : "-100%" },
|
|
2948
|
+
className: "h-full bg-zinc-900 dark:bg-white",
|
|
2949
|
+
transition: { duration: 0.6 }
|
|
2950
|
+
}
|
|
2951
|
+
) }, i)) });
|
|
2952
|
+
}
|
|
2953
|
+
function BreadcrumbStepper({ steps, currentStep }) {
|
|
2954
|
+
return /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("nav", { "aria-label": "Progress", className: "w-full", children: /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("div", { className: "flex w-full items-center gap-2", children: steps.map((step, i) => {
|
|
2955
|
+
const tone = getTone(i, currentStep);
|
|
2956
|
+
return /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)(
|
|
2957
|
+
"div",
|
|
2958
|
+
{
|
|
2959
|
+
className: "flex min-w-0 flex-1 items-center gap-2",
|
|
2960
|
+
children: [
|
|
2961
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
|
|
2962
|
+
import_framer_motion.motion.div,
|
|
2963
|
+
{
|
|
2964
|
+
animate: {
|
|
2965
|
+
opacity: tone === "upcoming" ? 0.45 : 1,
|
|
2966
|
+
scale: tone === "current" ? 1 : 0.98
|
|
2967
|
+
},
|
|
2968
|
+
transition: { duration: 0.25 },
|
|
2969
|
+
className: cn(
|
|
2970
|
+
"flex min-w-0 flex-1 items-center justify-center rounded-full px-2 py-2 text-[9px] font-bold uppercase tracking-wide transition-all duration-300",
|
|
2971
|
+
tone === "current" && "bg-zinc-900 text-white shadow-sm dark:bg-white dark:text-zinc-900",
|
|
2972
|
+
tone === "done" && "bg-zinc-100 text-zinc-900 dark:bg-zinc-800 dark:text-white",
|
|
2973
|
+
tone === "upcoming" && "text-zinc-400 dark:text-zinc-600"
|
|
2974
|
+
),
|
|
2975
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("span", { className: "whitespace-nowrap", children: step.title })
|
|
2976
|
+
}
|
|
2977
|
+
),
|
|
2978
|
+
i < steps.length - 1 && /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
|
|
2979
|
+
"span",
|
|
2980
|
+
{
|
|
2981
|
+
"aria-hidden": "true",
|
|
2982
|
+
className: "h-px w-4 shrink-0 bg-zinc-200 dark:bg-zinc-800"
|
|
2983
|
+
}
|
|
2984
|
+
)
|
|
2985
|
+
]
|
|
2986
|
+
},
|
|
2987
|
+
i
|
|
2988
|
+
);
|
|
2989
|
+
}) }) });
|
|
2990
|
+
}
|
|
2991
|
+
function TimelineStepper({ steps, currentStep }) {
|
|
2992
|
+
return /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("nav", { "aria-label": "Progress", className: "space-y-12", children: steps.map((step, i) => {
|
|
2993
|
+
const tone = getTone(i, currentStep);
|
|
2994
|
+
return /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("div", { className: "relative flex gap-8", children: [
|
|
2995
|
+
i < steps.length - 1 && /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("div", { className: cn("absolute left-5 top-10 -bottom-12 w-0.5 transition-colors duration-1000", i < currentStep ? "bg-zinc-900 dark:bg-white" : "bg-zinc-100 dark:bg-zinc-800") }),
|
|
2996
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
|
|
2997
|
+
import_framer_motion.motion.div,
|
|
2998
|
+
{
|
|
2999
|
+
animate: { scale: tone === "current" ? 1.2 : 1 },
|
|
3000
|
+
className: cn(
|
|
3001
|
+
"z-10 flex h-10 w-10 shrink-0 items-center justify-center rounded-full border-4 border-white shadow-xl ring-2 transition-all duration-300 dark:border-zinc-950",
|
|
3002
|
+
tone === "done" || tone === "current" ? "bg-zinc-900 ring-zinc-900 dark:bg-white dark:ring-white" : "bg-white ring-zinc-200 dark:bg-zinc-950 dark:ring-zinc-800"
|
|
3003
|
+
),
|
|
3004
|
+
children: tone === "done" ? /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(import_lucide_react14.Check, { size: 16, strokeWidth: 3, className: "text-white dark:text-zinc-900" }) : /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("span", { className: cn("text-xs font-bold", tone === "current" ? "text-white dark:text-zinc-900" : "text-zinc-400"), children: i + 1 })
|
|
3005
|
+
}
|
|
3006
|
+
),
|
|
3007
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("div", { className: cn("transition-all duration-500", tone === "upcoming" ? "translate-x-4 opacity-20" : "translate-x-0 opacity-100"), children: [
|
|
3008
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)("h3", { className: "text-sm font-black uppercase tracking-tighter text-zinc-900 dark:text-white", children: step.title }),
|
|
3009
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)("p", { className: "mt-1 text-xs text-zinc-500 dark:text-zinc-400", children: step.description })
|
|
3010
|
+
] })
|
|
3011
|
+
] }, i);
|
|
3012
|
+
}) });
|
|
3013
|
+
}
|
|
3014
|
+
function InteractiveStepper({ steps, currentStep, onStepClick }) {
|
|
3015
|
+
return /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("div", { className: "flex flex-wrap gap-4", children: steps.map((step, i) => {
|
|
3016
|
+
const tone = getTone(i, currentStep);
|
|
3017
|
+
return /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)(
|
|
3018
|
+
"button",
|
|
3019
|
+
{
|
|
3020
|
+
onClick: () => onStepClick == null ? void 0 : onStepClick(i),
|
|
3021
|
+
className: cn(
|
|
3022
|
+
"group relative flex min-w-44 flex-1 flex-col gap-2 rounded-2xl border-2 p-6 text-left transition-all duration-300",
|
|
3023
|
+
tone === "current" ? "border-zinc-900 bg-zinc-900 text-white dark:border-white dark:bg-white dark:text-zinc-900" : "border-zinc-100 hover:border-zinc-900 dark:border-zinc-800 dark:hover:border-white"
|
|
3024
|
+
),
|
|
3025
|
+
children: [
|
|
3026
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("span", { className: cn("text-[10px] font-bold uppercase tracking-widest", tone === "current" ? "text-zinc-400" : "text-zinc-400 group-hover:text-zinc-900 dark:group-hover:text-zinc-200"), children: [
|
|
3027
|
+
"Phase 0",
|
|
3028
|
+
i + 1
|
|
3029
|
+
] }),
|
|
3030
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)("span", { className: "text-sm font-black", children: step.title }),
|
|
3031
|
+
tone === "done" && /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(import_framer_motion.motion.div, { layoutId: "inter-check", className: "absolute -right-2 -top-2 rounded-full bg-zinc-900 p-1 text-white shadow-lg dark:bg-white dark:text-zinc-900", children: /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(import_lucide_react14.Check, { size: 14, strokeWidth: 3 }) })
|
|
3032
|
+
]
|
|
3033
|
+
},
|
|
3034
|
+
i
|
|
3035
|
+
);
|
|
3036
|
+
}) });
|
|
3037
|
+
}
|
|
3038
|
+
|
|
3039
|
+
// components/ui/switch.tsx
|
|
3040
|
+
var React21 = __toESM(require("react"));
|
|
3041
|
+
var import_class_variance_authority12 = require("class-variance-authority");
|
|
3042
|
+
var import_jsx_runtime25 = require("react/jsx-runtime");
|
|
3043
|
+
var switchTrackVariants = (0, import_class_variance_authority12.cva)(
|
|
3044
|
+
[
|
|
3045
|
+
"relative inline-flex shrink-0 cursor-pointer items-center rounded-full border border-transparent transition-colors duration-200",
|
|
3046
|
+
"focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-zinc-900/20 focus-visible:ring-offset-2 focus-visible:ring-offset-white",
|
|
3047
|
+
"dark:focus-visible:ring-zinc-100/20 dark:focus-visible:ring-offset-zinc-950",
|
|
3048
|
+
"disabled:cursor-not-allowed disabled:opacity-50",
|
|
3049
|
+
"data-[state=checked]:bg-zinc-900 data-[state=unchecked]:bg-zinc-200",
|
|
3050
|
+
"dark:data-[state=checked]:bg-zinc-100 dark:data-[state=unchecked]:bg-zinc-700",
|
|
3051
|
+
"hover:data-[state=unchecked]:bg-zinc-300 dark:hover:data-[state=unchecked]:bg-zinc-600",
|
|
3052
|
+
"hover:data-[state=checked]:bg-zinc-800 dark:hover:data-[state=checked]:bg-zinc-200"
|
|
3053
|
+
],
|
|
3054
|
+
{
|
|
3055
|
+
variants: {
|
|
3056
|
+
size: {
|
|
3057
|
+
sm: "h-5 w-9",
|
|
3058
|
+
md: "h-6 w-11",
|
|
3059
|
+
lg: "h-7 w-[3.25rem]"
|
|
3060
|
+
}
|
|
3061
|
+
},
|
|
3062
|
+
defaultVariants: { size: "md" }
|
|
3063
|
+
}
|
|
3064
|
+
);
|
|
3065
|
+
var switchThumbVariants = (0, import_class_variance_authority12.cva)(
|
|
3066
|
+
"pointer-events-none absolute left-0.5 top-1/2 block -translate-y-1/2 rounded-full bg-white shadow-sm transition-transform duration-200 dark:bg-zinc-950",
|
|
3067
|
+
{
|
|
3068
|
+
variants: {
|
|
3069
|
+
size: {
|
|
3070
|
+
sm: "h-3.5 w-3.5 data-[state=checked]:translate-x-4",
|
|
3071
|
+
md: "h-4 w-4 data-[state=checked]:translate-x-5",
|
|
3072
|
+
lg: "h-5 w-5 data-[state=checked]:translate-x-6"
|
|
3073
|
+
}
|
|
3074
|
+
},
|
|
3075
|
+
defaultVariants: { size: "md" }
|
|
3076
|
+
}
|
|
3077
|
+
);
|
|
3078
|
+
var Switch = React21.forwardRef(
|
|
3079
|
+
(_a, ref) => {
|
|
3080
|
+
var _b = _a, {
|
|
3081
|
+
className,
|
|
3082
|
+
size,
|
|
3083
|
+
checked,
|
|
3084
|
+
defaultChecked = false,
|
|
3085
|
+
onCheckedChange,
|
|
3086
|
+
disabled,
|
|
3087
|
+
label,
|
|
3088
|
+
description,
|
|
3089
|
+
id,
|
|
3090
|
+
onClick
|
|
3091
|
+
} = _b, props = __objRest(_b, [
|
|
3092
|
+
"className",
|
|
3093
|
+
"size",
|
|
3094
|
+
"checked",
|
|
3095
|
+
"defaultChecked",
|
|
3096
|
+
"onCheckedChange",
|
|
3097
|
+
"disabled",
|
|
3098
|
+
"label",
|
|
3099
|
+
"description",
|
|
3100
|
+
"id",
|
|
3101
|
+
"onClick"
|
|
3102
|
+
]);
|
|
3103
|
+
const generatedId = React21.useId();
|
|
3104
|
+
const switchId = id != null ? id : generatedId;
|
|
3105
|
+
const isControlled = checked !== void 0;
|
|
3106
|
+
const [uncontrolledChecked, setUncontrolledChecked] = React21.useState(defaultChecked);
|
|
3107
|
+
const isChecked = isControlled ? checked : uncontrolledChecked;
|
|
3108
|
+
const state = isChecked ? "checked" : "unchecked";
|
|
3109
|
+
const toggle = () => {
|
|
3110
|
+
if (disabled) return;
|
|
3111
|
+
const next = !isChecked;
|
|
3112
|
+
if (!isControlled) setUncontrolledChecked(next);
|
|
3113
|
+
onCheckedChange == null ? void 0 : onCheckedChange(next);
|
|
3114
|
+
};
|
|
3115
|
+
const switchControl = /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
|
|
3116
|
+
"button",
|
|
3117
|
+
__spreadProps(__spreadValues({
|
|
3118
|
+
ref,
|
|
3119
|
+
id: switchId,
|
|
3120
|
+
type: "button",
|
|
3121
|
+
role: "switch",
|
|
3122
|
+
"aria-checked": isChecked,
|
|
3123
|
+
"aria-labelledby": label ? `${switchId}-label` : void 0,
|
|
3124
|
+
"aria-describedby": description ? `${switchId}-description` : void 0,
|
|
3125
|
+
disabled,
|
|
3126
|
+
"data-state": state,
|
|
3127
|
+
className: cn(switchTrackVariants({ size }), className),
|
|
3128
|
+
onClick: (event) => {
|
|
3129
|
+
toggle();
|
|
3130
|
+
onClick == null ? void 0 : onClick(event);
|
|
3131
|
+
},
|
|
3132
|
+
onKeyDown: (event) => {
|
|
3133
|
+
if (event.key === " ") {
|
|
3134
|
+
event.preventDefault();
|
|
3135
|
+
toggle();
|
|
3136
|
+
}
|
|
3137
|
+
}
|
|
3138
|
+
}, props), {
|
|
3139
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("span", { "data-state": state, className: switchThumbVariants({ size }) })
|
|
3140
|
+
})
|
|
3141
|
+
);
|
|
3142
|
+
if (!label && !description) {
|
|
3143
|
+
return switchControl;
|
|
3144
|
+
}
|
|
3145
|
+
return /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)(
|
|
3146
|
+
"div",
|
|
3147
|
+
{
|
|
3148
|
+
className: cn(
|
|
3149
|
+
"flex items-start justify-between gap-4",
|
|
3150
|
+
disabled && "opacity-60"
|
|
3151
|
+
),
|
|
3152
|
+
children: [
|
|
3153
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("div", { className: "flex min-w-0 flex-col gap-0.5", children: [
|
|
3154
|
+
label && /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
|
|
3155
|
+
"label",
|
|
3156
|
+
{
|
|
3157
|
+
id: `${switchId}-label`,
|
|
3158
|
+
htmlFor: switchId,
|
|
3159
|
+
className: cn(
|
|
3160
|
+
"text-sm font-medium leading-snug text-zinc-800 dark:text-zinc-100",
|
|
3161
|
+
!disabled && "cursor-pointer"
|
|
3162
|
+
),
|
|
3163
|
+
children: label
|
|
3164
|
+
}
|
|
3165
|
+
),
|
|
3166
|
+
description && /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
|
|
3167
|
+
"p",
|
|
3168
|
+
{
|
|
3169
|
+
id: `${switchId}-description`,
|
|
3170
|
+
className: "text-xs leading-relaxed text-zinc-500 dark:text-zinc-400",
|
|
3171
|
+
children: description
|
|
3172
|
+
}
|
|
3173
|
+
)
|
|
3174
|
+
] }),
|
|
3175
|
+
switchControl
|
|
3176
|
+
]
|
|
3177
|
+
}
|
|
3178
|
+
);
|
|
3179
|
+
}
|
|
3180
|
+
);
|
|
3181
|
+
Switch.displayName = "Switch";
|
|
3182
|
+
|
|
3183
|
+
// components/ui/tabs.tsx
|
|
3184
|
+
var import_react10 = __toESM(require("react"));
|
|
3185
|
+
var import_jsx_runtime26 = require("react/jsx-runtime");
|
|
3186
|
+
var TabsContext = (0, import_react10.createContext)(null);
|
|
3187
|
+
function useTabs() {
|
|
3188
|
+
const context = (0, import_react10.useContext)(TabsContext);
|
|
3189
|
+
if (!context) return { activeTab: "", setActiveTab: () => {
|
|
3190
|
+
}, variant: "", uid: "" };
|
|
3191
|
+
return context;
|
|
3192
|
+
}
|
|
3193
|
+
function Tabs({
|
|
3194
|
+
children,
|
|
3195
|
+
defaultValue,
|
|
3196
|
+
variant = "underline",
|
|
3197
|
+
className
|
|
3198
|
+
}) {
|
|
3199
|
+
const [activeTab, setActiveTab] = (0, import_react10.useState)(defaultValue);
|
|
3200
|
+
const uid = import_react10.default.useId();
|
|
3201
|
+
return /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(TabsContext.Provider, { value: { activeTab, setActiveTab, variant, uid }, children: /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("div", { className: cn(variant === "vertical" ? "flex gap-8" : "flex flex-col gap-4", className), children }) });
|
|
3202
|
+
}
|
|
3203
|
+
function TabsList({ children, className }) {
|
|
3204
|
+
const { variant } = useTabs();
|
|
3205
|
+
const variantStyles = {
|
|
3206
|
+
underline: "flex min-w-0 gap-4 overflow-x-auto border-b border-zinc-200 dark:border-zinc-800 sm:gap-8 [-ms-overflow-style:none] [scrollbar-width:none] [&::-webkit-scrollbar]:hidden",
|
|
3207
|
+
pill: "flex min-w-0 flex-wrap gap-2",
|
|
3208
|
+
segmented: "inline-flex max-w-full flex-wrap p-1 bg-zinc-100 dark:bg-zinc-900 rounded-xl gap-1",
|
|
3209
|
+
bordered: "flex min-w-0 flex-wrap gap-3",
|
|
3210
|
+
filled: "flex min-w-0 flex-wrap gap-1 bg-zinc-50 dark:bg-zinc-900/50 p-1.5 rounded-lg",
|
|
3211
|
+
icon: "flex min-w-0 flex-wrap gap-6 sm:gap-10",
|
|
3212
|
+
vertical: "flex flex-col border-l border-zinc-100 dark:border-zinc-800",
|
|
3213
|
+
floating: "inline-flex max-w-full flex-wrap bg-white dark:bg-zinc-950 shadow-xl border border-zinc-100 dark:border-zinc-800 p-2 rounded-2xl gap-2",
|
|
3214
|
+
scrollable: "flex min-w-0 gap-6 overflow-x-auto pb-2 docs-scrollbar whitespace-nowrap",
|
|
3215
|
+
card: "flex min-w-0 gap-1 overflow-x-auto border-b border-zinc-100 dark:border-zinc-800 [-ms-overflow-style:none] [scrollbar-width:none] [&::-webkit-scrollbar]:hidden"
|
|
3216
|
+
};
|
|
3217
|
+
return /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
|
|
3218
|
+
"div",
|
|
3219
|
+
{
|
|
3220
|
+
role: "tablist",
|
|
3221
|
+
"aria-orientation": variant === "vertical" ? "vertical" : "horizontal",
|
|
3222
|
+
className: cn(variantStyles[variant], className),
|
|
3223
|
+
children
|
|
3224
|
+
}
|
|
3225
|
+
);
|
|
3226
|
+
}
|
|
3227
|
+
function TabsTrigger({
|
|
3228
|
+
value,
|
|
3229
|
+
label,
|
|
3230
|
+
icon: Icon,
|
|
3231
|
+
badge,
|
|
3232
|
+
className
|
|
3233
|
+
}) {
|
|
3234
|
+
const { activeTab, setActiveTab, variant, uid } = useTabs();
|
|
3235
|
+
const isActive = activeTab === value;
|
|
3236
|
+
const triggerStyles = {
|
|
3237
|
+
underline: cn(
|
|
3238
|
+
"relative pb-3 text-sm font-medium transition-all",
|
|
3239
|
+
isActive ? "text-zinc-900 dark:text-white" : "text-zinc-500 hover:text-zinc-900 dark:hover:text-zinc-100"
|
|
3240
|
+
),
|
|
3241
|
+
pill: cn(
|
|
3242
|
+
"px-4 py-2 rounded-full text-sm font-semibold transition-all",
|
|
3243
|
+
isActive ? "bg-zinc-900 text-white dark:bg-white dark:text-zinc-900 shadow-lg" : "bg-white dark:bg-zinc-900 text-zinc-600 border border-zinc-100 dark:border-zinc-800 hover:bg-zinc-50"
|
|
3244
|
+
),
|
|
3245
|
+
segmented: cn(
|
|
3246
|
+
"px-6 py-1.5 rounded-lg text-xs font-bold transition-all",
|
|
3247
|
+
isActive ? "bg-white dark:bg-zinc-800 text-zinc-900 dark:text-white shadow-sm" : "text-zinc-500 hover:text-zinc-700"
|
|
3248
|
+
),
|
|
3249
|
+
bordered: cn(
|
|
3250
|
+
"px-4 py-2 rounded-lg border-2 text-sm font-bold transition-all",
|
|
3251
|
+
isActive ? "border-zinc-900 text-zinc-900 dark:border-white dark:text-white" : "border-transparent text-zinc-400 hover:border-zinc-200"
|
|
3252
|
+
),
|
|
3253
|
+
filled: cn(
|
|
3254
|
+
"px-4 py-2 rounded-md text-sm font-medium transition-all",
|
|
3255
|
+
isActive ? "bg-zinc-900 text-white dark:bg-white dark:text-zinc-900" : "text-zinc-500 hover:text-zinc-800 dark:hover:text-zinc-200"
|
|
3256
|
+
),
|
|
3257
|
+
card: cn(
|
|
3258
|
+
"relative shrink-0 px-4 py-2.5 text-sm font-medium transition-all",
|
|
3259
|
+
isActive ? "text-zinc-900 dark:text-white" : "text-zinc-500 hover:text-zinc-800 dark:hover:text-zinc-200"
|
|
3260
|
+
),
|
|
3261
|
+
icon: cn(
|
|
3262
|
+
"flex flex-col items-center gap-1.5 transition-all",
|
|
3263
|
+
isActive ? "text-zinc-900 dark:text-white" : "text-zinc-400 hover:text-zinc-700"
|
|
3264
|
+
),
|
|
3265
|
+
vertical: cn(
|
|
3266
|
+
"pl-6 pr-12 py-2 text-sm font-medium border-l-2 -ml-[2px] transition-all",
|
|
3267
|
+
isActive ? "border-zinc-900 text-zinc-900 dark:border-white dark:text-white bg-zinc-50 dark:bg-zinc-900" : "border-transparent text-zinc-500 hover:text-zinc-800"
|
|
3268
|
+
),
|
|
3269
|
+
floating: cn(
|
|
3270
|
+
"px-4 py-2 rounded-xl text-sm font-medium transition-all",
|
|
3271
|
+
isActive ? "bg-zinc-900 text-white dark:bg-white dark:text-zinc-900" : "text-zinc-500 hover:bg-zinc-50"
|
|
3272
|
+
)
|
|
3273
|
+
};
|
|
3274
|
+
return /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)(
|
|
3275
|
+
"button",
|
|
3276
|
+
{
|
|
3277
|
+
type: "button",
|
|
3278
|
+
role: "tab",
|
|
3279
|
+
id: `${uid}-tab-${value}`,
|
|
3280
|
+
"aria-selected": isActive,
|
|
3281
|
+
"aria-controls": `${uid}-panel-${value}`,
|
|
3282
|
+
tabIndex: isActive ? 0 : -1,
|
|
3283
|
+
onClick: () => setActiveTab(value),
|
|
3284
|
+
className: cn("shrink-0 outline-none", triggerStyles[variant] || triggerStyles["underline"], className),
|
|
3285
|
+
children: [
|
|
3286
|
+
/* @__PURE__ */ (0, import_jsx_runtime26.jsxs)("div", { className: "flex items-center gap-2", children: [
|
|
3287
|
+
Icon && /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(Icon, { size: variant === "icon" ? 20 : 16 }),
|
|
3288
|
+
/* @__PURE__ */ (0, import_jsx_runtime26.jsx)("span", { children: label }),
|
|
3289
|
+
badge && /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("span", { className: cn("flex h-4 w-4 items-center justify-center rounded-full text-[10px] text-white", isActive ? "bg-zinc-800 dark:bg-zinc-700" : "bg-red-500"), children: badge })
|
|
3290
|
+
] }),
|
|
3291
|
+
variant === "underline" && isActive && /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("div", { className: "absolute bottom-0 left-0 h-[2.5px] w-full bg-zinc-900 dark:bg-white rounded-full animate-in fade-in" })
|
|
3292
|
+
]
|
|
3293
|
+
}
|
|
3294
|
+
);
|
|
3295
|
+
}
|
|
3296
|
+
function TabsContent({ value, children, className }) {
|
|
3297
|
+
const { activeTab, uid } = useTabs();
|
|
3298
|
+
if (activeTab !== value) return null;
|
|
3299
|
+
return /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
|
|
3300
|
+
"div",
|
|
3301
|
+
{
|
|
3302
|
+
role: "tabpanel",
|
|
3303
|
+
id: `${uid}-panel-${value}`,
|
|
3304
|
+
"aria-labelledby": `${uid}-tab-${value}`,
|
|
3305
|
+
tabIndex: 0,
|
|
3306
|
+
className: cn("outline-none animate-in fade-in slide-in-from-bottom-2 duration-300", className),
|
|
3307
|
+
children
|
|
3308
|
+
}
|
|
3309
|
+
);
|
|
3310
|
+
}
|
|
3311
|
+
|
|
3312
|
+
// components/ui/tooltip.tsx
|
|
3313
|
+
var React23 = __toESM(require("react"));
|
|
3314
|
+
var import_react_dom3 = require("react-dom");
|
|
3315
|
+
var import_class_variance_authority13 = require("class-variance-authority");
|
|
3316
|
+
var import_jsx_runtime27 = require("react/jsx-runtime");
|
|
3317
|
+
var tooltipVariants = (0, import_class_variance_authority13.cva)(
|
|
3318
|
+
[
|
|
3319
|
+
"pointer-events-none fixed z-50 max-w-[260px] rounded-lg px-3 py-2",
|
|
3320
|
+
"text-[13px] font-medium leading-normal tracking-tight",
|
|
3321
|
+
"bg-zinc-900 text-zinc-50",
|
|
3322
|
+
"shadow-[0_4px_16px_rgba(0,0,0,0.14),0_0_0_1px_rgba(255,255,255,0.06)]",
|
|
3323
|
+
"dark:bg-zinc-100 dark:text-zinc-900",
|
|
3324
|
+
"dark:shadow-[0_4px_16px_rgba(0,0,0,0.35),0_0_0_1px_rgba(0,0,0,0.06)]",
|
|
3325
|
+
"transition-[opacity,transform] duration-200 ease-[cubic-bezier(0.16,1,0.3,1)]",
|
|
3326
|
+
"will-change-[opacity,transform]"
|
|
3327
|
+
],
|
|
3328
|
+
{
|
|
3329
|
+
variants: {
|
|
3330
|
+
visible: {
|
|
3331
|
+
true: "opacity-100 scale-100",
|
|
3332
|
+
false: "opacity-0 scale-[0.97]"
|
|
3333
|
+
},
|
|
3334
|
+
side: {
|
|
3335
|
+
top: "origin-bottom",
|
|
3336
|
+
bottom: "origin-top",
|
|
3337
|
+
left: "origin-right",
|
|
3338
|
+
right: "origin-left"
|
|
3339
|
+
}
|
|
3340
|
+
},
|
|
3341
|
+
defaultVariants: { visible: false, side: "top" }
|
|
3342
|
+
}
|
|
3343
|
+
);
|
|
3344
|
+
var VIEWPORT_PADDING = 10;
|
|
3345
|
+
var ARROW_SIZE = 6;
|
|
3346
|
+
function getTooltipPosition(triggerRect, tooltipRect, side, align, sideOffset) {
|
|
3347
|
+
const offset = sideOffset + ARROW_SIZE;
|
|
3348
|
+
let top = 0;
|
|
3349
|
+
let left = 0;
|
|
3350
|
+
if (side === "top") {
|
|
3351
|
+
top = triggerRect.top - tooltipRect.height - offset;
|
|
3352
|
+
left = alignTooltipHorizontal(triggerRect, tooltipRect, align);
|
|
3353
|
+
} else if (side === "bottom") {
|
|
3354
|
+
top = triggerRect.bottom + offset;
|
|
3355
|
+
left = alignTooltipHorizontal(triggerRect, tooltipRect, align);
|
|
3356
|
+
} else if (side === "left") {
|
|
3357
|
+
top = alignTooltipVertical(triggerRect, tooltipRect, align);
|
|
3358
|
+
left = triggerRect.left - tooltipRect.width - offset;
|
|
3359
|
+
} else {
|
|
3360
|
+
top = alignTooltipVertical(triggerRect, tooltipRect, align);
|
|
3361
|
+
left = triggerRect.right + offset;
|
|
3362
|
+
}
|
|
3363
|
+
const maxLeft = window.innerWidth - tooltipRect.width - VIEWPORT_PADDING;
|
|
3364
|
+
const maxTop = window.innerHeight - tooltipRect.height - VIEWPORT_PADDING;
|
|
3365
|
+
return {
|
|
3366
|
+
top: Math.min(Math.max(top, VIEWPORT_PADDING), maxTop),
|
|
3367
|
+
left: Math.min(Math.max(left, VIEWPORT_PADDING), maxLeft)
|
|
3368
|
+
};
|
|
3369
|
+
}
|
|
3370
|
+
function alignTooltipHorizontal(triggerRect, tooltipRect, align) {
|
|
3371
|
+
if (align === "start") return triggerRect.left;
|
|
3372
|
+
if (align === "end") return triggerRect.right - tooltipRect.width;
|
|
3373
|
+
return triggerRect.left + triggerRect.width / 2 - tooltipRect.width / 2;
|
|
3374
|
+
}
|
|
3375
|
+
function alignTooltipVertical(triggerRect, tooltipRect, align) {
|
|
3376
|
+
if (align === "start") return triggerRect.top;
|
|
3377
|
+
if (align === "end") return triggerRect.bottom - tooltipRect.height;
|
|
3378
|
+
return triggerRect.top + triggerRect.height / 2 - tooltipRect.height / 2;
|
|
3379
|
+
}
|
|
3380
|
+
function TooltipArrow({ side }) {
|
|
3381
|
+
const position = {
|
|
3382
|
+
top: "bottom-0 left-1/2 -translate-x-1/2 translate-y-[calc(100%-1px)]",
|
|
3383
|
+
bottom: "top-0 left-1/2 -translate-x-1/2 -translate-y-[calc(100%-1px)] rotate-180",
|
|
3384
|
+
left: "right-0 top-1/2 -translate-y-1/2 translate-x-[calc(100%-1px)] -rotate-90",
|
|
3385
|
+
right: "left-0 top-1/2 -translate-y-1/2 -translate-x-[calc(100%-1px)] rotate-90"
|
|
3386
|
+
}[side];
|
|
3387
|
+
return /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
|
|
3388
|
+
"svg",
|
|
3389
|
+
{
|
|
3390
|
+
"aria-hidden": true,
|
|
3391
|
+
width: "10",
|
|
3392
|
+
height: "5",
|
|
3393
|
+
viewBox: "0 0 10 5",
|
|
3394
|
+
className: cn(
|
|
3395
|
+
"absolute text-zinc-900 dark:text-zinc-100",
|
|
3396
|
+
position
|
|
3397
|
+
),
|
|
3398
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime27.jsx)("path", { fill: "currentColor", d: "M0 0h10L5 5 0 0z" })
|
|
3399
|
+
}
|
|
3400
|
+
);
|
|
3401
|
+
}
|
|
3402
|
+
function Tooltip({
|
|
3403
|
+
content,
|
|
3404
|
+
children,
|
|
3405
|
+
side = "top",
|
|
3406
|
+
align = "center",
|
|
3407
|
+
sideOffset = 8,
|
|
3408
|
+
delayDuration = 250,
|
|
3409
|
+
disabled = false,
|
|
3410
|
+
className
|
|
3411
|
+
}) {
|
|
3412
|
+
const [open, setOpen] = React23.useState(false);
|
|
3413
|
+
const [visible, setVisible] = React23.useState(false);
|
|
3414
|
+
const [mounted, setMounted] = React23.useState(false);
|
|
3415
|
+
const [position, setPosition] = React23.useState({ top: -9999, left: -9999 });
|
|
3416
|
+
const timeoutRef = React23.useRef(null);
|
|
3417
|
+
const triggerRef = React23.useRef(null);
|
|
3418
|
+
const tooltipRef = React23.useRef(null);
|
|
3419
|
+
const id = React23.useId();
|
|
3420
|
+
React23.useEffect(() => setMounted(true), []);
|
|
3421
|
+
const clearTimer = () => {
|
|
3422
|
+
if (timeoutRef.current) {
|
|
3423
|
+
clearTimeout(timeoutRef.current);
|
|
3424
|
+
timeoutRef.current = null;
|
|
3425
|
+
}
|
|
3426
|
+
};
|
|
3427
|
+
const updatePosition = React23.useCallback(() => {
|
|
3428
|
+
const trigger2 = triggerRef.current;
|
|
3429
|
+
const tooltip = tooltipRef.current;
|
|
3430
|
+
if (!trigger2 || !tooltip) return;
|
|
3431
|
+
const triggerRect = trigger2.getBoundingClientRect();
|
|
3432
|
+
const tooltipRect = tooltip.getBoundingClientRect();
|
|
3433
|
+
setPosition(getTooltipPosition(triggerRect, tooltipRect, side, align, sideOffset));
|
|
3434
|
+
requestAnimationFrame(() => setVisible(true));
|
|
3435
|
+
}, [side, align, sideOffset]);
|
|
3436
|
+
const show = () => {
|
|
3437
|
+
if (disabled) return;
|
|
3438
|
+
clearTimer();
|
|
3439
|
+
timeoutRef.current = setTimeout(() => {
|
|
3440
|
+
setVisible(false);
|
|
3441
|
+
setOpen(true);
|
|
3442
|
+
}, delayDuration);
|
|
3443
|
+
};
|
|
3444
|
+
const hide = () => {
|
|
3445
|
+
clearTimer();
|
|
3446
|
+
setVisible(false);
|
|
3447
|
+
setOpen(false);
|
|
3448
|
+
};
|
|
3449
|
+
React23.useEffect(() => clearTimer, []);
|
|
3450
|
+
React23.useLayoutEffect(() => {
|
|
3451
|
+
if (!open) return;
|
|
3452
|
+
updatePosition();
|
|
3453
|
+
const handleUpdate = () => updatePosition();
|
|
3454
|
+
window.addEventListener("scroll", handleUpdate, true);
|
|
3455
|
+
window.addEventListener("resize", handleUpdate);
|
|
3456
|
+
return () => {
|
|
3457
|
+
window.removeEventListener("scroll", handleUpdate, true);
|
|
3458
|
+
window.removeEventListener("resize", handleUpdate);
|
|
3459
|
+
};
|
|
3460
|
+
}, [open, updatePosition, content]);
|
|
3461
|
+
const child = React23.Children.only(children);
|
|
3462
|
+
const trigger = React23.isValidElement(child) ? React23.cloneElement(
|
|
3463
|
+
child,
|
|
3464
|
+
{ "aria-describedby": open && visible ? id : void 0 }
|
|
3465
|
+
) : children;
|
|
3466
|
+
const tooltipNode = open ? /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)(
|
|
3467
|
+
"div",
|
|
3468
|
+
{
|
|
3469
|
+
ref: tooltipRef,
|
|
3470
|
+
id,
|
|
3471
|
+
role: "tooltip",
|
|
3472
|
+
"aria-hidden": !visible,
|
|
3473
|
+
style: { top: position.top, left: position.left },
|
|
3474
|
+
className: cn(tooltipVariants({ visible, side }), className),
|
|
3475
|
+
children: [
|
|
3476
|
+
content,
|
|
3477
|
+
/* @__PURE__ */ (0, import_jsx_runtime27.jsx)(TooltipArrow, { side })
|
|
3478
|
+
]
|
|
3479
|
+
}
|
|
3480
|
+
) : null;
|
|
3481
|
+
return /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)(import_jsx_runtime27.Fragment, { children: [
|
|
3482
|
+
/* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
|
|
3483
|
+
"span",
|
|
3484
|
+
{
|
|
3485
|
+
ref: triggerRef,
|
|
3486
|
+
className: "inline-flex",
|
|
3487
|
+
onMouseEnter: show,
|
|
3488
|
+
onMouseLeave: hide,
|
|
3489
|
+
onFocus: show,
|
|
3490
|
+
onBlur: hide,
|
|
3491
|
+
children: trigger
|
|
3492
|
+
}
|
|
3493
|
+
),
|
|
3494
|
+
mounted && tooltipNode ? (0, import_react_dom3.createPortal)(tooltipNode, document.body) : null
|
|
3495
|
+
] });
|
|
3496
|
+
}
|
|
3497
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
3498
|
+
0 && (module.exports = {
|
|
3499
|
+
AILoader,
|
|
3500
|
+
Accordion,
|
|
3501
|
+
AccordionItem,
|
|
3502
|
+
AccordionLink,
|
|
3503
|
+
AccordionNested,
|
|
3504
|
+
AccordionSkeletonChevron,
|
|
3505
|
+
AccordionSkeletonPlus,
|
|
3506
|
+
Alert,
|
|
3507
|
+
Avatar,
|
|
3508
|
+
AvatarGroup,
|
|
3509
|
+
Badge,
|
|
3510
|
+
BlurReveal,
|
|
3511
|
+
BreadcrumbStepper,
|
|
3512
|
+
Button,
|
|
3513
|
+
Card,
|
|
3514
|
+
CardContent,
|
|
3515
|
+
CardDescription,
|
|
3516
|
+
CardFooter,
|
|
3517
|
+
CardHeader,
|
|
3518
|
+
CardSkeletonGrid,
|
|
3519
|
+
CardTitle,
|
|
3520
|
+
Checkbox,
|
|
3521
|
+
CodeBlock,
|
|
3522
|
+
DataTable,
|
|
3523
|
+
Dialog,
|
|
3524
|
+
DialogAction,
|
|
3525
|
+
DialogContent,
|
|
3526
|
+
DialogFooter,
|
|
3527
|
+
DialogHeader,
|
|
3528
|
+
DialogItem,
|
|
3529
|
+
DialogTrigger,
|
|
3530
|
+
DotStepper,
|
|
3531
|
+
DotWave,
|
|
3532
|
+
Dropdown,
|
|
3533
|
+
DropdownContent,
|
|
3534
|
+
DropdownDivider,
|
|
3535
|
+
DropdownItem,
|
|
3536
|
+
DropdownLabel,
|
|
3537
|
+
DropdownTrigger,
|
|
3538
|
+
ExpandableRow,
|
|
3539
|
+
FeatureCard,
|
|
3540
|
+
Field,
|
|
3541
|
+
HalfCircles,
|
|
3542
|
+
HorizontalStepper,
|
|
3543
|
+
Input,
|
|
3544
|
+
InputAddon,
|
|
3545
|
+
InputAutocomplete,
|
|
3546
|
+
InputFilled,
|
|
3547
|
+
InputFloating,
|
|
3548
|
+
InputIcon,
|
|
3549
|
+
InputOTP,
|
|
3550
|
+
InputPassword,
|
|
3551
|
+
InputSearch,
|
|
3552
|
+
InputStandard,
|
|
3553
|
+
InputUnderline,
|
|
3554
|
+
InteractiveStepper,
|
|
3555
|
+
Label,
|
|
3556
|
+
ListSkeleton,
|
|
3557
|
+
LoadBar,
|
|
3558
|
+
Menu,
|
|
3559
|
+
MenuDivider,
|
|
3560
|
+
MenuItem,
|
|
3561
|
+
MenuLabel,
|
|
3562
|
+
Modal,
|
|
3563
|
+
ModalBody,
|
|
3564
|
+
ModalClose,
|
|
3565
|
+
ModalContent,
|
|
3566
|
+
ModalDescription,
|
|
3567
|
+
ModalFooter,
|
|
3568
|
+
ModalHeader,
|
|
3569
|
+
ModalOption,
|
|
3570
|
+
ModalTitle,
|
|
3571
|
+
ModalTrigger,
|
|
3572
|
+
MorphingLoader,
|
|
3573
|
+
OrbitLoader,
|
|
3574
|
+
Pagination,
|
|
3575
|
+
Progress,
|
|
3576
|
+
ProgressBar,
|
|
3577
|
+
ProgressRing,
|
|
3578
|
+
ProgressStepper,
|
|
3579
|
+
PulseLoader,
|
|
3580
|
+
Radio,
|
|
3581
|
+
RadioGroup,
|
|
3582
|
+
SegmentedStepper,
|
|
3583
|
+
SkeletonShimmer,
|
|
3584
|
+
SpinnerDots,
|
|
3585
|
+
SpinnerGradient,
|
|
3586
|
+
SquaresLoader,
|
|
3587
|
+
Switch,
|
|
3588
|
+
Table,
|
|
3589
|
+
TableBody,
|
|
3590
|
+
TableCell,
|
|
3591
|
+
TableHead,
|
|
3592
|
+
TableHeader,
|
|
3593
|
+
TableRow,
|
|
3594
|
+
TableSkeleton,
|
|
3595
|
+
Tabs,
|
|
3596
|
+
TabsContent,
|
|
3597
|
+
TabsList,
|
|
3598
|
+
TabsTrigger,
|
|
3599
|
+
ThreeDots,
|
|
3600
|
+
TimelineStepper,
|
|
3601
|
+
Tooltip,
|
|
3602
|
+
TypingIndicator,
|
|
3603
|
+
VerticalStepper,
|
|
3604
|
+
avatarVariants,
|
|
3605
|
+
badgeVariants,
|
|
3606
|
+
buttonVariants,
|
|
3607
|
+
checkboxControlVariants,
|
|
3608
|
+
getGradientFromName,
|
|
3609
|
+
getInitials,
|
|
3610
|
+
inputVariants,
|
|
3611
|
+
labelVariants,
|
|
3612
|
+
menuItemVariants,
|
|
3613
|
+
menuVariants,
|
|
3614
|
+
modalContentVariants,
|
|
3615
|
+
overlayVariants,
|
|
3616
|
+
radioControlVariants
|
|
3617
|
+
});
|
|
3618
|
+
//# sourceMappingURL=index.js.map
|