UNPKG

niva-ui

Version:

A beautiful, minimalistic React + Tailwind UI framework for SaaS applications

2,404 lines 96.1 kB
"use client";
var __create = Object.create;
var __defProp = Object.defineProperty;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
var __getOwnPropNames = Object.getOwnPropertyNames;
var __getProtoOf = Object.getPrototypeOf;
var __hasOwnProp = Object.prototype.hasOwnProperty;
var __export = (target, all) => {
  for (var name in all)
    __defProp(target, name, { get: all[name], enumerable: true });
};
var __copyProps = (to, from, except, desc) => {
  if (from && typeof from === "object" || typeof from === "function") {
    for (let key of __getOwnPropNames(from))
      if (!__hasOwnProp.call(to, key) && key !== except)
        __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
  }
  return to;
};
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
  // If the importer is in node compatibility mode or this is not an ESM
  // file that has been converted to a CommonJS file using a Babel-
  // compatible transform (i.e. "__esModule" has not been set), then set
  // "default" to the CommonJS "module.exports" for node compatibility.
  isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
  mod
));
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);

// src/index.ts
var index_exports = {};
__export(index_exports, {
  Alert: () => Alert,
  AlertDescription: () => AlertDescription,
  AlertIcon: () => AlertIcon,
  AlertTitle: () => AlertTitle,
  Avatar: () => Avatar,
  Badge: () => Badge,
  Button: () => Button,
  Card: () => Card,
  CardContent: () => CardContent,
  CardDescription: () => CardDescription,
  CardFooter: () => CardFooter,
  CardHeader: () => CardHeader,
  CardTitle: () => CardTitle,
  Chip: () => Chip,
  ChipGroup: () => ChipGroup,
  CodeBlock: () => CodeBlock,
  DataTable: () => DataTable,
  DropdownMenu: () => DropdownMenu,
  DropdownMenuCheckboxItem: () => DropdownMenuCheckboxItem,
  DropdownMenuContent: () => DropdownMenuContent,
  DropdownMenuGroup: () => DropdownMenuGroup,
  DropdownMenuItem: () => DropdownMenuItem,
  DropdownMenuLabel: () => DropdownMenuLabel,
  DropdownMenuPortal: () => DropdownMenuPortal,
  DropdownMenuRadioGroup: () => DropdownMenuRadioGroup,
  DropdownMenuRadioItem: () => DropdownMenuRadioItem,
  DropdownMenuSeparator: () => DropdownMenuSeparator,
  DropdownMenuShortcut: () => DropdownMenuShortcut,
  DropdownMenuSub: () => DropdownMenuSub,
  DropdownMenuSubContent: () => DropdownMenuSubContent,
  DropdownMenuSubTrigger: () => DropdownMenuSubTrigger,
  DropdownMenuTrigger: () => DropdownMenuTrigger,
  Form: () => Form,
  FormField: () => FormField,
  FormSubmit: () => FormSubmit,
  Input: () => Input,
  Loader: () => Loader,
  MetricCard: () => MetricCard,
  Modal: () => Modal,
  ModalContent: () => ModalContent,
  ModalDescription: () => ModalDescription,
  ModalFooter: () => ModalFooter,
  ModalHeader: () => ModalHeader,
  ModalTitle: () => ModalTitle,
  Navbar: () => Navbar,
  PageLoader: () => PageLoader,
  Pagination: () => Pagination,
  PaginationInfo: () => PaginationInfo,
  SearchBar: () => SearchBar,
  Select: () => Select,
  Sidebar: () => Sidebar,
  Skeleton: () => Skeleton,
  StatCard: () => StatCard,
  Table: () => Table,
  TableBody: () => TableBody,
  TableCaption: () => TableCaption,
  TableCell: () => TableCell,
  TableFooter: () => TableFooter,
  TableHead: () => TableHead,
  TableHeader: () => TableHeader,
  TableRow: () => TableRow,
  ThemeProvider: () => ThemeProvider,
  Toast: () => Toast,
  ToastContainer: () => ToastContainer,
  ToastProvider: () => ToastProvider,
  avatarVariants: () => avatarVariants,
  badgeVariants: () => badgeVariants,
  buttonVariants: () => buttonVariants,
  cn: () => cn,
  formVariants: () => formVariants,
  inputVariants: () => inputVariants,
  modalVariants: () => modalVariants,
  navbarVariants: () => navbarVariants,
  paginationVariants: () => paginationVariants,
  searchBarVariants: () => searchBarVariants,
  selectVariants: () => selectVariants,
  sidebarVariants: () => sidebarVariants,
  statCardVariants: () => statCardVariants,
  toast: () => toast,
  toastVariants: () => toastVariants,
  useConfirmModal: () => useConfirmModal,
  useFormContext: () => useFormContext,
  useSidebar: () => useSidebar,
  useToast: () => useToast
});
module.exports = __toCommonJS(index_exports);

// src/components/ui/button.tsx
var React2 = __toESM(require("react"));
var import_react_slot = require("@radix-ui/react-slot");
var import_class_variance_authority = require("class-variance-authority");

// src/lib/utils.ts
var import_clsx = require("clsx");
var import_tailwind_merge = require("tailwind-merge");
function cn(...inputs) {
  return (0, import_tailwind_merge.twMerge)((0, import_clsx.clsx)(inputs));
}

// src/components/ui/button.tsx
var buttonVariants = (0, import_class_variance_authority.cva)(
  "inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium ring-offset-background transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0",
  {
    variants: {
      variant: {
        default: "bg-primary text-primary-foreground hover:bg-primary/90",
        destructive: "bg-destructive text-destructive-foreground hover:bg-destructive/90",
        outline: "border border-input bg-background hover:bg-accent hover:text-accent-foreground",
        secondary: "bg-secondary text-secondary-foreground hover:bg-secondary/80",
        ghost: "hover:bg-accent hover:text-accent-foreground",
        link: "text-primary underline-offset-4 hover:underline"
      },
      size: {
        default: "h-10 px-4 py-2",
        sm: "h-9 rounded-md px-3",
        lg: "h-11 rounded-md px-8",
        icon: "h-10 w-10"
      }
    },
    defaultVariants: {
      variant: "default",
      size: "default"
    }
  }
);
var Button = React2.forwardRef(
  ({ className, variant, size, asChild = false, ...props }, ref) => {
    const Comp = asChild ? import_react_slot.Slot : "button";
    return /* @__PURE__ */ React2.createElement(
      Comp,
      {
        className: cn(buttonVariants({ variant, size, className })),
        ref,
        ...props
      }
    );
  }
);
Button.displayName = "Button";

// src/components/ui/badge.tsx
var React3 = __toESM(require("react"));
var import_class_variance_authority2 = require("class-variance-authority");
var badgeVariants = (0, import_class_variance_authority2.cva)(
  "inline-flex items-center rounded-full border px-2.5 py-0.5 text-xs font-semibold transition-colors focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2",
  {
    variants: {
      variant: {
        default: "border-transparent bg-primary text-primary-foreground hover:bg-primary/80",
        secondary: "border-transparent bg-secondary text-secondary-foreground hover:bg-secondary/80",
        destructive: "border-transparent bg-destructive text-destructive-foreground hover:bg-destructive/80",
        outline: "text-foreground"
      }
    },
    defaultVariants: {
      variant: "default"
    }
  }
);
function Badge({ className, variant, ...props }) {
  return /* @__PURE__ */ React3.createElement("div", { className: cn(badgeVariants({ variant }), className), ...props });
}

// src/components/ui/card.tsx
var React4 = __toESM(require("react"));
var Card = React4.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ React4.createElement(
  "div",
  {
    ref,
    className: cn(
      "rounded-lg border bg-card text-card-foreground shadow-sm",
      className
    ),
    ...props
  }
));
Card.displayName = "Card";
var CardHeader = React4.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ React4.createElement(
  "div",
  {
    ref,
    className: cn("flex flex-col space-y-1.5 p-6", className),
    ...props
  }
));
CardHeader.displayName = "CardHeader";
var CardTitle = React4.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ React4.createElement(
  "h3",
  {
    ref,
    className: cn(
      "text-2xl font-semibold leading-none tracking-tight",
      className
    ),
    ...props
  }
));
CardTitle.displayName = "CardTitle";
var CardDescription = React4.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ React4.createElement(
  "p",
  {
    ref,
    className: cn("text-sm text-muted-foreground", className),
    ...props
  }
));
CardDescription.displayName = "CardDescription";
var CardContent = React4.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ React4.createElement("div", { ref, className: cn("p-6 pt-0", className), ...props }));
CardContent.displayName = "CardContent";
var CardFooter = React4.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ React4.createElement(
  "div",
  {
    ref,
    className: cn("flex items-center p-6 pt-0", className),
    ...props
  }
));
CardFooter.displayName = "CardFooter";

// src/components/ui/input.tsx
var React5 = __toESM(require("react"));
var import_class_variance_authority3 = require("class-variance-authority");
var inputVariants = (0, import_class_variance_authority3.cva)(
  "flex w-full rounded-md border border-input bg-background px-3 py-2 text-sm ring-offset-background file:border-0 file:bg-transparent file:text-sm file:font-medium placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50",
  {
    variants: {
      variant: {
        default: "border-input",
        destructive: "border-destructive focus-visible:ring-destructive",
        ghost: "border-transparent bg-transparent hover:bg-accent"
      },
      size: {
        default: "h-10 px-4 py-2",
        sm: "h-9 px-3 text-sm",
        lg: "h-11 px-4 py-3"
      }
    },
    defaultVariants: {
      variant: "default",
      size: "default"
    }
  }
);
var Input = React5.forwardRef(
  ({ className, variant, size, type, label, error, icon, suffix, ...props }, ref) => {
    return /* @__PURE__ */ React5.createElement("div", { className: "grid w-full gap-1.5" }, label && /* @__PURE__ */ React5.createElement("label", { className: "text-sm font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70" }, label), /* @__PURE__ */ React5.createElement("div", { className: "relative" }, icon && /* @__PURE__ */ React5.createElement("div", { className: "absolute left-3 top-1/2 -translate-y-1/2 text-muted-foreground" }, icon), /* @__PURE__ */ React5.createElement(
      "input",
      {
        type,
        className: cn(
          inputVariants({ variant, size, className }),
          icon && "pl-10",
          suffix && "pr-10",
          error && "border-destructive focus-visible:ring-destructive"
        ),
        ref,
        ...props
      }
    ), suffix && /* @__PURE__ */ React5.createElement("div", { className: "absolute right-3 top-1/2 -translate-y-1/2 text-muted-foreground" }, suffix)), error && /* @__PURE__ */ React5.createElement("p", { className: "text-sm text-destructive" }, error));
  }
);
Input.displayName = "Input";

