@neasg/design-system 0.2.1 → 0.4.2

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 (100) hide show
  1. package/README.md +37 -1
  2. package/dist/alert.d.ts +15 -0
  3. package/dist/alert.js +24 -0
  4. package/dist/avatar.d.ts +5 -2
  5. package/dist/avatar.js +8 -4
  6. package/dist/back-button.d.ts +6 -0
  7. package/dist/back-button.js +8 -0
  8. package/dist/badge.d.ts +4 -2
  9. package/dist/badge.js +13 -2
  10. package/dist/breadcrumb.js +2 -2
  11. package/dist/button.d.ts +2 -2
  12. package/dist/button.js +3 -4
  13. package/dist/calendar.d.ts +8 -0
  14. package/dist/calendar.js +80 -0
  15. package/dist/card.d.ts +17 -0
  16. package/dist/card.js +16 -0
  17. package/dist/checkbox.d.ts +13 -0
  18. package/dist/checkbox.js +29 -0
  19. package/dist/collapsible.d.ts +19 -0
  20. package/dist/collapsible.js +20 -0
  21. package/dist/command-search.js +4 -3
  22. package/dist/copy-button.d.ts +19 -0
  23. package/dist/copy-button.js +31 -0
  24. package/dist/date-input.d.ts +22 -0
  25. package/dist/date-input.js +61 -0
  26. package/dist/dialog-primitive.js +1 -1
  27. package/dist/draggable-tabs.js +1 -1
  28. package/dist/drawer.js +1 -1
  29. package/dist/editable-table.js +2 -2
  30. package/dist/empty-state.js +1 -1
  31. package/dist/field.d.ts +4 -1
  32. package/dist/field.js +3 -3
  33. package/dist/file-upload.d.ts +12 -0
  34. package/dist/file-upload.js +106 -0
  35. package/dist/index.d.ts +56 -4
  36. package/dist/index.js +30 -3
  37. package/dist/input-control.d.ts +1 -1
  38. package/dist/input-control.js +1 -1
  39. package/dist/input.js +2 -2
  40. package/dist/label-value-grid.d.ts +3 -1
  41. package/dist/label-value-grid.js +15 -2
  42. package/dist/label-value.d.ts +4 -1
  43. package/dist/label-value.js +5 -3
  44. package/dist/layout.d.ts +7 -1
  45. package/dist/layout.js +3 -3
  46. package/dist/lib/date-utils.d.ts +9 -0
  47. package/dist/lib/date-utils.js +34 -0
  48. package/dist/link.d.ts +9 -0
  49. package/dist/link.js +19 -0
  50. package/dist/multi-select.d.ts +31 -0
  51. package/dist/multi-select.js +78 -0
  52. package/dist/otp-input.js +1 -1
  53. package/dist/page-section.d.ts +14 -0
  54. package/dist/page-section.js +13 -0
  55. package/dist/pagination.js +3 -2
  56. package/dist/popover-menu.d.ts +35 -0
  57. package/dist/popover-menu.js +36 -0
  58. package/dist/popover-primitive.d.ts +7 -0
  59. package/dist/popover-primitive.js +11 -0
  60. package/dist/popover.d.ts +12 -0
  61. package/dist/popover.js +8 -0
  62. package/dist/progress.d.ts +10 -0
  63. package/dist/progress.js +17 -0
  64. package/dist/search-input.js +1 -1
  65. package/dist/section-nav.d.ts +22 -0
  66. package/dist/section-nav.js +25 -0
  67. package/dist/select-primitive.d.ts +3 -1
  68. package/dist/select-primitive.js +3 -2
  69. package/dist/select.d.ts +1 -0
  70. package/dist/select.js +3 -3
  71. package/dist/separator.d.ts +6 -0
  72. package/dist/separator.js +6 -0
  73. package/dist/skeleton.d.ts +4 -0
  74. package/dist/skeleton.js +6 -0
  75. package/dist/spinner.d.ts +22 -0
  76. package/dist/spinner.js +24 -0
  77. package/dist/styles.css +42 -0
  78. package/dist/switch.d.ts +12 -0
  79. package/dist/switch.js +16 -0
  80. package/dist/table.d.ts +7 -1
  81. package/dist/table.js +26 -12
  82. package/dist/tabs.d.ts +24 -1
  83. package/dist/tabs.js +61 -3
  84. package/dist/tailwind-preset.js +9 -0
  85. package/dist/textarea.js +1 -1
  86. package/dist/toaster.d.ts +13 -0
  87. package/dist/toaster.js +27 -0
  88. package/dist/typography.d.ts +2 -0
  89. package/dist/typography.js +9 -2
  90. package/dist/use-error-shake.d.ts +7 -0
  91. package/dist/use-error-shake.js +36 -0
  92. package/dist/use-file-upload.d.ts +34 -0
  93. package/dist/use-file-upload.js +133 -0
  94. package/dist/use-sticky-sentinel.d.ts +16 -0
  95. package/dist/use-sticky-sentinel.js +62 -0
  96. package/dist/use-table-sort.d.ts +28 -0
  97. package/dist/use-table-sort.js +53 -0
  98. package/dist/use-viewport-threshold.d.ts +12 -0
  99. package/dist/use-viewport-threshold.js +43 -0
  100. package/package.json +36 -6
package/README.md CHANGED
@@ -76,7 +76,42 @@ The package currently includes:
76
76
 
77
77
  ## AI Usage
78
78
 
