@codeswayam/ui 1.1.0 → 1.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (43) hide show
  1. package/README.md +1 -1
  2. package/dist/components/base/badge.d.ts +1 -1
  3. package/dist/components/base/button.d.ts +1 -1
  4. package/dist/components/base/button.d.ts.map +1 -1
  5. package/dist/components/base/button.js +2 -2
  6. package/dist/components/base/modal.d.ts +14 -0
  7. package/dist/components/base/modal.d.ts.map +1 -0
  8. package/dist/components/base/modal.js +8 -0
  9. package/dist/components/data/DataTable.d.ts +18 -0
  10. package/dist/components/data/DataTable.d.ts.map +1 -0
  11. package/dist/components/data/DataTable.js +36 -0
  12. package/dist/components/data/EmptyState.d.ts +23 -0
  13. package/dist/components/data/EmptyState.d.ts.map +1 -0
  14. package/dist/components/data/EmptyState.js +9 -0
  15. package/dist/components/data/TableToolbar.d.ts +17 -0
  16. package/dist/components/data/TableToolbar.d.ts.map +1 -0
  17. package/dist/components/data/TableToolbar.js +21 -0
  18. package/dist/components/display/CopyButton.d.ts +14 -0
  19. package/dist/components/display/CopyButton.d.ts.map +1 -0
  20. package/dist/components/display/CopyButton.js +37 -0
  21. package/dist/components/display/PageHeader.d.ts +11 -0
  22. package/dist/components/display/PageHeader.d.ts.map +1 -0
  23. package/dist/components/display/PageHeader.js +5 -0
  24. package/dist/components/display/StatCard.d.ts +23 -0
  25. package/dist/components/display/StatCard.d.ts.map +1 -0
  26. package/dist/components/display/StatCard.js +6 -0
  27. package/dist/components/feedback/ConfirmDialog.d.ts +18 -0
  28. package/dist/components/feedback/ConfirmDialog.d.ts.map +1 -0
  29. package/dist/components/feedback/ConfirmDialog.js +10 -0
  30. package/dist/components/feedback/ErrorState.d.ts +10 -0
  31. package/dist/components/feedback/ErrorState.d.ts.map +1 -0
  32. package/dist/components/feedback/ErrorState.js +7 -0
  33. package/dist/components/feedback/Skeleton.d.ts +26 -0
  34. package/dist/components/feedback/Skeleton.d.ts.map +1 -0
  35. package/dist/components/feedback/Skeleton.js +31 -0
  36. package/dist/components/saas/status-badge.d.ts +15 -8
  37. package/dist/components/saas/status-badge.d.ts.map +1 -1
  38. package/dist/components/saas/status-badge.js +46 -25
  39. package/dist/index.d.ts +10 -0
  40. package/dist/index.d.ts.map +1 -1
  41. package/dist/index.js +27 -4
  42. package/dist/tsconfig.tsbuildinfo +1 -1
  43. package/package.json +5 -3
package/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # @codeswayam/ui
2
2
 
3
- **Version:** 1.1.0
3
+ **Version:** 1.2.0
4
4
 
5
5
  Shared React UI component library for all CodeSwayam SaaS applications. Built on Radix UI primitives with Tailwind CSS. Includes base components, SaaS-specific components, layout components, and design tokens.
6
6
 
@@ -1,7 +1,7 @@
1
1
  import * as React from "react";
2
2
  import { type VariantProps } from "class-variance-authority";
3
3
  declare const badgeVariants: (props?: ({
4
- variant?: "default" | "destructive" | "outline" | "secondary" | "success" | "warning" | "info" | "purple" | null | undefined;
4
+ variant?: "default" | "secondary" | "destructive" | "outline" | "success" | "warning" | "info" | "purple" | null | undefined;
5
5
  } & import("class-variance-authority/types").ClassProp) | undefined) => string;
6
6
  export interface BadgeProps extends React.HTMLAttributes<HTMLDivElement>, VariantProps<typeof badgeVariants> {
7
7
  }
@@ -1,7 +1,7 @@
1
1
  import * as React from "react";
2
2
  import { type VariantProps } from "class-variance-authority";
3
3
  declare const buttonVariants: (props?: ({
4
- variant?: "default" | "destructive" | "outline" | "secondary" | "ghost" | "link" | null | undefined;
4
+ variant?: "link" | "default" | "secondary" | "destructive" | "outline" | "ghost" | null | undefined;
5
5
  size?: "default" | "sm" | "lg" | "icon" | null | undefined;
6
6
  } & import("class-variance-authority/types").ClassProp) | undefined) => string;