// src/components/ui/select.tsx
var React6 = __toESM(require("react"));
var import_lucide_react = require("lucide-react");
var import_class_variance_authority4 = require("class-variance-authority");
var selectVariants = (0, import_class_variance_authority4.cva)(
  "flex h-10 w-full items-center justify-between rounded-md border border-input bg-background px-3 py-2 text-sm ring-offset-background placeholder:text-muted-foreground focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50",
  {
    variants: {
      variant: {
        default: "border-input",
        destructive: "border-destructive focus:ring-destructive"
      },
      size: {
        default: "h-10 px-4 py-2",
        sm: "h-9 px-3 text-sm",
        lg: "h-11 px-4 py-3"
      }
    },
    defaultVariants: {
      variant: "default",
      size: "default"
    }
  }
);
var Select = React6.forwardRef(
  ({
    className,
    variant,
    size,
    options,
    value,
    onValueChange,
    placeholder = "Select an option...",
    label,
    error,
    searchable = false,
    disabled,
    ...props
  }, ref) => {
    const [isOpen, setIsOpen] = React6.useState(false);
    const [searchTerm, setSearchTerm] = React6.useState("");
    const dropdownRef = React6.useRef(null);
    const selectedOption = options.find((option) => option.value === value);
    const filteredOptions = React6.useMemo(() => {
      if (!searchable || !searchTerm) return options;
      return options.filter(
        (option) => option.label.toLowerCase().includes(searchTerm.toLowerCase())
      );
    }, [options, searchTerm, searchable]);
    React6.useEffect(() => {
      const handleClickOutside = (event) => {
        if (dropdownRef.current && !dropdownRef.current.contains(event.target)) {
          setIsOpen(false);
          setSearchTerm("");
        }
      };
      document.addEventListener("mousedown", handleClickOutside);
      return () => document.removeEventListener("mousedown", handleClickOutside);
    }, []);
    const handleSelect = (optionValue) => {
      onValueChange?.(optionValue);
      setIsOpen(false);
      setSearchTerm("");
    };
    return /* @__PURE__ */ React6.createElement("div", { className: "grid w-full gap-1.5" }, label && /* @__PURE__ */ React6.createElement("label", { className: "text-sm font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70" }, label), /* @__PURE__ */ React6.createElement("div", { className: "relative", ref: dropdownRef }, /* @__PURE__ */ React6.createElement(
      "button",
      {
        type: "button",
        ref,
        className: cn(
          selectVariants({ variant, size, className }),
          error && "border-destructive focus:ring-destructive"
        ),
        onClick: () => !disabled && setIsOpen(!isOpen),
        disabled,
        ...props
      },
      /* @__PURE__ */ React6.createElement("span", { className: cn(
        "block truncate text-left",
        !selectedOption && "text-muted-foreground"
      ) }, selectedOption ? selectedOption.label : placeholder),
      /* @__PURE__ */ React6.createElement(import_lucide_react.ChevronDown, { className: cn(
        "h-4 w-4 transition-transform",
        isOpen && "rotate-180"
      ) })
    ), isOpen && /* @__PURE__ */ React6.createElement("div", { className: "absolute z-50 mt-1 w-full rounded-md border bg-popover p-1 shadow-md" }, searchable && /* @__PURE__ */ React6.createElement("div", { className: "p-1" }, /* @__PURE__ */ React6.createElement(
      "input",
      {
        type: "text",
        placeholder: "Search...",
        value: searchTerm,
        onChange: (e) => setSearchTerm(e.target.value),
        className: "w-full rounded-sm border border-input bg-background px-3 py-2 text-sm focus:outline-none focus:ring-2 focus:ring-ring"
      }
    )), /* @__PURE__ */ React6.createElement("div", { className: "max-h-60 overflow-auto" }, filteredOptions.length === 0 ? /* @__PURE__ */ React6.createElement("div", { className: "py-6 text-center text-sm text-muted-foreground" }, "No options found.") : filteredOptions.map((option) => /* @__PURE__ */ React6.createElement(
      "button",
      {
        key: option.value,
        type: "button",
        className: cn(
          "relative flex w-full cursor-pointer select-none items-center rounded-sm py-1.5 pl-8 pr-2 text-sm outline-none hover:bg-accent hover:text-accent-foreground",
          option.disabled && "cursor-not-allowed opacity-50",
          value === option.value && "bg-accent text-accent-foreground"
        ),
        onClick: () => !option.disabled && handleSelect(option.value),
        disabled: option.disabled
      },
      /* @__PURE__ */ React6.createElement("span", { className: "absolute left-2 flex h-3.5 w-3.5 items-center justify-center" }, value === option.value && /* @__PURE__ */ React6.createElement(import_lucide_react.Check, { className: "h-4 w-4" })),
      option.label
    ))))), error && /* @__PURE__ */ React6.createElement("p", { className: "text-sm text-destructive" }, error));
  }
);
Select.displayName = "Select";

// src/components/ui/avatar.tsx
var React7 = __toESM(require("react"));
var import_class_variance_authority5 = require("class-variance-authority");
var avatarVariants = (0, import_class_variance_authority5.cva)(
  "relative flex shrink-0 overflow-hidden rounded-full",
  {
    variants: {
      size: {
        sm: "h-6 w-6",
        default: "h-10 w-10",
        lg: "h-12 w-12",
        xl: "h-16 w-16",
        "2xl": "h-20 w-20"
      }
    },
    defaultVariants: {
      size: "default"
    }
  }
);
var avatarImageVariants = (0, import_class_variance_authority5.cva)("aspect-square h-full w-full object-cover");
var avatarFallbackVariants = (0, import_class_variance_authority5.cva)(
  "flex h-full w-full items-center justify-center rounded-full bg-muted text-muted-foreground font-medium",
  {
    variants: {
      size: {
        sm: "text-xs",
        default: "text-sm",
        lg: "text-base",
        xl: "text-lg",
        "2xl": "text-xl"
      }
    },
    defaultVariants: {
      size: "default"
    }
  }
);
var Avatar = React7.forwardRef(
  ({ className, size, src, alt, fallback, status, ...props }, ref) => {
    const [imageLoaded, setImageLoaded] = React7.useState(false);
    const [imageFailed, setImageFailed] = React7.useState(false);
    const initials = React7.useMemo(() => {
      if (fallback) return fallback;
      if (alt) {
        const names = alt.split(" ");
        return names.length > 1 ? `${names[0][0]}${names[names.length - 1][0]}`.toUpperCase() : names[0].slice(0, 2).toUpperCase();
      }
      return "??";
    }, [fallback, alt]);
    return /* @__PURE__ */ React7.createElement("div", { className: cn(avatarVariants({ size }), className), ref, ...props }, src && !imageFailed && /* @__PURE__ */ React7.createElement(
      "img",
      {
        src,
        alt,
        className: cn(avatarImageVariants()),
        onLoad: () => setImageLoaded(true),
        onError: () => setImageFailed(true)
      }
    ), (!src || imageFailed || !imageLoaded) && /* @__PURE__ */ React7.createElement("div", { className: cn(avatarFallbackVariants({ size })) }, initials), status && /* @__PURE__ */ React7.createElement("div", { className: cn(
      "absolute -bottom-0 -right-0 rounded-full border-2 border-background",
      size === "sm" && "h-2 w-2",
      size === "default" && "h-3 w-3",
      size === "lg" && "h-3.5 w-3.5",
      size === "xl" && "h-4 w-4",
      size === "2xl" && "h-5 w-5",
      status === "online" && "bg-green-500",
      status === "offline" && "bg-gray-400",
      status === "away" && "bg-yellow-500",
      status === "busy" && "bg-red-500"
    ) }));
  }
);
Avatar.displayName = "Avatar";

// src/components/ui/table.tsx
var React8 = __toESM(require("react"));
var import_lucide_react2 = require("lucide-react");
var Table = React8.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ React8.createElement("div", { className: "relative w-full overflow-auto" }, /* @__PURE__ */ React8.createElement(
  "table",
  {
    ref,
    className: cn("w-full caption-bottom text-sm", className),
    ...props
  }
)));
Table.displayName = "Table";
var TableHeader = React8.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ React8.createElement("thead", { ref, className: cn("[&_tr]:border-b", className), ...props }));
TableHeader.displayName = "TableHeader";
var TableBody = React8.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ React8.createElement(
  "tbody",
  {
    ref,
    className: cn("[&_tr:last-child]:border-0", className),
    ...props
  }
));
TableBody.displayName = "TableBody";
var TableFooter = React8.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ React8.createElement(
  "tfoot",
  {
    ref,
    className: cn(
      "border-t bg-muted/50 font-medium [&>tr]:last:border-b-0",
      className
    ),
    ...props
  }
));
TableFooter.displayName = "TableFooter";
var TableRow = React8.forwardRef(({ className, hover = true, ...props }, ref) => /* @__PURE__ */ React8.createElement(
  "tr",
  {
    ref,
    className: cn(
      "border-b transition-colors",
      hover && "hover:bg-muted/50",
      "data-[state=selected]:bg-muted",
      className
    ),
    ...props
  }
));
TableRow.displayName = "TableRow";
var TableHead = React8.forwardRef(
  ({ className, sortable, sortDirection, onSort, children, ...props }, ref) => /* @__PURE__ */ React8.createElement(
    "th",
    {
      ref,
      className: cn(
        "h-12 px-4 text-left align-middle font-medium text-muted-foreground [&:has([role=checkbox])]:pr-0",
        sortable && "cursor-pointer hover:text-foreground",
        className
      ),
      onClick: sortable ? onSort : void 0,
      ...props
    },
    /* @__PURE__ */ React8.createElement("div", { className: "flex items-center space-x-2" }, /* @__PURE__ */ React8.createElement("span", null, children), sortable && /* @__PURE__ */ React8.createElement("span", { className: "flex items-center" }, sortDirection === "asc" && /* @__PURE__ */ React8.createElement(import_lucide_react2.ChevronUp, { className: "h-4 w-4" }), sortDirection === "desc" && /* @__PURE__ */ React8.createElement(import_lucide_react2.ChevronDown, { className: "h-4 w-4" }), sortDirection === null && /* @__PURE__ */ React8.createElement(import_lucide_react2.ChevronsUpDown, { className: "h-4 w-4" })))
  )
);
TableHead.displayName = "TableHead";
var TableCell = React8.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ React8.createElement(
  "td",
  {
    ref,
    className: cn("p-4 align-middle [&:has([role=checkbox])]:pr-0", className),
    ...props
  }
));
TableCell.displayName = "TableCell";
var TableCaption = React8.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ React8.createElement(
  "caption",
  {
    ref,
    className: cn("mt-4 text-sm text-muted-foreground", className),
    ...props
  }
));
TableCaption.displayName = "TableCaption";
function DataTable({
  data,
  columns,
  loading = false,
  emptyMessage = "No data available",
  onRowClick,
  selectable = false,
  selectedRows = [],
  onSelectionChange
}) {
  const [sortConfig, setSortConfig] = React8.useState({ key: null, direction: "asc" });
  const sortedData = React8.useMemo(() => {
    if (!sortConfig.key) return data;
    return [...data].sort((a, b) => {
      const aValue = a[sortConfig.key];
      const bValue = b[sortConfig.key];
      if (aValue < bValue) {
        return sortConfig.direction === "asc" ? -1 : 1;
      }
      if (aValue > bValue) {
        return sortConfig.direction === "asc" ? 1 : -1;
      }
      return 0;
    });
  }, [data, sortConfig]);
  const handleSort = (key) => {
    setSortConfig((prev) => ({
      key,
      direction: prev.key === key && prev.direction === "asc" ? "desc" : "asc"
    }));
  };
  const isSelected = (row) => selectedRows.some((selected) => selected === row);
  const toggleSelection = (row) => {
    if (!onSelectionChange) return;
    const newSelection = isSelected(row) ? selectedRows.filter((selected) => selected !== row) : [...selectedRows, row];
    onSelectionChange(newSelection);
  };
  const toggleAllSelection = () => {
    if (!onSelectionChange) return;
    const allSelected = selectedRows.length === data.length;
    onSelectionChange(allSelected ? [] : [...data]);
  };
  if (loading) {
    return /* @__PURE__ */ React8.createElement("div", { className: "w-full p-8 text-center" }, /* @__PURE__ */ React8.createElement("div", { className: "text-sm text-muted-foreground" }, "Loading..."));
  }
  return /* @__PURE__ */ React8.createElement(Table, null, /* @__PURE__ */ React8.createElement(TableHeader, null, /* @__PURE__ */ React8.createElement(TableRow, null, selectable && /* @__PURE__ */ React8.createElement(TableHead, { className: "w-12" }, /* @__PURE__ */ React8.createElement(
    "input",
    {
      type: "checkbox",
      checked: selectedRows.length === data.length && data.length > 0,
      onChange: toggleAllSelection,
      className: "rounded"
    }
  )), columns.map((column) => /* @__PURE__ */ React8.createElement(
    TableHead,
    {
      key: String(column.key),
      sortable: column.sortable,
      sortDirection: sortConfig.key === column.key ? sortConfig.direction : null,
      onSort: () => column.sortable && handleSort(column.key),
      style: { width: column.width }
    },
    column.header
  )))), /* @__PURE__ */ React8.createElement(TableBody, null, sortedData.length === 0 ? /* @__PURE__ */ React8.createElement(TableRow, null, /* @__PURE__ */ React8.createElement(TableCell, { colSpan: columns.length + (selectable ? 1 : 0), className: "text-center py-8" }, /* @__PURE__ */ React8.createElement("div", { className: "text-muted-foreground" }, emptyMessage))) : sortedData.map((row, index) => /* @__PURE__ */ React8.createElement(
    TableRow,
    {
      key: index,
      className: cn(
        onRowClick && "cursor-pointer",
        isSelected(row) && "bg-muted/50"
      ),
      onClick: () => onRowClick?.(row)
    },
    selectable && /* @__PURE__ */ React8.createElement(TableCell, null, /* @__PURE__ */ React8.createElement(
      "input",
      {
        type: "checkbox",
        checked: isSelected(row),
        onChange: () => toggleSelection(row),
        onClick: (e) => e.stopPropagation(),
        className: "rounded"
      }
    )),
    columns.map((column) => /* @__PURE__ */ React8.createElement(TableCell, { key: String(column.key) }, column.render ? column.render(row[column.key], row) : String(row[column.key] ?? "")))
  ))));
}