79
- If you are using an AI coding assistant, give it these instructions explicitly:
79
+ ### MCP Server (recommended)
80
+
81
+ This design system includes the [Storybook MCP addon](https://storybook.js.org/docs/next/ai/mcp/overview/), which gives AI coding assistants direct access to component documentation, props, stories, and usage examples.
82
+
83
+ **Setup:**
84
+
85
+ 1. Start the Storybook dev server in this repo:
86
+ ```bash
87
+ npm run storybook
88
+ ```
89
+ This starts on `http://localhost:6007` with the MCP endpoint at `/mcp`.
90
+
91
+ 2. In your consuming project, add a `.mcp.json` at the project root:
92
+ ```json
93
+ {
94
+ "mcpServers": {
95
+ "nea-design-system": {
96
+ "type": "http",
97
+ "url": "http://localhost:6007/mcp"
98
+ }
99
+ }
100
+ }
101
+ ```
102
+
103
+ 3. Restart Claude Code (or your MCP-compatible AI tool) in the consuming project. The following tools become available:
104
+ - **list-all-documentation** — discover all components and their story IDs
105
+ - **get-documentation** — get full component docs, props, and code examples
106
+ - **get-documentation-for-story** — get details for a specific story variant
107
+ - **preview-stories** — generate preview URLs for stories
108
+ - **get-storybook-story-instructions** — get guidance on writing stories
109
+
110
+ The MCP server requires the Storybook dev server to be running. Start it before opening your AI tool.
111
+
112
+ ### Manual instructions
113
+
114
+ If you are not using the MCP server, give your AI coding assistant these instructions explicitly:
80
115
 
81
116
  ```text
82
117
  Use @neasg/design-system as the source of truth for shared UI.
@@ -105,6 +140,7 @@ Use @neasg/design-system as the source of truth for shared UI.
105
140
  - `@neasg/design-system/draggable-tabs`
106
141
  - `@neasg/design-system/layout`
107
142
  - `@neasg/design-system/page-header`
143
+ - `@neasg/design-system/popover`
108
144
  - `@neasg/design-system/pagination`
109
145
  - `@neasg/design-system/table`
110
146
  - `@neasg/design-system/tailwind-preset`
@@ -0,0 +1,15 @@
1
+ import * as React from "react";
2
+ import { type VariantProps } from "class-variance-authority";
3
+ declare const alertVariants: (props?: ({
4
+ variant?: "info" | "success" | "warning" | "destructive" | null | undefined;
5
+ } & import("class-variance-authority/types").ClassProp) | undefined) => string;
6
+ export interface AlertProps extends Omit<React.HTMLAttributes<HTMLDivElement>, "title">, VariantProps<typeof alertVariants> {
7
+ title?: React.ReactNode;
8
+ description?: React.ReactNode;
9
+ icon?: React.ComponentType<{
10
+ className?: string;
11
+ }>;
12
+ action?: React.ReactNode;
13
+ }
14
+ declare const Alert: React.ForwardRefExoticComponent<AlertProps & React.RefAttributes<HTMLDivElement>>;
15
+ export { Alert, alertVariants };
package/dist/alert.js ADDED
@@ -0,0 +1,24 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import * as React from "react";
3
+ import { cva } from "class-variance-authority";
4
+ import { cn } from "./lib/utils";
5
+ import { Typography } from "./typography";
6
+ const alertVariants = cva("relative flex w-full items-start gap-3 rounded-md border px-4 py-3", {
7
+ variants: {
8
+ variant: {
9
+ info: "border-[hsl(var(--status-info-foreground))]/20 bg-[hsl(var(--status-info))] text-[hsl(var(--status-info-foreground))]",
10
+ success: "border-[hsl(var(--status-success-foreground))]/20 bg-[hsl(var(--status-success))] text-[hsl(var(--status-success-foreground))]",
11
+ warning: "border-[hsl(var(--status-warning-foreground))]/20 bg-[hsl(var(--status-warning))] text-[hsl(var(--status-warning-foreground))]",
12
+ destructive: "border-[hsl(var(--status-destructive-foreground))]/20 bg-[hsl(var(--status-destructive))] text-[hsl(var(--status-destructive-foreground))]",
13
+ },
14
+ },
15
+ defaultVariants: {
16
+ variant: "info",
17
+ },
18
+ });
19
+ const Alert = React.forwardRef(({ variant, title, description, icon: Icon, action, className, children, role = "alert", ...props }, ref) => {
20
+ const body = description !== null && description !== void 0 ? description : children;
21
+ return (_jsxs("div", { ref: ref, role: role, className: cn(alertVariants({ variant }), className), ...props, children: [Icon ? (_jsx(Icon, { className: "mt-0.5 h-4 w-4 shrink-0" })) : null, _jsxs("div", { className: "flex min-w-0 flex-1 flex-col gap-1", children: [title ? (_jsx(Typography, { as: "p", variant: "bodySm", color: "inherit", className: "font-semibold", children: title })) : null, body ? (_jsx(Typography, { as: "div", variant: "caption", color: "inherit", className: "opacity-90", children: body })) : null] }), action ? _jsx("div", { className: "shrink-0 self-start", children: action }) : null] }));
22
+ });
23
+ Alert.displayName = "Alert";
24
+ export { Alert, alertVariants };
package/dist/avatar.d.ts CHANGED
@@ -3,10 +3,12 @@ import * as AvatarPrimitive from "@radix-ui/react-avatar";
3
3
  declare const AvatarRoot: React.ForwardRefExoticComponent<Omit<AvatarPrimitive.AvatarProps & React.RefAttributes<HTMLSpanElement>, "ref"> & React.RefAttributes<HTMLSpanElement>>;
4
4
  declare const AvatarImage: React.ForwardRefExoticComponent<Omit<AvatarPrimitive.AvatarImageProps & React.RefAttributes<HTMLImageElement>, "ref"> & React.RefAttributes<HTMLImageElement>>;
5
5
  declare const AvatarFallback: React.ForwardRefExoticComponent<Omit<AvatarPrimitive.AvatarFallbackProps & React.RefAttributes<HTMLSpanElement>, "ref"> & React.RefAttributes<HTMLSpanElement>>;
6
+ export type AvatarSize = "sm" | "md";
6
7
  interface AvatarProps extends Omit<React.ComponentPropsWithoutRef<typeof AvatarRoot>, "children"> {
7
8
  src?: string | null;
8
9
  alt?: string;
9
10
  fallback: React.ReactNode;
11
+ size?: AvatarSize;
10
12
  imageClassName?: string;
11
13
  fallbackClassName?: string;
12
14
  }
@@ -14,6 +16,7 @@ interface AvatarProfileProps extends Omit<React.HTMLAttributes<HTMLDivElement>,
14
16
  src?: string | null;
15
17
  alt?: string;
16
18
  fallback: React.ReactNode;
19
+ size?: AvatarSize;
17
20
  name?: React.ReactNode;
18
21
  role?: React.ReactNode;
19
22
  rolePlacement?: "above" | "below";
@@ -25,8 +28,8 @@ interface AvatarProfileProps extends Omit<React.HTMLAttributes<HTMLDivElement>,
25
28
  roleClassName?: string;
26
29
  avatarOverlay?: React.ReactNode;
27
30
  }
28
- declare function Avatar({ src, alt, fallback, className, imageClassName, fallbackClassName, ...props }: AvatarProps): import("react/jsx-runtime").JSX.Element;
29
- declare function AvatarProfile({ src, alt, fallback, name, role, rolePlacement, className, avatarClassName, imageClassName, fallbackClassName, contentClassName, nameClassName, roleClassName, avatarOverlay, ...props }: AvatarProfileProps): import("react/jsx-runtime").JSX.Element;
31
+ declare function Avatar({ src, alt, fallback, size, className, imageClassName, fallbackClassName, ...props }: AvatarProps): import("react/jsx-runtime").JSX.Element;
32
+ declare function AvatarProfile({ src, alt, fallback, size, name, role, rolePlacement, className, avatarClassName, imageClassName, fallbackClassName, contentClassName, nameClassName, roleClassName, avatarOverlay, ...props }: AvatarProfileProps): import("react/jsx-runtime").JSX.Element;
30
33
  export { Avatar, AvatarProfile, AvatarRoot, AvatarImage, AvatarFallback };
31
34
  export type AvatarRootProps = React.ComponentPropsWithoutRef<typeof AvatarRoot>;
32
35
  export type { AvatarProps, AvatarProfileProps };
package/dist/avatar.js CHANGED
@@ -9,13 +9,17 @@ const AvatarImage = React.forwardRef(({ className, ...props }, ref) => (_jsx(Ava
9
9
  AvatarImage.displayName = "AvatarImage";
10
10
  const AvatarFallback = React.forwardRef(({ className, ...props }, ref) => (_jsx(AvatarPrimitive.Fallback, { ref: ref, className: cn("flex size-full items-center justify-center rounded-full bg-muted", className), ...props })));
11
11
  AvatarFallback.displayName = "AvatarFallback";
12
- function Avatar({ src, alt = "", fallback, className, imageClassName, fallbackClassName, ...props }) {
13
- return (_jsxs(AvatarRoot, { className: cn("h-8 w-8", className), ...props, children: [src ? (_jsx(AvatarImage, { src: src, alt: alt, className: imageClassName })) : null, _jsx(AvatarFallback, { className: cn("bg-green-100 text-xs font-medium text-green-800", fallbackClassName), children: fallback })] }));
12
+ const avatarSizeClasses = {
13
+ sm: "h-8 w-8 text-xs",
14
+ md: "h-10 w-10 text-sm",
15
+ };
16
+ function Avatar({ src, alt = "", fallback, size = "sm", className, imageClassName, fallbackClassName, ...props }) {
17
+ return (_jsxs(AvatarRoot, { className: cn(avatarSizeClasses[size], className), ...props, children: [src ? (_jsx(AvatarImage, { src: src, alt: alt, className: imageClassName })) : null, _jsx(AvatarFallback, { className: cn("bg-green-100 font-medium text-green-800", fallbackClassName), children: fallback })] }));
14
18
  }
15
- function AvatarProfile({ src, alt = "", fallback, name, role, rolePlacement = "above", className, avatarClassName, imageClassName, fallbackClassName, contentClassName, nameClassName, roleClassName, avatarOverlay, ...props }) {
19
+ function AvatarProfile({ src, alt = "", fallback, size = "sm", name, role, rolePlacement = "above", className, avatarClassName, imageClassName, fallbackClassName, contentClassName, nameClassName, roleClassName, avatarOverlay, ...props }) {
16
20
  const hasMeta = name !== undefined || role !== undefined;
17
21
  const roleNode = role ? (_jsx("span", { className: cn("text-[10px] font-medium uppercase tracking-wide text-muted-foreground", roleClassName), children: role })) : null;
18
22
  const nameNode = name ? (_jsx("span", { className: cn("truncate text-sm font-medium text-foreground", nameClassName), children: name })) : null;
19
- return (_jsxs("div", { className: cn("flex items-center gap-2", className), ...props, children: [_jsxs("div", { className: "relative shrink-0", children: [_jsx(Avatar, { src: src, alt: alt, fallback: fallback, className: cn("h-8 w-8", avatarClassName), imageClassName: imageClassName, fallbackClassName: fallbackClassName }), avatarOverlay] }), hasMeta ? (_jsxs("div", { className: cn("flex min-w-0 flex-1 flex-col", contentClassName), children: [rolePlacement === "above" ? roleNode : null, nameNode, rolePlacement === "below" ? roleNode : null] })) : null] }));
23
+ return (_jsxs("div", { className: cn("flex items-center gap-2", className), ...props, children: [_jsxs("div", { className: "relative shrink-0", children: [_jsx(Avatar, { src: src, alt: alt, fallback: fallback, size: size, className: avatarClassName, imageClassName: imageClassName, fallbackClassName: fallbackClassName }), avatarOverlay] }), hasMeta ? (_jsxs("div", { className: cn("flex min-w-0 flex-1 flex-col", contentClassName), children: [rolePlacement === "above" ? roleNode : null, nameNode, rolePlacement === "below" ? roleNode : null] })) : null] }));
20
24
  }
21
25
  export { Avatar, AvatarProfile, AvatarRoot, AvatarImage, AvatarFallback };
@@ -0,0 +1,6 @@
1
+ import * as React from "react";
2
+ import { type ButtonProps } from "./button";
3
+ export interface BackButtonProps extends Omit<ButtonProps, "asChild" | "size" | "variant"> {
4
+ }
5
+ declare const BackButton: React.ForwardRefExoticComponent<BackButtonProps & React.RefAttributes<HTMLButtonElement>>;
6
+ export { BackButton };
@@ -0,0 +1,8 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import * as React from "react";
3
+ import { ChevronLeftIcon } from "./animated-icons/chevron-left";
4
+ import { Button } from "./button";
5
+ import { cn } from "./lib/utils";
6
+ const BackButton = React.forwardRef(({ children = "Back", className, type, ...props }, ref) => (_jsxs(Button, { ref: ref, type: type !== null && type !== void 0 ? type : "button", variant: "link", className: cn("h-auto gap-1 px-0", className), ...props, children: [_jsx(ChevronLeftIcon, { "aria-hidden": "true", className: "shrink-0", size: 16 }), _jsx("span", { children: children })] })));
7
+ BackButton.displayName = "BackButton";
8
+ export { BackButton };
package/dist/badge.d.ts CHANGED
@@ -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?: "muted" | "outline" | "secondary" | "destructive" | "success" | "warning" | "info" | "accent" | null | undefined;
4
+ variant?: "muted" | "outline" | "info" | "success" | "warning" | "destructive" | "secondary" | "accent" | null | undefined;
5
5
  } & import("class-variance-authority/types").ClassProp) | undefined) => string;
6
6
  /**
7
7
  * Visual status label used for short categorical values like case state,
@@ -9,6 +9,8 @@ declare const badgeVariants: (props?: ({
9
9
  * surface the full label via `title`.
10
10
  */
11
11
  export interface BadgeProps extends React.HTMLAttributes<HTMLDivElement>, VariantProps<typeof badgeVariants> {
12
+ /** Show a visible border matching the badge colour. */
13
+ bordered?: boolean;
12
14
  }
13
- declare function Badge({ className, variant, children, ...props }: BadgeProps): import("react/jsx-runtime").JSX.Element;
15
+ declare function Badge({ className, variant, bordered, children, ...props }: BadgeProps): import("react/jsx-runtime").JSX.Element;
14
16
  export { Badge, badgeVariants };
package/dist/badge.js CHANGED
@@ -19,12 +19,23 @@ const badgeVariants = cva("inline-flex max-w-[200px] items-center justify-center
19
19
  variant: "secondary",
20
20
  },
21
21
  });
22
- function Badge({ className, variant, children, ...props }) {
22
+ function Badge({ className, variant, bordered = false, children, ...props }) {
23
23
  const textContent = typeof children === "string"
24
24
  ? children
25
25
  : React.Children.toArray(children)
26
26
  .filter((child) => typeof child === "string")
27
27
  .join("");
28
- return (_jsx("div", { className: cn(badgeVariants({ variant }), className), title: textContent || undefined, ...props, children: children }));
28
+ const resolvedVariant = variant !== null && variant !== void 0 ? variant : "secondary";
29
+ const borderedClasses = {
30
+ secondary: "border-secondary-foreground/30",
31
+ muted: "border-muted-foreground/30",
32
+ destructive: "border-[hsl(var(--status-destructive-foreground))]/30",
33
+ outline: "border-foreground/30",
34
+ success: "border-[hsl(var(--status-success-foreground))]/30",
35
+ warning: "border-[hsl(var(--status-warning-foreground))]/30",
36
+ info: "border-[hsl(var(--status-info-foreground))]/30",
37
+ accent: "border-[hsl(var(--status-accent-foreground))]/30",
38
+ };
39
+ return (_jsx("div", { className: cn(badgeVariants({ variant }), bordered && borderedClasses[resolvedVariant], className), title: textContent || undefined, ...props, children: children }));
29
40
  }
30
41
  export { Badge, badgeVariants };
@@ -11,14 +11,14 @@ const BreadcrumbItem = React.forwardRef(({ className, ...props }, ref) => (_jsx(
11
11
  BreadcrumbItem.displayName = "BreadcrumbItem";
12
12
  const BreadcrumbLink = React.forwardRef(({ asChild, className, ...props }, ref) => {
13
13
  const Comp = asChild ? Slot : "a";
14
- return (_jsx(Comp, { ref: ref, className: cn("transition-colors hover:text-foreground", className), ...props }));
14
+ return (_jsx(Comp, { ref: ref, className: cn("cursor-pointer transition-colors hover:text-foreground", className), ...props }));
15
15
  });
16
16
  BreadcrumbLink.displayName = "BreadcrumbLink";
17
17
  const BreadcrumbPage = React.forwardRef(({ className, ...props }, ref) => (_jsx("span", { ref: ref, role: "link", "aria-disabled": "true", "aria-current": "page", className: cn("font-normal text-foreground", className), ...props })));
18
18
  BreadcrumbPage.displayName = "BreadcrumbPage";
19
19
  const BreadcrumbSeparator = ({ children, className, ...props }) => (_jsx("li", { role: "presentation", "aria-hidden": "true", className: cn("[&>svg]:h-3.5 [&>svg]:w-3.5", className), ...props, children: children !== null && children !== void 0 ? children : (_jsx("svg", { viewBox: "0 0 16 16", fill: "none", stroke: "currentColor", strokeWidth: "1.75", children: _jsx("path", { d: "M6 3.5 10.5 8 6 12.5" }) })) }));
20
20
  BreadcrumbSeparator.displayName = "BreadcrumbSeparator";
21
- const BreadcrumbEllipsis = ({ className, ...props }) => (_jsxs("span", { role: "presentation", "aria-hidden": "true", className: cn("flex h-9 w-9 items-center justify-center", className), ...props, children: [_jsx("span", { className: "text-lg leading-none", children: "\u2026" }), _jsx("span", { className: "sr-only", children: "More" })] }));
21
+ const BreadcrumbEllipsis = ({ className, ...props }) => (_jsxs("span", { role: "presentation", "aria-hidden": "true", className: cn("flex h-control w-control items-center justify-center", className), ...props, children: [_jsx("span", { className: "text-lg leading-none", children: "\u2026" }), _jsx("span", { className: "sr-only", children: "More" })] }));
22
22
  BreadcrumbEllipsis.displayName = "BreadcrumbEllipsis";
23
23
  function Breadcrumb({ items, separator, className, listClassName, itemClassName, linkClassName, currentClassName, ...props }) {
24
24
  if (!items.length) {
package/dist/button.d.ts CHANGED
@@ -1,8 +1,8 @@
1
1
  import * as React from "react";
2
2
  import { type VariantProps } from "class-variance-authority";
3
3
  declare const buttonVariants: (props?: ({
4
- variant?: "link" | "default" | "outline" | "secondary" | "destructive" | "ghost" | null | undefined;
5
- size?: "default" | "sm" | "icon" | "lg" | null | undefined;
4
+ variant?: "link" | "default" | "outline" | "destructive" | "secondary" | "ghost" | null | undefined;
5
+ size?: "default" | "sm" | "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> {
8
8
  /**
package/dist/button.js CHANGED
@@ -14,10 +14,9 @@ const buttonVariants = cva("inline-flex cursor-pointer items-center justify-cent
14
14
  link: "text-primary underline-offset-4 hover:underline",
15
15
  },
16
16
  size: {
17
- default: "h-10 px-4 py-2 [&_svg]:h-4 [&_svg]:w-4",
18
- sm: "h-9 rounded-md px-3 text-xs [&_svg]:h-4 [&_svg]:w-4",
19
- lg: "h-11 rounded-md px-8 [&_svg]:h-5 [&_svg]:w-5",
20
- icon: "h-10 w-10 [&_svg]:h-4 [&_svg]:w-4",
17
+ sm: "h-9 px-3 text-sm [&_svg]:h-4 [&_svg]:w-4",
18
+ default: "h-control px-4 py-2 [&_svg]:h-4 [&_svg]:w-4",
19
+ icon: "h-control w-control [&_svg]:h-4 [&_svg]:w-4",
21
20
  },
22
21
  },
23
22
  defaultVariants: {
@@ -0,0 +1,8 @@
1
+ import * as React from "react";
2
+ import { DayButton, DayPicker } from "react-day-picker";
3
+ import { Button } from "./button";
4
+ declare function CalendarDayButton({ className, day, modifiers, children, disabled, onClick, onFocus, onBlur, onKeyDown, onMouseEnter, onMouseLeave, tabIndex, type, "aria-label": ariaLabel, "aria-pressed": ariaPressed, "aria-selected": ariaSelected, }: React.ComponentProps<typeof DayButton>): import("react/jsx-runtime").JSX.Element;
5
+ declare function Calendar({ className, classNames, showOutsideDays, captionLayout, buttonVariant, formatters, components, ...props }: React.ComponentProps<typeof DayPicker> & {
6
+ buttonVariant?: React.ComponentProps<typeof Button>["variant"];
7
+ }): import("react/jsx-runtime").JSX.Element;
8
+ export { Calendar, CalendarDayButton };
@@ -0,0 +1,80 @@
1
+ "use client";
2
+ import { jsx as _jsx } from "react/jsx-runtime";
3
+ import * as React from "react";
4
+ import { DayPicker, getDefaultClassNames } from "react-day-picker";
5
+ import { buttonVariants } from "./button";
6
+ import { cn } from "./lib/utils";
7
+ function CalendarDayButton({ className, day, modifiers, children, disabled, onClick, onFocus, onBlur, onKeyDown, onMouseEnter, onMouseLeave, tabIndex, type, "aria-label": ariaLabel, "aria-pressed": ariaPressed, "aria-selected": ariaSelected, }) {
8
+ const defaultClassNames = getDefaultClassNames();
9
+ const ref = React.useRef(null);
10
+ React.useEffect(() => {
11
+ var _a;
12
+ if (modifiers.focused)
13
+ (_a = ref.current) === null || _a === void 0 ? void 0 : _a.focus();
14
+ }, [modifiers.focused]);
15
+ return (_jsx("button", { ref: ref, type: type, disabled: disabled, onClick: onClick, onFocus: onFocus, onBlur: onBlur, onKeyDown: onKeyDown, onMouseEnter: onMouseEnter, onMouseLeave: onMouseLeave, tabIndex: tabIndex, "aria-label": ariaLabel, "aria-pressed": ariaPressed, "aria-selected": ariaSelected, "data-day": day.date.toLocaleDateString(), "data-selected-single": modifiers.selected &&
16
+ !modifiers.range_start &&
17
+ !modifiers.range_end &&
18
+ !modifiers.range_middle, "data-range-start": modifiers.range_start, "data-range-end": modifiers.range_end, "data-range-middle": modifiers.range_middle, className: cn("inline-flex cursor-pointer items-center justify-center rounded-md text-sm outline-none transition-colors hover:bg-accent hover:text-accent-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50", "data-[selected-single=true]:bg-primary data-[selected-single=true]:text-primary-foreground data-[range-middle=true]:bg-accent data-[range-middle=true]:text-accent-foreground data-[range-start=true]:bg-primary data-[range-start=true]:text-primary-foreground data-[range-end=true]:bg-primary data-[range-end=true]:text-primary-foreground group-data-[focused=true]/day:border-ring group-data-[focused=true]/day:ring-ring/50 aspect-square w-full min-w-[--cell-size] font-normal leading-none data-[range-end=true]:rounded-md data-[range-middle=true]:rounded-none data-[range-start=true]:rounded-md group-data-[focused=true]/day:relative group-data-[focused=true]/day:z-10 group-data-[focused=true]/day:ring-[3px]", defaultClassNames.day, className), children: children }));
19
+ }
20
+ function Calendar({ className, classNames, showOutsideDays = true, captionLayout = "label", buttonVariant = "ghost", formatters, components, ...props }) {
21
+ const defaultClassNames = getDefaultClassNames();
22
+ return (_jsx(DayPicker, { showOutsideDays: showOutsideDays, className: cn("bg-background group/calendar p-3 [--cell-size:2rem] [[data-slot=card-content]_&]:bg-transparent [[data-slot=popover-content]_&]:bg-transparent", String.raw `rtl:**:[.rdp-button\_next>svg]:rotate-180`, String.raw `rtl:**:[.rdp-button\_previous>svg]:rotate-180`, className), captionLayout: captionLayout, formatters: {
23
+ formatMonthDropdown: (date) => date.toLocaleString("default", { month: "short" }),
24
+ ...formatters,
25
+ }, classNames: {
26
+ root: cn("w-fit", defaultClassNames.root),
27
+ months: cn("relative flex flex-col gap-4 md:flex-row", defaultClassNames.months),
28
+ month: cn("flex w-full flex-col gap-4", defaultClassNames.month),
29
+ nav: cn("absolute inset-x-0 top-0 flex w-full items-center justify-between gap-1", defaultClassNames.nav),
30
+ button_previous: cn(buttonVariants({ variant: buttonVariant }), "h-[--cell-size] w-[--cell-size] select-none p-0 aria-disabled:opacity-50", defaultClassNames.button_previous),
31
+ button_next: cn(buttonVariants({ variant: buttonVariant }), "h-[--cell-size] w-[--cell-size] select-none p-0 aria-disabled:opacity-50", defaultClassNames.button_next),
32
+ month_caption: cn("flex h-[--cell-size] w-full items-center justify-center px-[--cell-size]", defaultClassNames.month_caption),
33
+ dropdowns: cn("flex h-[--cell-size] w-full items-center justify-center gap-1.5 text-sm font-medium", defaultClassNames.dropdowns),
34
+ dropdown_root: cn("has-focus:border-ring border-input shadow-xs has-focus:ring-ring/50 has-focus:ring-[3px] relative rounded-md border", defaultClassNames.dropdown_root),
35
+ dropdown: cn("bg-popover absolute inset-0 opacity-0", defaultClassNames.dropdown),
36
+ caption_label: cn("select-none font-medium", captionLayout === "label"
37
+ ? "text-sm"
38
+ : "[&>svg]:text-muted-foreground flex h-8 items-center gap-1 rounded-md pl-2 pr-1 text-sm [&>svg]:size-3.5", defaultClassNames.caption_label),
39
+ table: "w-full border-collapse",
40
+ weekdays: cn("flex", defaultClassNames.weekdays),
41
+ weekday: cn("text-muted-foreground flex-1 select-none rounded-md text-[0.8rem] font-normal", defaultClassNames.weekday),
42
+ week: cn("mt-2 flex w-full", defaultClassNames.week),
43
+ week_number_header: cn("w-[--cell-size] select-none", defaultClassNames.week_number_header),
44
+ week_number: cn("text-muted-foreground select-none text-[0.8rem]", defaultClassNames.week_number),
45
+ day: cn("group/day relative aspect-square h-full w-full select-none p-0 text-center [&:first-child[data-selected=true]_button]:rounded-l-md [&:last-child[data-selected=true]_button]:rounded-r-md", defaultClassNames.day),
46
+ range_start: cn("bg-accent rounded-l-md", defaultClassNames.range_start),
47
+ range_middle: cn("rounded-none", defaultClassNames.range_middle),
48
+ range_end: cn("bg-accent rounded-r-md", defaultClassNames.range_end),
49
+ today: cn("bg-accent text-accent-foreground rounded-md data-[selected=true]:rounded-none", defaultClassNames.today),
50
+ outside: cn("text-muted-foreground aria-selected:text-muted-foreground", defaultClassNames.outside),
51
+ disabled: cn("text-muted-foreground opacity-50", defaultClassNames.disabled),
52
+ hidden: cn("invisible", defaultClassNames.hidden),
53
+ ...classNames,
54
+ }, components: {
55
+ Root: ({ className: rootClassName, rootRef, ...rootProps }) => (_jsx("div", { "data-slot": "calendar", ref: rootRef, className: cn(rootClassName), ...rootProps })),
56
+ Chevron: ({ className: chevronClassName, orientation }) => {
57
+ const svgProps = {
58
+ className: cn("size-4", chevronClassName),
59
+ viewBox: "0 0 24 24",
60
+ fill: "none",
61
+ stroke: "currentColor",
62
+ strokeWidth: 2,
63
+ strokeLinecap: "round",
64
+ strokeLinejoin: "round",
65
+ "aria-hidden": true,
66
+ };
67
+ if (orientation === "left") {
68
+ return _jsx("svg", { ...svgProps, children: _jsx("path", { d: "m15 18-6-6 6-6" }) });
69
+ }
70
+ if (orientation === "right") {
71
+ return _jsx("svg", { ...svgProps, children: _jsx("path", { d: "m9 18 6-6-6-6" }) });
72
+ }
73
+ return _jsx("svg", { ...svgProps, children: _jsx("path", { d: "m6 9 6 6 6-6" }) });
74
+ },
75
+ DayButton: CalendarDayButton,
76
+ WeekNumber: ({ children, ...weekNumberProps }) => (_jsx("td", { ...weekNumberProps, children: _jsx("div", { className: "flex size-[--cell-size] items-center justify-center text-center", children: children }) })),
77
+ ...components,
78
+ }, ...props }));
79
+ }
80
+ export { Calendar, CalendarDayButton };
package/dist/card.d.ts ADDED
@@ -0,0 +1,17 @@
1
+ import * as React from "react";
2
+ export interface CardProps extends Omit<React.HTMLAttributes<HTMLDivElement>, "title"> {
3
+ title: React.ReactNode;
4
+ description?: React.ReactNode;
5
+ variant?: "default" | "elevated" | "gradient";
6
+ size?: "default" | "compact";
7
+ /** Large value displayed above the title — use for stat/metric cards. */
8
+ stat?: React.ReactNode;
9
+ /** Small supporting text below the stat or body — use for sub-metrics. */
10
+ subMetric?: React.ReactNode;
11
+ footer?: React.ReactNode;
12
+ active?: boolean;
13
+ /** Replaces title/stat/subMetric with skeleton placeholders while data is loading. */
14
+ loading?: boolean;
15
+ }
16
+ declare const Card: React.ForwardRefExoticComponent<CardProps & React.RefAttributes<HTMLDivElement>>;
17
+ export { Card };
package/dist/card.js ADDED
@@ -0,0 +1,16 @@
1
+ "use client";
2
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
+ import * as React from "react";
4
+ import { cn } from "./lib/utils";
5
+ import { Skeleton } from "./skeleton";
6
+ import { Typography } from "./typography";
7
+ const Card = React.forwardRef(({ title, description, variant = "default", size = "default", stat, subMetric, footer, active, loading = false, children, className, onClick, ...props }, ref) => {
8
+ const renderedTitle = React.isValidElement(title) ? (title) : (_jsx(Typography, { as: "p", variant: "label", color: variant === "gradient" ? "inherit" : "muted", className: variant === "gradient" ? "opacity-80" : undefined, children: title }));
9
+ const renderedDescription = description == null ? null : React.isValidElement(description) ? (description) : (_jsx(Typography, { as: "p", variant: "caption", color: variant === "gradient" ? "inherit" : undefined, className: variant === "gradient" ? "opacity-70" : undefined, children: description }));
10
+ return (_jsxs("div", { ref: ref, onClick: onClick, className: cn("rounded-lg border text-card-foreground", variant === "default" && "bg-card", variant === "elevated" && "bg-card shadow-sm", variant === "gradient" &&
11
+ "border-primary/20 bg-gradient-to-br from-primary to-primary/80 text-primary-foreground", active && "border-primary bg-primary/[0.04] ring-1 ring-primary/20", onClick && "cursor-pointer transition-colors hover:border-primary", className), ...props, children: [_jsxs("div", { className: cn("flex flex-col gap-2", size === "default" && "p-6", size === "compact" && "p-3"), children: [loading ? (_jsx(Skeleton, { className: "h-3.5 w-24" })) : (renderedTitle), loading
12
+ ? description != null && _jsx(Skeleton, { className: "h-5 w-40" })
13
+ : renderedDescription, loading ? (stat !== undefined && _jsx(Skeleton, { className: "h-8 w-20" })) : stat ? (_jsx(Typography, { as: "p", variant: "title", color: variant === "gradient" ? "inherit" : undefined, children: stat })) : null, loading ? (subMetric !== undefined && _jsx(Skeleton, { className: "h-5 w-28" })) : subMetric ? (_jsx(Typography, { as: "p", variant: "caption", color: variant === "gradient" ? "inherit" : undefined, className: variant === "gradient" ? "opacity-80" : undefined, children: subMetric })) : null] }), children ? (_jsx("div", { className: cn(size === "default" && "p-6 pt-0", size === "compact" && "p-3 pt-0"), children: children })) : null, footer ? (_jsx("div", { className: cn("flex items-center", size === "default" && "p-6 pt-0", size === "compact" && "p-3 pt-0"), children: footer })) : null] }));
14
+ });
15
+ Card.displayName = "Card";
16
+ export { Card };
@@ -0,0 +1,13 @@
1
+ import * as React from "react";
2
+ export interface CheckboxProps extends Omit<React.InputHTMLAttributes<HTMLInputElement>, "type" | "size"> {
3
+ /** Renders the checkbox in an indeterminate (mixed) state. */
4
+ indeterminate?: boolean;
5
+ /** Visual size of the checkbox. */
6
+ size?: "sm" | "md" | "lg";
7
+ /** Label rendered next to the checkbox. When provided, the checkbox and label are wrapped in a `<label>`. */
8
+ label?: React.ReactNode;
9
+ /** Description shown below the label in smaller muted text. */
10
+ description?: React.ReactNode;
11
+ }
12
+ declare const Checkbox: React.ForwardRefExoticComponent<CheckboxProps & React.RefAttributes<HTMLInputElement>>;
13
+ export { Checkbox };
@@ -0,0 +1,29 @@
1
+ "use client";
2
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
+ import * as React from "react";
4
+ import { cn } from "./lib/utils";
5
+ import { Typography } from "./typography";
6
+ const sizeClasses = {
7
+ sm: "size-3.5",
8
+ md: "size-4",
9
+ lg: "size-5",
10
+ };
11
+ const Checkbox = React.forwardRef(({ className, indeterminate = false, size = "md", checked, disabled, label, description, id, ...props }, ref) => {
12
+ const innerRef = React.useRef(null);
13
+ const generatedId = React.useId();
14
+ const inputId = id !== null && id !== void 0 ? id : `checkbox-${generatedId}`;
15
+ React.useImperativeHandle(ref, () => innerRef.current);
16
+ React.useEffect(() => {
17
+ if (innerRef.current) {
18
+ innerRef.current.indeterminate = indeterminate;
19
+ }
20
+ }, [indeterminate]);
21
+ const box = (_jsxs("span", { className: cn("relative inline-block shrink-0 rounded-sm border bg-background align-middle text-primary-foreground transition-colors", sizeClasses[size], (checked || indeterminate) && !disabled
22
+ ? "border-primary bg-primary"
23
+ : "border-input", disabled && "cursor-not-allowed opacity-50", !label && className), children: [_jsx("input", { ref: innerRef, type: "checkbox", id: inputId, checked: checked, disabled: disabled, className: "absolute inset-0 h-full w-full cursor-pointer appearance-none opacity-0 disabled:cursor-not-allowed", ...props }), indeterminate ? (_jsx("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "3", strokeLinecap: "round", className: "pointer-events-none absolute inset-0 m-auto h-3 w-3", "aria-hidden": "true", children: _jsx("line", { x1: "5", y1: "12", x2: "19", y2: "12" }) })) : checked ? (_jsx("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "3", strokeLinecap: "round", strokeLinejoin: "round", className: "pointer-events-none absolute inset-0 m-auto h-3 w-3", "aria-hidden": "true", children: _jsx("polyline", { points: "20 6 9 17 4 12" }) })) : null] }));
24
+ if (!label)
25
+ return box;
26
+ return (_jsxs("label", { htmlFor: inputId, className: cn("inline-flex cursor-pointer items-center gap-2 text-sm", disabled && "cursor-not-allowed opacity-50", className), children: [box, _jsxs("div", { className: "select-none", children: [_jsx(Typography, { as: "span", variant: "bodySm", children: label }), description ? (_jsx(Typography, { as: "p", variant: "caption", className: "mt-1", children: description })) : null] })] }));
27
+ });
28
+ Checkbox.displayName = "Checkbox";
29
+ export { Checkbox };
@@ -0,0 +1,19 @@
1
+ import * as React from "react";
2
+ export interface CollapsibleProps {
3
+ id?: string;
4
+ title: React.ReactNode;
5
+ children: React.ReactNode;
6
+ defaultOpen?: boolean;
7
+ open?: boolean;
8
+ onOpenChange?: (open: boolean) => void;
9
+ /** Element rendered on the right of the header, before the chevron (e.g. an edit button). */
10
+ headerAction?: React.ReactNode;
11
+ /** Element rendered inline after the title (e.g. a tooltip icon). */
12
+ titleAdornment?: React.ReactNode;
13
+ className?: string;
14
+ headerClassName?: string;
15
+ contentClassName?: string;
16
+ }
17
+ declare function Collapsible({ id, title, children, defaultOpen, open: openProp, onOpenChange, headerAction, titleAdornment, className, headerClassName, contentClassName, }: CollapsibleProps): import("react/jsx-runtime").JSX.Element;
18
+ declare const CollapsibleSection: typeof Collapsible;
19
+ export { Collapsible, CollapsibleSection };
@@ -0,0 +1,20 @@
1
+ "use client";
2
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
+ import * as React from "react";
4
+ import * as CollapsiblePrimitive from "@radix-ui/react-collapsible";
5
+ import { ChevronUp } from "lucide-react";
6
+ import { cn } from "./lib/utils";
7
+ import { Typography } from "./typography";
8
+ function Collapsible({ id, title, children, defaultOpen = true, open: openProp, onOpenChange, headerAction, titleAdornment, className, headerClassName, contentClassName, }) {
9
+ const [uncontrolled, setUncontrolled] = React.useState(defaultOpen);
10
+ const isControlled = openProp !== undefined;
11
+ const open = isControlled ? openProp : uncontrolled;
12
+ const setOpen = (next) => {
13
+ if (!isControlled)
14
+ setUncontrolled(next);
15
+ onOpenChange === null || onOpenChange === void 0 ? void 0 : onOpenChange(next);
16
+ };
17
+ return (_jsxs(CollapsiblePrimitive.Root, { id: id, open: open, onOpenChange: setOpen, className: cn("scroll-mt-24 border-b border-border", className), children: [_jsxs("div", { className: cn("flex items-center gap-2 py-3", headerClassName), children: [_jsx(CollapsiblePrimitive.Trigger, { asChild: true, children: _jsxs("button", { type: "button", className: "flex flex-1 cursor-pointer items-center gap-2 text-left text-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 rounded-sm", children: [_jsx(Typography, { as: "h3", variant: "subheading", children: title }), titleAdornment] }) }), headerAction, _jsx(CollapsiblePrimitive.Trigger, { asChild: true, children: _jsx("button", { type: "button", "aria-label": open ? "Collapse section" : "Expand section", className: "group ml-1 cursor-pointer text-muted-foreground hover:text-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 rounded-sm", children: _jsx(ChevronUp, { "aria-hidden": "true", className: "h-4 w-4 transition-transform duration-150 group-data-[state=closed]:rotate-180" }) }) })] }), _jsx(CollapsiblePrimitive.Content, { "data-slot": "collapsible-content", className: "overflow-hidden", children: _jsx("div", { className: cn("pb-6 pt-4", contentClassName), children: children }) })] }));
18
+ }
19
+ const CollapsibleSection = Collapsible;
20
+ export { Collapsible, CollapsibleSection };
@@ -8,6 +8,7 @@ import { SearchIcon } from "./animated-icons/search";
8
8
  import { DialogRoot, DialogSurface } from "./dialog-primitive";
9
9
  import { FilterToggle } from "./filter-toggle";
10
10
  import { cn } from "./lib/utils";
11
+ import { Typography } from "./typography";
11
12
  import { SearchHighlight } from "./use-search-highlight";
12
13
  function CommandSearchEmptyIcon({ className }) {
13
14
  return _jsx(SearchIcon, { className: className, size: 20 });
@@ -57,14 +58,14 @@ function CommandSearch({ value, onValueChange, sections, children, className, is
57
58
  }
58
59
  }, [isOpen]);
59
60
  return (_jsxs("div", { className: className, ...props, children: [_jsxs(Button, { type: "button", onClick: () => setIsOpen(true), variant: "ghost", className: cn(isCollapsed
60
- ? "h-10 w-full justify-center rounded-lg px-3 !font-normal text-muted-foreground hover:bg-white hover:text-foreground"
61
- : "h-10 w-full min-w-[14rem] justify-start gap-3 rounded-lg border border-gray-200 bg-white px-3 !font-normal text-muted-foreground shadow-sm hover:bg-white hover:text-foreground"), children: [_jsx(SearchIcon, { className: "shrink-0", size: 16 }), !isCollapsed ? (_jsxs(_Fragment, { children: [_jsx("span", { className: "flex-1 text-left text-sm", children: triggerPlaceholder }), _jsx("kbd", { className: "hidden h-5 items-center gap-1 rounded border bg-muted px-1.5 font-mono text-[10px] text-muted-foreground sm:inline-flex", children: resolvedLabel })] })) : null] }), _jsx(DialogRoot, { open: isOpen, onOpenChange: setIsOpen, children: _jsx(DialogSurface, { className: cn("max-w-xl gap-0 overflow-hidden p-0 sm:max-w-xl", dialogClassName), hideCloseButton: true, children: _jsxs(Command, { shouldFilter: false, className: "rounded-none border-0", children: [_jsx(CommandInput, { ref: inputRef, value: value, onValueChange: onValueChange, placeholder: inputPlaceholder, className: "text-sm" }), allFilter || filters.length ? (_jsxs("div", { className: "flex items-center gap-1 border-b px-3 py-2", children: [allFilter ? (_jsx(FilterToggle, { selected: allFilter.selected, onClick: allFilter.onSelect, children: allFilter.label })) : null, filters.map((filter) => (_jsx(FilterToggle, { selected: filter.selected, onClick: filter.onSelect, children: filter.label }, filter.value)))] })) : null, _jsx(CommandList, { className: cn("max-h-[400px] p-1", resultsClassName), children: children !== undefined ? children : sections ? (visibleSections.length ? (visibleSections.map((section, index) => (_jsxs(React.Fragment, { children: [index > 0 ? _jsx(CommandSeparator, { alwaysRender: true }) : null, _jsx(CommandGroup, { heading: section.heading, children: section.items.map((item) => (_jsx(CommandItem, { value: getCommandSearchItemValue(item), disabled: item.disabled, onSelect: () => {
61
+ ? "h-control w-full justify-center rounded-lg px-3 !font-normal text-muted-foreground hover:bg-white hover:text-foreground"
62
+ : "h-control w-full min-w-[14rem] justify-start gap-3 rounded-lg border border-gray-200 bg-white px-3 !font-normal text-muted-foreground hover:bg-white hover:text-foreground"), children: [_jsx(SearchIcon, { className: "shrink-0", size: 16 }), !isCollapsed ? (_jsxs(_Fragment, { children: [_jsx("span", { className: "flex-1 text-left text-sm", children: triggerPlaceholder }), _jsx("kbd", { className: "hidden h-5 items-center gap-1 rounded border bg-muted px-1.5 font-mono text-[10px] text-muted-foreground sm:inline-flex", children: resolvedLabel })] })) : null] }), _jsx(DialogRoot, { open: isOpen, onOpenChange: setIsOpen, children: _jsx(DialogSurface, { className: cn("max-w-xl gap-0 overflow-hidden p-0 sm:max-w-xl", dialogClassName), hideCloseButton: true, children: _jsxs(Command, { shouldFilter: false, className: "rounded-none border-0", children: [_jsx(CommandInput, { ref: inputRef, value: value, onValueChange: onValueChange, placeholder: inputPlaceholder, className: "text-sm" }), allFilter || filters.length ? (_jsxs("div", { className: "flex items-center gap-1 border-b px-3 py-2", children: [allFilter ? (_jsx(FilterToggle, { selected: allFilter.selected, onClick: allFilter.onSelect, children: allFilter.label })) : null, filters.map((filter) => (_jsx(FilterToggle, { selected: filter.selected, onClick: filter.onSelect, children: filter.label }, filter.value)))] })) : null, _jsx(CommandList, { className: cn("max-h-[400px] p-1", resultsClassName), children: children !== undefined ? children : sections ? (visibleSections.length ? (visibleSections.map((section, index) => (_jsxs(React.Fragment, { children: [index > 0 ? _jsx(CommandSeparator, { alwaysRender: true }) : null, _jsx(CommandGroup, { heading: section.heading, children: section.items.map((item) => (_jsx(CommandItem, { value: getCommandSearchItemValue(item), disabled: item.disabled, onSelect: () => {
62
63
  var _a;
63
64
  (_a = item.onSelect) === null || _a === void 0 ? void 0 : _a.call(item);
64
65
  if (item.closeOnSelect !== false) {
65
66
  setIsOpen(false);
66
67
  }
67
- }, children: _jsxs("div", { className: "min-w-0", children: [_jsx("p", { className: "truncate text-sm font-medium", children: _jsx(SearchHighlight, { text: item.title, query: value }) }), item.subtitle ? (_jsx("p", { className: "truncate text-xs text-muted-foreground", children: _jsx(SearchHighlight, { text: item.subtitle, query: value }) })) : null] }) }, item.id))) })] }, section.key)))) : (_jsx(EmptyState, { icon: CommandSearchEmptyIcon, message: normalizedValue ? "No results found" : "Start typing to search", description: normalizedValue
68
+ }, children: _jsxs("div", { className: "min-w-0", children: [_jsx(Typography, { as: "p", variant: "label", className: "truncate", children: _jsx(SearchHighlight, { text: item.title, query: value }) }), item.subtitle ? (_jsx(Typography, { as: "p", variant: "caption", className: "truncate", children: _jsx(SearchHighlight, { text: item.subtitle, query: value }) })) : null] }) }, item.id))) })] }, section.key)))) : (_jsx(EmptyState, { icon: CommandSearchEmptyIcon, message: normalizedValue ? "No results found" : "Start typing to search", description: normalizedValue
68
69
  ? `No results found for "${value}".`
69
70
  : "Results will appear here as you type." }))) : (_jsx(EmptyState, { icon: CommandSearchEmptyIcon, message: normalizedValue ? "No results found" : "Start typing to search", description: normalizedValue
70
71
  ? `No results found for "${value}".`
@@ -0,0 +1,19 @@
1
+ import * as React from "react";
2
+ export interface CopyButtonProps extends Omit<React.ButtonHTMLAttributes<HTMLButtonElement>, "onCopy"> {
3
+ /** Text to copy to the clipboard. */
4
+ value: string;
5
+ /** Milliseconds the "copied" state stays visible. */
6
+ feedbackDuration?: number;
7
+ /** Optional label rendered next to the icon. When omitted, renders as icon-only. */
8
+ children?: React.ReactNode;
9
+ /** Called after a successful copy. */
10
+ onCopy?: (value: string) => void;
11
+ /** Called if the clipboard write fails. */
12
+ onError?: (error: unknown) => void;
13
+ /** Accessible label for the icon-only button. Defaults to "Copy". */
14
+ copyLabel?: string;
15
+ /** Accessible label announced after copy. Defaults to "Copied". */
16
+ copiedLabel?: string;
17
+ }
18
+ declare function CopyButton({ value, feedbackDuration, children, onCopy, onError, copyLabel, copiedLabel, className, type, ...props }: CopyButtonProps): import("react/jsx-runtime").JSX.Element;
19
+ export { CopyButton };
@@ -0,0 +1,31 @@
1
+ "use client";
2
+ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
3
+ import * as React from "react";
4
+ import { Copy } from "lucide-react";
5
+ import { CheckIcon } from "./animated-icons/check";
6
+ import { cn } from "./lib/utils";
7
+ function CopyButton({ value, feedbackDuration = 1500, children, onCopy, onError, copyLabel = "Copy", copiedLabel = "Copied", className, type = "button", ...props }) {
8
+ const [copied, setCopied] = React.useState(false);
9
+ const timeoutRef = React.useRef(null);
10
+ React.useEffect(() => () => {
11
+ if (timeoutRef.current)
12
+ clearTimeout(timeoutRef.current);
13
+ }, []);
14
+ const handleCopy = React.useCallback(async () => {
15
+ try {
16
+ await navigator.clipboard.writeText(value);
17
+ setCopied(true);
18
+ onCopy === null || onCopy === void 0 ? void 0 : onCopy(value);
19
+ if (timeoutRef.current)
20
+ clearTimeout(timeoutRef.current);
21
+ timeoutRef.current = setTimeout(() => setCopied(false), feedbackDuration);
22
+ }
23
+ catch (error) {
24
+ onError === null || onError === void 0 ? void 0 : onError(error);
25
+ }
26
+ }, [value, feedbackDuration, onCopy, onError]);
27
+ const iconOnly = children === undefined;
28
+ const label = copied ? copiedLabel : copyLabel;
29
+ return (_jsxs(_Fragment, { children: [_jsxs("button", { type: type, onClick: handleCopy, "aria-label": iconOnly ? label : undefined, className: cn("inline-flex cursor-pointer items-center gap-1.5 rounded text-muted-foreground transition-colors hover:text-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-1 disabled:cursor-not-allowed disabled:opacity-50", !iconOnly && "text-sm font-medium", className), ...props, children: [copied ? (_jsx(CheckIcon, { size: 16, className: "text-green-600" })) : (_jsx(Copy, { className: "h-4 w-4", "aria-hidden": "true" })), iconOnly ? null : _jsx("span", { children: copied ? copiedLabel : children })] }), _jsx("span", { className: "sr-only", "aria-live": "polite", children: copied ? copiedLabel : "" })] }));
30
+ }
31
+ export { CopyButton };
@@ -0,0 +1,22 @@
1
+ import * as React from "react";
2
+ export interface DateInputProps {
3
+ label: React.ReactNode;
4
+ value: string;
5
+ onValueChange: (value: string) => void;
6
+ description?: React.ReactNode;
7
+ error?: React.ReactNode;
8
+ invalid?: boolean;
9
+ hideLabel?: boolean;
10
+ placeholder?: string;
11
+ disabled?: boolean;
12
+ minDate?: Date;
13
+ maxDate?: Date;
14
+ className?: string;
15
+ triggerClassName?: string;
16
+ labelClassName?: string;
17
+ descriptionClassName?: string;
18
+ errorClassName?: string;
19
+ id?: string;
20
+ }
21
+ declare const DateInput: React.ForwardRefExoticComponent<DateInputProps & React.RefAttributes<HTMLButtonElement>>;
22
+ export { DateInput };