7
7
  export interface ButtonProps extends React.ButtonHTMLAttributes<HTMLButtonElement>, VariantProps<typeof buttonVariants> {
@@ -1 +1 @@
1
- {"version":3,"file":"button.d.ts","sourceRoot":"","sources":["../../../src/components/base/button.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAE/B,OAAO,EAAO,KAAK,YAAY,EAAE,MAAM,0BAA0B,CAAC;AAGlE,QAAA,MAAM,cAAc;;;8EAwBnB,CAAC;AAEF,MAAM,WAAW,WACf,SAAQ,KAAK,CAAC,oBAAoB,CAAC,iBAAiB,CAAC,EACnD,YAAY,CAAC,OAAO,cAAc,CAAC;IACrC,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB;AAED,QAAA,MAAM,MAAM,uFAOX,CAAC;AAGF,OAAO,EAAE,MAAM,EAAE,cAAc,EAAE,CAAC"}
1
+ {"version":3,"file":"button.d.ts","sourceRoot":"","sources":["../../../src/components/base/button.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAE/B,OAAO,EAAO,KAAK,YAAY,EAAE,MAAM,0BAA0B,CAAC;AAGlE,QAAA,MAAM,cAAc;;;8EAwBnB,CAAC;AAEF,MAAM,WAAW,WACf,SAAQ,KAAK,CAAC,oBAAoB,CAAC,iBAAiB,CAAC,EACnD,YAAY,CAAC,OAAO,cAAc,CAAC;IACrC,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB;AAED,QAAA,MAAM,MAAM,uFAYX,CAAC;AAGF,OAAO,EAAE,MAAM,EAAE,cAAc,EAAE,CAAC"}
@@ -25,9 +25,9 @@ const buttonVariants = cva("inline-flex items-center justify-center gap-2 whites
25
25
  size: "default",
26
26
  },
27
27
  });
28
- const Button = React.forwardRef(({ className, variant, size, asChild = false, ...props }, ref) => {
28
+ const Button = React.forwardRef(({ className, variant, size, asChild = false, disabled, ...props }, ref) => {
29
29
  const Comp = (asChild ? Slot : "button");
30
- return (_jsx(Comp, { className: cn(buttonVariants({ variant, size, className })), ref: ref, ...props }));
30
+ return (_jsx(Comp, { className: cn(buttonVariants({ variant, size, className })), ref: ref, disabled: disabled === true, ...props }));
31
31
  });
32
32
  Button.displayName = "Button";
33
33
  export { Button, buttonVariants };
@@ -0,0 +1,14 @@
1
+ import * as React from "react";
2
+ export interface ModalProps {
3
+ open: boolean;
4
+ onClose: () => void;
5
+ title?: React.ReactNode;
6
+ description?: React.ReactNode;
7
+ icon?: React.ReactNode;
8
+ children: React.ReactNode;
9
+ className?: string;
10
+ /** Max width class, e.g. "max-w-md" (default) or "max-w-2xl" */
11
+ maxWidth?: string;
12
+ }
13
+ export declare function Modal({ open, onClose, title, description, icon, children, className, maxWidth, }: ModalProps): import("react/jsx-runtime").JSX.Element;
14
+ //# sourceMappingURL=modal.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"modal.d.ts","sourceRoot":"","sources":["../../../src/components/base/modal.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAK/B,MAAM,WAAW,UAAU;IACzB,IAAI,EAAE,OAAO,CAAC;IACd,OAAO,EAAE,MAAM,IAAI,CAAC;IACpB,KAAK,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IACxB,WAAW,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IAC9B,IAAI,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IACvB,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC;IAC1B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,gEAAgE;IAChE,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,wBAAgB,KAAK,CAAC,EACpB,IAAI,EACJ,OAAO,EACP,KAAK,EACL,WAAW,EACX,IAAI,EACJ,QAAQ,EACR,SAAS,EACT,QAAqB,GACtB,EAAE,UAAU,2CAqDZ"}
@@ -0,0 +1,8 @@
1
+ "use client";
2
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
+ import * as DialogPrimitive from "@radix-ui/react-dialog";
4
+ import { X } from "lucide-react";
5
+ import { cn } from "../../utils/cn";
6
+ export function Modal({ open, onClose, title, description, icon, children, className, maxWidth = "max-w-md", }) {
7
+ return (_jsx(DialogPrimitive.Root, { open: open, onOpenChange: (o) => !o && onClose(), children: _jsxs(DialogPrimitive.Portal, { children: [_jsx(DialogPrimitive.Overlay, { className: "fixed inset-0 z-50 bg-black/60 backdrop-blur-sm data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0" }), _jsxs(DialogPrimitive.Content, { className: cn("fixed left-1/2 top-1/2 z-50 w-full -translate-x-1/2 -translate-y-1/2", "bg-background border border-border rounded-2xl shadow-2xl overflow-hidden", "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%]", maxWidth, className), children: [(title || description || icon) && (_jsxs("div", { className: "flex items-center justify-between px-6 py-5 border-b border-border bg-secondary/20", children: [_jsxs("div", { className: "flex items-center gap-3", children: [icon && (_jsx("div", { className: "w-10 h-10 rounded-xl bg-primary/15 border border-primary/30 flex items-center justify-center shrink-0", children: icon })), _jsxs("div", { children: [title && (_jsx(DialogPrimitive.Title, { className: "font-bold text-base leading-none", children: title })), description && (_jsx(DialogPrimitive.Description, { className: "text-xs text-muted-foreground mt-0.5", children: description }))] })] }), _jsxs(DialogPrimitive.Close, { onClick: onClose, className: "w-8 h-8 rounded-lg hover:bg-secondary flex items-center justify-center transition-colors", children: [_jsx(X, { size: 15 }), _jsx("span", { className: "sr-only", children: "Close" })] })] })), _jsx("div", { className: "p-6", children: children })] })] }) }));
8
+ }
@@ -0,0 +1,18 @@
1
+ import { ColumnDef } from '@tanstack/react-table';
2
+ interface DataTableProps<TData, TValue> {
3
+ columns: ColumnDef<TData, TValue>[];
4
+ data: TData[];
5
+ /** Optional title rendered above the table */
6
+ title?: string;
7
+ /** Optional description rendered below the title */
8
+ description?: string;
9
+ /** Page size options. Defaults to [10, 25, 50] */
10
+ pageSizeOptions?: number[];
11
+ /** Default page size. Defaults to 10 */
12
+ defaultPageSize?: number;
13
+ /** Extra className on the wrapper */
14
+ className?: string;
15
+ }
16
+ export declare function DataTable<TData, TValue>({ columns, data, title, description, pageSizeOptions, defaultPageSize, className, }: DataTableProps<TData, TValue>): import("react/jsx-runtime").JSX.Element;
17
+ export {};
18
+ //# sourceMappingURL=DataTable.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"DataTable.d.ts","sourceRoot":"","sources":["../../../src/components/data/DataTable.tsx"],"names":[],"mappings":"AAEA,OAAO,EAQL,SAAS,EAGV,MAAM,uBAAuB,CAAC;AAK/B,UAAU,cAAc,CAAC,KAAK,EAAE,MAAM;IACpC,OAAO,EAAE,SAAS,CAAC,KAAK,EAAE,MAAM,CAAC,EAAE,CAAC;IACpC,IAAI,EAAE,KAAK,EAAE,CAAC;IACd,8CAA8C;IAC9C,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,oDAAoD;IACpD,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,kDAAkD;IAClD,eAAe,CAAC,EAAE,MAAM,EAAE,CAAC;IAC3B,wCAAwC;IACxC,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,qCAAqC;IACrC,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,wBAAgB,SAAS,CAAC,KAAK,EAAE,MAAM,EAAE,EACvC,OAAO,EACP,IAAI,EACJ,KAAK,EACL,WAAW,EACX,eAA8B,EAC9B,eAAoB,EACpB,SAAS,GACV,EAAE,cAAc,CAAC,KAAK,EAAE,MAAM,CAAC,2CAoK/B"}
@@ -0,0 +1,36 @@
1
+ 'use client';
2
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
+ import { flexRender, getCoreRowModel, getPaginationRowModel, getSortedRowModel, getFilteredRowModel, useReactTable, } from '@tanstack/react-table';
4
+ import { useState } from 'react';
5
+ import { ChevronLeft, ChevronRight, ChevronsLeft, ChevronsRight, ArrowUpDown, ArrowUp, ArrowDown } from 'lucide-react';
6
+ import { cn } from '../../utils/cn';
7
+ export function DataTable({ columns, data, title, description, pageSizeOptions = [10, 25, 50], defaultPageSize = 10, className, }) {
8
+ const [sorting, setSorting] = useState([]);
9
+ const [columnVisibility, setColumnVisibility] = useState({});
10
+ const [rowSelection, setRowSelection] = useState({});
11
+ const [pagination, setPagination] = useState({ pageIndex: 0, pageSize: defaultPageSize });
12
+ const table = useReactTable({
13
+ data,
14
+ columns,
15
+ getCoreRowModel: getCoreRowModel(),
16
+ getPaginationRowModel: getPaginationRowModel(),
17
+ getSortedRowModel: getSortedRowModel(),
18
+ getFilteredRowModel: getFilteredRowModel(),
19
+ onSortingChange: setSorting,
20
+ onColumnVisibilityChange: setColumnVisibility,
21
+ onRowSelectionChange: setRowSelection,
22
+ onPaginationChange: setPagination,
23
+ state: { sorting, columnVisibility, rowSelection, pagination },
24
+ });
25
+ const totalRows = table.getFilteredRowModel().rows.length;
26
+ const { pageIndex, pageSize } = table.getState().pagination;
27
+ const from = totalRows === 0 ? 0 : pageIndex * pageSize + 1;
28
+ const to = Math.min((pageIndex + 1) * pageSize, totalRows);
29
+ return (_jsxs("div", { className: cn('rounded-xl border border-border bg-card overflow-hidden', className), children: [(title || description) && (_jsxs("div", { className: "px-6 py-4 border-b border-border", children: [title && _jsx("h2", { className: "text-lg font-semibold text-foreground", children: title }), description && _jsx("p", { className: "text-sm text-muted-foreground mt-0.5", children: description })] })), _jsx("div", { className: "overflow-x-auto", children: _jsxs("table", { className: "w-full text-sm", children: [_jsx("thead", { children: table.getHeaderGroups().map((headerGroup) => (_jsx("tr", { className: "border-b border-border bg-muted/40", children: headerGroup.headers.map((header) => {
30
+ const canSort = header.column.getCanSort();
31
+ const sorted = header.column.getIsSorted();
32
+ return (_jsx("th", { className: cn('px-4 py-3 text-left text-xs font-semibold text-muted-foreground uppercase tracking-wider select-none whitespace-nowrap', canSort && 'cursor-pointer hover:text-foreground transition-colors'), onClick: canSort ? header.column.getToggleSortingHandler() : undefined, children: _jsxs("div", { className: "flex items-center gap-1.5", children: [header.isPlaceholder ? null : flexRender(header.column.columnDef.header, header.getContext()), canSort && (_jsx("span", { className: "ml-0.5 text-muted-foreground/60", children: sorted === 'asc' ? (_jsx(ArrowUp, { className: "w-3 h-3 text-primary" })) : sorted === 'desc' ? (_jsx(ArrowDown, { className: "w-3 h-3 text-primary" })) : (_jsx(ArrowUpDown, { className: "w-3 h-3" })) }))] }) }, header.id));
33
+ }) }, headerGroup.id))) }), _jsx("tbody", { children: table.getRowModel().rows.length === 0 ? (_jsx("tr", { children: _jsx("td", { colSpan: columns.length, className: "px-6 py-12 text-center text-muted-foreground/50 text-sm", children: "No data to display" }) })) : (table.getRowModel().rows.map((row) => (_jsx("tr", { className: cn('border-b border-border/50 transition-colors hover:bg-muted/30 last:border-0', row.getIsSelected() && 'bg-primary/5'), children: row.getVisibleCells().map((cell) => (_jsx("td", { className: "px-4 py-3 text-foreground align-middle", children: flexRender(cell.column.columnDef.cell, cell.getContext()) }, cell.id))) }, row.id)))) })] }) }), _jsxs("div", { className: "flex flex-col gap-3 sm:flex-row sm:items-center sm:justify-between px-4 py-3 border-t border-border bg-muted/20", children: [_jsx("p", { className: "text-xs text-muted-foreground text-center sm:text-left", children: totalRows === 0
34
+ ? 'No results'
35
+ : `Showing ${from}–${to} of ${totalRows} row${totalRows !== 1 ? 's' : ''}` }), _jsxs("div", { className: "flex items-center gap-3 justify-center", children: [_jsxs("div", { className: "flex items-center gap-2", children: [_jsx("span", { className: "text-xs text-muted-foreground whitespace-nowrap", children: "Rows" }), _jsx("select", { value: pageSize, onChange: (e) => table.setPageSize(Number(e.target.value)), className: "h-7 rounded-md border border-input bg-background px-2 text-xs focus:outline-none focus:ring-1 focus:ring-ring", children: pageSizeOptions.map((s) => (_jsx("option", { value: s, children: s }, s))) })] }), _jsxs("div", { className: "flex items-center gap-1", children: [_jsx("button", { onClick: () => table.setPageIndex(0), disabled: !table.getCanPreviousPage(), className: "p-1 rounded hover:bg-muted transition-colors disabled:opacity-30 disabled:cursor-not-allowed", title: "First page", children: _jsx(ChevronsLeft, { className: "w-4 h-4" }) }), _jsx("button", { onClick: () => table.previousPage(), disabled: !table.getCanPreviousPage(), className: "p-1 rounded hover:bg-muted transition-colors disabled:opacity-30 disabled:cursor-not-allowed", title: "Previous page", children: _jsx(ChevronLeft, { className: "w-4 h-4" }) }), _jsxs("span", { className: "text-xs text-muted-foreground px-2 whitespace-nowrap", children: [pageIndex + 1, " / ", table.getPageCount() || 1] }), _jsx("button", { onClick: () => table.nextPage(), disabled: !table.getCanNextPage(), className: "p-1 rounded hover:bg-muted transition-colors disabled:opacity-30 disabled:cursor-not-allowed", title: "Next page", children: _jsx(ChevronRight, { className: "w-4 h-4" }) }), _jsx("button", { onClick: () => table.setPageIndex(table.getPageCount() - 1), disabled: !table.getCanNextPage(), className: "p-1 rounded hover:bg-muted transition-colors disabled:opacity-30 disabled:cursor-not-allowed", title: "Last page", children: _jsx(ChevronsRight, { className: "w-4 h-4" }) })] })] })] })] }));
36
+ }
@@ -0,0 +1,23 @@
1
+ import React from 'react';
2
+ interface EmptyStateProps {
3
+ /** Lucide icon element or any ReactNode to show above the title */
4
+ icon?: React.ReactNode;
5
+ /** Image src as alternative to icon */
6
+ imageSrc?: string;
7
+ /** Main heading */
8
+ title: string;
9
+ /** Supporting text */
10
+ description: string;
11
+ /** Label for the primary CTA button */
12
+ actionLabel?: string;
13
+ /** If provided, CTA renders as a Next.js Link */
14
+ actionHref?: string;
15
+ /** If provided, CTA calls this function (takes precedence over actionHref) */
16
+ onAction?: () => void;
17
+ /** Extra content rendered below the CTA */
18
+ footer?: React.ReactNode;
19
+ className?: string;
20
+ }
21
+ export declare function EmptyState({ icon, imageSrc, title, description, actionLabel, actionHref, onAction, footer, className, }: EmptyStateProps): import("react/jsx-runtime").JSX.Element;
22
+ export {};
23
+ //# sourceMappingURL=EmptyState.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"EmptyState.d.ts","sourceRoot":"","sources":["../../../src/components/data/EmptyState.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,MAAM,OAAO,CAAC;AAK1B,UAAU,eAAe;IACvB,mEAAmE;IACnE,IAAI,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IACvB,uCAAuC;IACvC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,mBAAmB;IACnB,KAAK,EAAE,MAAM,CAAC;IACd,sBAAsB;IACtB,WAAW,EAAE,MAAM,CAAC;IACpB,uCAAuC;IACvC,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,iDAAiD;IACjD,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,8EAA8E;IAC9E,QAAQ,CAAC,EAAE,MAAM,IAAI,CAAC;IACtB,2CAA2C;IAC3C,MAAM,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IACzB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,wBAAgB,UAAU,CAAC,EACzB,IAAI,EACJ,QAAQ,EACR,KAAK,EACL,WAAW,EACX,WAA2B,EAC3B,UAAU,EACV,QAAQ,EACR,MAAM,EACN,SAAS,GACV,EAAE,eAAe,2CAgDjB"}
@@ -0,0 +1,9 @@
1
+ 'use client';
2
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
+ import Link from 'next/link';
4
+ import { Plus, FolderOpen } from 'lucide-react';
5
+ import { cn } from '../../utils/cn';
6
+ export function EmptyState({ icon, imageSrc, title, description, actionLabel = 'Get Started', actionHref, onAction, footer, className, }) {
7
+ const hasAction = onAction || actionHref;
8
+ return (_jsxs("div", { className: cn('relative flex flex-col items-center justify-center py-16 px-4 text-center overflow-hidden', className), children: [_jsxs("div", { "aria-hidden": true, className: "pointer-events-none absolute inset-0 -z-10", children: [_jsx("div", { className: "absolute top-1/4 left-1/4 w-48 h-48 bg-primary/5 rounded-full blur-3xl" }), _jsx("div", { className: "absolute bottom-1/4 right-1/4 w-48 h-48 bg-primary/5 rounded-full blur-3xl" })] }), imageSrc ? (_jsx("img", { src: imageSrc, alt: title, className: "w-28 h-28 mb-6 opacity-60 object-contain" })) : (_jsx("div", { className: "mb-6 p-5 rounded-2xl bg-muted/70 text-muted-foreground", children: icon ?? _jsx(FolderOpen, { className: "w-10 h-10" }) })), _jsx("h3", { className: "text-xl font-bold text-foreground mb-2", children: title }), _jsx("p", { className: "text-muted-foreground max-w-sm text-sm leading-relaxed mb-7", children: description }), hasAction && (onAction ? (_jsxs("button", { onClick: onAction, className: "inline-flex items-center gap-2 h-10 px-5 rounded-lg bg-primary text-primary-foreground text-sm font-semibold hover:opacity-90 transition-opacity shadow-sm", children: [_jsx(Plus, { className: "w-4 h-4" }), actionLabel] })) : actionHref ? (_jsxs(Link, { href: actionHref, className: "inline-flex items-center gap-2 h-10 px-5 rounded-lg bg-primary text-primary-foreground text-sm font-semibold hover:opacity-90 transition-opacity shadow-sm", children: [_jsx(Plus, { className: "w-4 h-4" }), actionLabel] })) : null), footer && _jsx("div", { className: "mt-4", children: footer })] }));
9
+ }
@@ -0,0 +1,17 @@
1
+ interface TableToolbarProps {
2
+ searchValue: string;
3
+ onSearchChange: (value: string) => void;
4
+ onExport?: () => void;
5
+ onImport?: () => void;
6
+ selectedCount?: number;
7
+ onBulkDelete?: () => void;
8
+ onBulkArchive?: () => void;
9
+ onColumnSettings?: () => void;
10
+ placeholder?: string;
11
+ className?: string;
12
+ /** Extra action buttons rendered to the right of search */
13
+ children?: React.ReactNode;
14
+ }
15
+ export declare function TableToolbar({ searchValue, onSearchChange, onExport, onImport, selectedCount, onBulkDelete, onBulkArchive, onColumnSettings, placeholder, className, children, }: TableToolbarProps): import("react/jsx-runtime").JSX.Element;
16
+ export {};
17
+ //# sourceMappingURL=TableToolbar.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"TableToolbar.d.ts","sourceRoot":"","sources":["../../../src/components/data/TableToolbar.tsx"],"names":[],"mappings":"AAUA,UAAU,iBAAiB;IACzB,WAAW,EAAE,MAAM,CAAC;IACpB,cAAc,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IACxC,QAAQ,CAAC,EAAE,MAAM,IAAI,CAAC;IACtB,QAAQ,CAAC,EAAE,MAAM,IAAI,CAAC;IACtB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,YAAY,CAAC,EAAE,MAAM,IAAI,CAAC;IAC1B,aAAa,CAAC,EAAE,MAAM,IAAI,CAAC;IAC3B,gBAAgB,CAAC,EAAE,MAAM,IAAI,CAAC;IAC9B,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,2DAA2D;IAC3D,QAAQ,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;CAC5B;AAED,wBAAgB,YAAY,CAAC,EAC3B,WAAW,EACX,cAAc,EACd,QAAQ,EACR,QAAQ,EACR,aAAiB,EACjB,YAAY,EACZ,aAAa,EACb,gBAAgB,EAChB,WAAyB,EACzB,SAAS,EACT,QAAQ,GACT,EAAE,iBAAiB,2CAyGnB"}
@@ -0,0 +1,21 @@
1
+ 'use client';
2
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
+ import { Input } from '../base/input';
4
+ import { Search, Download, Upload, Settings2, MoreHorizontal, Trash2, Archive, X, } from 'lucide-react';
5
+ import { useState, useRef, useEffect } from 'react';
6
+ import { cn } from '../../utils/cn';
7
+ export function TableToolbar({ searchValue, onSearchChange, onExport, onImport, selectedCount = 0, onBulkDelete, onBulkArchive, onColumnSettings, placeholder = 'Search...', className, children, }) {
8
+ const [showBulkMenu, setShowBulkMenu] = useState(false);
9
+ const bulkRef = useRef(null);
10
+ // Close bulk menu on outside click
11
+ useEffect(() => {
12
+ const handler = (e) => {
13
+ if (bulkRef.current && !bulkRef.current.contains(e.target)) {
14
+ setShowBulkMenu(false);
15
+ }
16
+ };
17
+ document.addEventListener('mousedown', handler);
18
+ return () => document.removeEventListener('mousedown', handler);
19
+ }, []);
20
+ return (_jsxs("div", { className: cn('flex flex-col gap-3 md:flex-row md:items-center', className), children: [_jsxs("div", { className: "flex-1 relative min-w-0", children: [_jsx(Search, { className: "absolute left-3 top-1/2 -translate-y-1/2 w-4 h-4 text-muted-foreground pointer-events-none" }), _jsx(Input, { type: "text", placeholder: placeholder, value: searchValue, onChange: (e) => onSearchChange(e.target.value), className: "pl-9 pr-8" }), searchValue && (_jsx("button", { onClick: () => onSearchChange(''), className: "absolute right-2.5 top-1/2 -translate-y-1/2 text-muted-foreground hover:text-foreground transition-colors", children: _jsx(X, { className: "w-3.5 h-3.5" }) }))] }), _jsxs("div", { className: "flex items-center gap-2 flex-wrap shrink-0", children: [children, onImport && (_jsxs("button", { onClick: onImport, className: "inline-flex items-center gap-1.5 h-9 px-3 rounded-md border border-input bg-background text-xs font-medium text-foreground hover:bg-muted transition-colors", children: [_jsx(Upload, { className: "w-3.5 h-3.5" }), " Import"] })), onExport && (_jsxs("button", { onClick: onExport, className: "inline-flex items-center gap-1.5 h-9 px-3 rounded-md border border-input bg-background text-xs font-medium text-foreground hover:bg-muted transition-colors", children: [_jsx(Download, { className: "w-3.5 h-3.5" }), " Export"] })), onColumnSettings && (_jsx("button", { onClick: onColumnSettings, className: "inline-flex items-center justify-center h-9 w-9 rounded-md border border-input bg-background text-muted-foreground hover:bg-muted transition-colors", title: "Column settings", children: _jsx(Settings2, { className: "w-4 h-4" }) })), selectedCount > 0 && (_jsxs("div", { className: "relative", ref: bulkRef, children: [_jsxs("button", { onClick: () => setShowBulkMenu(!showBulkMenu), className: "inline-flex items-center gap-1.5 h-9 px-3 rounded-md border border-primary/40 bg-primary/5 text-xs font-semibold text-primary hover:bg-primary/10 transition-colors", children: [_jsx(MoreHorizontal, { className: "w-4 h-4" }), selectedCount, " selected"] }), showBulkMenu && (_jsxs("div", { className: "absolute right-0 mt-1 w-44 bg-popover border border-border rounded-lg shadow-lg overflow-hidden z-20 animate-in fade-in-0 zoom-in-95", children: [onBulkArchive && (_jsxs("button", { onClick: () => { onBulkArchive(); setShowBulkMenu(false); }, className: "w-full text-left px-4 py-2.5 text-sm text-muted-foreground hover:bg-muted hover:text-foreground transition-colors flex items-center gap-2", children: [_jsx(Archive, { className: "w-3.5 h-3.5" }), " Archive"] })), onBulkDelete && (_jsxs("button", { onClick: () => { onBulkDelete(); setShowBulkMenu(false); }, className: "w-full text-left px-4 py-2.5 text-sm text-destructive hover:bg-destructive/10 transition-colors flex items-center gap-2 border-t border-border", children: [_jsx(Trash2, { className: "w-3.5 h-3.5" }), " Delete"] }))] }))] }))] })] }));
21
+ }
@@ -0,0 +1,14 @@
1
+ interface CopyButtonProps {
2
+ /** The text to copy to clipboard */
3
+ value: string;
4
+ /** Milliseconds to show the "Copied!" state. Defaults to 2000 */
5
+ resetMs?: number;
6
+ className?: string;
7
+ /** Render variant. 'icon' shows only the icon. 'button' shows icon + label. */
8
+ variant?: 'icon' | 'button';
9
+ label?: string;
10
+ copiedLabel?: string;
11
+ }
12
+ export declare function CopyButton({ value, resetMs, className, variant, label, copiedLabel, }: CopyButtonProps): import("react/jsx-runtime").JSX.Element;
13
+ export {};
14
+ //# sourceMappingURL=CopyButton.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"CopyButton.d.ts","sourceRoot":"","sources":["../../../src/components/display/CopyButton.tsx"],"names":[],"mappings":"AAMA,UAAU,eAAe;IACvB,oCAAoC;IACpC,KAAK,EAAE,MAAM,CAAC;IACd,iEAAiE;IACjE,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,+EAA+E;IAC/E,OAAO,CAAC,EAAE,MAAM,GAAG,QAAQ,CAAC;IAC5B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,wBAAgB,UAAU,CAAC,EACzB,KAAK,EACL,OAAc,EACd,SAAS,EACT,OAAgB,EAChB,KAAc,EACd,WAAuB,GACxB,EAAE,eAAe,2CA8DjB"}
@@ -0,0 +1,37 @@
1
+ 'use client';
2
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
+ import { useState, useCallback } from 'react';
4
+ import { Copy, Check } from 'lucide-react';
5
+ import { cn } from '../../utils/cn';
6
+ export function CopyButton({ value, resetMs = 2000, className, variant = 'icon', label = 'Copy', copiedLabel = 'Copied!', }) {
7
+ const [copied, setCopied] = useState(false);
8
+ const handleCopy = useCallback(async () => {
9
+ try {
10
+ await navigator.clipboard.writeText(value);
11
+ setCopied(true);
12
+ setTimeout(() => setCopied(false), resetMs);
13
+ }
14
+ catch {
15
+ // Fallback for browsers without clipboard API
16
+ const ta = document.createElement('textarea');
17
+ ta.value = value;
18
+ ta.style.position = 'fixed';
19
+ ta.style.opacity = '0';
20
+ document.body.appendChild(ta);
21
+ ta.focus();
22
+ ta.select();
23
+ document.execCommand('copy');
24
+ document.body.removeChild(ta);
25
+ setCopied(true);
26
+ setTimeout(() => setCopied(false), resetMs);
27
+ }
28
+ }, [value, resetMs]);
29
+ if (variant === 'button') {
30
+ return (_jsxs("button", { onClick: handleCopy, className: cn('inline-flex items-center gap-1.5 h-8 px-3 rounded-md border border-input bg-background text-xs font-medium transition-colors', copied
31
+ ? 'border-emerald-500/40 bg-emerald-50 text-emerald-700'
32
+ : 'text-muted-foreground hover:text-foreground hover:bg-muted', className), title: copied ? copiedLabel : label, children: [copied ? (_jsx(Check, { className: "w-3.5 h-3.5" })) : (_jsx(Copy, { className: "w-3.5 h-3.5" })), copied ? copiedLabel : label] }));
33
+ }
34
+ return (_jsx("button", { onClick: handleCopy, className: cn('inline-flex items-center justify-center w-7 h-7 rounded-md transition-colors', copied
35
+ ? 'text-emerald-600'
36
+ : 'text-muted-foreground hover:text-foreground hover:bg-muted', className), title: copied ? copiedLabel : label, children: copied ? _jsx(Check, { className: "w-3.5 h-3.5" }) : _jsx(Copy, { className: "w-3.5 h-3.5" }) }));
37
+ }
@@ -0,0 +1,11 @@
1
+ import * as React from 'react';
2
+ interface PageHeaderProps {
3
+ title: string;
4
+ description?: string;
5
+ /** Right-side action buttons/badges */
6
+ children?: React.ReactNode;
7
+ className?: string;
8
+ }
9
+ export declare function PageHeader({ title, description, children, className }: PageHeaderProps): import("react/jsx-runtime").JSX.Element;
10
+ export {};
11
+ //# sourceMappingURL=PageHeader.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"PageHeader.d.ts","sourceRoot":"","sources":["../../../src/components/display/PageHeader.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAG/B,UAAU,eAAe;IACvB,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,uCAAuC;IACvC,QAAQ,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IAC3B,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,wBAAgB,UAAU,CAAC,EAAE,KAAK,EAAE,WAAW,EAAE,QAAQ,EAAE,SAAS,EAAE,EAAE,eAAe,2CActF"}
@@ -0,0 +1,5 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { cn } from '../../utils/cn';
3
+ export function PageHeader({ title, description, children, className }) {
4
+ return (_jsxs("div", { className: cn('flex flex-col gap-3 sm:flex-row sm:items-center sm:justify-between', className), children: [_jsxs("div", { className: "min-w-0", children: [_jsx("h1", { className: "text-2xl sm:text-3xl font-bold tracking-tight text-foreground truncate", children: title }), description && (_jsx("p", { className: "mt-1 text-sm text-muted-foreground", children: description }))] }), children && (_jsx("div", { className: "flex items-center gap-2 flex-wrap shrink-0", children: children }))] }));
5
+ }
@@ -0,0 +1,23 @@
1
+ import * as React from 'react';
2
+ interface TrendProps {
3
+ value: number;
4
+ label?: string;
5
+ }
6
+ interface StatCardProps {
7
+ /** Lucide icon or any icon node */
8
+ icon?: React.ReactNode;
9
+ /** Primary numeric value to display */
10
+ value: string | number;
11
+ /** Metric label */
12
+ label: string;
13
+ /** Optional trend indicator */
14
+ trend?: TrendProps;
15
+ /** Optional sub-label below value */
16
+ subLabel?: string;
17
+ /** Icon background color class (Tailwind). Defaults to bg-primary/10 */
18
+ iconColor?: string;
19
+ className?: string;
20
+ }
21
+ export declare function StatCard({ icon, value, label, trend, subLabel, iconColor, className, }: StatCardProps): import("react/jsx-runtime").JSX.Element;
22
+ export {};
23
+ //# sourceMappingURL=StatCard.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"StatCard.d.ts","sourceRoot":"","sources":["../../../src/components/display/StatCard.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAG/B,UAAU,UAAU;IAClB,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,UAAU,aAAa;IACrB,mCAAmC;IACnC,IAAI,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IACvB,uCAAuC;IACvC,KAAK,EAAE,MAAM,GAAG,MAAM,CAAC;IACvB,mBAAmB;IACnB,KAAK,EAAE,MAAM,CAAC;IACd,+BAA+B;IAC/B,KAAK,CAAC,EAAE,UAAU,CAAC;IACnB,qCAAqC;IACrC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,wEAAwE;IACxE,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,wBAAgB,QAAQ,CAAC,EACvB,IAAI,EACJ,KAAK,EACL,KAAK,EACL,KAAK,EACL,QAAQ,EACR,SAAwC,EACxC,SAAS,GACV,EAAE,aAAa,2CA2Cf"}
@@ -0,0 +1,6 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { cn } from '../../utils/cn';
3
+ export function StatCard({ icon, value, label, trend, subLabel, iconColor = 'bg-primary/10 text-primary', className, }) {
4
+ const trendUp = trend && trend.value >= 0;
5
+ return (_jsxs("div", { className: cn('group relative rounded-2xl border border-border bg-card p-5 overflow-hidden transition-shadow hover:shadow-md', className), children: [_jsx("div", { "aria-hidden": true, className: "pointer-events-none absolute inset-0 rounded-2xl opacity-0 group-hover:opacity-100 transition-opacity bg-gradient-to-br from-primary/5 to-transparent" }), _jsxs("div", { className: "flex items-start justify-between gap-3 relative", children: [_jsxs("div", { className: "flex-1 min-w-0", children: [_jsx("p", { className: "text-xs font-semibold text-muted-foreground uppercase tracking-wider mb-2", children: label }), _jsx("p", { className: "text-2xl sm:text-3xl font-bold text-foreground tabular-nums", children: value }), subLabel && _jsx("p", { className: "text-xs text-muted-foreground mt-1", children: subLabel }), trend && (_jsxs("div", { className: "flex items-center gap-1 mt-2", children: [_jsxs("span", { className: cn('text-xs font-semibold', trendUp ? 'text-emerald-600' : 'text-red-500'), children: [trendUp ? '+' : '', trend.value.toFixed(1), "%"] }), trend.label && (_jsx("span", { className: "text-xs text-muted-foreground", children: trend.label }))] }))] }), icon && (_jsx("div", { className: cn('w-11 h-11 rounded-xl flex items-center justify-center shrink-0', iconColor), children: icon }))] })] }));
6
+ }
@@ -0,0 +1,18 @@
1
+ interface ConfirmDialogProps {
2
+ open: boolean;
3
+ title: string;
4
+ description: string;
5
+ confirmLabel?: string;
6
+ cancelLabel?: string;
7
+ /** When true, the confirm button renders in destructive red */
8
+ isDangerous?: boolean;
9
+ /** Called when user confirms */
10
+ onConfirm: () => void;
11
+ /** Called when user cancels or closes */
12
+ onCancel: () => void;
13
+ /** Show a loading spinner on the confirm button */
14
+ isLoading?: boolean;
15
+ }
16
+ export declare function ConfirmDialog({ open, title, description, confirmLabel, cancelLabel, isDangerous, onConfirm, onCancel, isLoading, }: ConfirmDialogProps): import("react/jsx-runtime").JSX.Element;
17
+ export {};
18
+ //# sourceMappingURL=ConfirmDialog.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ConfirmDialog.d.ts","sourceRoot":"","sources":["../../../src/components/feedback/ConfirmDialog.tsx"],"names":[],"mappings":"AAOA,UAAU,kBAAkB;IAC1B,IAAI,EAAE,OAAO,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,+DAA+D;IAC/D,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,gCAAgC;IAChC,SAAS,EAAE,MAAM,IAAI,CAAC;IACtB,yCAAyC;IACzC,QAAQ,EAAE,MAAM,IAAI,CAAC;IACrB,mDAAmD;IACnD,SAAS,CAAC,EAAE,OAAO,CAAC;CACrB;AAED,wBAAgB,aAAa,CAAC,EAC5B,IAAI,EACJ,KAAK,EACL,WAAW,EACX,YAAwB,EACxB,WAAsB,EACtB,WAAmB,EACnB,SAAS,EACT,QAAQ,EACR,SAAiB,GAClB,EAAE,kBAAkB,2CAuDpB"}
@@ -0,0 +1,10 @@
1
+ 'use client';
2
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
+ import * as DialogPrimitive from '@radix-ui/react-dialog';
4
+ import { AlertCircle } from 'lucide-react';
5
+ import { cn } from '../../utils/cn';
6
+ export function ConfirmDialog({ open, title, description, confirmLabel = 'Confirm', cancelLabel = 'Cancel', isDangerous = false, onConfirm, onCancel, isLoading = false, }) {
7
+ return (_jsx(DialogPrimitive.Root, { open: open, onOpenChange: (isOpen) => !isOpen && onCancel(), children: _jsxs(DialogPrimitive.Portal, { children: [_jsx(DialogPrimitive.Overlay, { className: "fixed inset-0 z-50 bg-black/60 backdrop-blur-sm data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0" }), _jsxs(DialogPrimitive.Content, { className: "fixed left-1/2 top-1/2 z-50 w-full max-w-sm -translate-x-1/2 -translate-y-1/2 rounded-2xl border border-border bg-card p-6 shadow-2xl 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", children: [_jsxs("div", { className: "flex items-start gap-3 mb-3", children: [isDangerous && (_jsx("div", { className: "w-10 h-10 rounded-full bg-destructive/10 flex items-center justify-center shrink-0 mt-0.5", children: _jsx(AlertCircle, { className: "w-5 h-5 text-destructive" }) })), _jsxs("div", { className: "flex-1", children: [_jsx(DialogPrimitive.Title, { className: "text-base font-semibold text-foreground leading-tight", children: title }), _jsx(DialogPrimitive.Description, { className: "mt-1.5 text-sm text-muted-foreground leading-relaxed", children: description })] })] }), _jsxs("div", { className: "flex flex-col-reverse gap-2 sm:flex-row sm:justify-end mt-5", children: [_jsx("button", { onClick: onCancel, disabled: isLoading, className: "inline-flex items-center justify-center h-9 px-4 rounded-lg border border-input bg-background text-sm font-medium text-foreground hover:bg-muted transition-colors disabled:opacity-50", children: cancelLabel }), _jsxs("button", { onClick: onConfirm, disabled: isLoading, className: cn('inline-flex items-center justify-center gap-2 h-9 px-4 rounded-lg text-sm font-semibold text-white transition-colors disabled:opacity-50', isDangerous
8
+ ? 'bg-destructive hover:bg-destructive/90'
9
+ : 'bg-primary hover:bg-primary/90'), children: [isLoading && (_jsxs("svg", { className: "w-4 h-4 animate-spin", viewBox: "0 0 24 24", fill: "none", children: [_jsx("circle", { className: "opacity-25", cx: "12", cy: "12", r: "10", stroke: "currentColor", strokeWidth: "4" }), _jsx("path", { className: "opacity-75", fill: "currentColor", d: "M4 12a8 8 0 018-8v8H4z" })] })), confirmLabel] })] })] })] }) }));
10
+ }
@@ -0,0 +1,10 @@
1
+ interface ErrorStateProps {
2
+ /** The error message to display */
3
+ error: string;
4
+ /** Optional retry callback */
5
+ onRetry?: () => void;
6
+ className?: string;
7
+ }
8
+ export declare function ErrorState({ error, onRetry, className }: ErrorStateProps): import("react/jsx-runtime").JSX.Element;
9
+ export {};
10
+ //# sourceMappingURL=ErrorState.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ErrorState.d.ts","sourceRoot":"","sources":["../../../src/components/feedback/ErrorState.tsx"],"names":[],"mappings":"AAKA,UAAU,eAAe;IACvB,mCAAmC;IACnC,KAAK,EAAE,MAAM,CAAC;IACd,8BAA8B;IAC9B,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;IACrB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,wBAAgB,UAAU,CAAC,EAAE,KAAK,EAAE,OAAO,EAAE,SAAS,EAAE,EAAE,eAAe,2CAoBxE"}
@@ -0,0 +1,7 @@
1
+ 'use client';
2
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
+ import { AlertTriangle, RefreshCw } from 'lucide-react';
4
+ import { cn } from '../../utils/cn';
5
+ export function ErrorState({ error, onRetry, className }) {
6
+ return (_jsxs("div", { className: cn('flex flex-col items-center justify-center py-16 gap-4 text-center', className), children: [_jsx("div", { className: "w-14 h-14 rounded-full bg-destructive/10 flex items-center justify-center", children: _jsx(AlertTriangle, { className: "w-6 h-6 text-destructive" }) }), _jsxs("div", { children: [_jsx("p", { className: "font-semibold text-foreground", children: "Something went wrong" }), _jsx("p", { className: "text-sm text-muted-foreground mt-1 max-w-sm", children: error })] }), onRetry && (_jsxs("button", { onClick: onRetry, className: "inline-flex items-center gap-2 h-8 px-4 rounded-md border border-input bg-background text-xs font-medium text-foreground hover:bg-muted transition-colors", children: [_jsx(RefreshCw, { className: "w-3.5 h-3.5" }), " Try Again"] }))] }));
7
+ }
@@ -0,0 +1,26 @@
1
+ import * as React from 'react';
2
+ interface SkeletonProps {
3
+ className?: string;
4
+ style?: React.CSSProperties;
5
+ }
6
+ /** Generic skeleton block — use className to set size */
7
+ export declare function Skeleton({ className }: SkeletonProps): import("react/jsx-runtime").JSX.Element;
8
+ /** Skeleton shaped like a single line of text */
9
+ export declare function SkeletonText({ className }: SkeletonProps): import("react/jsx-runtime").JSX.Element;
10
+ /** Skeleton shaped like a circular avatar */
11
+ export declare function SkeletonAvatar({ className }: SkeletonProps): import("react/jsx-runtime").JSX.Element;
12
+ /** Skeleton for a StatCard */
13
+ export declare function SkeletonStatCard({ className }: SkeletonProps): import("react/jsx-runtime").JSX.Element;
14
+ /** Skeleton for a table row */
15
+ export declare function SkeletonTableRow({ cols }: {
16
+ cols?: number;
17
+ }): import("react/jsx-runtime").JSX.Element;
18
+ /** Full skeleton table (header + N rows) */
19
+ export declare function SkeletonTable({ rows, cols }: {
20
+ rows?: number;
21
+ cols?: number;
22
+ }): import("react/jsx-runtime").JSX.Element;
23
+ /** Skeleton for a user list item (avatar + two lines) */
24
+ export declare function SkeletonUserRow({ className }: SkeletonProps): import("react/jsx-runtime").JSX.Element;
25
+ export {};
26
+ //# sourceMappingURL=Skeleton.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Skeleton.d.ts","sourceRoot":"","sources":["../../../src/components/feedback/Skeleton.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAK/B,UAAU,aAAa;IACrB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE,KAAK,CAAC,aAAa,CAAC;CAC7B;AAED,yDAAyD;AACzD,wBAAgB,QAAQ,CAAC,EAAE,SAAS,EAAE,EAAE,aAAa,2CAOpD;AAED,iDAAiD;AACjD,wBAAgB,YAAY,CAAC,EAAE,SAAS,EAAE,EAAE,aAAa,2CAExD;AAED,6CAA6C;AAC7C,wBAAgB,cAAc,CAAC,EAAE,SAAS,EAAE,EAAE,aAAa,2CAE1D;AAID,8BAA8B;AAC9B,wBAAgB,gBAAgB,CAAC,EAAE,SAAS,EAAE,EAAE,aAAa,2CAQ5D;AAED,+BAA+B;AAC/B,wBAAgB,gBAAgB,CAAC,EAAE,IAAQ,EAAE,EAAE;IAAE,IAAI,CAAC,EAAE,MAAM,CAAA;CAAE,2CAU/D;AAED,4CAA4C;AAC5C,wBAAgB,aAAa,CAAC,EAAE,IAAQ,EAAE,IAAQ,EAAE,EAAE;IAAE,IAAI,CAAC,EAAE,MAAM,CAAC;IAAC,IAAI,CAAC,EAAE,MAAM,CAAA;CAAE,2CAiBrF;AAED,yDAAyD;AACzD,wBAAgB,eAAe,CAAC,EAAE,SAAS,EAAE,EAAE,aAAa,2CAU3D"}
@@ -0,0 +1,31 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { cn } from '../../utils/cn';
3
+ /** Generic skeleton block — use className to set size */
4
+ export function Skeleton({ className }) {
5
+ return (_jsx("div", { className: cn('animate-pulse rounded-md bg-muted', className), "aria-hidden": true }));
6
+ }
7
+ /** Skeleton shaped like a single line of text */
8
+ export function SkeletonText({ className }) {
9
+ return _jsx(Skeleton, { className: cn('h-4 w-3/4', className) });
10
+ }
11
+ /** Skeleton shaped like a circular avatar */
12
+ export function SkeletonAvatar({ className }) {
13
+ return _jsx(Skeleton, { className: cn('h-9 w-9 rounded-full', className) });
14
+ }
15
+ // ─── Composed skeleton cards ──────────────────────────────────────────────────
16
+ /** Skeleton for a StatCard */
17
+ export function SkeletonStatCard({ className }) {
18
+ return (_jsxs("div", { className: cn('rounded-2xl border border-border bg-card p-5 space-y-3', className), children: [_jsx(Skeleton, { className: "h-3.5 w-20" }), _jsx(Skeleton, { className: "h-8 w-28" }), _jsx(Skeleton, { className: "h-3 w-16" })] }));
19
+ }
20
+ /** Skeleton for a table row */
21
+ export function SkeletonTableRow({ cols = 4 }) {
22
+ return (_jsx("tr", { className: "border-b border-border/50", children: Array.from({ length: cols }).map((_, i) => (_jsx("td", { className: "px-4 py-3", children: _jsx(Skeleton, { className: "h-4", style: { width: `${60 + Math.random() * 30}%` } }) }, i))) }));
23
+ }
24
+ /** Full skeleton table (header + N rows) */
25
+ export function SkeletonTable({ rows = 5, cols = 4 }) {
26
+ return (_jsxs("div", { className: "rounded-xl border border-border overflow-hidden", children: [_jsx("div", { className: "px-4 py-3 border-b border-border bg-muted/40 flex gap-4", children: Array.from({ length: cols }).map((_, i) => (_jsx(Skeleton, { className: "h-3.5 w-20" }, i))) }), _jsx("table", { className: "w-full", children: _jsx("tbody", { children: Array.from({ length: rows }).map((_, i) => (_jsx(SkeletonTableRow, { cols: cols }, i))) }) })] }));
27
+ }
28
+ /** Skeleton for a user list item (avatar + two lines) */
29
+ export function SkeletonUserRow({ className }) {
30
+ return (_jsxs("div", { className: cn('flex items-center gap-3 p-3', className), children: [_jsx(SkeletonAvatar, {}), _jsxs("div", { className: "flex-1 space-y-2", children: [_jsx(Skeleton, { className: "h-3.5 w-32" }), _jsx(Skeleton, { className: "h-3 w-48" })] })] }));
31
+ }
@@ -1,10 +1,17 @@
1
- export type SubscriptionStatus = 'active' | 'past_due' | 'canceled' | 'pending_cancellation';
2
- export interface StatusBadgeProps {
3
- status: SubscriptionStatus | string;
1
+ type StatusType = 'todo' | 'in-progress' | 'in_progress' | 'done' | 'cancelled' | 'approved' | 'pending' | 'rejected' | 'submitted' | 'suspended' | 'active' | 'inactive' | 'past_due' | 'draft' | 'published';
2
+ type PriorityType = 'low' | 'medium' | 'high' | 'urgent';
3
+ type RoleType = 'admin' | 'manager' | 'employee' | 'ceo' | 'intern' | 'superadmin' | 'owner';
4
+ export declare function StatusBadge({ status, className }: {
5
+ status: StatusType;
4
6
  className?: string;
5
- }
6
- /**
7
- * Smart Status Badge for Subscription management.
8
- */
9
- export declare function StatusBadge({ status, className }: StatusBadgeProps): import("react/jsx-runtime").JSX.Element;
7
+ }): import("react/jsx-runtime").JSX.Element;
8
+ export declare function PriorityBadge({ priority, className }: {
9
+ priority: PriorityType;
10
+ className?: string;
11
+ }): import("react/jsx-runtime").JSX.Element;
12
+ export declare function RoleBadge({ role, className }: {
13
+ role: RoleType;
14
+ className?: string;
15
+ }): import("react/jsx-runtime").JSX.Element;
16
+ export type { StatusType, PriorityType, RoleType };
10
17
  //# sourceMappingURL=status-badge.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"status-badge.d.ts","sourceRoot":"","sources":["../../../src/components/saas/status-badge.tsx"],"names":[],"mappings":"AAIA,MAAM,MAAM,kBAAkB,GAAG,QAAQ,GAAG,UAAU,GAAG,UAAU,GAAG,sBAAsB,CAAC;AAE7F,MAAM,WAAW,gBAAgB;IAC/B,MAAM,EAAE,kBAAkB,GAAG,MAAM,CAAC;IACpC,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED;;GAEG;AACH,wBAAgB,WAAW,CAAC,EAAE,MAAM,EAAE,SAAS,EAAE,EAAE,gBAAgB,2CAiClE"}
1
+ {"version":3,"file":"status-badge.d.ts","sourceRoot":"","sources":["../../../src/components/saas/status-badge.tsx"],"names":[],"mappings":"AAIA,KAAK,UAAU,GACX,MAAM,GAAG,aAAa,GAAG,aAAa,GAAG,MAAM,GAAG,WAAW,GAC7D,UAAU,GAAG,SAAS,GAAG,UAAU,GAAG,WAAW,GAAG,WAAW,GAC/D,QAAQ,GAAG,UAAU,GAAG,UAAU,GAAG,OAAO,GAAG,WAAW,CAAC;AAE/D,KAAK,YAAY,GAAG,KAAK,GAAG,QAAQ,GAAG,MAAM,GAAG,QAAQ,CAAC;AAEzD,KAAK,QAAQ,GAAG,OAAO,GAAG,SAAS,GAAG,UAAU,GAAG,KAAK,GAAG,QAAQ,GAAG,YAAY,GAAG,OAAO,CAAC;AA4C7F,wBAAgB,WAAW,CAAC,EAAE,MAAM,EAAE,SAAS,EAAE,EAAE;IAAE,MAAM,EAAE,UAAU,CAAC;IAAC,SAAS,CAAC,EAAE,MAAM,CAAA;CAAE,2CAG5F;AAED,wBAAgB,aAAa,CAAC,EAAE,QAAQ,EAAE,SAAS,EAAE,EAAE;IAAE,QAAQ,EAAE,YAAY,CAAC;IAAC,SAAS,CAAC,EAAE,MAAM,CAAA;CAAE,2CAGpG;AAED,wBAAgB,SAAS,CAAC,EAAE,IAAI,EAAE,SAAS,EAAE,EAAE;IAAE,IAAI,EAAE,QAAQ,CAAC;IAAC,SAAS,CAAC,EAAE,MAAM,CAAA;CAAE,2CAGpF;AAGD,YAAY,EAAE,UAAU,EAAE,YAAY,EAAE,QAAQ,EAAE,CAAC"}