// src/components/ui/toast.tsx
var React9 = __toESM(require("react"));
var import_lucide_react3 = require("lucide-react");
var import_class_variance_authority6 = require("class-variance-authority");
var toastVariants = (0, import_class_variance_authority6.cva)(
  "group pointer-events-auto relative flex w-full items-center justify-between space-x-4 overflow-hidden rounded-md border p-6 pr-8 shadow-lg transition-all data-[swipe=cancel]:translate-x-0 data-[swipe=end]:translate-x-[var(--radix-toast-swipe-end-x)] data-[swipe=move]:translate-x-[var(--radix-toast-swipe-move-x)] data-[swipe=move]:transition-none data-[state=open]:animate-in data-[state=closed]:animate-out data-[swipe=end]:animate-out data-[state=closed]:fade-out-80 data-[state=closed]:slide-out-to-right-full data-[state=open]:slide-in-from-top-full data-[state=open]:sm:slide-in-from-bottom-full",
  {
    variants: {
      variant: {
        default: "border bg-background text-foreground",
        success: "border-green-200 bg-green-50 text-green-900 dark:border-green-800 dark:bg-green-950 dark:text-green-50",
        error: "border-red-200 bg-red-50 text-red-900 dark:border-red-800 dark:bg-red-950 dark:text-red-50",
        warning: "border-yellow-200 bg-yellow-50 text-yellow-900 dark:border-yellow-800 dark:bg-yellow-950 dark:text-yellow-50",
        info: "border-blue-200 bg-blue-50 text-blue-900 dark:border-blue-800 dark:bg-blue-950 dark:text-blue-50"
      }
    },
    defaultVariants: {
      variant: "default"
    }
  }
);
var Toast = React9.forwardRef(
  ({ className, variant, title, description, action, onClose, duration = 5e3, ...props }, ref) => {
    const [isVisible, setIsVisible] = React9.useState(true);
    React9.useEffect(() => {
      if (duration && duration > 0) {
        const timer = setTimeout(() => {
          setIsVisible(false);
          setTimeout(() => onClose?.(), 150);
        }, duration);
        return () => clearTimeout(timer);
      }
    }, [duration, onClose]);
    const getIcon = () => {
      switch (variant) {
        case "success":
          return /* @__PURE__ */ React9.createElement(import_lucide_react3.CheckCircle, { className: "h-5 w-5 text-green-600 dark:text-green-400" });
        case "error":
          return /* @__PURE__ */ React9.createElement(import_lucide_react3.AlertCircle, { className: "h-5 w-5 text-red-600 dark:text-red-400" });
        case "warning":
          return /* @__PURE__ */ React9.createElement(import_lucide_react3.AlertTriangle, { className: "h-5 w-5 text-yellow-600 dark:text-yellow-400" });
        case "info":
          return /* @__PURE__ */ React9.createElement(import_lucide_react3.Info, { className: "h-5 w-5 text-blue-600 dark:text-blue-400" });
        default:
          return null;
      }
    };
    if (!isVisible) return null;
    return /* @__PURE__ */ React9.createElement(
      "div",
      {
        ref,
        className: cn(toastVariants({ variant }), className),
        ...props
      },
      /* @__PURE__ */ React9.createElement("div", { className: "flex items-start space-x-3" }, /* @__PURE__ */ React9.createElement("div", { className: "flex-shrink-0 mt-0.5" }, getIcon()), /* @__PURE__ */ React9.createElement("div", { className: "flex-1 min-w-0" }, title && /* @__PURE__ */ React9.createElement("div", { className: "text-sm font-semibold" }, title), description && /* @__PURE__ */ React9.createElement("div", { className: "mt-1 text-sm opacity-90" }, description), action && /* @__PURE__ */ React9.createElement("div", { className: "mt-2" }, action))),
      /* @__PURE__ */ React9.createElement(
        "button",
        {
          onClick: () => {
            setIsVisible(false);
            setTimeout(() => onClose?.(), 150);
          },
          className: "absolute right-2 top-2 rounded-md p-1 text-foreground/50 opacity-0 transition-opacity hover:text-foreground focus:opacity-100 focus:outline-none focus:ring-2 group-hover:opacity-100"
        },
        /* @__PURE__ */ React9.createElement(import_lucide_react3.X, { className: "h-4 w-4" })
      )
    );
  }
);
Toast.displayName = "Toast";
var ToastContainer = ({
  position = "top-right"
}) => {
  const positionClasses = {
    "top-right": "top-0 right-0",
    "top-left": "top-0 left-0",
    "bottom-right": "bottom-0 right-0",
    "bottom-left": "bottom-0 left-0",
    "top-center": "top-0 left-1/2 -translate-x-1/2",
    "bottom-center": "bottom-0 left-1/2 -translate-x-1/2"
  };
  return /* @__PURE__ */ React9.createElement(
    "div",
    {
      className: cn(
        "fixed z-[100] flex max-h-screen w-full flex-col-reverse p-4 sm:flex-col md:max-w-[420px]",
        positionClasses[position]
      ),
      id: "toast-container"
    }
  );
};
var ToastContext = React9.createContext(void 0);
function ToastProvider({ children }) {
  const [toasts, setToasts] = React9.useState([]);
  const toast2 = React9.useCallback((options) => {
    const id = options.id || Math.random().toString(36).substring(7);
    setToasts((prev) => [...prev, { ...options, id }]);
    return id;
  }, []);
  const dismiss = React9.useCallback((id) => {
    setToasts((prev) => prev.filter((toast3) => toast3.id !== id));
  }, []);
  const clear = React9.useCallback(() => {
    setToasts([]);
  }, []);
  return /* @__PURE__ */ React9.createElement(ToastContext.Provider, { value: { toasts, toast: toast2, dismiss, clear } }, children, /* @__PURE__ */ React9.createElement(ToastContainer, null), toasts.map(({ id, ...toastProps }) => /* @__PURE__ */ React9.createElement(
    Toast,
    {
      key: id,
      ...toastProps,
      onClose: () => dismiss(id)
    }
  )));
}
function useToast() {
  const context = React9.useContext(ToastContext);
  if (!context) {
    throw new Error("useToast must be used within a ToastProvider");
  }
  return context;
}
var toast = {
  success: (message, options) => {
    if (typeof window !== "undefined") {
      window.dispatchEvent(new CustomEvent("toast", {
        detail: { variant: "success", description: message, ...options }
      }));
    }
  },
  error: (message, options) => {
    if (typeof window !== "undefined") {
      window.dispatchEvent(new CustomEvent("toast", {
        detail: { variant: "error", description: message, ...options }
      }));
    }
  },
  warning: (message, options) => {
    if (typeof window !== "undefined") {
      window.dispatchEvent(new CustomEvent("toast", {
        detail: { variant: "warning", description: message, ...options }
      }));
    }
  },
  info: (message, options) => {
    if (typeof window !== "undefined") {
      window.dispatchEvent(new CustomEvent("toast", {
        detail: { variant: "info", description: message, ...options }
      }));
    }
  }
};

// src/components/ui/modal.tsx
var React10 = __toESM(require("react"));
var import_lucide_react4 = require("lucide-react");
var import_class_variance_authority7 = require("class-variance-authority");
var modalVariants = (0, import_class_variance_authority7.cva)(
  "fixed left-[50%] top-[50%] z-50 grid w-full max-w-lg translate-x-[-50%] translate-y-[-50%] gap-4 border bg-background p-6 shadow-lg duration-200 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[state=closed]:slide-out-to-left-1/2 data-[state=closed]:slide-out-to-top-[48%] data-[state=open]:slide-in-from-left-1/2 data-[state=open]:slide-in-from-top-[48%] sm:rounded-lg",
  {
    variants: {
      size: {
        sm: "max-w-sm",
        default: "max-w-lg",
        lg: "max-w-2xl",
        xl: "max-w-4xl",
        full: "max-w-[95vw] max-h-[95vh]"
      }
    },
    defaultVariants: {
      size: "default"
    }
  }
);
var Modal = React10.forwardRef(
  ({
    className,
    size,
    isOpen,
    onClose,
    title,
    description,
    showCloseButton = true,
    closeOnOverlayClick = true,
    closeOnEscape = true,
    children,
    ...props
  }, ref) => {
    const modalRef = React10.useRef(null);
    React10.useEffect(() => {
      if (!closeOnEscape || !isOpen) return;
      const handleEscape = (e) => {
        if (e.key === "Escape") {
          onClose();
        }
      };
      document.addEventListener("keydown", handleEscape);
      return () => document.removeEventListener("keydown", handleEscape);
    }, [isOpen, closeOnEscape, onClose]);
    const handleOverlayClick = (e) => {
      if (closeOnOverlayClick && e.target === e.currentTarget) {
        onClose();
      }
    };
    React10.useEffect(() => {
      if (isOpen) {
        const previousActiveElement = document.activeElement;
        modalRef.current?.focus();
        return () => {
          previousActiveElement?.focus();
        };
      }
    }, [isOpen]);
    React10.useEffect(() => {
      if (isOpen) {
        document.body.style.overflow = "hidden";
        return () => {
          document.body.style.overflow = "unset";
        };
      }
    }, [isOpen]);
    if (!isOpen) return null;
    return /* @__PURE__ */ React10.createElement(React10.Fragment, null, /* @__PURE__ */ React10.createElement(
      "div",
      {
        className: "fixed inset-0 z-40 bg-black/50 backdrop-blur-sm",
        onClick: handleOverlayClick
      }
    ), /* @__PURE__ */ React10.createElement(
      "div",
      {
        ref: (node) => {
          modalRef.current = node;
          if (typeof ref === "function") {
            ref(node);
          } else if (ref) {
            ref.current = node;
          }
        },
        className: cn(modalVariants({ size }), className),
        role: "dialog",
        "aria-modal": "true",
        "aria-labelledby": title ? "modal-title" : void 0,
        "aria-describedby": description ? "modal-description" : void 0,
        tabIndex: -1,
        ...props
      },
      showCloseButton && /* @__PURE__ */ React10.createElement(
        "button",
        {
          onClick: onClose,
          className: "absolute right-4 top-4 rounded-sm opacity-70 ring-offset-background transition-opacity hover:opacity-100 focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2 disabled:pointer-events-none data-[state=open]:bg-accent data-[state=open]:text-muted-foreground"
        },
        /* @__PURE__ */ React10.createElement(import_lucide_react4.X, { className: "h-4 w-4" }),
        /* @__PURE__ */ React10.createElement("span", { className: "sr-only" }, "Close")
      ),
      (title || description) && /* @__PURE__ */ React10.createElement("div", { className: "flex flex-col space-y-1.5" }, title && /* @__PURE__ */ React10.createElement("h2", { id: "modal-title", className: "text-lg font-semibold leading-none tracking-tight" }, title), description && /* @__PURE__ */ React10.createElement("p", { id: "modal-description", className: "text-sm text-muted-foreground" }, description)),
      /* @__PURE__ */ React10.createElement("div", { className: "flex-1" }, children)
    ));
  }
);
Modal.displayName = "Modal";
var ModalHeader = React10.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ React10.createElement(
  "div",
  {
    ref,
    className: cn("flex flex-col space-y-1.5 text-center sm:text-left", className),
    ...props
  }
));
ModalHeader.displayName = "ModalHeader";
var ModalTitle = React10.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ React10.createElement(
  "h3",
  {
    ref,
    className: cn("text-lg font-semibold leading-none tracking-tight", className),
    ...props
  }
));
ModalTitle.displayName = "ModalTitle";
var ModalDescription = React10.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ React10.createElement(
  "p",
  {
    ref,
    className: cn("text-sm text-muted-foreground", className),
    ...props
  }
));
ModalDescription.displayName = "ModalDescription";
var ModalContent = React10.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ React10.createElement("div", { ref, className: cn("py-4", className), ...props }));
ModalContent.displayName = "ModalContent";
var ModalFooter = React10.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ React10.createElement(
  "div",
  {
    ref,
    className: cn("flex flex-col-reverse sm:flex-row sm:justify-end sm:space-x-2", className),
    ...props
  }
));
ModalFooter.displayName = "ModalFooter";
function useConfirmModal() {
  const [isOpen, setIsOpen] = React10.useState(false);
  const [options, setOptions] = React10.useState({});
  const resolveRef = React10.useRef(null);
  const confirm = React10.useCallback((opts = {}) => {
    setOptions({
      title: opts.title || "Are you sure?",
      description: opts.description || "This action cannot be undone.",
      confirmText: opts.confirmText || "Confirm",
      cancelText: opts.cancelText || "Cancel",
      variant: opts.variant || "default",
      ...opts
    });
    setIsOpen(true);
    return new Promise((resolve) => {
      resolveRef.current = resolve;
    });
  }, []);
  const handleConfirm = () => {
    resolveRef.current?.(true);
    setIsOpen(false);
  };
  const handleCancel = () => {
    resolveRef.current?.(false);
    setIsOpen(false);
  };
  const ConfirmModal = () => /* @__PURE__ */ React10.createElement(
    Modal,
    {
      isOpen,
      onClose: handleCancel,
      title: options.title,
      description: options.description
    },
    /* @__PURE__ */ React10.createElement(ModalFooter, null, /* @__PURE__ */ React10.createElement(
      "button",
      {
        onClick: handleCancel,
        className: cn(
          "inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium ring-offset-background transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50",
          "border border-input bg-background hover:bg-accent hover:text-accent-foreground h-10 px-4 py-2"
        )
      },
      options.cancelText
    ), /* @__PURE__ */ React10.createElement(
      "button",
      {
        onClick: handleConfirm,
        className: cn(
          "inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium ring-offset-background transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50",
          options.variant === "destructive" ? "bg-destructive text-destructive-foreground hover:bg-destructive/90 h-10 px-4 py-2" : "bg-primary text-primary-foreground hover:bg-primary/90 h-10 px-4 py-2"
        )
      },
      options.confirmText
    ))
  );
  return { confirm, ConfirmModal };
}

// src/components/ui/navbar.tsx
var React11 = __toESM(require("react"));
var import_lucide_react5 = require("lucide-react");
var import_class_variance_authority8 = require("class-variance-authority");
var navbarVariants = (0, import_class_variance_authority8.cva)(
  "flex w-full items-center justify-between border-b bg-background px-4",
  {
    variants: {
      size: {
        default: "h-16",
        sm: "h-12",
        lg: "h-20"
      },
      variant: {
        default: "border-border",
        minimal: "border-transparent",
        elevated: "shadow-sm border-border"
      }
    },
    defaultVariants: {
      size: "default",
      variant: "default"
    }
  }
);
var Navbar = React11.forwardRef(
  ({
    className,
    size,
    variant,
    logo,
    items = [],
    actions,
    mobileMenuButton = true,
    onMobileMenuToggle,
    isMobileMenuOpen = false,
    ...props
  }, ref) => {
    const [openDropdown, setOpenDropdown] = React11.useState(null);
    const handleDropdownToggle = (label) => {
      setOpenDropdown(openDropdown === label ? null : label);
    };
    const handleItemClick = (item) => {
      if (item.disabled) return;
      if (item.onClick) {
        item.onClick();
      } else if (item.href) {
        window.location.href = item.href;
      }
      setOpenDropdown(null);
    };
    return /* @__PURE__ */ React11.createElement(
      "nav",
      {
        ref,
        className: cn(navbarVariants({ size, variant }), className),
        ...props
      },
      /* @__PURE__ */ React11.createElement("div", { className: "flex items-center space-x-4" }, logo),
      /* @__PURE__ */ React11.createElement("div", { className: "hidden md:flex items-center space-x-1" }, items.map((item) => /* @__PURE__ */ React11.createElement("div", { key: item.label, className: "relative" }, item.items && item.items.length > 0 ? (
        // Dropdown Menu
        /* @__PURE__ */ React11.createElement("div", { className: "relative" }, /* @__PURE__ */ React11.createElement(
          "button",
          {
            onClick: () => handleDropdownToggle(item.label),
            className: cn(
              "flex items-center space-x-1 px-3 py-2 text-sm font-medium rounded-md transition-colors",
              "hover:bg-accent hover:text-accent-foreground",
              "focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2",
              item.disabled && "opacity-50 cursor-not-allowed",
              openDropdown === item.label && "bg-accent text-accent-foreground"
            ),
            disabled: item.disabled
          },
          item.icon,
          /* @__PURE__ */ React11.createElement("span", null, item.label),
          item.badge && /* @__PURE__ */ React11.createElement("span", { className: "ml-1 px-2 py-0.5 text-xs bg-primary text-primary-foreground rounded-full" }, item.badge),
          /* @__PURE__ */ React11.createElement(import_lucide_react5.ChevronDown, { className: cn(
            "h-4 w-4 transition-transform",
            openDropdown === item.label && "rotate-180"
          ) })
        ), openDropdown === item.label && /* @__PURE__ */ React11.createElement("div", { className: "absolute top-full left-0 mt-1 w-48 rounded-md border bg-popover p-1 shadow-md z-50" }, item.items.map((subItem) => /* @__PURE__ */ React11.createElement(
          "button",
          {
            key: subItem.label,
            onClick: () => handleItemClick(subItem),
            className: cn(
              "flex w-full items-center space-x-2 px-3 py-2 text-sm rounded-sm transition-colors text-left",
              "hover:bg-accent hover:text-accent-foreground",
              "focus:outline-none focus:ring-2 focus:ring-ring",
              subItem.disabled && "opacity-50 cursor-not-allowed"
            ),
            disabled: subItem.disabled
          },
          subItem.icon,
          /* @__PURE__ */ React11.createElement("span", null, subItem.label),
          subItem.badge && /* @__PURE__ */ React11.createElement("span", { className: "ml-auto px-2 py-0.5 text-xs bg-primary text-primary-foreground rounded-full" }, subItem.badge)
        ))))
      ) : (
        // Regular Menu Item
        /* @__PURE__ */ React11.createElement(
          "button",
          {
            onClick: () => handleItemClick(item),
            className: cn(
              "flex items-center space-x-2 px-3 py-2 text-sm font-medium rounded-md transition-colors",
              "hover:bg-accent hover:text-accent-foreground",
              "focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2",
              item.disabled && "opacity-50 cursor-not-allowed"
            ),
            disabled: item.disabled
          },
          item.icon,
          /* @__PURE__ */ React11.createElement("span", null, item.label),
          item.badge && /* @__PURE__ */ React11.createElement("span", { className: "ml-1 px-2 py-0.5 text-xs bg-primary text-primary-foreground rounded-full" }, item.badge)
        )
      )))),
      /* @__PURE__ */ React11.createElement("div", { className: "flex items-center space-x-2" }, actions, mobileMenuButton && /* @__PURE__ */ React11.createElement(
        "button",
        {
          onClick: onMobileMenuToggle,
          className: "md:hidden p-2 rounded-md hover:bg-accent hover:text-accent-foreground focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2"
        },
        isMobileMenuOpen ? /* @__PURE__ */ React11.createElement(import_lucide_react5.X, { className: "h-5 w-5" }) : /* @__PURE__ */ React11.createElement(import_lucide_react5.Menu, { className: "h-5 w-5" })
      )),
      isMobileMenuOpen && /* @__PURE__ */ React11.createElement("div", { className: "absolute top-full left-0 right-0 md:hidden border-b bg-background shadow-lg z-40" }, /* @__PURE__ */ React11.createElement("div", { className: "px-4 py-2 space-y-1" }, items.map((item) => /* @__PURE__ */ React11.createElement("div", { key: item.label }, item.items && item.items.length > 0 ? /* @__PURE__ */ React11.createElement("div", null, /* @__PURE__ */ React11.createElement(
        "button",
        {
          onClick: () => handleDropdownToggle(item.label),
          className: cn(
            "flex w-full items-center justify-between px-3 py-2 text-sm font-medium rounded-md transition-colors",
            "hover:bg-accent hover:text-accent-foreground",
            item.disabled && "opacity-50 cursor-not-allowed"
          ),
          disabled: item.disabled
        },
        /* @__PURE__ */ React11.createElement("div", { className: "flex items-center space-x-2" }, item.icon, /* @__PURE__ */ React11.createElement("span", null, item.label), item.badge && /* @__PURE__ */ React11.createElement("span", { className: "px-2 py-0.5 text-xs bg-primary text-primary-foreground rounded-full" }, item.badge)),
        /* @__PURE__ */ React11.createElement(import_lucide_react5.ChevronDown, { className: cn(
          "h-4 w-4 transition-transform",
          openDropdown === item.label && "rotate-180"
        ) })
      ), openDropdown === item.label && /* @__PURE__ */ React11.createElement("div", { className: "ml-4 mt-1 space-y-1" }, item.items.map((subItem) => /* @__PURE__ */ React11.createElement(
        "button",
        {
          key: subItem.label,
          onClick: () => handleItemClick(subItem),
          className: cn(
            "flex w-full items-center space-x-2 px-3 py-2 text-sm rounded-md transition-colors text-left",
            "hover:bg-accent hover:text-accent-foreground",
            subItem.disabled && "opacity-50 cursor-not-allowed"
          ),
          disabled: subItem.disabled
        },
        subItem.icon,
        /* @__PURE__ */ React11.createElement("span", null, subItem.label),
        subItem.badge && /* @__PURE__ */ React11.createElement("span", { className: "ml-auto px-2 py-0.5 text-xs bg-primary text-primary-foreground rounded-full" }, subItem.badge)
      )))) : /* @__PURE__ */ React11.createElement(
        "button",
        {
          onClick: () => handleItemClick(item),
          className: cn(
            "flex w-full items-center space-x-2 px-3 py-2 text-sm font-medium rounded-md transition-colors text-left",
            "hover:bg-accent hover:text-accent-foreground",
            item.disabled && "opacity-50 cursor-not-allowed"
          ),
          disabled: item.disabled
        },
        item.icon,
        /* @__PURE__ */ React11.createElement("span", null, item.label),
        item.badge && /* @__PURE__ */ React11.createElement("span", { className: "ml-auto px-2 py-0.5 text-xs bg-primary text-primary-foreground rounded-full" }, item.badge)
      )))))
    );
  }
);
Navbar.displayName = "Navbar";

// src/components/ui/sidebar.tsx
var React12 = __toESM(require("react"));
var import_lucide_react6 = require("lucide-react");
var import_class_variance_authority9 = require("class-variance-authority");
var sidebarVariants = (0, import_class_variance_authority9.cva)(
  "flex flex-col border-r bg-background transition-all duration-300 ease-in-out",
  {
    variants: {
      variant: {
        default: "border-border",
        minimal: "border-transparent",
        elevated: "shadow-lg border-border"
      },
      size: {
        sm: "w-16",
        default: "w-64",
        lg: "w-80"
      }
    },
    defaultVariants: {
      variant: "default",
      size: "default"
    }
  }
);
var Sidebar = React12.forwardRef(
  ({
    className,
    variant,
    size,
    header,
    footer,
    sections = [],
    collapsible = false,
    collapsed = false,
    onCollapse,
    showCollapseButton = true,
    ...props
  }, ref) => {
    const [expandedItems, setExpandedItems] = React12.useState(/* @__PURE__ */ new Set());
    const [internalCollapsed, setInternalCollapsed] = React12.useState(collapsed);
    const isCollapsed = collapsible ? internalCollapsed : false;
    React12.useEffect(() => {
      setInternalCollapsed(collapsed);
    }, [collapsed]);
    const toggleCollapse = () => {
      const newCollapsed = !internalCollapsed;
      setInternalCollapsed(newCollapsed);
      onCollapse?.(newCollapsed);
    };
    const toggleExpanded = (label) => {
      const newExpanded = new Set(expandedItems);
      if (newExpanded.has(label)) {
        newExpanded.delete(label);
      } else {
        newExpanded.add(label);
      }
      setExpandedItems(newExpanded);
    };
    const handleItemClick = (item) => {
      if (item.disabled) return;
      if (item.items && item.items.length > 0) {
        toggleExpanded(item.label);
      } else if (item.onClick) {
        item.onClick();
      } else if (item.href) {
        window.location.href = item.href;
      }
    };
    const renderItem = (item, level = 0) => {
      const hasChildren = item.items && item.items.length > 0;
      const isExpanded = expandedItems.has(item.label);
      return /* @__PURE__ */ React12.createElement("div", { key: item.label }, /* @__PURE__ */ React12.createElement(
        "button",
        {
          onClick: () => handleItemClick(item),
          className: cn(
            "flex w-full items-center justify-between px-3 py-2 text-sm font-medium rounded-lg transition-colors group",
            "hover:bg-accent hover:text-accent-foreground",
            "focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2",
            level > 0 && "ml-4 pl-6",
            item.active && "bg-accent text-accent-foreground",
            item.disabled && "opacity-50 cursor-not-allowed",
            isCollapsed && "justify-center px-2"
          ),
          disabled: item.disabled,
          title: isCollapsed ? item.label : void 0
        },
        /* @__PURE__ */ React12.createElement("div", { className: "flex items-center space-x-3" }, item.icon && /* @__PURE__ */ React12.createElement("div", { className: "flex-shrink-0" }, item.icon), !isCollapsed && /* @__PURE__ */ React12.createElement("span", { className: "truncate" }, item.label)),
        !isCollapsed && /* @__PURE__ */ React12.createElement("div", { className: "flex items-center space-x-2" }, item.badge && /* @__PURE__ */ React12.createElement("span", { className: "px-2 py-0.5 text-xs bg-primary text-primary-foreground rounded-full" }, item.badge), hasChildren && /* @__PURE__ */ React12.createElement(import_lucide_react6.ChevronDown, { className: cn(
          "h-4 w-4 transition-transform",
          isExpanded && "rotate-180"
        ) }))
      ), hasChildren && isExpanded && !isCollapsed && /* @__PURE__ */ React12.createElement("div", { className: "mt-1 space-y-1" }, item.items.map((subItem) => renderItem(subItem, level + 1))));
    };
    return /* @__PURE__ */ React12.createElement(
      "div",
      {
        ref,
        className: cn(
          sidebarVariants({
            variant,
            size: isCollapsed ? "sm" : size
          }),
          className
        ),
        ...props
      },
      header && /* @__PURE__ */ React12.createElement("div", { className: cn(
        "flex items-center p-4 border-b border-border",
        isCollapsed && "justify-center px-2"
      ) }, header),
      /* @__PURE__ */ React12.createElement("div", { className: "flex-1 overflow-y-auto p-4 space-y-2" }, sections.map((section, sectionIndex) => /* @__PURE__ */ React12.createElement("div", { key: `section-${sectionIndex}` }, section.title && !isCollapsed && /* @__PURE__ */ React12.createElement("div", { className: "px-3 mb-2" }, /* @__PURE__ */ React12.createElement("h3", { className: "text-xs font-semibold text-muted-foreground uppercase tracking-wider" }, section.title)), /* @__PURE__ */ React12.createElement("div", { className: "space-y-1" }, section.items.map((item) => renderItem(item))), sectionIndex < sections.length - 1 && /* @__PURE__ */ React12.createElement("div", { className: "my-4 border-t border-border" })))),
      footer && /* @__PURE__ */ React12.createElement("div", { className: cn(
        "p-4 border-t border-border",
        isCollapsed && "px-2"
      ) }, footer),
      collapsible && showCollapseButton && /* @__PURE__ */ React12.createElement("div", { className: "p-2 border-t border-border" }, /* @__PURE__ */ React12.createElement(
        "button",
        {
          onClick: toggleCollapse,
          className: "flex w-full items-center justify-center p-2 rounded-lg hover:bg-accent hover:text-accent-foreground focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2",
          title: isCollapsed ? "Expand sidebar" : "Collapse sidebar"
        },
        isCollapsed ? /* @__PURE__ */ React12.createElement(import_lucide_react6.ChevronRight, { className: "h-4 w-4" }) : /* @__PURE__ */ React12.createElement(import_lucide_react6.ChevronLeft, { className: "h-4 w-4" })
      ))
    );
  }
);
Sidebar.displayName = "Sidebar";
function useSidebar(defaultCollapsed = false) {
  const [collapsed, setCollapsed] = React12.useState(defaultCollapsed);
  const toggle = React12.useCallback(() => {
    setCollapsed((prev) => !prev);
  }, []);
  const expand = React12.useCallback(() => {
    setCollapsed(false);
  }, []);
  const collapse = React12.useCallback(() => {
    setCollapsed(true);
  }, []);
  return {
    collapsed,
    toggle,
    expand,
    collapse,
    setCollapsed
  };
}

// src/components/ui/form.tsx
var React13 = __toESM(require("react"));
var import_class_variance_authority10 = require("class-variance-authority");
var formVariants = (0, import_class_variance_authority10.cva)("space-y-6", {
  variants: {
    variant: {
      default: "",
      card: "p-6 border border-border rounded-lg bg-card",
      inline: "space-y-0 flex items-end space-x-4"
    }
  },
  defaultVariants: {
    variant: "default"
  }
});
var FormContext = React13.createContext(void 0);
function useFormContext() {
  const context = React13.useContext(FormContext);
  if (!context) {
    throw new Error("useFormContext must be used within a Form component");
  }
  return context;
}
var Form = React13.forwardRef(
  ({
    className,
    variant,
    initialValues = {},
    validationRules = {},
    onFormSubmit,
    validateOnChange = true,
    validateOnBlur = true,
    children,
    ...props
  }, ref) => {
    const [values, setValues] = React13.useState(initialValues);
    const [errors, setErrors] = React13.useState({});
    const [touched, setTouchedState] = React13.useState({});
    const [isSubmitting, setIsSubmitting] = React13.useState(false);
    const validateField = React13.useCallback(async (name) => {
      const rule = validationRules[name];
      if (!rule) return true;
      const value = values[name];
      let error;
      if (rule.required) {
        const isRequired = typeof rule.required === "boolean" ? rule.required : true;
        const message = typeof rule.required === "string" ? rule.required : `${name} is required`;
        if (isRequired && (value === void 0 || value === null || value === "")) {
          error = { message, type: "required" };
        }
      }
      if (!error && rule.minLength && typeof value === "string") {
        const minLength = typeof rule.minLength === "number" ? rule.minLength : rule.minLength.value;
        const message = typeof rule.minLength === "object" ? rule.minLength.message : `${name} must be at least ${minLength} characters`;
        if (value.length < minLength) {
          error = { message, type: "minLength" };
        }
      }
      if (!error && rule.maxLength && typeof value === "string") {
        const maxLength = typeof rule.maxLength === "number" ? rule.maxLength : rule.maxLength.value;
        const message = typeof rule.maxLength === "object" ? rule.maxLength.message : `${name} must be no more than ${maxLength} characters`;
        if (value.length > maxLength) {
          error = { message, type: "maxLength" };
        }
      }
      if (!error && rule.pattern && typeof value === "string") {
        const pattern = rule.pattern instanceof RegExp ? rule.pattern : rule.pattern.value;
        const message = rule.pattern instanceof RegExp ? `${name} format is invalid` : rule.pattern.message;
        if (!pattern.test(value)) {
          error = { message, type: "pattern" };
        }
      }
      if (!error && rule.validate) {
        const result = await rule.validate(value, values);
        if (typeof result === "string") {
          error = { message: result, type: "custom" };
        } else if (result === false) {
          error = { message: `${name} is invalid`, type: "custom" };
        }
      }
      setErrors((prev) => ({ ...prev, [name]: error }));
      return !error;
    }, [values, validationRules]);
    const setValue = React13.useCallback((name, value) => {
      setValues((prev) => ({ ...prev, [name]: value }));
      if (validateOnChange && touched[name]) {
        setTimeout(() => validateField(name), 0);
      }
    }, [validateOnChange, touched, validateField]);
    const setError = React13.useCallback((name, error) => {
      setErrors((prev) => ({ ...prev, [name]: error }));
    }, []);
    const setTouched = React13.useCallback((name, isTouched = true) => {
      setTouchedState((prev) => ({ ...prev, [name]: isTouched }));
      if (validateOnBlur && isTouched) {
        validateField(name);
      }
    }, [validateOnBlur, validateField]);
    const resetForm = React13.useCallback(() => {
      setValues(initialValues);
      setErrors({});
      setTouchedState({});
      setIsSubmitting(false);
    }, [initialValues]);
    const handleSubmit = async (e) => {
      e.preventDefault();
      if (!onFormSubmit || isSubmitting) return;
      setIsSubmitting(true);
      const fieldNames = Object.keys(validationRules);
      const validationResults = await Promise.all(
        fieldNames.map((name) => validateField(name))
      );
      const hasErrors = validationResults.some((result) => !result);
      if (hasErrors) {
        setIsSubmitting(false);
        return;
      }
      try {
        await onFormSubmit(values, {
          setSubmitting: setIsSubmitting,
          setErrors: (errors2) => setErrors(errors2)
        });
      } catch (error) {
        console.error("Form submission error:", error);
      } finally {
        setIsSubmitting(false);
      }
    };
    const contextValue = {
      values,
      errors,
      touched,
      isSubmitting,
      setValue,
      setError,
      setTouched,
      validateField,
      resetForm
    };
    return /* @__PURE__ */ React13.createElement(FormContext.Provider, { value: contextValue }, /* @__PURE__ */ React13.createElement(
      "form",
      {
        ref,
        className: cn(formVariants({ variant }), className),
        onSubmit: handleSubmit,
        ...props
      },
      children
    ));
  }
);
Form.displayName = "Form";
var FormField = ({ name, children }) => {
  const { values, errors, touched, setValue, setTouched } = useFormContext();
  const handleChange = (value) => {
    setValue(name, value);
  };
  const handleBlur = () => {
    setTouched(name, true);
  };
  return /* @__PURE__ */ React13.createElement(React13.Fragment, null, children({
    value: values[name] ?? "",
    onChange: handleChange,
    onBlur: handleBlur,
    error: errors[name],
    touched: !!touched[name]
  }));
};
var FormSubmit = React13.forwardRef(
  ({ children, loadingText = "Submitting...", disabled, ...props }, ref) => {
    const { isSubmitting } = useFormContext();
    return /* @__PURE__ */ React13.createElement(
      "button",
      {
        ref,
        type: "submit",
        disabled: disabled || isSubmitting,
        ...props
      },
      isSubmitting ? loadingText : children
    );
  }
);
FormSubmit.displayName = "FormSubmit";

// src/components/ui/dropdown.tsx
var React14 = __toESM(require("react"));
var DropdownMenuPrimitive = __toESM(require("@radix-ui/react-dropdown-menu"));
var import_lucide_react7 = require("lucide-react");
var DropdownMenu = DropdownMenuPrimitive.Root;
var DropdownMenuTrigger = DropdownMenuPrimitive.Trigger;
var DropdownMenuGroup = DropdownMenuPrimitive.Group;
var DropdownMenuPortal = DropdownMenuPrimitive.Portal;
var DropdownMenuSub = DropdownMenuPrimitive.Sub;
var DropdownMenuRadioGroup = DropdownMenuPrimitive.RadioGroup;
var DropdownMenuSubTrigger = React14.forwardRef(({ className, inset, children, ...props }, ref) => /* @__PURE__ */ React14.createElement(
  DropdownMenuPrimitive.SubTrigger,
  {
    ref,
    className: cn(
      "flex cursor-default select-none items-center rounded-sm px-2 py-1.5 text-sm outline-none focus:bg-accent data-[state=open]:bg-accent",
      inset && "pl-8",
      className
    ),
    ...props
  },
  children,
  /* @__PURE__ */ React14.createElement(import_lucide_react7.ChevronRight, { className: "ml-auto h-4 w-4" })
));
DropdownMenuSubTrigger.displayName = DropdownMenuPrimitive.SubTrigger.displayName;
var DropdownMenuSubContent = React14.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ React14.createElement(
  DropdownMenuPrimitive.SubContent,
  {
    ref,
    className: cn(
      "z-50 min-w-[8rem] overflow-hidden rounded-md border bg-popover p-1 text-popover-foreground shadow-lg data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2",
      className
    ),
    ...props
  }
));
DropdownMenuSubContent.displayName = DropdownMenuPrimitive.SubContent.displayName;
var DropdownMenuContent = React14.forwardRef(({ className, sideOffset = 4, ...props }, ref) => /* @__PURE__ */ React14.createElement(DropdownMenuPrimitive.Portal, null, /* @__PURE__ */ React14.createElement(
  DropdownMenuPrimitive.Content,
  {
    ref,
    sideOffset,
    className: cn(
      "z-50 min-w-[8rem] overflow-hidden rounded-md border bg-popover p-1 text-popover-foreground shadow-md data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2",
      className
    ),
    ...props
  }
)));
DropdownMenuContent.displayName = DropdownMenuPrimitive.Content.displayName;
var DropdownMenuItem = React14.forwardRef(({ className, inset, ...props }, ref) => /* @__PURE__ */ React14.createElement(
  DropdownMenuPrimitive.Item,
  {
    ref,
    className: cn(
      "relative flex cursor-default select-none items-center rounded-sm px-2 py-1.5 text-sm outline-none transition-colors focus:bg-accent focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50",
      inset && "pl-8",
      className
    ),
    ...props
  }
));
DropdownMenuItem.displayName = DropdownMenuPrimitive.Item.displayName;
var DropdownMenuCheckboxItem = React14.forwardRef(({ className, children, checked, ...props }, ref) => /* @__PURE__ */ React14.createElement(
  DropdownMenuPrimitive.CheckboxItem,
  {
    ref,
    className: cn(
      "relative flex cursor-default select-none items-center rounded-sm py-1.5 pl-8 pr-2 text-sm outline-none transition-colors focus:bg-accent focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50",
      className
    ),
    checked,
    ...props
  },
  /* @__PURE__ */ React14.createElement("span", { className: "absolute left-2 flex h-3.5 w-3.5 items-center justify-center" }, /* @__PURE__ */ React14.createElement(DropdownMenuPrimitive.ItemIndicator, null, /* @__PURE__ */ React14.createElement(import_lucide_react7.Check, { className: "h-4 w-4" }))),
  children
));
DropdownMenuCheckboxItem.displayName = DropdownMenuPrimitive.CheckboxItem.displayName;
var DropdownMenuRadioItem = React14.forwardRef(({ className, children, ...props }, ref) => /* @__PURE__ */ React14.createElement(
  DropdownMenuPrimitive.RadioItem,
  {
    ref,
    className: cn(
      "relative flex cursor-default select-none items-center rounded-sm py-1.5 pl-8 pr-2 text-sm outline-none transition-colors focus:bg-accent focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50",
      className
    ),
    ...props
  },
  /* @__PURE__ */ React14.createElement("span", { className: "absolute left-2 flex h-3.5 w-3.5 items-center justify-center" }, /* @__PURE__ */ React14.createElement(DropdownMenuPrimitive.ItemIndicator, null, /* @__PURE__ */ React14.createElement(import_lucide_react7.Circle, { className: "h-2 w-2 fill-current" }))),
  children
));
DropdownMenuRadioItem.displayName = DropdownMenuPrimitive.RadioItem.displayName;
var DropdownMenuLabel = React14.forwardRef(({ className, inset, ...props }, ref) => /* @__PURE__ */ React14.createElement(
  DropdownMenuPrimitive.Label,
  {
    ref,
    className: cn(
      "px-2 py-1.5 text-sm font-semibold",
      inset && "pl-8",
      className
    ),
    ...props
  }
));
DropdownMenuLabel.displayName = DropdownMenuPrimitive.Label.displayName;
var DropdownMenuSeparator = React14.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ React14.createElement(
  DropdownMenuPrimitive.Separator,
  {
    ref,
    className: cn("-mx-1 my-1 h-px bg-muted", className),
    ...props
  }
));
DropdownMenuSeparator.displayName = DropdownMenuPrimitive.Separator.displayName;
var DropdownMenuShortcut = ({
  className,
  ...props
}) => {
  return /* @__PURE__ */ React14.createElement(
    "span",
    {
      className: cn("ml-auto text-xs tracking-widest opacity-60", className),
      ...props
    }
  );
};
DropdownMenuShortcut.displayName = "DropdownMenuShortcut";

// src/components/ui/alert.tsx
var React15 = __toESM(require("react"));
var import_class_variance_authority11 = require("class-variance-authority");
var import_lucide_react8 = require("lucide-react");
var alertVariants = (0, import_class_variance_authority11.cva)(
  "relative w-full rounded-lg border p-4 [&>svg~*]:pl-7 [&>svg+div]:translate-y-[-3px] [&>svg]:absolute [&>svg]:left-4 [&>svg]:top-4 [&>svg]:text-foreground",
  {
    variants: {
      variant: {
        default: "bg-background text-foreground",
        destructive: "border-destructive/50 text-destructive dark:border-destructive [&>svg]:text-destructive",
        warning: "border-yellow-200 bg-yellow-50 text-yellow-800 dark:border-yellow-900/50 dark:bg-yellow-900/20 dark:text-yellow-200 [&>svg]:text-yellow-600 dark:[&>svg]:text-yellow-400",
        success: "border-green-200 bg-green-50 text-green-800 dark:border-green-900/50 dark:bg-green-900/20 dark:text-green-200 [&>svg]:text-green-600 dark:[&>svg]:text-green-400",
        info: "border-blue-200 bg-blue-50 text-blue-800 dark:border-blue-900/50 dark:bg-blue-900/20 dark:text-blue-200 [&>svg]:text-blue-600 dark:[&>svg]:text-blue-400"
      }
    },
    defaultVariants: {
      variant: "default"
    }
  }
);
var Alert = React15.forwardRef(({ className, variant, ...props }, ref) => /* @__PURE__ */ React15.createElement(
  "div",
  {
    ref,
    role: "alert",
    className: cn(alertVariants({ variant }), className),
    ...props
  }
));
Alert.displayName = "Alert";
var AlertTitle = React15.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ React15.createElement(
  "h5",
  {
    ref,
    className: cn("mb-1 font-medium leading-none tracking-tight", className),
    ...props
  }
));
AlertTitle.displayName = "AlertTitle";
var AlertDescription = React15.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ React15.createElement(
  "div",
  {
    ref,
    className: cn("text-sm [&_p]:leading-relaxed", className),
    ...props
  }
));
AlertDescription.displayName = "AlertDescription";
var AlertIcon = ({ variant }) => {
  switch (variant) {
    case "destructive":
      return /* @__PURE__ */ React15.createElement(import_lucide_react8.XCircle, { className: "h-4 w-4" });
    case "warning":
      return /* @__PURE__ */ React15.createElement(import_lucide_react8.AlertCircle, { className: "h-4 w-4" });
    case "success":
      return /* @__PURE__ */ React15.createElement(import_lucide_react8.CheckCircle2, { className: "h-4 w-4" });
    case "info":
      return /* @__PURE__ */ React15.createElement(import_lucide_react8.Info, { className: "h-4 w-4" });
    default:
      return /* @__PURE__ */ React15.createElement(import_lucide_react8.Info, { className: "h-4 w-4" });
  }
};

// src/components/ui/loader.tsx
var React16 = __toESM(require("react"));
var import_class_variance_authority12 = require("class-variance-authority");
var loaderVariants = (0, import_class_variance_authority12.cva)("animate-spin inline-block border-solid border-current border-r-transparent align-[-0.125em] motion-reduce:animate-[spin_1.5s_linear_infinite]", {
  variants: {
    size: {
      xs: "h-3 w-3 border-2",
      sm: "h-4 w-4 border-2",
      md: "h-6 w-6 border-2",
      lg: "h-8 w-8 border-[3px]",
      xl: "h-12 w-12 border-4"
    },
    variant: {
      default: "text-primary",
      secondary: "text-secondary",
      muted: "text-muted-foreground",
      white: "text-white"
    }
  },
  defaultVariants: {
    size: "md",
    variant: "default"
  }
});
var Loader = React16.forwardRef(
  ({ className, size, variant, text, ...props }, ref) => {
    return /* @__PURE__ */ React16.createElement(
      "div",
      {
        ref,
        className: cn("flex items-center gap-2", className),
        role: "status",
        "aria-label": text || "Loading",
        ...props
      },
      /* @__PURE__ */ React16.createElement(
        "div",
        {
          className: cn(loaderVariants({ size, variant }), "rounded-full")
        }
      ),
      text && /* @__PURE__ */ React16.createElement("span", { className: "text-sm text-muted-foreground" }, text)
    );
  }
);
Loader.displayName = "Loader";
var skeletonVariants = (0, import_class_variance_authority12.cva)("animate-pulse bg-muted rounded", {
  variants: {
    variant: {
      default: "bg-muted",
      card: "bg-muted/50",
      text: "bg-muted/60"
    }
  },
  defaultVariants: {
    variant: "default"
  }
});
var Skeleton = React16.forwardRef(
  ({ className, variant, ...props }, ref) => {
    return /* @__PURE__ */ React16.createElement(
      "div",
      {
        ref,
        className: cn(skeletonVariants({ variant }), className),
        ...props
      }
    );
  }
);
Skeleton.displayName = "Skeleton";
var PageLoader = ({ text = "Loading...", size = "lg" }) => {
  return /* @__PURE__ */ React16.createElement("div", { className: "flex min-h-[400px] w-full items-center justify-center" }, /* @__PURE__ */ React16.createElement(Loader, { size, text }));
};

// src/components/ui/chip.tsx
var React17 = __toESM(require("react"));
var import_class_variance_authority13 = require("class-variance-authority");
var import_lucide_react9 = require("lucide-react");
var chipVariants = (0, import_class_variance_authority13.cva)(
  "inline-flex items-center gap-1 rounded-full px-2.5 py-0.5 text-xs font-medium transition-colors focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2",
  {
    variants: {
      variant: {
        default: "bg-primary text-primary-foreground hover:bg-primary/80",
        secondary: "bg-secondary text-secondary-foreground hover:bg-secondary/80",
        destructive: "bg-destructive text-destructive-foreground hover:bg-destructive/80",
        outline: "text-foreground border border-input hover:bg-accent hover:text-accent-foreground",
        success: "bg-green-100 text-green-800 hover:bg-green-200 dark:bg-green-900/20 dark:text-green-400 dark:hover:bg-green-900/30",
        warning: "bg-yellow-100 text-yellow-800 hover:bg-yellow-200 dark:bg-yellow-900/20 dark:text-yellow-400 dark:hover:bg-yellow-900/30",
        info: "bg-blue-100 text-blue-800 hover:bg-blue-200 dark:bg-blue-900/20 dark:text-blue-400 dark:hover:bg-blue-900/30"
      },
      size: {
        sm: "h-5 px-2 text-xs",
        md: "h-6 px-2.5 text-xs",
        lg: "h-7 px-3 text-sm"
      }
    },
    defaultVariants: {
      variant: "default",
      size: "md"
    }
  }
);
var Chip = React17.forwardRef(
  ({ className, variant, size, onRemove, removable = false, disabled = false, children, ...props }, ref) => {
    return /* @__PURE__ */ React17.createElement(
      "div",
      {
        ref,
        className: cn(
          chipVariants({ variant, size }),
          disabled && "opacity-50 cursor-not-allowed",
          className
        ),
        ...props
      },
      /* @__PURE__ */ React17.createElement("span", { className: "truncate" }, children),
      removable && !disabled && /* @__PURE__ */ React17.createElement(
        "button",
        {
          type: "button",
          onClick: onRemove,
          className: "ml-1 inline-flex h-3 w-3 items-center justify-center rounded-full hover:bg-black/20 dark:hover:bg-white/20 transition-colors",
          "aria-label": "Remove"
        },
        /* @__PURE__ */ React17.createElement(import_lucide_react9.X, { className: "h-2 w-2" })
      )
    );
  }
);
Chip.displayName = "Chip";
var ChipGroup = React17.forwardRef(
  ({ className, chips, onRemove, maxVisible, ...props }, ref) => {
    const visibleChips = maxVisible ? chips.slice(0, maxVisible) : chips;
    const hiddenCount = maxVisible ? Math.max(0, chips.length - maxVisible) : 0;
    return /* @__PURE__ */ React17.createElement(
      "div",
      {
        ref,
        className: cn("flex flex-wrap items-center gap-1", className),
        ...props
      },
      visibleChips.map((chip) => /* @__PURE__ */ React17.createElement(
        Chip,
        {
          key: chip.id,
          variant: chip.variant,
          removable: chip.removable,
          onRemove: () => onRemove?.(chip.id)
        },
        chip.label
      )),
      hiddenCount > 0 && /* @__PURE__ */ React17.createElement(Chip, { variant: "outline", size: "sm" }, "+", hiddenCount, " more")
    );
  }
);
ChipGroup.displayName = "ChipGroup";

// src/components/ui/pagination.tsx
var React18 = __toESM(require("react"));
var import_class_variance_authority14 = require("class-variance-authority");
var import_lucide_react10 = require("lucide-react");
var paginationVariants = (0, import_class_variance_authority14.cva)(
  "flex items-center justify-center space-x-2",
  {
    variants: {
      size: {
        default: "",
        sm: "[&_button]:h-8 [&_button]:px-2 [&_button]:text-xs",
        lg: "[&_button]:h-12 [&_button]:px-4 [&_button]:text-base"
      }
    },
    defaultVariants: {
      size: "default"
    }
  }
);
var Pagination = React18.forwardRef(
  ({
    className,
    size,
    currentPage,
    totalPages,
    onPageChange,
    showFirstLast = true,
    showPrevNext = true,
    maxVisiblePages = 5,
    ...props
  }, ref) => {
    const getVisiblePages = () => {
      const half = Math.floor(maxVisiblePages / 2);
      let start = Math.max(currentPage - half, 1);
      let end = Math.min(start + maxVisiblePages - 1, totalPages);
      if (end - start + 1 < maxVisiblePages) {
        start = Math.max(end - maxVisiblePages + 1, 1);
      }
      return Array.from({ length: end - start + 1 }, (_, i) => start + i);
    };
    const visiblePages = getVisiblePages();
    const isFirstPage = currentPage === 1;
    const isLastPage = currentPage === totalPages;
    return /* @__PURE__ */ React18.createElement(
      "nav",
      {
        ref,
        className: cn(paginationVariants({ size }), className),
        role: "navigation",
        "aria-label": "Pagination",
        ...props
      },
      showFirstLast && !isFirstPage && /* @__PURE__ */ React18.createElement(
        Button,
        {
          variant: "outline",
          size: size === "sm" ? "sm" : size === "lg" ? "lg" : "default",
          onClick: () => onPageChange(1),
          "aria-label": "Go to first page"
        },
        "First"
      ),
      showPrevNext && !isFirstPage && /* @__PURE__ */ React18.createElement(
        Button,
        {
          variant: "outline",
          size: size === "sm" ? "sm" : size === "lg" ? "lg" : "default",
          onClick: () => onPageChange(currentPage - 1),
          "aria-label": "Go to previous page"
        },
        /* @__PURE__ */ React18.createElement(import_lucide_react10.ChevronLeft, { className: "h-4 w-4" })
      ),
      visiblePages[0] > 1 && /* @__PURE__ */ React18.createElement(React18.Fragment, null, /* @__PURE__ */ React18.createElement(
        Button,
        {
          variant: "outline",
          size: size === "sm" ? "sm" : size === "lg" ? "lg" : "default",
          onClick: () => onPageChange(1)
        },
        "1"
      ), visiblePages[0] > 2 && /* @__PURE__ */ React18.createElement("span", { className: "px-2 text-muted-foreground" }, "...")),
      visiblePages.map((page) => /* @__PURE__ */ React18.createElement(
        Button,
        {
          key: page,
          variant: page === currentPage ? "default" : "outline",
          size: size === "sm" ? "sm" : size === "lg" ? "lg" : "default",
          onClick: () => onPageChange(page),
          "aria-label": `Go to page ${page}`,
          "aria-current": page === currentPage ? "page" : void 0
        },
        page
      )),
      visiblePages[visiblePages.length - 1] < totalPages && /* @__PURE__ */ React18.createElement(React18.Fragment, null, visiblePages[visiblePages.length - 1] < totalPages - 1 && /* @__PURE__ */ React18.createElement("span", { className: "px-2 text-muted-foreground" }, "..."), /* @__PURE__ */ React18.createElement(
        Button,
        {
          variant: "outline",
          size: size === "sm" ? "sm" : size === "lg" ? "lg" : "default",
          onClick: () => onPageChange(totalPages)
        },
        totalPages
      )),
      showPrevNext && !isLastPage && /* @__PURE__ */ React18.createElement(
        Button,
        {
          variant: "outline",
          size: size === "sm" ? "sm" : size === "lg" ? "lg" : "default",
          onClick: () => onPageChange(currentPage + 1),
          "aria-label": "Go to next page"
        },
        /* @__PURE__ */ React18.createElement(import_lucide_react10.ChevronRight, { className: "h-4 w-4" })
      ),
      showFirstLast && !isLastPage && /* @__PURE__ */ React18.createElement(
        Button,
        {
          variant: "outline",
          size: size === "sm" ? "sm" : size === "lg" ? "lg" : "default",
          onClick: () => onPageChange(totalPages),
          "aria-label": "Go to last page"
        },
        "Last"
      )
    );
  }
);
Pagination.displayName = "Pagination";
var PaginationInfo = ({
  currentPage,
  totalItems,
  itemsPerPage,
  className
}) => {
  const startItem = (currentPage - 1) * itemsPerPage + 1;
  const endItem = Math.min(currentPage * itemsPerPage, totalItems);
  return /* @__PURE__ */ React18.createElement("div", { className: cn("text-sm text-muted-foreground", className) }, "Showing ", startItem, " to ", endItem, " of ", totalItems, " results");
};

// src/components/ui/search-bar.tsx
var React19 = __toESM(require("react"));
var import_class_variance_authority15 = require("class-variance-authority");
var import_lucide_react11 = require("lucide-react");
var searchBarVariants = (0, import_class_variance_authority15.cva)(
  "flex items-center space-x-2 p-4 bg-background border rounded-lg",
  {
    variants: {
      variant: {
        default: "border-border",
        elevated: "border-border shadow-md",
        ghost: "border-transparent bg-transparent p-2"
      },
      size: {
        sm: "p-2 space-x-1",
        md: "p-4 space-x-2",
        lg: "p-6 space-x-3"
      }
    },
    defaultVariants: {
      variant: "default",
      size: "md"
    }
  }
);
var SearchBar = React19.forwardRef(
  ({
    className,
    variant,
    size,
    searchValue,
    onSearchChange,
    placeholder = "Search...",
    filters = [],
    activeFilters = [],
    onFilterAdd,
    onFilterRemove,
    onClearAll,
    showFilterButton = true,
    showClearButton = true,
    ...props
  }, ref) => {
    const [isFilterOpen, setIsFilterOpen] = React19.useState(false);
    const [selectedFilterId, setSelectedFilterId] = React19.useState("");
    const [filterValue, setFilterValue] = React19.useState("");
    const selectedFilter = filters.find((f) => f.id === selectedFilterId);
    const handleAddFilter = () => {
      if (selectedFilter && filterValue.trim() && onFilterAdd) {
        const display = selectedFilter.type === "select" ? selectedFilter.options?.find((opt) => opt.value === filterValue)?.label || filterValue : filterValue;
        onFilterAdd({
          id: `${selectedFilter.id}-${Date.now()}`,
          label: selectedFilter.label,
          value: filterValue,
          display: `${selectedFilter.label}: ${display}`
        });
        setSelectedFilterId("");
        setFilterValue("");
        setIsFilterOpen(false);
      }
    };
    return /* @__PURE__ */ React19.createElement(
      "div",
      {
        ref,
        className: cn(searchBarVariants({ variant, size }), "flex-col space-y-3", className),
        ...props
      },
      /* @__PURE__ */ React19.createElement("div", { className: "flex items-center space-x-2 w-full" }, /* @__PURE__ */ React19.createElement("div", { className: "relative flex-1" }, /* @__PURE__ */ React19.createElement(import_lucide_react11.Search, { className: "absolute left-3 top-1/2 transform -translate-y-1/2 h-4 w-4 text-muted-foreground" }), /* @__PURE__ */ React19.createElement(
        Input,
        {
          value: searchValue,
          onChange: (e) => onSearchChange(e.target.value),
          placeholder,
          className: "pl-10"
        }
      )), showFilterButton && filters.length > 0 && /* @__PURE__ */ React19.createElement(
        Button,
        {
          variant: "outline",
          size: "sm",
          onClick: () => setIsFilterOpen(!isFilterOpen),
          className: "shrink-0"
        },
        /* @__PURE__ */ React19.createElement(import_lucide_react11.Filter, { className: "h-4 w-4 mr-2" }),
        "Filter"
      ), showClearButton && (activeFilters.length > 0 || searchValue) && /* @__PURE__ */ React19.createElement(
        Button,
        {
          variant: "ghost",
          size: "sm",
          onClick: () => {
            onSearchChange("");
            onClearAll?.();
          },
          className: "shrink-0"
        },
        /* @__PURE__ */ React19.createElement(import_lucide_react11.X, { className: "h-4 w-4 mr-2" }),
        "Clear"
      )),
      activeFilters.length > 0 && /* @__PURE__ */ React19.createElement("div", { className: "flex flex-wrap gap-2" }, activeFilters.map((filter) => /* @__PURE__ */ React19.createElement(
        Chip,
        {
          key: filter.id,
          variant: "outline",
          size: "sm",
          removable: true,
          onRemove: () => onFilterRemove?.(filter.id)
        },
        filter.display
      ))),
      isFilterOpen && /* @__PURE__ */ React19.createElement("div", { className: "flex items-end space-x-2 p-3 bg-muted/50 rounded-md" }, /* @__PURE__ */ React19.createElement("div", { className: "flex-1" }, /* @__PURE__ */ React19.createElement("label", { className: "text-sm font-medium mb-1 block" }, "Filter by"), /* @__PURE__ */ React19.createElement(
        Select,
        {
          options: filters.map((f) => ({ value: f.id, label: f.label })),
          value: selectedFilterId,
          onValueChange: setSelectedFilterId,
          placeholder: "Select filter..."
        }
      )), selectedFilter && /* @__PURE__ */ React19.createElement("div", { className: "flex-1" }, /* @__PURE__ */ React19.createElement("label", { className: "text-sm font-medium mb-1 block" }, "Value"), selectedFilter.type === "select" ? /* @__PURE__ */ React19.createElement(
        Select,
        {
          options: selectedFilter.options || [],
          value: filterValue,
          onValueChange: setFilterValue,
          placeholder: selectedFilter.placeholder || "Select value..."
        }
      ) : /* @__PURE__ */ React19.createElement(
        Input,
        {
          type: selectedFilter.type === "date" ? "date" : selectedFilter.type === "number" ? "number" : "text",
          value: filterValue,
          onChange: (e) => setFilterValue(e.target.value),
          placeholder: selectedFilter.placeholder || "Enter value..."
        }
      )), /* @__PURE__ */ React19.createElement(
        Button,
        {
          onClick: handleAddFilter,
          disabled: !selectedFilter || !filterValue.trim(),
          size: "sm"
        },
        "Add Filter"
      ))
    );
  }
);
SearchBar.displayName = "SearchBar";

// src/components/ui/stat-card.tsx
var React20 = __toESM(require("react"));
var import_class_variance_authority16 = require("class-variance-authority");
var import_lucide_react12 = require("lucide-react");
var statCardVariants = (0, import_class_variance_authority16.cva)(
  "transition-all duration-200 hover:shadow-md",
  {
    variants: {
      variant: {
        default: "",
        accent: "border-l-4 border-l-primary",
        gradient: "bg-gradient-to-br from-primary/5 to-primary/10",
        elevated: "shadow-lg border-0"
      },
      size: {
        sm: "[&_.stat-value]:text-xl [&_.stat-label]:text-xs",
        md: "[&_.stat-value]:text-2xl [&_.stat-label]:text-sm",
        lg: "[&_.stat-value]:text-3xl [&_.stat-label]:text-base"
      }
    },
    defaultVariants: {
      variant: "default",
      size: "md"
    }
  }
);
var StatCard = React20.forwardRef(
  ({
    className,
    variant,
    size,
    title,
    value,
    change,
    icon,
    trend,
    format = "number",
    loading = false,
    ...props
  }, ref) => {
    const formatValue = (val) => {
      const numValue = typeof val === "string" ? parseFloat(val) : val;
      if (isNaN(numValue)) return val;
      switch (format) {
        case "currency":
          return new Intl.NumberFormat("en-US", {
            style: "currency",
            currency: "USD",
            minimumFractionDigits: 0,
            maximumFractionDigits: 2
          }).format(numValue);
        case "percentage":
          return `${numValue}%`;
        case "number":
        default:
          return new Intl.NumberFormat("en-US").format(numValue);
      }
    };
    const getTrendIcon = () => {
      if (!change) return null;
      const trendType = trend || (change.value > 0 ? "up" : change.value < 0 ? "down" : "neutral");
      switch (trendType) {
        case "up":
          return /* @__PURE__ */ React20.createElement(import_lucide_react12.TrendingUp, { className: "h-4 w-4 text-green-500" });
        case "down":
          return /* @__PURE__ */ React20.createElement(import_lucide_react12.TrendingDown, { className: "h-4 w-4 text-red-500" });
        case "neutral":
        default:
          return /* @__PURE__ */ React20.createElement(import_lucide_react12.Minus, { className: "h-4 w-4 text-muted-foreground" });
      }
    };
    const getTrendColor = () => {
      if (!change) return "text-muted-foreground";
      const trendType = trend || (change.value > 0 ? "up" : change.value < 0 ? "down" : "neutral");
      switch (trendType) {
        case "up":
          return "text-green-600";
        case "down":
          return "text-red-600";
        case "neutral":
        default:
          return "text-muted-foreground";
      }
    };
    if (loading) {
      return /* @__PURE__ */ React20.createElement(Card, { ref, className: cn(statCardVariants({ variant, size }), className), ...props }, /* @__PURE__ */ React20.createElement(CardHeader, { className: "flex flex-row items-center justify-between space-y-0 pb-2" }, /* @__PURE__ */ React20.createElement("div", { className: "animate-pulse bg-muted h-4 w-20 rounded" }), icon && /* @__PURE__ */ React20.createElement("div", { className: "animate-pulse bg-muted h-6 w-6 rounded" })), /* @__PURE__ */ React20.createElement(CardContent, null, /* @__PURE__ */ React20.createElement("div", { className: "animate-pulse bg-muted h-8 w-24 rounded mb-2" }), /* @__PURE__ */ React20.createElement("div", { className: "animate-pulse bg-muted h-3 w-16 rounded" })));
    }
    return /* @__PURE__ */ React20.createElement(Card, { ref, className: cn(statCardVariants({ variant, size }), className), ...props }, /* @__PURE__ */ React20.createElement(CardHeader, { className: "flex flex-row items-center justify-between space-y-0 pb-2" }, /* @__PURE__ */ React20.createElement(CardTitle, { className: "stat-label text-sm font-medium" }, title), icon && /* @__PURE__ */ React20.createElement("div", { className: "text-muted-foreground" }, icon)), /* @__PURE__ */ React20.createElement(CardContent, null, /* @__PURE__ */ React20.createElement("div", { className: "stat-value text-2xl font-bold" }, formatValue(value)), change && /* @__PURE__ */ React20.createElement("div", { className: "flex items-center space-x-1 text-xs mt-1" }, getTrendIcon(), /* @__PURE__ */ React20.createElement("span", { className: getTrendColor() }, change.value > 0 ? "+" : "", change.value, change.label && ` ${change.label}`), change.period && /* @__PURE__ */ React20.createElement("span", { className: "text-muted-foreground" }, "from ", change.period))));
  }
);
StatCard.displayName = "StatCard";
var MetricCard = React20.forwardRef(
  ({ type, ...props }, ref) => {
    const getIconAndFormat = () => {
      switch (type) {
        case "revenue":
          return { icon: /* @__PURE__ */ React20.createElement(import_lucide_react12.DollarSign, { className: "h-4 w-4" }), format: "currency" };
        case "users":
          return { icon: /* @__PURE__ */ React20.createElement(import_lucide_react12.Users, { className: "h-4 w-4" }), format: "number" };
        case "conversion":
          return { icon: /* @__PURE__ */ React20.createElement(import_lucide_react12.Activity, { className: "h-4 w-4" }), format: "percentage" };
        case "views":
          return { icon: /* @__PURE__ */ React20.createElement(import_lucide_react12.Eye, { className: "h-4 w-4" }), format: "number" };
        case "custom":
        default:
          return { icon: void 0, format: "number" };
      }
    };
    const { icon, format } = getIconAndFormat();
    return /* @__PURE__ */ React20.createElement(
      StatCard,
      {
        ref,
        icon,
        format,
        ...props
      }
    );
  }
);
MetricCard.displayName = "MetricCard";

// src/components/ui/code-block.tsx
var import_react = require("react");
var import_lucide_react13 = require("lucide-react");
function CodeBlock({ children, className = "" }) {
  const [copied, setCopied] = (0, import_react.useState)(false);
  const copyToClipboard = async () => {
    try {
      await navigator.clipboard.writeText(children);
      setCopied(true);
      setTimeout(() => setCopied(false), 2e3);
    } catch (err) {
      console.error("Failed to copy text: ", err);
    }
  };
  return /* @__PURE__ */ React.createElement("div", { className: `relative bg-muted p-4 rounded-lg text-sm overflow-x-auto ${className}` }, /* @__PURE__ */ React.createElement(
    Button,
    {
      variant: "ghost",
      size: "sm",
      className: "absolute top-2 right-2 h-8 w-8 p-0",
      onClick: copyToClipboard
    },
    copied ? /* @__PURE__ */ React.createElement(import_lucide_react13.Check, { className: "h-4 w-4 text-green-600" }) : /* @__PURE__ */ React.createElement(import_lucide_react13.Copy, { className: "h-4 w-4" })
  ), /* @__PURE__ */ React.createElement("pre", null, /* @__PURE__ */ React.createElement("code", null, children)));
}

// src/components/theme-provider.tsx
var React21 = __toESM(require("react"));
var import_next_themes = require("next-themes");
function ThemeProvider({ children, ...props }) {
  return /* @__PURE__ */ React21.createElement(import_next_themes.ThemeProvider, { ...props }, children);
}
// Annotate the CommonJS export names for ESM import in node:
0 && (module.exports = {
  Alert,
  AlertDescription,
  AlertIcon,
  AlertTitle,
  Avatar,
  Badge,
  Button,
  Card,
  CardContent,
  CardDescription,
  CardFooter,
  CardHeader,
  CardTitle,
  Chip,
  ChipGroup,
  CodeBlock,
  DataTable,
  DropdownMenu,
  DropdownMenuCheckboxItem,
  DropdownMenuContent,
  DropdownMenuGroup,
  DropdownMenuItem,
  DropdownMenuLabel,
  DropdownMenuPortal,
  DropdownMenuRadioGroup,
  DropdownMenuRadioItem,
  DropdownMenuSeparator,
  DropdownMenuShortcut,
  DropdownMenuSub,
  DropdownMenuSubContent,
  DropdownMenuSubTrigger,
  DropdownMenuTrigger,
  Form,
  FormField,
  FormSubmit,
  Input,
  Loader,
  MetricCard,
  Modal,
  ModalContent,
  ModalDescription,
  ModalFooter,
  ModalHeader,
  ModalTitle,
  Navbar,
  PageLoader,
  Pagination,
  PaginationInfo,
  SearchBar,
  Select,
  Sidebar,
  Skeleton,
  StatCard,
  Table,
  TableBody,
  TableCaption,
  TableCell,
  TableFooter,
  TableHead,
  TableHeader,
  TableRow,
  ThemeProvider,
  Toast,
  ToastContainer,
  ToastProvider,
  avatarVariants,
  badgeVariants,
  buttonVariants,
  cn,
  formVariants,
  inputVariants,
  modalVariants,
  navbarVariants,
  paginationVariants,
  searchBarVariants,
  selectVariants,
  sidebarVariants,
  statCardVariants,
  toast,
  toastVariants,
  useConfirmModal,
  useFormContext,
  useSidebar,
  useToast
});
//# sourceMappingURL=index.js.map